diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..dd82417 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,54 @@ +Mark Andrews +Andreas Gustafsson +Evan Hunt +Brian Wellington +Bob Halley +David Lawrence +Michael Graff +Michael Sawyer +Ondřej Surý +James Brister +Tatuya JINMEI 神明達哉 +Francis Dupont +Michał Kępień +Danny Mayer +Mukund Sivaraman +Jeremy C. Reed +William King +Stephen Morris +Witold Kręcicki +Curtis Blackburn +Scott Mann +Rob Austein +Jim Reid +Eric Luce +Olafur Gudmundsson +Stephen Jacob +Damien Neil +Tony Finch +Jakob Schlyter +Petr Menšík +Vernon Schryver +Matt Nelson +Shane Kerr +Paul Ebersman +Ray Bellis +Shawn Routhier +Ben Cottrell +Tomas Hozza +johnd +Bill Parker +李昶 +Kevin Chen +Jonathan Casey +Mary Stahl +Mathieu Arnold +David Hankins +Paul Hoffman +Paul Vixie +Brian Conry +Anay Panvalkar +colleen +Robert Edmonds +João Damas +Artem Boldariev (Артем Болдарєв) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..153305e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,84 @@ + + +# BIND 9 Code of Conduct + +Like the technical community as a whole, the BIND 9 team and community is made +up of a mixture of professionals and volunteers from all over the world, working +on every aspect of the mission - including mentorship, teaching, and connecting +people. + +Diversity is one of our huge strengths, but it can also lead to communication +issues and unhappiness. To that end, we have a few ground rules that we ask +people to adhere to. This code applies equally to the core development team, +open source contributors and those seeking help and guidance. + +This isn't an exhaustive list of things that you can't do. Rather, take it in +the spirit in which it's intended - a guide to make it easier to enrich all of +us and the technical communities in which we participate. + +This code of conduct applies to all spaces managed by the BIND 9 project or +Internet Systems Consortium. This includes chat, the mailing lists, the issue +tracker, and any other fora created by the project team which the +community uses for communication. In addition, violations of this code outside +these spaces may affect a person's ability to participate within them. + +If you believe someone is violating the code of conduct, we ask that you report +it by emailing [conduct@isc.org](conduct@isc.org). For more details please see +our [Reporting Guidelines](https://www.isc.org/conductreporting/). + +* **Be friendly and patient.** +* **Be welcoming.** We strive to be a community that welcomes and supports + people of all backgrounds and identities. This includes, but is not limited to + members of any race, ethnicity, culture, national origin, colour, immigration + status, social and economic class, educational level, sex, sexual orientation, + gender identity and expression, age, size, family status, political belief, + religion, and mental and physical ability. +* **Be considerate.** Your work will be used by other people, and you in turn + will depend on the work of others. Any decision you take will affect users and + colleagues, and you should take those consequences into account when making + decisions. Remember that we're a world-wide community, so you might not be + communicating in someone else's primary language. +* **Be respectful.** Not all of us will agree all the time, but disagreement is + no excuse for poor behavior and poor manners. We might all experience some + frustration now and then, but we cannot allow that frustration to turn into a + personal attack. It's important to remember that a community where people feel + uncomfortable or threatened is not a productive one. Members of the BIND 9 + community should be respectful when dealing with other members as well as with + people outside the BIND 9 community. +* **Be careful in the words that you choose.** We are a community of + professionals, and we conduct ourselves professionally. Be kind to others. Do + not insult or put down other participants. Harassment and other exclusionary + behavior aren't acceptable. This includes, but is not limited to: + * Violent threats or language directed against another person. + * Discriminatory jokes and language. + * Posting sexually explicit or violent material. + * Posting (or threatening to post) other people's personally identifying + information ("doxing"). + * Personal insults, especially those using racist or sexist terms. + * Unwelcome sexual attention. + * Advocating for, or encouraging, any of the above behavior. + * Repeated harassment of others. In general, if someone asks you to stop, then + stop. +* **When we disagree, try to understand why.** Disagreements, both social and + technical, happen all the time and BIND 9 is no exception. It is important + that we resolve disagreements and differing views constructively. Remember + that we're different. The strength of BIND 9 comes from its varied community, + people from a wide range of backgrounds. Different people have different + perspectives on issues. Being unable to understand why someone holds a + viewpoint doesn't mean that they're wrong. Don't forget that it is human to + err and blaming each other doesn't get us anywhere. Instead, focus on helping + to resolve issues and learning from mistakes. + +Original text courtesy of the [Django Code of Conduct](https://www.djangoproject.com/conduct/) +project. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8a86090 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,194 @@ + +## BIND 9 Source Access and Contributor Guidelines +*Nov 26, 2024* + +### Contents + +1. [Access to source code](#access) +1. [Reporting bugs](#bugs) +1. [Contributing code](#contrib) + +### Introduction + +Thank you for using BIND 9! + +BIND is open source software that implements the Domain Name System (DNS) +protocols for the Internet. It is a reference implementation of those +protocols, but it is also production-grade software, suitable for use in +high-volume and high-reliability applications. It is very +widely used DNS software, providing a robust and stable platform on top of +which organizations can build distributed computing systems with the +knowledge that those systems are fully compliant with published DNS +standards. + +BIND is and will always remain free and openly available. It can be +used and modified in any way by anyone. + +BIND is maintained by [Internet Systems Consortium](https://www.isc.org), +a public-benefit 501(c)(3) nonprofit, using a "managed open source" approach: +anyone can see the source, but only ISC employees have commit access. +In the past, the source could only be seen once ISC had published +a release; read access to the source repository was restricted just +as commit access was. That has changed, as ISC now provides a +public git repository of the BIND source tree (see below). + +At ISC, we're committed to +building communities that are welcoming and inclusive: environments where people +are encouraged to share ideas, treat each other with respect, and collaborate +towards the best solutions. To reinforce our commitment, ISC +has adopted a slightly modified version of the Django +[Code of Conduct](https://gitlab.isc.org/isc-projects/bind9/-/blob/main/CODE_OF_CONDUCT.md) +for the BIND 9 project, as well as for the conduct of our developers throughout +the industry. + +### Access to source code + +Public BIND releases are always available from the +[ISC FTP site](ftp://ftp.isc.org/isc/bind9). + +A public-access git repository is also available at +[https://gitlab.isc.org](https://gitlab.isc.org). This repository +contains all public release branches. Upcoming releases can be viewed in +their current state at any time. Short-lived development branches +contain unreviewed work in progress. Commits which address security +vulnerablilities are withheld until after public disclosure. + +You can browse the source online via +[https://gitlab.isc.org/isc-projects/bind9](https://gitlab.isc.org/isc-projects/bind9) + +To clone the repository, use: + +> $ git clone https://gitlab.isc.org/isc-projects/bind9.git + +Release branch names are of the form `bind-9.X`, where X represents the second +number in the BIND 9 version number. So, to check out the BIND 9.20 +branch, use: + +> $ git checkout bind-9.20 + +Whenever a branch is ready for publication, a tag is placed of the +form `v9.X.Y`. The 9.20.0 release, for instance, is tagged as `v9.20.0`. + +The branch in which the next major release is being developed is called +`main`. + +### Reporting bugs + +Reports of flaws in the BIND package, including software bugs, errors +in the documentation, missing files in the tarball, suggested changes +or requests for new features, etc., can be filed using +[https://gitlab.isc.org/isc-projects/bind9/issues](https://gitlab.isc.org/isc-projects/bind9/issues). + +Due to a large ticket backlog, we are sometimes slow to respond, +especially if a bug is cosmetic or if a feature request is vague or +low in priority, but we try at least to acknowledge legitimate +bug reports within a week. + +ISC's GitLab system is publicly readable; however, you must have +an account to create a new issue. You can either register locally or +use credentials from an existing account at GitHub, GitLab, Google, +Twitter, or Facebook. + +### Reporting possible security issues + +See `SECURITY.md`. + +### Contributing code + +BIND is licensed under the +[Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL/2.0/). +Earlier versions (BIND 9.10 and earlier) were licensed under the +[ISC License](https://www.isc.org/licenses/) + +ISC does not require an explicit copyright assignment for patch +contributions. However, by submitting a patch to ISC, you implicitly +certify that you are the author of the code, that you intend to relinquish +exclusive copyright, and that you grant permission to publish your work +under the open source license used for the BIND version(s) to which your +patch will be applied. + +#### BIND code + +Patches for BIND may be submitted directly via merge requests in +[ISC's GitLab](https://gitlab.isc.org/isc-projects/bind9/) source repository for +BIND. Please contact ISC and provide your GitLab username in order to be allowed +to fork the project and submit merge requests. + +Patches can also be submitted as diffs against a specific version of +BIND -- preferably the current top of the `main` branch. Diffs may +be generated using either `git format-patch` or `git diff`. + +Those wanting to write code for BIND may be interested in the +[developer information](doc/dev/dev.md) page, which includes information +about BIND design and coding practices, including discussion of internal +APIs and overall system architecture. + +Every patch submitted is reviewed by ISC engineers following our +[code review process](doc/dev/dev.md#reviews) before it is merged. + +It may take considerable time to review patch submissions, especially if +they don't meet ISC style and quality guidelines. If a patch is a good +idea, we can and will do additional work to bring it up to par, but if +we're busy with other work, it may take us a long time to get to it. + +To ensure your patch is acted on as promptly as possible, please: + +* Try to adhere to the [BIND 9 coding style](doc/dev/style.md). +* Run unit and system tests to ensure your change hasn't caused any + functional regressions (these can be checked in the CI pipeline). +* Document your work, both in the patch itself and in the + accompanying email. +* In patches that make non-trivial functional changes, include system + tests if possible; when introducing or substantially altering a + library API, include unit tests. See [Testing](doc/dev/dev.md#testing) + for more information. + +##### Changes to `configure` + +If you need to make changes to `configure`, you should not edit it +directly; instead, edit `configure.ac`, then run `autoconf`. Similarly, +instead of editing `config.h.in` directly, edit `configure.ac` and run +`autoheader`. + +When submitting a patch as a diff, it's fine to omit the `configure` +diffs to save space. Just send the `configure.ac` diffs and we'll +generate the new `configure` during the review process. + +##### Documentation + +All functional changes should be documented. There are three types +of documentation in the BIND source tree: + +* Man pages are kept alongside the source code for the commands + they document, in files ending in `.rst`: for example, the + `named` man page is `bin/named/named.rst`. +* The *BIND 9 Administrator Reference Manual* is in the .rst files in + `doc/arm/`; the HTML version is automatically generated from + the `.rst` files. +* API documentation is in the header file describing the API, in + Doxygen-formatted comments. + +Patches to improve existing documentation are also very welcome! + +##### Tests + +BIND is a large and complex project. We rely heavily on continuous +automated testing and cannot merge new code without adequate test coverage. +Please see [the "Testing" section of doc/dev/dev.md](doc/dev/dev.md#testing) +for more information. + +#### Thanks + +Thank you for your interest in contributing to the ongoing development +of BIND 9. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..7bad356 --- /dev/null +++ b/COPYING @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + 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 + https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..12f7917 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,391 @@ +Copyright (C) 1996-2023 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 https://mozilla.org/MPL/2.0/. + + ----------------------------------------------------------------------------- + + Portions of this code release fall under one or more of the + following Copyright notices. Please see individual source + files for details. + + For binary releases also see: OpenSSL-LICENSE. + +Copyright (C) 1996-2001 Nominum, Inc. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (C) 1995-2000 by Network Associates, Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET +DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. + +The development of Dynamically Loadable Zones (DLZ) for Bind 9 was +conceived and contributed by Rob Butler. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER +DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE +USE OR PERFORMANCE OF THIS SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (c) 1987, 1990, 1993, 1994 + The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + ----------------------------------------------------------------------------- + +Copyright (C) The Internet Society 2005. This version of +this module is part of RFC 4178; see the RFC itself for +full legal notices. + +(The above copyright notice is per RFC 3978 5.6 (a), q.v.) + + ----------------------------------------------------------------------------- + +Copyright (c) 2004 Masarykova universita +(Masaryk University, Brno, Czech Republic) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + ----------------------------------------------------------------------------- + +Copyright (c) 1997 - 2003 Kungliga Tekniska Hgskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + ----------------------------------------------------------------------------- + +Copyright (c) 1993 by Digital Equipment Corporation. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies, and that +the name of Digital Equipment Corporation not be used in advertising or +publicity pertaining to distribution of the document or software without +specific, written prior permission. + +THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT +CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + ----------------------------------------------------------------------------- + +Copyright (c) 1999-2000 by Nortel Networks Corporation + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS +BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (C) 2004 Nominet, Ltd. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + ----------------------------------------------------------------------------- + +Copyright (c) 1996, David Mazieres +Copyright (c) 2008, Damien Miller + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +----------------------------------------------------------------------------- + +Copyright (c) 1995, 1997, 1998 The NetBSD Foundation, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +----------------------------------------------------------------------------- + +Copyright (C) 2008-2011 Red Hat, Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND Red Hat DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +----------------------------------------------------------------------------- + +Copyright (c) 2013-2014, Farsight Security, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +----------------------------------------------------------------------------- + +Copyright (c) 2014 by Farsight Security, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +----------------------------------------------------------------------------- + +Copyright Joyent, Inc. and other Node contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..3e42469 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,30 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. _changelog: + +Changelog +========= + +.. note:: The following list contains detailed information about BIND 9 + development. Regular users should refer to :ref:`Release Notes ` + for changes relevant to them. + +.. include:: ../changelog/changelog-9.20.9.rst +.. include:: ../changelog/changelog-9.20.8.rst +.. include:: ../changelog/changelog-9.20.7.rst +.. include:: ../changelog/changelog-9.20.6.rst +.. include:: ../changelog/changelog-9.20.5.rst +.. include:: ../changelog/changelog-9.20.4.rst +.. include:: ../changelog/changelog-9.20.3.rst +.. include:: ../changelog/changelog-9.20.2.rst +.. include:: ../changelog/changelog-9.20.1.rst +.. include:: ../changelog/changelog-history.rst diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7bad356 --- /dev/null +++ b/LICENSE @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + 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 + https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..9a81318 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,30 @@ +include $(top_srcdir)/Makefile.top + +SUBDIRS = . lib doc + +# build libtest before fuzz/* and bin/tests +SUBDIRS += tests + +# run fuzz tests before system tests +SUBDIRS += fuzz bin + +BUILT_SOURCES += bind.keys.h +CLEANFILES += bind.keys.h + +bind.keys.h: bind.keys Makefile + ${PERL} ${top_srcdir}/util/bindkeys.pl ${top_srcdir}/bind.keys > $@ + +.PHONY: doc + +EXTRA_DIST = \ + bind.keys \ + util/bindkeys.pl \ + util/dtrace.sh \ + contrib \ + COPYRIGHT \ + LICENSE \ + *.md + +dist-hook: + find $(distdir) -type f -name .gitignore -delete + git rev-parse --short HEAD | cut -b1-7 > $(distdir)/srcid diff --git a/Makefile.docs b/Makefile.docs new file mode 100644 index 0000000..a205c5e --- /dev/null +++ b/Makefile.docs @@ -0,0 +1,59 @@ +SPHINX_V = $(SPHINX_V_@AM_V@) +SPHINX_V_ = $(SPHINX_V_@AM_DEFAULT_V@) +SPHINX_V_0 = -q +SPHINX_V_1 = -n +SPHINX_W = -W + +AM_V_SPHINX = $(AM_V_SPHINX_@AM_V@) +AM_V_SPHINX_ = $(AM_V_SPHINX_@AM_DEFAULT_V@) +AM_V_SPHINX_0 = @echo " SPHINX $@"; + +SPHINXBUILDDIR = $(builddir)/_build + +LF = \n +RNDC_CONF = .. |rndc_conf| replace:: ``$(sysconfdir)/rndc.conf`` +RNDC_KEY = .. |rndc_key| replace:: ``$(sysconfdir)/rndc.key`` +NAMED_CONF = .. |named_conf| replace:: ``$(sysconfdir)/named.conf`` +NAMED_PID = .. |named_pid| replace:: ``$(runstatedir)/named.pid`` +SESSION_KEY = .. |session_key| replace:: ``$(runstatedir)/session.key`` + +export RST_EPILOG = $(RNDC_CONF)$(LF)$(RNDC_KEY)$(LF)$(NAMED_CONF)$(LF)$(BIND_KEYS)$(LF)$(NAMED_PID)$(LF)$(SESSION_KEY) + +common_SPHINXOPTS = \ + $(SPHINX_W) \ + -c $(srcdir) \ + -a \ + $(SPHINX_V) + +ALLSPHINXOPTS = \ + $(common_SPHINXOPTS) \ + -D rst_epilog="$$(printf "$${RST_EPILOG}")" \ + $(SPHINXOPTS) \ + $(srcdir) + +_ = @ +man_RNDC_CONF = .. |rndc_conf| replace:: ``$(_)sysconfdir$(_)/rndc.conf`` +man_RNDC_KEY = .. |rndc_key| replace:: ``$(_)sysconfdir$(_)/rndc.key`` +man_NAMED_CONF = .. |named_conf| replace:: ``$(_)sysconfdir$(_)/named.conf`` +man_BIND_KEYS = .. |bind_keys| replace:: ``$(_)sysconfdir$(_)/bind.keys`` +man_NAMED_PID = .. |named_pid| replace:: ``$(_)runstatedir$(_)/named.pid`` +man_SESSION_KEY = .. |session_key| replace:: ``$(_)runstatedir$(_)/session.key`` + +export man_RST_EPILOG = $(man_RNDC_CONF)$(LF)$(man_RNDC_KEY)$(LF)$(man_NAMED_CONF)$(LF)$(man_BIND_KEYS)$(LF)$(man_NAMED_PID)$(LF)$(man_SESSION_KEY) + +man_SPHINXOPTS = \ + $(common_SPHINXOPTS) \ + -D version="@""PACKAGE_VERSION@" \ + -D today="@""RELEASE_DATE@" \ + -D release="@""PACKAGE_VERSION@" \ + -D rst_epilog="$$(printf "$${man_RST_EPILOG}")" \ + $(SPHINXOPTS) \ + $(srcdir) + +AM_V_SED = $(AM_V_SED_@AM_V@) +AM_V_SED_ = $(AM_V_SED_@AM_DEFAULT_V@) +AM_V_SED_0 = @echo " SED $@"; + +AM_V_CFG_TEST = $(AM_V_CFG_TEST_@AM_V@) +AM_V_CFG_TEST_ = $(AM_V_CFG_TEST_@AM_DEFAULT_V@) +AM_V_CFG_TEST_0 = @echo " CFG_GEN $@"; diff --git a/Makefile.dtrace b/Makefile.dtrace new file mode 100644 index 0000000..9cb6b00 --- /dev/null +++ b/Makefile.dtrace @@ -0,0 +1,20 @@ +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +AM_V_DTRACE = $(AM_V_DTRACE_@AM_V@) +AM_V_DTRACE_ = $(AM_V_DTRACE_@AM_DEFAULT_V@) +AM_V_DTRACE_0 = @echo " DTRACE $@"; + +BUILT_SOURCES += probes.h +CLEANFILES += probes.h probes.o + +probes.h: Makefile probes.d + $(AM_V_DTRACE)$(DTRACE) -s $(srcdir)/probes.d -h -o $@ +probes.lo: Makefile probes.d $(DTRACE_DEPS) + $(AM_V_DTRACE)$(LIBTOOL) --mode=compile --tag=CC $(DTRACE) -s $(srcdir)/probes.d -G -o $@ $(DTRACE_OBJS) + +if HAVE_DTRACE +if !HOST_MACOS +DTRACE_LIBADD = probes.lo +endif +endif diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..399f4e4 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1078 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = doc/doxygen/doxygen-input-filter \ + bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR \ + bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR \ + bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE \ + bin/tests/system/isctest/vars/.ac_vars/SHELL \ + bin/tests/system/isctest/vars/.ac_vars/PYTHON \ + bin/tests/system/isctest/vars/.ac_vars/PERL \ + bin/tests/system/isctest/vars/.ac_vars/CURL \ + bin/tests/system/isctest/vars/.ac_vars/NC \ + bin/tests/system/isctest/vars/.ac_vars/XSLTPROC \ + bin/tests/system/isctest/vars/.ac_vars/PYTEST \ + util/check-make-install +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir distdir-am dist dist-all distcheck +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/Makefile.top \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/CURL.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/NC.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PERL.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PYTEST.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PYTHON.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/SHELL.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR.in \ + $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/XSLTPROC.in \ + $(top_srcdir)/doc/doxygen/doxygen-input-filter.in \ + $(top_srcdir)/util/check-make-install.in AUTHORS COPYING \ + ChangeLog NEWS README.md ar-lib compile config.guess \ + config.sub install-sh ltmain.sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +GZIP_ENV = --best +DIST_ARCHIVES = $(distdir).tar.xz +DIST_TARGETS = dist-xz +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = \ + $(STD_CPPFLAGS) \ + -include $(top_builddir)/config.h \ + -I$(srcdir)/include + +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = bind.keys.h +CLEANFILES = bind.keys.h +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + + +# build libtest before fuzz/* and bin/tests + +# run fuzz tests before system tests +SUBDIRS = . lib doc tests fuzz bin +EXTRA_DIST = \ + bind.keys \ + util/bindkeys.pl \ + util/dtrace.sh \ + contrib \ + COPYRIGHT \ + LICENSE \ + *.md + +all: $(BUILT_SOURCES) config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +doc/doxygen/doxygen-input-filter: $(top_builddir)/config.status $(top_srcdir)/doc/doxygen/doxygen-input-filter.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/SHELL: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/SHELL.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/PYTHON: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PYTHON.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/PERL: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PERL.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/CURL: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/CURL.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/NC: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/NC.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/XSLTPROC: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/XSLTPROC.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +bin/tests/system/isctest/vars/.ac_vars/PYTEST: $(top_builddir)/config.status $(top_srcdir)/bin/tests/system/isctest/vars/.ac_vars/PYTEST.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +util/check-make-install: $(top_builddir)/config.status $(top_srcdir)/util/check-make-install.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +doc: doc-recursive + +doc-am: doc-local + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +test: test-recursive + +test-am: test-local + +uninstall-am: + +unit: unit-recursive + +unit-am: unit-local + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-exec install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \ + dist-tarZ dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-tags distcleancheck distdir distuninstallcheck \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +bind.keys.h: bind.keys Makefile + ${PERL} ${top_srcdir}/util/bindkeys.pl ${top_srcdir}/bind.keys > $@ + +.PHONY: doc + +dist-hook: + find $(distdir) -type f -name .gitignore -delete + git rev-parse --short HEAD | cut -b1-7 > $(distdir)/srcid + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Makefile.tests b/Makefile.tests new file mode 100644 index 0000000..a0ea914 --- /dev/null +++ b/Makefile.tests @@ -0,0 +1,28 @@ +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +unit-local: check + +if HAVE_CMOCKA +TESTS = $(check_PROGRAMS) +endif HAVE_CMOCKA + +LOG_COMPILER = $(top_builddir)/tests/unit-test-driver.sh + +AM_CFLAGS += \ + -I$(top_srcdir)/tests/include \ + $(TEST_CFLAGS) + +AM_CPPFLAGS += \ + $(CMOCKA_CFLAGS) \ + -DNAMED_PLUGINDIR=\"$(pkglibdir)\" \ + -DTESTS_DIR=\"$(abs_srcdir)\" + +LDADD += \ + $(top_builddir)/tests/libtest/libtest.la \ + $(CMOCKA_LIBS) + +if HAVE_JEMALLOC +AM_CFLAGS += $(JEMALLOC_CFLAGS) +LDADD += $(JEMALLOC_LIBS) +endif diff --git a/Makefile.top b/Makefile.top new file mode 100644 index 0000000..da95a2d --- /dev/null +++ b/Makefile.top @@ -0,0 +1,73 @@ +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 + +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = \ + $(STD_CPPFLAGS) \ + -include $(top_builddir)/config.h \ + -I$(srcdir)/include + +AM_LDFLAGS = \ + $(STD_LDFLAGS) +LDADD = + +BUILT_SOURCES = +CLEANFILES = + +if HOST_MACOS +AM_LDFLAGS += \ + -Wl,-flat_namespace +endif HOST_MACOS + +if HAVE_JEMALLOC +LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) +LIBISC_LIBS = $(JEMALLOC_LIBS) +else +LIBISC_CFLAGS = +LIBISC_LIBS = +endif + +LIBISC_CFLAGS += \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib/isc/include \ + -I$(top_builddir)/lib/isc/include + +LIBISC_LIBS += $(top_builddir)/lib/isc/libisc.la +if HAVE_DTRACE +LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +endif + +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la +if HAVE_DTRACE +LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +endif + +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la +if HAVE_DTRACE +LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +endif + +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3e42469 --- /dev/null +++ b/NEWS @@ -0,0 +1,30 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. _changelog: + +Changelog +========= + +.. note:: The following list contains detailed information about BIND 9 + development. Regular users should refer to :ref:`Release Notes ` + for changes relevant to them. + +.. include:: ../changelog/changelog-9.20.9.rst +.. include:: ../changelog/changelog-9.20.8.rst +.. include:: ../changelog/changelog-9.20.7.rst +.. include:: ../changelog/changelog-9.20.6.rst +.. include:: ../changelog/changelog-9.20.5.rst +.. include:: ../changelog/changelog-9.20.4.rst +.. include:: ../changelog/changelog-9.20.3.rst +.. include:: ../changelog/changelog-9.20.2.rst +.. include:: ../changelog/changelog-9.20.1.rst +.. include:: ../changelog/changelog-history.rst diff --git a/OPTIONS.md b/OPTIONS.md new file mode 100644 index 0000000..acdcaf8 --- /dev/null +++ b/OPTIONS.md @@ -0,0 +1,29 @@ + +Setting the `CPPFLAGS` environment variable before running `configure` +can be used to enable certain compile-time options that are not +explicitly defined in `configure`. + +Some of these settings are: + +| Setting | Description | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `-DCHECK_LOCAL=0` | Don't check out-of-zone addresses in `named-checkzone` | +| `-DCHECK_SIBLING=0` | Don't check sibling glue in `named-checkzone` | +| `-DISC_FACILITY=LOG_LOCAL0` | Change the default syslog facility for `named` | +| `-DISC_HEAP_CHECK` | Test heap consistency after every heap operation; used when debugging | +| `-DISC_MEM_DEFAULTFILL=1` | Overwrite memory with tag values when allocating or freeing it; this impairs performance but makes debugging of memory problems easier | +| `-DISC_MEM_TRACKLINES=0` | Don't track memory allocations by file and line number; this improves performance but makes debugging more difficult | +| `-DNAMED_RUN_PID_DIR=0` | Create default PID files in `${localstatedir}/run` rather than `${localstatedir}/run/named/` | +| `-DNS_CLIENT_DROPPORT=0` | Disable dropping queries from particular well-known ports | +| `-DOPENSSL_API_COMPAT=10100` | Build using the deprecated OpenSSL APIs so that the `engine` API is available when building with OpenSSL 3.0.0 for PKCS#11 support | diff --git a/README.md b/README.md new file mode 100644 index 0000000..16ede04 --- /dev/null +++ b/README.md @@ -0,0 +1,205 @@ + +# BIND 9 + +### Contents + +1. [Introduction](#intro) +1. [Reporting bugs and getting help](#help) +1. [Contributing to BIND](#contrib) +1. [Building BIND](#build) +1. [Automated testing](#testing) +1. [Documentation](#doc) +1. [Acknowledgments](#ack) + +### Introduction + +BIND (Berkeley Internet Name Domain) is a complete, highly portable +implementation of the Domain Name System (DNS) protocol. + +The BIND name server, `named`, can act as an authoritative name +server, recursive resolver, DNS forwarder, or all three simultaneously. It +implements views for split-horizon DNS, automatic DNSSEC zone signing and +key management, catalog zones to facilitate provisioning of zone data +throughout a name server constellation, response policy zones (RPZ) to +protect clients from malicious data, response rate limiting (RRL) and +recursive query limits to reduce distributed denial of service attacks, +and many other advanced DNS features. BIND also includes a suite of +administrative tools, including the `dig` and `delv` DNS lookup tools, +`nsupdate` for dynamic DNS zone updates, `rndc` for remote name server +administration, and more. + +BIND 9 began as a complete rewrite of the BIND architecture that was +used in versions 4 and 8. Internet Systems Consortium +([https://www.isc.org](https://www.isc.org)), a 501(c)(3) US public benefit +corporation dedicated to providing software and services in support of the +Internet infrastructure, developed BIND 9 and is responsible for its +ongoing maintenance and improvement. BIND is open source software +licensed under the terms of the Mozilla Public License, version 2.0. + +For a detailed list of changes made throughout the history of BIND 9, see +the [changelog](doc/arm/changelog.rst). + +For up-to-date versions and release notes, see +[https://www.isc.org/download/](https://www.isc.org/download/). + +For information about supported platforms, see the +["Supported Platforms"](doc/arm/platforms.rst) section in the BIND 9 +Administrator Reference Manual. + +### Reporting bugs and getting help + +To report non-security-sensitive bugs or request new features, you may +open an issue in the BIND 9 project on the +[ISC GitLab server](https://gitlab.isc.org) at +[https://gitlab.isc.org/isc-projects/bind9](https://gitlab.isc.org/isc-projects/bind9). + +Please note that, unless you explicitly mark the newly created issue as +"confidential," it will be publicly readable. Please do not include any +information in bug reports that you consider to be confidential unless +the issue has been marked as such. In particular, if submitting the +contents of your configuration file in a non-confidential issue, it is +advisable to obscure key secrets; this can be done automatically by +using `named-checkconf -px`. + +For information about ISC's Security Vulnerability Disclosure Policy and +information about reporting potential security issues, please see +`SECURITY.md`. + +Professional support and training for BIND are available from +ISC. Contact us at [https://www.isc.org/contact](https://www.isc.org/contact) +for more information. + +To join the __BIND Users__ mailing list, or view the archives, visit +[https://lists.isc.org/mailman/listinfo/bind-users](https://lists.isc.org/mailman/listinfo/bind-users). + +If you're planning on making changes to the BIND 9 source code, you +may also want to join the __BIND Workers__ mailing list, at +[https://lists.isc.org/mailman/listinfo/bind-workers](https://lists.isc.org/mailman/listinfo/bind-workers). + +### Contributing to BIND + +ISC maintains a public git repository for BIND; details can be found +at [https://www.isc.org/sourceaccess/](https://www.isc.org/sourceaccess/). + +Information for BIND contributors can be found in the following files: +- General information: [CONTRIBUTING.md](CONTRIBUTING.md) +- Code of Conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) +- BIND 9 code style: [doc/dev/style.md](doc/dev/style.md) +- BIND architecture and developer guide: [doc/dev/dev.md](doc/dev/dev.md) + +Patches for BIND may be submitted as +[merge requests](https://gitlab.isc.org/isc-projects/bind9/merge_requests) +on the [ISC GitLab server](https://gitlab.isc.org). + +By default, external contributors do not have the ability to fork BIND on the +GitLab server; if you wish to contribute code to BIND, you may request +permission to do so. Thereafter, you can create git branches and directly +submit requests that they be reviewed and merged. + +If you prefer, you may also submit code by opening a +[GitLab issue](https://gitlab.isc.org/isc-projects/bind9/issues) and +including your patch as an attachment, preferably generated by +`git format-patch`. + +### Building BIND 9 + +For information about building BIND 9, see the +["Building BIND 9"](doc/arm/build.inc.rst) section in the BIND 9 +Administrator Reference Manual. + +### Automated testing + +A system test suite can be run with `make check`. The system tests require +you to configure a set of virtual IP addresses on your system (this allows +multiple servers to run locally and communicate with each other). These +IP addresses can be configured by running the command +`bin/tests/system/ifconfig.sh up` as root. + +Some tests require Perl and the `Net::DNS` and/or `IO::Socket::IP` modules, +and are skipped if these are not available. Some tests require Python +and the `dnspython` module and are skipped if these are not available. +See bin/tests/system/README for further details. + +Unit tests are implemented using the CMocka unit testing framework. To build +them, use `configure --with-cmocka`. Execution of tests is done by the automake +parallel test driver; unit tests are also run by `make check`. + +### Documentation + +The *BIND 9 Administrator Reference Manual* (ARM) is included with the source +distribution, and in .rst format, in the `doc/arm` +directory. The HTML version is automatically generated and can +be viewed at [https://bind9.readthedocs.io/en/latest/index.html](https://bind9.readthedocs.io/en/latest/index.html). + +The PDF version can be built by running: + + cd doc/arm/ + sphinx-build -b latex . pdf/ + make -C pdf/ all-pdf + +The above requires TeX Live in order to work. The PDF will be written to +`doc/arm/pdf/Bv9ARM.pdf`. + +Man pages for some of the programs in the BIND 9 distribution +are also included in the BIND ARM. + +Frequently (and not-so-frequently) asked questions and their answers +can be found in the ISC Knowledgebase at +[https://kb.isc.org](https://kb.isc.org). + +Additional information on various subjects can be found in other +`README` files throughout the source tree. + +#### Bug report identifiers + +Most notes in the ARM Changelog appendix include a reference to a bug report or +issue number. Prior to 2018, these were usually of the form `[RT #NNN]` +and referred to entries in the "bind9-bugs" RT database, which was not open +to the public. More recent entries use the form `[GL #NNN]` or, less often, +`[GL !NNN]`, which, respectively, refer to issues or merge requests in the +GitLab database. Most of these are publicly readable, unless they include +information which is confidential or security-sensitive. + +To look up a GitLab issue by its number, use the URL +[https://gitlab.isc.org/isc-projects/bind9/issues/NNN](https://gitlab.isc.org/isc-projects/bind9/issues). +To look up a merge request, use +[https://gitlab.isc.org/isc-projects/bind9/merge_requests/NNN](https://gitlab.isc.org/isc-projects/bind9/merge_requests). + +In rare cases, an issue or merge request number may be followed with the +letter "P". This indicates that the information is in the private ISC +GitLab instance, which is not visible to the public. + +### Acknowledgments + +* The original development of BIND 9 was underwritten by the + following organizations: + + Sun Microsystems, Inc. + Hewlett Packard + Compaq Computer Corporation + IBM + Process Software Corporation + Silicon Graphics, Inc. + Network Associates, Inc. + U.S. Defense Information Systems Agency + USENIX Association + Stichting NLnet - NLnet Foundation + Nominum, Inc. + +* This product includes software developed by the OpenSSL Project for use + in the OpenSSL Toolkit. + [https://www.OpenSSL.org/](https://www.OpenSSL.org/) +* This product includes cryptographic software written by Eric Young + (eay@cryptsoft.com). +* This product includes software written by Tim Hudson (tjh@cryptsoft.com). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2c63605 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,35 @@ + +# Security Policy + +ISC's Security Vulnerability Disclosure Policy is documented in the +relevant [ISC Knowledgebase article][1]. + +## Reporting possible security issues + +If you think you may be seeing a potential security vulnerability in +BIND (for example, a crash with a REQUIRE, INSIST, or ASSERT failure), +please report it immediately by [opening a confidential GitLab issue][2] +(preferred) or emailing bind-security@isc.org. + +Please do not discuss undisclosed security vulnerabilities on any public +mailing list. ISC has a long history of handling reported +vulnerabilities promptly and effectively and we respect and acknowledge +responsible reporters. + +If you have a crash, you may want to consult the Knowledgebase article +entitled ["What to do if your BIND or DHCP server has crashed"][3]. + +[1]: https://kb.isc.org/docs/aa-00861 +[2]: https://gitlab.isc.org/isc-projects/bind9/-/issues/new?issue[confidential]=true&issuable_template=Bug +[3]: https://kb.isc.org/docs/aa-00340 diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..f81f959 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1983 @@ +# generated automatically by aclocal 1.16.5 -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, +[m4_warning([this file was generated for autoconf 2.71. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurrence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + +# Copyright (C) 2002-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.16' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.16.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.16.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Copyright (C) 2011-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_AR([ACT-IF-FAIL]) +# ------------------------- +# Try to determine the archiver interface, and trigger the ar-lib wrapper +# if it is needed. If the detection of archiver interface fails, run +# ACT-IF-FAIL (default is to abort configure with a proper error message). +AC_DEFUN([AM_PROG_AR], +[AC_BEFORE([$0], [LT_INIT])dnl +AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([ar-lib])dnl +AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) +: ${AR=ar} + +AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], + [AC_LANG_PUSH([C]) + am_cv_ar_interface=ar + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], + [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=ar + else + am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([am_ar_try]) + if test "$ac_status" -eq 0; then + am_cv_ar_interface=lib + else + am_cv_ar_interface=unknown + fi + fi + rm -f conftest.lib libconftest.a + ]) + AC_LANG_POP([C])]) + +case $am_cv_ar_interface in +ar) + ;; +lib) + # Microsoft lib, so override with the ar-lib wrapper script. + # FIXME: It is wrong to rewrite AR. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__AR in this case, + # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something + # similar. + AR="$am_aux_dir/ar-lib $AR" + ;; +unknown) + m4_default([$1], + [AC_MSG_ERROR([could not determine $AR interface])]) + ;; +esac +AC_SUBST([AR])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? + done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*- + +# Copyright (C) 2012-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_EXTRA_RECURSIVE_TARGETS +# -------------------------- +# Define the list of user recursive targets. This macro exists only to +# be traced by Automake, which will ensure that a proper definition of +# user-defined recursive targets (and associated rules) is propagated +# into all the generated Makefiles. +# TODO: We should really reject non-literal arguments here... +AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], []) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +m4_ifdef([_$0_ALREADY_INIT], + [m4_fatal([$0 expanded multiple times +]m4_defn([_$0_ALREADY_INIT]))], + [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi +AC_SUBST([CTAGS]) +if test -z "$ETAGS"; then + ETAGS=etags +fi +AC_SUBST([ETAGS]) +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi +AC_SUBST([CSCOPE]) + +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 1999-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# --------------------------------------------------------------------------- +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. +# +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. +# +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). +# +# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. +AC_DEFUN([AM_PATH_PYTHON], + [ + dnl Find a Python interpreter. Python versions prior to 2.0 are not + dnl supported. (2.0 was released on October 16, 2000). + m4_define_default([_AM_PYTHON_INTERPRETER_LIST], +[python python2 python3 dnl + python3.11 python3.10 dnl + python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl + python3.2 python3.1 python3.0 dnl + python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl + python2.0]) + + AC_ARG_VAR([PYTHON], [the Python interpreter]) + + m4_if([$1],[],[ + dnl No version check is needed. + # Find any Python interpreter. + if test -z "$PYTHON"; then + AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) + fi + am_display_PYTHON=python + ], [ + dnl A version check is needed. + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + AC_MSG_CHECKING([whether $PYTHON version is >= $1]) + AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([Python interpreter is too old])]) + am_display_PYTHON=$PYTHON + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + AC_CACHE_CHECK([for a Python interpreter with version >= $1], + [am_cv_pathless_PYTHON],[ + for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do + test "$am_cv_pathless_PYTHON" = none && break + AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) + done]) + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + if test "$am_cv_pathless_PYTHON" = none; then + PYTHON=: + else + AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) + fi + am_display_PYTHON=$am_cv_pathless_PYTHON + fi + ]) + + if test "$PYTHON" = :; then + dnl Run any user-specified action, or abort. + m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) + else + + dnl Query Python for its version number. Although site.py simply uses + dnl sys.version[:3], printing that failed with Python 3.10, since the + dnl trailing zero was eliminated. So now we output just the major + dnl and minor version numbers, as numbers. Apparently the tertiary + dnl version is not of interest. + dnl + AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], + [am_cv_python_version=`$PYTHON -c "import sys; print ('%u.%u' % sys.version_info[[:2]])"`]) + AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) + + dnl At times, e.g., when building shared libraries, you may want + dnl to know which OS platform Python thinks this is. + dnl + AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], + [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) + AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) + + dnl emacs-page + dnl If --with-python-sys-prefix is given, use the values of sys.prefix + dnl and sys.exec_prefix for the corresponding values of PYTHON_PREFIX + dnl and PYTHON_EXEC_PREFIX. Otherwise, use the GNU ${prefix} and + dnl ${exec_prefix} variables. + dnl + dnl The two are made distinct variables so they can be overridden if + dnl need be, although general consensus is that you shouldn't need + dnl this separation. + dnl + dnl Also allow directly setting the prefixes via configure options, + dnl overriding any default. + dnl + if test "x$prefix" = xNONE; then + am__usable_prefix=$ac_default_prefix + else + am__usable_prefix=$prefix + fi + + # Allow user to request using sys.* values from Python, + # instead of the GNU $prefix values. + AC_ARG_WITH([python-sys-prefix], + [AS_HELP_STRING([--with-python-sys-prefix], + [use Python's sys.prefix and sys.exec_prefix values])], + [am_use_python_sys=:], + [am_use_python_sys=false]) + + # Allow user to override whatever the default Python prefix is. + AC_ARG_WITH([python_prefix], + [AS_HELP_STRING([--with-python_prefix], + [override the default PYTHON_PREFIX])], + [am_python_prefix_subst=$withval + am_cv_python_prefix=$withval + AC_MSG_CHECKING([for explicit $am_display_PYTHON prefix]) + AC_MSG_RESULT([$am_cv_python_prefix])], + [ + if $am_use_python_sys; then + # using python sys.prefix value, not GNU + AC_CACHE_CHECK([for python default $am_display_PYTHON prefix], + [am_cv_python_prefix], + [am_cv_python_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.prefix)"`]) + + dnl If sys.prefix is a subdir of $prefix, replace the literal value of + dnl $prefix with a variable reference so it can be overridden. + case $am_cv_python_prefix in + $am__usable_prefix*) + am__strip_prefix=`echo "$am__usable_prefix" | sed 's|.|.|g'` + am_python_prefix_subst=`echo "$am_cv_python_prefix" | sed "s,^$am__strip_prefix,\\${prefix},"` + ;; + *) + am_python_prefix_subst=$am_cv_python_prefix + ;; + esac + else # using GNU prefix value, not python sys.prefix + am_python_prefix_subst='${prefix}' + am_python_prefix=$am_python_prefix_subst + AC_MSG_CHECKING([for GNU default $am_display_PYTHON prefix]) + AC_MSG_RESULT([$am_python_prefix]) + fi]) + # Substituting python_prefix_subst value. + AC_SUBST([PYTHON_PREFIX], [$am_python_prefix_subst]) + + # emacs-page Now do it all over again for Python exec_prefix, but with yet + # another conditional: fall back to regular prefix if that was specified. + AC_ARG_WITH([python_exec_prefix], + [AS_HELP_STRING([--with-python_exec_prefix], + [override the default PYTHON_EXEC_PREFIX])], + [am_python_exec_prefix_subst=$withval + am_cv_python_exec_prefix=$withval + AC_MSG_CHECKING([for explicit $am_display_PYTHON exec_prefix]) + AC_MSG_RESULT([$am_cv_python_exec_prefix])], + [ + # no explicit --with-python_exec_prefix, but if + # --with-python_prefix was given, use its value for python_exec_prefix too. + AS_IF([test -n "$with_python_prefix"], + [am_python_exec_prefix_subst=$with_python_prefix + am_cv_python_exec_prefix=$with_python_prefix + AC_MSG_CHECKING([for python_prefix-given $am_display_PYTHON exec_prefix]) + AC_MSG_RESULT([$am_cv_python_exec_prefix])], + [ + # Set am__usable_exec_prefix whether using GNU or Python values, + # since we use that variable for pyexecdir. + if test "x$exec_prefix" = xNONE; then + am__usable_exec_prefix=$am__usable_prefix + else + am__usable_exec_prefix=$exec_prefix + fi + # + if $am_use_python_sys; then # using python sys.exec_prefix, not GNU + AC_CACHE_CHECK([for python default $am_display_PYTHON exec_prefix], + [am_cv_python_exec_prefix], + [am_cv_python_exec_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)"`]) + dnl If sys.exec_prefix is a subdir of $exec_prefix, replace the + dnl literal value of $exec_prefix with a variable reference so it can + dnl be overridden. + case $am_cv_python_exec_prefix in + $am__usable_exec_prefix*) + am__strip_prefix=`echo "$am__usable_exec_prefix" | sed 's|.|.|g'` + am_python_exec_prefix_subst=`echo "$am_cv_python_exec_prefix" | sed "s,^$am__strip_prefix,\\${exec_prefix},"` + ;; + *) + am_python_exec_prefix_subst=$am_cv_python_exec_prefix + ;; + esac + else # using GNU $exec_prefix, not python sys.exec_prefix + am_python_exec_prefix_subst='${exec_prefix}' + am_python_exec_prefix=$am_python_exec_prefix_subst + AC_MSG_CHECKING([for GNU default $am_display_PYTHON exec_prefix]) + AC_MSG_RESULT([$am_python_exec_prefix]) + fi])]) + # Substituting python_exec_prefix_subst. + AC_SUBST([PYTHON_EXEC_PREFIX], [$am_python_exec_prefix_subst]) + + # Factor out some code duplication into this shell variable. + am_python_setup_sysconfig="\ +import sys +# Prefer sysconfig over distutils.sysconfig, for better compatibility +# with python 3.x. See automake bug#10227. +try: + import sysconfig +except ImportError: + can_use_sysconfig = 0 +else: + can_use_sysconfig = 1 +# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: +# +try: + from platform import python_implementation + if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': + can_use_sysconfig = 0 +except ImportError: + pass" + + dnl emacs-page Set up 4 directories: + + dnl 1. pythondir: where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behavior + dnl is more consistent with lispdir.m4 for example. + dnl Query distutils for this directory. + dnl + AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)], + [am_cv_python_pythondir], + [if test "x$am_cv_python_prefix" = x; then + am_py_prefix=$am__usable_prefix + else + am_py_prefix=$am_cv_python_prefix + fi + am_cv_python_pythondir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + if hasattr(sysconfig, 'get_default_scheme'): + scheme = sysconfig.get_default_scheme() + else: + scheme = sysconfig._get_default_scheme() + if scheme == 'posix_local': + # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ + scheme = 'posix_prefix' + sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') +sys.stdout.write(sitedir)"` + # + case $am_cv_python_pythondir in + $am_py_prefix*) + am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` + am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,\\${PYTHON_PREFIX},"` + ;; + *) + case $am_py_prefix in + /usr|/System*) ;; + *) am_cv_python_pythondir="\${PYTHON_PREFIX}/lib/python$PYTHON_VERSION/site-packages" + ;; + esac + ;; + esac + ]) + AC_SUBST([pythondir], [$am_cv_python_pythondir]) + + dnl 2. pkgpythondir: $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + dnl + AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) + + dnl 3. pyexecdir: directory for installing python extension modules + dnl (shared libraries). + dnl Query distutils for this directory. + dnl + AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)], + [am_cv_python_pyexecdir], + [if test "x$am_cv_python_exec_prefix" = x; then + am_py_exec_prefix=$am__usable_exec_prefix + else + am_py_exec_prefix=$am_cv_python_exec_prefix + fi + am_cv_python_pyexecdir=`$PYTHON -c " +$am_python_setup_sysconfig +if can_use_sysconfig: + if hasattr(sysconfig, 'get_default_scheme'): + scheme = sysconfig.get_default_scheme() + else: + scheme = sysconfig._get_default_scheme() + if scheme == 'posix_local': + # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ + scheme = 'posix_prefix' + sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'}) +else: + from distutils import sysconfig + sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix') +sys.stdout.write(sitedir)"` + # + case $am_cv_python_pyexecdir in + $am_py_exec_prefix*) + am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` + am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,\\${PYTHON_EXEC_PREFIX},"` + ;; + *) + case $am_py_exec_prefix in + /usr|/System*) ;; + *) am_cv_python_pyexecdir="\${PYTHON_EXEC_PREFIX}/lib/python$PYTHON_VERSION/site-packages" + ;; + esac + ;; + esac + ]) + AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) + + dnl 4. pkgpyexecdir: $(pyexecdir)/$(PACKAGE) + dnl + AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) + + dnl Run any user-specified action. + $2 + fi +]) + + +# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# This test uses sys.hexversion instead of the string equivalent (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). +AC_DEFUN([AM_PYTHON_CHECK_VERSION], + [prog="import sys +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +# map returns an iterator in Python 3.0 and a list in 2.x +minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] +minverhex = 0 +# xrange is not present in Python 3.0 and range returns an iterator +for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] +sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2021 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/ax_check_compile_flag.m4]) +m4_include([m4/ax_check_link_flag.m4]) +m4_include([m4/ax_check_openssl.m4]) +m4_include([m4/ax_gcc_func_attribute.m4]) +m4_include([m4/ax_jemalloc.m4]) +m4_include([m4/ax_lib_lmdb.m4]) +m4_include([m4/ax_posix_shell.m4]) +m4_include([m4/ax_prog_cc_for_build.m4]) +m4_include([m4/ax_pthread.m4]) +m4_include([m4/ax_restore_flags.m4]) +m4_include([m4/ax_save_flags.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/pkg-modversion.m4]) diff --git a/ar-lib b/ar-lib new file mode 100755 index 0000000..c349042 --- /dev/null +++ b/ar-lib @@ -0,0 +1,271 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2019-07-04.01; # UTC + +# Copyright (C) 2010-2021 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN* | MSYS*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin | msys) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat <&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = bin +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = named rndc dig delv dnssec tools nsupdate check confgen tests plugins +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +doc: doc-recursive + +doc-am: doc-local + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +test: test-recursive + +test-am: test-local + +uninstall-am: + +unit: unit-recursive + +unit-am: unit-local + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am test-am \ + test-local uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/check/Makefile.am b/bin/check/Makefile.am new file mode 100644 index 0000000..c25dc4d --- /dev/null +++ b/bin/check/Makefile.am @@ -0,0 +1,32 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) + +AM_CPPFLAGS += \ + -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" + +noinst_LTLIBRARIES = libcheck-tool.la + +libcheck_tool_la_SOURCES = \ + check-tool.h \ + check-tool.c + +LDADD += \ + libcheck-tool.la \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) \ + $(LIBISCCFG_LIBS) + +bin_PROGRAMS = named-checkconf named-checkzone + +install-exec-hook: + ln -f $(DESTDIR)$(bindir)/named-checkzone \ + $(DESTDIR)$(bindir)/named-compilezone + +uninstall-hook: + -rm -f $(DESTDIR)$(bindir)/named-compilezone diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in new file mode 100644 index 0000000..0297ebb --- /dev/null +++ b/bin/check/Makefile.in @@ -0,0 +1,886 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +bin_PROGRAMS = named-checkconf$(EXEEXT) named-checkzone$(EXEEXT) +subdir = bin/check +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libcheck_tool_la_LIBADD = +am_libcheck_tool_la_OBJECTS = check-tool.lo +libcheck_tool_la_OBJECTS = $(am_libcheck_tool_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +named_checkconf_SOURCES = named-checkconf.c +named_checkconf_OBJECTS = named-checkconf.$(OBJEXT) +named_checkconf_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +named_checkconf_DEPENDENCIES = libcheck-tool.la $(am__DEPENDENCIES_2) \ + $(LIBDNS_LIBS) $(LIBNS_LIBS) $(LIBISCCFG_LIBS) +named_checkzone_SOURCES = named-checkzone.c +named_checkzone_OBJECTS = named-checkzone.$(OBJEXT) +named_checkzone_LDADD = $(LDADD) +named_checkzone_DEPENDENCIES = libcheck-tool.la $(am__DEPENDENCIES_2) \ + $(LIBDNS_LIBS) $(LIBNS_LIBS) $(LIBISCCFG_LIBS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/check-tool.Plo \ + ./$(DEPDIR)/named-checkconf.Po ./$(DEPDIR)/named-checkzone.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcheck_tool_la_SOURCES) named-checkconf.c \ + named-checkzone.c +DIST_SOURCES = $(libcheck_tool_la_SOURCES) named-checkconf.c \ + named-checkzone.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS) \ + -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = libcheck-tool.la $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(LIBISCCFG_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = libcheck-tool.la +libcheck_tool_la_SOURCES = \ + check-tool.h \ + check-tool.c + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/check/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/check/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libcheck-tool.la: $(libcheck_tool_la_OBJECTS) $(libcheck_tool_la_DEPENDENCIES) $(EXTRA_libcheck_tool_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libcheck_tool_la_OBJECTS) $(libcheck_tool_la_LIBADD) $(LIBS) + +named-checkconf$(EXEEXT): $(named_checkconf_OBJECTS) $(named_checkconf_DEPENDENCIES) $(EXTRA_named_checkconf_DEPENDENCIES) + @rm -f named-checkconf$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(named_checkconf_OBJECTS) $(named_checkconf_LDADD) $(LIBS) + +named-checkzone$(EXEEXT): $(named_checkzone_OBJECTS) $(named_checkzone_DEPENDENCIES) $(EXTRA_named_checkzone_DEPENDENCIES) + @rm -f named-checkzone$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(named_checkzone_OBJECTS) $(named_checkzone_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check-tool.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-checkconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/named-checkzone.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/check-tool.Plo + -rm -f ./$(DEPDIR)/named-checkconf.Po + -rm -f ./$(DEPDIR)/named-checkzone.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/check-tool.Plo + -rm -f ./$(DEPDIR)/named-checkconf.Po + -rm -f ./$(DEPDIR)/named-checkzone.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-exec-am \ + install-strip uninstall-am + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-hook unit-am \ + unit-local + +.PRECIOUS: Makefile + + +install-exec-hook: + ln -f $(DESTDIR)$(bindir)/named-checkzone \ + $(DESTDIR)$(bindir)/named-compilezone + +uninstall-hook: + -rm -f $(DESTDIR)$(bindir)/named-compilezone + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c new file mode 100644 index 0000000..1b66ccf --- /dev/null +++ b/bin/check/check-tool.c @@ -0,0 +1,693 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "check-tool.h" + +#ifndef CHECK_SIBLING +#define CHECK_SIBLING 1 +#endif /* ifndef CHECK_SIBLING */ + +#ifndef CHECK_LOCAL +#define CHECK_LOCAL 1 +#endif /* ifndef CHECK_LOCAL */ + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +#define ERR_IS_CNAME 1 +#define ERR_NO_ADDRESSES 2 +#define ERR_LOOKUP_FAILURE 3 +#define ERR_EXTRA_A 4 +#define ERR_EXTRA_AAAA 5 +#define ERR_MISSING_GLUE 5 +#define ERR_IS_MXCNAME 6 +#define ERR_IS_SRVCNAME 7 + +static const char *dbtype[] = { ZONEDB_DEFAULT }; + +int debug = 0; +const char *journal = NULL; +bool nomerge = true; +#if CHECK_LOCAL +bool docheckmx = true; +bool dochecksrv = true; +bool docheckns = true; +#else /* if CHECK_LOCAL */ +bool docheckmx = false; +bool dochecksrv = false; +bool docheckns = false; +#endif /* if CHECK_LOCAL */ +dns_zoneopt_t zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_CHECKMX | + DNS_ZONEOPT_CHECKDUPRR | DNS_ZONEOPT_CHECKSPF | + DNS_ZONEOPT_MANYERRORS | DNS_ZONEOPT_CHECKNAMES | + DNS_ZONEOPT_CHECKINTEGRITY | +#if CHECK_SIBLING + DNS_ZONEOPT_CHECKSIBLING | +#endif /* if CHECK_SIBLING */ + DNS_ZONEOPT_CHECKSVCB | DNS_ZONEOPT_CHECKWILDCARD | + DNS_ZONEOPT_WARNMXCNAME | DNS_ZONEOPT_WARNSRVCNAME; + +/* + * This needs to match the list in bin/named/log.c. + */ +static isc_logcategory_t categories[] = { { "", 0 }, + { "unmatched", 0 }, + { NULL, 0 } }; + +static isc_symtab_t *symtab = NULL; +static isc_mem_t *sym_mctx; + +static void +freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) { + UNUSED(type); + UNUSED(value); + isc_mem_free(userarg, key); +} + +static void +add(char *key, int value) { + isc_result_t result; + isc_symvalue_t symvalue; + + if (sym_mctx == NULL) { + isc_mem_create(&sym_mctx); + } + + if (symtab == NULL) { + result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx, + false, &symtab); + if (result != ISC_R_SUCCESS) { + return; + } + } + + key = isc_mem_strdup(sym_mctx, key); + + symvalue.as_pointer = NULL; + result = isc_symtab_define(symtab, key, value, symvalue, + isc_symexists_reject); + if (result != ISC_R_SUCCESS) { + isc_mem_free(sym_mctx, key); + } +} + +static bool +logged(char *key, int value) { + isc_result_t result; + + if (symtab == NULL) { + return false; + } + + result = isc_symtab_lookup(symtab, key, value, NULL); + if (result == ISC_R_SUCCESS) { + return true; + } + return false; +} + +static bool +checkns(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner, + dns_rdataset_t *a, dns_rdataset_t *aaaa) { + dns_rdataset_t *rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + struct addrinfo hints, *ai, *cur; + char namebuf[DNS_NAME_FORMATSIZE + 1]; + char ownerbuf[DNS_NAME_FORMATSIZE]; + char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")]; + bool answer = true; + bool match; + const char *type; + void *ptr = NULL; + int result; + + REQUIRE(a == NULL || !dns_rdataset_isassociated(a) || + a->type == dns_rdatatype_a); + REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) || + aaaa->type == dns_rdatatype_aaaa); + + if (a == NULL || aaaa == NULL) { + return answer; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + /* + * Turn off search. + */ + if (dns_name_countlabels(name) > 1U) { + strlcat(namebuf, ".", sizeof(namebuf)); + } + dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); + + result = getaddrinfo(namebuf, NULL, &hints, &ai); + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + switch (result) { + case 0: + /* + * Work around broken getaddrinfo() implementations that + * fail to set ai_canonname on first entry. + */ + cur = ai; + while (cur != NULL && cur->ai_canonname == NULL && + cur->ai_next != NULL) + { + cur = cur->ai_next; + } + if (cur != NULL && cur->ai_canonname != NULL && + strcasecmp(cur->ai_canonname, namebuf) != 0 && + !logged(namebuf, ERR_IS_CNAME)) + { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/NS '%s' (out of zone) " + "is a CNAME '%s' (illegal)", + ownerbuf, namebuf, cur->ai_canonname); + /* XXX950 make fatal for 9.5.0 */ + /* answer = false; */ + add(namebuf, ERR_IS_CNAME); + } + break; + case EAI_NONAME: +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */ + if (!logged(namebuf, ERR_NO_ADDRESSES)) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/NS '%s' (out of zone) " + "has no addresses records (A or AAAA)", + ownerbuf, namebuf); + add(namebuf, ERR_NO_ADDRESSES); + } + /* XXX950 make fatal for 9.5.0 */ + return true; + + default: + if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { + dns_zone_log(zone, ISC_LOG_WARNING, + "getaddrinfo(%s) failed: %s", namebuf, + gai_strerror(result)); + add(namebuf, ERR_LOOKUP_FAILURE); + } + return true; + } + + /* + * Check that all glue records really exist. + */ + if (!dns_rdataset_isassociated(a)) { + goto checkaaaa; + } + result = dns_rdataset_first(a); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(a, &rdata); + match = false; + for (cur = ai; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET) { + continue; + } + ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; + if (memcmp(ptr, rdata.data, rdata.length) == 0) { + match = true; + break; + } + } + if (!match && !logged(namebuf, ERR_EXTRA_A)) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/NS '%s' " + "extra GLUE A record (%s)", + ownerbuf, namebuf, + inet_ntop(AF_INET, rdata.data, addrbuf, + sizeof(addrbuf))); + add(namebuf, ERR_EXTRA_A); + /* XXX950 make fatal for 9.5.0 */ + /* answer = false; */ + } + dns_rdata_reset(&rdata); + result = dns_rdataset_next(a); + } + +checkaaaa: + if (!dns_rdataset_isassociated(aaaa)) { + goto checkmissing; + } + result = dns_rdataset_first(aaaa); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(aaaa, &rdata); + match = false; + for (cur = ai; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) { + continue; + } + ptr = &((struct sockaddr_in6 *)(cur->ai_addr)) + ->sin6_addr; + if (memcmp(ptr, rdata.data, rdata.length) == 0) { + match = true; + break; + } + } + if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/NS '%s' " + "extra GLUE AAAA record (%s)", + ownerbuf, namebuf, + inet_ntop(AF_INET6, rdata.data, addrbuf, + sizeof(addrbuf))); + add(namebuf, ERR_EXTRA_AAAA); + /* XXX950 make fatal for 9.5.0. */ + /* answer = false; */ + } + dns_rdata_reset(&rdata); + result = dns_rdataset_next(aaaa); + } + +checkmissing: + /* + * Check that all addresses appear in the glue. + */ + if (!logged(namebuf, ERR_MISSING_GLUE)) { + bool missing_glue = false; + for (cur = ai; cur != NULL; cur = cur->ai_next) { + switch (cur->ai_family) { + case AF_INET: + rdataset = a; + ptr = &((struct sockaddr_in *)(cur->ai_addr)) + ->sin_addr; + type = "A"; + break; + case AF_INET6: + rdataset = aaaa; + ptr = &((struct sockaddr_in6 *)(cur->ai_addr)) + ->sin6_addr; + type = "AAAA"; + break; + default: + continue; + } + match = false; + if (dns_rdataset_isassociated(rdataset)) { + result = dns_rdataset_first(rdataset); + } else { + result = ISC_R_FAILURE; + } + while (result == ISC_R_SUCCESS && !match) { + dns_rdataset_current(rdataset, &rdata); + if (memcmp(ptr, rdata.data, rdata.length) == 0) + { + match = true; + } + dns_rdata_reset(&rdata); + result = dns_rdataset_next(rdataset); + } + if (!match) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/NS '%s' " + "missing GLUE %s record (%s)", + ownerbuf, namebuf, type, + inet_ntop(cur->ai_family, ptr, + addrbuf, + sizeof(addrbuf))); + /* XXX950 make fatal for 9.5.0. */ + /* answer = false; */ + missing_glue = true; + } + } + if (missing_glue) { + add(namebuf, ERR_MISSING_GLUE); + } + } + freeaddrinfo(ai); + return answer; +} + +static bool +checkmx(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner) { + struct addrinfo hints, *ai, *cur; + char namebuf[DNS_NAME_FORMATSIZE + 1]; + char ownerbuf[DNS_NAME_FORMATSIZE]; + int result; + int level = ISC_LOG_ERROR; + bool answer = true; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + /* + * Turn off search. + */ + if (dns_name_countlabels(name) > 1U) { + strlcat(namebuf, ".", sizeof(namebuf)); + } + dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); + + result = getaddrinfo(namebuf, NULL, &hints, &ai); + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + switch (result) { + case 0: + /* + * Work around broken getaddrinfo() implementations that + * fail to set ai_canonname on first entry. + */ + cur = ai; + while (cur != NULL && cur->ai_canonname == NULL && + cur->ai_next != NULL) + { + cur = cur->ai_next; + } + if (cur != NULL && cur->ai_canonname != NULL && + strcasecmp(cur->ai_canonname, namebuf) != 0) + { + if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0) { + level = ISC_LOG_WARNING; + } + if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) { + if (!logged(namebuf, ERR_IS_MXCNAME)) { + dns_zone_log(zone, level, + "%s/MX '%s' (out of zone)" + " is a CNAME '%s' " + "(illegal)", + ownerbuf, namebuf, + cur->ai_canonname); + add(namebuf, ERR_IS_MXCNAME); + } + if (level == ISC_LOG_ERROR) { + answer = false; + } + } + } + freeaddrinfo(ai); + return answer; + + case EAI_NONAME: +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */ + if (!logged(namebuf, ERR_NO_ADDRESSES)) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/MX '%s' (out of zone) " + "has no addresses records (A or AAAA)", + ownerbuf, namebuf); + add(namebuf, ERR_NO_ADDRESSES); + } + /* XXX950 make fatal for 9.5.0. */ + return true; + + default: + if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { + dns_zone_log(zone, ISC_LOG_WARNING, + "getaddrinfo(%s) failed: %s", namebuf, + gai_strerror(result)); + add(namebuf, ERR_LOOKUP_FAILURE); + } + return true; + } +} + +static bool +checksrv(dns_zone_t *zone, const dns_name_t *name, const dns_name_t *owner) { + struct addrinfo hints, *ai, *cur; + char namebuf[DNS_NAME_FORMATSIZE + 1]; + char ownerbuf[DNS_NAME_FORMATSIZE]; + int result; + int level = ISC_LOG_ERROR; + bool answer = true; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + /* + * Turn off search. + */ + if (dns_name_countlabels(name) > 1U) { + strlcat(namebuf, ".", sizeof(namebuf)); + } + dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); + + result = getaddrinfo(namebuf, NULL, &hints, &ai); + dns_name_format(name, namebuf, sizeof(namebuf) - 1); + switch (result) { + case 0: + /* + * Work around broken getaddrinfo() implementations that + * fail to set ai_canonname on first entry. + */ + cur = ai; + while (cur != NULL && cur->ai_canonname == NULL && + cur->ai_next != NULL) + { + cur = cur->ai_next; + } + if (cur != NULL && cur->ai_canonname != NULL && + strcasecmp(cur->ai_canonname, namebuf) != 0) + { + if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) { + level = ISC_LOG_WARNING; + } + if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) { + if (!logged(namebuf, ERR_IS_SRVCNAME)) { + dns_zone_log(zone, level, + "%s/SRV '%s'" + " (out of zone) is a " + "CNAME '%s' (illegal)", + ownerbuf, namebuf, + cur->ai_canonname); + add(namebuf, ERR_IS_SRVCNAME); + } + if (level == ISC_LOG_ERROR) { + answer = false; + } + } + } + freeaddrinfo(ai); + return answer; + + case EAI_NONAME: +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif /* if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) */ + if (!logged(namebuf, ERR_NO_ADDRESSES)) { + dns_zone_log(zone, ISC_LOG_ERROR, + "%s/SRV '%s' (out of zone) " + "has no addresses records (A or AAAA)", + ownerbuf, namebuf); + add(namebuf, ERR_NO_ADDRESSES); + } + /* XXX950 make fatal for 9.5.0. */ + return true; + + default: + if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { + dns_zone_log(zone, ISC_LOG_WARNING, + "getaddrinfo(%s) failed: %s", namebuf, + gai_strerror(result)); + add(namebuf, ERR_LOOKUP_FAILURE); + } + return true; + } +} + +isc_result_t +setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + isc_log_t *log = NULL; + + isc_log_create(mctx, &log, &logconfig); + isc_log_registercategories(log, categories); + isc_log_setcontext(log); + dns_log_init(log); + dns_log_setcontext(log); + cfg_log_init(log); + ns_log_init(log); + + destination.file.stream = errout; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, &destination, 0); + + RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) == + ISC_R_SUCCESS); + + *logp = log; + return ISC_R_SUCCESS; +} + +/*% load the zone */ +isc_result_t +load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, + dns_masterformat_t fileformat, const char *classname, + dns_ttl_t maxttl, dns_zone_t **zonep) { + isc_result_t result; + dns_rdataclass_t rdclass; + isc_textregion_t region; + isc_buffer_t buffer; + dns_fixedname_t fixorigin; + dns_name_t *origin; + dns_zone_t *zone = NULL; + + REQUIRE(zonep == NULL || *zonep == NULL); + + if (debug) { + fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n", + zonename, filename, classname); + } + + dns_zone_create(&zone, mctx, 0); + + dns_zone_settype(zone, dns_zone_primary); + + isc_buffer_constinit(&buffer, zonename, strlen(zonename)); + isc_buffer_add(&buffer, strlen(zonename)); + origin = dns_fixedname_initname(&fixorigin); + CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); + CHECK(dns_zone_setorigin(zone, origin)); + dns_zone_setdbtype(zone, 1, (const char *const *)dbtype); + if (strcmp(filename, "-") == 0) { + CHECK(dns_zone_setstream(zone, stdin, fileformat, + &dns_master_style_default)); + } else { + CHECK(dns_zone_setfile(zone, filename, fileformat, + &dns_master_style_default)); + } + if (journal != NULL) { + CHECK(dns_zone_setjournal(zone, journal)); + } + + region.base = UNCONST(classname); + region.length = strlen(classname); + CHECK(dns_rdataclass_fromtext(&rdclass, ®ion)); + + dns_zone_setclass(zone, rdclass); + dns_zone_setoption(zone, zone_options, true); + dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge); + + dns_zone_setmaxttl(zone, maxttl); + + if (docheckmx) { + dns_zone_setcheckmx(zone, checkmx); + } + if (docheckns) { + dns_zone_setcheckns(zone, checkns); + } + if (dochecksrv) { + dns_zone_setchecksrv(zone, checksrv); + } + + CHECK(dns_zone_load(zone, false)); + + if (zonep != NULL) { + *zonep = zone; + zone = NULL; + } + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + return result; +} + +/*% dump the zone */ +isc_result_t +dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, + dns_masterformat_t fileformat, const dns_master_style_t *style, + const uint32_t rawversion) { + isc_result_t result; + FILE *output = stdout; + const char *flags; + + flags = (fileformat == dns_masterformat_text) ? "w" : "wb"; + + if (debug) { + if (filename != NULL && strcmp(filename, "-") != 0) { + fprintf(stderr, "dumping \"%s\" to \"%s\"\n", zonename, + filename); + } else { + fprintf(stderr, "dumping \"%s\"\n", zonename); + } + } + + if (filename != NULL && strcmp(filename, "-") != 0) { + result = isc_stdio_open(filename, flags, &output); + + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "could not open output " + "file \"%s\" for writing\n", + filename); + return ISC_R_FAILURE; + } + } + + result = dns_zone_dumptostream(zone, output, fileformat, style, + rawversion); + if (output != stdout) { + (void)isc_stdio_close(output); + } + + return result; +} diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h new file mode 100644 index 0000000..64ac9e7 --- /dev/null +++ b/bin/check/check-tool.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp); + +isc_result_t +load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, + dns_masterformat_t fileformat, const char *classname, + dns_ttl_t maxttl, dns_zone_t **zonep); + +isc_result_t +dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, + dns_masterformat_t fileformat, const dns_master_style_t *style, + const uint32_t rawversion); + +extern int debug; +extern const char *journal; +extern bool nomerge; +extern bool docheckmx; +extern bool docheckns; +extern bool dochecksrv; +extern dns_zoneopt_t zone_options; + +ISC_LANG_ENDDECLS diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c new file mode 100644 index 0000000..ce0a980 --- /dev/null +++ b/bin/check/named-checkconf.c @@ -0,0 +1,778 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "check-tool.h" + +static const char *program = "named-checkconf"; + +isc_log_t *logc = NULL; + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +/*% usage */ +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, + "usage: %s [-achijlvz] [-p [-x]] [-t directory] " + "[named.conf]\n", + program); + exit(EXIT_SUCCESS); +} + +/*% directory callback */ +static isc_result_t +directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { + isc_result_t result; + const char *directory; + + REQUIRE(strcasecmp("directory", clausename) == 0); + + UNUSED(arg); + UNUSED(clausename); + + /* + * Change directory. + */ + directory = cfg_obj_asstring(obj); + result = isc_dir_chdir(directory); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, logc, ISC_LOG_ERROR, + "change directory to '%s' failed: %s\n", directory, + isc_result_totext(result)); + return result; + } + + return ISC_R_SUCCESS; +} + +static bool +get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) { + int i; + for (i = 0;; i++) { + if (maps[i] == NULL) { + return false; + } + if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) { + return true; + } + } +} + +static bool +get_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) { + const cfg_listelt_t *element; + const cfg_obj_t *checknames; + const cfg_obj_t *type; + const cfg_obj_t *value; + isc_result_t result; + int i; + + for (i = 0;; i++) { + if (maps[i] == NULL) { + return false; + } + checknames = NULL; + result = cfg_map_get(maps[i], "check-names", &checknames); + if (result != ISC_R_SUCCESS) { + continue; + } + if (checknames != NULL && !cfg_obj_islist(checknames)) { + *obj = checknames; + return true; + } + for (element = cfg_list_first(checknames); element != NULL; + element = cfg_list_next(element)) + { + value = cfg_listelt_value(element); + type = cfg_tuple_get(value, "type"); + if ((strcasecmp(cfg_obj_asstring(type), "primary") != + 0) && + (strcasecmp(cfg_obj_asstring(type), "master") != 0)) + { + continue; + } + *obj = cfg_tuple_get(value, "mode"); + return true; + } + } +} + +static isc_result_t +configure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) { + isc_result_t result; + dns_db_t *db = NULL; + dns_rdataclass_t rdclass; + isc_textregion_t r; + + if (zfile == NULL) { + return ISC_R_FAILURE; + } + + r.base = UNCONST(zclass); + r.length = strlen(zclass); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_rootns_create(mctx, rdclass, zfile, &db); + if (result != ISC_R_SUCCESS) { + return result; + } + + dns_db_detach(&db); + return ISC_R_SUCCESS; +} + +/*% configure the zone */ +static isc_result_t +configure_zone(const char *vclass, const char *view, const cfg_obj_t *zconfig, + const cfg_obj_t *vconfig, const cfg_obj_t *config, + isc_mem_t *mctx, bool list) { + int i = 0; + isc_result_t result; + const char *zclass; + const char *zname; + const char *zfile = NULL; + const cfg_obj_t *maps[4]; + const cfg_obj_t *primariesobj = NULL; + const cfg_obj_t *inviewobj = NULL; + const cfg_obj_t *zoptions = NULL; + const cfg_obj_t *classobj = NULL; + const cfg_obj_t *typeobj = NULL; + const cfg_obj_t *fileobj = NULL; + const cfg_obj_t *dlzobj = NULL; + const cfg_obj_t *dbobj = NULL; + const cfg_obj_t *obj = NULL; + const cfg_obj_t *fmtobj = NULL; + dns_masterformat_t masterformat; + dns_ttl_t maxttl = 0; + + zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS; + + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + classobj = cfg_tuple_get(zconfig, "class"); + if (!cfg_obj_isstring(classobj)) { + zclass = vclass; + } else { + zclass = cfg_obj_asstring(classobj); + } + + zoptions = cfg_tuple_get(zconfig, "options"); + maps[i++] = zoptions; + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + if (config != NULL) { + cfg_map_get(config, "options", &obj); + if (obj != NULL) { + maps[i++] = obj; + } + } + maps[i] = NULL; + + cfg_map_get(zoptions, "in-view", &inviewobj); + if (inviewobj != NULL && list) { + const char *inview = cfg_obj_asstring(inviewobj); + printf("%s %s %s in-view %s\n", zname, zclass, view, inview); + } + if (inviewobj != NULL) { + return ISC_R_SUCCESS; + } + + cfg_map_get(zoptions, "type", &typeobj); + if (typeobj == NULL) { + return ISC_R_FAILURE; + } + + if (list) { + const char *ztype = cfg_obj_asstring(typeobj); + printf("%s %s %s %s\n", zname, zclass, view, ztype); + return ISC_R_SUCCESS; + } + + /* + * Skip checks when using an alternate data source. + */ + cfg_map_get(zoptions, "database", &dbobj); + if (dbobj != NULL && + strcmp(ZONEDB_DEFAULT, cfg_obj_asstring(dbobj)) != 0) + { + return ISC_R_SUCCESS; + } + + cfg_map_get(zoptions, "dlz", &dlzobj); + if (dlzobj != NULL) { + return ISC_R_SUCCESS; + } + + cfg_map_get(zoptions, "file", &fileobj); + if (fileobj != NULL) { + zfile = cfg_obj_asstring(fileobj); + } + + /* + * Check hints files for hint zones. + * Skip loading checks for any type other than + * master and redirect + */ + if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0) { + return configure_hint(zfile, zclass, mctx); + } else if ((strcasecmp(cfg_obj_asstring(typeobj), "primary") != 0) && + (strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) && + (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0)) + { + return ISC_R_SUCCESS; + } + + /* + * Is the redirect zone configured as a secondary? + */ + if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) { + cfg_map_get(zoptions, "primaries", &primariesobj); + if (primariesobj == NULL) { + cfg_map_get(zoptions, "masters", &primariesobj); + } + + if (primariesobj != NULL) { + return ISC_R_SUCCESS; + } + } + + if (zfile == NULL) { + return ISC_R_FAILURE; + } + + obj = NULL; + if (get_maps(maps, "check-dup-records", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } + + obj = NULL; + if (get_maps(maps, "check-mx", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKMX; + zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options |= DNS_ZONEOPT_CHECKMX; + zone_options |= DNS_ZONEOPT_CHECKMXFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKMX; + zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_CHECKMX; + zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; + } + + obj = NULL; + if (get_maps(maps, "check-integrity", &obj)) { + if (cfg_obj_asboolean(obj)) { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; + } else { + zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; + } + } else { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; + } + + obj = NULL; + if (get_maps(maps, "check-mx-cname", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_WARNMXCNAME; + zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; + zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options |= DNS_ZONEOPT_WARNMXCNAME; + zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_WARNMXCNAME; + zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; + } + + obj = NULL; + if (get_maps(maps, "check-srv-cname", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_WARNSRVCNAME; + zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; + zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options |= DNS_ZONEOPT_WARNSRVCNAME; + zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_WARNSRVCNAME; + zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; + } + + obj = NULL; + if (get_maps(maps, "check-sibling", &obj)) { + if (cfg_obj_asboolean(obj)) { + zone_options |= DNS_ZONEOPT_CHECKSIBLING; + } else { + zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; + } + } + + obj = NULL; + if (get_maps(maps, "check-spf", &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKSPF; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKSPF; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_CHECKSPF; + } + + obj = NULL; + if (get_maps(maps, "check-svcb", &obj)) { + if (cfg_obj_asboolean(obj)) { + zone_options |= DNS_ZONEOPT_CHECKSVCB; + } else { + zone_options &= ~DNS_ZONEOPT_CHECKSVCB; + } + } else { + zone_options |= DNS_ZONEOPT_CHECKSVCB; + } + + obj = NULL; + if (get_maps(maps, "check-wildcard", &obj)) { + if (cfg_obj_asboolean(obj)) { + zone_options |= DNS_ZONEOPT_CHECKWILDCARD; + } else { + zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD; + } + } else { + zone_options |= DNS_ZONEOPT_CHECKWILDCARD; + } + + obj = NULL; + if (get_checknames(maps, &obj)) { + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + zone_options |= DNS_ZONEOPT_CHECKNAMES; + zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + zone_options |= DNS_ZONEOPT_CHECKNAMES; + zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + zone_options &= ~DNS_ZONEOPT_CHECKNAMES; + zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; + } else { + UNREACHABLE(); + } + } else { + zone_options |= DNS_ZONEOPT_CHECKNAMES; + zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; + } + + masterformat = dns_masterformat_text; + fmtobj = NULL; + if (get_maps(maps, "masterfile-format", &fmtobj)) { + const char *masterformatstr = cfg_obj_asstring(fmtobj); + if (strcasecmp(masterformatstr, "text") == 0) { + masterformat = dns_masterformat_text; + } else if (strcasecmp(masterformatstr, "raw") == 0) { + masterformat = dns_masterformat_raw; + } else { + UNREACHABLE(); + } + } + + obj = NULL; + if (get_maps(maps, "max-zone-ttl", &obj)) { + maxttl = cfg_obj_asduration(obj); + zone_options |= DNS_ZONEOPT_CHECKTTL; + } + + result = load_zone(mctx, zname, zfile, masterformat, zclass, maxttl, + NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass, + isc_result_totext(result)); + } + return result; +} + +/*% configure a view */ +static isc_result_t +configure_view(const char *vclass, const char *view, const cfg_obj_t *config, + const cfg_obj_t *vconfig, isc_mem_t *mctx, bool list) { + const cfg_listelt_t *element; + const cfg_obj_t *voptions; + const cfg_obj_t *zonelist; + isc_result_t result = ISC_R_SUCCESS; + isc_result_t tresult; + + voptions = NULL; + if (vconfig != NULL) { + voptions = cfg_tuple_get(vconfig, "options"); + } + + zonelist = NULL; + if (voptions != NULL) { + (void)cfg_map_get(voptions, "zone", &zonelist); + } else { + (void)cfg_map_get(config, "zone", &zonelist); + } + + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = cfg_listelt_value(element); + tresult = configure_zone(vclass, view, zconfig, vconfig, config, + mctx, list); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + } + } + return result; +} + +static isc_result_t +config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, + dns_rdataclass_t *classp) { + isc_textregion_t r; + + if (!cfg_obj_isstring(classobj)) { + *classp = defclass; + return ISC_R_SUCCESS; + } + r.base = UNCONST(cfg_obj_asstring(classobj)); + r.length = strlen(r.base); + return dns_rdataclass_fromtext(classp, &r); +} + +/*% load zones from the configuration */ +static isc_result_t +load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, + bool list_zones) { + const cfg_listelt_t *element; + const cfg_obj_t *views; + const cfg_obj_t *vconfig; + isc_result_t result = ISC_R_SUCCESS; + isc_result_t tresult; + + views = NULL; + + (void)cfg_map_get(config, "view", &views); + for (element = cfg_list_first(views); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *classobj; + dns_rdataclass_t viewclass; + const char *vname; + char buf[sizeof("CLASS65535")]; + + vconfig = cfg_listelt_value(element); + if (vconfig == NULL) { + continue; + } + + classobj = cfg_tuple_get(vconfig, "class"); + tresult = config_getclass(classobj, dns_rdataclass_in, + &viewclass); + if (tresult != ISC_R_SUCCESS) { + CHECK(tresult); + } + + if (dns_rdataclass_ismeta(viewclass)) { + CHECK(ISC_R_FAILURE); + } + + dns_rdataclass_format(viewclass, buf, sizeof(buf)); + vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); + tresult = configure_view(buf, vname, config, vconfig, mctx, + list_zones); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + } + } + + if (views == NULL) { + tresult = configure_view("IN", "_default", config, NULL, mctx, + list_zones); + if (tresult != ISC_R_SUCCESS) { + result = tresult; + } + } + +cleanup: + return result; +} + +static void +output(void *closure, const char *text, int textlen) { + if (fwrite(text, 1, textlen, stdout) != (size_t)textlen) { + isc_result_t *result = closure; + perror("fwrite"); + *result = ISC_R_FAILURE; + } +} + +/*% The main processing routine */ +int +main(int argc, char **argv) { + int c; + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + const char *conffile = NULL; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_SUCCESS; + bool cleanup_dst = false; + bool load_zones = false; + bool list_zones = false; + bool print = false; + bool nodeprecate = false; + unsigned int flags = 0; + unsigned int checkflags = BIND_CHECK_PLUGINS | BIND_CHECK_ALGORITHMS; + + isc_commandline_errprint = false; + + /* + * Process memory debugging argument first. + */ +#define CMDLINE_FLAGS "acdhijlm:t:pvxz" + while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (c) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + } + if (strcasecmp(isc_commandline_argument, "trace") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + } + if (strcasecmp(isc_commandline_argument, "usage") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + } + break; + default: + break; + } + } + isc_commandline_reset = true; + + isc_mem_create(&mctx); + + while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) { + switch (c) { + case 'a': + checkflags &= ~BIND_CHECK_ALGORITHMS; + break; + + case 'c': + checkflags &= ~BIND_CHECK_PLUGINS; + break; + + case 'd': + debug++; + break; + + case 'i': + nodeprecate = true; + break; + + case 'j': + nomerge = false; + break; + + case 'l': + list_zones = true; + break; + + case 'm': + break; + + case 't': + result = isc_dir_chroot(isc_commandline_argument); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_dir_chroot: %s\n", + isc_result_totext(result)); + CHECK(result); + } + break; + + case 'p': + print = true; + break; + + case 'v': + printf("%s\n", PACKAGE_VERSION); + result = ISC_R_SUCCESS; + goto cleanup; + + case 'x': + flags |= CFG_PRINTER_XKEY; + break; + + case 'z': + load_zones = true; + docheckmx = false; + docheckns = false; + dochecksrv = false; + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + isc_mem_detach(&mctx); + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + CHECK(ISC_R_FAILURE); + } + } + + if (((flags & CFG_PRINTER_XKEY) != 0) && !print) { + fprintf(stderr, "%s: -x cannot be used without -p\n", program); + CHECK(ISC_R_FAILURE); + } + if (print && list_zones) { + fprintf(stderr, "%s: -l cannot be used with -p\n", program); + CHECK(ISC_R_FAILURE); + } + + if (isc_commandline_index + 1 < argc) { + isc_mem_detach(&mctx); + usage(); + } + if (argv[isc_commandline_index] != NULL) { + conffile = argv[isc_commandline_index]; + } + if (conffile == NULL || conffile[0] == '\0') { + conffile = NAMED_CONFFILE; + } + + CHECK(setup_logging(mctx, stdout, &logc)); + + CHECK(dst_lib_init(mctx, NULL)); + cleanup_dst = true; + + CHECK(cfg_parser_create(mctx, logc, &parser)); + + if (nodeprecate) { + cfg_parser_setflags(parser, CFG_PCTX_NODEPRECATED, true); + } + cfg_parser_setcallback(parser, directory_callback, NULL); + + CHECK(cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config)); + CHECK(isccfg_check_namedconf(config, checkflags, logc, mctx)); + if (load_zones || list_zones) { + CHECK(load_zones_fromconfig(config, mctx, list_zones)); + } + + if (print) { + cfg_printx(config, flags, output, &result); + } + +cleanup: + if (config != NULL) { + cfg_obj_destroy(parser, &config); + } + + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + + if (cleanup_dst) { + dst_lib_destroy(); + } + + /* + * Wait for memory reclamation in dns_qp to finish. + */ + rcu_barrier(); + + if (logc != NULL) { + isc_log_destroy(&logc); + } + + if (mctx != NULL) { + isc_mem_destroy(&mctx); + } + + return result == ISC_R_SUCCESS ? 0 : 1; +} diff --git a/bin/check/named-checkconf.rst b/bin/check/named-checkconf.rst new file mode 100644 index 0000000..41dad39 --- /dev/null +++ b/bin/check/named-checkconf.rst @@ -0,0 +1,116 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: named-checkconf +.. program:: named-checkconf +.. _man_named-checkconf: + +named-checkconf - named configuration file syntax checking tool +--------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`named-checkconf` [**-achjlvz**] [**-p** [**-x** ]] [**-t** directory] {filename} + +Description +~~~~~~~~~~~ + +:program:`named-checkconf` checks the syntax, but not the semantics, of a +:iscman:`named` configuration file. The file, along with all files included by it, is parsed and checked for syntax +errors. If no file is specified, +|named_conf| is read by default. + +Note: files that :iscman:`named` reads in separate parser contexts, such as +``rndc.conf`` or ``rndc.key``, are not automatically read by +:program:`named-checkconf`. Configuration errors in these files may cause +:iscman:`named` to fail to run, even if :program:`named-checkconf` was +successful. However, :program:`named-checkconf` can be run on these files +explicitly. + +Options +~~~~~~~ + +.. option:: -a + + Don't check the `dnssec-policy`'s DNSSEC key algorithms against + those supported by the crypto provider. This is useful when checking + a `named.conf` intended to be run on another machine with possibly a + different set of supported DNSSEC key algorithms. + +.. option:: -h + + This option prints the usage summary and exits. + +.. option:: -j + + When loading a zonefile, this option instructs :iscman:`named` to read the journal if it exists. + +.. option:: -l + + This option lists all the configured zones. Each line of output contains the zone + name, class (e.g. IN), view, and type (e.g. primary or secondary). + +.. option:: -c + + This option specifies that only the "core" configuration should be checked. This suppresses the loading of + plugin modules, and causes all parameters to ``plugin`` statements to + be ignored. + +.. option:: -i + + This option ignores warnings on deprecated options. + +.. option:: -p + + This option prints out the :iscman:`named.conf` and included files in canonical form if + no errors were detected. See also the :option:`-x` option. + +.. option:: -t directory + + This option instructs :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the + configuration file are processed as if run by a similarly chrooted + :iscman:`named`. + +.. option:: -v + + This option prints the version of the :program:`named-checkconf` program and exits. + +.. option:: -x + + When printing the configuration files in canonical form, this option obscures + shared secrets by replacing them with strings of question marks + (``?``). This allows the contents of :iscman:`named.conf` and related files + to be shared - for example, when submitting bug reports - + without compromising private data. This option cannot be used without + :option:`-p`. + +.. option:: -z + + This option performs a test load of all zones of type ``primary`` found in :iscman:`named.conf`. + +.. option:: filename + + This indicates the name of the configuration file to be checked. If not specified, + it defaults to |named_conf|. + +Return Values +~~~~~~~~~~~~~ + +:program:`named-checkconf` returns an exit status of 1 if errors were detected +and 0 otherwise. + +See Also +~~~~~~~~ + +:iscman:`named(8) `, :iscman:`named-checkzone(8) `, BIND 9 Administrator Reference Manual. diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c new file mode 100644 index 0000000..9f5bf45 --- /dev/null +++ b/bin/check/named-checkzone.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "check-tool.h" + +static int quiet = 0; +static isc_mem_t *mctx = NULL; +dns_zone_t *zone = NULL; +dns_zonetype_t zonetype = dns_zone_primary; +static int dumpzone = 0; +static const char *output_filename; +static const char *prog_name = NULL; +static const dns_master_style_t *outputstyle = NULL; +static enum { progmode_check, progmode_compile } progmode; + +#define ERRRET(result, function) \ + do { \ + if (result != ISC_R_SUCCESS) { \ + if (!quiet) \ + fprintf(stderr, "%s() returned %s\n", \ + function, isc_result_totext(result)); \ + return (result); \ + } \ + } while (0) + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, + "usage: %s [-djqvD] [-c class] " + "[-f inputformat] [-F outputformat] [-J filename] " + "[-s (full|relative)] [-t directory] [-w directory] " + "[-k (ignore|warn|fail)] [-m (ignore|warn|fail)] " + "[-n (ignore|warn|fail)] [-r (ignore|warn|fail)] " + "[-i (full|full-sibling|local|local-sibling|none)] " + "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] " + "[-W (ignore|warn)] " + "%s zonename [ (filename|-) ]\n", + prog_name, + progmode == progmode_check ? "[-o filename]" : "-o filename"); + exit(EXIT_FAILURE); +} + +static void +destroy(void) { + if (zone != NULL) { + dns_zone_detach(&zone); + } +} + +/*% main processing routine */ +int +main(int argc, char **argv) { + int c; + char *origin = NULL; + const char *filename = NULL; + isc_log_t *lctx = NULL; + isc_result_t result; + char classname_in[] = "IN"; + char *classname = classname_in; + const char *workdir = NULL; + const char *inputformatstr = NULL; + const char *outputformatstr = NULL; + dns_masterformat_t inputformat = dns_masterformat_text; + dns_masterformat_t outputformat = dns_masterformat_text; + dns_masterrawheader_t header; + uint32_t rawversion = 1, serialnum = 0; + dns_ttl_t maxttl = 0; + bool snset = false; + bool logdump = false; + FILE *errout = stdout; + char *endp; + + /* + * Uncomment the following line if memory debugging is needed: + * isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + */ + + outputstyle = &dns_master_style_full; + + prog_name = strrchr(argv[0], '/'); + if (prog_name == NULL) { + prog_name = strrchr(argv[0], '\\'); + } + if (prog_name != NULL) { + prog_name++; + } else { + prog_name = argv[0]; + } + /* + * Libtool doesn't preserve the program name prior to final + * installation. Remove the libtool prefix ("lt-"). + */ + if (strncmp(prog_name, "lt-", 3) == 0) { + prog_name += 3; + } + +#define PROGCMP(X) \ + (strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0) + + if (PROGCMP("named-checkzone")) { + progmode = progmode_check; + } else if (PROGCMP("named-compilezone")) { + progmode = progmode_compile; + } else { + UNREACHABLE(); + } + + /* When compiling, disable checks by default */ + if (progmode == progmode_compile) { + zone_options = 0; + docheckmx = false; + docheckns = false; + dochecksrv = false; + } + +#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0) + + isc_commandline_errprint = false; + + while ((c = isc_commandline_parse(argc, argv, + "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:C:" + "DF:M:S:T:W:")) != EOF) + { + switch (c) { + case 'c': + classname = isc_commandline_argument; + break; + + case 'd': + debug++; + break; + + case 'i': + if (ARGCMP("full")) { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY | + DNS_ZONEOPT_CHECKSIBLING; + docheckmx = true; + docheckns = true; + dochecksrv = true; + } else if (ARGCMP("full-sibling")) { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; + zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; + docheckmx = true; + docheckns = true; + dochecksrv = true; + } else if (ARGCMP("local")) { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; + zone_options |= DNS_ZONEOPT_CHECKSIBLING; + docheckmx = false; + docheckns = false; + dochecksrv = false; + } else if (ARGCMP("local-sibling")) { + zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; + zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; + docheckmx = false; + docheckns = false; + dochecksrv = false; + } else if (ARGCMP("none")) { + zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; + zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; + docheckmx = false; + docheckns = false; + dochecksrv = false; + } else { + fprintf(stderr, "invalid argument to -i: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'f': + inputformatstr = isc_commandline_argument; + break; + + case 'F': + outputformatstr = isc_commandline_argument; + break; + + case 'j': + nomerge = false; + break; + + case 'J': + journal = isc_commandline_argument; + nomerge = false; + break; + + case 'k': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKNAMES; + zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKNAMES | + DNS_ZONEOPT_CHECKNAMESFAIL; + } else if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKNAMES | + DNS_ZONEOPT_CHECKNAMESFAIL); + } else { + fprintf(stderr, "invalid argument to -k: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'L': + snset = true; + endp = NULL; + serialnum = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "source serial number " + "must be numeric"); + exit(EXIT_FAILURE); + } + break; + + case 'l': + zone_options |= DNS_ZONEOPT_CHECKTTL; + endp = NULL; + maxttl = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "maximum TTL " + "must be numeric"); + exit(EXIT_FAILURE); + } + break; + + case 'n': + if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKNS | + DNS_ZONEOPT_FATALNS); + } else if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKNS; + zone_options &= ~DNS_ZONEOPT_FATALNS; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKNS | + DNS_ZONEOPT_FATALNS; + } else { + fprintf(stderr, "invalid argument to -n: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'm': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKMX; + zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKMX | + DNS_ZONEOPT_CHECKMXFAIL; + } else if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKMX | + DNS_ZONEOPT_CHECKMXFAIL); + } else { + fprintf(stderr, "invalid argument to -m: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'o': + output_filename = isc_commandline_argument; + break; + + case 'q': + quiet++; + break; + + case 'r': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR; + zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("fail")) { + zone_options |= DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL; + } else if (ARGCMP("ignore")) { + zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR | + DNS_ZONEOPT_CHECKDUPRRFAIL); + } else { + fprintf(stderr, "invalid argument to -r: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 's': + if (ARGCMP("full")) { + outputstyle = &dns_master_style_full; + } else if (ARGCMP("relative")) { + outputstyle = &dns_master_style_default; + } else { + fprintf(stderr, + "unknown or unsupported style: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 't': + result = isc_dir_chroot(isc_commandline_argument); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_dir_chroot: %s: %s\n", + isc_commandline_argument, + isc_result_totext(result)); + exit(EXIT_FAILURE); + } + break; + + case 'v': + printf("%s\n", PACKAGE_VERSION); + exit(EXIT_SUCCESS); + + case 'w': + workdir = isc_commandline_argument; + break; + + case 'C': + if (ARGCMP("check-svcb:fail")) { + zone_options |= DNS_ZONEOPT_CHECKSVCB; + } else if (ARGCMP("check-svcb:ignore")) { + zone_options &= ~DNS_ZONEOPT_CHECKSVCB; + } else { + fprintf(stderr, "invalid argument to -C: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'D': + dumpzone++; + break; + + case 'M': + if (ARGCMP("fail")) { + zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; + zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; + } else if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_WARNMXCNAME; + zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; + } else if (ARGCMP("ignore")) { + zone_options |= DNS_ZONEOPT_WARNMXCNAME; + zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; + } else { + fprintf(stderr, "invalid argument to -M: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'S': + if (ARGCMP("fail")) { + zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; + zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; + } else if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_WARNSRVCNAME; + zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; + } else if (ARGCMP("ignore")) { + zone_options |= DNS_ZONEOPT_WARNSRVCNAME; + zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; + } else { + fprintf(stderr, "invalid argument to -S: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'T': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKSPF; + } else if (ARGCMP("ignore")) { + zone_options &= ~DNS_ZONEOPT_CHECKSPF; + } else { + fprintf(stderr, "invalid argument to -T: %s\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'W': + if (ARGCMP("warn")) { + zone_options |= DNS_ZONEOPT_CHECKWILDCARD; + } else if (ARGCMP("ignore")) { + zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD; + } + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + prog_name, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + usage(); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", prog_name, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + if (workdir != NULL) { + result = isc_dir_chdir(workdir); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "isc_dir_chdir: %s: %s\n", workdir, + isc_result_totext(result)); + exit(EXIT_FAILURE); + } + } + + if (inputformatstr != NULL) { + if (strcasecmp(inputformatstr, "text") == 0) { + inputformat = dns_masterformat_text; + } else if (strcasecmp(inputformatstr, "raw") == 0) { + inputformat = dns_masterformat_raw; + } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { + inputformat = dns_masterformat_raw; + fprintf(stderr, "WARNING: input format raw, version " + "ignored\n"); + } else { + fprintf(stderr, "unknown file format: %s\n", + inputformatstr); + exit(EXIT_FAILURE); + } + } + + if (outputformatstr != NULL) { + if (strcasecmp(outputformatstr, "text") == 0) { + outputformat = dns_masterformat_text; + } else if (strcasecmp(outputformatstr, "raw") == 0) { + outputformat = dns_masterformat_raw; + } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { + char *end; + + outputformat = dns_masterformat_raw; + rawversion = strtol(outputformatstr + 4, &end, 10); + if (end == outputformatstr + 4 || *end != '\0' || + rawversion > 1U) + { + fprintf(stderr, "unknown raw format version\n"); + exit(EXIT_FAILURE); + } + } else { + fprintf(stderr, "unknown file format: %s\n", + outputformatstr); + exit(EXIT_FAILURE); + } + } + + if (progmode == progmode_compile) { + dumpzone = 1; /* always dump */ + logdump = !quiet; + if (output_filename == NULL) { + fprintf(stderr, "output file required, but not " + "specified\n"); + usage(); + } + } + + if (output_filename != NULL) { + dumpzone = 1; + } + + /* + * If we are printing to stdout then send the informational + * output to stderr. + */ + if (dumpzone && + (output_filename == NULL || strcmp(output_filename, "-") == 0 || + strcmp(output_filename, "/dev/fd/1") == 0 || + strcmp(output_filename, "/dev/stdout") == 0)) + { + errout = stderr; + logdump = false; + } + + if (argc - isc_commandline_index < 1 || + argc - isc_commandline_index > 2) + { + usage(); + } + + isc_mem_create(&mctx); + if (!quiet) { + RUNTIME_CHECK(setup_logging(mctx, errout, &lctx) == + ISC_R_SUCCESS); + } + + origin = argv[isc_commandline_index++]; + + if (isc_commandline_index == argc) { + /* "-" will be interpreted as stdin */ + filename = "-"; + } else { + filename = argv[isc_commandline_index]; + } + + isc_commandline_index++; + + result = load_zone(mctx, origin, filename, inputformat, classname, + maxttl, &zone); + + if (snset) { + dns_master_initrawheader(&header); + header.flags = DNS_MASTERRAW_SOURCESERIALSET; + header.sourceserial = serialnum; + dns_zone_setrawdata(zone, &header); + } + + if (result == ISC_R_SUCCESS && dumpzone) { + if (logdump) { + fprintf(errout, "dump zone to %s...", output_filename); + fflush(errout); + } + result = dump_zone(origin, zone, output_filename, outputformat, + outputstyle, rawversion); + if (logdump) { + fprintf(errout, "done\n"); + } + } + + if (!quiet && result == ISC_R_SUCCESS) { + fprintf(errout, "OK\n"); + } + destroy(); + if (lctx != NULL) { + isc_log_destroy(&lctx); + } + isc_mem_destroy(&mctx); + + return (result == ISC_R_SUCCESS) ? 0 : 1; +} diff --git a/bin/check/named-checkzone.rst b/bin/check/named-checkzone.rst new file mode 100644 index 0000000..e6ad56f --- /dev/null +++ b/bin/check/named-checkzone.rst @@ -0,0 +1,231 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. BEWARE: Do not forget to edit also named-compilezone.rst! + +.. iscman:: named-checkzone +.. program:: named-checkzone +.. _man_named-checkzone: + +named-checkzone - zone file validation tool +------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`named-checkzone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-o** filename] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {zonename} {filename} + +Description +~~~~~~~~~~~ + +:program:`named-checkzone` checks the syntax and integrity of a zone file. It +performs the same checks as :iscman:`named` does when loading a zone. This +makes :program:`named-checkzone` useful for checking zone files before +configuring them into a name server. + +Options +~~~~~~~ + +.. option:: -d + + This option enables debugging. + +.. option:: -h + + This option prints the usage summary and exits. + +.. option:: -q + + This option sets quiet mode, which only sets an exit code to indicate + successful or failed completion. + +.. option:: -v + + This option prints the version of the :program:`named-checkzone` program and exits. + +.. option:: -j + + When loading a zone file, this option tells :iscman:`named` to read the journal if it exists. The journal + file name is assumed to be the zone file name with the + string ``.jnl`` appended. + +.. option:: -J filename + + When loading the zone file, this option tells :iscman:`named` to read the journal from the given file, if + it exists. This implies :option:`-j`. + +.. option:: -c class + + This option specifies the class of the zone. If not specified, ``IN`` is assumed. + +.. option:: -C mode + + This option controls check mode on zone files when loading. + Possible modes are ``check-svcb:fail`` and ``check-svcb:ignore``. + + ``check-svcb:fail`` turns on additional checks on ``_dns`` SVCB + records and ``check-svcb:ignore`` disables these checks. The + default is ``check-svcb:fail``. + +.. option:: -i mode + + This option performs post-load zone integrity checks. Possible modes are + ``full`` (the default), ``full-sibling``, ``local``, + ``local-sibling``, and ``none``. + + Mode ``full`` checks that MX records refer to A or AAAA records + (both in-zone and out-of-zone hostnames). Mode ``local`` only + checks MX records which refer to in-zone hostnames. + + Mode ``full`` checks that SRV records refer to A or AAAA records + (both in-zone and out-of-zone hostnames). Mode ``local`` only + checks SRV records which refer to in-zone hostnames. + + Mode ``full`` checks that delegation NS records refer to A or AAAA + records (both in-zone and out-of-zone hostnames). It also checks that + glue address records in the zone match those advertised by the child. + Mode ``local`` only checks NS records which refer to in-zone + hostnames or verifies that some required glue exists, i.e., when the + name server is in a child zone. + + Modes ``full-sibling`` and ``local-sibling`` disable sibling glue + checks, but are otherwise the same as ``full`` and ``local``, + respectively. + + Mode ``none`` disables the checks. + +.. option:: -f format + + This option specifies the format of the zone file. Possible formats are + ``text`` (the default), and ``raw``. + +.. option:: -F format + + This option specifies the format of the output file specified. For + :program:`named-checkzone`, this does not have any effect unless it dumps + the zone contents. + + Possible formats are ``text`` (the default), which is the standard + textual representation of the zone, and ``raw`` and ``raw=N``, which + store the zone in a binary format for rapid loading by :iscman:`named`. + ``raw=N`` specifies the format version of the raw zone file: if ``N`` is + 0, the raw file can be read by any version of :iscman:`named`; if N is 1, the + file can only be read by release 9.9.0 or higher. The default is 1. + +.. option:: -k mode + + This option performs ``check-names`` checks with the specified failure mode. + Possible modes are ``fail``, ``warn`` (the default), and ``ignore``. + +.. option:: -l ttl + + This option sets a maximum permissible TTL for the input file. Any record with a + TTL higher than this value causes the zone to be rejected. This + is similar to using the ``max-zone-ttl`` option in :iscman:`named.conf`. + +.. option:: -L serial + + When compiling a zone to ``raw`` format, this option sets the "source + serial" value in the header to the specified serial number. This is + expected to be used primarily for testing purposes. + +.. option:: -m mode + + This option specifies whether MX records should be checked to see if they are + addresses. Possible modes are ``fail``, ``warn`` (the default), and + ``ignore``. + +.. option:: -M mode + + This option checks whether a MX record refers to a CNAME. Possible modes are + ``fail``, ``warn`` (the default), and ``ignore``. + +.. option:: -n mode + + This option specifies whether NS records should be checked to see if they are + addresses. Possible modes are ``fail``, ``warn`` (the default), and ``ignore``. + +.. option:: -o filename + + This option writes the zone output to ``filename``. If ``filename`` is ``-``, then + the zone output is written to standard output. + +.. option:: -r mode + + This option checks for records that are treated as different by DNSSEC but are + semantically equal in plain DNS. Possible modes are ``fail``, + ``warn`` (the default), and ``ignore``. + +.. option:: -s style + + This option specifies the style of the dumped zone file. Possible styles are + ``full`` (the default) and ``relative``. The ``full`` format is most + suitable for processing automatically by a separate script. + The relative format is more human-readable and is thus + suitable for editing by hand. This does not have any effect unless it dumps + the zone contents. It also does not have any meaning if the output format + is not text. + +.. option:: -S mode + + This option checks whether an SRV record refers to a CNAME. Possible modes are + ``fail``, ``warn`` (the default), and ``ignore``. + +.. option:: -t directory + + This option tells :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the + configuration file are processed as if run by a similarly chrooted + :iscman:`named`. + +.. option:: -T mode + + This option checks whether Sender Policy Framework (SPF) records exist and issues a + warning if an SPF-formatted TXT record is not also present. Possible + modes are ``warn`` (the default) and ``ignore``. + +.. option:: -w directory + + This option instructs :iscman:`named` to chdir to ``directory``, so that relative filenames in master file + ``$INCLUDE`` directives work. This is similar to the directory clause in + :iscman:`named.conf`. + +.. option:: -D + + This option dumps the zone file in canonical format. + +.. option:: -W mode + + This option specifies whether to check for non-terminal wildcards. Non-terminal + wildcards are almost always the result of a failure to understand the + wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn`` + (the default) and ``ignore``. + +.. option:: zonename + + This indicates the domain name of the zone being checked. + +.. option:: filename + + This is the name of the zone file. + +Return Values +~~~~~~~~~~~~~ + +:program:`named-checkzone` returns an exit status of 1 if errors were detected +and 0 otherwise. + +See Also +~~~~~~~~ + +:iscman:`named(8) `, :iscman:`named-checkconf(8) `, :iscman:`named-compilezone(8) `, :rfc:`1035`, BIND 9 Administrator Reference +Manual. diff --git a/bin/check/named-compilezone.rst b/bin/check/named-compilezone.rst new file mode 100644 index 0000000..8c68d0d --- /dev/null +++ b/bin/check/named-compilezone.rst @@ -0,0 +1,239 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. BEWARE: Do not forget to edit also named-checkzone.rst! + +.. iscman:: named-compilezone +.. program:: named-compilezone +.. _man_named-compilezone: + +named-compilezone - zone file converting tool +--------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`named-compilezone` [**-d**] [**-h**] [**-j**] [**-q**] [**-v**] [**-c** class] [**-C** mode] [**-f** format] [**-F** format] [**-J** filename] [**-i** mode] [**-k** mode] [**-m** mode] [**-M** mode] [**-n** mode] [**-l** ttl] [**-L** serial] [**-r** mode] [**-s** style] [**-S** mode] [**-t** directory] [**-T** mode] [**-w** directory] [**-D**] [**-W** mode] {**-o** filename} {zonename} {filename} + +Description +~~~~~~~~~~~ + +:program:`named-compilezone` checks the syntax and integrity of a zone file, +and dumps the zone contents to a specified file in a specified format. + +Unlike :program:`named-checkzone`, zone contents are not strictly checked +by default. If the output is to be used as an actual zone file to be loaded +by :iscman:`named`, then the check levels should be manually configured to +be at least as strict as those specified in the :iscman:`named` configuration +file. + +Running :program:`named-checkzone` on the input prior to compiling will +ensure that the zone compiles with the default requirements of +:iscman:`named`. + +Options +~~~~~~~ + +.. option:: -d + + This option enables debugging. + +.. option:: -h + + This option prints the usage summary and exits. + +.. option:: -q + + This option sets quiet mode, which only sets an exit code to indicate + successful or failed completion. + +.. option:: -v + + This option prints the version of the :iscman:`named-checkzone` program and exits. + +.. option:: -j + + When loading a zone file, this option tells :iscman:`named` to read the journal if it exists. The journal + file name is assumed to be the zone file name with the + string ``.jnl`` appended. + +.. option:: -J filename + + When loading the zone file, this option tells :iscman:`named` to read the journal from the given file, if + it exists. This implies :option:`-j`. + +.. option:: -c class + + This option specifies the class of the zone. If not specified, ``IN`` is assumed. + +.. option:: -C mode + + This option controls check mode on zone files when loading. + Possible modes are ``check-svcb:fail`` and ``check-svcb:ignore``. + + ``check-svcb:fail`` turns on additional checks on ``_dns`` SVCB + records and ``check-svcb:ignore`` disables these checks. The + default is ``check-svcb:ignore``. + +.. option:: -i mode + + This option performs post-load zone integrity checks. Possible modes are + ``full``, ``full-sibling``, ``local``, + ``local-sibling``, and ``none`` (the default). + + Mode ``full`` checks that MX records refer to A or AAAA records + (both in-zone and out-of-zone hostnames). Mode ``local`` only + checks MX records which refer to in-zone hostnames. + + Mode ``full`` checks that SRV records refer to A or AAAA records + (both in-zone and out-of-zone hostnames). Mode ``local`` only + checks SRV records which refer to in-zone hostnames. + + Mode ``full`` checks that delegation NS records refer to A or AAAA + records (both in-zone and out-of-zone hostnames). It also checks that + glue address records in the zone match those advertised by the child. + Mode ``local`` only checks NS records which refer to in-zone + hostnames or verifies that some required glue exists, i.e., when the + name server is in a child zone. + + Modes ``full-sibling`` and ``local-sibling`` disable sibling glue + checks, but are otherwise the same as ``full`` and ``local``, + respectively. + + Mode ``none`` disables the checks. + +.. option:: -f format + + This option specifies the format of the zone file. Possible formats are + ``text`` (the default), and ``raw``. + +.. option:: -F format + + This option specifies the format of the output file specified. For + :iscman:`named-checkzone`, this does not have any effect unless it dumps + the zone contents. + + Possible formats are ``text`` (the default), which is the standard + textual representation of the zone, and ``raw`` and ``raw=N``, which + store the zone in a binary format for rapid loading by :iscman:`named`. + ``raw=N`` specifies the format version of the raw zone file: if ``N`` is + 0, the raw file can be read by any version of :iscman:`named`; if N is 1, the + file can only be read by release 9.9.0 or higher. The default is 1. + +.. option:: -k mode + + This option performs ``check-names`` checks with the specified failure mode. + Possible modes are ``fail``, ``warn``, and ``ignore`` (the default). + +.. option:: -l ttl + + This option sets a maximum permissible TTL for the input file. Any record with a + TTL higher than this value causes the zone to be rejected. This + is similar to using the ``max-zone-ttl`` option in :iscman:`named.conf`. + +.. option:: -L serial + + When compiling a zone to ``raw`` format, this option sets the "source + serial" value in the header to the specified serial number. This is + expected to be used primarily for testing purposes. + +.. option:: -m mode + + This option specifies whether MX records should be checked to see if they are + addresses. Possible modes are ``fail``, ``warn``, and + ``ignore`` (the default). + +.. option:: -M mode + + This option checks whether a MX record refers to a CNAME. Possible modes are + ``fail``, ``warn``, and ``ignore`` (the default). + +.. option:: -n mode + + This option specifies whether NS records should be checked to see if they are + addresses. Possible modes are ``fail``, ``warn``, and + ``ignore`` (the default). + +.. option:: -o filename + + This option writes the zone output to ``filename``. If ``filename`` is ``-``, then + the zone output is written to standard output. This is mandatory for :program:`named-compilezone`. + +.. option:: -r mode + + This option checks for records that are treated as different by DNSSEC but are + semantically equal in plain DNS. Possible modes are ``fail``, + ``warn``, and ``ignore`` (the default). + +.. option:: -s style + + This option specifies the style of the dumped zone file. Possible styles are + ``full`` (the default) and ``relative``. The ``full`` format is most + suitable for processing automatically by a separate script. + The relative format is more human-readable and is thus + suitable for editing by hand. + +.. option:: -S mode + + This option checks whether an SRV record refers to a CNAME. Possible modes are + ``fail``, ``warn``, and ``ignore`` (the default). + +.. option:: -t directory + + This option tells :iscman:`named` to chroot to ``directory``, so that ``include`` directives in the + configuration file are processed as if run by a similarly chrooted + :iscman:`named`. + +.. option:: -T mode + + This option checks whether Sender Policy Framework (SPF) records exist and issues a + warning if an SPF-formatted TXT record is not also present. Possible + modes are ``warn`` and ``ignore`` (the default). + +.. option:: -w directory + + This option instructs :iscman:`named` to chdir to ``directory``, so that relative filenames in master file + ``$INCLUDE`` directives work. This is similar to the directory clause in + :iscman:`named.conf`. + +.. option:: -D + + This option dumps the zone file in canonical format. This is always enabled for + :program:`named-compilezone`. + +.. option:: -W mode + + This option specifies whether to check for non-terminal wildcards. Non-terminal + wildcards are almost always the result of a failure to understand the + wildcard matching algorithm (:rfc:`4592`). Possible modes are ``warn`` + and ``ignore`` (the default). + +.. option:: zonename + + This indicates the domain name of the zone being checked. + +.. option:: filename + + This is the name of the zone file. + +Return Values +~~~~~~~~~~~~~ + +:program:`named-compilezone` returns an exit status of 1 if errors were detected +and 0 otherwise. + +See Also +~~~~~~~~ + +:iscman:`named(8) `, :iscman:`named-checkconf(8) `, :iscman:`named-checkzone(8) `, :rfc:`1035`, +BIND 9 Administrator Reference Manual. diff --git a/bin/confgen/Makefile.am b/bin/confgen/Makefile.am new file mode 100644 index 0000000..c1dca43 --- /dev/null +++ b/bin/confgen/Makefile.am @@ -0,0 +1,30 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" + +LDADD += \ + libconfgen.la \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +noinst_LTLIBRARIES = libconfgen.la + +libconfgen_la_SOURCES = \ + include/confgen/os.h \ + keygen.c \ + keygen.h \ + os.c \ + util.c \ + util.h + +sbin_PROGRAMS = tsig-keygen rndc-confgen + +install-exec-hook: + ln -f $(DESTDIR)$(sbindir)/tsig-keygen \ + $(DESTDIR)$(sbindir)/ddns-confgen + +uninstall-hook: + -rm -f $(DESTDIR)$(sbindir)/ddns-confgen diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in new file mode 100644 index 0000000..ae2444b --- /dev/null +++ b/bin/confgen/Makefile.in @@ -0,0 +1,893 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +sbin_PROGRAMS = tsig-keygen$(EXEEXT) rndc-confgen$(EXEEXT) +subdir = bin/confgen +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libconfgen_la_LIBADD = +am_libconfgen_la_OBJECTS = keygen.lo os.lo util.lo +libconfgen_la_OBJECTS = $(am_libconfgen_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +rndc_confgen_SOURCES = rndc-confgen.c +rndc_confgen_OBJECTS = rndc-confgen.$(OBJEXT) +rndc_confgen_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +rndc_confgen_DEPENDENCIES = libconfgen.la $(am__DEPENDENCIES_2) \ + $(LIBDNS_LIBS) +tsig_keygen_SOURCES = tsig-keygen.c +tsig_keygen_OBJECTS = tsig-keygen.$(OBJEXT) +tsig_keygen_LDADD = $(LDADD) +tsig_keygen_DEPENDENCIES = libconfgen.la $(am__DEPENDENCIES_2) \ + $(LIBDNS_LIBS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/keygen.Plo ./$(DEPDIR)/os.Plo \ + ./$(DEPDIR)/rndc-confgen.Po ./$(DEPDIR)/tsig-keygen.Po \ + ./$(DEPDIR)/util.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libconfgen_la_SOURCES) rndc-confgen.c tsig-keygen.c +DIST_SOURCES = $(libconfgen_la_SOURCES) rndc-confgen.c tsig-keygen.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = libconfgen.la $(LIBISC_LIBS) $(LIBDNS_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = libconfgen.la +libconfgen_la_SOURCES = \ + include/confgen/os.h \ + keygen.c \ + keygen.h \ + os.c \ + util.c \ + util.h + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/confgen/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/confgen/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libconfgen.la: $(libconfgen_la_OBJECTS) $(libconfgen_la_DEPENDENCIES) $(EXTRA_libconfgen_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libconfgen_la_OBJECTS) $(libconfgen_la_LIBADD) $(LIBS) + +rndc-confgen$(EXEEXT): $(rndc_confgen_OBJECTS) $(rndc_confgen_DEPENDENCIES) $(EXTRA_rndc_confgen_DEPENDENCIES) + @rm -f rndc-confgen$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rndc_confgen_OBJECTS) $(rndc_confgen_LDADD) $(LIBS) + +tsig-keygen$(EXEEXT): $(tsig_keygen_OBJECTS) $(tsig_keygen_DEPENDENCIES) $(EXTRA_tsig_keygen_DEPENDENCIES) + @rm -f tsig-keygen$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(tsig_keygen_OBJECTS) $(tsig_keygen_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygen.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndc-confgen.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig-keygen.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/keygen.Plo + -rm -f ./$(DEPDIR)/os.Plo + -rm -f ./$(DEPDIR)/rndc-confgen.Po + -rm -f ./$(DEPDIR)/tsig-keygen.Po + -rm -f ./$(DEPDIR)/util.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/keygen.Plo + -rm -f ./$(DEPDIR)/os.Plo + -rm -f ./$(DEPDIR)/rndc-confgen.Po + -rm -f ./$(DEPDIR)/tsig-keygen.Po + -rm -f ./$(DEPDIR)/util.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-sbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-exec-am \ + install-strip uninstall-am + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-hook uninstall-sbinPROGRAMS unit-am \ + unit-local + +.PRECIOUS: Makefile + + +install-exec-hook: + ln -f $(DESTDIR)$(sbindir)/tsig-keygen \ + $(DESTDIR)$(sbindir)/ddns-confgen + +uninstall-hook: + -rm -f $(DESTDIR)$(sbindir)/ddns-confgen + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/confgen/ddns-confgen.rst b/bin/confgen/ddns-confgen.rst new file mode 100644 index 0000000..9dd9d5e --- /dev/null +++ b/bin/confgen/ddns-confgen.rst @@ -0,0 +1,96 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. BEWARE: Do not forget to edit also tsig-keygen.rst! + +.. iscman:: ddns-confgen +.. program:: ddns-confgen +.. _man_ddns-confgen: + +ddns-confgen - TSIG key generation tool +--------------------------------------- + +Synopsis +~~~~~~~~ +:program:`ddns-confgen` [**-a** algorithm] [**-h**] [**-k** keyname] [**-q**] [**-s** name] [**-z** zone] + +Description +~~~~~~~~~~~ + +:program:`ddns-confgen` is an utility that generates keys for use in TSIG signing. +The resulting keys can be used, for example, to secure dynamic DNS updates +to a zone, or for the :iscman:`rndc` command channel. + +The key name can specified using :option:`-k` parameter and defaults to ``ddns-key``. +The generated key is accompanied by configuration text and instructions that +can be used with :iscman:`nsupdate` and :iscman:`named` when setting up dynamic DNS, +including an example ``update-policy`` statement. +(This usage is similar to the :iscman:`rndc-confgen` command for setting up +command-channel security.) + +Note that :iscman:`named` itself can configure a local DDNS key for use with +:option:`nsupdate -l`; it does this when a zone is configured with +``update-policy local;``. :program:`ddns-confgen` is only needed when a more +elaborate configuration is required: for instance, if :iscman:`nsupdate` is to +be used from a remote system. + +Options +~~~~~~~ + +.. option:: -a algorithm + + This option specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, + and hmac-sha512. The default is hmac-sha256. Options are + case-insensitive, and the "hmac-" prefix may be omitted. + +.. option:: -h + + This option prints a short summary of options and arguments. + +.. option:: -k keyname + + This option specifies the key name of the DDNS authentication key. The + default is ``ddns-key`` when neither the :option:`-s` nor :option:`-z` option is + specified; otherwise, the default is ``ddns-key`` as a separate label + followed by the argument of the option, e.g., ``ddns-key.example.com.`` + The key name must have the format of a valid domain name, consisting of + letters, digits, hyphens, and periods. + +.. option:: -q + + This option enables quiet mode, which prints only the key, with no + explanatory text or usage examples. This is essentially identical to + :iscman:`tsig-keygen`. + +.. option:: -s name + + This option generates a configuration example to allow dynamic updates + of a single hostname. The example :iscman:`named.conf` text shows how to set + an update policy for the specified name using the "name" nametype. The + default key name is ``ddns-key.name``. Note that the "self" nametype + cannot be used, since the name to be updated may differ from the key + name. This option cannot be used with the :option:`-z` option. + +.. option:: -z zone + + This option generates a configuration example to allow + dynamic updates of a zone. The example :iscman:`named.conf` text shows how + to set an update policy for the specified zone using the "zonesub" + nametype, allowing updates to all subdomain names within that zone. + This option cannot be used with the :option:`-s` option. + +See Also +~~~~~~~~ + +:iscman:`nsupdate(1) `, :iscman:`named.conf(5) `, :iscman:`named(8) `, BIND 9 Administrator Reference Manual. diff --git a/bin/confgen/include/confgen/os.h b/bin/confgen/include/confgen/os.h new file mode 100644 index 0000000..2a924a3 --- /dev/null +++ b/bin/confgen/include/confgen/os.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#pragma once + +#include + +#include + +ISC_LANG_BEGINDECLS + +int +set_user(FILE *fd, const char *user); +/*%< + * Set the owner of the file referenced by 'fd' to 'user'. + * Returns: + * 0 success + * -1 insufficient permissions, or 'user' does not exist. + */ + +ISC_LANG_ENDDECLS diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c new file mode 100644 index 0000000..cb370fe --- /dev/null +++ b/bin/confgen/keygen.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include "keygen.h" +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "util.h" + +/*% + * Convert string to algorithm type. + */ +dns_secalg_t +alg_fromtext(const char *name) { + const char *p = name; + if (strncasecmp(p, "hmac-", 5) == 0) { + p = &name[5]; + } + + if (strcasecmp(p, "md5") == 0) { + return DST_ALG_HMACMD5; + } + if (strcasecmp(p, "sha1") == 0) { + return DST_ALG_HMACSHA1; + } + if (strcasecmp(p, "sha224") == 0) { + return DST_ALG_HMACSHA224; + } + if (strcasecmp(p, "sha256") == 0) { + return DST_ALG_HMACSHA256; + } + if (strcasecmp(p, "sha384") == 0) { + return DST_ALG_HMACSHA384; + } + if (strcasecmp(p, "sha512") == 0) { + return DST_ALG_HMACSHA512; + } + return DST_ALG_UNKNOWN; +} + +/*% + * Return default keysize for a given algorithm type. + */ +int +alg_bits(dns_secalg_t alg) { + switch (alg) { + case DST_ALG_HMACMD5: + return 128; + case DST_ALG_HMACSHA1: + return 160; + case DST_ALG_HMACSHA224: + return 224; + case DST_ALG_HMACSHA256: + return 256; + case DST_ALG_HMACSHA384: + return 384; + case DST_ALG_HMACSHA512: + return 512; + default: + return 0; + } +} + +/*% + * Generate a key of size 'keysize' and place it in 'key_txtbuffer' + */ +void +generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize, + isc_buffer_t *key_txtbuffer) { + isc_result_t result = ISC_R_SUCCESS; + isc_buffer_t key_rawbuffer; + isc_region_t key_rawregion; + char key_rawsecret[64]; + dst_key_t *key = NULL; + + switch (alg) { + case DST_ALG_HMACMD5: + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: + case DST_ALG_HMACSHA256: + if (keysize < 1 || keysize > 512) { + fatal("keysize %d out of range (must be 1-512)\n", + keysize); + } + break; + case DST_ALG_HMACSHA384: + case DST_ALG_HMACSHA512: + if (keysize < 1 || keysize > 1024) { + fatal("keysize %d out of range (must be 1-1024)\n", + keysize); + } + break; + default: + fatal("unsupported algorithm %d\n", alg); + } + + DO("initialize dst library", dst_lib_init(mctx, NULL)); + + DO("generate key", + dst_key_generate(dns_rootname, alg, keysize, 0, 0, DNS_KEYPROTO_ANY, + dns_rdataclass_in, NULL, mctx, &key, NULL)); + + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + + DO("dump key to buffer", dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + + DO("bsse64 encode secret", + isc_base64_totext(&key_rawregion, -1, "", key_txtbuffer)); + + if (key != NULL) { + dst_key_free(&key); + } + + dst_lib_destroy(); +} + +/*% + * Write a key file to 'keyfile'. If 'user' is non-NULL, + * make that user the owner of the file. The key will have + * the name 'keyname' and the secret in the buffer 'secret'. + */ +void +write_key_file(const char *keyfile, const char *user, const char *keyname, + isc_buffer_t *secret, dns_secalg_t alg) { + isc_result_t result; + const char *algname = dst_hmac_algorithm_totext(alg); + FILE *fd = NULL; + + DO("create keyfile", isc_file_safecreate(keyfile, &fd)); + + if (user != NULL) { + if (set_user(fd, user) == -1) { + fatal("unable to set file owner\n"); + } + } + + fprintf(fd, + "key \"%s\" {\n\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", + keyname, algname, (int)isc_buffer_usedlength(secret), + (char *)isc_buffer_base(secret)); + fflush(fd); + if (ferror(fd)) { + fatal("write to %s failed\n", keyfile); + } + if (fclose(fd)) { + fatal("fclose(%s) failed\n", keyfile); + } +} diff --git a/bin/confgen/keygen.h b/bin/confgen/keygen.h new file mode 100644 index 0000000..f5b7a55 --- /dev/null +++ b/bin/confgen/keygen.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include +#include + +#include + +ISC_LANG_BEGINDECLS + +void +generate_key(isc_mem_t *mctx, dns_secalg_t alg, int keysize, + isc_buffer_t *key_txtbuffer); + +void +write_key_file(const char *keyfile, const char *user, const char *keyname, + isc_buffer_t *secret, dns_secalg_t alg); + +const char * +alg_totext(dns_secalg_t alg); +dns_secalg_t +alg_fromtext(const char *name); +int +alg_bits(dns_secalg_t alg); + +ISC_LANG_ENDDECLS diff --git a/bin/confgen/os.c b/bin/confgen/os.c new file mode 100644 index 0000000..3c3ccbc --- /dev/null +++ b/bin/confgen/os.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +int +set_user(FILE *fd, const char *user) { + struct passwd *pw; + + pw = getpwnam(user); + if (pw == NULL) { + errno = EINVAL; + return -1; + } + return fchown(fileno(fd), pw->pw_uid, -1); +} diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c new file mode 100644 index 0000000..01b30c4 --- /dev/null +++ b/bin/confgen/rndc-confgen.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/** + * rndc-confgen generates configuration files for rndc. It can be used + * as a convenient alternative to writing the rndc.conf file and the + * corresponding controls and key statements in named.conf by hand. + * Alternatively, it can be run with the -a option to set up a + * rndc.key file and avoid the need for a rndc.conf file and a + * controls statement altogether. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "keygen.h" +#include "util.h" + +#define DEFAULT_KEYNAME "rndc-key" +#define DEFAULT_SERVER "127.0.0.1" +#define DEFAULT_PORT 953 + +static char program[256]; +const char *progname; + +bool verbose = false; + +const char *keyfile, *keydef; + +noreturn static void +usage(int status); + +static void +usage(int status) { + fprintf(stderr, "\ +Usage:\n\ + %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] \ +[-s addr] [-t chrootdir] [-u user]\n\ + -a: generate just the key clause and write it to keyfile (%s)\n\ + -A alg: algorithm (default hmac-sha256)\n\ + -b bits: from 1 through 512, default 256; total length of the secret\n\ + -c keyfile: specify an alternate key file (requires -a)\n\ + -k keyname: the name as it will be used in named.conf and rndc.conf\n\ + -p port: the port named will listen on and rndc will connect to\n\ + -q: suppress printing written key path\n\ + -s addr: the address to which rndc should connect\n\ + -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ + -u user: set the keyfile owner to \"user\" (requires -a)\n", + progname, keydef); + + exit(status); +} + +int +main(int argc, char **argv) { + bool show_final_mem = false; + isc_buffer_t key_txtbuffer; + char key_txtsecret[256]; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_SUCCESS; + const char *keyname = NULL; + const char *serveraddr = NULL; + dns_secalg_t alg; + const char *algname; + char *p; + int ch; + int port; + int keysize = -1; + struct in_addr addr4_dummy; + struct in6_addr addr6_dummy; + char *chrootdir = NULL; + char *user = NULL; + bool keyonly = false; + bool quiet = false; + int len; + + keydef = keyfile = RNDC_KEYFILE; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) { + memmove(program, "rndc-confgen", 13); + } + progname = program; + + keyname = DEFAULT_KEYNAME; + alg = DST_ALG_HMACSHA256; + serveraddr = DEFAULT_SERVER; + port = DEFAULT_PORT; + + isc_commandline_errprint = false; + + while ((ch = isc_commandline_parse(argc, argv, + "aA:b:c:hk:Mmp:r:s:t:u:Vy")) != -1) + { + switch (ch) { + case 'a': + keyonly = true; + break; + case 'A': + algname = isc_commandline_argument; + alg = alg_fromtext(algname); + if (alg == DST_ALG_UNKNOWN) { + fatal("Unsupported algorithm '%s'", algname); + } + break; + case 'b': + keysize = strtol(isc_commandline_argument, &p, 10); + if (*p != '\0' || keysize < 0) { + fatal("-b requires a non-negative number"); + } + break; + case 'c': + keyfile = isc_commandline_argument; + break; + case 'h': + usage(EXIT_SUCCESS); + break; + case 'k': + case 'y': /* Compatible with rndc -y. */ + keyname = isc_commandline_argument; + break; + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + + case 'm': + show_final_mem = true; + break; + case 'p': + port = strtol(isc_commandline_argument, &p, 10); + if (*p != '\0' || port < 0 || port > 65535) { + fatal("port '%s' out of range", + isc_commandline_argument); + } + break; + case 'q': + quiet = true; + break; + case 'r': + fatal("The -r option has been deprecated."); + break; + case 's': + serveraddr = isc_commandline_argument; + if (inet_pton(AF_INET, serveraddr, &addr4_dummy) != 1 && + inet_pton(AF_INET6, serveraddr, &addr6_dummy) != 1) + { + fatal("-s should be an IPv4 or IPv6 address"); + } + break; + case 't': + chrootdir = isc_commandline_argument; + break; + case 'u': + user = isc_commandline_argument; + break; + case 'V': + verbose = true; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(EXIT_FAILURE); + } else { + usage(EXIT_SUCCESS); + } + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + POST(argv); + + if (argc > 0) { + usage(EXIT_FAILURE); + } + + if (alg == DST_ALG_HMACMD5) { + fprintf(stderr, "warning: use of hmac-md5 for RNDC keys " + "is deprecated; hmac-sha256 is now " + "recommended.\n"); + } + + if (keysize < 0) { + keysize = alg_bits(alg); + } + algname = dst_hmac_algorithm_totext(alg); + + isc_mem_create(&mctx); + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + + generate_key(mctx, alg, keysize, &key_txtbuffer); + + if (keyonly) { + write_key_file(keyfile, chrootdir == NULL ? user : NULL, + keyname, &key_txtbuffer, alg); + if (!quiet) { + printf("wrote key file \"%s\"\n", keyfile); + } + + if (chrootdir != NULL) { + char *buf; + len = strlen(chrootdir) + strlen(keyfile) + 2; + buf = isc_mem_get(mctx, len); + snprintf(buf, len, "%s%s%s", chrootdir, + (*keyfile != '/') ? "/" : "", keyfile); + + write_key_file(buf, user, keyname, &key_txtbuffer, alg); + if (!quiet) { + printf("wrote key file \"%s\"\n", buf); + } + isc_mem_put(mctx, buf, len); + } + } else { + printf("\ +# Start of rndc.conf\n\ +key \"%s\" {\n\ + algorithm %s;\n\ + secret \"%.*s\";\n\ +};\n\ +\n\ +options {\n\ + default-key \"%s\";\n\ + default-server %s;\n\ + default-port %d;\n\ +};\n\ +# End of rndc.conf\n\ +\n\ +# Use with the following in named.conf, adjusting the allow list as needed:\n\ +# key \"%s\" {\n\ +# algorithm %s;\n\ +# secret \"%.*s\";\n\ +# };\n\ +# \n\ +# controls {\n\ +# inet %s port %d\n\ +# allow { %s; } keys { \"%s\"; };\n\ +# };\n\ +# End of named.conf\n", + keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), keyname, + serveraddr, port, keyname, algname, + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer), serveraddr, + port, serveraddr, keyname); + } + + if (show_final_mem) { + isc_mem_stats(mctx, stderr); + } + + isc_mem_destroy(&mctx); + + return 0; +} diff --git a/bin/confgen/rndc-confgen.rst b/bin/confgen/rndc-confgen.rst new file mode 100644 index 0000000..0a91489 --- /dev/null +++ b/bin/confgen/rndc-confgen.rst @@ -0,0 +1,121 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: rndc-confgen +.. program:: rndc-confgen +.. _man_rndc-confgen: + +rndc-confgen - rndc key generation tool +--------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`rndc-confgen` [**-a**] [**-A** algorithm] [**-b** keysize] [**-c** keyfile] [**-h**] [**-k** keyname] [**-p** port] [**-s** address] [**-t** chrootdir] [**-u** user] + +Description +~~~~~~~~~~~ + +:program:`rndc-confgen` generates configuration files for :iscman:`rndc`. It can be +used as a convenient alternative to writing the :iscman:`rndc.conf` file and +the corresponding ``controls`` and ``key`` statements in :iscman:`named.conf` +by hand. Alternatively, it can be run with the :option:`-a` option to set up a +``rndc.key`` file and avoid the need for a :iscman:`rndc.conf` file and a +``controls`` statement altogether. + +Options +~~~~~~~ + +.. option:: -a + + This option sets automatic :iscman:`rndc` configuration, which creates a file + |rndc_key| that is read by both :iscman:`rndc` and :iscman:`named` on startup. + The ``rndc.key`` file defines a default command channel and + authentication key allowing :iscman:`rndc` to communicate with :iscman:`named` on + the local host with no further configuration. + + If a more elaborate configuration than that generated by + :option:`rndc-confgen -a` is required, for example if rndc is to be used + remotely, run :program:`rndc-confgen` without the :option:`-a` option + and set up :iscman:`rndc.conf` and :iscman:`named.conf` as directed. + +.. option:: -A algorithm + + This option specifies the algorithm to use for the TSIG key. Available choices + are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, and + hmac-sha512. The default is hmac-sha256. + +.. option:: -b keysize + + This option specifies the size of the authentication key in bits. The size must be between + 1 and 512 bits; the default is the hash size. + +.. option:: -c keyfile + + This option is used with the :option:`-a` option to specify an alternate location for + ``rndc.key``. + +.. option:: -h + + This option prints a short summary of the options and arguments to + :program:`rndc-confgen`. + +.. option:: -k keyname + + This option specifies the key name of the :iscman:`rndc` authentication key. This must be a + valid domain name. The default is ``rndc-key``. + +.. option:: -p port + + This option specifies the command channel port where :iscman:`named` listens for + connections from :iscman:`rndc`. The default is 953. + +.. option:: -q + + This option prevets printing the written path in automatic configuration mode. + +.. option:: -s address + + This option specifies the IP address where :iscman:`named` listens for command-channel + connections from :iscman:`rndc`. The default is the loopback address + 127.0.0.1. + +.. option:: -t chrootdir + + This option is used with the :option:`-a` option to specify a directory where :iscman:`named` + runs chrooted. An additional copy of the ``rndc.key`` is + written relative to this directory, so that it is found by the + chrooted :iscman:`named`. + +.. option:: -u user + + This option is used with the :option:`-a` option to set the owner of the generated ``rndc.key`` file. + If :option:`-t` is also specified, only the file in the chroot + area has its owner changed. + +Examples +~~~~~~~~ + +To allow :iscman:`rndc` to be used with no manual configuration, run: + +``rndc-confgen -a`` + +To print a sample :iscman:`rndc.conf` file and the corresponding ``controls`` and +``key`` statements to be manually inserted into :iscman:`named.conf`, run: + +:program:`rndc-confgen` + +See Also +~~~~~~~~ + +:iscman:`rndc(8) `, :iscman:`rndc.conf(5) `, :iscman:`named(8) `, BIND 9 Administrator Reference Manual. diff --git a/bin/confgen/tsig-keygen.c b/bin/confgen/tsig-keygen.c new file mode 100644 index 0000000..7299b12 --- /dev/null +++ b/bin/confgen/tsig-keygen.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/** + * tsig-keygen generates TSIG keys that can be used in named configuration + * files for dynamic DNS. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "keygen.h" +#include "util.h" + +#define KEYGEN_DEFAULT "tsig-key" +#define CONFGEN_DEFAULT "ddns-key" + +static char program[256]; +const char *progname; +static enum { progmode_keygen, progmode_confgen } progmode; +bool verbose = false; /* needed by util.c but not used here */ + +noreturn static void +usage(int status); + +static void +usage(int status) { + if (progmode == progmode_confgen) { + fprintf(stderr, "\ +Usage:\n\ + %s [-a alg] [-k keyname] [-q] [-s name | -z zone]\n\ + -a alg: algorithm (default hmac-sha256)\n\ + -k keyname: name of the key as it will be used in named.conf\n\ + -s name: domain name to be updated using the created key\n\ + -z zone: name of the zone as it will be used in named.conf\n\ + -q: quiet mode: print the key, with no explanatory text\n", + progname); + } else { + fprintf(stderr, "\ +Usage:\n\ + %s [-a alg] [keyname]\n\ + -a alg: algorithm (default hmac-sha256)\n\n", + progname); + } + + exit(status); +} + +int +main(int argc, char **argv) { + isc_result_t result = ISC_R_SUCCESS; + bool show_final_mem = false; + bool quiet = false; + isc_buffer_t key_txtbuffer; + char key_txtsecret[256]; + isc_mem_t *mctx = NULL; + const char *keyname = NULL; + const char *zone = NULL; + const char *self_domain = NULL; + char *keybuf = NULL; + dns_secalg_t alg = DST_ALG_HMACSHA256; + const char *algname; + int keysize = 256; + int len = 0; + int ch; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) { + memmove(program, "tsig-keygen", 11); + } + progname = program; + + /* + * Libtool doesn't preserve the program name prior to final + * installation. Remove the libtool prefix ("lt-"). + */ + if (strncmp(progname, "lt-", 3) == 0) { + progname += 3; + } + +#define PROGCMP(X) \ + (strcasecmp(progname, X) == 0 || strcasecmp(progname, X ".exe") == 0) + + if (PROGCMP("tsig-keygen")) { + progmode = progmode_keygen; + quiet = true; + } else if (PROGCMP("ddns-confgen")) { + progmode = progmode_confgen; + } else { + UNREACHABLE(); + } + + isc_commandline_errprint = false; + + while ((ch = isc_commandline_parse(argc, argv, "a:hk:Mmr:qs:y:z:")) != + -1) + { + switch (ch) { + case 'a': + algname = isc_commandline_argument; + alg = alg_fromtext(algname); + if (alg == DST_ALG_UNKNOWN) { + fatal("Unsupported algorithm '%s'", algname); + } + keysize = alg_bits(alg); + break; + case 'h': + usage(EXIT_SUCCESS); + case 'k': + case 'y': + if (progmode == progmode_confgen) { + keyname = isc_commandline_argument; + } else { + usage(EXIT_FAILURE); + } + break; + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + case 'm': + show_final_mem = true; + break; + case 'q': + if (progmode == progmode_confgen) { + quiet = true; + } else { + usage(EXIT_FAILURE); + } + break; + case 'r': + fatal("The -r option has been deprecated."); + break; + case 's': + if (progmode == progmode_confgen) { + self_domain = isc_commandline_argument; + } else { + usage(EXIT_FAILURE); + } + break; + case 'z': + if (progmode == progmode_confgen) { + zone = isc_commandline_argument; + } else { + usage(EXIT_FAILURE); + } + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(EXIT_FAILURE); + } else { + usage(EXIT_SUCCESS); + } + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + if (progmode == progmode_keygen) { + keyname = argv[isc_commandline_index++]; + } + + POST(argv); + + if (self_domain != NULL && zone != NULL) { + usage(EXIT_FAILURE); /* -s and -z cannot coexist */ + } + + if (argc > isc_commandline_index) { + usage(EXIT_FAILURE); + } + + /* Use canonical algorithm name */ + algname = dst_hmac_algorithm_totext(alg); + + isc_mem_create(&mctx); + + if (keyname == NULL) { + const char *suffix = NULL; + + keyname = ((progmode == progmode_keygen) ? KEYGEN_DEFAULT + : CONFGEN_DEFAULT); + if (self_domain != NULL) { + suffix = self_domain; + } else if (zone != NULL) { + suffix = zone; + } + if (suffix != NULL) { + len = strlen(keyname) + strlen(suffix) + 2; + keybuf = isc_mem_get(mctx, len); + snprintf(keybuf, len, "%s.%s", keyname, suffix); + keyname = (const char *)keybuf; + } + } + + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + + generate_key(mctx, alg, keysize, &key_txtbuffer); + + if (!quiet) { + printf("\ +# To activate this key, place the following in named.conf, and\n\ +# in a separate keyfile on the system or systems from which nsupdate\n\ +# will be run:\n"); + } + + printf("\ +key \"%s\" {\n\ + algorithm %s;\n\ + secret \"%.*s\";\n\ +};\n", + keyname, algname, (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + + if (!quiet) { + if (self_domain != NULL) { + printf("\n\ +# Then, in the \"zone\" statement for the zone containing the\n\ +# name \"%s\", place an \"update-policy\" statement\n\ +# like this one, adjusted as needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s name %s ANY;\n\ +};\n", + self_domain, keyname, self_domain); + } else if (zone != NULL) { + printf("\n\ +# Then, in the \"zone\" definition statement for \"%s\",\n\ +# place an \"update-policy\" statement like this one, adjusted as \n\ +# needed for your preferred permissions:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + zone, keyname); + } else { + printf("\n\ +# Then, in the \"zone\" statement for each zone you wish to dynamically\n\ +# update, place an \"update-policy\" statement granting update permission\n\ +# to this key. For example, the following statement grants this key\n\ +# permission to update any name within the zone:\n\ +update-policy {\n\ + grant %s zonesub ANY;\n\ +};\n", + keyname); + } + + printf("\n\ +# After the keyfile has been placed, the following command will\n\ +# execute nsupdate using this key:\n\ +nsupdate -k \n"); + } + + if (keybuf != NULL) { + isc_mem_put(mctx, keybuf, len); + } + + if (show_final_mem) { + isc_mem_stats(mctx, stderr); + } + + isc_mem_destroy(&mctx); + + return 0; +} diff --git a/bin/confgen/tsig-keygen.rst b/bin/confgen/tsig-keygen.rst new file mode 100644 index 0000000..5ecce5d --- /dev/null +++ b/bin/confgen/tsig-keygen.rst @@ -0,0 +1,55 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. BEWARE: Do not forget to edit also ddns-confgen.rst! + +.. iscman:: tsig-keygen +.. program:: tsig-keygen +.. _man_tsig-keygen: + +tsig-keygen - TSIG key generation tool +-------------------------------------- + +Synopsis +~~~~~~~~ +:program:`tsig-keygen` [**-a** algorithm] [**-h**] [name] + +Description +~~~~~~~~~~~ + +:program:`tsig-keygen` is an utility that generates keys for use with TSIG +(Transaction Signatures) as defined in :rfc:`2845`. The resulting keys can be used, +for example, to secure dynamic DNS updates to a zone, or for the :iscman:`rndc` +command channel. + +A domain name can be specified on the command line to be used as the name +of the generated key. If no name is specified, the default is ``tsig-key``. + +Options +~~~~~~~ + +.. option:: -a algorithm + + This option specifies the algorithm to use for the TSIG key. Available + choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, + and hmac-sha512. The default is hmac-sha256. Options are + case-insensitive, and the "hmac-" prefix may be omitted. + +.. option:: -h + + This option prints a short summary of options and arguments. + +See Also +~~~~~~~~ + +:iscman:`nsupdate(1) `, :iscman:`named.conf(5) `, :iscman:`named(8) `, BIND 9 Administrator Reference Manual. diff --git a/bin/confgen/util.c b/bin/confgen/util.c new file mode 100644 index 0000000..5d7ce50 --- /dev/null +++ b/bin/confgen/util.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +extern bool verbose; +extern const char *progname; + +void +notify(const char *fmt, ...) { + va_list ap; + + if (verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + } +} + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + _exit(EXIT_FAILURE); +} diff --git a/bin/confgen/util.h b/bin/confgen/util.h new file mode 100644 index 0000000..4ac83e5 --- /dev/null +++ b/bin/confgen/util.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include +#include + +#define NS_CONTROL_PORT 953 + +#undef DO +#define DO(name, function) \ + do { \ + result = function; \ + if (result != ISC_R_SUCCESS) \ + fatal("%s: %s", name, isc_result_totext(result)); \ + else \ + notify("%s", name); \ + } while (0) + +ISC_LANG_BEGINDECLS + +void +notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); + +noreturn void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_LANG_ENDDECLS diff --git a/bin/delv/Makefile.am b/bin/delv/Makefile.am new file mode 100644 index 0000000..3c51bd8 --- /dev/null +++ b/bin/delv/Makefile.am @@ -0,0 +1,23 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + -I$(top_builddir)/include \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(OPENSSL_CFLAGS) + +AM_CPPFLAGS += \ + -DSYSCONFDIR=\"${sysconfdir}\" + +bin_PROGRAMS = delv + +delv_SOURCES = \ + delv.c + +delv_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) \ + $(LIBISCCFG_LIBS) diff --git a/bin/delv/Makefile.in b/bin/delv/Makefile.in new file mode 100644 index 0000000..b77665b --- /dev/null +++ b/bin/delv/Makefile.in @@ -0,0 +1,838 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +bin_PROGRAMS = delv$(EXEEXT) +subdir = bin/delv +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_delv_OBJECTS = delv.$(OBJEXT) +delv_OBJECTS = $(am_delv_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +delv_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(LIBISCCFG_LIBS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/delv.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(delv_SOURCES) +DIST_SOURCES = $(delv_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include -I$(top_builddir)/include $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS) \ + $(OPENSSL_CFLAGS) -DSYSCONFDIR=\"${sysconfdir}\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +delv_SOURCES = \ + delv.c + +delv_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) \ + $(LIBISCCFG_LIBS) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/delv/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/delv/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +delv$(EXEEXT): $(delv_OBJECTS) $(delv_DEPENDENCIES) $(EXTRA_delv_DEPENDENCIES) + @rm -f delv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(delv_OBJECTS) $(delv_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delv.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/delv.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/delv.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-binPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir doc-am doc-local dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-binPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/delv/delv.c b/bin/delv/delv.c new file mode 100644 index 0000000..3cf4bd2 --- /dev/null +++ b/bin/delv/delv.c @@ -0,0 +1,2342 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +#define MAXNAME (DNS_NAME_MAXTEXT + 1) + +#define MAX_QUERIES 50 +#define MAX_TOTAL 200 +#define MAX_RESTARTS 11 + +/* Variables used internally by delv. */ +char *progname = NULL; +static isc_mem_t *mctx = NULL; +static isc_log_t *lctx = NULL; +static dns_view_t *view = NULL; +static ns_server_t *sctx = NULL; +static ns_interface_t *ifp = NULL; +static dns_dispatch_t *dispatch = NULL; +static dns_db_t *roothints = NULL; +static isc_stats_t *resstats = NULL; +static dns_stats_t *resquerystats = NULL; +static FILE *logfp = NULL; + +/* Managers */ +static isc_nm_t *netmgr = NULL; +static isc_loopmgr_t *loopmgr = NULL; +static dns_dispatchmgr_t *dispatchmgr = NULL; +static dns_requestmgr_t *requestmgr = NULL; +static ns_interfacemgr_t *interfacemgr = NULL; + +/* TLS */ +static isc_tlsctx_cache_t *tlsctx_client_cache = NULL; + +/* Configurables */ +static char *server = NULL; +static const char *port = "53"; +static uint32_t destport = 53; +static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL; +static isc_sockaddr_t a4, a6; +static char *curqname = NULL, *qname = NULL; +static bool classset = false; +static dns_rdatatype_t qtype = dns_rdatatype_none; +static bool typeset = false; +static const char *hintfile = NULL; + +static unsigned int styleflags = 0; +static uint32_t splitwidth = 0xffffffff; +static bool showcomments = true, showdnssec = true, showtrust = true, + rrcomments = true, noclass = false, nocrypto = false, nottl = false, + multiline = false, short_form = false, print_unknown_format = false, + yaml = false, fulltrace = false; + +static uint32_t maxqueries = MAX_QUERIES; +static uint32_t maxtotal = MAX_TOTAL; +static uint32_t restarts = MAX_RESTARTS; + +static bool resolve_trace = false, validator_trace = false, + message_trace = false, send_trace = false; + +static bool use_ipv4 = true, use_ipv6 = true; + +static bool cdflag = false, no_sigs = false, root_validation = true; +static bool qmin = false, qmin_strict = false; + +static bool use_tcp = false; + +static char *anchorfile = NULL; +static char *trust_anchor = NULL; +static int num_keys = 0; + +static dns_fixedname_t afn; +static dns_name_t *anchor_name = NULL; + +static dns_master_style_t *style = NULL; +static dns_fixedname_t qfn; + +/* Default trust anchors */ +static char anchortext[] = TRUST_ANCHORS; + +/* + * Static function prototypes + */ +static isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict); + +static isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc); + +static void +usage(void) { + fprintf(stderr, + "Usage: delv [@server] {q-opt} {d-opt} [domain] [q-type] " + "[q-class]\n" + "Where: domain is in the Domain Name System\n" + " q-class is one of (in,hs,ch,...) [default: in]\n" + " q-type is one of " + "(a,any,mx,ns,soa,hinfo,axfr,txt,...) " + "[default:a]\n" + " q-opt is one of:\n" + " -4 (use IPv4 query " + "transport " + "only)\n" + " -6 (use IPv6 query " + "transport " + "only)\n" + " -a anchor-file (specify root trust " + "anchor)\n" + " -b address[#port] (bind to source " + "address/port)\n" + " -c class (option included for " + "compatibility;\n" + " -d level (set debugging level)\n" + " -h (print help and exit)\n" + " -i (disable DNSSEC " + "validation)\n" + " -m (enable memory usage " + "debugging)\n" + " -p port (specify port number)\n" + " -q name (specify query name)\n" + " -t type (specify query type)\n" + " only IN is supported)\n" + " -v (print version and " + "exit)\n" + " -x dot-notation (shortcut for reverse " + "lookups)\n" + " d-opt is of the form +keyword[=value], where " + "keyword " + "is:\n" + " +[no]all (Set or clear all " + "display " + "flags)\n" + " +[no]class (Control display of " + "class)\n" + " +[no]comments (Control display of " + "comment lines)\n" + " +[no]crypto (Control display of " + "cryptographic\n" + " fields in records)\n" + " +[no]dlv (Obsolete)\n" + " +[no]dnssec (Display DNSSEC " + "records)\n" + " +[no]mtrace (Trace messages " + "received)\n" + " +[no]ns (Run internal name " + "server)\n" + " +[no]multiline (Print records in an " + "expanded format)\n" + " +[no]qmin[=mode] (QNAME minimization: " + "relaxed or strict)\n" + " +[no]root (DNSSEC validation trust " + "anchor)\n" + " +[no]rrcomments (Control display of " + "per-record " + "comments)\n" + " +[no]rtrace (Trace resolver " + "fetches)\n" + " +[no]short (Short form answer)\n" + " +[no]split=## (Split hex/base64 fields " + "into chunks)\n" + " +[no]strace (Trace messages " + "sent)\n" + " +[no]tcp (TCP mode)\n" + " +[no]ttl (Control display of ttls " + "in records)\n" + " +[no]trust (Control display of " + "trust " + "level)\n" + " +[no]unknownformat (Print RDATA in RFC 3597 " + "\"unknown\" format)\n" + " +[no]vtrace (Trace validation " + "process)\n" + " +[no]yaml (Present the results as " + "YAML)\n"); + exit(EXIT_FAILURE); +} + +noreturn static void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +fatal(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + _exit(EXIT_FAILURE); +} + +static void +warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +warn(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: warning: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +} + +static isc_logcategory_t categories[] = { { "delv", 0 }, { NULL, 0 } }; +#define LOGCATEGORY_DEFAULT (&categories[0]) +#define LOGMODULE_DEFAULT (&modules[0]) + +static isc_logmodule_t modules[] = { { "delv", 0 }, { NULL, 0 } }; + +static void +delv_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); + +static void +delv_log(int level, const char *fmt, ...) { + va_list ap; + char msgbuf[2048]; + + if (!isc_log_wouldlog(lctx, level)) { + return; + } + + va_start(ap, fmt); + + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, level, "%s", + msgbuf); + va_end(ap); +} + +static int loglevel = 0; + +static void +setup_logging(FILE *errout) { + isc_result_t result; + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + int packetlevel = 10; + + isc_log_create(mctx, &lctx, &logconfig); + isc_log_registercategories(lctx, categories); + isc_log_registermodules(lctx, modules); + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + cfg_log_init(lctx); + + destination.file.stream = errout; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, &destination, + ISC_LOG_PRINTPREFIX); + + isc_log_setdebuglevel(lctx, loglevel); + isc_log_settag(logconfig, ";; "); + + result = isc_log_usechannel(logconfig, "stderr", + ISC_LOGCATEGORY_DEFAULT, NULL); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'stderr'"); + } + + if (resolve_trace && loglevel < 1) { + isc_log_createchannel(logconfig, "resolver", ISC_LOG_TOFILEDESC, + ISC_LOG_DEBUG(1), &destination, + ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "resolver", + DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'resolver'"); + } + } + + if (validator_trace && loglevel < 3) { + isc_log_createchannel(logconfig, "validator", + ISC_LOG_TOFILEDESC, ISC_LOG_DEBUG(3), + &destination, ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "validator", + DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_VALIDATOR); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'validator'"); + } + } + + if (send_trace) { + packetlevel = 11; + } + if ((message_trace || send_trace) && loglevel < packetlevel) { + isc_log_createchannel(logconfig, "messages", ISC_LOG_TOFILEDESC, + ISC_LOG_DEBUG(packetlevel), &destination, + ISC_LOG_PRINTPREFIX); + + result = isc_log_usechannel(logconfig, "messages", + DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_PACKETS); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't attach to log channel 'messagse'"); + } + } +} + +static void +print_status(dns_rdataset_t *rdataset) { + char buf[1024] = { 0 }; + + REQUIRE(rdataset != NULL); + + if (!showtrust || !dns_rdataset_isassociated(rdataset)) { + return; + } + + buf[0] = '\0'; + + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { + strlcat(buf, "negative response", sizeof(buf)); + strlcat(buf, (yaml ? "_" : ", "), sizeof(buf)); + } + + switch (rdataset->trust) { + case dns_trust_none: + strlcat(buf, "untrusted", sizeof(buf)); + break; + case dns_trust_pending_additional: + strlcat(buf, "signed additional data", sizeof(buf)); + if (!yaml) { + strlcat(buf, ", ", sizeof(buf)); + } + strlcat(buf, "pending validation", sizeof(buf)); + break; + case dns_trust_pending_answer: + strlcat(buf, "signed answer", sizeof(buf)); + if (!yaml) { + strlcat(buf, ", ", sizeof(buf)); + } + strlcat(buf, "pending validation", sizeof(buf)); + break; + case dns_trust_additional: + strlcat(buf, "unsigned additional data", sizeof(buf)); + break; + case dns_trust_glue: + strlcat(buf, "glue data", sizeof(buf)); + break; + case dns_trust_answer: + if (root_validation) { + strlcat(buf, "unsigned answer", sizeof(buf)); + } else { + strlcat(buf, "answer not validated", sizeof(buf)); + } + break; + case dns_trust_authauthority: + strlcat(buf, "authority data", sizeof(buf)); + break; + case dns_trust_authanswer: + strlcat(buf, "authoritative", sizeof(buf)); + break; + case dns_trust_secure: + strlcat(buf, "fully validated", sizeof(buf)); + break; + case dns_trust_ultimate: + strlcat(buf, "ultimate trust", sizeof(buf)); + break; + } + + if (yaml) { + char *p; + + /* Convert spaces to underscores for YAML */ + for (p = buf; p != NULL && *p != '\0'; p++) { + if (*p == ' ') { + *p = '_'; + } + } + + printf(" - %s:\n", buf); + } else { + printf("; %s\n", buf); + } +} + +static void +printdata(dns_rdataset_t *rdataset, dns_name_t *owner) { + isc_result_t result = ISC_R_SUCCESS; + static dns_trust_t trust; + static bool first = true; + isc_buffer_t target; + isc_region_t r; + char *t = NULL; + int len = 2048; + + if (!dns_rdataset_isassociated(rdataset)) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(owner, namebuf, sizeof(namebuf)); + delv_log(ISC_LOG_DEBUG(4), "warning: empty rdataset %s", + namebuf); + return; + } + + if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) { + return; + } + + if (first || rdataset->trust != trust) { + if (!first && showtrust && !short_form && !yaml) { + putchar('\n'); + } + print_status(rdataset); + trust = rdataset->trust; + first = false; + } + + do { + t = isc_mem_get(mctx, len); + + isc_buffer_init(&target, t, len); + if (short_form) { + dns_rdata_t rdata = DNS_RDATA_INIT; + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + if ((rdataset->attributes & + DNS_RDATASETATTR_NEGATIVE) != 0) + { + continue; + } + + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tofmttext( + &rdata, dns_rootname, styleflags, 0, + splitwidth, " ", &target); + if (result != ISC_R_SUCCESS) { + break; + } + + if (isc_buffer_availablelength(&target) < 1) { + result = ISC_R_NOSPACE; + break; + } + + isc_buffer_putstr(&target, "\n"); + + dns_rdata_reset(&rdata); + } + } else { + dns_indent_t indent = { " ", 2 }; + if (!yaml && (rdataset->attributes & + DNS_RDATASETATTR_NEGATIVE) != 0) + { + isc_buffer_putstr(&target, "; "); + } + result = dns_master_rdatasettotext( + owner, rdataset, style, yaml ? &indent : NULL, + &target); + } + + if (result == ISC_R_NOSPACE) { + isc_mem_put(mctx, t, len); + len += 1024; + } else if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } else { + CHECK(result); + } + } while (result == ISC_R_NOSPACE); + + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + +cleanup: + if (t != NULL) { + isc_mem_put(mctx, t, len); + } +} + +static isc_result_t +setup_style(void) { + isc_result_t result; + + styleflags |= DNS_STYLEFLAG_REL_OWNER; + if (yaml) { + styleflags |= DNS_STYLEFLAG_YAML; + } else { + if (showcomments) { + styleflags |= DNS_STYLEFLAG_COMMENT; + } + if (print_unknown_format) { + styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; + } + if (rrcomments) { + styleflags |= DNS_STYLEFLAG_RRCOMMENT; + } + if (nottl) { + styleflags |= DNS_STYLEFLAG_NO_TTL; + } + if (noclass) { + styleflags |= DNS_STYLEFLAG_NO_CLASS; + } + if (nocrypto) { + styleflags |= DNS_STYLEFLAG_NOCRYPTO; + } + if (multiline) { + styleflags |= DNS_STYLEFLAG_MULTILINE; + styleflags |= DNS_STYLEFLAG_COMMENT; + } + } + + if (multiline || (nottl && noclass)) { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 24, + 32, 80, 8, splitwidth, mctx); + } else if (nottl || noclass) { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 32, + 40, 80, 8, splitwidth, mctx); + } else { + result = dns_master_stylecreate(&style, styleflags, 24, 32, 40, + 48, 80, 8, splitwidth, mctx); + } + + return result; +} + +static isc_result_t +convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) { + isc_result_t result; + isc_buffer_t b; + dns_name_t *n = NULL; + unsigned int len; + + REQUIRE(fn != NULL && name != NULL && text != NULL); + len = strlen(text); + + isc_buffer_constinit(&b, text, len); + isc_buffer_add(&b, len); + n = dns_fixedname_initname(fn); + + result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "failed to convert name %s: %s", text, + isc_result_totext(result)); + return result; + } + + *name = n; + return ISC_R_SUCCESS; +} + +static isc_result_t +key_fromconfig(const cfg_obj_t *key, dns_client_t *client, dns_view_t *toview) { + dns_rdata_dnskey_t dnskey; + dns_rdata_ds_t ds; + uint32_t rdata1, rdata2, rdata3; + const char *datastr = NULL, *keynamestr = NULL, *atstr = NULL; + unsigned char data[4096]; + isc_buffer_t databuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + dns_fixedname_t fkeyname; + dns_name_t *keyname; + isc_result_t result; + bool match_root = false; + enum { + INITIAL_KEY, + STATIC_KEY, + INITIAL_DS, + STATIC_DS, + TRUSTED + } anchortype; + const cfg_obj_t *obj; + + REQUIRE(client != NULL || toview != NULL); + + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + CHECK(convert_name(&fkeyname, &keyname, keynamestr)); + + if (!root_validation) { + return ISC_R_SUCCESS; + } + + if (anchor_name) { + match_root = dns_name_equal(keyname, anchor_name); + } + + if (!match_root) { + return ISC_R_SUCCESS; + } + + if (!root_validation) { + return ISC_R_SUCCESS; + } + + delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor); + + /* if DNSKEY, flags; if DS, key tag */ + rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); + + /* if DNSKEY, protocol; if DS, algorithm */ + rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); + + /* if DNSKEY, algorithm; if DS, digest type */ + rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); + + /* What type of trust anchor is this? */ + obj = cfg_tuple_get(key, "anchortype"); + if (cfg_obj_isvoid(obj)) { + /* + * "anchortype" is not defined, this must be a static-key + * configured with trusted-keys. + */ + anchortype = STATIC_KEY; + } else { + atstr = cfg_obj_asstring(obj); + if (strcasecmp(atstr, "static-key") == 0) { + anchortype = STATIC_KEY; + } else if (strcasecmp(atstr, "static-ds") == 0) { + anchortype = STATIC_DS; + } else if (strcasecmp(atstr, "initial-key") == 0) { + anchortype = INITIAL_KEY; + } else if (strcasecmp(atstr, "initial-ds") == 0) { + anchortype = INITIAL_DS; + } else { + delv_log(ISC_LOG_ERROR, + "key '%s': invalid initialization method '%s'", + keynamestr, atstr); + result = ISC_R_FAILURE; + goto cleanup; + } + } + + isc_buffer_init(&databuf, data, sizeof(data)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + if (rdata1 > 0xffff) { + CHECK(ISC_R_RANGE); + } + if (rdata2 > 0xff) { + CHECK(ISC_R_RANGE); + } + if (rdata3 > 0xff) { + CHECK(ISC_R_RANGE); + } + + switch (anchortype) { + case STATIC_KEY: + case INITIAL_KEY: + case TRUSTED: + dnskey.common.rdclass = dns_rdataclass_in; + dnskey.common.rdtype = dns_rdatatype_dnskey; + dnskey.mctx = NULL; + + ISC_LINK_INIT(&dnskey.common, link); + + dnskey.flags = (uint16_t)rdata1; + dnskey.protocol = (uint8_t)rdata2; + dnskey.algorithm = (uint8_t)rdata3; + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_base64_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + dnskey.datalen = r.length; + dnskey.data = r.base; + + CHECK(dns_rdata_fromstruct(NULL, dnskey.common.rdclass, + dnskey.common.rdtype, &dnskey, + &rrdatabuf)); + if (client != NULL) { + CHECK(dns_client_addtrustedkey( + client, dns_rdataclass_in, dns_rdatatype_dnskey, + keyname, &rrdatabuf)); + } else if (toview != NULL) { + CHECK(dns_view_addtrustedkey(toview, + dns_rdatatype_dnskey, + keyname, &rrdatabuf)); + } + break; + case INITIAL_DS: + case STATIC_DS: + ds.common.rdclass = dns_rdataclass_in; + ds.common.rdtype = dns_rdatatype_ds; + ds.mctx = NULL; + + ISC_LINK_INIT(&ds.common, link); + + ds.key_tag = (uint16_t)rdata1; + ds.algorithm = (uint8_t)rdata2; + ds.digest_type = (uint8_t)rdata3; + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_hex_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + + switch (ds.digest_type) { + case DNS_DSDIGEST_SHA1: + if (r.length != ISC_SHA1_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA256: + if (r.length != ISC_SHA256_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA384: + if (r.length != ISC_SHA384_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + } + + ds.length = r.length; + ds.digest = r.base; + + CHECK(dns_rdata_fromstruct(NULL, ds.common.rdclass, + ds.common.rdtype, &ds, &rrdatabuf)); + if (client != NULL) { + CHECK(dns_client_addtrustedkey( + client, dns_rdataclass_in, dns_rdatatype_ds, + keyname, &rrdatabuf)); + } else if (toview != NULL) { + CHECK(dns_view_addtrustedkey(toview, dns_rdatatype_ds, + keyname, &rrdatabuf)); + } + } + + num_keys++; + +cleanup: + if (result == DST_R_NOCRYPTO) { + cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); + } else if (result == DST_R_UNSUPPORTEDALG) { + cfg_obj_log(key, lctx, ISC_LOG_WARNING, + "skipping trusted key '%s': %s", keynamestr, + isc_result_totext(result)); + result = ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + cfg_obj_log(key, lctx, ISC_LOG_ERROR, + "failed to add trusted key '%s': %s", keynamestr, + isc_result_totext(result)); + result = ISC_R_FAILURE; + } + + return result; +} + +static isc_result_t +load_keys(const cfg_obj_t *keys, dns_client_t *client, dns_view_t *toview) { + const cfg_listelt_t *elt, *elt2; + const cfg_obj_t *key, *keylist; + isc_result_t result = ISC_R_SUCCESS; + + for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) + { + keylist = cfg_listelt_value(elt); + + for (elt2 = cfg_list_first(keylist); elt2 != NULL; + elt2 = cfg_list_next(elt2)) + { + key = cfg_listelt_value(elt2); + CHECK(key_fromconfig(key, client, toview)); + } + } + +cleanup: + if (result == DST_R_NOCRYPTO) { + result = ISC_R_SUCCESS; + } + return result; +} + +static isc_result_t +setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) { + isc_result_t result; + cfg_parser_t *parser = NULL; + const cfg_obj_t *trusted_keys = NULL; + const cfg_obj_t *managed_keys = NULL; + const cfg_obj_t *trust_anchors = NULL; + cfg_obj_t *bindkeys = NULL; + + if (!root_validation) { + return ISC_R_SUCCESS; + } + + if (trust_anchor == NULL) { + trust_anchor = isc_mem_strdup(mctx, "."); + } + + if (trust_anchor != NULL) { + CHECK(convert_name(&afn, &anchor_name, trust_anchor)); + } + + CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); + + if (anchorfile != NULL) { + if (access(anchorfile, R_OK) != 0) { + fatal("Unable to read key file '%s'", anchorfile); + } + + result = cfg_parse_file(parser, anchorfile, &cfg_type_bindkeys, + &bindkeys); + if (result != ISC_R_SUCCESS) { + fatal("Unable to load keys from '%s'", anchorfile); + } + } else { + isc_buffer_t b; + + isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); + isc_buffer_add(&b, sizeof(anchortext) - 1); + cfg_parser_reset(parser); + result = cfg_parse_buffer(parser, &b, NULL, 0, + &cfg_type_bindkeys, 0, &bindkeys); + if (result != ISC_R_SUCCESS) { + fatal("Unable to parse built-in keys"); + } + } + + INSIST(bindkeys != NULL); + cfg_map_get(bindkeys, "trusted-keys", &trusted_keys); + cfg_map_get(bindkeys, "managed-keys", &managed_keys); + cfg_map_get(bindkeys, "trust-anchors", &trust_anchors); + + if (trusted_keys != NULL) { + CHECK(load_keys(trusted_keys, client, toview)); + } + if (managed_keys != NULL) { + CHECK(load_keys(managed_keys, client, toview)); + } + if (trust_anchors != NULL) { + CHECK(load_keys(trust_anchors, client, toview)); + } + result = ISC_R_SUCCESS; + + if (num_keys == 0) { + fatal("No trusted keys were loaded"); + } + +cleanup: + if (bindkeys != NULL) { + cfg_obj_destroy(parser, &bindkeys); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", + isc_result_totext(result)); + } + return result; +} + +static isc_result_t +addserver(dns_client_t *client) { + struct addrinfo hints, *res = NULL, *cur = NULL; + int gaierror; + struct in_addr in4; + struct in6_addr in6; + isc_sockaddr_t *sa = NULL; + isc_sockaddrlist_t servers; + isc_result_t result; + dns_name_t *name = NULL; + + ISC_LIST_INIT(servers); + + if (inet_pton(AF_INET, server, &in4) == 1) { + if (!use_ipv4) { + fatal("Use of IPv4 disabled by -6"); + } + sa = isc_mem_get(mctx, sizeof(*sa)); + ISC_LINK_INIT(sa, link); + isc_sockaddr_fromin(sa, &in4, destport); + ISC_LIST_APPEND(servers, sa, link); + } else if (inet_pton(AF_INET6, server, &in6) == 1) { + if (!use_ipv6) { + fatal("Use of IPv6 disabled by -4"); + } + sa = isc_mem_get(mctx, sizeof(*sa)); + ISC_LINK_INIT(sa, link); + isc_sockaddr_fromin6(sa, &in6, destport); + ISC_LIST_APPEND(servers, sa, link); + } else { + memset(&hints, 0, sizeof(hints)); + if (!use_ipv6) { + hints.ai_family = AF_INET; + } else if (!use_ipv4) { + hints.ai_family = AF_INET6; + } else { + hints.ai_family = AF_UNSPEC; + } + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + gaierror = getaddrinfo(server, port, &hints, &res); + if (gaierror != 0) { + delv_log(ISC_LOG_ERROR, "getaddrinfo failed: %s", + gai_strerror(gaierror)); + return ISC_R_FAILURE; + } + + result = ISC_R_SUCCESS; + for (cur = res; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET && + cur->ai_family != AF_INET6) + { + continue; + } + sa = isc_mem_get(mctx, sizeof(*sa)); + *sa = (isc_sockaddr_t){ + .length = (unsigned int)cur->ai_addrlen, + }; + ISC_LINK_INIT(sa, link); + memmove(&sa->type, cur->ai_addr, cur->ai_addrlen); + ISC_LIST_APPEND(servers, sa, link); + } + freeaddrinfo(res); + CHECK(result); + } + + CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); + +cleanup: + while (!ISC_LIST_EMPTY(servers)) { + sa = ISC_LIST_HEAD(servers); + ISC_LIST_UNLINK(servers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "addserver: %s", + isc_result_totext(result)); + } + + return result; +} + +static isc_result_t +findserver(dns_client_t *client) { + isc_result_t result; + irs_resconf_t *resconf = NULL; + isc_sockaddrlist_t *nameservers; + isc_sockaddr_t *sa = NULL, *next = NULL; + + result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); + if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { + delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", + isc_result_totext(result)); + goto cleanup; + } + + /* Get nameservers from resolv.conf */ + nameservers = irs_resconf_getnameservers(resconf); + for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { + next = ISC_LIST_NEXT(sa, link); + + /* Set destination port */ + if (sa->type.sa.sa_family == AF_INET && use_ipv4) { + sa->type.sin.sin_port = htons(destport); + continue; + } + if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { + sa->type.sin6.sin6_port = htons(destport); + continue; + } + + /* Incompatible protocol family */ + ISC_LIST_UNLINK(*nameservers, sa, link); + isc_mem_put(mctx, sa, sizeof(*sa)); + } + + /* None found, use localhost */ + if (ISC_LIST_EMPTY(*nameservers)) { + if (use_ipv4) { + struct in_addr localhost; + localhost.s_addr = htonl(INADDR_LOOPBACK); + sa = isc_mem_get(mctx, sizeof(*sa)); + isc_sockaddr_fromin(sa, &localhost, destport); + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(*nameservers, sa, link); + } + + if (use_ipv6) { + sa = isc_mem_get(mctx, sizeof(*sa)); + isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); + + ISC_LINK_INIT(sa, link); + ISC_LIST_APPEND(*nameservers, sa, link); + } + } + + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + nameservers); + if (result != ISC_R_SUCCESS) { + delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", + isc_result_totext(result)); + } + +cleanup: + if (resconf != NULL) { + irs_resconf_destroy(&resconf); + } + return result; +} + +static isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { + uint32_t n; + isc_result_t result = isc_parse_uint32(&n, value, 10); + if (result == ISC_R_SUCCESS && n > max) { + result = ISC_R_RANGE; + } + if (result != ISC_R_SUCCESS) { + printf("invalid %s '%s': %s\n", desc, value, + isc_result_totext(result)); + return result; + } + *uip = n; + return ISC_R_SUCCESS; +} + +static void +plus_option(char *option) { + isc_result_t result; + char *cmd, *value, *last = NULL; + bool state = true; + + INSIST(option != NULL); + + cmd = strtok_r(option, "=", &last); + if (cmd == NULL) { + printf(";; Invalid option %s\n", option); + return; + } + if (strncasecmp(cmd, "no", 2) == 0) { + cmd += 2; + state = false; + } + + value = strtok_r(NULL, "\0", &last); + +#define FULLCHECK(A) \ + do { \ + size_t _l = strlen(cmd); \ + if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ + goto invalid_option; \ + } while (0) + + switch (cmd[0]) { + case 'a': /* all */ + FULLCHECK("all"); + showcomments = state; + rrcomments = state; + showtrust = state; + break; + case 'c': + switch (cmd[1]) { + case 'd': /* cdflag */ + FULLCHECK("cdflag"); + cdflag = state; + break; + case 'l': /* class */ + FULLCHECK("class"); + noclass = !state; + break; + case 'o': /* comments */ + FULLCHECK("comments"); + showcomments = state; + break; + case 'r': /* crypto */ + FULLCHECK("crypto"); + nocrypto = !state; + break; + default: + goto invalid_option; + } + break; + case 'd': + switch (cmd[1]) { + case 'l': /* dlv */ + FULLCHECK("dlv"); + if (state) { + fprintf(stderr, "Invalid option: " + "+dlv is obsolete\n"); + exit(EXIT_FAILURE); + } + break; + case 'n': /* dnssec */ + FULLCHECK("dnssec"); + showdnssec = state; + break; + default: + goto invalid_option; + } + break; + case 'h': + switch (cmd[1]) { + case 'i': /* hint */ + if (state) { + if (value == NULL) { + fatal("+hint: must specify hint file"); + } + hintfile = value; + } else { + hintfile = NULL; + } + break; + default: + goto invalid_option; + } + break; + case 'm': + switch (cmd[1]) { + case 'a': + switch (cmd[3]) { + case 'q': /* maxqueries */ + FULLCHECK("maxqueries"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&maxqueries, value, + UINT_MAX, "maxqueries"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse maxqueries"); + } + if (maxqueries == 0) { + fatal("maxqueries must be nonzero"); + } + break; + case 't': /* maxtotalqueries */ + FULLCHECK("maxtotalqueries"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&maxtotal, value, UINT_MAX, + "maxtotalqueries"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse maxtotalqueries"); + } + if (maxtotal == 0) { + fatal("maxtotalqueries must be " + "nonzero"); + } + break; + default: + goto invalid_option; + } + break; + case 't': /* mtrace */ + FULLCHECK("mtrace"); + message_trace = state; + if (state) { + resolve_trace = state; + } + break; + case 'u': /* multiline */ + FULLCHECK("multiline"); + multiline = state; + break; + default: + goto invalid_option; + } + break; + case 'n': + switch (cmd[1]) { + case 's': /* ns */ + FULLCHECK("ns"); + fulltrace = state; + if (state) { + message_trace = state; + send_trace = state; + resolve_trace = state; + logfp = stdout; + } + break; + default: + goto invalid_option; + } + break; + case 'q': /* qmin */ + FULLCHECK("qmin"); + if (state) { + if (value == NULL || strcasecmp(value, "relaxed") == 0) + { + qmin = true; + } else if (strcasecmp(value, "strict") == 0) { + qmin = true; + qmin_strict = true; + } else { + fatal("Invalid qmin option '%s': " + "use 'relaxed' or 'strict'\n", + value); + } + } else { + qmin = false; + qmin_strict = false; + } + break; + case 'r': + switch (cmd[1]) { + case 'e': /* restarts */ + FULLCHECK("restarts"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&restarts, value, 255, "restarts"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse restarts"); + } + if (restarts == 0) { + fatal("restarts must be between 1..255"); + } + break; + case 'o': /* root */ + FULLCHECK("root"); + if (state && no_sigs) { + break; + } + root_validation = state; + if (value != NULL) { + trust_anchor = isc_mem_strdup(mctx, value); + } + break; + case 'r': /* rrcomments */ + FULLCHECK("rrcomments"); + rrcomments = state; + break; + case 't': /* rtrace */ + FULLCHECK("rtrace"); + resolve_trace = state; + break; + default: + goto invalid_option; + } + break; + case 's': + switch (cmd[1]) { + case 'h': /* short */ + FULLCHECK("short"); + short_form = state; + if (short_form) { + multiline = false; + showcomments = false; + showtrust = false; + showdnssec = false; + } + break; + case 'p': /* split */ + FULLCHECK("split"); + if (value != NULL && !state) { + goto invalid_option; + } + if (!state) { + splitwidth = 0; + break; + } else if (value == NULL) { + break; + } + + result = parse_uint(&splitwidth, value, 1023, "split"); + if (splitwidth % 4 != 0) { + splitwidth = ((splitwidth + 3) / 4) * 4; + warn("split must be a multiple of 4; " + "adjusting to %d", + splitwidth); + } + /* + * There is an adjustment done in the + * totext_() functions which causes + * splitwidth to shrink. This is okay when we're + * using the default width but incorrect in this + * case, so we correct for it + */ + if (splitwidth) { + splitwidth += 3; + } + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse split"); + } + break; + case 't': /* strace */ + FULLCHECK("strace"); + send_trace = state; + if (state) { + message_trace = state; + } + break; + default: + goto invalid_option; + } + break; + case 'u': + FULLCHECK("unknownformat"); + print_unknown_format = state; + break; + case 't': + switch (cmd[1]) { + case 'c': /* tcp */ + FULLCHECK("tcp"); + use_tcp = state; + break; + case 'r': + switch (cmd[2]) { + case 'a': /* trace */ + FULLCHECK("trace"); + fatal("Invalid argument +trace. For " + "delegation path tracing, use +ns."); + break; + case 'u': /* trust */ + FULLCHECK("trust"); + showtrust = state; + break; + default: + goto invalid_option; + } + break; + case 't': /* ttl */ + FULLCHECK("ttl"); + nottl = !state; + break; + default: + goto invalid_option; + } + break; + case 'v': /* vtrace */ + FULLCHECK("vtrace"); + validator_trace = state; + if (state) { + resolve_trace = state; + } + break; + case 'y': /* yaml */ + FULLCHECK("yaml"); + yaml = state; + if (state) { + rrcomments = false; + } + break; + default: + invalid_option: + need_value: + fprintf(stderr, "Invalid option: +%s\n", option); + usage(); + } + return; +} + +/* + * options: "46a:b:c:d:himp:q:t:vx:"; + */ +static const char *single_dash_opts = "46himv"; +static const char *dash_opts = "46abcdhimpqtvx"; + +static bool +dash_option(char *option, char *next, bool *open_type_class) { + char opt, *value; + isc_result_t result; + bool value_from_next; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + char textname[MAXNAME]; + struct in_addr in4; + struct in6_addr in6; + in_port_t srcport; + uint32_t num; + char *hash; + + while (strpbrk(option, single_dash_opts) == &option[0]) { + /* + * Since the -[46himv] options do not take an argument, + * account for them (in any number and/or combination) + * if they appear as the first character(s) of a q-opt. + */ + opt = option[0]; + switch (opt) { + case '4': + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + fatal("IPv4 networking not available"); + } + if (use_ipv6) { + isc_net_disableipv6(); + use_ipv6 = false; + } + break; + case '6': + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + fatal("IPv6 networking not available"); + } + if (use_ipv4) { + isc_net_disableipv4(); + use_ipv4 = false; + } + break; + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 'i': + no_sigs = true; + root_validation = false; + break; + case 'm': + /* handled in preparse_args() */ + break; + case 'v': + printf("delv %s\n", PACKAGE_VERSION); + exit(EXIT_SUCCESS); + default: + UNREACHABLE(); + } + if (strlen(option) > 1U) { + option = &option[1]; + } else { + return false; + } + } + opt = option[0]; + if (strlen(option) > 1U) { + value_from_next = false; + value = &option[1]; + } else { + value_from_next = true; + value = next; + } + if (value == NULL) { + goto invalid_option; + } + switch (opt) { + case 'a': + anchorfile = isc_mem_strdup(mctx, value); + return value_from_next; + case 'b': + hash = strchr(value, '#'); + if (hash != NULL) { + result = parse_uint(&num, hash + 1, 0xffff, "port"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + srcport = num; + *hash = '\0'; + } else { + srcport = 0; + } + + if (inet_pton(AF_INET, value, &in4) == 1) { + if (srcaddr4 != NULL) { + fatal("Only one local address per family " + "can be specified\n"); + } + isc_sockaddr_fromin(&a4, &in4, srcport); + srcaddr4 = &a4; + } else if (inet_pton(AF_INET6, value, &in6) == 1) { + if (srcaddr6 != NULL) { + fatal("Only one local address per family " + "can be specified\n"); + } + isc_sockaddr_fromin6(&a6, &in6, srcport); + srcaddr6 = &a6; + } else { + if (hash != NULL) { + *hash = '#'; + } + fatal("Invalid address %s", value); + } + if (hash != NULL) { + *hash = '#'; + } + return value_from_next; + case 'c': + if (classset) { + warn("extra query class"); + } + + *open_type_class = false; + tr.base = value; + tr.length = strlen(value); + result = dns_rdataclass_fromtext(&rdclass, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + classset = true; + } else if (rdclass != dns_rdataclass_in) { + warn("ignoring non-IN query class"); + } else { + warn("ignoring invalid class"); + } + return value_from_next; + case 'd': + result = parse_uint(&num, value, 99, "debug level"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse debug level"); + } + loglevel = num; + return value_from_next; + case 'p': + port = value; + result = parse_uint(&destport, port, 0xffff, "port"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + return value_from_next; + case 'q': + if (curqname != NULL) { + warn("extra query name"); + isc_mem_free(mctx, curqname); + } + curqname = isc_mem_strdup(mctx, value); + return value_from_next; + case 't': + *open_type_class = false; + tr.base = value; + tr.length = strlen(value); + result = dns_rdatatype_fromtext(&rdtype, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (typeset) { + warn("extra query type"); + } + if (rdtype == dns_rdatatype_ixfr || + rdtype == dns_rdatatype_axfr) + { + fatal("Transfer not supported"); + } + qtype = rdtype; + typeset = true; + } else { + warn("ignoring invalid type"); + } + return value_from_next; + case 'x': + result = get_reverse(textname, sizeof(textname), value, false); + if (result == ISC_R_SUCCESS) { + if (curqname != NULL) { + isc_mem_free(mctx, curqname); + warn("extra query name"); + } + curqname = isc_mem_strdup(mctx, textname); + if (typeset) { + warn("extra query type"); + } + qtype = dns_rdatatype_ptr; + typeset = true; + } else { + fprintf(stderr, "Invalid IP address %s\n", value); + exit(EXIT_FAILURE); + } + return value_from_next; + invalid_option: + default: + fprintf(stderr, "Invalid option: -%s\n", option); + usage(); + } + UNREACHABLE(); + return false; +} + +/* + * Check for -m first to determine whether to enable + * memory debugging when setting up the memory context. + */ +static void +preparse_args(int argc, char **argv) { + bool ipv4only = false, ipv6only = false; + char *option; + + for (argc--, argv++; argc > 0; argc--, argv++) { + if (argv[0][0] != '-') { + continue; + } + + option = &argv[0][1]; + while (strpbrk(option, single_dash_opts) == &option[0]) { + switch (option[0]) { + case 'm': + isc_mem_debugging = ISC_MEM_DEBUGTRACE | + ISC_MEM_DEBUGRECORD; + break; + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + } + option = &option[1]; + } + + if (strlen(option) == 0U) { + continue; + } + + /* Look for dash value option. */ + if (strpbrk(option, dash_opts) != &option[0] || + strlen(option) > 1U) + { + /* Error or value in option. */ + continue; + } + + /* Dash value is next argument so we need to skip it. */ + argc--; + argv++; + + /* Handle missing argument */ + if (argc == 0) { + break; + } + } +} + +/* + * Argument parsing is based on dig, but simplified: only one + * QNAME/QCLASS/QTYPE tuple can be specified, and options have + * been removed that aren't applicable to delv. The interface + * should be familiar to dig users, however. + */ +static void +parse_args(int argc, char **argv) { + isc_result_t result; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + bool open_type_class = true; + + for (; argc > 0; argc--, argv++) { + if (argv[0][0] == '@') { + server = &argv[0][1]; + } else if (argv[0][0] == '+') { + plus_option(&argv[0][1]); + } else if (argv[0][0] == '-') { + if (argc <= 1) { + if (dash_option(&argv[0][1], NULL, + &open_type_class)) + { + argc--; + argv++; + } + } else { + if (dash_option(&argv[0][1], argv[1], + &open_type_class)) + { + argc--; + argv++; + } + } + } else { + /* + * Anything which isn't an option + */ + if (open_type_class) { + tr.base = argv[0]; + tr.length = strlen(argv[0]); + result = dns_rdatatype_fromtext( + &rdtype, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (typeset) { + warn("extra query type"); + } + if (rdtype == dns_rdatatype_ixfr || + rdtype == dns_rdatatype_axfr) + { + fatal("Transfer not supported"); + } + qtype = rdtype; + typeset = true; + continue; + } + result = dns_rdataclass_fromtext( + &rdclass, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (classset) { + warn("extra query class"); + } else if (rdclass != dns_rdataclass_in) + { + warn("ignoring non-IN " + "query class"); + } + continue; + } + } + + if (curqname == NULL) { + curqname = isc_mem_strdup(mctx, argv[0]); + } + } + } + + /* check consistency */ + if (qmin && !fulltrace) { + fatal("'+qmin' cannot be used without '+ns'"); + } + + /* + * If no qname or qtype specified, search for root/NS + * If no qtype specified, use A + */ + if (!typeset) { + qtype = dns_rdatatype_a; + } + + if (curqname == NULL) { + qname = isc_mem_strdup(mctx, "."); + + if (!typeset) { + qtype = dns_rdatatype_ns; + } + } else { + qname = curqname; + } +} + +static isc_result_t +append_str(const char *text, int len, char **p, char *end) { + if (len > end - *p) { + return ISC_R_NOSPACE; + } + memmove(*p, text, len); + *p += len; + return ISC_R_SUCCESS; +} + +static isc_result_t +reverse_octets(const char *in, char **p, char *end) { + char *dot = strchr(in, '.'); + int len; + if (dot != NULL) { + isc_result_t result; + result = reverse_octets(dot + 1, p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + result = append_str(".", 1, p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + len = (int)(dot - in); + } else { + len = strlen(in); + } + return append_str(in, len, p, end); +} + +static isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict) { + int r; + isc_result_t result; + isc_netaddr_t addr; + + addr.family = AF_INET6; + r = inet_pton(AF_INET6, value, &addr.type.in6); + if (r > 0) { + /* This is a valid IPv6 address. */ + dns_fixedname_t fname; + dns_name_t *name; + + name = dns_fixedname_initname(&fname); + result = dns_byaddr_createptrname(&addr, name); + if (result != ISC_R_SUCCESS) { + return result; + } + dns_name_format(name, reverse, (unsigned int)len); + return ISC_R_SUCCESS; + } else { + /* + * Not a valid IPv6 address. Assume IPv4. + * If 'strict' is not set, construct the + * in-addr.arpa name by blindly reversing + * octets whether or not they look like integers, + * so that this can be used for RFC2317 names + * and such. + */ + char *p = reverse; + char *end = reverse + len; + if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) { + return DNS_R_BADDOTTEDQUAD; + } + result = reverse_octets(value, &p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + result = append_str(".in-addr.arpa.", 15, &p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + return ISC_R_SUCCESS; + } +} + +static void +resolve_cb(dns_client_t *client, const dns_name_t *query_name, + dns_namelist_t *namelist, isc_result_t result) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_rdataset_t *rdataset; + + if (result != ISC_R_SUCCESS && !yaml) { + delv_log(ISC_LOG_ERROR, "resolution failed: %s", + isc_result_totext(result)); + } + + if (yaml) { + printf("type: DELV_RESULT\n"); + dns_name_format(query_name, namestr, sizeof(namestr)); + printf("query_name: %s\n", namestr); + printf("status: %s\n", isc_result_totext(result)); + printf("records:\n"); + } + + for (dns_name_t *response_name = ISC_LIST_HEAD(*namelist); + response_name != NULL; + response_name = ISC_LIST_NEXT(response_name, link)) + { + for (rdataset = ISC_LIST_HEAD(response_name->list); + rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) + { + printdata(rdataset, response_name); + } + } + + dns_client_freeresanswer(client, namelist); + isc_mem_put(mctx, namelist, sizeof(*namelist)); + + dns_client_detach(&client); + + isc_loopmgr_shutdown(loopmgr); +} + +static void +run_resolve(void *arg) { + dns_client_t *client = NULL; + dns_namelist_t *namelist = NULL; + unsigned int resopt; + isc_result_t result; + dns_name_t *query_name = NULL; + + UNUSED(arg); + + namelist = isc_mem_get(mctx, sizeof(*namelist)); + ISC_LIST_INIT(*namelist); + + /* Construct QNAME */ + CHECK(convert_name(&qfn, &query_name, qname)); + + /* Set up resolution options */ + resopt = DNS_CLIENTRESOPT_NOCDFLAG; + if (no_sigs) { + resopt |= DNS_CLIENTRESOPT_NODNSSEC; + } + if (!root_validation) { + resopt |= DNS_CLIENTRESOPT_NOVALIDATE; + } + if (cdflag) { + resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG; + } + if (use_tcp) { + resopt |= DNS_CLIENTRESOPT_TCP; + } + + /* Create client */ + CHECK(dns_client_create(mctx, loopmgr, netmgr, 0, tlsctx_client_cache, + &client, srcaddr4, srcaddr6)); + dns_client_setmaxrestarts(client, restarts); + dns_client_setmaxqueries(client, maxtotal); + + /* Set the nameserver */ + if (server != NULL) { + addserver(client); + } else { + findserver(client); + } + + CHECK(setup_dnsseckeys(client, NULL)); + + /* Perform resolution */ + CHECK(dns_client_resolve(client, query_name, dns_rdataclass_in, qtype, + resopt, namelist, resolve_cb)); + return; +cleanup: + if (!yaml) { + delv_log(ISC_LOG_ERROR, "resolution failed: %s", + isc_result_totext(result)); + } + + isc_mem_put(mctx, namelist, sizeof(*namelist)); + isc_loopmgr_shutdown(loopmgr); + + dns_client_detach(&client); +} + +static void +shutdown_server(void) { + if (requestmgr != NULL) { + dns_requestmgr_shutdown(requestmgr); + dns_requestmgr_detach(&requestmgr); + } + if (interfacemgr != NULL) { + ns_interfacemgr_shutdown(interfacemgr); + ns_interfacemgr_detach(&interfacemgr); + } + if (dispatch != NULL) { + dns_dispatch_detach(&dispatch); + } + if (dispatchmgr != NULL) { + dns_dispatchmgr_detach(&dispatchmgr); + } + if (sctx != NULL) { + ns_server_detach(&sctx); + } + + isc_loopmgr_shutdown(loopmgr); +} + +static void +recvresponse(void *arg) { + dns_request_t *request = (dns_request_t *)arg; + dns_message_t *query = dns_request_getarg(request); + isc_result_t result = dns_request_getresult(request); + dns_message_t *response = NULL; + dns_name_t *prev = NULL; + + if (result != ISC_R_SUCCESS) { + fatal("request event result: %s", isc_result_totext(result)); + } + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, + &response); + + result = dns_request_getresponse(request, response, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result != ISC_R_SUCCESS) { + fatal("request response failed: %s", isc_result_totext(result)); + } + if (response->rcode != dns_rcode_noerror) { + result = dns_result_fromrcode(response->rcode); + delv_log(ISC_LOG_INFO, "response code: %s", + isc_result_totext(result)); + goto cleanup; + } + + for (result = dns_message_firstname(response, DNS_SECTION_ANSWER); + result == ISC_R_SUCCESS; + result = dns_message_nextname(response, DNS_SECTION_ANSWER)) + { + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + dns_rdatatype_t prevtype = 0; + + dns_message_currentname(response, DNS_SECTION_ANSWER, &name); + + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + dns_rdataset_t rds, sigs; + int options = 0; + + /* + * The response message contains the answer the + * resolver found, but it doesn't contain the + * trust status. if we're not displaying that, + * fine, we can just print that version. + */ + if (!showtrust) { + printdata(rdataset, name); + continue; + } + + /* + * ... but if we are printing the trust status + * (which is the default behavior)), we'll need + * to retrieve a copy of the rdataset from the cache. + * if we do that for ever record, it will produce + * duplicate output, so we check here whether we've + * already printed this name and type. + */ + if (prev != NULL && dns_name_equal(prev, name)) { + continue; + } + prev = name; + + if (prevtype == rdataset->type) { + continue; + } + prevtype = rdataset->type; + + /* do the cache lookup */ + if (rdataset->type == dns_rdatatype_rrsig) { + continue; + } + + dns_rdataset_init(&rds); + dns_rdataset_init(&sigs); + + if (cdflag) { + options |= DNS_DBFIND_PENDINGOK; + } + result = dns_view_simplefind(view, name, rdataset->type, + 0, options, false, &rds, + &sigs); + if (result == ISC_R_SUCCESS) { + printdata(&rds, name); + dns_rdataset_disassociate(&rds); + if (dns_rdataset_isassociated(&sigs)) { + printdata(&sigs, name); + dns_rdataset_disassociate(&sigs); + } + } + } + } + +cleanup: + dns_message_detach(&query); + dns_message_detach(&response); + dns_request_destroy(&request); + + dns_view_detach(&view); + shutdown_server(); +} + +static isc_result_t +accept_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + UNUSED(handle); + UNUSED(arg); + + return result; +} + +static void +sendquery(void *arg) { + isc_nmsocket_t *sock = (isc_nmsocket_t *)arg; + isc_sockaddr_t peer = isc_nmsocket_getaddr(sock); + isc_result_t result; + dns_message_t *message = NULL; + dns_name_t *query_name = NULL, *mname = NULL; + dns_rdataset_t *mrdataset = NULL; + dns_rdataset_t *opt = NULL; + dns_request_t *request = NULL; + + /* Construct query message */ + CHECK(convert_name(&qfn, &query_name, qname)); + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &message); + message->opcode = dns_opcode_query; + message->flags = DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_AD; + if (cdflag) { + message->flags |= DNS_MESSAGEFLAG_CD; + } + message->rdclass = dns_rdataclass_in; + message->id = (dns_messageid_t)isc_random16(); + + dns_message_gettempname(message, &mname); + dns_message_gettemprdataset(message, &mrdataset); + dns_name_clone(query_name, mname); + dns_rdataset_makequestion(mrdataset, dns_rdataclass_in, qtype); + ISC_LIST_APPEND(mname->list, mrdataset, link); + dns_message_addname(message, mname, DNS_SECTION_QUESTION); + mrdataset = NULL; + mname = NULL; + + CHECK(dns_message_buildopt(message, &opt, 0, 0, DNS_MESSAGEEXTFLAG_DO, + NULL, 0)); + CHECK(dns_message_setopt(message, opt)); + + CHECK(dns_requestmgr_create(mctx, loopmgr, dispatchmgr, NULL, NULL, + &requestmgr)); + + dns_view_attach(view, &(dns_view_t *){ NULL }); + CHECK(dns_request_create(requestmgr, message, NULL, &peer, NULL, NULL, + DNS_REQUESTOPT_TCP, NULL, 1, 0, 0, isc_loop(), + recvresponse, message, &request)); + return; + +cleanup: + if (message != NULL) { + dns_message_detach(&message); + } + + shutdown_server(); +} + +static isc_result_t +matchview(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, + dns_message_t *message, dns_aclenv_t *env, ns_server_t *lsctx, + isc_loop_t *loop, isc_job_cb cb, void *cbarg, + isc_result_t *sigresultp, isc_result_t *viewpatchresultp, + dns_view_t **viewp) { + UNUSED(srcaddr); + UNUSED(destaddr); + UNUSED(message); + UNUSED(env); + UNUSED(lsctx); + UNUSED(loop); + UNUSED(cb); + UNUSED(cbarg); + UNUSED(sigresultp); + + *viewp = view; + *viewpatchresultp = ISC_R_SUCCESS; + return ISC_R_SUCCESS; +} + +static void +run_server(void *arg) { + isc_result_t result; + dns_cache_t *cache = NULL; + isc_sockaddr_t addr, any; + struct in_addr in; + + UNUSED(arg); + + RUNTIME_CHECK(inet_pton(AF_INET, "127.0.0.1", &in)); + isc_sockaddr_fromin(&addr, &in, 0); + + ns_server_create(mctx, matchview, &sctx); + + CHECK(dns_dispatchmgr_create(mctx, loopmgr, netmgr, &dispatchmgr)); + isc_sockaddr_any(&any); + CHECK(dns_dispatch_createudp(dispatchmgr, &any, &dispatch)); + CHECK(ns_interfacemgr_create(mctx, sctx, loopmgr, netmgr, dispatchmgr, + NULL, &interfacemgr)); + + CHECK(dns_view_create(mctx, loopmgr, dispatchmgr, dns_rdataclass_in, + "_default", &view)); + CHECK(dns_cache_create(loopmgr, dns_rdataclass_in, "", mctx, &cache)); + dns_view_setcache(view, cache, false); + dns_cache_detach(&cache); + dns_view_setdstport(view, destport); + dns_view_setmaxrestarts(view, restarts); + dns_view_setmaxqueries(view, maxtotal); + + CHECK(dns_rootns_create(mctx, dns_rdataclass_in, hintfile, &roothints)); + dns_view_sethints(view, roothints); + dns_db_detach(&roothints); + + view->qminimization = qmin; + view->qmin_strict = qmin_strict; + + dns_view_initsecroots(view); + CHECK(setup_dnsseckeys(NULL, view)); + + CHECK(dns_view_createresolver(view, netmgr, 0, tlsctx_client_cache, + dispatch, NULL)); + dns_resolver_setmaxqueries(view->resolver, maxqueries); + + isc_stats_create(mctx, &resstats, dns_resstatscounter_max); + dns_resolver_setstats(view->resolver, resstats); + isc_stats_detach(&resstats); + + dns_rdatatypestats_create(mctx, &resquerystats); + dns_resolver_setquerystats(view->resolver, resquerystats); + dns_stats_detach(&resquerystats); + + dns_view_freeze(view); + + ns_interface_create(interfacemgr, &addr, NULL, &ifp); + + CHECK(isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE, &addr, + ns_client_request, ifp, accept_cb, ifp, 10, + NULL, NULL, ISC_NM_PROXY_NONE, + &ifp->tcplistensocket)); + ifp->flags |= NS_INTERFACEFLAG_LISTENING; + isc_async_current(sendquery, ifp->tcplistensocket); + + return; + +cleanup: + if (view != NULL) { + dns_view_detach(&view); + } + shutdown_server(); +} + +int +main(int argc, char *argv[]) { + isc_result_t result; + isc_loop_t *loop = NULL; + + progname = argv[0]; + logfp = stderr; + + preparse_args(argc, argv); + + argc--; + argv++; + + isc_managers_create(&mctx, 1, &loopmgr, &netmgr); + loop = isc_loop_main(loopmgr); + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + fatal("dst_lib_init failed: %d", result); + } + + parse_args(argc, argv); + + CHECK(setup_style()); + + setup_logging(logfp); + + if (!fulltrace && hintfile != NULL) { + delv_log(ISC_LOG_WARNING, + "WARNING: not using internal name server mode, " + "hint file will be ignored"); + } + + if (fulltrace && server != NULL) { + delv_log(ISC_LOG_WARNING, + "WARNING: using internal name server mode: " + "'@%s' will be ignored", + server); + } + + isc_tlsctx_cache_create(mctx, &tlsctx_client_cache); + + isc_loop_setup(loop, fulltrace ? run_server : run_resolve, NULL); + isc_loopmgr_run(loopmgr); + +cleanup: + if (tlsctx_client_cache != NULL) { + isc_tlsctx_cache_detach(&tlsctx_client_cache); + } + if (trust_anchor != NULL) { + isc_mem_free(mctx, trust_anchor); + } + if (anchorfile != NULL) { + isc_mem_free(mctx, anchorfile); + } + if (qname != NULL) { + isc_mem_free(mctx, qname); + } + if (style != NULL) { + dns_master_styledestroy(&style, mctx); + } + + isc_log_destroy(&lctx); + dst_lib_destroy(); + + isc_managers_destroy(&mctx, &loopmgr, &netmgr); + + return 0; +} diff --git a/bin/delv/delv.rst b/bin/delv/delv.rst new file mode 100644 index 0000000..dffb37b --- /dev/null +++ b/bin/delv/delv.rst @@ -0,0 +1,422 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: delv +.. program:: delv +.. _man_delv: + +delv - DNS lookup and validation utility +---------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`delv` [@server] [ [**-4**] | [**-6**] ] [**-a** anchor-file] [**-b** address] [**-c** class] [**-d** level] [**-i**] [**-m**] [**-p** port#] [**-q** name] [**-t** type] [**-x** addr] [name] [type] [class] [queryopt...] + +:program:`delv` [**-h**] + +:program:`delv` [**-v**] + +:program:`delv` [queryopt...] [query...] + +Description +~~~~~~~~~~~ + +:program:`delv` is a tool for sending DNS queries and validating the results, +using the same internal resolver and validator logic as :iscman:`named`. + +:program:`delv` sends to a specified name server all queries needed to +fetch and validate the requested data; this includes the original +requested query, subsequent queries to follow CNAME or DNAME chains, +queries for DNSKEY, and DS records to establish a chain of trust for +DNSSEC validation. It does not perform iterative resolution, but +simulates the behavior of a name server configured for DNSSEC validating +and forwarding. + +By default, responses are validated using the built-in DNSSEC trust anchor +for the root zone ("."). Records returned by :program:`delv` are either fully +validated or were not signed. If validation fails, an explanation of the +failure is included in the output; the validation process can be traced +in detail. Because :program:`delv` does not rely on an external server to carry +out validation, it can be used to check the validity of DNS responses in +environments where local name servers may not be trustworthy. + +Unless it is told to query a specific name server, :program:`delv` tries +each of the servers listed in ``/etc/resolv.conf``. If no usable server +addresses are found, :program:`delv` sends queries to the localhost +addresses (127.0.0.1 for IPv4, ::1 for IPv6). + +When no command-line arguments or options are given, :program:`delv` +performs an NS query for "." (the root zone). + +Simple Usage +~~~~~~~~~~~~ + +A typical invocation of :program:`delv` looks like: + +:: + + delv @server name type + +where: + +.. option:: server + + is the name or IP address of the name server to query. This can be an + IPv4 address in dotted-decimal notation or an IPv6 address in + colon-delimited notation. When the supplied ``server`` argument is a + hostname, :program:`delv` resolves that name before querying that name + server (note, however, that this initial lookup is *not* validated by + DNSSEC). + + If no ``server`` argument is provided, :program:`delv` consults + ``/etc/resolv.conf``; if an address is found there, it queries the + name server at that address. If either of the :option:`-4` or :option:`-6` + options is in use, then only addresses for the corresponding + transport are tried. If no usable addresses are found, :program:`delv` + sends queries to the localhost addresses (127.0.0.1 for IPv4, ::1 + for IPv6). + +.. option:: name + + is the domain name to be looked up. + +.. option:: type + + indicates what type of query is required - ANY, A, MX, etc. + ``type`` can be any valid query type. If no ``type`` argument is + supplied, :program:`delv` performs a lookup for an A record. + +Options +~~~~~~~ + +.. option:: -a anchor-file + + This option specifies a file from which to read an alternate + DNSSEC root zone trust anchor. + + By default, keys that do not match the root zone name (`.`) are + ignored. If an alternate key name is desired, it can be + specified using the :option:`+root` option. + + Note: When reading trust anchors, :program:`delv` treats + ``trust-anchors``, ``initial-key``, and ``static-key`` identically. That + is, for a managed key, it is the *initial* key that is trusted; + :rfc:`5011` key management is not supported. :program:`delv` does not + consult the managed-keys database maintained by :iscman:`named`. This + means that if the default key built in to :program:`delv` is revoked, + :program:`delv` must be updated to a newer version in order to continue + validating. + +.. option:: -b address + + This option sets the source IP address of the query to ``address``. This must be + a valid address on one of the host's network interfaces, or ``0.0.0.0``, + or ``::``. An optional source port may be specified by appending + ``#`` + +.. option:: -c class + + This option sets the query class for the requested data. Currently, only class + "IN" is supported in :program:`delv` and any other value is ignored. + +.. option:: -d level + + This option sets the systemwide debug level to ``level``. The allowed range is + from 0 to 99. The default is 0 (no debugging). Debugging traces from + :program:`delv` become more verbose as the debug level increases. See the + :option:`+mtrace`, :option:`+rtrace`, and :option:`+vtrace` options below for + additional debugging details. + +.. option:: -h + + This option displays the :program:`delv` help usage output and exits. + +.. option:: -i + + This option sets insecure mode, which disables internal DNSSEC validation. (Note, + however, that this does not set the CD bit on upstream queries. If the + server being queried is performing DNSSEC validation, then it does + not return invalid data; this can cause :program:`delv` to time out. When it + is necessary to examine invalid data to debug a DNSSEC problem, use + :option:`dig +cd`.) + +.. option:: -m + + This option enables memory usage debugging. + +.. option:: -p port# + + This option specifies a destination port to use for queries, instead of the + standard DNS port number 53. This option is used with a name + server that has been configured to listen for queries on a + non-standard port number. + +.. option:: -q name + + This option sets the query name to ``name``. While the query name can be + specified without using the :option:`-q` option, it is sometimes necessary to + disambiguate names from types or classes (for example, when looking + up the name "ns", which could be misinterpreted as the type NS, or + "ch", which could be misinterpreted as class CH). + +.. option:: -t type + + This option sets the query type to ``type``, which can be any valid query type + supported in BIND 9 except for zone transfer types AXFR and IXFR. As + with :option:`-q`, this is useful to distinguish query-name types or classes + when they are ambiguous. It is sometimes necessary to disambiguate + names from types. + + The default query type is "A", unless the :option:`-x` option is supplied + to indicate a reverse lookup, in which case it is "PTR". + +.. option:: -v + + This option prints the :program:`delv` version and exits. + +.. option:: -x addr + + This option performs a reverse lookup, mapping an address to a name. ``addr`` + is an IPv4 address in dotted-decimal notation, or a colon-delimited + IPv6 address. When :option:`-x` is used, there is no need to provide the + ``name`` or ``type`` arguments; :program:`delv` automatically performs a + lookup for a name like ``11.12.13.10.in-addr.arpa`` and sets the + query type to PTR. IPv6 addresses are looked up using nibble format + under the IP6.ARPA domain. + +.. option:: -4 + + This option forces :program:`delv` to only use IPv4. + +.. option:: -6 + + This option forces :program:`delv` to only use IPv6. + +Query Options +~~~~~~~~~~~~~ + +:program:`delv` provides a number of query options which affect the way results +are displayed, and in some cases the way lookups are performed. + +Each query option is identified by a keyword preceded by a plus sign +(``+``). Some keywords set or reset an option. These may be preceded by +the string ``no`` to negate the meaning of that keyword. Other keywords +assign values to options like the timeout interval. They have the form +``+keyword=value``. The query options are: + +.. option:: +cdflag, +nocdflag + + This option controls whether to set the CD (checking disabled) bit in queries + sent by :program:`delv`. This may be useful when troubleshooting DNSSEC + problems from behind a validating resolver. A validating resolver + blocks invalid responses, making it difficult to retrieve them + for analysis. Setting the CD flag on queries causes the resolver + to return invalid responses, which :program:`delv` can then validate + internally and report the errors in detail. + +.. option:: +class, +noclass + + This option controls whether to display the CLASS when printing a record. The + default is to display the CLASS. + +.. option:: +hint=FILE, +nohint + + This option specifies a filename from which to load root hints; + this will be used to find the root name servers when name server + mode (``delv +ns``) is in use. If the option is not specified, + built-in root hints will be used. + +.. option:: +ns, +nons + + This option toggles name server mode. When this option is in use, + the ``delv`` process instantiates a full recursive resolver, and uses + that to look up the requested query name and type. Turning on this + option also activates ``+mtrace``, ``+strace`` and ``+rtrace``, so that + every iterative query will be logged, including the full response messages + from each authoritatve server. These logged messages will be written + to ``stdout`` rather than ``stderr`` as usual, so that the full trace + can be captured more easily. + + This is intended to be similar to the behavior of ``dig +trace``, but + because it uses the same code as ``named``, it much more accurately + replicates the behavior of a recursive name server with a cold cache + that is processing a recursive query. + +.. option:: +qmin[=MODE], +noqmin + + When used with ``+ns``, this option enables QNAME minimization mode. + Valid options of MODE are ``relaxed`` and ``strict``. By default, + QNAME minimization is disabled. If ``+qmin`` is specified but MODE + is omitted, then ``relaxed`` mode will be used. + +.. option:: +ttl, +nottl + + This option controls whether to display the TTL when printing a record. The + default is to display the TTL. + +.. option:: +rtrace, +nortrace + + This option toggles resolver fetch logging. This reports the name and + type of each query sent by :program:`delv` in the process of carrying + out the resolution and validation process, including the original query + and all subsequent queries to follow CNAMEs and to establish a chain of + trust for DNSSEC validation. + + This is equivalent to setting the debug level to 1 in the "resolver" + logging category. Setting the systemwide debug level to 1 using the + :option:`-d` option produces the same output, but affects other + logging categories as well. + +.. option:: +mtrace, +nomtrace + + This option toggles logging of messages received. This produces + a detailed dump of the responses received by :program:`delv` in the + process of carrying out the resolution and validation process. + + This is equivalent to setting the debug level to 10 for the "packets" + module of the "resolver" logging category. Setting the systemwide + debug level to 10 using the :option:`-d` option produces the same + output, but affects other logging categories as well. + +.. option:: +strace, +nostrace + + This option toggles logging of messages sent. This produces a detailed + dump of the queries sent by :program:`delv` in the process of carrying + out the resolution and validation process. Turning on this option + also activates ``+mtrace``. + + This is equivalent to setting the debug level to 11 for the "packets" + module of the "resolver" logging category. Setting the systemwide + debug level to 11 using the :option:`-d` option produces the same + output, but affects other logging categories as well. + +.. option:: +vtrace, +novtrace + + This option toggles validation logging. This shows the internal process of the + validator as it determines whether an answer is validly signed, + unsigned, or invalid. + + This is equivalent to setting the debug level to 3 for the + "validator" module of the "dnssec" logging category. Setting the + systemwide debug level to 3 using the :option:`-d` option produces the + same output, but affects other logging categories as well. + +.. option:: +short, +noshort + + This option toggles between verbose and terse answers. The default is to print the answer in a + verbose form. + +.. option:: +comments, +nocomments + + This option toggles the display of comment lines in the output. The default is to + print comments. + +.. option:: +rrcomments, +norrcomments + + This option toggles the display of per-record comments in the output (for example, + human-readable key information about DNSKEY records). The default is + to print per-record comments. + +.. option:: +crypto, +nocrypto + + This option toggles the display of cryptographic fields in DNSSEC records. The + contents of these fields are unnecessary to debug most DNSSEC + validation failures and removing them makes it easier to see the + common failures. The default is to display the fields. When omitted, + they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the + key ID is displayed as the replacement, e.g. ``[ key id = value ]``. + +.. option:: +restarts + + When name server mode (``delv +ns``) is in use, this option sets the + maximum number of CNAME queries to follow before terminating resolution. + This prevents ``delv`` from hanging in the event of a CNAME loop. + The default is 11. + +.. option:: +maxqueries + + This option specifies the maximum number of queries to send to resolve + a name before giving up. The default is 50. + +.. option:: +maxtotalqueries + + This option specifies the maximum number of queries to send to resolve + a client request before giving up. The default is 200. + +.. option:: +trust, +notrust + + This option controls whether to display the trust level when printing a record. + The default is to display the trust level. + +.. option:: +split[=W], +nosplit + + This option splits long hex- or base64-formatted fields in resource records into + chunks of ``W`` characters (where ``W`` is rounded up to the nearest + multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be + split at all. The default is 56 characters, or 44 characters when + multiline mode is active. + +.. option:: +all, +noall + + This option sets or clears the display options :option:`+comments`, + :option:`+rrcomments`, and :option:`+trust` as a group. + +.. option:: +multiline, +nomultiline + + This option prints long records (such as RRSIG, DNSKEY, and SOA records) in a + verbose multi-line format with human-readable comments. The default + is to print each record on a single line, to facilitate machine + parsing of the :program:`delv` output. + +.. option:: +dnssec, +nodnssec + + This option indicates whether to display RRSIG records in the :program:`delv` output. + The default is to do so. Note that (unlike in :iscman:`dig`) this does + *not* control whether to request DNSSEC records or to + validate them. DNSSEC records are always requested, and validation + always occurs unless suppressed by the use of :option:`-i` or + :option:`+noroot`. + +.. option:: +root[=ROOT], +noroot + + This option indicates whether to perform conventional DNSSEC validation, and if so, + specifies the name of a trust anchor. The default is to validate using a + trust anchor of "." (the root zone), for which there is a built-in key. If + specifying a different trust anchor, then :option:`-a` must be used to specify a + file containing the key. + +.. option:: +tcp, +notcp + + This option controls whether to use TCP when sending queries. The default is to + use UDP unless a truncated response has been received. + +.. option:: +unknownformat, +nounknownformat + + This option prints all RDATA in unknown RR-type presentation format (:rfc:`3597`). + The default is to print RDATA for known types in the type's + presentation format. + +.. option:: +yaml, +noyaml + + This option prints response data in YAML format. + +Files +~~~~~ + +``/etc/resolv.conf`` + +See Also +~~~~~~~~ + +:iscman:`dig(1) `, :iscman:`named(8) `, :rfc:`4034`, :rfc:`4035`, :rfc:`4431`, :rfc:`5074`, :rfc:`5155`. diff --git a/bin/dig/Makefile.am b/bin/dig/Makefile.am new file mode 100644 index 0000000..3e86eeb --- /dev/null +++ b/bin/dig/Makefile.am @@ -0,0 +1,37 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(LIBIDN2_CFLAGS) \ + $(LIBUV_CFLAGS) \ + $(OPENSSL_CFLAGS) + +LDADD += \ + libdighost.la \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(LIBIDN2_LIBS) + +noinst_LTLIBRARIES = libdighost.la + +libdighost_la_SOURCES = \ + dighost.h \ + dighost.c + +bin_PROGRAMS = dig host nslookup + +nslookup_CPPFLAGS = \ + $(AM_CPPFLAGS) + +nslookup_LDADD = \ + $(LDADD) + +if HAVE_READLINE +nslookup_CPPFLAGS += \ + $(READLINE_CFLAGS) +nslookup_LDADD += \ + $(READLINE_LIBS) +endif HAVE_READLINE diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in new file mode 100644 index 0000000..020eba6 --- /dev/null +++ b/bin/dig/Makefile.in @@ -0,0 +1,908 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +bin_PROGRAMS = dig$(EXEEXT) host$(EXEEXT) nslookup$(EXEEXT) +@HAVE_READLINE_TRUE@am__append_2 = \ +@HAVE_READLINE_TRUE@ $(READLINE_CFLAGS) + +@HAVE_READLINE_TRUE@am__append_3 = \ +@HAVE_READLINE_TRUE@ $(READLINE_LIBS) + +subdir = bin/dig +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdighost_la_LIBADD = +am_libdighost_la_OBJECTS = dighost.lo +libdighost_la_OBJECTS = $(am_libdighost_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +dig_SOURCES = dig.c +dig_OBJECTS = dig.$(OBJEXT) +dig_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +dig_DEPENDENCIES = libdighost.la $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) +host_SOURCES = host.c +host_OBJECTS = host.$(OBJEXT) +host_LDADD = $(LDADD) +host_DEPENDENCIES = libdighost.la $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) +nslookup_SOURCES = nslookup.c +nslookup_OBJECTS = nslookup-nslookup.$(OBJEXT) +am__DEPENDENCIES_3 = libdighost.la $(am__DEPENDENCIES_2) \ + $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) +@HAVE_READLINE_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +nslookup_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/dig.Po ./$(DEPDIR)/dighost.Plo \ + ./$(DEPDIR)/host.Po ./$(DEPDIR)/nslookup-nslookup.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdighost_la_SOURCES) dig.c host.c nslookup.c +DIST_SOURCES = $(libdighost_la_SOURCES) dig.c host.c nslookup.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) $(LIBIDN2_CFLAGS) $(LIBUV_CFLAGS) \ + $(OPENSSL_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = libdighost.la $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) \ + $(LIBIDN2_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = libdighost.la +libdighost_la_SOURCES = \ + dighost.h \ + dighost.c + +nslookup_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_2) +nslookup_LDADD = $(LDADD) $(am__append_3) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/dig/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/dig/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libdighost.la: $(libdighost_la_OBJECTS) $(libdighost_la_DEPENDENCIES) $(EXTRA_libdighost_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libdighost_la_OBJECTS) $(libdighost_la_LIBADD) $(LIBS) + +dig$(EXEEXT): $(dig_OBJECTS) $(dig_DEPENDENCIES) $(EXTRA_dig_DEPENDENCIES) + @rm -f dig$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dig_OBJECTS) $(dig_LDADD) $(LIBS) + +host$(EXEEXT): $(host_OBJECTS) $(host_DEPENDENCIES) $(EXTRA_host_DEPENDENCIES) + @rm -f host$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(host_OBJECTS) $(host_LDADD) $(LIBS) + +nslookup$(EXEEXT): $(nslookup_OBJECTS) $(nslookup_DEPENDENCIES) $(EXTRA_nslookup_DEPENDENCIES) + @rm -f nslookup$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nslookup_OBJECTS) $(nslookup_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dig.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dighost.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/host.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nslookup-nslookup.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +nslookup-nslookup.o: nslookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nslookup-nslookup.o -MD -MP -MF $(DEPDIR)/nslookup-nslookup.Tpo -c -o nslookup-nslookup.o `test -f 'nslookup.c' || echo '$(srcdir)/'`nslookup.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nslookup-nslookup.Tpo $(DEPDIR)/nslookup-nslookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nslookup.c' object='nslookup-nslookup.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nslookup-nslookup.o `test -f 'nslookup.c' || echo '$(srcdir)/'`nslookup.c + +nslookup-nslookup.obj: nslookup.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nslookup-nslookup.obj -MD -MP -MF $(DEPDIR)/nslookup-nslookup.Tpo -c -o nslookup-nslookup.obj `if test -f 'nslookup.c'; then $(CYGPATH_W) 'nslookup.c'; else $(CYGPATH_W) '$(srcdir)/nslookup.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nslookup-nslookup.Tpo $(DEPDIR)/nslookup-nslookup.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nslookup.c' object='nslookup-nslookup.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(nslookup_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nslookup-nslookup.obj `if test -f 'nslookup.c'; then $(CYGPATH_W) 'nslookup.c'; else $(CYGPATH_W) '$(srcdir)/nslookup.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/dig.Po + -rm -f ./$(DEPDIR)/dighost.Plo + -rm -f ./$(DEPDIR)/host.Po + -rm -f ./$(DEPDIR)/nslookup-nslookup.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/dig.Po + -rm -f ./$(DEPDIR)/dighost.Plo + -rm -f ./$(DEPDIR)/host.Po + -rm -f ./$(DEPDIR)/nslookup-nslookup.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-binPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am test-am test-local uninstall uninstall-am \ + uninstall-binPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/dig/dig.c b/bin/dig/dig.c new file mode 100644 index 0000000..921b092 --- /dev/null +++ b/bin/dig/dig.c @@ -0,0 +1,3446 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dighost.h" + +#define ADD_STRING(b, s) \ + { \ + if (strlen(s) >= isc_buffer_availablelength(b)) { \ + return ((((ISC_R_NOSPACE)))); \ + } else { \ + isc_buffer_putstr(b, s); \ + } \ + } + +#define DIG_MAX_ADDRESSES 20 + +dig_lookup_t *default_lookup = NULL; + +static char *batchname = NULL; +static FILE *batchfp = NULL; +static char *argv0; +static int addresscount = 0; + +static char domainopt[DNS_NAME_MAXTEXT]; +static char hexcookie[81]; + +static bool short_form = false, printcmd = true, plusquest = false, + pluscomm = false, ipv4only = false, ipv6only = false, digrc = true; +static uint32_t splitwidth = 0xffffffff; + +/*% opcode text */ +static const char *const opcodetext[] = { + "QUERY", "IQUERY", "STATUS", "RESERVED3", + "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7", + "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11", + "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15" +}; + +static const char * +rcode_totext(dns_rcode_t rcode) { + static char buf[64]; + isc_buffer_t b; + isc_result_t result; + + memset(buf, 0, sizeof(buf)); + isc_buffer_init(&b, buf + 1, sizeof(buf) - 2); + result = dns_rcode_totext(rcode, &b); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (strspn(buf + 1, "0123456789") == strlen(buf + 1)) { + buf[0] = '?'; + return buf; + } + return buf + 1; +} + +/*% print usage */ +static void +print_usage(FILE *fp) { + fprintf(fp, + "Usage: dig [@global-server] [domain] [q-type] [q-class] " + "{q-opt}\n" + " {global-d-opt} host [@local-server] " + "{local-d-opt}\n" + " [ host [@local-server] {local-d-opt} [...]]\n"); +} + +#if TARGET_OS_IPHONE +static void +usage(void) { + fprintf(stderr, "Press for complete list of options\n"); +} +#else /* if TARGET_OS_IPHONE */ +noreturn static void +usage(void); + +static void +usage(void) { + print_usage(stderr); + fprintf(stderr, "\nUse \"dig -h\" (or \"dig -h | more\") " + "for complete list of options\n"); + exit(EXIT_FAILURE); +} +#endif /* if TARGET_OS_IPHONE */ + +/*% help */ +static void +help(void) { + print_usage(stdout); + printf("Where: domain is in the Domain Name System\n" + " q-class is one of (in,hs,ch,...) [default: in]\n" + " q-type is one of " + "(a,any,mx,ns,soa,hinfo,axfr,txt,...) " + "[default:a]\n" + " (Use ixfr=version for type ixfr)\n" + " q-opt is one of:\n" + " -4 (use IPv4 query transport " + "only)\n" + " -6 (use IPv6 query transport " + "only)\n" + " -b address[#port] (bind to source " + "address/port)\n" + " -c class (specify query class)\n" + " -f filename (batch mode)\n" + " -k keyfile (specify tsig key file)\n" + " -m (enable memory usage " + "debugging)\n" + " -p port (specify port number)\n" + " -q name (specify query name)\n" + " -r (do not read ~/.digrc)\n" + " -t type (specify query type)\n" + " -u (display times in usec " + "instead of msec)\n" + " -x dot-notation (shortcut for reverse " + "lookups)\n" + " -y [hmac:]name:key (specify named base64 " + "tsig " + "key)\n" + " d-opt is of the form +keyword[=value], where " + "keyword " + "is:\n" + " +[no]aaflag (Set AA flag in query " + "(+[no]aaflag))\n" + " +[no]aaonly (Set AA flag in query " + "(+[no]aaflag))\n" + " +[no]additional (Control display of " + "additional section)\n" + " +[no]adflag (Set AD flag in query " + "(default on))\n" + " +[no]all (Set or clear all display " + "flags)\n" + " +[no]answer (Control display of " + "answer " + "section)\n" + " +[no]authority (Control display of " + "authority section)\n" + " +[no]badcookie (Retry BADCOOKIE " + "responses)\n" + " +[no]besteffort (Try to parse even " + "illegal " + "messages)\n" + " +bufsize[=###] (Set EDNS0 Max UDP packet " + "size)\n" + " +[no]cdflag (Set checking disabled " + "flag in query)\n" + " +[no]class (Control display of class " + "in records)\n" + " +[no]cmd (Control display of " + "command line -\n" + " global option)\n" + " +[no]comments (Control display of " + "packet " + "header\n" + " and section name " + "comments)\n" + " +[no]cookie (Add a COOKIE option to " + "the request)\n" + " +[no]crypto (Control display of " + "cryptographic\n" + " fields in records)\n" + " +[no]defname (Use search list " + "(+[no]search))\n" + " +[no]dns64prefix (Get the DNS64 prefixes " + "from ipv4only.arpa)\n" + " +[no]dnssec (Request DNSSEC records)\n" + " +domain=### (Set default domainname)\n" + " +[no]edns[=###] (Set EDNS version) [0]\n" + " +ednsflags=### (Set EDNS flag bits)\n" + " +[no]ednsnegotiation (Set EDNS version " + "negotiation)\n" + " +ednsopt=###[:value] (Send specified EDNS " + "option)\n" + " +noednsopt (Clear list of +ednsopt " + "options)\n" + " +[no]expandaaaa (Expand AAAA records)\n" + " +[no]expire (Request time to expire)\n" + " +[no]fail (Don't try next server on " + "SERVFAIL)\n" + " +[no]header-only (Send query without a " + "question section)\n" + " +[no]https[=###] (DNS-over-HTTPS mode) " + "[/]\n" + " +[no]https-get (Use GET instead of " + "default POST method while using HTTPS)\n" + " +[no]http-plain[=###] (DNS over plain HTTP " + "mode) " + "[/]\n" + " +[no]http-plain-get (Use GET instead of " + "default POST method while using plain HTTP)\n" + " +[no]identify (ID responders in short " + "answers)\n" +#ifdef HAVE_LIBIDN2 + " +[no]idn (convert international " + "domain names)\n" +#endif /* ifdef HAVE_LIBIDN2 */ + " +[no]ignore (Don't revert to TCP for " + "TC responses.)\n" + " +[no]keepalive (Request EDNS TCP " + "keepalive)\n" + " +[no]keepopen (Keep the TCP socket open " + "between " + "queries)\n" + " +[no]multiline (Print records in an " + "expanded format)\n" + " +ndots=### (Set search NDOTS value)\n" + " +[no]nsid (Request Name Server ID)\n" + " +[no]nssearch (Search all authoritative " + "nameservers)\n" + " +[no]onesoa (AXFR prints only one soa " + "record)\n" + " +[no]opcode=### (Set the opcode of the " + "request)\n" + " +padding=### (Set padding block size " + "[0])\n" + " " + "+[no]proxy[=src_addr[#src_port]-dst_addr[#dst_port]] " + "(Add PROXYv2 headers to the queries. If addresses are omitted, " + "LOCAL PROXYv2 headers are added)\n" + " " + "+[no]proxy-plain[=src_addr[#src_port]-dst_addr[#dst_port]] " + "(The same as '+[no]proxy', but send PROXYv2 headers ahead of " + "any encryption if an encrypted transport is used)\n" + " +qid=### (Specify the query ID to " + "use when sending queries)\n" + " +[no]qr (Print question before " + "sending)\n" + " +[no]question (Control display of " + "question section)\n" + " +[no]raflag (Set RA flag in query " + "(+[no]raflag))\n" + " +[no]rdflag (Recursive mode " + "(+[no]recurse))\n" + " +[no]recurse (Recursive mode " + "(+[no]rdflag))\n" + " +retry=### (Set number of UDP " + "retries) [2]\n" + " +[no]rrcomments (Control display of " + "per-record " + "comments)\n" + " +[no]search (Set whether to use " + "searchlist)\n" + " +[no]short (Display nothing except " + "short\n" + " form of answers - global " + "option)\n" + " +[no]showbadcookie (Show BADCOOKIE message)\n" + " +[no]showbadvers (Show BADVERS message)\n" + " +[no]showsearch (Search with intermediate " + "results)\n" + " +[no]split=## (Split hex/base64 fields " + "into chunks)\n" + " +[no]stats (Control display of " + "statistics)\n" + " +subnet=addr (Set edns-client-subnet " + "option)\n" + " +[no]tcflag (Set TC flag in query " + "(+[no]tcflag))\n" + " +[no]tcp (TCP mode (+[no]vc))\n" + " +timeout=### (Set query timeout) [5]\n" + " +[no]tls (DNS-over-TLS mode)\n" + " +[no]tls-ca[=file] (Enable remote server's " + "TLS certificate validation)\n" + " +[no]tls-hostname=hostname (Explicitly set " + "the expected TLS hostname)\n" + " +[no]tls-certfile=file (Load client TLS " + "certificate chain from file)\n" + " +[no]tls-keyfile=file (Load client TLS " + "private key from file)\n" + " +[no]trace (Trace delegation down " + "from root [implies +dnssec])\n" + " +tries=### (Set number of UDP " + "attempts) [3]\n" + " +[no]ttlid (Control display of ttls " + "in records)\n" + " +[no]ttlunits (Display TTLs in " + "human-readable units)\n" + " +[no]unknownformat (Print RDATA in RFC 3597 " + "\"unknown\" " + "format)\n" + " +[no]vc (TCP mode (+[no]tcp))\n" + " +[no]yaml (Present the results as " + "YAML)\n" + " +[no]zflag (Set Z flag in query)\n" + " global d-opts and servers (before host name) affect " + "all " + "queries.\n" + " local d-opts and servers (after host name) affect only " + "that lookup.\n" + " -h (print help and exit)\n" + " -v (print version " + "and exit)\n"); +} + +/*% + * Callback from dighost.c to print the received message. + */ +static void +received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) { + uint64_t diff; + time_t tnow; + struct tm tmnow; + char time_str[100]; + char fromtext[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(from, fromtext, sizeof(fromtext)); + + if (short_form || yaml) { + return; + } + + if (query->lookup->stats) { + const char *proto; + diff = isc_time_microdiff(&query->time_recv, &query->time_sent); + if (query->lookup->use_usec) { + printf(";; Query time: %ld usec\n", (long)diff); + } else { + printf(";; Query time: %ld msec\n", (long)diff / 1000); + } + if (dig_lookup_is_tls(query->lookup)) { + proto = "TLS"; + } else if (query->lookup->https_mode) { + if (query->lookup->http_plain) { + proto = query->lookup->https_get ? "HTTP-GET" + : "HTTP"; + } else { + proto = query->lookup->https_get ? "HTTPS-GET" + : "HTTPS"; + } + } else if (query->lookup->tcp_mode) { + proto = "TCP"; + } else { + proto = "UDP"; + } + printf(";; SERVER: %s(%s) (%s)\n", fromtext, query->userarg, + proto); + + if (query->lookup->proxy_mode) { + printf(";; CLIENT PROXY HEADER"); + + if ((dig_lookup_is_tls(query->lookup) || + (query->lookup->https_mode && + !query->lookup->http_plain)) && + query->lookup->proxy_plain) + { + printf(" (plain)"); + } + + printf(": "); + + if (!query->lookup->proxy_local) { + char src_buf[ISC_SOCKADDR_FORMATSIZE] = { 0 }; + char dst_buf[ISC_SOCKADDR_FORMATSIZE] = { 0 }; + + isc_sockaddr_format( + &query->lookup->proxy_src_addr, src_buf, + sizeof(src_buf)); + + isc_sockaddr_format( + &query->lookup->proxy_dst_addr, dst_buf, + sizeof(dst_buf)); + printf("source: %s, destination: %s", src_buf, + dst_buf); + } else { + printf("LOCAL"); + } + + printf("\n"); + } + time(&tnow); + (void)localtime_r(&tnow, &tmnow); + + if (strftime(time_str, sizeof(time_str), + "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) + { + printf(";; WHEN: %s\n", time_str); + } + if (query->lookup->doing_xfr) { + printf(";; XFR size: %u records (messages %u, " + "bytes %" PRIu64 ")\n", + query->rr_count, query->msg_count, + query->byte_count); + } else { + printf(";; MSG SIZE rcvd: %u\n", bytes); + } + if (tsigkey != NULL) { + if (!validated) { + puts(";; WARNING -- Some TSIG could not " + "be validated"); + } + } + if ((tsigkey == NULL) && (keysecret[0] != 0)) { + puts(";; WARNING -- TSIG key was not used."); + } + puts(""); + } else if (query->lookup->identify) { + diff = isc_time_microdiff(&query->time_recv, &query->time_sent); + if (query->lookup->use_usec) { + printf(";; Received %" PRIu64 " bytes " + "from %s(%s) in %ld us\n\n", + query->lookup->doing_xfr ? query->byte_count + : (uint64_t)bytes, + fromtext, query->userarg, (long)diff); + } else { + printf(";; Received %" PRIu64 " bytes " + "from %s(%s) in %ld ms\n\n", + query->lookup->doing_xfr ? query->byte_count + : (uint64_t)bytes, + fromtext, query->userarg, (long)diff / 1000); + } + } +} + +/* + * Callback from dighost.c to print that it is trying a server. + * Not used in dig. + * XXX print_trying + */ +static void +trying(char *frm, dig_lookup_t *lookup) { + UNUSED(frm); + UNUSED(lookup); +} + +/*% + * Internal print routine used to print short form replies. + */ +static isc_result_t +say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) { + isc_result_t result; + uint64_t diff; + char store[sizeof(" in 18446744073709551616 us.")]; + unsigned int styleflags = 0; + + if (query->lookup->trace || query->lookup->ns_search_only) { + result = dns_rdatatype_totext(rdata->type, buf); + if (result != ISC_R_SUCCESS) { + return result; + } + ADD_STRING(buf, " "); + } + + /* Turn on rrcomments if explicitly enabled */ + if (query->lookup->rrcomments > 0) { + styleflags |= DNS_STYLEFLAG_RRCOMMENT; + } + if (query->lookup->nocrypto) { + styleflags |= DNS_STYLEFLAG_NOCRYPTO; + } + if (query->lookup->print_unknown_format) { + styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; + } + if (query->lookup->expandaaaa) { + styleflags |= DNS_STYLEFLAG_EXPANDAAAA; + } + result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0, splitwidth, + " ", buf); + if (result == ISC_R_NOSPACE) { + return result; + } + check_result(result, "dns_rdata_totext"); + if (query->lookup->identify) { + diff = isc_time_microdiff(&query->time_recv, &query->time_sent); + ADD_STRING(buf, " from server "); + ADD_STRING(buf, query->servname); + if (query->lookup->use_usec) { + snprintf(store, sizeof(store), " in %" PRIu64 " us.", + diff); + } else { + snprintf(store, sizeof(store), " in %" PRIu64 " ms.", + diff / 1000); + } + ADD_STRING(buf, store); + } + ADD_STRING(buf, "\n"); + return ISC_R_SUCCESS; +} + +/*% + * short_form message print handler. Calls above say_message() + */ +static isc_result_t +dns64prefix_answer(dns_message_t *msg, isc_buffer_t *buf) { + dns_rdataset_t *rdataset = NULL; + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + isc_netprefix_t prefix[10]; + size_t i, count = 10; + + name = dns_fixedname_initname(&fixed); + result = dns_name_fromstring(name, "ipv4only.arpa", dns_rootname, 0, + NULL); + check_result(result, "dns_name_fromstring"); + + result = dns_message_findname(msg, DNS_SECTION_ANSWER, name, + dns_rdatatype_aaaa, dns_rdatatype_none, + NULL, &rdataset); + if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_dns64_findprefix(rdataset, prefix, &count); + if (result == ISC_R_NOTFOUND) { + return ISC_R_SUCCESS; + } + if (count > 10) { + count = 10; + } + for (i = 0; i < count; i++) { + result = isc_netaddr_totext(&prefix[i].addr, buf); + if (result != ISC_R_SUCCESS) { + return result; + } + result = isc_buffer_printf(buf, "/%u\n", prefix[i].prefixlen); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + return ISC_R_SUCCESS; +} + +/*% + * short_form message print handler. Calls above say_message() + */ +static isc_result_t +short_answer(dns_message_t *msg, dns_messagetextflag_t flags, isc_buffer_t *buf, + dig_query_t *query) { + dns_name_t *name; + dns_rdataset_t *rdataset; + isc_result_t result, loopresult; + dns_name_t empty_name; + dns_rdata_t rdata = DNS_RDATA_INIT; + + UNUSED(flags); + + dns_name_init(&empty_name, NULL); + result = dns_message_firstname(msg, DNS_SECTION_ANSWER); + if (result == ISC_R_NOMORE) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + return result; + } + + for (;;) { + name = NULL; + dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); + + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + loopresult = dns_rdataset_first(rdataset); + while (loopresult == ISC_R_SUCCESS) { + dns_rdataset_current(rdataset, &rdata); + result = say_message(&rdata, query, buf); + if (result == ISC_R_NOSPACE) { + return result; + } + check_result(result, "say_message"); + loopresult = dns_rdataset_next(rdataset); + dns_rdata_reset(&rdata); + } + } + result = dns_message_nextname(msg, DNS_SECTION_ANSWER); + if (result == ISC_R_NOMORE) { + break; + } else if (result != ISC_R_SUCCESS) { + return result; + } + } + + return ISC_R_SUCCESS; +} + +static bool +isdotlocal(dns_message_t *msg) { + isc_result_t result; + static unsigned char local_ndata[] = { "\005local" }; + static unsigned char local_offsets[] = { 0, 6 }; + static dns_name_t local = DNS_NAME_INITABSOLUTE(local_ndata, + local_offsets); + + for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); + result == ISC_R_SUCCESS; + result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) + { + dns_name_t *name = NULL; + dns_message_currentname(msg, DNS_SECTION_QUESTION, &name); + if (dns_name_issubdomain(name, &local)) { + return true; + } + } + return false; +} + +/* + * Callback from dighost.c to print the reply from a server + */ +static isc_result_t +printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg, + bool headers) { + isc_result_t result; + dns_messagetextflag_t flags; + isc_buffer_t *buf = NULL; + unsigned int len = OUTPUTBUF; + dns_master_style_t *style = NULL; + unsigned int styleflags = 0; + bool isquery = (msg == query->lookup->sendmsg); + bool dns64prefix = query->lookup->dns64prefix; + + UNUSED(msgbuf); + + dig_idnsetup(query->lookup, true); + + styleflags |= DNS_STYLEFLAG_REL_OWNER; + if (yaml) { + msg->indent.string = " "; + msg->indent.count = 3; + styleflags |= DNS_STYLEFLAG_YAML; + } else { + if (query->lookup->comments) { + styleflags |= DNS_STYLEFLAG_COMMENT; + } + if (query->lookup->print_unknown_format) { + styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT; + } + /* Turn on rrcomments if explicitly enabled */ + if (query->lookup->rrcomments > 0) { + styleflags |= DNS_STYLEFLAG_RRCOMMENT; + } + if (query->lookup->ttlunits) { + styleflags |= DNS_STYLEFLAG_TTL_UNITS; + } + if (query->lookup->nottl) { + styleflags |= DNS_STYLEFLAG_NO_TTL; + } + if (query->lookup->noclass) { + styleflags |= DNS_STYLEFLAG_NO_CLASS; + } + if (query->lookup->nocrypto) { + styleflags |= DNS_STYLEFLAG_NOCRYPTO; + } + if (query->lookup->expandaaaa) { + styleflags |= DNS_STYLEFLAG_EXPANDAAAA; + } + if (query->lookup->multiline) { + styleflags |= DNS_STYLEFLAG_OMIT_OWNER; + styleflags |= DNS_STYLEFLAG_OMIT_CLASS; + styleflags |= DNS_STYLEFLAG_REL_DATA; + styleflags |= DNS_STYLEFLAG_OMIT_TTL; + styleflags |= DNS_STYLEFLAG_TTL; + styleflags |= DNS_STYLEFLAG_MULTILINE; + /* Turn on rrcomments unless explicitly disabled */ + if (query->lookup->rrcomments >= 0) { + styleflags |= DNS_STYLEFLAG_RRCOMMENT; + } + } + } + if (query->lookup->multiline || + (query->lookup->nottl && query->lookup->noclass)) + { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 24, + 32, 80, 8, splitwidth, mctx); + } else if (query->lookup->nottl || query->lookup->noclass) { + result = dns_master_stylecreate(&style, styleflags, 24, 24, 32, + 40, 80, 8, splitwidth, mctx); + } else { + result = dns_master_stylecreate(&style, styleflags, 24, 32, 40, + 48, 80, 8, splitwidth, mctx); + } + check_result(result, "dns_master_stylecreate"); + + if (query->lookup->cmdline[0] != 0) { + if (!short_form && !dns64prefix && printcmd) { + printf("%s", query->lookup->cmdline); + } + query->lookup->cmdline[0] = '\0'; + } + debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders", + query->lookup->comments ? "comments" : "nocomments", + short_form ? "short_form" + : dns64prefix ? "dns64prefix_form" + : "long_form"); + + flags = 0; + if (!headers) { + flags |= DNS_MESSAGETEXTFLAG_NOHEADERS; + flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; + } + if (query->lookup->onesoa && + query->lookup->rdtype == dns_rdatatype_axfr) + { + flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA + : DNS_MESSAGETEXTFLAG_OMITSOA; + } + if (!query->lookup->comments) { + flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS; + } + + isc_buffer_allocate(mctx, &buf, len); + + if (yaml) { + enum { Q = 0x1, R = 0x2 }; /* Q:query; R:ecursive */ + unsigned int tflag = 0; + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + uint16_t sport; + char *hash; + int pf; + + printf("- type: MESSAGE\n"); + printf(" message:\n"); + + if (isquery) { + tflag |= Q; + if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { + tflag |= R; + } + } else if (((msg->flags & DNS_MESSAGEFLAG_RD) != 0) && + ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)) + { + tflag |= R; + } + + if (tflag == (Q | R)) { + printf(" type: RECURSIVE_QUERY\n"); + } else if (tflag == Q) { + printf(" type: AUTH_QUERY\n"); + } else if (tflag == R) { + printf(" type: RECURSIVE_RESPONSE\n"); + } else { + printf(" type: AUTH_RESPONSE\n"); + } + + if (!isc_time_isepoch(&query->time_sent)) { + char tbuf[100]; + if (query->lookup->use_usec) { + isc_time_formatISO8601us(&query->time_sent, + tbuf, sizeof(tbuf)); + } else { + isc_time_formatISO8601ms(&query->time_sent, + tbuf, sizeof(tbuf)); + } + printf(" query_time: !!timestamp %s\n", tbuf); + } + + if (!isquery && !isc_time_isepoch(&query->time_recv)) { + char tbuf[100]; + if (query->lookup->use_usec) { + isc_time_formatISO8601us(&query->time_recv, + tbuf, sizeof(tbuf)); + } else { + isc_time_formatISO8601ms(&query->time_recv, + tbuf, sizeof(tbuf)); + } + printf(" response_time: !!timestamp %s\n", tbuf); + } + + printf(" message_size: %ub\n", + isc_buffer_usedlength(msgbuf)); + + pf = isc_sockaddr_pf(&query->sockaddr); + if (pf == PF_INET || pf == PF_INET6) { + printf(" socket_family: %s\n", + pf == PF_INET ? "INET" : "INET6"); + + printf(" socket_protocol: %s\n", + query->lookup->tcp_mode ? "TCP" : "UDP"); + + sport = isc_sockaddr_getport(&query->sockaddr); + isc_sockaddr_format(&query->sockaddr, sockstr, + sizeof(sockstr)); + hash = strchr(sockstr, '#'); + if (hash != NULL) { + *hash = '\0'; + } + if (strcmp(sockstr, "::") == 0) { + strlcat(sockstr, "0", sizeof(sockstr)); + } + + printf(" response_address: \"%s\"\n", sockstr); + printf(" response_port: %u\n", sport); + } + + if (query->handle != NULL) { + isc_sockaddr_t saddr = + isc_nmhandle_localaddr(query->handle); + sport = isc_sockaddr_getport(&saddr); + isc_sockaddr_format(&saddr, sockstr, sizeof(sockstr)); + hash = strchr(sockstr, '#'); + if (hash != NULL) { + *hash = '\0'; + } + if (strcmp(sockstr, "::") == 0) { + strlcat(sockstr, "0", sizeof(sockstr)); + } + + printf(" query_address: \"%s\"\n", sockstr); + printf(" query_port: %u\n", sport); + } + + printf(" %s:\n", isquery ? "query_message_data" + : "response_message_data"); + result = dns_message_headertotext(msg, style, flags, buf); + } else if (query->lookup->comments && !short_form && !dns64prefix) { + if (query->lookup->cmdline[0] != '\0' && printcmd) { + printf("; %s\n", query->lookup->cmdline); + } + if (msg == query->lookup->sendmsg) { + printf(";; Sending:\n"); + } else { + printf(";; Got answer:\n"); + } + + if (headers) { + if (isdotlocal(msg)) { + printf(";; WARNING: .local is reserved for " + "Multicast DNS\n;; You are currently " + "testing what happens when an mDNS " + "query is leaked to DNS\n"); + } + printf(";; ->>HEADER<<- opcode: %s, status: %s, " + "id: %u\n", + opcodetext[msg->opcode], + rcode_totext(msg->rcode), msg->id); + printf(";; flags:"); + if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { + printf(" qr"); + } + if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { + printf(" aa"); + } + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { + printf(" tc"); + } + if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { + printf(" rd"); + } + if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { + printf(" ra"); + } + if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { + printf(" ad"); + } + if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { + printf(" cd"); + } + if ((msg->flags & 0x0040U) != 0) { + printf("; MBZ: 0x4"); + } + + printf("; QUERY: %u, ANSWER: %u, " + "AUTHORITY: %u, ADDITIONAL: %u\n", + msg->counts[DNS_SECTION_QUESTION], + msg->counts[DNS_SECTION_ANSWER], + msg->counts[DNS_SECTION_AUTHORITY], + msg->counts[DNS_SECTION_ADDITIONAL]); + + if (msg != query->lookup->sendmsg && + (msg->flags & DNS_MESSAGEFLAG_RD) != 0 && + (msg->flags & DNS_MESSAGEFLAG_RA) == 0) + { + printf(";; WARNING: recursion requested " + "but not available\n"); + } + } + if (msg != query->lookup->sendmsg && + query->lookup->edns != -1 && msg->opt == NULL && + (msg->rcode == dns_rcode_formerr || + msg->rcode == dns_rcode_notimp)) + { + printf("\n;; WARNING: EDNS query returned status " + "%s - retry with '%s+noedns'\n", + rcode_totext(msg->rcode), + query->lookup->dnssec ? "+nodnssec " : ""); + } + if (msg != query->lookup->sendmsg && extrabytes != 0U) { + printf(";; WARNING: Message has %u extra byte%s at " + "end\n", + extrabytes, extrabytes != 0 ? "s" : ""); + } + } + +repopulate_buffer: + + if (query->lookup->comments && headers && !short_form && !dns64prefix) { + result = dns_message_pseudosectiontotext( + msg, DNS_PSEUDOSECTION_OPT, style, flags, buf); + if (result == ISC_R_NOSPACE) { + buftoosmall: + len += OUTPUTBUF; + isc_buffer_free(&buf); + isc_buffer_allocate(mctx, &buf, len); + goto repopulate_buffer; + } + check_result(result, "dns_message_pseudosectiontotext"); + } + + if (query->lookup->section_question && headers) { + if (!short_form && !dns64prefix) { + result = dns_message_sectiontotext( + msg, DNS_SECTION_QUESTION, style, flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_sectiontotext"); + } + } + if (query->lookup->section_answer) { + if (!short_form && !dns64prefix) { + result = dns_message_sectiontotext( + msg, DNS_SECTION_ANSWER, style, flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_sectiontotext"); + } else if (dns64prefix) { + result = dns64prefix_answer(msg, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns64prefix_answer"); + } else { + result = short_answer(msg, flags, buf, query); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "short_answer"); + } + } + if (query->lookup->section_authority) { + if (!short_form && !dns64prefix) { + result = dns_message_sectiontotext( + msg, DNS_SECTION_AUTHORITY, style, flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_sectiontotext"); + } + } + if (query->lookup->section_additional) { + if (!short_form && !dns64prefix) { + result = dns_message_sectiontotext( + msg, DNS_SECTION_ADDITIONAL, style, flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_sectiontotext"); + /* + * Only print the signature on the first record. + */ + if (headers) { + result = dns_message_pseudosectiontotext( + msg, DNS_PSEUDOSECTION_TSIG, style, + flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_" + "pseudosectiontotext"); + result = dns_message_pseudosectiontotext( + msg, DNS_PSEUDOSECTION_SIG0, style, + flags, buf); + if (result == ISC_R_NOSPACE) { + goto buftoosmall; + } + check_result(result, "dns_message_" + "pseudosectiontotext"); + } + } + } + + if (headers && query->lookup->comments && !short_form && !yaml) { + printf("\n"); + } + + printf("%.*s", (int)isc_buffer_usedlength(buf), + (char *)isc_buffer_base(buf)); + isc_buffer_free(&buf); + + if (style != NULL) { + dns_master_styledestroy(&style, mctx); + } + + dig_idnsetup(query->lookup, false); + + return result; +} + +/*% + * print the greeting message when the program first starts up. + */ +static void +printgreeting(int argc, char **argv, dig_lookup_t *lookup) { + int i; + static bool first = true; + char append[MXNAME]; + + if (printcmd) { + snprintf(lookup->cmdline, sizeof(lookup->cmdline), + "%s; <<>> DiG %s <<>>", first ? "\n" : "", + PACKAGE_VERSION); + i = 1; + while (i < argc) { + snprintf(append, sizeof(append), " %s", argv[i++]); + strlcat(lookup->cmdline, append, + sizeof(lookup->cmdline)); + } + strlcat(lookup->cmdline, "\n", sizeof(lookup->cmdline)); + if (first && addresscount != 0) { + snprintf(append, sizeof(append), + "; (%d server%s found)\n", addresscount, + addresscount > 1 ? "s" : ""); + strlcat(lookup->cmdline, append, + sizeof(lookup->cmdline)); + } + if (first) { + snprintf(append, sizeof(append), + ";; global options:%s%s\n", + short_form ? " +short" : "", + printcmd ? " +cmd" : ""); + first = false; + strlcat(lookup->cmdline, append, + sizeof(lookup->cmdline)); + } + } +} + +#define FULLCHECK(A) \ + do { \ + size_t _l = strlen(cmd); \ + if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ + goto invalid_option; \ + } while (0) +#define FULLCHECK2(A, B) \ + do { \ + size_t _l = strlen(cmd); \ + if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ + (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ + goto invalid_option; \ + } while (0) +#define FULLCHECK6(A, B, C, D, E, F) \ + do { \ + size_t _l = strlen(cmd); \ + if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ + (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0) && \ + (_l >= sizeof(C) || strncasecmp(cmd, C, _l) != 0) && \ + (_l >= sizeof(D) || strncasecmp(cmd, D, _l) != 0) && \ + (_l >= sizeof(E) || strncasecmp(cmd, E, _l) != 0) && \ + (_l >= sizeof(F) || strncasecmp(cmd, F, _l) != 0)) \ + goto invalid_option; \ + } while (0) + +/* + * Parse source and destination addresses in the same format as used by "kdig": + * + * SRC_ADDR[#SRC_PORT]-DST_ADDR[#DST_PORT] + * + * This can be described (pretty closely for our purpose) using the + * following EBNF grammar: + * + * S = proxy-addrs. (* start rule *) + * proxy-addrs = addr "-" addr EOF. + * addr = addr-char { addr-char } ["#" port ]. + * port = digit { digit }. + * addr-char = . + * EOF = '\0'. + */ +#define MATCH(ch) (st->str[0] == (ch)) +#define MATCH_DIGIT() isdigit((unsigned char)(st->str[0])) +#define ADVANCE() st->str++ +#define GETP() (st->str) + +typedef struct isc_proxy_addrs_parser_state { + const char *str; + + const char *last_addr_start; + size_t last_addr_len; + + const char *last_port_start; + size_t last_port_len; + + const char *src_addr_start; + size_t src_addr_len; + + const char *src_port_start; + size_t src_port_len; + + const char *dst_addr_start; + size_t dst_addr_len; + + const char *dst_port_start; + size_t dst_port_len; +} isc_proxy_addrs_parser_state_t; + +static bool +rule_proxy_addrs(isc_proxy_addrs_parser_state_t *st); + +static bool +rule_addr(isc_proxy_addrs_parser_state_t *st); + +static bool +rule_port(isc_proxy_addrs_parser_state_t *st); + +static bool +rule_addr_char(isc_proxy_addrs_parser_state_t *st); + +static void +proxy_handle_port_string(const char *port_start, const size_t port_len, + in_port_t *pport) { + char buf[512] = { 0 }; /* max */ + size_t string_size = 0, max_string_bytes = 0; + unsigned int tmp; + isc_result_t result; + + string_size = port_len + 1; + max_string_bytes = string_size > sizeof(buf) ? sizeof(buf) + : string_size; + + (void)strlcpy(buf, port_start, max_string_bytes); + result = parse_uint(&tmp, buf, MAXPORT, "port number"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + *pport = tmp; +} + +static isc_result_t +proxy_handle_addr_string(const char *addr_start, const size_t addr_len, + const in_port_t addr_port, isc_sockaddr_t *addr) { + isc_result_t result = ISC_R_FAILURE; + char buf[512] = { 0 }; /* max */ + size_t string_size = 0, max_string_bytes = 0; + struct in_addr ipv4 = { 0 }; + struct in6_addr ipv6 = { 0 }; + int ret = 0; + + string_size = addr_len + 1; + max_string_bytes = string_size > sizeof(buf) ? sizeof(buf) + : string_size; + + (void)strlcpy(buf, addr_start, max_string_bytes); + + ret = inet_pton(AF_INET, buf, &ipv4); + if (ret == 1) { + isc_sockaddr_fromin(addr, &ipv4, addr_port); + result = ISC_R_SUCCESS; + } else { + ret = inet_pton(AF_INET6, buf, &ipv6); + if (ret == 1) { + isc_sockaddr_fromin6(addr, &ipv6, addr_port); + result = ISC_R_SUCCESS; + } + } + + return result; +} + +static bool +parse_proxy_addresses(const char *addrs, isc_sockaddr_t *psrc, + isc_sockaddr_t *pdst) { + isc_result_t result = ISC_R_FAILURE; + isc_sockaddr_t src = { 0 }, dst = { 0 }; + isc_proxy_addrs_parser_state_t st = { 0 }; + in_port_t src_port = 0, dst_port = 53; /* Follow kdig footsteps */ + + REQUIRE(addrs != NULL && *addrs != '\0'); + REQUIRE(psrc != NULL); + REQUIRE(pdst != NULL); + + st.str = addrs; + + /* start syntax analysis and verification */ + if (!rule_proxy_addrs(&st)) { + warn("PROXY source and destination addresses cannot be parsed"); + return false; + } + + /* get port numeric values */ + if (st.src_port_len > 0) { + INSIST(st.src_port_start != NULL); + proxy_handle_port_string(st.src_port_start, st.src_port_len, + &src_port); + } + + if (st.dst_port_len > 0) { + INSIST(st.dst_port_start != NULL); + proxy_handle_port_string(st.dst_port_start, st.dst_port_len, + &dst_port); + } + + /* get addresses */ + INSIST(st.src_addr_len > 0); + INSIST(st.src_addr_start != NULL); + INSIST(st.dst_addr_len > 0); + INSIST(st.dst_addr_start != NULL); + + result = proxy_handle_addr_string(st.src_addr_start, st.src_addr_len, + src_port, &src); + if (result != ISC_R_SUCCESS) { + warn("Cannot get PROXY source address: %s", + isc_result_totext(result)); + return false; + } + + result = proxy_handle_addr_string(st.dst_addr_start, st.dst_addr_len, + dst_port, &dst); + if (result != ISC_R_SUCCESS) { + warn("Cannot get PROXY destination address: %s", + isc_result_totext(result)); + return false; + } + + /* addresses should be of the same type */ + if (isc_sockaddr_pf(&src) != isc_sockaddr_pf(&dst)) { + warn("PROXY source and destination addresses must be of the " + "same type"); + return false; + } + + *psrc = src; + *pdst = dst; + + return true; +} + +static bool +rule_proxy_addrs(isc_proxy_addrs_parser_state_t *st) { + if (!rule_addr(st)) { + return false; + } + + st->src_addr_start = st->last_addr_start; + st->src_addr_len = st->last_addr_len; + st->src_port_start = st->last_port_start; + st->src_port_len = st->last_port_len; + + if (!MATCH('-')) { + return false; + } + + ADVANCE(); + + if (!rule_addr(st)) { + return false; + } + + st->dst_addr_start = st->last_addr_start; + st->dst_addr_len = st->last_addr_len; + st->dst_port_start = st->last_port_start; + st->dst_port_len = st->last_port_len; + + if (!MATCH('\0')) { + return false; + } + + return true; +} + +static bool +rule_addr(isc_proxy_addrs_parser_state_t *st) { + const char *start = GETP(); + if (!rule_addr_char(st)) { + return false; + } + + while (rule_addr_char(st)) { + /* skip */ + } + + st->last_addr_start = start; + st->last_addr_len = GETP() - start; + + if (MATCH('#')) { + ADVANCE(); + + if (!rule_port(st)) { + return false; + } + } + + return true; +} + +static bool +rule_port(isc_proxy_addrs_parser_state_t *st) { + const char *start = GETP(); + if (!MATCH_DIGIT()) { + return false; + } + + ADVANCE(); + + while (MATCH_DIGIT()) { + ADVANCE(); + } + + st->last_port_start = start; + st->last_port_len = GETP() - start; + + return true; +} + +static bool +rule_addr_char(isc_proxy_addrs_parser_state_t *st) { + if (MATCH('#') || MATCH('-') || MATCH('\0')) { + return false; + } + + ADVANCE(); + + return true; +} + +#undef GETP +#undef ADVANCE +#undef MATCH_DIGIT +#undef MATCH + +static bool +plus_proxy_handle_addresses(const char *value, const bool state, + dig_lookup_t *lookup) { + lookup->proxy_mode = state; + if (!state) { + /* + * We are not interested in the option value in that + * case + */ + return true; + } + + if (value == NULL || *value == '\0') { + lookup->proxy_local = true; + return true; + } + + if (!parse_proxy_addresses(value, &lookup->proxy_src_addr, + &lookup->proxy_dst_addr)) + { + return false; + } + return true; +} + +static bool +plus_proxy_options(const char *cmd, const char *value, const bool state, + dig_lookup_t *lookup) { + switch (cmd[5]) { + case '-': + FULLCHECK("proxy-plain"); + lookup->proxy_plain = state; + if (!plus_proxy_handle_addresses(value, state, lookup)) { + goto invalid_option; + } + break; + case '\0': + FULLCHECK("proxy"); + if (!plus_proxy_handle_addresses(value, state, lookup)) { + goto invalid_option; + } + break; + default: + goto invalid_option; + } + return true; + +invalid_option: + return false; +} + +static bool +plus_tls_options(const char *cmd, const char *value, const bool state, + dig_lookup_t *lookup) { + /* + * Using TLS implies "TCP-like" mode. + */ + if (!lookup->tcp_mode_set) { + lookup->tcp_mode = state; + } + switch (cmd[3]) { + case '-': + /* + * Assume that if any of the +tls-* options are set, then we + * need to verify the remote certificate (compatibility with + * kdig). + */ + if (state) { + lookup->tls_ca_set = state; + } + switch (cmd[4]) { + case 'c': + switch (cmd[5]) { + case 'a': + FULLCHECK("tls-ca"); + lookup->tls_ca_set = state; + if (state && value != NULL) { + lookup->tls_ca_file = + isc_mem_strdup(mctx, value); + } + break; + case 'e': + FULLCHECK("tls-certfile"); + lookup->tls_cert_file_set = state; + if (state) { + if (value != NULL && *value != '\0') { + lookup->tls_cert_file = + isc_mem_strdup(mctx, + value); + } else { + fprintf(stderr, + ";; TLS certificate " + "file is " + "not specified\n"); + goto invalid_option; + } + } + break; + default: + goto invalid_option; + } + break; + case 'h': + FULLCHECK("tls-hostname"); + lookup->tls_hostname_set = state; + if (state) { + if (value != NULL && *value != '\0') { + lookup->tls_hostname = + isc_mem_strdup(mctx, value); + } else { + fprintf(stderr, ";; TLS hostname is " + "not specified\n"); + goto invalid_option; + } + } + break; + case 'k': + FULLCHECK("tls-keyfile"); + lookup->tls_key_file_set = state; + if (state) { + if (value != NULL && *value != '\0') { + lookup->tls_key_file = + isc_mem_strdup(mctx, value); + } else { + fprintf(stderr, + ";; TLS private key file is " + "not specified\n"); + goto invalid_option; + } + } + break; + default: + goto invalid_option; + } + break; + case '\0': + FULLCHECK("tls"); + lookup->tls_mode = state; + break; + default: + goto invalid_option; + } + + return true; +invalid_option: + return false; +} + +/*% + * We're not using isc_commandline_parse() here since the command line + * syntax of dig is quite a bit different from that which can be described + * by that routine. + * XXX doc options + */ + +static dig_lookup_t * +plus_option(char *option, bool is_batchfile, bool *need_clone, + dig_lookup_t *lookup) { + isc_result_t result; + char *cmd, *value, *last = NULL, *code, *extra; + uint32_t num; + bool state = true; + size_t n; + + INSIST(option != NULL); + + if ((cmd = strtok_r(option, "=", &last)) == NULL) { + printf(";; Invalid option %s\n", option); + return lookup; + } + if (strncasecmp(cmd, "no", 2) == 0) { + cmd += 2; + state = false; + } + /* parse the rest of the string */ + value = strtok_r(NULL, "", &last); + + switch (cmd[0]) { + case 'a': + switch (cmd[1]) { + case 'a': /* aaonly / aaflag */ + FULLCHECK2("aaonly", "aaflag"); + lookup->aaonly = state; + break; + case 'd': + switch (cmd[2]) { + case 'd': /* additional */ + FULLCHECK("additional"); + lookup->section_additional = state; + break; + case 'f': /* adflag */ + case '\0': /* +ad is a synonym for +adflag */ + FULLCHECK("adflag"); + lookup->adflag = state; + break; + default: + goto invalid_option; + } + break; + case 'l': /* all */ + FULLCHECK("all"); + lookup->section_question = state; + lookup->section_authority = state; + lookup->section_answer = state; + lookup->section_additional = state; + lookup->comments = state; + lookup->stats = state; + printcmd = state; + break; + case 'n': /* answer */ + FULLCHECK("answer"); + lookup->section_answer = state; + break; + case 'u': /* authority */ + FULLCHECK("authority"); + lookup->section_authority = state; + break; + default: + goto invalid_option; + } + break; + case 'b': + switch (cmd[1]) { + case 'a': /* badcookie */ + FULLCHECK("badcookie"); + lookup->badcookie = state; + break; + case 'e': /* besteffort */ + FULLCHECK("besteffort"); + lookup->besteffort = state; + break; + case 'u': /* bufsize */ + FULLCHECK("bufsize"); + if (!state) { + goto invalid_option; + } + if (value == NULL) { + lookup->udpsize = DEFAULT_EDNS_BUFSIZE; + break; + } + result = parse_uint(&num, value, COMMSIZE, + "buffer size"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse buffer size"); + goto exit_or_usage; + } + lookup->udpsize = num; + break; + default: + goto invalid_option; + } + break; + case 'c': + switch (cmd[1]) { + case 'd': /* cdflag */ + switch (cmd[2]) { + case 'f': /* cdflag */ + case '\0': /* +cd is a synonym for +cdflag */ + FULLCHECK("cdflag"); + lookup->cdflag = state; + break; + default: + goto invalid_option; + } + break; + case 'l': /* class */ + /* keep +cl for backwards compatibility */ + FULLCHECK2("cl", "class"); + lookup->noclass = !state; + break; + case 'm': /* cmd */ + FULLCHECK("cmd"); + printcmd = state; + break; + case 'o': /* comments */ + switch (cmd[2]) { + case 'm': + FULLCHECK("comments"); + lookup->comments = state; + if (lookup == default_lookup) { + pluscomm = state; + } + break; + case 'o': /* cookie */ + FULLCHECK("cookie"); + if (state && lookup->edns == -1) { + lookup->edns = DEFAULT_EDNS_VERSION; + } + lookup->sendcookie = state; + if (value != NULL) { + n = strlcpy(hexcookie, value, + sizeof(hexcookie)); + if (n >= sizeof(hexcookie)) { + warn("COOKIE data too large"); + goto exit_or_usage; + } + lookup->cookie = hexcookie; + } else { + lookup->cookie = NULL; + } + break; + default: + goto invalid_option; + } + break; + case 'r': + FULLCHECK("crypto"); + lookup->nocrypto = !state; + break; + default: + goto invalid_option; + } + break; + case 'd': + switch (cmd[1]) { + case 'e': /* defname */ + FULLCHECK("defname"); + fprintf(stderr, ";; +[no]defname option is " + "deprecated; use +[no]search\n"); + if (!lookup->trace) { + usesearch = state; + } + break; + case 'n': + switch (cmd[2]) { + case 's': + switch (cmd[3]) { + case '6': /* dns64prefix */ + FULLCHECK("dns64prefix"); + if (state) { + if (*need_clone) { + lookup = clone_lookup( + default_lookup, + true); + } + *need_clone = true; + lookup->dns64prefix = state; + strlcpy(lookup->textname, + "ipv4only.arpa", + sizeof(lookup->textname)); + printcmd = false; + lookup->section_additional = + false; + lookup->section_answer = true; + lookup->section_authority = + false; + lookup->section_question = + false; + lookup->comments = false; + lookup->stats = false; + lookup->rrcomments = -1; + lookup->rdtype = + dns_rdatatype_aaaa; + lookup->rdtypeset = true; + ISC_LIST_APPEND(lookup_list, + lookup, link); + } + break; + case 's': /* dnssec */ + FULLCHECK("dnssec"); + dnssec: + if (state && lookup->edns == -1) { + lookup->edns = + DEFAULT_EDNS_VERSION; + } + lookup->dnssec = state; + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'o': /* domain ... but treat "do" as synonym for dnssec */ + if (cmd[2] == '\0') { + goto dnssec; + } + FULLCHECK("domain"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + strlcpy(domainopt, value, sizeof(domainopt)); + break; + default: + goto invalid_option; + } + break; + case 'e': + switch (cmd[1]) { + case 'd': + switch (cmd[2]) { + case 'n': + switch (cmd[3]) { + case 's': + switch (cmd[4]) { + case 0: + FULLCHECK("edns"); + if (!state) { + lookup->edns = -1; + lookup->original_edns = + -1; + break; + } + if (value == NULL) { + lookup->edns = + DEFAULT_EDNS_VERSION; + break; + } + result = parse_uint(&num, value, + 255, + "edns"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse " + "edns"); + goto exit_or_usage; + } + lookup->edns = num; + lookup->original_edns = num; + break; + case 'f': + FULLCHECK("ednsflags"); + if (!state) { + lookup->ednsflags = 0; + break; + } + if (value == NULL) { + lookup->ednsflags = 0; + break; + } + result = parse_xint( + &num, value, 0xffff, + "ednsflags"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse " + "ednsflags"); + goto exit_or_usage; + } + if (lookup->edns == -1) { + lookup->edns = + DEFAULT_EDNS_VERSION; + } + lookup->ednsflags = num; + break; + case 'n': + FULLCHECK("ednsnegotiation"); + lookup->ednsneg = state; + break; + case 'o': + FULLCHECK("ednsopt"); + if (!state) { + lookup->ednsoptscnt = 0; + break; + } + code = NULL; + if (value != NULL) { + code = strtok_r(value, + ":", + &last); + } + if (code == NULL) { + warn("ednsopt no " + "code point " + "specified"); + goto exit_or_usage; + } + extra = strtok_r(NULL, "", + &last); + save_opt(lookup, code, extra); + if (extra != NULL) { + extra[-1] = ':'; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'x': + switch (cmd[2]) { + case 'p': + switch (cmd[3]) { + case 'a': + FULLCHECK("expandaaaa"); + lookup->expandaaaa = state; + break; + case 'i': + FULLCHECK("expire"); + lookup->expire = state; + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'f': /* fail */ + switch (cmd[1]) { + case 'a': + FULLCHECK("fail"); + lookup->servfail_stops = state; + break; + case 'u': + FULLCHECK("fuzztime"); + lookup->fuzzing = state; + if (lookup->fuzzing) { + if (value == NULL) { + lookup->fuzztime = 0x622acce1; + break; + } + result = parse_uint(&num, value, 0xffffffff, + "fuzztime"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse fuzztime"); + goto exit_or_usage; + } + lookup->fuzztime = num; + } + break; + default: + goto invalid_option; + } + break; + case 'h': + switch (cmd[1]) { + case 'e': /* header-only */ + FULLCHECK("header-only"); + lookup->header_only = state; + break; + case 't': + FULLCHECK6("https", "https-get", "https-post", + "http-plain", "http-plain-get", + "http-plain-post"); +#if HAVE_LIBNGHTTP2 + if (lookup->https_path != NULL) { + isc_mem_free(mctx, lookup->https_path); + lookup->https_path = NULL; + } + if (!state) { + lookup->https_mode = false; + break; + } + lookup->https_mode = true; + if (cmd[4] == '-') { + lookup->http_plain = true; + switch (cmd[10]) { + case '\0': + FULLCHECK("http-plain"); + break; + case '-': + switch (cmd[11]) { + case 'p': + FULLCHECK("http-plain-post"); + break; + case 'g': + FULLCHECK("http-plain-get"); + lookup->https_get = true; + break; + } + break; + default: + goto invalid_option; + } + } else { + switch (cmd[5]) { + case '\0': + FULLCHECK("https"); + break; + case '-': + switch (cmd[6]) { + case 'p': + FULLCHECK("https-post"); + break; + case 'g': + FULLCHECK("https-get"); + lookup->https_get = true; + break; + } + break; + default: + goto invalid_option; + } + } + if (!lookup->tcp_mode_set) { + lookup->tcp_mode = state; + } + if (value == NULL) { + lookup->https_path = isc_mem_strdup( + mctx, ISC_NM_HTTP_DEFAULT_PATH); + } else { + if (!isc_nm_http_path_isvalid(value)) { + fprintf(stderr, + ";; The given HTTP path \"%s\" " + "is not " + "a valid absolute path\n", + value); + goto invalid_option; + } + lookup->https_path = isc_mem_strdup(mctx, + value); + } +#else + fprintf(stderr, ";; DoH support not enabled\n"); +#endif + break; + default: + goto invalid_option; + } + break; + case 'i': + switch (cmd[1]) { + case 'd': + switch (cmd[2]) { + case 'e': + FULLCHECK("identify"); + lookup->identify = state; + break; + case 'n': + switch (cmd[3]) { + case '\0': + FULLCHECK("idn"); + lookup->idnin = state; + lookup->idnout = state; + break; + case 'i': /* (compat) */ + FULLCHECK("idnin"); + lookup->idnin = state; + break; + case 'o': /* (compat) */ + FULLCHECK("idnout"); + lookup->idnout = state; + break; + default: + goto invalid_option; + } +#ifndef HAVE_LIBIDN2 + if (state) { + printf(";; IDN support " + "is not available\n"); + } +#endif /* ifndef HAVE_LIBIDN2 */ + break; + default: + goto invalid_option; + } + break; + case 'g': /* ignore */ + default: /* + * Inherits default for compatibility (+[no]i*). + */ + FULLCHECK("ignore"); + lookup->ignore = state; + } + break; + case 'k': + switch (cmd[1]) { + case 'e': + switch (cmd[2]) { + case 'e': + switch (cmd[3]) { + case 'p': + switch (cmd[4]) { + case 'a': + FULLCHECK("keepalive"); + lookup->tcp_keepalive = state; + break; + case 'o': + FULLCHECK("keepopen"); + keep_open = state; + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'm': + switch (cmd[1]) { + case 'a': + FULLCHECK("mapped"); + fatal("+mapped option no longer supported"); + case 'u': + FULLCHECK("multiline"); + lookup->multiline = state; + break; + default: + goto invalid_option; + } + break; + case 'n': + switch (cmd[1]) { + case 'd': /* ndots */ + FULLCHECK("ndots"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&num, value, MAXNDOTS, "ndots"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse ndots"); + goto exit_or_usage; + } + ndots = num; + break; + case 's': + switch (cmd[2]) { + case 'i': /* nsid */ + FULLCHECK("nsid"); + if (state && lookup->edns == -1) { + lookup->edns = DEFAULT_EDNS_VERSION; + } + lookup->nsid = state; + break; + case 's': /* nssearch */ + FULLCHECK("nssearch"); + lookup->ns_search_only = state; + if (state) { + lookup->trace_root = true; + lookup->recurse = true; + lookup->identify = true; + lookup->stats = false; + lookup->comments = false; + lookup->section_additional = false; + lookup->section_authority = false; + lookup->section_question = false; + lookup->rdtype = dns_rdatatype_ns; + lookup->rdtypeset = true; + short_form = true; + lookup->rrcomments = 0; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'o': + switch (cmd[1]) { + case 'n': + FULLCHECK("onesoa"); + lookup->onesoa = state; + break; + case 'p': + FULLCHECK("opcode"); + if (!state) { + lookup->opcode = 0; /* default - query */ + break; + } + if (value == NULL) { + goto need_value; + } + for (num = 0; + num < sizeof(opcodetext) / sizeof(opcodetext[0]); + num++) + { + if (strcasecmp(opcodetext[num], value) == 0) { + break; + } + } + if (num < 16) { + lookup->opcode = (dns_opcode_t)num; + break; + } + result = parse_uint(&num, value, 15, "opcode"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse opcode"); + goto exit_or_usage; + } + lookup->opcode = (dns_opcode_t)num; + break; + default: + goto invalid_option; + } + break; + case 'p': + switch (cmd[1]) { + case 'a': + FULLCHECK("padding"); + if (state && lookup->edns == -1) { + lookup->edns = DEFAULT_EDNS_VERSION; + } + if (value == NULL) { + goto need_value; + } + result = parse_uint(&num, value, 512, "padding"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse padding"); + goto exit_or_usage; + } + lookup->padding = (uint16_t)num; + break; + case 'r': + if (!plus_proxy_options(cmd, value, state, lookup)) { + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'q': + switch (cmd[1]) { + case 'i': /* qid */ + FULLCHECK("qid"); + if (!state) { + lookup->setqid = false; + lookup->qid = 0; + break; + } + if (value == NULL) { + goto need_value; + } + result = parse_uint(&num, value, MAXQID, "qid"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse qid"); + goto exit_or_usage; + } + lookup->setqid = true; + lookup->qid = num; + break; + case 'r': /* qr */ + FULLCHECK("qr"); + lookup->qr = state; + break; + case 'u': /* question */ + FULLCHECK("question"); + lookup->section_question = state; + if (lookup == default_lookup) { + plusquest = state; + } + break; + default: + goto invalid_option; + } + break; + case 'r': + switch (cmd[1]) { + case 'a': /* raflag */ + FULLCHECK("raflag"); + lookup->raflag = state; + break; + case 'd': /* rdflag */ + FULLCHECK("rdflag"); + lookup->recurse = state; + break; + case 'e': + switch (cmd[2]) { + case 'c': /* recurse */ + FULLCHECK("recurse"); + lookup->recurse = state; + break; + case 't': /* retry / retries */ + FULLCHECK2("retry", "retries"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&lookup->retries, value, + MAXTRIES - 1, "retries"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse retries"); + goto exit_or_usage; + } + lookup->retries++; + break; + default: + goto invalid_option; + } + break; + case 'r': /* rrcomments */ + FULLCHECK("rrcomments"); + lookup->rrcomments = state ? 1 : -1; + break; + default: + goto invalid_option; + } + break; + case 's': + switch (cmd[1]) { + case 'e': /* search */ + FULLCHECK("search"); + if (!lookup->trace) { + usesearch = state; + } + break; + case 'h': + if (cmd[2] != 'o') { + goto invalid_option; + } + switch (cmd[3]) { + case 'r': /* short */ + FULLCHECK("short"); + short_form = state; + if (state) { + printcmd = false; + lookup->section_additional = false; + lookup->section_answer = true; + lookup->section_authority = false; + lookup->section_question = false; + lookup->comments = false; + lookup->stats = false; + lookup->rrcomments = -1; + } + break; + case 'w': /* showsearch */ + switch (cmd[4]) { + case 'b': + switch (cmd[7]) { + case 'c': + FULLCHECK("showbadcookie"); + lookup->showbadcookie = state; + break; + case 'v': + FULLCHECK("showbadvers"); + lookup->showbadvers = state; + break; + default: + goto invalid_option; + } + break; + case 's': + FULLCHECK("showsearch"); + if (!lookup->trace) { + showsearch = state; + usesearch = state; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'i': /* sigchase */ + FULLCHECK("sigchase"); + fatal("+sigchase option no longer supported"); + case 'p': /* split */ + FULLCHECK("split"); + if (value != NULL && !state) { + goto invalid_option; + } + if (!state) { + splitwidth = 0; + break; + } else if (value == NULL) { + break; + } + + result = parse_uint(&splitwidth, value, 1023, "split"); + if ((splitwidth % 4) != 0U) { + splitwidth = ((splitwidth + 3) / 4) * 4; + fprintf(stderr, + ";; Warning, split must be " + "a multiple of 4; adjusting " + "to %u\n", + splitwidth); + } + /* + * There is an adjustment done in the + * totext_() functions which causes + * splitwidth to shrink. This is okay when we're + * using the default width but incorrect in this + * case, so we correct for it + */ + if (splitwidth) { + splitwidth += 3; + } + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse split"); + goto exit_or_usage; + } + break; + case 't': /* stats */ + FULLCHECK("stats"); + lookup->stats = state; + break; + case 'u': /* subnet */ + FULLCHECK("subnet"); + if (state && value == NULL) { + goto need_value; + } + if (!state) { + if (lookup->ecs_addr != NULL) { + isc_mem_put(mctx, lookup->ecs_addr, + sizeof(*lookup->ecs_addr)); + lookup->ecs_addr = NULL; + } + break; + } + if (lookup->edns == -1) { + lookup->edns = DEFAULT_EDNS_VERSION; + } + if (lookup->ecs_addr != NULL) { + isc_mem_put(mctx, lookup->ecs_addr, + sizeof(*lookup->ecs_addr)); + lookup->ecs_addr = NULL; + } + result = parse_netprefix(&lookup->ecs_addr, value); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse client"); + goto exit_or_usage; + } + break; + default: + goto invalid_option; + } + break; + case 't': + switch (cmd[1]) { + case 'c': /* tcp */ + switch (cmd[2]) { + case 'f': + FULLCHECK("tcflag"); + lookup->tcflag = state; + break; + case 'p': + FULLCHECK("tcp"); + if (!is_batchfile) { + lookup->tcp_mode = state; + lookup->tcp_mode_set = true; + } + break; + default: + goto invalid_option; + } + break; + case 'i': /* timeout */ + FULLCHECK("timeout"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&timeout, value, MAXTIMEOUT, + "timeout"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse timeout"); + goto exit_or_usage; + } + if (timeout == 0) { + timeout = 1; + } + break; + case 'l': + switch (cmd[2]) { + case 's': + if (!plus_tls_options(cmd, value, state, + lookup)) + { + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'o': + FULLCHECK("topdown"); + fatal("+topdown option no longer supported"); + case 'r': + switch (cmd[2]) { + case 'a': /* trace */ + FULLCHECK("trace"); + lookup->trace = state; + lookup->trace_root = state; + if (state) { + lookup->recurse = true; + lookup->identify = true; + lookup->comments = false; + lookup->rrcomments = 0; + lookup->stats = false; + lookup->section_additional = false; + lookup->section_authority = true; + lookup->section_question = false; + lookup->dnssec = true; + lookup->sendcookie = true; + usesearch = false; + } + break; + case 'i': /* tries */ + FULLCHECK("tries"); + if (value == NULL) { + goto need_value; + } + if (!state) { + goto invalid_option; + } + result = parse_uint(&lookup->retries, value, + MAXTRIES, "tries"); + if (result != ISC_R_SUCCESS) { + warn("Couldn't parse tries"); + goto exit_or_usage; + } + if (lookup->retries == 0) { + lookup->retries = 1; + } + break; + case 'u': /* trusted-key */ + FULLCHECK("trusted-key"); + fatal("+trusted-key option " + "no longer supported"); + default: + goto invalid_option; + } + break; + case 't': + switch (cmd[2]) { + case 'l': + switch (cmd[3]) { + case 0: + case 'i': /* ttlid */ + FULLCHECK2("ttl", "ttlid"); + lookup->nottl = !state; + break; + case 'u': /* ttlunits */ + FULLCHECK("ttlunits"); + lookup->nottl = false; + lookup->ttlunits = state; + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + default: + goto invalid_option; + } + break; + case 'u': + switch (cmd[1]) { + case 'n': + switch (cmd[2]) { + case 'e': + FULLCHECK("unexpected"); + fatal("+unexpected option " + "no longer supported"); + case 'k': + FULLCHECK("unknownformat"); + lookup->print_unknown_format = state; + break; + default: + goto invalid_option; + } + } + break; + case 'v': + FULLCHECK("vc"); + if (!is_batchfile) { + lookup->tcp_mode = state; + lookup->tcp_mode_set = true; + } + break; + case 'y': /* yaml */ + FULLCHECK("yaml"); + yaml = state; + if (state) { + printcmd = false; + lookup->stats = false; + lookup->rrcomments = -1; + } + break; + case 'z': /* zflag */ + FULLCHECK("zflag"); + lookup->zflag = state; + break; + default: + invalid_option: + need_value: +#if TARGET_OS_IPHONE + exit_or_usage: +#endif /* if TARGET_OS_IPHONE */ + fprintf(stderr, "Invalid option: +%s\n", option); + usage(); + } + if (value != NULL) { + value[-1] = '='; + } + return lookup; + +#if !TARGET_OS_IPHONE +exit_or_usage: + cleanup_openssl_refs(); + digexit(); +#endif /* if !TARGET_OS_IPHONE */ +} + +/*% + * #true returned if value was used + */ +static const char *single_dash_opts = "46dhimnruv"; +static const char *dash_opts = "46bcdfhikmnpqrtvyx"; +static bool +dash_option(char *option, char *next, dig_lookup_t **lookup, + bool *open_type_class, bool *need_clone, bool config_only, int argc, + char **argv, bool *firstarg) { + char opt, *value, *ptr, *ptr2, *ptr3, *last; + isc_result_t result; + bool value_from_next; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + char textname[MXNAME]; + struct in_addr in4; + struct in6_addr in6; + in_port_t srcport; + char *hash, *cmd; + uint32_t num; + + while (strpbrk(option, single_dash_opts) == &option[0]) { + /* + * Since the -[46dhimnuv] options do not take an argument, + * account for them (in any number and/or combination) + * if they appear as the first character(s) of a q-opt. + */ + opt = option[0]; + switch (opt) { + case '4': + if (have_ipv4) { + isc_net_disableipv6(); + have_ipv6 = false; + } else { + fatal("can't find IPv4 networking"); + UNREACHABLE(); + return false; + } + break; + case '6': + if (have_ipv6) { + isc_net_disableipv4(); + have_ipv4 = false; + } else { + fatal("can't find IPv6 networking"); + UNREACHABLE(); + return false; + } + break; + case 'd': + ptr = strpbrk(&option[1], dash_opts); + if (ptr != &option[1]) { + cmd = option; + FULLCHECK("debug"); + debugging = true; + return false; + } else { + debugging = true; + } + break; + case 'h': + help(); + exit(EXIT_SUCCESS); + break; + case 'i': + fatal("-%c removed", option[0]); + case 'm': /* memdebug */ + /* memdebug is handled in preparse_args() */ + break; + case 'n': + fatal("-%c removed", option[0]); + case 'r': + debug("digrc (late)"); + digrc = false; + break; + case 'u': + (*lookup)->use_usec = true; + break; + case 'v': + printf("DiG %s\n", PACKAGE_VERSION); + exit(EXIT_SUCCESS); + break; + } + if (strlen(option) > 1U) { + option = &option[1]; + } else { + return false; + } + } + opt = option[0]; + if (strlen(option) > 1U) { + value_from_next = false; + value = &option[1]; + } else { + value_from_next = true; + value = next; + } + if (value == NULL) { + goto invalid_option; + } + switch (opt) { + case 'b': + hash = strchr(value, '#'); + if (hash != NULL) { + result = parse_uint(&num, hash + 1, MAXPORT, + "port number"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + srcport = num; + *hash = '\0'; + } else { + srcport = 0; + } + if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) { + isc_sockaddr_fromin6(&localaddr, &in6, srcport); + isc_net_disableipv4(); + } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) { + isc_sockaddr_fromin(&localaddr, &in4, srcport); + isc_net_disableipv6(); + } else { + if (hash != NULL) { + *hash = '#'; + } + fatal("invalid address %s", value); + } + if (hash != NULL) { + *hash = '#'; + } + specified_source = true; + return value_from_next; + case 'c': + if ((*lookup)->rdclassset) { + fprintf(stderr, ";; Warning, extra class option\n"); + } + *open_type_class = false; + tr.base = value; + tr.length = (unsigned int)strlen(value); + result = dns_rdataclass_fromtext(&rdclass, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + (*lookup)->rdclass = rdclass; + (*lookup)->rdclassset = true; + } else { + fprintf(stderr, + ";; Warning, ignoring " + "invalid class %s\n", + value); + } + return value_from_next; + case 'f': + batchname = value; + return value_from_next; + case 'k': + strlcpy(keyfile, value, sizeof(keyfile)); + return value_from_next; + case 'p': + result = parse_uint(&num, value, MAXPORT, "port number"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse port number"); + } + port = num; + port_set = true; + return value_from_next; + case 'q': + if (!config_only) { + if (*need_clone) { + (*lookup) = clone_lookup(default_lookup, true); + } + *need_clone = true; + strlcpy((*lookup)->textname, value, + sizeof((*lookup)->textname)); + (*lookup)->trace_root = ((*lookup)->trace || + (*lookup)->ns_search_only); + (*lookup)->new_search = true; + if (*firstarg) { + printgreeting(argc, argv, *lookup); + *firstarg = false; + } + ISC_LIST_APPEND(lookup_list, (*lookup), link); + debug("looking up %s", (*lookup)->textname); + } + return value_from_next; + case 't': + *open_type_class = false; + if (strncasecmp(value, "ixfr=", 5) == 0) { + rdtype = dns_rdatatype_ixfr; + result = ISC_R_SUCCESS; + } else { + tr.base = value; + tr.length = (unsigned int)strlen(value); + result = dns_rdatatype_fromtext( + &rdtype, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS && + rdtype == dns_rdatatype_ixfr) + { + result = DNS_R_UNKNOWN; + } + } + if (result == ISC_R_SUCCESS) { + if ((*lookup)->rdtypeset) { + fprintf(stderr, ";; Warning, " + "extra type option\n"); + } + if (rdtype == dns_rdatatype_ixfr) { + uint32_t serial; + (*lookup)->rdtype = dns_rdatatype_ixfr; + (*lookup)->rdtypeset = true; + result = parse_uint(&serial, &value[5], + MAXSERIAL, "serial number"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse serial number"); + } + (*lookup)->ixfr_serial = serial; + (*lookup)->section_question = plusquest; + (*lookup)->comments = pluscomm; + if (!(*lookup)->tcp_mode_set) { + (*lookup)->tcp_mode = true; + } + } else { + (*lookup)->rdtype = rdtype; + if (!config_only) { + (*lookup)->rdtypeset = true; + } + if (rdtype == dns_rdatatype_axfr) { + (*lookup)->section_question = plusquest; + (*lookup)->comments = pluscomm; + } else if (rdtype == dns_rdatatype_any) { + if (!(*lookup)->tcp_mode_set) { + (*lookup)->tcp_mode = true; + } + } + (*lookup)->ixfr_serial = false; + } + } else { + fprintf(stderr, + ";; Warning, ignoring " + "invalid type %s\n", + value); + } + return value_from_next; + case 'y': + if ((ptr = strtok_r(value, ":", &last)) == NULL) { + usage(); + } + if ((ptr2 = strtok_r(NULL, ":", &last)) == NULL) { /* name or + * secret */ + usage(); + } + if ((ptr3 = strtok_r(NULL, "", &last)) != NULL) { /* secret or + * NULL */ + parse_hmac(ptr); + ptr = ptr2; + ptr2 = ptr3; + } else { + hmac_alg = DST_ALG_HMACMD5; + digestbits = 0; + } + /* XXXONDREJ: FIXME */ + strlcpy(keynametext, ptr, sizeof(keynametext)); + strlcpy(keysecret, ptr2, sizeof(keysecret)); + if (ptr3 != NULL) { + ptr[-1] = ':'; + } + ptr2[-1] = ':'; + return value_from_next; + case 'x': + if (*need_clone) { + *lookup = clone_lookup(default_lookup, true); + } + *need_clone = true; + if (get_reverse(textname, sizeof(textname), value, false) == + ISC_R_SUCCESS) + { + strlcpy((*lookup)->textname, textname, + sizeof((*lookup)->textname)); + debug("looking up %s", (*lookup)->textname); + (*lookup)->trace_root = ((*lookup)->trace || + (*lookup)->ns_search_only); + if (!(*lookup)->rdtypeset) { + (*lookup)->rdtype = dns_rdatatype_ptr; + } + if (!(*lookup)->rdclassset) { + (*lookup)->rdclass = dns_rdataclass_in; + } + (*lookup)->new_search = true; + if (*firstarg) { + printgreeting(argc, argv, *lookup); + *firstarg = false; + } + ISC_LIST_APPEND(lookup_list, *lookup, link); + } else { + fprintf(stderr, "Invalid IP address %s\n", value); + exit(EXIT_FAILURE); + } + return value_from_next; + invalid_option: + default: + fprintf(stderr, "Invalid option: -%s\n", option); + usage(); + } + UNREACHABLE(); + return false; +} + +/*% + * Because we may be trying to do memory allocation recording, we're going + * to need to parse the arguments for the -m *before* we start the main + * argument parsing routine. + * + * I'd prefer not to have to do this, but I am not quite sure how else to + * fix the problem. Argument parsing in dig involves memory allocation + * by its nature, so it can't be done in the main argument parser. + */ +static void +preparse_args(int argc, char **argv) { + int rc; + char **rv; + char *option; + + rc = argc; + rv = argv; + for (rc--, rv++; rc > 0; rc--, rv++) { + if (rv[0][0] != '-') { + continue; + } + option = &rv[0][1]; + while (strpbrk(option, single_dash_opts) == &option[0]) { + switch (option[0]) { + case 'd': + /* For debugging early startup */ + debugging = true; + break; + case 'm': + memdebugging = true; + isc_mem_debugging = ISC_MEM_DEBUGTRACE | + ISC_MEM_DEBUGRECORD; + break; + case 'r': + /* + * Must be done early, because ~/.digrc + * is read before command line parsing + */ + debug("digrc (early)"); + digrc = false; + break; + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + } + option = &option[1]; + } + if (strlen(option) == 0U) { + continue; + } + /* Look for dash value option. */ + if (strpbrk(option, dash_opts) != &option[0]) { + goto invalid_option; + } + if (strlen(option) > 1U) { + /* value in option. */ + continue; + } + /* Dash value is next argument so we need to skip it. */ + rc--, rv++; + /* Handle missing argument */ + if (rc == 0) { + invalid_option: + fprintf(stderr, "Invalid option: -%s\n", option); + usage(); + } + } +} + +static int +split_batchline(char *batchline, char **bargv, int len, const char *msg) { + int bargc; + char *last = NULL; + + REQUIRE(batchline != NULL); + + for (bargc = 1, bargv[bargc] = strtok_r(batchline, " \t\r\n", &last); + bargc < len && bargv[bargc]; + bargv[++bargc] = strtok_r(NULL, " \t\r\n", &last)) + { + debug("%s %d: %s", msg, bargc, bargv[bargc]); + } + return bargc; +} + +static void +parse_args(bool is_batchfile, bool config_only, int argc, char **argv) { + isc_result_t result; + isc_textregion_t tr; + bool firstarg = true; + dig_lookup_t *lookup = NULL; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + bool open_type_class = true; + char batchline[MXNAME]; + int bargc; + char *bargv[64]; + int rc; + char **rv; +#ifndef NOPOSIX + char *homedir; + char rcfile[PATH_MAX]; +#endif /* ifndef NOPOSIX */ + bool need_clone = true; + + /* + * The semantics for parsing the args is a bit complex; if + * we don't have a host yet, make the arg apply globally, + * otherwise make it apply to the latest host. This is + * a bit different than the previous versions, but should + * form a consistent user interface. + * + * First, create a "default lookup" which won't actually be used + * anywhere, except for cloning into new lookups + */ + + debug("parse_args()"); + if (!is_batchfile) { + debug("making new lookup"); + default_lookup = make_empty_lookup(); + default_lookup->adflag = true; + default_lookup->edns = DEFAULT_EDNS_VERSION; + default_lookup->sendcookie = true; + +#ifndef NOPOSIX + /* + * Treat ${HOME}/.digrc as a special batchfile + */ + INSIST(batchfp == NULL); + homedir = getenv("HOME"); + if (homedir != NULL && digrc) { + unsigned int n; + debug("digrc (open)"); + n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc", + homedir); + if (n < sizeof(rcfile)) { + batchfp = fopen(rcfile, "r"); + } + } + if (batchfp != NULL) { + while (fgets(batchline, sizeof(batchline), batchfp) != + 0) + { + debug("config line %s", batchline); + bargc = split_batchline(batchline, bargv, 62, + ".digrc argv"); + bargv[0] = argv[0]; + argv0 = argv[0]; + parse_args(true, true, bargc, (char **)bargv); + } + fclose(batchfp); + } +#endif /* ifndef NOPOSIX */ + } + + if (is_batchfile && !config_only) { + /* Processing '-f batchfile'. */ + lookup = clone_lookup(default_lookup, true); + need_clone = false; + } else { + lookup = default_lookup; + } + + rc = argc; + rv = argv; + for (rc--, rv++; rc > 0; rc--, rv++) { + debug("main parsing %s", rv[0]); + if (strncmp(rv[0], "%", 1) == 0) { + break; + } + if (rv[0][0] == '@') { + if (is_batchfile && !config_only) { + addresscount = getaddresses(lookup, &rv[0][1], + &result); + if (addresscount == 0) { + fprintf(stderr, + "couldn't get address " + "for '%s': %s: skipping " + "lookup\n", + &rv[0][1], + isc_result_totext(result)); + if (ISC_LINK_LINKED(lookup, link)) { + ISC_LIST_DEQUEUE(lookup_list, + lookup, link); + } + destroy_lookup(lookup); + return; + } + } else { + addresscount = getaddresses(lookup, &rv[0][1], + NULL); + if (addresscount == 0) { + fatal("no valid addresses for '%s'\n", + &rv[0][1]); + } + } + } else if (rv[0][0] == '+') { + lookup = plus_option(&rv[0][1], is_batchfile, + &need_clone, lookup); + } else if (rv[0][0] == '-') { + if (rc <= 1) { + if (dash_option(&rv[0][1], NULL, &lookup, + &open_type_class, &need_clone, + config_only, argc, argv, + &firstarg)) + { + rc--; + rv++; + } + } else { + if (dash_option(&rv[0][1], rv[1], &lookup, + &open_type_class, &need_clone, + config_only, argc, argv, + &firstarg)) + { + rc--; + rv++; + } + } + } else { + /* + * Anything which isn't an option + */ + if (open_type_class) { + if (strncasecmp(rv[0], "ixfr=", 5) == 0) { + rdtype = dns_rdatatype_ixfr; + result = ISC_R_SUCCESS; + } else { + tr.base = rv[0]; + tr.length = (unsigned int)strlen(rv[0]); + result = dns_rdatatype_fromtext( + &rdtype, + (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS && + rdtype == dns_rdatatype_ixfr) + { + fprintf(stderr, ";; Warning, " + "ixfr requires " + "a " + "serial " + "number\n"); + continue; + } + } + if (result == ISC_R_SUCCESS) { + if (lookup->rdtypeset) { + fprintf(stderr, ";; Warning, " + "extra type " + "option\n"); + } + if (rdtype == dns_rdatatype_ixfr) { + uint32_t serial; + lookup->rdtype = + dns_rdatatype_ixfr; + lookup->rdtypeset = true; + result = parse_uint(&serial, + &rv[0][5], + MAXSERIAL, + "serial " + "number"); + if (result != ISC_R_SUCCESS) { + fatal("Couldn't parse " + "serial number"); + } + lookup->ixfr_serial = serial; + lookup->section_question = + plusquest; + lookup->comments = pluscomm; + if (!lookup->tcp_mode_set) { + lookup->tcp_mode = true; + } + } else { + lookup->rdtype = rdtype; + lookup->rdtypeset = true; + if (rdtype == + dns_rdatatype_axfr) + { + lookup->section_question = + plusquest; + lookup->comments = + pluscomm; + } + if (rdtype == + dns_rdatatype_any && + !lookup->tcp_mode_set) + { + lookup->tcp_mode = true; + } + lookup->ixfr_serial = false; + } + continue; + } + result = dns_rdataclass_fromtext( + &rdclass, (isc_textregion_t *)&tr); + if (result == ISC_R_SUCCESS) { + if (lookup->rdclassset) { + fprintf(stderr, ";; Warning, " + "extra class " + "option\n"); + } + lookup->rdclass = rdclass; + lookup->rdclassset = true; + continue; + } + } + + if (!config_only) { + if (need_clone) { + lookup = clone_lookup(default_lookup, + true); + } + need_clone = true; + strlcpy(lookup->textname, rv[0], + sizeof(lookup->textname)); + lookup->trace_root = (lookup->trace || + lookup->ns_search_only); + lookup->new_search = true; + if (firstarg) { + printgreeting(argc, argv, lookup); + firstarg = false; + } + ISC_LIST_APPEND(lookup_list, lookup, link); + debug("looking up %s", lookup->textname); + } + /* XXX Error message */ + } + } + + /* + * If we have a batchfile, seed the lookup list with the + * first entry, then trust the callback in dighost_shutdown + * to get the rest + */ + char *filename = batchname; + if ((filename != NULL) && !(is_batchfile)) { + if (strcmp(filename, "-") == 0) { + batchfp = stdin; + } else { + batchfp = fopen(filename, "r"); + } + if (batchfp == NULL) { + perror(filename); + if (exitcode < 8) { + exitcode = 8; + } + fatal("couldn't open specified batch file"); + } + /* XXX Remove code dup from shutdown code */ + next_line: + if (fgets(batchline, sizeof(batchline), batchfp) != 0) { + debug("batch line %s", batchline); + if (batchline[0] == '\r' || batchline[0] == '\n' || + batchline[0] == '#' || batchline[0] == ';') + { + goto next_line; + } + bargc = split_batchline(batchline, bargv, 14, + "batch argv"); + bargv[0] = argv[0]; + argv0 = argv[0]; + parse_args(true, false, bargc, (char **)bargv); + return; + } + return; + } + /* + * If no lookup specified, search for root + */ + if ((lookup_list.head == NULL) && !config_only) { + if (need_clone) { + lookup = clone_lookup(default_lookup, true); + } + need_clone = true; + lookup->trace_root = (lookup->trace || lookup->ns_search_only); + lookup->new_search = true; + strlcpy(lookup->textname, ".", sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_ns; + lookup->rdtypeset = true; + if (firstarg) { + printgreeting(argc, argv, lookup); + firstarg = false; + } + ISC_LIST_APPEND(lookup_list, lookup, link); + } + if (!need_clone) { + destroy_lookup(lookup); + } +} + +/* + * Callback from dighost.c to allow program-specific shutdown code. + * Here, we're possibly reading from a batch file, then shutting down + * for real if there's nothing in the batch file to read. + */ +static void +query_finished(void) { + char batchline[MXNAME]; + + fflush(stdout); + + if (batchname != NULL && !feof(batchfp) && + fgets(batchline, sizeof(batchline), batchfp) != NULL) + { + int bargc; + char *bargv[16]; + debug("batch line %s", batchline); + bargc = split_batchline(batchline, bargv, 14, "batch argv"); + bargv[0] = argv0; + parse_args(true, false, bargc, (char **)bargv); + start_lookup(); + return; + } + + debug("shutdown"); + + /* We are done */ + if (batchname != NULL) { + if (batchfp != stdin) { + fclose(batchfp); + } + batchname = NULL; + } + isc_loopmgr_shutdown(loopmgr); +} + +static void +dig_error(const char *format, ...) { + va_list args; + + if (yaml) { + printf("- type: DIG_ERROR\n"); + + /* + * Print an indent before a literal block quote. + * Note: this will break if used to print more than + * one line of text as only the first line would be + * indented. + */ + printf(" message: |\n"); + printf(" "); + } else { + printf(";; "); + } + + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); /* We get the error without a newline */ +} + +static void +dig_warning(const char *format, ...) { + va_list args; + + if (!yaml) { + printf(";; "); + + va_start(args, format); + vprintf(format, args); + va_end(args); + + printf("\n"); + } +} + +static void +dig_comments(dig_lookup_t *lookup, const char *format, ...) { + va_list args; + + if (lookup->comments && !yaml) { + printf(";; "); + + va_start(args, format); + vprintf(format, args); + va_end(args); + + printf("\n"); + } +} + +void +dig_setup(int argc, char **argv) { + ISC_LIST_INIT(lookup_list); + ISC_LIST_INIT(server_list); + ISC_LIST_INIT(search_list); + + debug("dig_setup()"); + + /* setup dighost callbacks */ + dighost_printmessage = printmessage; + dighost_received = received; + dighost_trying = trying; + dighost_shutdown = query_finished; + dighost_error = dig_error; + dighost_warning = dig_warning; + dighost_comments = dig_comments; + + progname = argv[0]; + preparse_args(argc, argv); + + setup_libs(); + setup_system(ipv4only, ipv6only); +} + +void +dig_query_setup(bool is_batchfile, bool config_only, int argc, char **argv) { + debug("dig_query_setup"); + + parse_args(is_batchfile, config_only, argc, argv); + if (keyfile[0] != 0) { + setup_file_key(); + } else if (keysecret[0] != 0) { + setup_text_key(); + } + if (domainopt[0] != '\0') { + set_search_domain(domainopt); + usesearch = true; + } +} + +void +dig_startup(void) { + debug("dig_startup()"); + + isc_loopmgr_setup(loopmgr, run_loop, NULL); + isc_loopmgr_run(loopmgr); +} + +void +dig_shutdown(void) { + destroy_lookup(default_lookup); + cancel_all(); + destroy_libs(); +} + +/*% Main processing routine for dig */ +int +main(int argc, char **argv) { + dig_setup(argc, argv); + dig_query_setup(false, false, argc, argv); + dig_startup(); + dig_shutdown(); + + return exitcode; +} diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst new file mode 100644 index 0000000..ef492a3 --- /dev/null +++ b/bin/dig/dig.rst @@ -0,0 +1,816 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dig +.. program:: dig +.. _man_dig: + +dig - DNS lookup utility +------------------------ + +Synopsis +~~~~~~~~ +:program:`dig` [@server] [**-b** address] [**-c** class] [**-f** filename] [**-k** filename] [**-m**] [**-p** port#] [**-q** name] [**-t** type] [**-v**] [**-x** addr] [**-y** [hmac:]name:key] [ [**-4**] | [**-6**] ] [name] [type] [class] [queryopt...] + +:program:`dig` [**-h**] + +:program:`dig` [global-queryopt...] [query...] + +Description +~~~~~~~~~~~ + +:program:`dig` is a flexible tool for interrogating DNS name servers. It +performs DNS lookups and displays the answers that are returned from the +name server(s) that were queried. Most DNS administrators use :program:`dig` to +troubleshoot DNS problems because of its flexibility, ease of use, and +clarity of output. Other lookup tools tend to have less functionality +than :program:`dig`. + +Although :program:`dig` is normally used with command-line arguments, it also +has a batch mode of operation for reading lookup requests from a file. A +brief summary of its command-line arguments and options is printed when +the :option:`-h` option is given. The BIND 9 +implementation of :program:`dig` allows multiple lookups to be issued from the +command line. + +Unless it is told to query a specific name server, :program:`dig` tries each +of the servers listed in ``/etc/resolv.conf``. If no usable server +addresses are found, :program:`dig` sends the query to the local host. + +When no command-line arguments or options are given, :program:`dig` +performs an NS query for "." (the root). + +It is possible to set per-user defaults for :program:`dig` via +``${HOME}/.digrc``. This file is read and any options in it are applied +before the command-line arguments. The :option:`-r` option disables this +feature, for scripts that need predictable behavior. + +The IN and CH class names overlap with the IN and CH top-level domain +names. Either use the :option:`-t` and :option:`-c` options to specify the type and +class, use the :option:`-q` to specify the domain name, or use "IN." and +"CH." when looking up these top-level domains. + +Simple Usage +~~~~~~~~~~~~ + +A typical invocation of :program:`dig` looks like: + +:: + + dig @server name type + +where: + +.. option:: server + + is the name or IP address of the name server to query. This can be an + IPv4 address in dotted-decimal notation or an IPv6 address in + colon-delimited notation. When the supplied ``server`` argument is a + hostname, :program:`dig` resolves that name before querying that name + server. + + If no ``server`` argument is provided, :program:`dig` consults + ``/etc/resolv.conf``; if an address is found there, it queries the + name server at that address. If either of the :option:`-4` or :option:`-6` + options are in use, then only addresses for the corresponding + transport are tried. If no usable addresses are found, :program:`dig` + sends the query to the local host. The reply from the name server + that responds is displayed. + +.. option:: name + + is the name of the resource record that is to be looked up. + +.. option:: type + + indicates what type of query is required - ANY, A, MX, SIG, etc. + ``type`` can be any valid query type. If no ``type`` argument is + supplied, :program:`dig` performs a lookup for an A record. + +Options +~~~~~~~ + +.. option:: -4 + + This option indicates that only IPv4 should be used. + +.. option:: -6 + + This option indicates that only IPv6 should be used. + +.. option:: -b address[#port] + + This option sets the source IP address of the query. The ``address`` must be a + valid address on one of the host's network interfaces, or "0.0.0.0" + or "::". An optional port may be specified by appending ``#port``. + +.. option:: -c class + + This option sets the query class. The default ``class`` is IN; other classes are + HS for Hesiod records or CH for Chaosnet records. + +.. option:: -f file + + This option sets batch mode, in which :program:`dig` reads a list of lookup requests to process from + the given ``file``. Each line in the file should be organized in the + same way it would be presented as a query to :program:`dig` using the + command-line interface. + +.. option:: -h + + Print a usage summary. + +.. option:: -k keyfile + + This option tells :program:`dig` to sign queries using TSIG or + SIG(0) using a key read from the given file. Key files can be + generated using :iscman:`tsig-keygen`. When using TSIG authentication + with :program:`dig`, the name server that is queried needs to + know the key and algorithm that is being used. In BIND, this is + done by providing appropriate ``key`` and ``server`` statements + in :iscman:`named.conf` for TSIG and by looking up the KEY record + in zone data for SIG(0). + +.. option:: -m + + This option enables memory usage debugging. + +.. option:: -p port + + This option sends the query to a non-standard port on the server, instead of the + default port 53. This option is used to test a name server that + has been configured to listen for queries on a non-standard port + number. + +.. option:: -q name + + This option specifies the domain name to query. This is useful to distinguish the ``name`` + from other arguments. + +.. option:: -r + + This option indicates that options from ``${HOME}/.digrc`` should not be read. This is useful for + scripts that need predictable behavior. + +.. option:: -t type + + This option indicates the resource record type to query, which can be any valid query type. If + it is a resource record type supported in BIND 9, it can be given by + the type mnemonic (such as ``NS`` or ``AAAA``). The default query type is + ``A``, unless the :option:`-x` option is supplied to indicate a reverse + lookup. A zone transfer can be requested by specifying a type of + AXFR. When an incremental zone transfer (IXFR) is required, set the + ``type`` to ``ixfr=N``. The incremental zone transfer contains + all changes made to the zone since the serial number in the zone's + SOA record was ``N``. + + All resource record types can be expressed as ``TYPEnn``, where ``nn`` is + the number of the type. If the resource record type is not supported + in BIND 9, the result is displayed as described in :rfc:`3597`. + +.. option:: -u + + This option indicates that print query times should be provided in microseconds instead of milliseconds. + +.. option:: -v + + This option prints the version number and exits. + +.. option:: -x addr + + This option sets simplified reverse lookups, for mapping addresses to names. The + ``addr`` is an IPv4 address in dotted-decimal notation, or a + colon-delimited IPv6 address. When the :option:`-x` option is used, there is no + need to provide the ``name``, ``class``, and ``type`` arguments. + :program:`dig` automatically performs a lookup for a name like + ``94.2.0.192.in-addr.arpa`` and sets the query type and class to PTR + and IN respectively. IPv6 addresses are looked up using nibble format + under the IP6.ARPA domain. + +.. option:: -y [hmac:]keyname:secret + + This option signs queries using TSIG with the given authentication key. + ``keyname`` is the name of the key, and ``secret`` is the + base64-encoded shared secret. ``hmac`` is the name of the key algorithm; + valid choices are ``hmac-md5``, ``hmac-sha1``, ``hmac-sha224``, + ``hmac-sha256``, ``hmac-sha384``, or ``hmac-sha512``. If ``hmac`` is + not specified, the default is ``hmac-md5``; if MD5 was disabled, the default is + ``hmac-sha256``. + +.. note:: Only the :option:`-k` option should be used, rather than the :option:`-y` option, + because with :option:`-y` the shared secret is supplied as a command-line + argument in clear text. This may be visible in the output from ``ps1`` or + in a history file maintained by the user's shell. + +Query Options +~~~~~~~~~~~~~ + +:program:`dig` provides a number of query options which affect the way in which +lookups are made and the results displayed. Some of these set or reset +flag bits in the query header, some determine which sections of the +answer get printed, and others determine the timeout and retry +strategies. + +Each query option is identified by a keyword preceded by a plus sign +(``+``). Some keywords set or reset an option; these may be preceded by +the string ``no`` to negate the meaning of that keyword. Other keywords +assign values to options, like the timeout interval. They have the form +``+keyword=value``. Keywords may be abbreviated, provided the +abbreviation is unambiguous; for example, :option:`+cd` is equivalent to +:option:`+cdflag`. The query options are: + +.. option:: +aaflag, +noaaflag + + This option is a synonym for :option:`+aaonly`, :option:`+noaaonly`. + +.. option:: +aaonly, +noaaonly + + This option sets the ``aa`` flag in the query. + +.. option:: +additional, +noadditional + + This option displays [or does not display] the additional section of a reply. The + default is to display it. + +.. option:: +adflag, +noadflag + + This option sets [or does not set] the AD (authentic data) bit in the query. This + requests the server to return whether all of the answer and authority + sections have been validated as secure, according to the security + policy of the server. ``AD=1`` indicates that all records have been + validated as secure and the answer is not from a OPT-OUT range. ``AD=0`` + indicates that some part of the answer was insecure or not validated. + This bit is set by default. + +.. option:: +all, +noall + + This option sets or clears all display flags. + +.. option:: +answer, +noanswer + + This option displays [or does not display] the answer section of a reply. The default + is to display it. + +.. option:: +authority, +noauthority + + This option displays [or does not display] the authority section of a reply. The + default is to display it. + +.. option:: +badcookie, +nobadcookie + + This option retries the lookup with a new server cookie if a BADCOOKIE response is + received. + +.. option:: +besteffort, +nobesteffort + + This option attempts to display the contents of messages which are malformed. The + default is to not display malformed answers. + +.. option:: +bufsize[=B] + + This option sets the UDP message buffer size advertised using EDNS0 to + ``B`` bytes. The maximum and minimum sizes of this buffer are 65535 and + 0, respectively. ``+bufsize`` restores the default buffer size. + +.. option:: +cd, +cdflag, +nocdflag + + This option sets [or does not set] the CD (checking disabled) bit in the query. This + requests the server to not perform DNSSEC validation of responses. + +.. option:: +class, +noclass + + This option displays [or does not display] the CLASS when printing the record. + +.. option:: +cmd, +nocmd + + This option toggles the printing of the initial comment in the output, identifying the + version of :program:`dig` and the query options that have been applied. This option + always has a global effect; it cannot be set globally and then overridden on a + per-lookup basis. The default is to print this comment. + +.. option:: +comments, +nocomments + + This option toggles the display of some comment lines in the output, with + information about the packet header and OPT pseudosection, and the names of + the response section. The default is to print these comments. + + Other types of comments in the output are not affected by this option, but + can be controlled using other command-line switches. These include + :option:`+cmd`, :option:`+question`, :option:`+stats`, and :option:`+rrcomments`. + +.. option:: +cookie=####, +nocookie + + This option sends [or does not send] a COOKIE EDNS option, with an optional value. Replaying a COOKIE + from a previous response allows the server to identify a previous + client. The default is ``+cookie``. + + ``+cookie`` is also set when :option:`+trace` is set to better emulate the + default queries from a nameserver. + +.. option:: +crypto, +nocrypto + + This option toggles the display of cryptographic fields in DNSSEC records. The + contents of these fields are unnecessary for debugging most DNSSEC + validation failures and removing them makes it easier to see the + common failures. The default is to display the fields. When omitted, + they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the + key ID is displayed as the replacement, e.g. ``[ key id = value ]``. + +.. option:: +defname, +nodefname + + This option, which is deprecated, is treated as a synonym for + :option:`+search`, :option:`+nosearch`. + +.. option:: +dns64prefix, +nodns64prefix + + Lookup IPV4ONLY.ARPA AAAA and print any DNS64 prefixes found. + +.. option:: +dnssec, +do, +nodnssec, +nodo + + This option requests that DNSSEC records be sent by setting the DNSSEC OK (DO) bit in + the OPT record in the additional section of the query. + +.. option:: +domain=somename + + This option sets the search list to contain the single domain ``somename``, as if + specified in a ``domain`` directive in ``/etc/resolv.conf``, and + enables search list processing as if the :option:`+search` option were + given. + +.. option:: +edns[=#], +noedns + + This option specifies the EDNS version to query with. Valid values are 0 to 255. + Setting the EDNS version causes an EDNS query to be sent. + ``+noedns`` clears the remembered EDNS version. EDNS is set to 0 by + default. + +.. option:: +ednsflags[=#], +noednsflags + + This option sets the must-be-zero EDNS flags bits (Z bits) to the specified value. + Decimal, hex, and octal encodings are accepted. Setting a named flag + (e.g., DO) is silently ignored. By default, no Z bits are set. + +.. option:: +ednsnegotiation, +noednsnegotiation + + This option enables/disables EDNS version negotiation. By default, EDNS version + negotiation is enabled. + +.. option:: +ednsopt[=code[:value]], +noednsopt + + This option specifies the EDNS option with code point ``code`` and an optional payload + of ``value`` as a hexadecimal string. ``code`` can be either an EDNS + option name (for example, ``NSID`` or ``ECS``) or an arbitrary + numeric value. ``+noednsopt`` clears the EDNS options to be sent. + +.. option:: +expire, +noexpire + + This option sends an EDNS Expire option. + +.. option:: +fail, +nofail + + This option indicates that :iscman:`named` should try [or not try] the next server if a SERVFAIL is received. The default is + to not try the next server, which is the reverse of normal stub + resolver behavior. + +.. option:: +fuzztime[=value], +nofuzztime + + This option allows the signing time to be specified when generating + signed messages. If a value is specified it is the seconds since + 00:00:00 January 1, 1970 UTC ignoring leap seconds. If no value + is specified 1646972129 (Fri 11 Mar 2022 04:15:29 UTC) is used. + The default is ``+nofuzztime`` and the current time is used. + +.. option:: +header-only, +noheader-only + + This option sends a query with a DNS header without a question section. The + default is to add a question section. The query type and query name + are ignored when this is set. + +.. option:: +https[=value], +nohttps + + This option indicates whether to use DNS over HTTPS (DoH) when querying + name servers. When this option is in use, the port number defaults to 443. + The HTTP POST request mode is used when sending the query. + + If ``value`` is specified, it will be used as the HTTP endpoint in the + query URI; the default is ``/dns-query``. So, for example, ``dig + @example.com +https`` will use the URI ``https://example.com/dns-query``. + +.. option:: +https-get[=value], +nohttps-get + + Similar to :option:`+https`, except that the HTTP GET request mode is used + when sending the query. + +.. option:: +https-post[=value], +nohttps-post + + Same as :option:`+https`. + +.. option:: +http-plain[=value], +nohttp-plain + + Similar to :option:`+https`, except that HTTP queries will be sent over a + non-encrypted channel. When this option is in use, the port number + defaults to 80 and the HTTP request mode is POST. + +.. option:: +http-plain-get[=value], +nohttp-plain-get + + Similar to :option:`+http-plain`, except that the HTTP request mode is GET. + +.. option:: +http-plain-post[=value], +nohttp-plain-post + + Same as :option:`+http-plain`. + +.. option:: +identify, +noidentify + + This option shows [or does not show] the IP address and port number that + supplied the answer, when the :option:`+short` option is enabled. If short + form answers are requested, the default is not to show the source + address and port number of the server that provided the answer. + +.. option:: +idn, +noidn + + Enable or disable IDN processing. By default IDN is enabled for + input query names, and for display when the output is a terminal. + + You can also turn off :program:`dig`'s IDN processing by setting + the ``IDN_DISABLE`` environment variable. + +.. option:: +ignore, +noignore + + This option ignores [or does not ignore] truncation in UDP + responses instead of retrying with TCP. By default, TCP retries are + performed. + +.. option:: +keepalive, +nokeepalive + + This option sends [or does not send] an EDNS Keepalive option. + +.. option:: +keepopen, +nokeepopen + + This option keeps [or does not keep] the TCP socket open between queries, and reuses it rather than + creating a new TCP socket for each lookup. The default is + ``+nokeepopen``. + +.. option:: +multiline, +nomultiline + + This option prints [or does not print] records, like the SOA records, in a verbose multi-line format + with human-readable comments. The default is to print each record on + a single line to facilitate machine parsing of the :program:`dig` output. + +.. option:: +ndots=D + + This option sets the number of dots (``D``) that must appear in ``name`` for + it to be considered absolute. The default value is that defined using + the ``ndots`` statement in ``/etc/resolv.conf``, or 1 if no ``ndots`` + statement is present. Names with fewer dots are interpreted as + relative names, and are searched for in the domains listed in the + ``search`` or ``domain`` directive in ``/etc/resolv.conf`` if + :option:`+search` is set. + +.. option:: +nsid, +nonsid + + When enabled, this option includes an EDNS name server ID request when sending a query. + +.. option:: +nssearch, +nonssearch + + When this option is set, :program:`dig` attempts to find the authoritative + name servers for the zone containing the name being looked up, and + display the SOA record that each name server has for the zone. + Addresses of servers that did not respond are also printed. + +.. option:: +onesoa, +noonesoa + + When enabled, this option prints only one (starting) SOA record when performing an AXFR. The + default is to print both the starting and ending SOA records. + +.. option:: +opcode=value, +noopcode + + When enabled, this option sets (restores) the DNS message opcode to the specified value. The + default value is QUERY (0). + +.. option:: +padding=value + + This option pads the size of the query packet using the EDNS Padding option to + blocks of ``value`` bytes. For example, ``+padding=32`` causes a + 48-byte query to be padded to 64 bytes. The default block size is 0, + which disables padding; the maximum is 512. Values are ordinarily + expected to be powers of two, such as 128; however, this is not + mandatory. Responses to padded queries may also be padded, but only + if the query uses TCP or DNS COOKIE. + +.. option:: +proxy[=src_addr[#src_port]-dst_addr[#dst_port]], +noproxy + + When this option is set, :program:`dig` adds PROXYv2 headers to the + queries. When source and destination addresses are specified, the + headers contain them and use the ``PROXY`` command. It means for + the remote peer that the queries were sent on behalf of another + node and that the PROXYv2 header reflects the original connection + endpoints. The default source port is ``0`` and destination port is + `53`. + + For encrypted DNS transports, to prevent accidental information + leakage, encryption is applied to the PROXYv2 headers: the headers + are sent right after the handshake process has been completed. + + For plain DNS transports, no encryption is applied to the PROXYv2 + headers. + + If the addressees are omitted, PROXYv2 headers, that use the + ``LOCAL`` command set, are added instead. For the remote peer, that + means that the queries were sent on purpose without being relayed, + so the real connection endpoint addresses must be used. + +.. option:: +proxy-plain[=src_addr[#src_port]-dst_addr[#dst_port], +noproxy-plain + + The same as ``+[no]proxy``, but instructs ``dig`` to send PROXYv2 + headers ahead of any encryption, before any handshake messages are + sent. That makes :program:`dig` behave exactly how it is described + in the PROXY protocol specification, but not all software expects + such behaviour. + + Please consult the software documentation to find out if you need + this option. (for example, ``dnsdist`` expects encrypted PROXYv2 + headers sent over TLS when encryption is used, while ``HAProxy`` + and many other software packages expect plain ones). + + For plain DNS transports the option is effectively an alias for the + ``+[no]proxy`` described above. + +.. option:: +qid=value + + This option specifies the query ID to use when sending queries. + +.. option:: +qr, +noqr + + This option toggles the display of the query message as it is sent. By default, the query + is not printed. + +.. option:: +question, +noquestion + + This option toggles the display of the question section of a query when an answer is + returned. The default is to print the question section as a comment. + +.. option:: +raflag, +noraflag + + This option sets [or does not set] the RA (Recursion Available) bit in the query. The + default is ``+noraflag``. This bit is ignored by the server for + QUERY. + +.. option:: +rdflag, +nordflag + + This option is a synonym for :option:`+recurse`, :option:`+norecurse`. + +.. option:: +recurse, +norecurse + + This option toggles the setting of the RD (recursion desired) bit in the query. + This bit is set by default, which means :program:`dig` normally sends + recursive queries. Recursion is automatically disabled when the + :option:`+nssearch` or :option:`+trace` query option is used. + +.. option:: +retry=T + + This option sets the number of times to retry UDP and TCP queries to server to ``T`` + instead of the default, 2. Unlike :option:`+tries`, this does not include + the initial query. + +.. option:: +rrcomments, +norrcomments + + This option toggles the display of per-record comments in the output (for example, + human-readable key information about DNSKEY records). The default is + not to print record comments unless multiline mode is active. + +.. option:: +search, +nosearch + + This option uses [or does not use] the search list defined by the searchlist or domain + directive in ``resolv.conf``, if any. The search list is not used by + default. + + ``ndots`` from ``resolv.conf`` (default 1), which may be overridden by + :option:`+ndots`, determines whether the name is treated as relative + and hence whether a search is eventually performed. + +.. option:: +short, +noshort + + This option toggles whether a terse answer is provided. The default is to print the answer in a verbose + form. This option always has a global effect; it cannot be set globally and + then overridden on a per-lookup basis. + +.. option:: +showbadcookie, +noshowbadcookie + + This option toggles whether to show the message containing the + BADCOOKIE rcode before retrying the request or not. The default + is to not show the messages. + +.. option:: +showbadvers, +noshowbadvers + + This option toggles whether to show the message containing the + BADVERS rcode before retrying the request or not. The default + is to not show the messages. + +.. option:: +showsearch, +noshowsearch + + This option performs [or does not perform] a search showing intermediate results. + +.. option:: +split=W + + This option splits long hex- or base64-formatted fields in resource records into + chunks of ``W`` characters (where ``W`` is rounded up to the nearest + multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be + split at all. The default is 56 characters, or 44 characters when + multiline mode is active. + +.. option:: +stats, +nostats + + This option toggles the printing of statistics: when the query was made, the size of the + reply, etc. The default behavior is to print the query statistics as a + comment after each lookup. + +.. option:: +subnet=addr[/prefix-length], +nosubnet + + This option sends [or does not send] an EDNS CLIENT-SUBNET option with the specified IP + address or network prefix. + + ``dig +subnet=0.0.0.0/0``, or simply ``dig +subnet=0`` for short, + sends an EDNS CLIENT-SUBNET option with an empty address and a source + prefix-length of zero, which signals a resolver that the client's + address information must *not* be used when resolving this query. + +.. option:: +tcflag, +notcflag + + This option sets [or does not set] the TC (TrunCation) bit in the query. The default is + ``+notcflag``. This bit is ignored by the server for QUERY. + +.. option:: +tcp, +notcp + + This option indicates whether to use TCP when querying name + servers. The default behavior is to use UDP unless a type ``any`` + or ``ixfr=N`` query is requested, in which case the default is + TCP. AXFR queries always use TCP. To prevent retry over TCP when + TC=1 is returned from a UDP query, use ``+ignore``. + +.. option:: +timeout=T + + This option sets the timeout for a query to ``T`` seconds. The default timeout is + 5 seconds. An attempt to set ``T`` to less than 1 is silently set to 1. + +.. option:: +tls, +notls + + This option indicates whether to use DNS over TLS (DoT) when querying + name servers. When this option is in use, the port number defaults + to 853. + +.. option:: +tls-ca[=file-name], +notls-ca + + This option enables remote server TLS certificate validation for + DNS transports, relying on TLS. Certificate authorities + certificates are loaded from the specified PEM file + (``file-name``). If the file is not specified, the default + certificates from the global certificates store are used. + +.. option:: +tls-certfile=file-name, +tls-keyfile=file-name, +notls-certfile, +notls-keyfile + + These options set the state of certificate-based client + authentication for DNS transports, relying on TLS. Both certificate + chain file and private key file are expected to be in PEM format. + Both options must be specified at the same time. + +.. option:: +tls-hostname=hostname, +notls-hostname + + This option makes :program:`dig` use the provided hostname during remote + server TLS certificate verification. Otherwise, the DNS server name + is used. This option has no effect if :option:`+tls-ca` is not specified. + +.. option:: +trace, +notrace + + This option toggles tracing of the delegation path from the root name + servers for the name being looked up. Tracing is disabled by default. + When tracing is enabled, :program:`dig` makes iterative queries to + resolve the name being looked up. It follows referrals from the root + servers, showing the answer from each server that was used to resolve + the lookup. + + If ``@server`` is also specified, it affects only the initial query for + the root zone name servers. + + :option:`+dnssec` is set when :option:`+trace` is set, to better + emulate the default queries from a name server. + + Note that the ``delv +ns`` option can also be used for tracing the + resolution of a name from the root (see :iscman:`delv`). + +.. option:: +tries=T + + This option sets the number of times to try UDP and TCP queries to server to ``T`` + instead of the default, 3. If ``T`` is less than or equal to zero, + the number of tries is silently rounded up to 1. + +.. option:: +ttlid, +nottlid + + This option displays [or does not display] the TTL when printing the record. + +.. option:: +ttlunits, +nottlunits + + This option displays [or does not display] the TTL in friendly human-readable time + units of ``s``, ``m``, ``h``, ``d``, and ``w``, representing seconds, minutes, + hours, days, and weeks. This implies :option:`+ttlid`. + +.. option:: +unknownformat, +nounknownformat + + This option prints all RDATA in unknown RR type presentation format (:rfc:`3597`). + The default is to print RDATA for known types in the type's + presentation format. + +.. option:: +vc, +novc + + This option uses [or does not use] TCP when querying name servers. This alternate + syntax to :option:`+tcp` is provided for backwards compatibility. The + ``vc`` stands for "virtual circuit." + +.. option:: +yaml, +noyaml + + When enabled, this option prints the responses (and, if :option:`+qr` is in use, also the + outgoing queries) in a detailed YAML format. + +.. option:: +zflag, +nozflag + + This option sets [or does not set] the last unassigned DNS header flag in a DNS query. + This flag is off by default. + +Multiple Queries +~~~~~~~~~~~~~~~~ + +The BIND 9 implementation of :program:`dig` supports specifying multiple +queries on the command line (in addition to supporting the :option:`-f` batch +file option). Each of those queries can be supplied with its own set of +flags, options, and query options. + +In this case, each ``query`` argument represents an individual query in +the command-line syntax described above. Each consists of any of the +standard options and flags, the name to be looked up, an optional query +type and class, and any query options that should be applied to that +query. + +A global set of query options, which should be applied to all queries, +can also be supplied. These global query options must precede the first +tuple of name, class, type, options, flags, and query options supplied +on the command line. Any global query options (except :option:`+cmd` and +:option:`+short` options) can be overridden by a query-specific set of +query options. For example: + +:: + + dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr + +shows how :program:`dig` can be used from the command line to make three +lookups: an ANY query for ``www.isc.org``, a reverse lookup of 127.0.0.1, +and a query for the NS records of ``isc.org``. A global query option of +:option:`+qr` is applied, so that :program:`dig` shows the initial query it made for +each lookup. The final query has a local query option of :option:`+noqr` which +means that :program:`dig` does not print the initial query when it looks up the +NS records for ``isc.org``. + +Return Codes +~~~~~~~~~~~~ + +:program:`dig` return codes are: + +``0`` + DNS response received, including NXDOMAIN status + +``1`` + Usage error + +``8`` + Couldn't open batch file + +``9`` + No reply from server + +``10`` + Internal error + +Files +~~~~~ + +``/etc/resolv.conf`` + +``${HOME}/.digrc`` + +See Also +~~~~~~~~ + +:iscman:`delv(1) `, :iscman:`host(1) `, :iscman:`named(8) `, :iscman:`dnssec-keygen(8) `, :rfc:`1035`. + +Bugs +~~~~ + +There are probably too many query options. diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c new file mode 100644 index 0000000..b7e3c52 --- /dev/null +++ b/bin/dig/dighost.c @@ -0,0 +1,4932 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file + * \note + * Notice to programmers: Do not use this code as an example of how to + * use the ISC library to perform DNS lookups. Dig and Host both operate + * on the request level, since they allow fine-tuning of output and are + * intended as debugging tools. As a result, they perform many of the + * functions which could be better handled using the dns_resolver + * functions in most applications. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBIDN2 +#include +#endif /* HAVE_LIBIDN2 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "dighost.h" + +#define systemlocale(l) (void)setlocale(l, "") +#define resetlocale(l) (void)setlocale(l, "C") + +dig_lookuplist_t lookup_list; +dig_serverlist_t server_list; +dig_searchlistlist_t search_list; + +static bool cancel_now = false; + +bool check_ra = false, have_ipv4 = false, have_ipv6 = false, + specified_source = false, free_now = false, usesearch = false, + showsearch = false, is_dst_up = false, keep_open = false, verbose = false, + yaml = false; +in_port_t port = 53; +bool port_set = false; +unsigned int timeout = 0; +unsigned int extrabytes; +isc_mem_t *mctx = NULL; +isc_log_t *lctx = NULL; +isc_nm_t *netmgr = NULL; +isc_loopmgr_t *loopmgr = NULL; +isc_loop_t *mainloop = NULL; +isc_sockaddr_t localaddr; +isc_refcount_t sendcount = 0; +isc_refcount_t recvcount = 0; +int ndots = -1; +int tries = -1; +int lookup_counter = 0; + +static char servercookie[256]; + +#ifdef HAVE_LIBIDN2 +static void +idn_input(const char *src, char *dst, size_t dstlen); +#endif /* HAVE_LIBIDN2 */ + +isc_nmhandle_t *keep = NULL; +isc_sockaddr_t keepaddr; + +/*% + * Exit Codes: + * + *\li 0 Everything went well, including things like NXDOMAIN + *\li 1 Usage error + *\li 7 Got too many RR's or Names + *\li 8 Couldn't open batch file + *\li 9 No reply from server + *\li 10 Internal error + */ +int exitcode = 0; +int fatalexit = 0; +char keynametext[MXNAME]; +char keyfile[MXNAME] = ""; +char keysecret[MXNAME] = ""; +unsigned char cookie_secret[33]; +unsigned char cookie[8]; +dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; +unsigned int digestbits = 0; +isc_buffer_t *namebuf = NULL; +dns_tsigkey_t *tsigkey = NULL; +dst_key_t *sig0key = NULL; +bool validated = true; +bool debugging = false; +bool debugtiming = false; +bool memdebugging = false; +char *progname = NULL; +dig_lookup_t *current_lookup = NULL; + +#define DIG_MAX_ADDRESSES 20 + +static void +default_warnerr(const char *format, ...) { + va_list args; + + printf(";; "); + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); +} + +static void +default_comments(dig_lookup_t *lookup, const char *format, ...) { + va_list args; + + if (lookup->comments) { + printf(";; "); + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); + } +} + +/* dynamic callbacks */ + +isc_result_t (*dighost_printmessage)(dig_query_t *query, + const isc_buffer_t *msgbuf, + dns_message_t *msg, bool headers); + +void (*dighost_error)(const char *format, ...) = default_warnerr; + +void (*dighost_warning)(const char *format, ...) = default_warnerr; + +void (*dighost_comments)(dig_lookup_t *lookup, const char *format, + ...) = default_comments; + +void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, + dig_query_t *query); + +void (*dighost_trying)(char *frm, dig_lookup_t *lookup); + +void (*dighost_shutdown)(void); + +/* forward declarations */ + +#define cancel_lookup(l) _cancel_lookup(l, __FILE__, __LINE__) +static void +_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line); + +static void +recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg); + +static void +start_udp(dig_query_t *query); + +static void +start_tcp(dig_query_t *query); + +static void +force_next(dig_query_t *query); + +static void +launch_next_query(dig_query_t *query); + +static void +clear_current_lookup(void); + +static bool +next_origin(dig_lookup_t *oldlookup); + +static int +count_dots(char *string) { + char *s; + int i = 0; + + s = string; + while (*s != '\0') { + if (*s == '.') { + i++; + } + s++; + } + return i; +} + +static void +hex_dump(isc_buffer_t *b) { + unsigned int len, i; + isc_region_t r; + + isc_buffer_usedregion(b, &r); + + printf("%u bytes\n", r.length); + for (len = 0; len < r.length; len++) { + printf("%02x ", r.base[len]); + if (len % 16 == 15) { + printf(" "); + for (i = len - 15; i <= len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') { + putchar(r.base[i]); + } else { + putchar('.'); + } + } + printf("\n"); + } + } + if (len % 16 != 0) { + for (i = len; (i % 16) != 0; i++) { + printf(" "); + } + printf(" "); + for (i = ((len >> 4) << 4); i < len; i++) { + if (r.base[i] >= '!' && r.base[i] <= '}') { + putchar(r.base[i]); + } else { + putchar('.'); + } + } + printf("\n"); + } +} + +/*% + * Append 'len' bytes of 'text' at '*p', failing with + * ISC_R_NOSPACE if that would advance p past 'end'. + */ +static isc_result_t +append(const char *text, size_t len, char **p, char *end) { + if (*p + len > end) { + return ISC_R_NOSPACE; + } + memmove(*p, text, len); + *p += len; + return ISC_R_SUCCESS; +} + +static isc_result_t +reverse_octets(const char *in, char **p, char *end) { + const char *dot = strchr(in, '.'); + size_t len; + if (dot != NULL) { + isc_result_t result; + result = reverse_octets(dot + 1, p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + result = append(".", 1, p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + len = (int)(dot - in); + } else { + len = (int)strlen(in); + } + return append(in, len, p, end); +} + +isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict) { + int r; + isc_result_t result; + isc_netaddr_t addr; + + addr.family = AF_INET6; + r = inet_pton(AF_INET6, value, &addr.type.in6); + if (r > 0) { + /* This is a valid IPv6 address. */ + dns_fixedname_t fname; + dns_name_t *name; + + name = dns_fixedname_initname(&fname); + result = dns_byaddr_createptrname(&addr, name); + if (result != ISC_R_SUCCESS) { + return result; + } + dns_name_format(name, reverse, (unsigned int)len); + return ISC_R_SUCCESS; + } else { + /* + * Not a valid IPv6 address. Assume IPv4. + * If 'strict' is not set, construct the + * in-addr.arpa name by blindly reversing + * octets whether or not they look like integers, + * so that this can be used for RFC2317 names + * and such. + */ + char *p = reverse; + char *end = reverse + len; + if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) { + return DNS_R_BADDOTTEDQUAD; + } + result = reverse_octets(value, &p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + /* Append .in-addr.arpa. and a terminating NUL. */ + result = append(".in-addr.arpa.", 15, &p, end); + if (result != ISC_R_SUCCESS) { + return result; + } + return ISC_R_SUCCESS; + } +} + +#if TARGET_OS_IPHONE +void +warn(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, ";; Warning: "); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +} +#else /* if TARGET_OS_IPHONE */ +void +warn(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +} +#endif /* if TARGET_OS_IPHONE */ + +void +digexit(void) { + if (exitcode < 10) { + exitcode = 10; + } + if (fatalexit != 0) { + _exit(fatalexit); + } + exit(exitcode); +} + +void +fatal(const char *format, ...) { + va_list args; + + fflush(stdout); + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + if (fatalexit == 0 && exitcode != 0) { + fatalexit = exitcode; + } else if (fatalexit == 0) { + fatalexit = EXIT_FAILURE; + } + digexit(); +} + +void +debug(const char *format, ...) { + va_list args; + isc_time_t t; + + if (debugging) { + fflush(stdout); + if (debugtiming) { + t = isc_time_now(); + fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t), + isc_time_nanoseconds(&t) / 1000); + } + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + +void +check_result(isc_result_t result, const char *msg) { + if (result != ISC_R_SUCCESS) { + fatal("%s: %s", msg, isc_result_totext(result)); + } +} + +/*% + * Create a server structure, which is part of the lookup structure. + * This is little more than a linked list of servers to query in hopes + * of finding the answer the user is looking for + */ +dig_server_t * +make_server(const char *servname, const char *userarg) { + dig_server_t *srv; + + REQUIRE(servname != NULL); + + debug("make_server(%s)", servname); + srv = isc_mem_allocate(mctx, sizeof(struct dig_server)); + strlcpy(srv->servername, servname, MXNAME); + strlcpy(srv->userarg, userarg, MXNAME); + ISC_LINK_INIT(srv, link); + return srv; +} + +/*% + * Create a copy of the server list from the resolver configuration structure. + * The dest list must have already had ISC_LIST_INIT applied. + */ +static void +get_server_list(irs_resconf_t *resconf) { + isc_sockaddrlist_t *servers; + isc_sockaddr_t *sa; + dig_server_t *newsrv; + char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + + sizeof("%4000000000")]; + debug("get_server_list()"); + servers = irs_resconf_getnameservers(resconf); + for (sa = ISC_LIST_HEAD(*servers); sa != NULL; + sa = ISC_LIST_NEXT(sa, link)) + { + int pf = isc_sockaddr_pf(sa); + isc_netaddr_t na; + isc_result_t result; + isc_buffer_t b; + + if (pf == AF_INET && !have_ipv4) { + continue; + } + if (pf == AF_INET6 && !have_ipv6) { + continue; + } + + isc_buffer_init(&b, tmp, sizeof(tmp)); + isc_netaddr_fromsockaddr(&na, sa); + result = isc_netaddr_totext(&na, &b); + if (result != ISC_R_SUCCESS) { + continue; + } + isc_buffer_putuint8(&b, 0); + if (pf == AF_INET6 && na.zone != 0) { + char buf[sizeof("%4000000000")]; + snprintf(buf, sizeof(buf), "%%%u", na.zone); + strlcat(tmp, buf, sizeof(tmp)); + } + newsrv = make_server(tmp, tmp); + ISC_LINK_INIT(newsrv, link); + ISC_LIST_APPEND(server_list, newsrv, link); + } +} + +void +flush_server_list(void) { + dig_server_t *s, *ps; + + debug("flush_server_list()"); + s = ISC_LIST_HEAD(server_list); + while (s != NULL) { + ps = s; + s = ISC_LIST_NEXT(s, link); + ISC_LIST_DEQUEUE(server_list, ps, link); + isc_mem_free(mctx, ps); + } +} + +void +set_nameserver(char *opt) { + isc_result_t result; + isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; + isc_netaddr_t netaddr; + int count, i; + dig_server_t *srv; + char tmp[ISC_NETADDR_FORMATSIZE]; + + if (opt == NULL) { + return; + } + + isc_loopmgr_blocking(loopmgr); + result = isc_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES, &count); + isc_loopmgr_nonblocking(loopmgr); + if (result != ISC_R_SUCCESS) { + fatal("couldn't get address for '%s': %s", opt, + isc_result_totext(result)); + } + + flush_server_list(); + + for (i = 0; i < count; i++) { + isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); + isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); + srv = make_server(tmp, opt); + if (srv == NULL) { + fatal("memory allocation failure"); + } + ISC_LIST_APPEND(server_list, srv, link); + } +} + +/*% + * Produce a cloned server list. The dest list must have already had + * ISC_LIST_INIT applied. + */ +void +clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) { + dig_server_t *srv, *newsrv; + + debug("clone_server_list()"); + srv = ISC_LIST_HEAD(src); + while (srv != NULL) { + newsrv = make_server(srv->servername, srv->userarg); + ISC_LINK_INIT(newsrv, link); + ISC_LIST_ENQUEUE(*dest, newsrv, link); + srv = ISC_LIST_NEXT(srv, link); + } +} + +/*% + * Create an empty lookup structure, which holds all the information needed + * to get an answer to a user's question. This structure contains two + * linked lists: the server list (servers to query) and the query list + * (outstanding queries which have been made to the listed servers). + */ +dig_lookup_t * +make_empty_lookup(void) { + dig_lookup_t *looknew; + int idnin = false, idnout = false; + +#ifdef HAVE_LIBIDN2 + if (getenv("IDN_DISABLE") == NULL) { + idnin = true; + idnout = isatty(1); + } +#endif /* HAVE_LIBIDN2 */ + + debug("make_empty_lookup()"); + + INSIST(!free_now); + + looknew = isc_mem_allocate(mctx, sizeof(*looknew)); + *looknew = (dig_lookup_t){ + .pending = true, + .rdtype = dns_rdatatype_a, + .qrdtype = dns_rdatatype_a, + .rdclass = dns_rdataclass_in, + .servfail_stops = true, + .besteffort = true, + .opcode = dns_opcode_query, + .badcookie = true, + .idnin = idnin, + .idnout = idnout, + .udpsize = -1, + .edns = -1, + .original_edns = -1, + .recurse = true, + .retries = tries, + .comments = true, + .stats = true, + .section_question = true, + .section_answer = true, + .section_authority = true, + .section_additional = true, + .ednsneg = true, + }; + + dns_fixedname_init(&looknew->fdomain); + ISC_LINK_INIT(looknew, link); + ISC_LIST_INIT(looknew->q); + ISC_LIST_INIT(looknew->my_server_list); + + isc_tlsctx_cache_create(mctx, &looknew->tls_ctx_cache); + + isc_refcount_init(&looknew->references, 1); + + looknew->magic = DIG_LOOKUP_MAGIC; + + debug("make_empty_lookup() = %p->references = %" PRIuFAST32, looknew, + isc_refcount_current(&looknew->references)); + + return looknew; +} + +#define EDNSOPT_OPTIONS 100U + +static void +cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) { + size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS; + size_t i; + looknew->ednsopts = isc_mem_allocate(mctx, len); + for (i = 0; i < EDNSOPT_OPTIONS; i++) { + looknew->ednsopts[i].code = 0; + looknew->ednsopts[i].length = 0; + looknew->ednsopts[i].value = NULL; + } + looknew->ednsoptscnt = 0; + if (lookold == NULL || lookold->ednsopts == NULL) { + return; + } + + for (i = 0; i < lookold->ednsoptscnt; i++) { + len = lookold->ednsopts[i].length; + if (len != 0) { + INSIST(lookold->ednsopts[i].value != NULL); + looknew->ednsopts[i].value = isc_mem_allocate(mctx, + len); + memmove(looknew->ednsopts[i].value, + lookold->ednsopts[i].value, len); + } + looknew->ednsopts[i].code = lookold->ednsopts[i].code; + looknew->ednsopts[i].length = len; + } + looknew->ednsoptscnt = lookold->ednsoptscnt; +} + +/*% + * Clone a lookup, perhaps copying the server list. This does not clone + * the query list, since it will be regenerated by the setup_lookup() + * function, nor does it queue up the new lookup for processing. + * Caution: If you don't clone the servers, you MUST clone the server + * list separately from somewhere else, or construct it by hand. + */ +dig_lookup_t * +clone_lookup(dig_lookup_t *lookold, bool servers) { + dig_lookup_t *looknew; + + debug("clone_lookup()"); + + INSIST(!free_now); + + looknew = make_empty_lookup(); + strlcpy(looknew->textname, lookold->textname, MXNAME); + strlcpy(looknew->cmdline, lookold->cmdline, MXNAME); + looknew->textname[MXNAME - 1] = 0; + looknew->rdtype = lookold->rdtype; + looknew->qrdtype = lookold->qrdtype; + looknew->rdclass = lookold->rdclass; + looknew->rdtypeset = lookold->rdtypeset; + looknew->rdclassset = lookold->rdclassset; + looknew->doing_xfr = lookold->doing_xfr; + looknew->ixfr_serial = lookold->ixfr_serial; + looknew->trace = lookold->trace; + looknew->trace_root = lookold->trace_root; + looknew->identify = lookold->identify; + looknew->identify_previous_line = lookold->identify_previous_line; + looknew->ignore = lookold->ignore; + looknew->servfail_stops = lookold->servfail_stops; + looknew->besteffort = lookold->besteffort; + looknew->dns64prefix = lookold->dns64prefix; + looknew->dnssec = lookold->dnssec; + looknew->ednsflags = lookold->ednsflags; + looknew->opcode = lookold->opcode; + looknew->expire = lookold->expire; + looknew->nsid = lookold->nsid; + looknew->tcp_keepalive = lookold->tcp_keepalive; + looknew->header_only = lookold->header_only; + looknew->https_mode = lookold->https_mode; + if (lookold->https_path != NULL) { + looknew->https_path = isc_mem_strdup(mctx, lookold->https_path); + } + looknew->https_get = lookold->https_get; + looknew->http_plain = lookold->http_plain; + + looknew->tls_ca_set = lookold->tls_ca_set; + if (lookold->tls_ca_file != NULL) { + looknew->tls_ca_file = isc_mem_strdup(mctx, + lookold->tls_ca_file); + }; + + looknew->tls_hostname_set = lookold->tls_hostname_set; + if (lookold->tls_hostname != NULL) { + looknew->tls_hostname = isc_mem_strdup(mctx, + lookold->tls_hostname); + } + + looknew->tls_key_file_set = lookold->tls_key_file_set; + if (lookold->tls_key_file != NULL) { + looknew->tls_key_file = isc_mem_strdup(mctx, + lookold->tls_key_file); + } + + looknew->tls_cert_file_set = lookold->tls_cert_file_set; + if (lookold->tls_cert_file != NULL) { + looknew->tls_cert_file = isc_mem_strdup(mctx, + lookold->tls_cert_file); + } + + looknew->showbadcookie = lookold->showbadcookie; + looknew->showbadvers = lookold->showbadvers; + looknew->sendcookie = lookold->sendcookie; + looknew->seenbadcookie = lookold->seenbadcookie; + looknew->badcookie = lookold->badcookie; + looknew->cookie = lookold->cookie; + if (lookold->ednsopts != NULL) { + cloneopts(looknew, lookold); + } else { + looknew->ednsopts = NULL; + looknew->ednsoptscnt = 0; + } + looknew->ednsneg = lookold->ednsneg; + looknew->padding = lookold->padding; + looknew->multiline = lookold->multiline; + looknew->nottl = lookold->nottl; + looknew->noclass = lookold->noclass; + looknew->onesoa = lookold->onesoa; + looknew->use_usec = lookold->use_usec; + looknew->nocrypto = lookold->nocrypto; + looknew->ttlunits = lookold->ttlunits; + looknew->expandaaaa = lookold->expandaaaa; + looknew->qr = lookold->qr; + looknew->idnin = lookold->idnin; + looknew->idnout = lookold->idnout; + looknew->udpsize = lookold->udpsize; + looknew->edns = lookold->edns; + looknew->original_edns = lookold->original_edns; + looknew->recurse = lookold->recurse; + looknew->aaonly = lookold->aaonly; + looknew->adflag = lookold->adflag; + looknew->cdflag = lookold->cdflag; + looknew->raflag = lookold->raflag; + looknew->tcflag = lookold->tcflag; + looknew->print_unknown_format = lookold->print_unknown_format; + looknew->zflag = lookold->zflag; + looknew->setqid = lookold->setqid; + looknew->qid = lookold->qid; + looknew->ns_search_only = lookold->ns_search_only; + looknew->tcp_mode = lookold->tcp_mode; + looknew->tcp_mode_set = lookold->tcp_mode_set; + looknew->tls_mode = lookold->tls_mode; + looknew->comments = lookold->comments; + looknew->stats = lookold->stats; + looknew->section_question = lookold->section_question; + looknew->section_answer = lookold->section_answer; + looknew->section_authority = lookold->section_authority; + looknew->section_additional = lookold->section_additional; + looknew->origin = lookold->origin; + looknew->retries = lookold->retries; + looknew->tsigctx = NULL; + looknew->need_search = lookold->need_search; + looknew->done_as_is = lookold->done_as_is; + looknew->rrcomments = lookold->rrcomments; + looknew->fuzzing = lookold->fuzzing; + looknew->fuzztime = lookold->fuzztime; + looknew->proxy_mode = lookold->proxy_mode; + looknew->proxy_plain = lookold->proxy_plain; + looknew->proxy_local = lookold->proxy_local; + looknew->proxy_src_addr = lookold->proxy_src_addr; + looknew->proxy_dst_addr = lookold->proxy_dst_addr; + + if (lookold->ecs_addr != NULL) { + looknew->ecs_addr = isc_mem_get(mctx, + sizeof(*looknew->ecs_addr)); + memmove(looknew->ecs_addr, lookold->ecs_addr, + sizeof(*looknew->ecs_addr)); + } + + dns_name_copy(dns_fixedname_name(&lookold->fdomain), + dns_fixedname_name(&looknew->fdomain)); + + if (servers) { + if (lookold->tls_ctx_cache != NULL) { + isc_tlsctx_cache_detach(&looknew->tls_ctx_cache); + isc_tlsctx_cache_attach(lookold->tls_ctx_cache, + &looknew->tls_ctx_cache); + } + clone_server_list(lookold->my_server_list, + &looknew->my_server_list); + } + + isc_refcount_init(&looknew->references, 1); + + looknew->magic = DIG_LOOKUP_MAGIC; + + return looknew; +} + +/*% + * Requeue a lookup for further processing, perhaps copying the server + * list. The new lookup structure is returned to the caller, and is + * queued for processing. If servers are not cloned in the requeue, they + * must be added before allowing the current event to complete, since the + * completion of the event may result in the next entry on the lookup + * queue getting run. + */ +dig_lookup_t * +requeue_lookup(dig_lookup_t *lookold, bool servers) { + dig_lookup_t *looknew = NULL; + + debug("requeue_lookup()"); + + lookup_counter++; + if (lookup_counter > LOOKUP_LIMIT) { + fatal("too many lookups"); + } + + looknew = clone_lookup(lookold, servers); + INSIST(looknew != NULL); + + debug("before insertion, init@%p -> %p, new@%p -> %p", lookold, + lookold->link.next, looknew, looknew->link.next); + ISC_LIST_PREPEND(lookup_list, looknew, link); + debug("after insertion, init -> %p, new = %p, new -> %p", lookold, + looknew, looknew->link.next); + return looknew; +} + +void +setup_text_key(void) { + isc_result_t result; + dns_name_t keyname; + isc_buffer_t secretbuf; + unsigned int secretsize; + unsigned char *secretstore; + + debug("setup_text_key()"); + isc_buffer_allocate(mctx, &namebuf, MXNAME); + dns_name_init(&keyname, NULL); + isc_buffer_putstr(namebuf, keynametext); + secretsize = (unsigned int)strlen(keysecret) * 3 / 4; + secretstore = isc_mem_allocate(mctx, secretsize); + isc_buffer_init(&secretbuf, secretstore, secretsize); + result = isc_base64_decodestring(keysecret, &secretbuf); + if (result != ISC_R_SUCCESS) { + goto failure; + } + + secretsize = isc_buffer_usedlength(&secretbuf); + + if (hmac_alg == DST_ALG_UNKNOWN) { + result = DST_R_UNSUPPORTEDALG; + goto failure; + } + + result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf); + if (result != ISC_R_SUCCESS) { + goto failure; + } + + result = dns_tsigkey_create(&keyname, hmac_alg, secretstore, + (int)secretsize, mctx, &tsigkey); +failure: + if (result != ISC_R_SUCCESS) { + printf(";; Couldn't create key %s: %s\n", keynametext, + isc_result_totext(result)); + } else { + dst_key_setbits(tsigkey->key, digestbits); + } + + isc_mem_free(mctx, secretstore); + dns_name_invalidate(&keyname); + isc_buffer_free(&namebuf); +} + +static isc_result_t +parse_uint_helper(uint32_t *uip, const char *value, uint32_t max, + const char *desc, int base) { + uint32_t n; + isc_result_t result = isc_parse_uint32(&n, value, base); + if (result == ISC_R_SUCCESS && n > max) { + result = ISC_R_RANGE; + } + if (result != ISC_R_SUCCESS) { + printf("invalid %s '%s': %s\n", desc, value, + isc_result_totext(result)); + return result; + } + *uip = n; + return ISC_R_SUCCESS; +} + +isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { + return parse_uint_helper(uip, value, max, desc, 10); +} + +isc_result_t +parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) { + return parse_uint_helper(uip, value, max, desc, 0); +} + +static uint32_t +parse_bits(char *arg, const char *desc, uint32_t max) { + isc_result_t result; + uint32_t tmp; + + result = parse_uint(&tmp, arg, max, desc); + if (result != ISC_R_SUCCESS) { + fatal("couldn't parse digest bits"); + } + tmp = (tmp + 7) & ~0x7U; + return tmp; +} + +isc_result_t +parse_netprefix(isc_sockaddr_t **sap, const char *value) { + isc_result_t result = ISC_R_SUCCESS; + isc_sockaddr_t *sa = NULL; + struct in_addr in4; + struct in6_addr in6; + uint32_t prefix_length = 0xffffffff; + char *slash = NULL; + bool parsed = false; + bool prefix_parsed = false; + char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")]; + + REQUIRE(sap != NULL && *sap == NULL); + + if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) { + fatal("invalid prefix '%s'\n", value); + } + + sa = isc_mem_get(mctx, sizeof(*sa)); + *sa = (isc_sockaddr_t){ .length = 0 }; + + if (strcmp(buf, "0") == 0) { + sa->type.sa.sa_family = AF_UNSPEC; + prefix_length = 0; + goto done; + } + + slash = strchr(buf, '/'); + if (slash != NULL) { + *slash = '\0'; + result = isc_parse_uint32(&prefix_length, slash + 1, 10); + if (result != ISC_R_SUCCESS) { + fatal("invalid prefix length in '%s': %s\n", value, + isc_result_totext(result)); + } + prefix_parsed = true; + } + + if (inet_pton(AF_INET6, buf, &in6) == 1) { + parsed = true; + isc_sockaddr_fromin6(sa, &in6, 0); + if (prefix_length > 128) { + prefix_length = 128; + } + } else if (inet_pton(AF_INET, buf, &in4) == 1) { + parsed = true; + isc_sockaddr_fromin(sa, &in4, 0); + if (prefix_length > 32) { + prefix_length = 32; + } + } else if (prefix_parsed) { + int i; + + for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) { + strlcat(buf, ".0", sizeof(buf)); + if (inet_pton(AF_INET, buf, &in4) == 1) { + parsed = true; + isc_sockaddr_fromin(sa, &in4, 0); + break; + } + } + + if (prefix_length > 32) { + prefix_length = 32; + } + } + + if (!parsed) { + fatal("invalid address '%s'", value); + } + +done: + sa->length = prefix_length; + *sap = sa; + + return ISC_R_SUCCESS; +} + +/* + * Parse HMAC algorithm specification + */ +void +parse_hmac(const char *algname) { + char buf[20]; + size_t len; + + REQUIRE(algname != NULL); + + len = strlen(algname); + if (len >= sizeof(buf)) { + fatal("unknown key type '%.*s'", (int)len, algname); + } + strlcpy(buf, algname, sizeof(buf)); + + digestbits = 0; + + if (strcasecmp(buf, "hmac-md5") == 0) { + hmac_alg = DST_ALG_HMACMD5; + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + hmac_alg = DST_ALG_HMACMD5; + digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); + } else if (strcasecmp(buf, "hmac-sha1") == 0) { + hmac_alg = DST_ALG_HMACSHA1; + digestbits = 0; + } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { + hmac_alg = DST_ALG_HMACSHA1; + digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160); + } else if (strcasecmp(buf, "hmac-sha224") == 0) { + hmac_alg = DST_ALG_HMACSHA224; + } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { + hmac_alg = DST_ALG_HMACSHA224; + digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224); + } else if (strcasecmp(buf, "hmac-sha256") == 0) { + hmac_alg = DST_ALG_HMACSHA256; + } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { + hmac_alg = DST_ALG_HMACSHA256; + digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256); + } else if (strcasecmp(buf, "hmac-sha384") == 0) { + hmac_alg = DST_ALG_HMACSHA384; + } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { + hmac_alg = DST_ALG_HMACSHA384; + digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384); + } else if (strcasecmp(buf, "hmac-sha512") == 0) { + hmac_alg = DST_ALG_HMACSHA512; + } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { + hmac_alg = DST_ALG_HMACSHA512; + digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512); + } else { + fprintf(stderr, + ";; Warning, ignoring " + "invalid TSIG algorithm %s\n", + buf); + } +} + +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_confkey(void) { + cfg_parser_t *pctx = NULL; + cfg_obj_t *file = NULL; + const cfg_obj_t *keyobj = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *keyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + + if (!isc_file_exists(keyfile)) { + return ISC_R_FILENOTFOUND; + } + + result = cfg_parser_create(mctx, NULL, &pctx); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = cfg_map_get(file, "key", &keyobj); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + (void)cfg_map_get(keyobj, "secret", &secretobj); + (void)cfg_map_get(keyobj, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) { + fatal("key must have algorithm and secret"); + } + + keyname = cfg_obj_asstring(cfg_map_getname(keyobj)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + strlcpy(keynametext, keyname, sizeof(keynametext)); + strlcpy(keysecret, secretstr, sizeof(keysecret)); + parse_hmac(algorithm); + setup_text_key(); + +cleanup: + if (pctx != NULL) { + if (file != NULL) { + cfg_obj_destroy(pctx, &file); + } + cfg_parser_destroy(&pctx); + } + + return result; +} + +void +setup_file_key(void) { + isc_result_t result; + dst_key_t *dstkey = NULL; + + debug("setup_file_key()"); + + if (sig0key != NULL) { + dst_key_free(&sig0key); + } + + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile( + keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_confkey(); + if (result == ISC_R_SUCCESS) { + return; + } + } + + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile, + isc_result_totext(result)); + goto failure; + } + + switch (dst_key_alg(dstkey)) { + case DST_ALG_HMACMD5: + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: + case DST_ALG_HMACSHA256: + case DST_ALG_HMACSHA384: + case DST_ALG_HMACSHA512: + hmac_alg = dst_key_alg(dstkey); + break; + default: + dst_key_attach(dstkey, &sig0key); + dst_key_free(&dstkey); + return; + } + + if (dstkey != NULL) { + result = dns_tsigkey_createfromkey( + dst_key_name(dstkey), hmac_alg, dstkey, false, false, + NULL, 0, 0, mctx, &tsigkey); + if (result != ISC_R_SUCCESS) { + printf(";; Couldn't create key %s: %s\n", keynametext, + isc_result_totext(result)); + } + } + +failure: + if (dstkey != NULL) { + dst_key_free(&dstkey); + } +} + +static dig_searchlist_t * +make_searchlist_entry(char *domain) { + dig_searchlist_t *search; + search = isc_mem_allocate(mctx, sizeof(*search)); + strlcpy(search->origin, domain, MXNAME); + search->origin[MXNAME - 1] = 0; + ISC_LINK_INIT(search, link); + return search; +} + +static void +clear_searchlist(void) { + dig_searchlist_t *search; + while ((search = ISC_LIST_HEAD(search_list)) != NULL) { + ISC_LIST_UNLINK(search_list, search, link); + isc_mem_free(mctx, search); + } +} + +static void +create_search_list(irs_resconf_t *resconf) { + irs_resconf_searchlist_t *list; + irs_resconf_search_t *entry; + dig_searchlist_t *search; + + debug("create_search_list()"); + clear_searchlist(); + + list = irs_resconf_getsearchlist(resconf); + for (entry = ISC_LIST_HEAD(*list); entry != NULL; + entry = ISC_LIST_NEXT(entry, link)) + { + search = make_searchlist_entry(entry->domain); + ISC_LIST_APPEND(search_list, search, link); + } +} + +/*% + * Append 'addr' to the list of servers to be queried. This function is only + * called when no server addresses are explicitly specified and either libirs + * returns an empty list of servers to use or none of the addresses returned by + * libirs are usable due to the specified address family restrictions. + */ +static void +add_fallback_nameserver(const char *addr) { + dig_server_t *server = make_server(addr, addr); + ISC_LINK_INIT(server, link); + ISC_LIST_APPEND(server_list, server, link); +} + +/*% + * Setup the system as a whole, reading key information and resolv.conf + * settings. + */ +void +setup_system(bool ipv4only, bool ipv6only) { + irs_resconf_t *resconf = NULL; + isc_result_t result; + + debug("setup_system()"); + + if (ipv4only) { + if (have_ipv4) { + isc_net_disableipv6(); + have_ipv6 = false; + } else { + fatal("can't find IPv4 networking"); + } + } + + if (ipv6only) { + if (have_ipv6) { + isc_net_disableipv4(); + have_ipv4 = false; + } else { + fatal("can't find IPv6 networking"); + } + } + + result = irs_resconf_load(mctx, RESOLV_CONF, &resconf); + if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { + fatal("parse of %s failed", RESOLV_CONF); + } + + create_search_list(resconf); + if (ndots == -1) { + ndots = irs_resconf_getndots(resconf); + debug("ndots is %d.", ndots); + } + if (timeout == 0) { + timeout = irs_resconf_gettimeout(resconf); + debug("timeout is %d.", timeout); + } + if (tries == -1) { + tries = irs_resconf_getattempts(resconf); + if (tries == 0) { + tries = 3; + } + debug("retries is %d.", tries); + } + + /* If user doesn't specify server use nameservers from resolv.conf. */ + if (ISC_LIST_EMPTY(server_list)) { + get_server_list(resconf); + } + + /* If we don't find a nameserver fall back to localhost */ + if (ISC_LIST_EMPTY(server_list)) { + if (have_ipv6) { + add_fallback_nameserver("::1"); + } + if (have_ipv4) { + add_fallback_nameserver("127.0.0.1"); + } + } + + irs_resconf_destroy(&resconf); + + if (keyfile[0] != 0) { + setup_file_key(); + } else if (keysecret[0] != 0) { + setup_text_key(); + } + + isc_nonce_buf(cookie_secret, sizeof(cookie_secret)); +} + +/*% + * Override the search list derived from resolv.conf by 'domain'. + */ +void +set_search_domain(char *domain) { + dig_searchlist_t *search; + + clear_searchlist(); + search = make_searchlist_entry(domain); + ISC_LIST_APPEND(search_list, search, link); +} + +/*% + * Setup the ISC and DNS libraries for use by the system. + */ +void +setup_libs(void) { + isc_result_t result; + isc_logconfig_t *logconfig = NULL; + + debug("setup_libs()"); + + result = isc_net_probeipv4(); + if (result == ISC_R_SUCCESS) { + have_ipv4 = true; + } + + result = isc_net_probeipv6(); + if (result == ISC_R_SUCCESS) { + have_ipv6 = true; + } + if (!have_ipv6 && !have_ipv4) { + fatal("can't find either v4 or v6 networking"); + } + + isc_managers_create(&mctx, 1, &loopmgr, &netmgr); + + isc_log_create(mctx, &lctx, &logconfig); + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + + result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); + check_result(result, "isc_log_usechannel"); + + isc_log_setdebuglevel(lctx, 0); + + isc_mem_setname(mctx, "dig"); + mainloop = isc_loop_main(loopmgr); + + result = dst_lib_init(mctx, NULL); + check_result(result, "dst_lib_init"); + is_dst_up = true; +} + +typedef struct dig_ednsoptname { + uint32_t code; + const char *name; +} dig_ednsoptname_t; + +dig_ednsoptname_t optnames[] = { + { 1, "LLQ" }, /* draft-sekar-dns-llq */ + { 2, "UPDATE-LEASE" }, /* draft-ietf-dnssd-update-lease */ + { 2, "UL" }, /* draft-ietf-dnssd-update-lease */ + { 3, "NSID" }, /* RFC 5001 */ + { 5, "DAU" }, /* RFC 6975 */ + { 6, "DHU" }, /* RFC 6975 */ + { 7, "N3U" }, /* RFC 6975 */ + { 8, "ECS" }, /* RFC 7871 */ + { 9, "EXPIRE" }, /* RFC 7314 */ + { 10, "COOKIE" }, /* RFC 7873 */ + { 11, "KEEPALIVE" }, /* RFC 7828 */ + { 12, "PADDING" }, /* RFC 7830 */ + { 12, "PAD" }, /* shorthand */ + { 13, "CHAIN" }, /* RFC 7901 */ + { 14, "KEY-TAG" }, /* RFC 8145 */ + { 15, "EDE" }, /* ietf-dnsop-extended-error-16 */ + { 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */ + { 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */ + { 18, "REPORT-CHANNEL" }, /* RFC 9567 */ + { 18, "RC" }, /* shorthand */ + { 19, "ZONEVERSION" }, /* RFC 9660 */ + { 26946, "DEVICEID" }, /* Brian Hartvigsen */ +}; + +#define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0])) + +void +save_opt(dig_lookup_t *lookup, char *code, char *value) { + isc_result_t result; + uint32_t num = 0; + isc_buffer_t b; + bool found = false; + unsigned int i; + + if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) { + fatal("too many ednsopts"); + } + + for (i = 0; i < N_EDNS_OPTNAMES; i++) { + if (strcasecmp(code, optnames[i].name) == 0) { + num = optnames[i].code; + found = true; + break; + } + } + + if (!found) { + result = parse_uint(&num, code, 65535, "ednsopt"); + if (result != ISC_R_SUCCESS) { + fatal("bad edns code point: %s", code); + } + } + + if (lookup->ednsopts == NULL) { + cloneopts(lookup, NULL); + } + INSIST(lookup->ednsopts != NULL); + + if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) { + isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value); + } + + lookup->ednsopts[lookup->ednsoptscnt].code = num; + lookup->ednsopts[lookup->ednsoptscnt].length = 0; + lookup->ednsopts[lookup->ednsoptscnt].value = NULL; + + if (value != NULL) { + char *buf; + buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1); + isc_buffer_init(&b, buf, (unsigned int)strlen(value) / 2 + 1); + result = isc_hex_decodestring(value, &b); + check_result(result, "isc_hex_decodestring"); + lookup->ednsopts[lookup->ednsoptscnt].value = + isc_buffer_base(&b); + lookup->ednsopts[lookup->ednsoptscnt].length = + isc_buffer_usedlength(&b); + } + + lookup->ednsoptscnt++; +} + +/*% + * Add EDNS0 option record to a message. Currently, the only supported + * options are UDP buffer size, the DO bit, and EDNS options + * (e.g., NSID, COOKIE, client-subnet) + */ +static void +add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags, + dns_ednsopt_t *opts, size_t count) { + dns_rdataset_t *rdataset = NULL; + isc_result_t result; + + debug("add_opt()"); + result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags, + opts, count); + check_result(result, "dns_message_buildopt"); + result = dns_message_setopt(msg, rdataset); + check_result(result, "dns_message_setopt"); +} + +/*% + * Add a question section to a message, asking for the specified name, + * type, and class. + */ +static void +add_question(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype) { + dns_rdataset_t *rdataset; + + debug("add_question()"); + rdataset = NULL; + dns_message_gettemprdataset(message, &rdataset); + dns_rdataset_makequestion(rdataset, rdclass, rdtype); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +/*% + * Check if we're done with all the queued lookups, which is true iff + * all sockets, sends, and recvs are accounted for (counters == 0), + * and the lookup list is empty. + * If we are done, pass control back out to dighost_shutdown() (which is + * part of dig.c, host.c, or nslookup.c) to either shutdown the system as + * a whole or reseed the lookup list. + */ +static void +check_if_done(void) { + dig_lookup_t *lookup = NULL; + + debug("check_if_done()"); + debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full"); + + lookup = ISC_LIST_HEAD(lookup_list); + while (lookup != NULL) { + dig_lookup_t *next = NULL; + debug("pending lookup %p", lookup); + next = ISC_LIST_NEXT(lookup, link); + lookup = next; + } + + if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL && + isc_refcount_current(&sendcount) == 0) + { + INSIST(isc_refcount_current(&recvcount) == 0); + debug("shutting down"); + dighost_shutdown(); + + if (current_lookup == NULL && keep != NULL) { + isc_nmhandle_detach(&keep); + } + } +} + +/*% + * Check if we're done with all the queries in the lookup, except for + * the `except_q` query (can be NULL if no exception is required). + * Expects `l` to be a valid and locked lookup. + */ +static bool +check_if_queries_done(dig_lookup_t *l, dig_query_t *except_q) { + dig_query_t *q = ISC_LIST_HEAD(l->q); + + debug("check_if_queries_done(%p)", l); + + while (q != NULL) { + if (!q->started || isc_refcount_current(&q->references) > 1) { + if (!q->canceled && q != except_q) { + debug("there is a pending query %p", q); + return false; + } + } + q = ISC_LIST_NEXT(q, link); + } + + return true; +} + +static void +_destroy_lookup(dig_lookup_t *lookup) { + dig_server_t *s; + void *ptr; + + REQUIRE(lookup != NULL); + REQUIRE(ISC_LIST_EMPTY(lookup->q)); + + debug("destroy_lookup"); + + isc_refcount_destroy(&lookup->references); + + s = ISC_LIST_HEAD(lookup->my_server_list); + while (s != NULL) { + debug("freeing server %p belonging to %p", s, lookup); + ptr = s; + s = ISC_LIST_NEXT(s, link); + ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr, + link); + isc_mem_free(mctx, ptr); + } + if (lookup->sendmsg != NULL) { + dns_message_detach(&lookup->sendmsg); + } + if (lookup->querysig != NULL) { + debug("freeing buffer %p", lookup->querysig); + isc_buffer_free(&lookup->querysig); + } + if (lookup->sendspace != NULL) { + isc_mem_put(mctx, lookup->sendspace, COMMSIZE); + } + + if (lookup->tsigctx != NULL) { + dst_context_destroy(&lookup->tsigctx); + } + + if (lookup->ecs_addr != NULL) { + isc_mem_put(mctx, lookup->ecs_addr, sizeof(*lookup->ecs_addr)); + } + + if (lookup->ednsopts != NULL) { + size_t i; + for (i = 0; i < EDNSOPT_OPTIONS; i++) { + if (lookup->ednsopts[i].value != NULL) { + isc_mem_free(mctx, lookup->ednsopts[i].value); + } + } + isc_mem_free(mctx, lookup->ednsopts); + } + + if (lookup->https_path) { + isc_mem_free(mctx, lookup->https_path); + } + + if (lookup->tls_ctx_cache != NULL) { + isc_tlsctx_cache_detach(&lookup->tls_ctx_cache); + } + + if (lookup->tls_ca_file != NULL) { + isc_mem_free(mctx, lookup->tls_ca_file); + } + + if (lookup->tls_hostname != NULL) { + isc_mem_free(mctx, lookup->tls_hostname); + } + + if (lookup->tls_key_file != NULL) { + isc_mem_free(mctx, lookup->tls_key_file); + } + + if (lookup->tls_cert_file != NULL) { + isc_mem_free(mctx, lookup->tls_cert_file); + } + + isc_mem_free(mctx, lookup); +} + +#define lookup_attach(s, t) _lookup_attach(s, t, __FILE__, __LINE__) +static void +_lookup_attach(dig_lookup_t *lookup, dig_lookup_t **lookupp, const char *file, + unsigned int line) { + REQUIRE(DIG_VALID_LOOKUP(lookup)); + REQUIRE(lookupp != NULL && *lookupp == NULL); + + debug("%s:%u:lookup_attach(%p) = %" PRIuFAST32, file, line, lookup, + isc_refcount_current(&lookup->references) + 1); + + (void)isc_refcount_increment(&lookup->references); + + *lookupp = lookup; +} + +#define lookup_detach(l) _lookup_detach(l, __FILE__, __LINE__) +static void +_lookup_detach(dig_lookup_t **lookupp, const char *file, unsigned int line) { + REQUIRE(DIG_VALID_LOOKUP(*lookupp)); + + dig_lookup_t *lookup = *lookupp; + *lookupp = NULL; + + debug("%s:%u:lookup_detach(%p) = %" PRIuFAST32, file, line, lookup, + isc_refcount_current(&lookup->references) - 1); + + if (isc_refcount_decrement(&lookup->references) == 1) { + _destroy_lookup(lookup); + if (lookup == current_lookup) { + current_lookup = NULL; + start_lookup(); + } + } +} + +void +destroy_lookup(dig_lookup_t *lookup) { + REQUIRE(DIG_VALID_LOOKUP(lookup)); + + REQUIRE(isc_refcount_decrement(&lookup->references) == 1); + _destroy_lookup(lookup); +} + +/*% + * Destroy a query when we're done with it. WARNING: This routine + * WILL invalidate the query pointer. + */ +static void +destroy_query(dig_query_t *query, const char *file, unsigned int line) { + debug("%s:%u:destroy_query(%p) = %" PRIuFAST32, file, line, query, + isc_refcount_current(&query->references)); + + isc_refcount_destroy(&query->references); + + lookup_detach(&query->lookup); + + INSIST(query->recvspace != NULL); + + isc_mem_put(mctx, query->recvspace, COMMSIZE); + isc_mem_put(mctx, query->tmpsendspace, COMMSIZE); + + query->magic = 0; + isc_mem_free(mctx, query); +} + +#define query_attach(s, t) _query_attach(s, t, __FILE__, __LINE__) + +static void +_query_attach(dig_query_t *source, dig_query_t **targetp, const char *file, + unsigned int line) { + REQUIRE(DIG_VALID_QUERY(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + debug("%s:%u:query_attach(%p) = %" PRIuFAST32, file, line, source, + isc_refcount_current(&source->references) + 1); + + (void)isc_refcount_increment(&source->references); + + *targetp = source; +} + +#define query_detach(q) _query_detach(q, __FILE__, __LINE__) + +static void +_query_detach(dig_query_t **queryp, const char *file, unsigned int line) { + dig_query_t *query = NULL; + dig_lookup_t *lookup = NULL; + + REQUIRE(DIG_VALID_QUERY(*queryp)); + + query = *queryp; + *queryp = NULL; + + lookup = query->lookup; + + if (lookup->current_query == query) { + query_detach(&lookup->current_query); + } + + debug("%s:%u:query_detach(%p) = %" PRIuFAST32, file, line, query, + isc_refcount_current(&query->references) - 1); + + if (isc_refcount_decrement(&query->references) == 1) { + INSIST(query->readhandle == NULL); + INSIST(query->sendhandle == NULL); + + if (ISC_LINK_LINKED(query, link)) { + ISC_LIST_UNLINK(lookup->q, query, link); + } + destroy_query(query, file, line); + } +} + +/*% + * If we can, start the next lookup in the queue running. + * This assumes that the lookup on the head of the queue hasn't been + * started yet. It also removes the lookup from the head of the queue, + * setting the current_lookup pointer pointing to it. + */ +void +start_lookup(void) { + debug("start_lookup()"); + + if (cancel_now) { + return; + } + + /* + * If there's a current lookup running, we really shouldn't get + * here. + */ + INSIST(current_lookup == NULL); + + current_lookup = ISC_LIST_HEAD(lookup_list); + + /* + * Put the current lookup somewhere so cancel_all can find it + */ + if (current_lookup != NULL) { + /* + * Formally, we should attach the lookup to the current_lookup + * and detach it from the lookup_list, but it would be one + * attach and one detach. + */ + ISC_LIST_DEQUEUE(lookup_list, current_lookup, link); + if (setup_lookup(current_lookup)) { + do_lookup(current_lookup); + } else if (next_origin(current_lookup)) { + lookup_detach(¤t_lookup); + start_lookup(); + } + } else { + check_if_done(); + } +} + +/*% + * If we can, clear the current lookup and start the next one running. + * (Note that while the reference count of current_lookup may be + * decremented, current_lookup will not be set to NULL.) + */ +static void +clear_current_lookup(void) { + dig_lookup_t *lookup = current_lookup; + + INSIST(!free_now); + + debug("clear_current_lookup()"); + + if (lookup == NULL) { + debug("current_lookup is already detached"); + return; + } + + if (lookup->cleared) { + debug("current_lookup is already cleared"); + return; + } + + if (ISC_LIST_HEAD(lookup->q) != NULL) { + debug("still have a worker"); + return; + } + + lookup->cleared = true; + debug("lookup cleared"); + + lookup_detach(&lookup); +} + +/*% + * Create and queue a new lookup as a followup to the current lookup, + * based on the supplied message and section. This is used in trace and + * name server search modes to start a new lookup using servers from + * NS records in a reply. Returns the number of followup lookups made. + */ +static int +followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { + dig_lookup_t *lookup = NULL; + dig_server_t *srv = NULL; + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_name_t *name = NULL; + isc_result_t result; + bool success = false; + int numLookups = 0; + int num; + isc_result_t lresult, addresses_result; + char bad_namestr[DNS_NAME_FORMATSIZE]; + dns_name_t *domain; + bool horizontal = false, bad = false; + + INSIST(!free_now); + + debug("following up %s", query->lookup->textname); + + addresses_result = ISC_R_SUCCESS; + bad_namestr[0] = '\0'; + for (result = dns_message_firstname(msg, section); + result == ISC_R_SUCCESS; + result = dns_message_nextname(msg, section)) + { + name = NULL; + dns_message_currentname(msg, section, &name); + + if (section == DNS_SECTION_AUTHORITY) { + rdataset = NULL; + result = dns_message_findtype(name, dns_rdatatype_soa, + 0, &rdataset); + if (result == ISC_R_SUCCESS) { + return 0; + } + } + rdataset = NULL; + result = dns_message_findtype(name, dns_rdatatype_ns, 0, + &rdataset); + if (result != ISC_R_SUCCESS) { + continue; + } + + debug("found NS set"); + + if (query->lookup->trace && !query->lookup->trace_root) { + dns_namereln_t namereln; + unsigned int nlabels; + int order; + + domain = dns_fixedname_name(&query->lookup->fdomain); + namereln = dns_name_fullcompare(name, domain, &order, + &nlabels); + if (namereln == dns_namereln_equal) { + if (!horizontal) { + dighost_warning("BAD (HORIZONTAL) " + "REFERRAL"); + } + horizontal = true; + } else if (namereln != dns_namereln_subdomain) { + if (!bad) { + dighost_warning("BAD REFERRAL"); + } + bad = true; + continue; + } + } + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + char namestr[DNS_NAME_FORMATSIZE]; + dns_rdata_ns_t ns; + + if (query->lookup->trace_root && + query->lookup->nsfound >= MXSERV) + { + break; + } + + dns_rdataset_current(rdataset, &rdata); + + query->lookup->nsfound++; + result = dns_rdata_tostruct(&rdata, &ns, NULL); + check_result(result, "dns_rdata_tostruct"); + dns_name_format(&ns.name, namestr, sizeof(namestr)); + dns_rdata_freestruct(&ns); + + /* Initialize lookup if we've not yet */ + debug("found NS %s", namestr); + if (!success) { + success = true; + lookup_counter++; + lookup = requeue_lookup(query->lookup, false); + cancel_lookup(query->lookup); + lookup->doing_xfr = false; + if (!lookup->trace_root && + section == DNS_SECTION_ANSWER) + { + lookup->trace = false; + } else { + lookup->trace = query->lookup->trace; + } + lookup->ns_search_only = + query->lookup->ns_search_only; + lookup->trace_root = false; + if (lookup->ns_search_only) { + lookup->recurse = false; + } + domain = dns_fixedname_name(&lookup->fdomain); + dns_name_copy(name, domain); + lookup->edns = lookup->original_edns; + } + debug("adding server %s", namestr); + num = getaddresses(lookup, namestr, &lresult); + if (lresult != ISC_R_SUCCESS) { + printf("couldn't get address for '%s': %s\n", + namestr, isc_result_totext(lresult)); + if (addresses_result == ISC_R_SUCCESS) { + addresses_result = lresult; + strlcpy(bad_namestr, namestr, + sizeof(bad_namestr)); + } + } + numLookups += num; + dns_rdata_reset(&rdata); + } + } + if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) { + fatal("couldn't get address for '%s': %s", bad_namestr, + isc_result_totext(result)); + } + + if (lookup == NULL && section == DNS_SECTION_ANSWER && + (query->lookup->trace || query->lookup->ns_search_only)) + { + return followup_lookup(msg, query, DNS_SECTION_AUTHORITY); + } + + /* + * Randomize the order the nameserver will be tried. + */ + if (numLookups > 1) { + uint32_t i, j; + dig_serverlist_t my_server_list; + dig_server_t *next; + + ISC_LIST_INIT(my_server_list); + + i = numLookups; + for (srv = ISC_LIST_HEAD(lookup->my_server_list); srv != NULL; + srv = ISC_LIST_HEAD(lookup->my_server_list)) + { + INSIST(i > 0); + j = isc_random_uniform(i); + next = ISC_LIST_NEXT(srv, link); + while (j-- > 0 && next != NULL) { + srv = next; + next = ISC_LIST_NEXT(srv, link); + } + ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link); + ISC_LIST_APPEND(my_server_list, srv, link); + i--; + } + ISC_LIST_APPENDLIST(lookup->my_server_list, my_server_list, + link); + } + + return numLookups; +} + +/*% + * Create and queue a new lookup using the next origin from the search + * list, read in setup_system(). + * + * Return true iff there was another searchlist entry. + */ +static bool +next_origin(dig_lookup_t *oldlookup) { + dig_lookup_t *newlookup; + dig_searchlist_t *search; + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + + INSIST(!free_now); + + debug("next_origin()"); + debug("following up %s", oldlookup->textname); + + if (!usesearch) { + /* + * We're not using a search list, so don't even think + * about finding the next entry. + */ + return false; + } + + /* + * Check for a absolute name or ndots being met. + */ + name = dns_fixedname_initname(&fixed); + result = dns_name_fromstring(name, oldlookup->textname, NULL, 0, NULL); + if (result == ISC_R_SUCCESS && + (dns_name_isabsolute(name) || + (int)dns_name_countlabels(name) > ndots)) + { + return false; + } + + if (oldlookup->origin == NULL && !oldlookup->need_search) { + /* + * Then we just did rootorg; there's nothing left. + */ + return false; + } + if (oldlookup->origin == NULL && oldlookup->need_search) { + newlookup = requeue_lookup(oldlookup, true); + newlookup->origin = ISC_LIST_HEAD(search_list); + newlookup->need_search = false; + } else { + search = ISC_LIST_NEXT(oldlookup->origin, link); + if (search == NULL && oldlookup->done_as_is) { + return false; + } + newlookup = requeue_lookup(oldlookup, true); + newlookup->origin = search; + } + cancel_lookup(oldlookup); + return true; +} + +/*% + * Insert an SOA record into the sendmessage in a lookup. Used for + * creating IXFR queries. + */ +static void +insert_soa(dig_lookup_t *lookup) { + isc_result_t result; + dns_rdata_soa_t soa; + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t *rdataset = NULL; + dns_name_t *soaname = NULL; + + debug("insert_soa()"); + soa.mctx = mctx; + soa.serial = lookup->ixfr_serial; + soa.refresh = 0; + soa.retry = 0; + soa.expire = 0; + soa.minimum = 0; + soa.common.rdclass = lookup->rdclass; + soa.common.rdtype = dns_rdatatype_soa; + + dns_name_init(&soa.origin, NULL); + dns_name_init(&soa.contact, NULL); + + dns_name_clone(dns_rootname, &soa.origin); + dns_name_clone(dns_rootname, &soa.contact); + + isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore, + sizeof(lookup->rdatastore)); + + dns_message_gettemprdata(lookup->sendmsg, &rdata); + + result = dns_rdata_fromstruct(rdata, lookup->rdclass, dns_rdatatype_soa, + &soa, &lookup->rdatabuf); + check_result(result, "isc_rdata_fromstruct"); + + dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist); + + dns_message_gettemprdataset(lookup->sendmsg, &rdataset); + + dns_rdatalist_init(rdatalist); + rdatalist->type = dns_rdatatype_soa; + rdatalist->rdclass = lookup->rdclass; + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + + dns_rdatalist_tordataset(rdatalist, rdataset); + + dns_message_gettempname(lookup->sendmsg, &soaname); + dns_name_clone(lookup->name, soaname); + ISC_LIST_INIT(soaname->list); + ISC_LIST_APPEND(soaname->list, rdataset, link); + dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY); +} + +static void +compute_cookie(unsigned char *clientcookie, size_t len) { + /* XXXMPA need to fix, should be per server. */ + INSIST(len >= 8U); + memmove(clientcookie, cookie_secret, 8); +} + +#define new_query(l, s, u) _new_query(l, s, u, __FILE__, __LINE__) + +static dig_query_t * +_new_query(dig_lookup_t *lookup, char *servname, char *userarg, + const char *file, unsigned int line) { + dig_query_t *query = NULL; + + query = isc_mem_allocate(mctx, sizeof(dig_query_t)); + debug("create query %p linked to lookup %p", query, lookup); + *query = (dig_query_t){ .sendbuf = lookup->renderbuf, + .servname = servname, + .userarg = userarg, + .warn_id = true, + .recvspace = isc_mem_get(mctx, COMMSIZE), + .tmpsendspace = isc_mem_get(mctx, COMMSIZE) }; + + lookup_attach(lookup, &query->lookup); + + isc_refcount_init(&query->references, 1); + + debug("%s:%u:new_query(%p) = %" PRIuFAST32, file, line, query, + isc_refcount_current(&query->references)); + + if (query->recvspace == NULL) { + fatal("memory allocation failure"); + } + if (query->tmpsendspace == NULL) { + fatal("memory allocation failure"); + } + + isc_time_settoepoch(&query->time_sent); + isc_time_settoepoch(&query->time_recv); + + ISC_LINK_INIT(query, clink); + ISC_LINK_INIT(query, link); + + query->magic = DIG_QUERY_MAGIC; + return query; +} + +/*% + * Setup the supplied lookup structure, making it ready to start sending + * queries to servers. Create and initialize the message to be sent as + * well as the query structures and buffer space for the replies. If the + * server list is empty, clone it from the system default list. + */ +bool +setup_lookup(dig_lookup_t *lookup) { + isc_result_t result; + unsigned int len; + dig_server_t *serv; + dig_query_t *query; + isc_buffer_t b; + dns_compress_t cctx; + char store[MXNAME]; + char ecsbuf[20]; + char cookiebuf[256]; + char *origin = NULL; + char *textname = NULL; + + REQUIRE(lookup != NULL); + +#ifdef HAVE_LIBIDN2 + char idn_origin[MXNAME], idn_textname[MXNAME]; +#endif /* HAVE_LIBIDN2 */ + + INSIST(!free_now); + + debug("setup_lookup(%p)", lookup); + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &lookup->sendmsg); + + if (lookup->new_search) { + debug("resetting lookup counter."); + lookup_counter = 0; + } + + if (ISC_LIST_EMPTY(lookup->my_server_list)) { + debug("cloning server list"); + clone_server_list(server_list, &lookup->my_server_list); + } + dns_message_gettempname(lookup->sendmsg, &lookup->name); + + isc_buffer_init(&lookup->namebuf, lookup->name_space, + sizeof(lookup->name_space)); + isc_buffer_init(&lookup->onamebuf, lookup->oname_space, + sizeof(lookup->oname_space)); + + /* + * We cannot convert `textname' and `origin' separately. + * `textname' doesn't contain TLD, but local mapping needs + * TLD. + */ + textname = lookup->textname; +#ifdef HAVE_LIBIDN2 + if (lookup->idnin) { + idn_input(textname, idn_textname, sizeof(idn_textname)); + debug("idn_textname: %s", idn_textname); + textname = idn_textname; + } +#endif /* HAVE_LIBIDN2 */ + + /* + * If the name has too many dots, force the origin to be NULL + * (which produces an absolute lookup). Otherwise, take the origin + * we have if there's one in the struct already. If it's NULL, + * take the first entry in the searchlist iff either usesearch + * is TRUE or we got a domain line in the resolv.conf file. + */ + if (lookup->new_search) { + if ((count_dots(textname) >= ndots) || !usesearch) { + lookup->origin = NULL; /* Force abs lookup */ + lookup->done_as_is = true; + lookup->need_search = usesearch; + } else if (lookup->origin == NULL && usesearch) { + lookup->origin = ISC_LIST_HEAD(search_list); + lookup->need_search = false; + } + } + + if (lookup->origin != NULL) { + debug("trying origin %s", lookup->origin->origin); + dns_message_gettempname(lookup->sendmsg, &lookup->oname); + /* XXX Helper funct to conv char* to name? */ + origin = lookup->origin->origin; +#ifdef HAVE_LIBIDN2 + if (lookup->idnin) { + idn_input(origin, idn_origin, sizeof(idn_origin)); + debug("trying idn origin %s", idn_origin); + origin = idn_origin; + } +#endif /* HAVE_LIBIDN2 */ + len = (unsigned int)strlen(origin); + isc_buffer_init(&b, origin, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 0, + &lookup->onamebuf); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, &lookup->name); + dns_message_puttempname(lookup->sendmsg, + &lookup->oname); + fatal("'%s' is not in legal name syntax (%s)", origin, + isc_result_totext(result)); + } + if (lookup->trace && lookup->trace_root) { + dns_name_clone(dns_rootname, lookup->name); + } else { + dns_fixedname_t fixed; + dns_name_t *name; + + name = dns_fixedname_initname(&fixed); + len = (unsigned int)strlen(textname); + isc_buffer_init(&b, textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(name, &b, NULL, 0, NULL); + if (result == ISC_R_SUCCESS) { + if (!dns_name_isabsolute(name)) { + result = dns_name_concatenate( + name, lookup->oname, + lookup->name, &lookup->namebuf); + } else { + dns_name_copy(name, lookup->name); + } + } + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, + &lookup->name); + dns_message_puttempname(lookup->sendmsg, + &lookup->oname); + if (result == DNS_R_NAMETOOLONG) { + return false; + } + fatal("'%s' is not in legal name syntax (%s)", + lookup->textname, + isc_result_totext(result)); + } + } + dns_message_puttempname(lookup->sendmsg, &lookup->oname); + } else { + debug("using root origin"); + if (lookup->trace && lookup->trace_root) { + dns_name_clone(dns_rootname, lookup->name); + } else { + len = (unsigned int)strlen(textname); + isc_buffer_init(&b, textname, len); + isc_buffer_add(&b, len); + result = dns_name_fromtext(lookup->name, &b, + dns_rootname, 0, + &lookup->namebuf); + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(lookup->sendmsg, + &lookup->name); + warn("'%s' is not a legal name (%s)", + lookup->textname, + isc_result_totext(result)); +#if TARGET_OS_IPHONE + clear_current_lookup(); + return false; +#else /* if TARGET_OS_IPHONE */ + cleanup_openssl_refs(); + digexit(); +#endif /* if TARGET_OS_IPHONE */ + } + } + } + dns_name_format(lookup->name, store, sizeof(store)); + dighost_trying(store, lookup); + INSIST(dns_name_isabsolute(lookup->name)); + + lookup->sendmsg->id = (dns_messageid_t)isc_random16(); + lookup->sendmsg->opcode = lookup->opcode; + lookup->msgcounter = 0; + + /* + * If this is a trace request, completely disallow recursion after + * looking up the root name servers, since it's meaningless for traces. + */ + if ((lookup->trace || lookup->ns_search_only) && !lookup->trace_root) { + lookup->recurse = false; + } + + if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr && + lookup->rdtype != dns_rdatatype_ixfr) + { + debug("recursive query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; + } + + /* XXX aaflag */ + if (lookup->aaonly) { + debug("AA query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA; + } + + if (lookup->adflag) { + debug("AD query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD; + } + + if (lookup->cdflag) { + debug("CD query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD; + } + + if (lookup->raflag) { + debug("RA query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RA; + } + + if (lookup->tcflag) { + debug("TC query"); + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_TC; + } + + if (lookup->zflag) { + debug("Z query"); + lookup->sendmsg->flags |= 0x0040U; + } + + if (lookup->setqid) { + debug("set QID"); + lookup->sendmsg->id = lookup->qid; + } + + dns_message_addname(lookup->sendmsg, lookup->name, + DNS_SECTION_QUESTION); + + if (lookup->trace && lookup->trace_root) { + lookup->qrdtype = lookup->rdtype; + lookup->rdtype = dns_rdatatype_ns; + } + + if ((lookup->rdtype == dns_rdatatype_axfr) || + (lookup->rdtype == dns_rdatatype_ixfr)) + { + /* + * Force TCP mode if we're doing an axfr. + */ + if (lookup->rdtype == dns_rdatatype_axfr) { + lookup->doing_xfr = true; + lookup->tcp_mode = true; + } else if (lookup->tcp_mode) { + lookup->doing_xfr = true; + } + } + + if (!lookup->header_only) { + add_question(lookup->sendmsg, lookup->name, lookup->rdclass, + lookup->rdtype); + } + + /* add_soa */ + if (lookup->rdtype == dns_rdatatype_ixfr) { + insert_soa(lookup); + } + + /* XXX Insist this? */ + lookup->tsigctx = NULL; + lookup->querysig = NULL; + if (tsigkey != NULL) { + debug("initializing keys"); + result = dns_message_settsigkey(lookup->sendmsg, tsigkey); + check_result(result, "dns_message_settsigkey"); + } else if (sig0key != NULL) { + debug("initializing keys"); + result = dns_message_setsig0key(lookup->sendmsg, sig0key); + check_result(result, "dns_message_setsig0key"); + } + + if (lookup->fuzzing) { + lookup->sendmsg->fuzzing = true; + lookup->sendmsg->fuzztime = lookup->fuzztime; + } + + lookup->sendspace = isc_mem_get(mctx, COMMSIZE); + + dns_compress_init(&cctx, mctx, 0); + + debug("starting to render the message"); + isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE); + result = dns_message_renderbegin(lookup->sendmsg, &cctx, + &lookup->renderbuf); + check_result(result, "dns_message_renderbegin"); + if (lookup->udpsize > -1 || lookup->dnssec || lookup->edns > -1 || + lookup->ecs_addr != NULL) + { +#define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS) + dns_ednsopt_t opts[MAXOPTS]; + unsigned int flags; + unsigned int i = 0; + + /* + * There can't be more than MAXOPTS options to send: + * a maximum of EDNSOPT_OPTIONS set by +ednsopt + * and DNS_EDNSOPTIONS set by other arguments + * (+nsid, +cookie, etc). + */ + if (lookup->udpsize < 0) { + lookup->udpsize = DEFAULT_EDNS_BUFSIZE; + } + if (lookup->edns < 0) { + lookup->original_edns = lookup->edns = + DEFAULT_EDNS_VERSION; + } + + if (lookup->nsid) { + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_NSID; + opts[i].length = 0; + opts[i].value = NULL; + i++; + } + + if (lookup->ecs_addr != NULL) { + uint8_t addr[16]; + uint16_t family = 0; + uint32_t plen; + struct sockaddr *sa; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + size_t addrl; + + sa = &lookup->ecs_addr->type.sa; + plen = lookup->ecs_addr->length; + + /* Round up prefix len to a multiple of 8 */ + addrl = (plen + 7) / 8; + + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_CLIENT_SUBNET; + opts[i].length = (uint16_t)addrl + 4; + check_result(result, "isc_buffer_allocate"); + + /* + * XXXMUKS: According to RFC7871, "If there is + * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is + * set to 0, then FAMILY SHOULD be set to the + * transport over which the query is sent." + * + * However, at this point we don't know what + * transport(s) we'll be using, so we can't + * set the value now. For now, we're using + * IPv4 as the default the +subnet option + * used an IPv4 prefix, or for +subnet=0, + * and IPv6 if the +subnet option used an + * IPv6 prefix. + * + * (For future work: preserve the offset into + * the buffer where the family field is; + * that way we can update it in start_udp() + * or start_tcp() once we know + * what it outght to be.) + */ + switch (sa->sa_family) { + case AF_UNSPEC: + INSIST(plen == 0); + family = 1; + break; + case AF_INET: + INSIST(plen <= 32); + family = 1; + sin = (struct sockaddr_in *)sa; + memmove(addr, &sin->sin_addr, addrl); + break; + case AF_INET6: + INSIST(plen <= 128); + family = 2; + sin6 = (struct sockaddr_in6 *)sa; + memmove(addr, &sin6->sin6_addr, addrl); + break; + default: + UNREACHABLE(); + } + + isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf)); + /* family */ + isc_buffer_putuint16(&b, family); + /* source prefix-length */ + isc_buffer_putuint8(&b, plen); + /* scope prefix-length */ + isc_buffer_putuint8(&b, 0); + + /* address */ + if (addrl > 0) { + /* Mask off last address byte */ + if ((plen % 8) != 0) { + addr[addrl - 1] &= ~0U + << (8 - (plen % 8)); + } + isc_buffer_putmem(&b, addr, + (unsigned int)addrl); + } + + opts[i].value = (uint8_t *)ecsbuf; + i++; + } + + if (lookup->sendcookie) { + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_COOKIE; + if (lookup->cookie != NULL) { + isc_buffer_init(&b, cookiebuf, + sizeof(cookiebuf)); + result = isc_hex_decodestring(lookup->cookie, + &b); + check_result(result, "isc_hex_decodestring"); + opts[i].value = isc_buffer_base(&b); + opts[i].length = isc_buffer_usedlength(&b); + } else { + compute_cookie(cookie, sizeof(cookie)); + opts[i].length = 8; + opts[i].value = cookie; + } + i++; + } + + if (lookup->expire) { + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_EXPIRE; + opts[i].length = 0; + opts[i].value = NULL; + i++; + } + + if (lookup->tcp_keepalive) { + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_TCP_KEEPALIVE; + opts[i].length = 0; + opts[i].value = NULL; + i++; + } + + if (lookup->ednsoptscnt != 0) { + INSIST(i + lookup->ednsoptscnt <= MAXOPTS); + memmove(&opts[i], lookup->ednsopts, + sizeof(dns_ednsopt_t) * lookup->ednsoptscnt); + i += lookup->ednsoptscnt; + } + + if (lookup->padding != 0 && (i >= MAXOPTS)) { + debug("turned off padding because of EDNS overflow"); + lookup->padding = 0; + } + + if (lookup->padding != 0) { + INSIST(i < MAXOPTS); + opts[i].code = DNS_OPT_PAD; + opts[i].length = 0; + opts[i].value = NULL; + i++; + dns_message_setpadding(lookup->sendmsg, + lookup->padding); + } + + flags = lookup->ednsflags; + flags &= ~DNS_MESSAGEEXTFLAG_DO; + if (lookup->dnssec) { + flags |= DNS_MESSAGEEXTFLAG_DO; + } + add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags, + opts, i); + } + + result = dns_message_rendersection(lookup->sendmsg, + DNS_SECTION_QUESTION, 0); + check_result(result, "dns_message_rendersection"); + result = dns_message_rendersection(lookup->sendmsg, + DNS_SECTION_AUTHORITY, 0); + check_result(result, "dns_message_rendersection"); + result = dns_message_renderend(lookup->sendmsg); + check_result(result, "dns_message_renderend"); + debug("done rendering"); + + dns_compress_invalidate(&cctx); + + /* + * Force TCP mode if the request is larger than 512 bytes. + */ + if (isc_buffer_usedlength(&lookup->renderbuf) > 512) { + lookup->tcp_mode = true; + } + + lookup->pending = false; + + for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL; + serv = ISC_LIST_NEXT(serv, link)) + { + query = new_query(lookup, serv->servername, serv->userarg); + ISC_LIST_ENQUEUE(lookup->q, query, link); + } + + return true; +} + +/*% + * NSSEARCH mode special mode handling function to start the next query in the + * list. The lookup lock must be held by the caller. The function will detach + * both the lookup and the query, and may cancel the lookup and clear the + * current lookup. + */ +static void +nssearch_next(dig_lookup_t *l, dig_query_t *q) { + dig_query_t *next = ISC_LIST_NEXT(q, link); + bool tcp_mode = l->tcp_mode; + + INSIST(l->ns_search_only && !l->trace_root); + INSIST(l == current_lookup); + + if (next == NULL) { + /* + * If this is the last query, and if there was + * not a single successful query in the whole + * lookup, then treat the situation as an error, + * cancel and clear the lookup. + */ + if (check_if_queries_done(l, q) && !l->ns_search_success) { + dighost_error("NS servers could not be reached"); + if (exitcode < 9) { + exitcode = 9; + } + + cancel_lookup(l); + query_detach(&q); + lookup_detach(&l); + clear_current_lookup(); + } else { + query_detach(&q); + lookup_detach(&l); + } + } else { + query_detach(&q); + lookup_detach(&l); + + debug("sending next, since searching"); + if (tcp_mode) { + start_tcp(next); + } else { + start_udp(next); + } + } +} + +/*% + * Event handler for send completion. Track send counter, and clear out + * the query if the send was canceled. + */ +static void +send_done(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dig_query_t *query = (dig_query_t *)arg; + dig_lookup_t *l = NULL; + + REQUIRE(DIG_VALID_QUERY(query)); + INSIST(query->sendhandle != NULL); + INSIST(handle == query->sendhandle); + + debug("send_done(%p, %s, %p)", handle, isc_result_totext(eresult), arg); + + isc_refcount_decrement0(&sendcount); + debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount)); + + INSIST(!free_now); + + isc_nmhandle_detach(&query->sendhandle); + + lookup_attach(query->lookup, &l); + + if (eresult == ISC_R_CANCELED || query->canceled) { + debug("send_done: cancel"); + if (!query->canceled) { + cancel_lookup(l); + } + query_detach(&query); + lookup_detach(&l); + return; + } else if (eresult != ISC_R_SUCCESS) { + debug("send failed: %s", isc_result_totext(eresult)); + } + + if (l->ns_search_only && !l->trace_root) { + nssearch_next(l, query); + } else { + query_detach(&query); + lookup_detach(&l); + } + + check_if_done(); +} + +/*% + * Cancel a lookup, sending canceling reads on all existing sockets. + */ + +static void +_cancel_lookup(dig_lookup_t *lookup, const char *file, unsigned int line) { + dig_query_t *query, *next; + + debug("%s:%u:%s()", file, line, __func__); + query = ISC_LIST_HEAD(lookup->q); + while (query != NULL) { + REQUIRE(DIG_VALID_QUERY(query)); + next = ISC_LIST_NEXT(query, link); + ISC_LIST_DEQUEUE(lookup->q, query, link); + debug("canceling pending query %p, belonging to %p", query, + query->lookup); + query->canceled = true; + if (query->readhandle != NULL && + !isc_nm_is_http_handle(query->readhandle)) + { + isc_nm_cancelread(query->readhandle); + } + query_detach(&query); + query = next; + } + lookup->pending = false; + lookup->retries = 0; + check_if_done(); +} + +static inline const char * +get_tls_sni_hostname(dig_query_t *query) { + const char *hostname = query->lookup->tls_hostname_set + ? query->lookup->tls_hostname + : query->userarg; + + if (query->lookup->tls_hostname_set) { + return query->lookup->tls_hostname; + } + + if (isc_tls_valid_sni_hostname(hostname)) { + return hostname; + } + + return NULL; +} + +static isc_tlsctx_t * +get_create_tls_context(dig_query_t *query, const bool is_https, + isc_tlsctx_client_session_cache_t **psess_cache) { + isc_result_t result; + isc_tlsctx_t *ctx = NULL, *found_ctx = NULL; + isc_tls_cert_store_t *store = NULL, *found_store = NULL; + char tlsctxname[ISC_SOCKADDR_FORMATSIZE]; + const uint16_t family = isc_sockaddr_pf(&query->sockaddr) == PF_INET6 + ? AF_INET6 + : AF_INET; + isc_tlsctx_cache_transport_t transport = + is_https ? isc_tlsctx_cache_https : isc_tlsctx_cache_tls; + const bool hostname_ignore_subject = !is_https; + isc_tlsctx_client_session_cache_t *sess_cache = NULL, + *found_sess_cache = NULL; + + if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set) + { + return NULL; + } + + isc_sockaddr_format(&query->sockaddr, tlsctxname, sizeof(tlsctxname)); + + result = isc_tlsctx_cache_find(query->lookup->tls_ctx_cache, tlsctxname, + transport, family, &found_ctx, + &found_store, &found_sess_cache); + if (result != ISC_R_SUCCESS) { + if (query->lookup->tls_ca_set) { + if (found_store == NULL) { + result = isc_tls_cert_store_create( + query->lookup->tls_ca_file, &store); + + if (result != ISC_R_SUCCESS) { + goto failure; + } + } else { + store = found_store; + } + } + + result = isc_tlsctx_createclient(&ctx); + if (result != ISC_R_SUCCESS) { + goto failure; + } + + if (store != NULL) { + const char *hostname = get_tls_sni_hostname(query); + /* + * According to RFC 8310, Subject field MUST NOT be + * inspected when verifying hostname for DoT. Only + * SubjectAltName must be checked. That is NOT the case + * for HTTPS. + */ + result = isc_tlsctx_enable_peer_verification( + ctx, false, store, hostname, + hostname_ignore_subject); + if (result != ISC_R_SUCCESS) { + goto failure; + } + } + + if (query->lookup->tls_key_file_set && + query->lookup->tls_cert_file_set) + { + result = isc_tlsctx_load_certificate( + ctx, query->lookup->tls_key_file, + query->lookup->tls_cert_file); + if (result != ISC_R_SUCCESS) { + goto failure; + } + } + + if (!is_https) { + isc_tlsctx_enable_dot_client_alpn(ctx); + } + +#if HAVE_LIBNGHTTP2 + if (is_https) { + isc_tlsctx_enable_http2client_alpn(ctx); + } +#endif /* HAVE_LIBNGHTTP2 */ + + isc_tlsctx_client_session_cache_create( + mctx, ctx, ISC_TLSCTX_CLIENT_SESSION_CACHE_DEFAULT_SIZE, + &sess_cache); + + result = isc_tlsctx_cache_add( + query->lookup->tls_ctx_cache, tlsctxname, transport, + family, ctx, store, sess_cache, NULL, NULL, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (psess_cache != NULL) { + INSIST(*psess_cache == NULL); + *psess_cache = sess_cache; + } + return ctx; + } + + if (psess_cache != NULL) { + INSIST(*psess_cache == NULL); + *psess_cache = found_sess_cache; + } + + INSIST(!query->lookup->tls_ca_set || found_store != NULL); + return found_ctx; +failure: + if (ctx != NULL) { + isc_tlsctx_free(&ctx); + } + /* + * The 'found_store' is being managed by the TLS context + * cache. Thus, we should keep it as it is, as it will get + * destroyed alongside the cache. As there is one store per + * multiple TLS contexts, we need to handle store deletion in a + * special way. + */ + if (store != NULL && store != found_store) { + isc_tls_cert_store_free(&store); + } + return NULL; +} + +static void +tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg); + +/*% + * Unlike start_udp, this can't be called multiple times with the same + * query. When we retry TCP, we requeue the whole lookup, which should + * start anew. + */ +static void +start_tcp(dig_query_t *query) { + isc_result_t result; + dig_query_t *next = NULL; + dig_query_t *connectquery = NULL; + isc_tlsctx_t *tlsctx = NULL; + bool tls_mode = false; + isc_tlsctx_client_session_cache_t *sess_cache = NULL; + int local_timeout; + isc_nm_proxy_type_t proxy_type = ISC_NM_PROXY_NONE; + isc_nm_proxyheader_info_t proxy_info = { 0 }; + isc_nm_proxyheader_info_t *ppi = NULL; + + REQUIRE(DIG_VALID_QUERY(query)); + + debug("start_tcp(%p)", query); + + query_attach(query, &query->lookup->current_query); + + tls_mode = dig_lookup_is_tls(query->lookup); + + /* + * For TLS connections, we want to override the default + * port number. + */ + if (!port_set) { + if (tls_mode) { + port = 853; + } else if (query->lookup->https_mode && + !query->lookup->http_plain) + { + port = 443; + } else if (query->lookup->https_mode) { + port = 80; + } else { + port = 53; + } + } + + debug("query->servname = %s\n", query->servname); + + result = get_address(query->servname, port, &query->sockaddr); + if (result != ISC_R_SUCCESS) { + /* + * This servname doesn't have an address. Try the next server + * by triggering an immediate 'timeout' (we lie, but the effect + * is the same). + */ + force_next(query); + return; + } + + if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) + { + isc_netaddr_t netaddr; + char buf[ISC_NETADDR_FORMATSIZE]; + + isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); + isc_netaddr_format(&netaddr, buf, sizeof(buf)); + dighost_warning("Skipping mapped address '%s'", buf); + + if (ISC_LINK_LINKED(query, link)) { + next = ISC_LIST_NEXT(query, link); + } else { + next = NULL; + } + query_detach(&query); + if (next == NULL) { + dighost_warning("No acceptable nameservers"); + clear_current_lookup(); + } else { + start_tcp(next); + } + return; + } + + INSIST(query->handle == NULL); + + if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) { + query->handle = keep; + launch_next_query(query); + query_detach(&query); + return; + } else if (keep != NULL) { + isc_nmhandle_detach(&keep); + } + + if (timeout != 0) { + local_timeout = timeout * 1000; + } else { + local_timeout = TCP_TIMEOUT * 1000; + } + + if (!specified_source) { + if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) + { + isc_sockaddr_any(&localaddr); + } else { + isc_sockaddr_any6(&localaddr); + } + } + + if (query->lookup->proxy_mode) { + proxy_type = ISC_NM_PROXY_PLAIN; + if ((tls_mode || (query->lookup->https_mode && + !query->lookup->http_plain)) && + !query->lookup->proxy_plain) + { + proxy_type = ISC_NM_PROXY_ENCRYPTED; + } + if (!query->lookup->proxy_local) { + isc_nm_proxyheader_info_init( + &proxy_info, &query->lookup->proxy_src_addr, + &query->lookup->proxy_dst_addr, NULL); + ppi = &proxy_info; + } + } + + REQUIRE(query != NULL); + + query_attach(query, &connectquery); + + if (tls_mode) { + tlsctx = get_create_tls_context(connectquery, false, + &sess_cache); + if (tlsctx == NULL) { + goto failure_tls; + } + isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, + tcp_connected, connectquery, + local_timeout, tlsctx, + get_tls_sni_hostname(query), sess_cache, + proxy_type, ppi); +#if HAVE_LIBNGHTTP2 + } else if (query->lookup->https_mode) { + char uri[4096] = { 0 }; + isc_nm_http_makeuri(!query->lookup->http_plain, + &query->sockaddr, query->userarg, port, + query->lookup->https_path, uri, + sizeof(uri)); + + if (!query->lookup->http_plain) { + tlsctx = get_create_tls_context(connectquery, true, + &sess_cache); + if (tlsctx == NULL) { + goto failure_tls; + } + } + + isc_nm_httpconnect(netmgr, &localaddr, &query->sockaddr, uri, + !query->lookup->https_get, tcp_connected, + connectquery, tlsctx, + get_tls_sni_hostname(query), sess_cache, + local_timeout, proxy_type, ppi); +#endif + } else { + isc_nm_streamdnsconnect(netmgr, &localaddr, &query->sockaddr, + tcp_connected, connectquery, + local_timeout, NULL, NULL, NULL, + proxy_type, ppi); + } + + return; + +failure_tls: + if (query->lookup->tls_key_file_set != query->lookup->tls_cert_file_set) + { + dighost_warning( + "both TLS client certificate and key file must be " + "specified a the same time"); + } else { + dighost_warning("TLS context cannot be created"); + } + + if (ISC_LINK_LINKED(query, link)) { + next = ISC_LIST_NEXT(query, link); + } else { + next = NULL; + } + query_detach(&connectquery); + query_detach(&query); + if (next == NULL) { + clear_current_lookup(); + } else { + start_tcp(next); + } +} + +static void +print_query_size(dig_query_t *query) { + if (!yaml) { + printf(";; QUERY SIZE: %u\n\n", + isc_buffer_usedlength(&query->lookup->renderbuf)); + } +} + +static void +send_udp(dig_query_t *query) { + dig_query_t *sendquery = NULL; + isc_region_t r; + + query_attach(query, &sendquery); + + isc_buffer_usedregion(&query->sendbuf, &r); + debug("sending a request"); + if (query->lookup->use_usec) { + query->time_sent = isc_time_now_hires(); + } else { + query->time_sent = isc_time_now(); + } + + isc_nmhandle_attach(query->handle, &query->sendhandle); + + isc_nm_send(query->handle, &r, send_done, sendquery); + isc_refcount_increment0(&sendcount); + debug("sendcount=%" PRIuFAST32, isc_refcount_current(&sendcount)); + + /* XXX qrflag, print_query, etc... */ + if (query->lookup->qr) { + extrabytes = 0; + dighost_printmessage(query, &query->lookup->renderbuf, + query->lookup->sendmsg, true); + if (query->lookup->stats) { + print_query_size(query); + } + } +} + +static void +udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dig_query_t *query = (dig_query_t *)arg; + dig_query_t *next = NULL; + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + dig_lookup_t *l = NULL; + dig_query_t *readquery = NULL; + int local_timeout = timeout * 1000; + + REQUIRE(DIG_VALID_QUERY(query)); + REQUIRE(query->handle == NULL); + + debug("udp_ready()"); + + query->started = true; + + if (cancel_now) { + query_detach(&query); + return; + } + + INSIST(!free_now); + + debug("udp_ready(%p, %s, %p)", handle, isc_result_totext(eresult), + query); + + lookup_attach(query->lookup, &l); + + if (eresult == ISC_R_CANCELED || query->canceled) { + debug("in cancel handler"); + if (!query->canceled) { + cancel_lookup(l); + } + query_detach(&query); + lookup_detach(&l); + clear_current_lookup(); + return; + } + + if (eresult != ISC_R_SUCCESS) { + debug("udp setup failed: %s", isc_result_totext(eresult)); + isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); + dighost_warning("UDP setup with %s(%s) for %s failed: %s.", + sockstr, query->servname, l->textname, + isc_result_totext(eresult)); + + /* + * NSSEARCH mode: if the current query failed to start properly, + * then send_done() will not be called, and we want to make sure + * that the next query gets a chance to start in order to not + * break the chain. + */ + if (l->ns_search_only && !l->trace_root) { + nssearch_next(l, query); + + check_if_done(); + return; + } + + if (exitcode < 9) { + exitcode = 9; + } + + if (l->retries > 1) { + l->retries--; + debug("making new UDP request, %d tries left", + l->retries); + requeue_lookup(l, true); + next = NULL; + } else if ((l->current_query != NULL) && + (ISC_LINK_LINKED(l->current_query, link))) + { + next = ISC_LIST_NEXT(l->current_query, link); + } else { + next = NULL; + } + + query_detach(&query); + if (next == NULL) { + cancel_lookup(l); + } + lookup_detach(&l); + + if (next != NULL) { + start_udp(next); + check_if_done(); + } else { + dighost_error("no servers could be reached"); + clear_current_lookup(); + } + + return; + } + + exitcode = 0; + + query_attach(query, &readquery); + + debug("recving with lookup=%p, query=%p, handle=%p", query->lookup, + query, handle); + + query->handle = handle; + isc_nmhandle_attach(handle, &query->readhandle); + isc_refcount_increment0(&recvcount); + debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); + + if (local_timeout == 0) { + local_timeout = UDP_TIMEOUT * 1000; + } + + debug("have local timeout of %d", local_timeout); + isc_nmhandle_settimeout(handle, local_timeout); + + isc_nm_read(handle, recv_done, readquery); + send_udp(readquery); + + query_detach(&query); + lookup_detach(&l); +} + +/*% + * Send a UDP packet to the remote nameserver, possible starting the + * recv action as well. Also make sure that the timer is running and + * is properly reset. + */ +static void +start_udp(dig_query_t *query) { + isc_result_t result; + dig_query_t *next = NULL; + dig_query_t *connectquery = NULL; + + REQUIRE(DIG_VALID_QUERY(query)); + + debug("start_udp(%p)", query); + + query_attach(query, &query->lookup->current_query); + debug("working on lookup %p, query %p", query->lookup, query); + + if (query->handle != NULL) { + launch_next_query(query); + query_detach(&query); + return; + } + + if (!port_set) { + port = 53; + } + + result = get_address(query->servname, port, &query->sockaddr); + if (result != ISC_R_SUCCESS) { + /* This servname doesn't have an address. */ + force_next(query); + return; + } + + if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) + { + isc_netaddr_t netaddr; + char buf[ISC_NETADDR_FORMATSIZE]; + + isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); + isc_netaddr_format(&netaddr, buf, sizeof(buf)); + dighost_warning("Skipping mapped address '%s'", buf); + next = ISC_LIST_NEXT(query, link); + query_detach(&query); + if (next == NULL) { + dighost_warning("No acceptable nameservers"); + clear_current_lookup(); + } else { + start_udp(next); + } + return; + } + + if (!specified_source) { + if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4) + { + isc_sockaddr_any(&localaddr); + } else { + isc_sockaddr_any6(&localaddr); + } + } + + query_attach(query, &connectquery); + if (query->lookup->proxy_mode) { + isc_nm_proxyheader_info_t proxy_info = { 0 }; + isc_nm_proxyheader_info_t *ppi = NULL; + if (!query->lookup->proxy_local) { + isc_nm_proxyheader_info_init( + &proxy_info, &query->lookup->proxy_src_addr, + &query->lookup->proxy_dst_addr, NULL); + ppi = &proxy_info; + } + isc_nm_proxyudpconnect(netmgr, &localaddr, &query->sockaddr, + udp_ready, connectquery, + (timeout ? timeout : UDP_TIMEOUT) * 1000, + ppi); + } else { + isc_nm_udpconnect(netmgr, &localaddr, &query->sockaddr, + udp_ready, connectquery, + (timeout ? timeout : UDP_TIMEOUT) * 1000); + } +} + +/*% + * If there are more servers available for querying within 'lookup', initiate a + * TCP or UDP query to the next available server and return true; otherwise, + * return false. + */ +static bool +try_next_server(dig_lookup_t *lookup) { + dig_query_t *current_query, *next_query; + + current_query = lookup->current_query; + if (current_query == NULL || !ISC_LINK_LINKED(current_query, link)) { + return false; + } + + next_query = ISC_LIST_NEXT(current_query, link); + if (next_query == NULL) { + return false; + } + + debug("trying next server..."); + + if (lookup->tcp_mode) { + start_tcp(next_query); + } else { + start_udp(next_query); + } + + return true; +} + +static void +force_next(dig_query_t *query) { + dig_lookup_t *l = NULL; + + REQUIRE(DIG_VALID_QUERY(query)); + + debug("force_next()"); + + INSIST(!free_now); + + if (cancel_now) { + return; + } + + lookup_attach(query->lookup, &l); + + if (try_next_server(l)) { + lookup_detach(&l); + return; + } + + if (l->retries > 1) { + l->retries--; + debug("making new %s request, %d tries left", + l->tcp_mode ? "TCP" : "UDP", l->retries); + requeue_lookup(l, true); + lookup_detach(&l); + isc_refcount_decrement0(&recvcount); + debug("recvcount=%" PRIuFAST32, + isc_refcount_current(&recvcount)); + query_detach(&query); + clear_current_lookup(); + return; + } + + if (query->readhandle != NULL) { + isc_refcount_decrement0(&recvcount); + debug("recvcount=%" PRIuFAST32, + isc_refcount_current(&recvcount)); + } + + if (l->ns_search_only) { + isc_netaddr_t netaddr; + char buf[ISC_NETADDR_FORMATSIZE]; + + isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr); + isc_netaddr_format(&netaddr, buf, sizeof(buf)); + + dighost_error("no response from %s", buf); + } else { + printf("%s", l->cmdline); + dighost_error("no servers could be reached"); + } + + if (exitcode < 9) { + exitcode = 9; + } + + query_detach(&query); + cancel_lookup(l); + lookup_detach(&l); + clear_current_lookup(); +} + +/*% + * For transfers that involve multiple recvs (XFR's in particular), + * launch the next recv. + */ +static void +launch_next_query(dig_query_t *query) { + dig_query_t *readquery = NULL; + int local_timeout = timeout * 1000; + dig_lookup_t *l = NULL; + isc_region_t r; + bool xfr; + + REQUIRE(DIG_VALID_QUERY(query)); + INSIST(!free_now); + + debug("launch_next_query()"); + + lookup_attach(query->lookup, &l); + + if (!l->pending) { + debug("ignoring launch_next_query because !pending"); + query_detach(&query); + lookup_detach(&l); + clear_current_lookup(); + return; + } + + isc_nmhandle_attach(query->handle, &query->readhandle); + isc_refcount_increment0(&recvcount); + debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); + + if (local_timeout == 0) { + local_timeout = TCP_TIMEOUT * 1000; + } + + debug("have local timeout of %d", local_timeout); + isc_nmhandle_settimeout(query->handle, local_timeout); + + xfr = query->lookup->rdtype == dns_rdatatype_ixfr || + query->lookup->rdtype == dns_rdatatype_axfr; + if (xfr && + isc_nm_socket_type(query->handle) == isc_nm_streamdnssocket && + query->lookup->tls_mode) + { + isc_result_t result = isc_nm_xfr_checkperm(query->handle); + if (result != ISC_R_SUCCESS) { + dighost_error("zone transfers over the established TLS " + "connection are not allowed: %s", + isc_result_totext(result)); + isc_refcount_decrement0(&recvcount); + isc_nmhandle_detach(&query->readhandle); + cancel_lookup(l); + lookup_detach(&l); + clear_current_lookup(); + return; + } + } + + query_attach(query, &readquery); + + isc_nm_read(query->handle, recv_done, readquery); + + if (!query->first_soa_rcvd) { + dig_query_t *sendquery = NULL; + debug("sending a request in launch_next_query"); + if (query->lookup->use_usec) { + query->time_sent = isc_time_now_hires(); + } else { + query->time_sent = isc_time_now(); + } + + query_attach(query, &sendquery); + isc_buffer_usedregion(&query->sendbuf, &r); + if (keep != NULL) { + query->handle = keep; + } + + isc_nmhandle_attach(query->handle, &query->sendhandle); + isc_nm_send(query->handle, &r, send_done, sendquery); + isc_refcount_increment0(&sendcount); + debug("sendcount=%" PRIuFAST32, + isc_refcount_current(&sendcount)); + + /* XXX qrflag, print_query, etc... */ + if (l->qr) { + extrabytes = 0; + dighost_printmessage(query, &l->renderbuf, l->sendmsg, + true); + if (l->stats) { + print_query_size(query); + } + } + } + + lookup_detach(&l); + return; +} + +/*% + * Event handler for TCP connect complete. Make sure the connection was + * successful, then pass into launch_next_query to actually send the + * question. + */ +static void +tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { + dig_query_t *query = (dig_query_t *)arg; + dig_query_t *next = NULL; + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + dig_lookup_t *l = NULL; + + REQUIRE(DIG_VALID_QUERY(query)); + REQUIRE(query->handle == NULL); + + debug("tcp_connected()"); + + query->started = true; + + if (cancel_now) { + query_detach(&query); + return; + } + + INSIST(!free_now); + + debug("tcp_connected(%p, %s, %p)", handle, isc_result_totext(eresult), + query); + + if (eresult == ISC_R_SHUTTINGDOWN) { + query_detach(&query); + cancel_all(); + return; + } + + lookup_attach(query->lookup, &l); + + if (eresult == ISC_R_CANCELED || eresult == ISC_R_TLSBADPEERCERT || + query->canceled) + { + debug("in cancel handler"); + isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); + if (eresult == ISC_R_TLSBADPEERCERT) { + dighost_warning( + "TLS peer certificate verification for " + "%s failed: %s", + sockstr, + isc_nm_verify_tls_peer_result_string(handle)); + } else if (query->lookup->rdtype == dns_rdatatype_ixfr || + query->lookup->rdtype == dns_rdatatype_axfr) + { + puts("; Transfer failed."); + } + + if (!query->canceled) { + cancel_lookup(l); + } + + query_detach(&query); + lookup_detach(&l); + clear_current_lookup(); + return; + } + + if (eresult != ISC_R_SUCCESS) { + debug("unsuccessful connection: %s", + isc_result_totext(eresult)); + isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); + dighost_warning("Connection to %s(%s) for %s failed: %s.", + sockstr, query->servname, l->textname, + isc_result_totext(eresult)); + + /* + * NSSEARCH mode: if the current query failed to start properly, + * then send_done() will not be called, and we want to make sure + * that the next query gets a chance to start in order to not + * break the chain. + */ + if (l->ns_search_only && !l->trace_root) { + nssearch_next(l, query); + check_if_done(); + return; + } + + /* XXX Clean up exitcodes */ + if (exitcode < 9) { + exitcode = 9; + } + + if (l->retries > 1) { + l->retries--; + debug("making new TCP request, %d tries left", + l->retries); + requeue_lookup(l, true); + next = NULL; + } else if ((l->current_query != NULL) && + (ISC_LINK_LINKED(l->current_query, link))) + { + next = ISC_LIST_NEXT(l->current_query, link); + } else { + next = NULL; + } + + query_detach(&query); + if (next == NULL) { + cancel_lookup(l); + } + lookup_detach(&l); + + if (next != NULL) { + start_tcp(next); + check_if_done(); + } else { + dighost_error("no servers could be reached"); + clear_current_lookup(); + } + + return; + } + + exitcode = 0; + + query->handle = handle; + if (keep_open) { + keepaddr = query->sockaddr; + if (keep != NULL) { + isc_nmhandle_detach(&keep); + } + + isc_nmhandle_attach(handle, &keep); + } + + launch_next_query(query); + query_detach(&query); + lookup_detach(&l); +} + +/*% + * Check if the ongoing XFR needs more data before it's complete, using + * the semantics of IXFR and AXFR protocols. Much of the complexity of + * this routine comes from determining when an IXFR is complete. + * false means more data is on the way, and the recv has been issued. + */ +static bool +check_for_more_data(dig_lookup_t *lookup, dig_query_t *query, + dns_message_t *msg, isc_sockaddr_t *peer, int len) { + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_soa_t soa; + uint32_t ixfr_serial = lookup->ixfr_serial, serial; + isc_result_t result; + bool ixfr = lookup->rdtype == dns_rdatatype_ixfr; + bool axfr = lookup->rdtype == dns_rdatatype_axfr; + + if (ixfr) { + axfr = query->ixfr_axfr; + } + + debug("check_for_more_data()"); + + /* + * By the time we're in this routine, we know we're doing + * either an AXFR or IXFR. If there's no second_rr_type, + * then we don't yet know which kind of answer we got back + * from the server. Here, we're going to walk through the + * rr's in the message, acting as necessary whenever we hit + * an SOA rr. + */ + + query->msg_count++; + query->byte_count += len; + result = dns_message_firstname(msg, DNS_SECTION_ANSWER); + if (result != ISC_R_SUCCESS) { + puts("; Transfer failed."); + return true; + } + do { + dns_name_t *name; + name = NULL; + dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + result = dns_rdataset_first(rdataset); + if (result != ISC_R_SUCCESS) { + continue; + } + do { + query->rr_count++; + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + /* + * If this is the first rr, make sure + * it's an SOA + */ + if ((!query->first_soa_rcvd) && + (rdata.type != dns_rdatatype_soa)) + { + puts("; Transfer failed. " + "Didn't start with SOA answer."); + return true; + } + if ((!query->second_rr_rcvd) && + (rdata.type != dns_rdatatype_soa)) + { + query->second_rr_rcvd = true; + query->second_rr_serial = 0; + debug("got the second rr as nonsoa"); + axfr = query->ixfr_axfr = true; + goto next_rdata; + } + + /* + * If the record is anything except an SOA + * now, just continue on... + */ + if (rdata.type != dns_rdatatype_soa) { + goto next_rdata; + } + + /* Now we have an SOA. Work with it. */ + debug("got an SOA"); + result = dns_rdata_tostruct(&rdata, &soa, NULL); + check_result(result, "dns_rdata_tostruct"); + serial = soa.serial; + dns_rdata_freestruct(&soa); + if (!query->first_soa_rcvd) { + query->first_soa_rcvd = true; + query->first_rr_serial = serial; + debug("this is the first serial %u", + serial); + if (ixfr && + isc_serial_ge(ixfr_serial, serial)) + { + debug("got up to date " + "response"); + goto doexit; + } + goto next_rdata; + } + if (axfr) { + debug("doing axfr, got second SOA"); + goto doexit; + } + if (!query->second_rr_rcvd) { + if (query->first_rr_serial == serial) { + debug("doing ixfr, got " + "empty zone"); + goto doexit; + } + debug("this is the second serial %u", + serial); + query->second_rr_rcvd = true; + query->second_rr_serial = serial; + goto next_rdata; + } + /* + * If we get to this point, we're doing an + * IXFR and have to start really looking + * at serial numbers. + */ + if (query->first_rr_serial == serial) { + debug("got a match for ixfr"); + if (!query->first_repeat_rcvd) { + query->first_repeat_rcvd = true; + goto next_rdata; + } + debug("done with ixfr"); + goto doexit; + } + debug("meaningless soa %u", serial); + next_rdata: + result = dns_rdataset_next(rdataset); + } while (result == ISC_R_SUCCESS); + } + result = dns_message_nextname(msg, DNS_SECTION_ANSWER); + } while (result == ISC_R_SUCCESS); + isc_nmhandle_detach(&query->readhandle); + launch_next_query(query); + query_detach(&query); + return false; +doexit: + dighost_received(len, peer, query); + return true; +} + +static void +process_cookie(dig_lookup_t *l, dns_message_t *msg, isc_buffer_t *optbuf, + size_t optlen) { + char bb[256]; + isc_buffer_t hexbuf; + size_t len; + const unsigned char *sent; + bool copy = true; + isc_result_t result; + + if (l->cookie != NULL) { + isc_buffer_init(&hexbuf, bb, sizeof(bb)); + result = isc_hex_decodestring(l->cookie, &hexbuf); + check_result(result, "isc_hex_decodestring"); + sent = isc_buffer_base(&hexbuf); + len = isc_buffer_usedlength(&hexbuf); + } else { + sent = cookie; + len = sizeof(cookie); + } + + INSIST(msg->cc_ok == 0 && msg->cc_bad == 0); + if (len >= 8 && optlen >= 8U) { + if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) { + msg->cc_ok = 1; + } else { + dighost_warning("Warning: Client COOKIE mismatch"); + msg->cc_bad = 1; + copy = false; + } + } else { + dighost_warning("Warning: COOKIE bad token (too short)"); + msg->cc_bad = 1; + copy = false; + } + if (copy) { + isc_region_t r; + + r.base = isc_buffer_current(optbuf); + r.length = (unsigned int)optlen; + isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie)); + result = isc_hex_totext(&r, 2, "", &hexbuf); + check_result(result, "isc_hex_totext"); + if (isc_buffer_availablelength(&hexbuf) > 0) { + isc_buffer_putuint8(&hexbuf, 0); + l->cookie = servercookie; + } + } + isc_buffer_forward(optbuf, (unsigned int)optlen); +} + +static void +process_opt(dig_lookup_t *l, dns_message_t *msg) { + dns_rdata_t rdata; + isc_result_t result; + isc_buffer_t optbuf; + uint16_t optcode, optlen; + dns_rdataset_t *opt = msg->opt; + bool seen_cookie = false; + + result = dns_rdataset_first(opt); + if (result == ISC_R_SUCCESS) { + dns_rdata_init(&rdata); + dns_rdataset_current(opt, &rdata); + isc_buffer_init(&optbuf, rdata.data, rdata.length); + isc_buffer_add(&optbuf, rdata.length); + while (isc_buffer_remaininglength(&optbuf) >= 4) { + optcode = isc_buffer_getuint16(&optbuf); + optlen = isc_buffer_getuint16(&optbuf); + switch (optcode) { + case DNS_OPT_COOKIE: + /* + * Only process the first cookie option. + */ + if (seen_cookie) { + isc_buffer_forward(&optbuf, optlen); + break; + } + process_cookie(l, msg, &optbuf, optlen); + seen_cookie = true; + break; + default: + isc_buffer_forward(&optbuf, optlen); + break; + } + } + } +} + +static int +ednsvers(dns_rdataset_t *opt) { + return (opt->ttl >> 16) & 0xff; +} + +/*% + * Event handler for recv complete. Perform whatever actions are necessary, + * based on the specifics of the user's request. + */ +static void +recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, + void *arg) { + dig_query_t *query = (dig_query_t *)arg; + isc_buffer_t b; + dns_message_t *msg = NULL; + isc_result_t result; + dig_lookup_t *n = NULL; + dig_lookup_t *l = NULL; + bool docancel = false; + bool donext = false; + bool match = true; + bool done_process_opt = false; + unsigned int parseflags; + dns_messageid_t id; + unsigned int msgflags; + int newedns; + isc_sockaddr_t peer; + + REQUIRE(DIG_VALID_QUERY(query)); + REQUIRE(query->readhandle != NULL); + INSIST(!free_now); + + debug("recv_done(%p, %s, %p, %p)", handle, isc_result_totext(eresult), + region, arg); + + isc_refcount_decrement0(&recvcount); + debug("recvcount=%" PRIuFAST32, isc_refcount_current(&recvcount)); + + lookup_attach(query->lookup, &l); + + if (eresult == ISC_R_CANCELED || eresult == ISC_R_SHUTTINGDOWN || + query->canceled) + { + debug("recv_done: cancel"); + isc_nmhandle_detach(&query->readhandle); + if (eresult == ISC_R_SHUTTINGDOWN) { + cancel_all(); + } else if (!query->canceled) { + cancel_lookup(l); + } + query_detach(&query); + lookup_detach(&l); + clear_current_lookup(); + return; + } + + if (query->lookup->use_usec) { + query->time_recv = isc_time_now_hires(); + } else { + query->time_recv = isc_time_now(); + } + + if ((!l->pending && !l->ns_search_only) || cancel_now) { + debug("no longer pending. Got %s", isc_result_totext(eresult)); + + goto next_lookup; + } + + /* + * NSSEARCH mode is special, because the queries in the followup lookup + * are independent and they are being started in parallel, so if one of + * them fails there is no need to start the next query in the lookup, + * and this failure can be treated as a soft error (with a warning + * message), because there are usually more than one NS servers in the + * lookup's queries list. However, if there was not a single successful + * query in the followup lookup, then print an error message and exit + * with a non-zero exit code. + */ + if (l->ns_search_only && !l->trace_root) { + if (eresult == ISC_R_SUCCESS) { + l->ns_search_success = true; + } else { + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(&query->sockaddr, sockstr, + sizeof(sockstr)); + + dighost_warning("communications error to %s: %s", + sockstr, isc_result_totext(eresult)); + + /* + * If this is not the last query, then we detach the + * query, but keep the lookup running. + */ + if (!check_if_queries_done(l, query)) { + goto detach_query; + } + + /* + * This is the last query, and if there was not a + * single successful query in the whole lookup, then + * treat the situation as an error. + */ + if (!l->ns_search_success) { + dighost_error( + "NS servers could not be reached"); + if (exitcode < 9) { + exitcode = 9; + } + } + + goto cancel_lookup; + } + } + + if (eresult != ISC_R_SUCCESS) { + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); + dighost_warning("communications error to %s: %s", sockstr, + isc_result_totext(eresult)); + + if (l->retries > 1 && !l->tcp_mode) { + dig_query_t *newq = NULL; + + /* + * For UDP, insert a copy of the current query just + * after itself in the list, and start it to retry the + * request. + */ + newq = new_query(l, query->servname, query->userarg); + ISC_LIST_INSERTAFTER(l->q, query, newq, link); + if (l->current_query == query) { + query_detach(&l->current_query); + } + if (l->current_query == NULL) { + l->retries--; + debug("making new UDP request, %d tries left", + l->retries); + start_udp(newq); + } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + + goto detach_query; + } else if (l->retries > 1 && l->tcp_mode) { + /* + * For TCP, we have to requeue the whole lookup, see + * the comments above the start_tcp() function. + */ + l->retries--; + debug("making new TCP request, %d tries left", + l->retries); + requeue_lookup(l, true); + + if (keep != NULL) { + isc_nmhandle_detach(&keep); + } + + goto cancel_lookup; + } else { + dig_query_t *next = ISC_LIST_NEXT(query, link); + + /* + * No retries left, go to the next query, if there is + * one. + */ + if (next != NULL) { + if (l->current_query == query) { + query_detach(&l->current_query); + } + if (l->current_query == NULL) { + debug("starting next query %p", next); + if (l->tcp_mode) { + start_tcp(next); + } else { + start_udp(next); + } + } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + + goto detach_query; + } + + /* + * Otherwise, print the cmdline and an error message, + * and cancel the lookup. + */ + printf("%s", l->cmdline); + dighost_error("no servers could be reached"); + + if (exitcode < 9) { + exitcode = 9; + } + + if (keep != NULL) { + isc_nmhandle_detach(&keep); + } + + goto cancel_lookup; + } + } + + isc_buffer_init(&b, region->base, region->length); + isc_buffer_add(&b, region->length); + + peer = isc_nmhandle_peeraddr(handle); + + result = dns_message_peekheader(&b, &id, &msgflags); + if (result != ISC_R_SUCCESS || l->sendmsg->id != id) { + match = false; + if (l->tcp_mode) { + bool fail = true; + if (result == ISC_R_SUCCESS) { + if (!query->first_soa_rcvd || query->warn_id) { + dighost_warning("%s: ID mismatch: " + "expected ID %u, got " + "%u", + query->first_soa_rcvd + ? "WARNING" + : "ERROR", + l->sendmsg->id, id); + } + if (query->first_soa_rcvd) { + fail = false; + } + query->warn_id = false; + } else { + dighost_warning("ERROR: short (< header size) " + "message"); + } + if (fail) { + goto cancel_lookup; + } + match = true; + } else if (result == ISC_R_SUCCESS) { + dighost_warning("Warning: ID mismatch: expected ID %u," + " got %u", + l->sendmsg->id, id); + } else { + dighost_warning("Warning: short (< header size) " + "message received"); + } + } + + if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) { + dighost_warning("Warning: query response not set"); + } + + if (!match) { + /* + * We are still attached to query and the query->readhandle is + * also attached + */ + isc_refcount_increment0(&recvcount); + debug("recvcount=%" PRIuFAST32, + isc_refcount_current(&recvcount)); + isc_nm_read(handle, recv_done, query); + goto keep_query; + } + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &msg); + + if (tsigkey != NULL) { + if (l->querysig == NULL) { + debug("getting initial querysig"); + result = dns_message_getquerytsig(l->sendmsg, mctx, + &l->querysig); + check_result(result, "dns_message_getquerytsig"); + } + dns_message_setquerytsig(msg, l->querysig); + result = dns_message_settsigkey(msg, tsigkey); + check_result(result, "dns_message_settsigkey"); + msg->tsigctx = l->tsigctx; + l->tsigctx = NULL; + if (l->msgcounter != 0) { + msg->tcp_continuation = 1; + } + l->msgcounter++; + } + + debug("before parse starts"); + parseflags = l->dns64prefix ? 0 : DNS_MESSAGEPARSE_PRESERVEORDER; + if (l->besteffort) { + parseflags |= DNS_MESSAGEPARSE_BESTEFFORT; + parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION; + } + + result = dns_message_parse(msg, &b, parseflags); + if (result == DNS_R_RECOVERABLE) { + dighost_warning("Warning: Message parser reports malformed " + "message packet."); + } else if (result != ISC_R_SUCCESS) { + if (!yaml) { + printf(";; Got bad packet: %s\n", + isc_result_totext(result)); + hex_dump(&b); + } + goto cancel_lookup; + } + + if (msg->opcode != l->opcode) { + char expect[20] = { 0 }, got[20] = { 0 }; + + isc_buffer_init(&b, &expect, sizeof(expect)); + result = dns_opcode_totext(l->opcode, &b); + check_result(result, "dns_opcode_totext"); + + isc_buffer_init(&b, &got, sizeof(got)); + result = dns_opcode_totext(msg->opcode, &b); + check_result(result, "dns_opcode_totext"); + + dighost_warning("Warning: Opcode mismatch: expected %s, got %s", + expect, got); + + isc_refcount_increment0(&recvcount); + debug("recvcount=%" PRIuFAST32, + isc_refcount_current(&recvcount)); + isc_nm_read(handle, recv_done, query); + goto keep_query; + } + + if (msg->counts[DNS_SECTION_QUESTION] == 0) { + if (l->doing_xfr) { + if (query->msg_count == 0) { + dighost_warning("missing question section"); + } + } else if (!l->header_only && msg->opcode == dns_opcode_query) { + dighost_warning("missing question section"); + } + } else { + match = true; + for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); + result == ISC_R_SUCCESS && match; + result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) + { + dns_name_t *name = NULL; + dns_rdataset_t *rdataset; + + dns_message_currentname(msg, DNS_SECTION_QUESTION, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (l->rdtype != rdataset->type || + l->rdclass != rdataset->rdclass || + !dns_name_equal(l->name, name)) + { + char namestr[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; + dns_name_format(name, namestr, + sizeof(namestr)); + dns_rdatatype_format(rdataset->type, + typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdataset->rdclass, + classbuf, + sizeof(classbuf)); + dighost_warning(";; Question section " + "mismatch: got " + "%s/%s/%s", + namestr, typebuf, + classbuf); + match = false; + } + } + } + + if (!match) { + if (l->tcp_mode) { + goto cancel_lookup; + } + + /* + * We are still attached to query and the + * query->readhandle is also attached + */ + isc_refcount_increment0(&recvcount); + debug("recvcount=%" PRIuFAST32, + isc_refcount_current(&recvcount)); + isc_nm_read(handle, recv_done, query); + goto keep_query; + } + } + + if (msg->rcode == dns_rcode_badvers && msg->opt != NULL && + (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) + { + if (l->showbadvers) { + dighost_printmessage(query, &b, msg, true); + dighost_received(isc_buffer_usedlength(&b), &peer, + query); + } + /* + * Add minimum EDNS version required checks here if needed. + */ + dighost_comments(l, "BADVERS, retrying with EDNS version %u.", + (unsigned int)newedns); + l->edns = newedns; + /* + * Extract the server cookie so it can be sent in the retry. + */ + if (l->cookie == NULL && l->sendcookie) { + process_opt(l, msg); + } + n = requeue_lookup(l, true); + if (l->trace && l->trace_root) { + n->rdtype = l->qrdtype; + } + goto cancel_lookup; + } + + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore && + !l->tcp_mode) + { + if (l->cookie == NULL && l->sendcookie && msg->opt != NULL) { + process_opt(l, msg); + } + dighost_comments(l, "Truncated, retrying in TCP mode."); + n = requeue_lookup(l, true); + n->tcp_mode = true; + if (l->trace && l->trace_root) { + n->rdtype = l->qrdtype; + } + goto cancel_lookup; + } + + if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode && + l->sendcookie && l->badcookie) + { + process_opt(l, msg); + if (msg->cc_ok) { + if (l->showbadcookie) { + dighost_printmessage(query, &b, msg, true); + dighost_received(isc_buffer_usedlength(&b), + &peer, query); + } + dighost_comments(l, "BADCOOKIE, retrying%s.", + l->seenbadcookie ? " in TCP mode" + : ""); + n = requeue_lookup(l, true); + if (l->seenbadcookie) { + n->tcp_mode = true; + } + n->seenbadcookie = true; + if (l->trace && l->trace_root) { + n->rdtype = l->qrdtype; + } + goto cancel_lookup; + } + done_process_opt = true; + } + + if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || + (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) + { + const char *err = (msg->rcode == dns_rcode_servfail && + !l->servfail_stops) + ? "SERVFAIL reply" + : "recursion not available"; + dig_query_t *next = ISC_LIST_NEXT(query, link); + if (l->current_query == query) { + query_detach(&l->current_query); + } + if (next != NULL && (!l->ns_search_only || l->trace_root)) { + dighost_comments(l, + "Got %s from %s, trying next server", + err, query->servname); + debug("sending query %p", next); + if (l->tcp_mode) { + start_tcp(next); + } else { + start_udp(next); + } + if (check_if_queries_done(l, query)) { + goto cancel_lookup; + } + + goto detach_query; + } else { + dighost_comments(l, "Got %s from %s", err, + query->servname); + } + } + + if (tsigkey != NULL) { + result = dns_tsig_verify(&b, msg, NULL, NULL); + if (result != ISC_R_SUCCESS) { + dighost_warning("Couldn't verify signature: %s", + isc_result_totext(result)); + validated = false; + } + l->tsigctx = msg->tsigctx; + msg->tsigctx = NULL; + if (l->querysig != NULL) { + debug("freeing querysig buffer %p", l->querysig); + isc_buffer_free(&l->querysig); + } + result = dns_message_getquerytsig(msg, mctx, &l->querysig); + check_result(result, "dns_message_getquerytsig"); + } + + extrabytes = isc_buffer_remaininglength(&b); + + debug("after parse"); + if (l->doing_xfr && l->xfr_q == NULL) { + l->xfr_q = query; + /* + * Once we are in the XFR message, increase + * the timeout to much longer, so brief network + * outages won't cause the XFR to abort + */ + if (timeout != INT_MAX && query->timer != NULL) { + unsigned int local_timeout; + + if (timeout == 0) { + if (l->tcp_mode) { + local_timeout = TCP_TIMEOUT * 4000; + } else { + local_timeout = UDP_TIMEOUT * 4000; + } + } else { + if (timeout < (INT_MAX / 4)) { + local_timeout = timeout * 4000; + } else { + local_timeout = INT_MAX; + } + } + + debug("have local timeout of %d", local_timeout); + isc_nmhandle_settimeout(query->handle, local_timeout); + } + } + + if (!done_process_opt) { + if (l->cookie != NULL) { + if (msg->opt == NULL) { + dighost_warning("expected opt record in " + "response"); + } else { + process_opt(l, msg); + } + } else if (l->sendcookie && msg->opt != NULL) { + process_opt(l, msg); + } + } + + if (!l->doing_xfr || l->xfr_q == query) { + if (msg->rcode == dns_rcode_nxdomain && + (l->origin != NULL || l->need_search)) + { + if (!next_origin(l) || showsearch) { + dighost_printmessage(query, &b, msg, true); + dighost_received(isc_buffer_usedlength(&b), + &peer, query); + } + } else if (!l->trace && !l->ns_search_only) { + dighost_printmessage(query, &b, msg, true); + } else if (l->trace) { + int nl = 0; + int count = msg->counts[DNS_SECTION_ANSWER]; + + debug("in TRACE code"); + if (!l->ns_search_only) { + dighost_printmessage(query, &b, msg, true); + } + + l->rdtype = l->qrdtype; + if (l->trace_root || (l->ns_search_only && count > 0)) { + if (!l->trace_root) { + l->rdtype = dns_rdatatype_soa; + } + nl = followup_lookup(msg, query, + DNS_SECTION_ANSWER); + l->trace_root = false; + } else if (count == 0) { + nl = followup_lookup(msg, query, + DNS_SECTION_AUTHORITY); + } + if (nl == 0) { + docancel = true; + } + } else { + debug("in NSSEARCH code"); + + if (l->trace_root) { + /* + * This is the initial NS query. + */ + int nl; + + l->rdtype = dns_rdatatype_soa; + nl = followup_lookup(msg, query, + DNS_SECTION_ANSWER); + if (nl == 0) { + docancel = true; + } + l->trace_root = false; + usesearch = false; + } else { + /* + * This is a query in the followup lookup + */ + dighost_printmessage(query, &b, msg, true); + + docancel = check_if_queries_done(l, query); + } + } + } + + if (l->pending) { + debug("still pending."); + } + + if (l->doing_xfr) { + if (query != l->xfr_q) { + goto detach_query; + } + if (!docancel) { + docancel = check_for_more_data(l, query, msg, &peer, + region->length); + } + if (docancel) { + goto cancel_lookup; + } + /* + * check_for_more_data() will detach from query->readhandle + * and query on its own, as it needs to reuse the query and + * reattach to the readhandle in launch_next_query(). + */ + goto keep_query; + } else { + if (msg->rcode == dns_rcode_noerror || l->origin == NULL) { + dighost_received(isc_buffer_usedlength(&b), &peer, + query); + } + + if (!l->ns_search_only) { + l->pending = false; + } + if (!l->ns_search_only || l->trace_root || docancel) { + goto cancel_lookup; + } + goto next_lookup; + } +cancel_lookup: + docancel = true; +next_lookup: + donext = true; +detach_query: + isc_nmhandle_detach(&query->readhandle); + query_detach(&query); + if (docancel) { + cancel_lookup(l); + } +keep_query: + if (msg != NULL) { + dns_message_detach(&msg); + } + lookup_detach(&l); + if (donext) { + clear_current_lookup(); + } +} + +/*% + * Turn a name into an address, using system-supplied routines. This is + * used in looking up server names, etc... and needs to use system-supplied + * routines, since they may be using a non-DNS system for these lookups. + */ +isc_result_t +get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) { + int count; + isc_result_t result; + + isc_loopmgr_blocking(loopmgr); + result = isc_getaddresses(host, myport, sockaddr, 1, &count); + isc_loopmgr_nonblocking(loopmgr); + if (result != ISC_R_SUCCESS) { + return result; + } + + INSIST(count == 1); + + return ISC_R_SUCCESS; +} + +int +getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) { + isc_result_t result; + isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES]; + isc_netaddr_t netaddr; + int count, i; + dig_server_t *srv; + char tmp[ISC_NETADDR_FORMATSIZE]; + + isc_loopmgr_blocking(loopmgr); + result = isc_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES, + &count); + isc_loopmgr_nonblocking(loopmgr); + SET_IF_NOT_NULL(resultp, result); + if (result != ISC_R_SUCCESS) { + if (resultp == NULL) { + fatal("couldn't get address for '%s': %s", host, + isc_result_totext(result)); + } + return 0; + } + + for (i = 0; i < count; i++) { + isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]); + isc_netaddr_format(&netaddr, tmp, sizeof(tmp)); + srv = make_server(tmp, host); + ISC_LIST_APPEND(lookup->my_server_list, srv, link); + } + + return count; +} + +/*% + * Initiate either a TCP or UDP lookup + */ +void +do_lookup(dig_lookup_t *lookup) { + dig_query_t *query; + + REQUIRE(lookup != NULL); + + debug("do_lookup()"); + lookup->pending = true; + query = ISC_LIST_HEAD(lookup->q); + if (query != NULL) { + REQUIRE(DIG_VALID_QUERY(query)); + if (lookup->tcp_mode) { + start_tcp(query); + } else { + start_udp(query); + } + } +} + +/*% + * Start everything in action upon task startup. + */ +void +onrun_callback(void *arg) { + UNUSED(arg); + + start_lookup(); +} + +void +run_loop(void *arg) { + UNUSED(arg); + + start_lookup(); +} + +/*% + * Make everything on the lookup queue go away. Mainly used by the + * SIGINT handler. + */ +void +cancel_all(void) { + dig_lookup_t *l, *n; + dig_query_t *q, *nq; + + debug("cancel_all()"); + + if (free_now) { + return; + } + + cancel_now = true; + + while (current_lookup != NULL) { + for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) { + nq = ISC_LIST_NEXT(q, link); + debug("canceling pending query %p, belonging to %p", q, + current_lookup); + q->canceled = true; + if (q->readhandle != NULL && + !isc_nm_is_http_handle(q->readhandle)) + { + isc_nm_cancelread(q->readhandle); + } + query_detach(&q); + } + + /* + * current_lookup could have been detached via query_detach(). + */ + if (current_lookup != NULL) { + lookup_detach(¤t_lookup); + } + } + l = ISC_LIST_HEAD(lookup_list); + while (l != NULL) { + n = ISC_LIST_NEXT(l, link); + ISC_LIST_DEQUEUE(lookup_list, l, link); + lookup_detach(&l); + l = n; + } +} + +void +cleanup_openssl_refs(void) { + if (tsigkey != NULL) { + debug("freeing TSIG key %p", tsigkey); + dns_tsigkey_detach(&tsigkey); + } + + if (sig0key != NULL) { + debug("freeing SIG(0) key %p", sig0key); + dst_key_free(&sig0key); + } + + if (is_dst_up) { + debug("destroy DST lib"); + dst_lib_destroy(); + is_dst_up = false; + } +} + +/*% + * Destroy all of the libs we are using, and get everything ready for a + * clean shutdown. + */ +void +destroy_libs(void) { + debug("destroy_libs()"); + + isc_refcount_destroy(&recvcount); + isc_refcount_destroy(&sendcount); + + INSIST(ISC_LIST_HEAD(lookup_list) == NULL); + INSIST(current_lookup == NULL); + INSIST(!free_now); + + free_now = true; + + flush_server_list(); + + clear_searchlist(); + + cleanup_openssl_refs(); + + if (namebuf != NULL) { + debug("freeing key %p", tsigkey); + isc_buffer_free(&namebuf); + } + + debug("Removing log context"); + isc_log_destroy(&lctx); + + debug("Destroy memory"); + if (memdebugging != 0) { + isc_mem_stats(mctx, stderr); + } + + isc_managers_destroy(&mctx, &loopmgr, &netmgr); + +#if ENABLE_LEAK_DETECTION + isc__tls_setdestroycheck(true); + isc__uv_setdestroycheck(true); + isc__xml_setdestroycheck(true); +#endif + + isc_mem_checkdestroyed(stderr); +} + +#ifdef HAVE_LIBIDN2 + +static isc_result_t +idn_filter(isc_buffer_t *buffer, unsigned int start) { + char src[MXNAME]; + char *dst = NULL; + size_t srclen, dstlen; + int res; + + /* + * Copy name from 'buffer' to 'src' and terminate it with NULL. + */ + srclen = isc_buffer_usedlength(buffer) - start; + INSIST(srclen < sizeof(src)); + memmove(src, (char *)isc_buffer_base(buffer) + start, srclen); + src[srclen] = '\0'; + + /* + * Try to convert the name; leave it unchanged if conversion fails. + */ + systemlocale(LC_ALL); + res = idn2_to_unicode_8zlz(src, &dst, IDN2_NONTRANSITIONAL); + if (res == IDN2_DISALLOWED) { + res = idn2_to_unicode_8zlz(src, &dst, IDN2_TRANSITIONAL); + } + resetlocale(LC_ALL); + if (res != IDN2_OK) { + return ISC_R_SUCCESS; + } + + /* + * Copy the converted back into 'buffer' if it fits. + */ + dstlen = strlen(dst); + if (isc_buffer_length(buffer) < start + dstlen) { + return ISC_R_NOSPACE; + } + isc_buffer_subtract(buffer, srclen); + memmove(isc_buffer_used(buffer), dst, dstlen); + isc_buffer_add(buffer, dstlen); + + idn2_free(dst); + return ISC_R_SUCCESS; +} + +/*% + * Convert 'src', which is a string using the current locale's character + * encoding, into an ACE string suitable for use in the DNS, storing the + * conversion result in 'dst', which is 'dstlen' bytes large. + * + * 'dst' MUST be large enough to hold any valid domain name. + */ +static void +idn_input(const char *src, char *dst, size_t dstlen) { + char *ascii = NULL; + size_t len; + int res; + + /* + * We trust libidn2 to return an error if 'src' is too large to be a + * valid domain name. + * + * If conversion fails under IDNA2008 rules, retry with transitional + * rules. The aim is that characters whose interpretation changed will + * be handled under the new rules, but we will accept characters (such + * as emoji) that were OK but are now forbidden. + */ + systemlocale(LC_ALL); + res = idn2_to_ascii_lz(src, &ascii, IDN2_NONTRANSITIONAL); + if (res == IDN2_DISALLOWED) { + res = idn2_to_ascii_lz(src, &ascii, IDN2_TRANSITIONAL); + } + resetlocale(LC_ALL); + + /* + * idn2_to_ascii_lz() normalizes all strings to lower case, but + * we generally don't want to lowercase all input strings; make + * sure to return the original case if the two strings differ + * only in case. + */ + if (res == IDN2_OK && strcasecmp(src, ascii) != 0) { + len = strlcpy(dst, ascii, dstlen); + } else { + len = strlcpy(dst, src, dstlen); + } + INSIST(len < dstlen); + idn2_free(ascii); +} + +#endif /* HAVE_LIBIDN2 */ + +void +dig_idnsetup(dig_lookup_t *lookup, bool active) { +#ifdef HAVE_LIBIDN2 + isc_result_t result; + result = dns_name_settotextfilter( + (active && lookup->idnout) ? idn_filter : NULL); + check_result(result, "dns_name_settotextfilter"); +#else + UNUSED(lookup); + UNUSED(active); + return; +#endif /* HAVE_LIBIDN2 */ +} + +bool +dig_lookup_is_tls(const dig_lookup_t *lookup) { + if (lookup->tls_mode || (lookup->tls_ca_set && !lookup->https_mode)) { + return true; + } + + return false; +} diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h new file mode 100644 index 0000000..86ccfe0 --- /dev/null +++ b/bin/dig/dighost.h @@ -0,0 +1,471 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef __APPLE__ +#include +#endif /* ifdef __APPLE__ */ + +#define MXSERV 20 +#define MXNAME (DNS_NAME_MAXTEXT + 1) +#define MXRD 32 +/*% Buffer Size */ +#define BUFSIZE 512 +#define COMMSIZE 0xffff +#ifndef RESOLV_CONF +/*% location of resolve.conf */ +#define RESOLV_CONF "/etc/resolv.conf" +#endif /* ifndef RESOLV_CONF */ +/*% output buffer */ +#define OUTPUTBUF 32767 +/*% Max RR Limit */ +#define MAXRRLIMIT 0xffffffff +#define MAXTIMEOUT 0xffff +/*% Max number of tries */ +#define MAXTRIES 0xffffffff +/*% Max number of dots */ +#define MAXNDOTS 0xffff +/*% Max number of ports */ +#define MAXPORT 0xffff +/*% Max serial number */ +#define MAXSERIAL 0xffffffff +/*% Max query ID */ +#define MAXQID 0xffff + +/*% Default TCP Timeout */ +#define TCP_TIMEOUT 10 +/*% Default UDP Timeout */ +#define UDP_TIMEOUT 5 + +#define SERVER_TIMEOUT 1 + +#define LOOKUP_LIMIT 64 + +#define DEFAULT_EDNS_VERSION 0 +#define DEFAULT_EDNS_BUFSIZE 1232 + +#define DEFAULT_HTTPS_QUERY "?dns=" + +/*% + * Lookup_limit is just a limiter, keeping too many lookups from being + * created. It's job is mainly to prevent the program from running away + * in a tight loop of constant lookups. It's value is arbitrary. + */ + +ISC_LANG_BEGINDECLS + +typedef struct dig_lookup dig_lookup_t; +typedef struct dig_query dig_query_t; +typedef struct dig_server dig_server_t; +typedef ISC_LIST(dig_server_t) dig_serverlist_t; +typedef struct dig_searchlist dig_searchlist_t; + +#define DIG_LOOKUP_MAGIC ISC_MAGIC('D', 'i', 'g', 'l') + +#define DIG_VALID_LOOKUP(x) ISC_MAGIC_VALID((x), DIG_LOOKUP_MAGIC) + +#define DIG_QUERY_MAGIC ISC_MAGIC('D', 'i', 'g', 'q') + +#define DIG_VALID_QUERY(x) ISC_MAGIC_VALID((x), DIG_QUERY_MAGIC) + +/*% The dig_lookup structure */ +struct dig_lookup { + unsigned int magic; + isc_refcount_t references; + bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, comments, + dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, expandaaaa, + expire, fuzzing, header_only, identify, /*%< Append an "on + server " message + */ + identify_previous_line, /*% Prepend a "Nameserver :" + message, with newline and tab */ + idnin, idnout, ignore, multiline, need_search, new_search, + noclass, nocrypto, nottl, ns_search_only, /*%< dig +nssearch, + host -C */ + ns_search_success, nsid, /*% Name Server ID (RFC 5001) */ + onesoa, pending, /*%< Pending a successful answer */ + print_unknown_format, qr, raflag, recurse, section_additional, + section_answer, section_authority, section_question, + seenbadcookie, sendcookie, servfail_stops, + setqid, /*% use a speciied query ID */ + showbadcookie, showbadvers, stats, tcflag, tcp_keepalive, + tcp_mode, tcp_mode_set, tls_mode, /*% connect using TLS */ + trace, /*% dig +trace */ + trace_root, /*% initial query for either +trace or +nssearch */ + ttlunits, use_usec, waiting_connect, zflag; + char textname[MXNAME]; /*% Name we're going to be looking up */ + char cmdline[MXNAME]; + dns_rdatatype_t rdtype; + dns_rdatatype_t qrdtype; + dns_rdataclass_t rdclass; + bool rdtypeset; + bool rdclassset; + char name_space[BUFSIZE]; + char oname_space[BUFSIZE]; + isc_buffer_t namebuf; + isc_buffer_t onamebuf; + isc_buffer_t renderbuf; + char *sendspace; + dns_name_t *name; + isc_interval_t interval; + dns_message_t *sendmsg; + dns_name_t *oname; + ISC_LINK(dig_lookup_t) link; + ISC_LIST(dig_query_t) q; + ISC_LIST(dig_query_t) connecting; + dig_query_t *current_query; + dig_serverlist_t my_server_list; + dig_searchlist_t *origin; + dig_query_t *xfr_q; + uint32_t retries; + int nsfound; + int16_t udpsize; + int16_t edns; + int16_t original_edns; + int16_t padding; + uint32_t ixfr_serial; + isc_buffer_t rdatabuf; + char rdatastore[MXNAME]; + dst_context_t *tsigctx; + isc_buffer_t *querysig; + uint32_t msgcounter; + dns_fixedname_t fdomain; + isc_sockaddr_t *ecs_addr; + char *cookie; + dns_ednsopt_t *ednsopts; + unsigned int ednsoptscnt; + unsigned int ednsflags; + dns_opcode_t opcode; + int rrcomments; + uint16_t qid; + struct { + bool http_plain; + bool https_mode; + bool https_get; + char *https_path; + }; + struct { + bool tls_ca_set; + char *tls_ca_file; + bool tls_hostname_set; + char *tls_hostname; + bool tls_cert_file_set; + char *tls_cert_file; + bool tls_key_file_set; + char *tls_key_file; + isc_tlsctx_cache_t *tls_ctx_cache; + }; + struct { + bool proxy_mode; + bool proxy_plain; + bool proxy_local; + isc_sockaddr_t proxy_src_addr; + isc_sockaddr_t proxy_dst_addr; + }; + isc_stdtime_t fuzztime; +}; + +/*% The dig_query structure */ +struct dig_query { + unsigned int magic; + dig_lookup_t *lookup; + bool started; + bool first_soa_rcvd; + bool second_rr_rcvd; + bool first_repeat_rcvd; + bool warn_id; + bool canceled; + uint32_t first_rr_serial; + uint32_t second_rr_serial; + uint32_t msg_count; + uint32_t rr_count; + bool ixfr_axfr; + char *servname; + char *userarg; + isc_buffer_t sendbuf; + char *recvspace, *tmpsendspace, lengthspace[4]; + isc_refcount_t references; + isc_nmhandle_t *handle; + isc_nmhandle_t *readhandle; + isc_nmhandle_t *sendhandle; + ISC_LINK(dig_query_t) link; + ISC_LINK(dig_query_t) clink; + isc_sockaddr_t sockaddr; + isc_time_t time_sent; + isc_time_t time_recv; + uint64_t byte_count; + isc_timer_t *timer; +}; + +struct dig_server { + char servername[MXNAME]; + char userarg[MXNAME]; + ISC_LINK(dig_server_t) link; +}; + +struct dig_searchlist { + char origin[MXNAME]; + ISC_LINK(dig_searchlist_t) link; +}; + +typedef ISC_LIST(dig_searchlist_t) dig_searchlistlist_t; +typedef ISC_LIST(dig_lookup_t) dig_lookuplist_t; + +/* + * Externals from dighost.c + */ + +extern dig_lookuplist_t lookup_list; +extern dig_serverlist_t server_list; +extern dig_searchlistlist_t search_list; +extern unsigned int extrabytes; + +extern bool check_ra, have_ipv4, have_ipv6, specified_source, usesearch, + showsearch, yaml; +extern in_port_t port; +extern bool port_set; +extern unsigned int timeout; +extern isc_mem_t *mctx; +extern isc_refcount_t sendcount; +extern int ndots; +extern int lookup_counter; +extern int exitcode; +extern isc_sockaddr_t localaddr; +extern char keynametext[MXNAME]; +extern char keyfile[MXNAME]; +extern char keysecret[MXNAME]; +extern dst_algorithm_t hmac_alg; +extern unsigned int digestbits; +extern dns_tsigkey_t *tsigkey; +extern bool validated; +extern isc_loopmgr_t *loopmgr; +extern isc_loop_t *mainloop; +extern bool free_now; +extern bool debugging, debugtiming, memdebugging; +extern bool keep_open; + +extern char *progname; +extern int tries; +extern int fatalexit; +extern bool verbose; + +/* + * Routines in dighost.c. + */ +isc_result_t +get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr); + +int +getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp); + +isc_result_t +get_reverse(char *reverse, size_t len, char *value, bool strict); + +noreturn void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +void +warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +noreturn void +digexit(void); + +void +cleanup_openssl_refs(void); + +void +debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +void +check_result(isc_result_t result, const char *msg); + +bool +setup_lookup(dig_lookup_t *lookup); + +void +destroy_lookup(dig_lookup_t *lookup); + +void +do_lookup(dig_lookup_t *lookup); + +void +start_lookup(void); + +void +onrun_callback(void *arg); + +void +run_loop(void *arg); + +int +dhmain(int argc, char **argv); + +void +setup_libs(void); + +void +setup_system(bool ipv4only, bool ipv6only); + +isc_result_t +parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc); + +isc_result_t +parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc); + +isc_result_t +parse_netprefix(isc_sockaddr_t **sap, const char *value); + +void +parse_hmac(const char *algname); + +dig_lookup_t * +requeue_lookup(dig_lookup_t *lookold, bool servers); + +dig_lookup_t * +make_empty_lookup(void); + +dig_lookup_t * +clone_lookup(dig_lookup_t *lookold, bool servers); + +dig_server_t * +make_server(const char *servname, const char *userarg); + +void +flush_server_list(void); + +void +set_nameserver(char *opt); + +void +clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest); + +void +cancel_all(void); + +void +destroy_libs(void); + +void +set_search_domain(char *domain); + +/* + * Routines to be defined in dig.c, host.c, and nslookup.c. and + * then assigned to the appropriate function pointer + */ +extern isc_result_t (*dighost_printmessage)(dig_query_t *query, + const isc_buffer_t *msgbuf, + dns_message_t *msg, bool headers); + +/* + * Print an error message in the appropriate format. + */ +extern void (*dighost_error)(const char *format, ...); + +/* + * Print a warning message in the appropriate format. + */ +extern void (*dighost_warning)(const char *format, ...); + +/* + * Print a comment in the appropriate format. + */ +extern void (*dighost_comments)(dig_lookup_t *lookup, const char *format, ...); + +/*%< + * Print the final result of the lookup. + */ + +extern void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, + dig_query_t *query); +/*%< + * Print a message about where and when the response + * was received from, like the final comment in the + * output of "dig". + */ + +extern void (*dighost_trying)(char *frm, dig_lookup_t *lookup); + +extern void (*dighost_shutdown)(void); + +extern void (*dighost_pre_exit_hook)(void); + +void +save_opt(dig_lookup_t *lookup, char *code, char *value); + +void +setup_file_key(void); +void +setup_text_key(void); + +/* + * Routines exported from dig.c for use by dig for iOS + */ + +/*% + * Call once only to set up libraries, parse global + * parameters and initial command line query parameters + */ +void +dig_setup(int argc, char **argv); + +/*% + * Call to supply new parameters for the next lookup + */ +void +dig_query_setup(bool, bool, int argc, char **argv); + +/*% + * set the main application event cycle running + */ +void +dig_startup(void); + +/*% + * Activate/deactivate IDN filtering of output. + */ +void +dig_idnsetup(dig_lookup_t *lookup, bool active); + +/*% + * Cleans up the application + */ +void +dig_shutdown(void); + +bool +dig_lookup_is_tls(const dig_lookup_t *lookup); + +ISC_LANG_ENDDECLS diff --git a/bin/dig/host.c b/bin/dig/host.c new file mode 100644 index 0000000..533ecfa --- /dev/null +++ b/bin/dig/host.c @@ -0,0 +1,932 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dighost.h" + +static bool short_form = true, listed_server = false; +static bool default_lookups = true; +static int seen_error = -1; +static bool list_addresses = true; +static bool list_almost_all = false; +static dns_rdatatype_t list_type = dns_rdatatype_a; +static bool printed_server = false; +static bool ipv4only = false, ipv6only = false; + +static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS", + "RESERVED3", "NOTIFY", "UPDATE", + "RESERVED6", "RESERVED7", "RESERVED8", + "RESERVED9", "RESERVED10", "RESERVED11", + "RESERVED12", "RESERVED13", "RESERVED14", + "RESERVED15" }; + +static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", + "NXDOMAIN", "NOTIMP", "REFUSED", + "YXDOMAIN", "YXRRSET", "NXRRSET", + "NOTAUTH", "NOTZONE", "RESERVED11", + "RESERVED12", "RESERVED13", "RESERVED14", + "RESERVED15", "BADVERS" }; + +struct rtype { + unsigned int type; + const char *text; +}; + +struct rtype rtypes[] = { { 1, "has address" }, + { 2, "name server" }, + { 5, "is an alias for" }, + { 11, "has well known services" }, + { 12, "domain name pointer" }, + { 13, "host information" }, + { 15, "mail is handled by" }, + { 16, "descriptive text" }, + { 19, "x25 address" }, + { 20, "ISDN address" }, + { 24, "has signature" }, + { 25, "has key" }, + { 28, "has IPv6 address" }, + { 29, "location" }, + { dns_rdatatype_https, "has HTTP service bindings" }, + { 0, NULL } }; + +static char * +rcode_totext(dns_rcode_t rcode) { + static char buf[sizeof("?65535")]; + union { + const char *consttext; + char *deconsttext; + } totext; + + if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) { + snprintf(buf, sizeof(buf), "?%u", rcode); + totext.deconsttext = buf; + } else { + totext.consttext = rcodetext[rcode]; + } + return totext.deconsttext; +} + +noreturn static void +show_usage(void); + +static void +show_usage(void) { + fprintf(stderr, + "Usage: host [-aCdilrTvVw] [-c class] [-N ndots] [-t type] [-W " + "time]\n" + " [-R number] [-m flag] [-p port] hostname " + "[server]\n" + " -a is equivalent to -v -t ANY\n" + " -A is like -a but omits RRSIG, NSEC, NSEC3\n" + " -c specifies query class for non-IN data\n" + " -C compares SOA records on authoritative nameservers\n" + " -d is equivalent to -v\n" + " -l lists all hosts in a domain, using AXFR\n" + " -m set memory debugging flag (trace|record|usage)\n" + " -N changes the number of dots allowed before root " + "lookup " + "is done\n" + " -p specifies the port on the server to query\n" + " -r disables recursive processing\n" + " -R specifies number of retries for UDP packets\n" + " -s a SERVFAIL response should stop query\n" + " -t specifies the query type\n" + " -T enables TCP/IP mode\n" + " -U enables UDP mode\n" + " -v enables verbose output\n" + " -V print version number and exit\n" + " -w specifies to wait forever for a reply\n" + " -W specifies how long to wait for a reply\n" + " -4 use IPv4 query transport only\n" + " -6 use IPv6 query transport only\n"); + exit(EXIT_FAILURE); +} + +static void +host_shutdown(void) { + isc_loopmgr_shutdown(loopmgr); +} + +static void +received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) { + isc_time_t now; + int diff; + + if (!short_form) { + char fromtext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(from, fromtext, sizeof(fromtext)); + if (query->lookup->use_usec) { + now = isc_time_now_hires(); + } else { + now = isc_time_now(); + } + diff = (int)isc_time_microdiff(&now, &query->time_sent); + printf("Received %u bytes from %s in %d ms\n", bytes, fromtext, + diff / 1000); + } +} + +static void +trying(char *frm, dig_lookup_t *lookup) { + UNUSED(lookup); + + if (!short_form) { + printf("Trying \"%s\"\n", frm); + } +} + +static void +say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata, + dig_query_t *query) { + isc_buffer_t *b = NULL; + char namestr[DNS_NAME_FORMATSIZE]; + isc_region_t r; + isc_result_t result; + unsigned int bufsize = BUFSIZ; + + dns_name_format(name, namestr, sizeof(namestr)); +retry: + isc_buffer_allocate(mctx, &b, bufsize); + result = dns_rdata_totext(rdata, NULL, b); + if (result == ISC_R_NOSPACE) { + isc_buffer_free(&b); + INSIST(bufsize <= (UINT_MAX / 2)); + bufsize *= 2; + goto retry; + } + check_result(result, "dns_rdata_totext"); + isc_buffer_usedregion(b, &r); + if (query->lookup->identify_previous_line) { + printf("Nameserver %s:\n\t", query->servname); + } + printf("%s %s %.*s", namestr, msg, (int)r.length, (char *)r.base); + if (query->lookup->identify) { + printf(" on server %s", query->servname); + } + printf("\n"); + isc_buffer_free(&b); +} + +static isc_result_t +printsection(dns_message_t *msg, dns_section_t sectionid, + const char *section_name, bool headers, dig_query_t *query) { + dns_name_t *name, *print_name; + dns_rdataset_t *rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t target; + isc_result_t result, loopresult; + isc_region_t r; + dns_name_t empty_name; + char tbuf[4096] = { 0 }; + bool first; + bool no_rdata = (sectionid == DNS_SECTION_QUESTION); + + if (headers) { + printf(";; %s SECTION:\n", section_name); + } + + dns_name_init(&empty_name, NULL); + + result = dns_message_firstname(msg, sectionid); + if (result == ISC_R_NOMORE) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + return result; + } + + for (;;) { + name = NULL; + dns_message_currentname(msg, sectionid, &name); + + isc_buffer_init(&target, tbuf, sizeof(tbuf)); + first = true; + print_name = name; + + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (query->lookup->rdtype == dns_rdatatype_axfr && + !((!list_addresses && + (list_type == dns_rdatatype_any || + rdataset->type == list_type)) || + (list_addresses && + (rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa || + rdataset->type == dns_rdatatype_ns || + rdataset->type == dns_rdatatype_ptr)))) + { + continue; + } + if (list_almost_all && + (rdataset->type == dns_rdatatype_rrsig || + rdataset->type == dns_rdatatype_nsec || + rdataset->type == dns_rdatatype_nsec3)) + { + continue; + } + if (!short_form) { + result = dns_rdataset_totext(rdataset, + print_name, false, + no_rdata, &target); + if (result != ISC_R_SUCCESS) { + return result; + } +#ifdef USEINITALWS + if (first) { + print_name = &empty_name; + first = false; + } +#else /* ifdef USEINITALWS */ + UNUSED(first); /* Shut up compiler. */ +#endif /* ifdef USEINITALWS */ + } else { + loopresult = dns_rdataset_first(rdataset); + while (loopresult == ISC_R_SUCCESS) { + struct rtype *t; + const char *rtt; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char typebuf2[DNS_RDATATYPE_FORMATSIZE + + 20]; + dns_rdataset_current(rdataset, &rdata); + + for (t = rtypes; t->text != NULL; t++) { + if (t->type == rdata.type) { + rtt = t->text; + goto found; + } + } + + dns_rdatatype_format(rdata.type, + typebuf, + sizeof(typebuf)); + snprintf(typebuf2, sizeof(typebuf2), + "has %s record", typebuf); + rtt = typebuf2; + found: + say_message(print_name, rtt, &rdata, + query); + dns_rdata_reset(&rdata); + loopresult = + dns_rdataset_next(rdataset); + } + } + } + if (!short_form) { + isc_buffer_usedregion(&target, &r); + if (no_rdata) { + printf(";%.*s", (int)r.length, (char *)r.base); + } else { + printf("%.*s", (int)r.length, (char *)r.base); + } + } + + result = dns_message_nextname(msg, sectionid); + if (result == ISC_R_NOMORE) { + break; + } else if (result != ISC_R_SUCCESS) { + return result; + } + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, + const dns_name_t *owner, const char *set_name, bool headers) { + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char tbuf[4096]; + + UNUSED(msg); + if (headers) { + printf(";; %s SECTION:\n", set_name); + } + + isc_buffer_init(&target, tbuf, sizeof(tbuf)); + + result = dns_rdataset_totext(rdataset, owner, false, false, &target); + if (result != ISC_R_SUCCESS) { + return result; + } + isc_buffer_usedregion(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return ISC_R_SUCCESS; +} + +static void +chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { + isc_result_t result; + dns_rdataset_t *rdataset; + dns_rdata_cname_t cname; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned int i = msg->counts[DNS_SECTION_ANSWER]; + + while (i-- > 0) { + rdataset = NULL; + result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, + dns_rdatatype_cname, 0, NULL, + &rdataset); + if (result != ISC_R_SUCCESS) { + return; + } + result = dns_rdataset_first(rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &cname, NULL); + check_result(result, "dns_rdata_tostruct"); + dns_name_copy(&cname.cname, qname); + dns_rdata_freestruct(&cname); + } +} + +static isc_result_t +printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg, + bool headers) { + bool did_flag = false; + dns_rdataset_t *opt, *tsig = NULL; + const dns_name_t *tsigname; + isc_result_t result = ISC_R_SUCCESS; + int force_error; + + UNUSED(msgbuf); + UNUSED(headers); + + /* + * We get called multiple times. + * Preserve any existing error status. + */ + force_error = (seen_error == 1) ? 1 : 0; + seen_error = 1; + if (listed_server && !printed_server) { + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + + printf("Using domain server:\n"); + printf("Name: %s\n", query->userarg); + isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr)); + printf("Address: %s\n", sockstr); + printf("Aliases: \n\n"); + printed_server = true; + } + + if (msg->rcode != 0) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_name_format(query->lookup->name, namestr, sizeof(namestr)); + + if (query->lookup->identify_previous_line) { + printf("Nameserver %s:\n\t%s not found: %d(%s)\n", + query->servname, + (msg->rcode != dns_rcode_nxdomain) + ? namestr + : query->lookup->textname, + msg->rcode, rcode_totext(msg->rcode)); + } else { + printf("Host %s not found: %d(%s)\n", + (msg->rcode != dns_rcode_nxdomain) + ? namestr + : query->lookup->textname, + msg->rcode, rcode_totext(msg->rcode)); + } + return ISC_R_SUCCESS; + } + + if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { + char namestr[DNS_NAME_FORMATSIZE]; + dig_lookup_t *lookup; + dns_fixedname_t fixed; + dns_name_t *name; + + /* Add AAAA and MX lookups. */ + name = dns_fixedname_initname(&fixed); + dns_name_copy(query->lookup->name, name); + chase_cnamechain(msg, name); + dns_name_format(name, namestr, sizeof(namestr)); + lookup = clone_lookup(query->lookup, false); + if (lookup != NULL) { + strlcpy(lookup->textname, namestr, + sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_aaaa; + lookup->rdtypeset = true; + lookup->origin = NULL; + lookup->retries = tries; + ISC_LIST_APPEND(lookup_list, lookup, link); + } + lookup = clone_lookup(query->lookup, false); + if (lookup != NULL) { + strlcpy(lookup->textname, namestr, + sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_mx; + lookup->rdtypeset = true; + lookup->origin = NULL; + lookup->retries = tries; + ISC_LIST_APPEND(lookup_list, lookup, link); + } + lookup = clone_lookup(query->lookup, false); + if (lookup != NULL) { + strlcpy(lookup->textname, namestr, + sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_https; + lookup->rdtypeset = true; + lookup->origin = NULL; + lookup->retries = tries; + ISC_LIST_APPEND(lookup_list, lookup, link); + } + } + + if (!short_form) { + printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", + opcodetext[msg->opcode], rcode_totext(msg->rcode), + msg->id); + printf(";; flags: "); + if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { + printf("qr"); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { + printf("%saa", did_flag ? " " : ""); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { + printf("%stc", did_flag ? " " : ""); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { + printf("%srd", did_flag ? " " : ""); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { + printf("%sra", did_flag ? " " : ""); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { + printf("%sad", did_flag ? " " : ""); + did_flag = true; + } + if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { + printf("%scd", did_flag ? " " : ""); + did_flag = true; + POST(did_flag); + } + printf("; QUERY: %u, ANSWER: %u, " + "AUTHORITY: %u, ADDITIONAL: %u\n", + msg->counts[DNS_SECTION_QUESTION], + msg->counts[DNS_SECTION_ANSWER], + msg->counts[DNS_SECTION_AUTHORITY], + msg->counts[DNS_SECTION_ADDITIONAL]); + opt = dns_message_getopt(msg); + if (opt != NULL) { + printf(";; EDNS: version: %u, udp=%u\n", + (unsigned int)((opt->ttl & 0x00ff0000) >> 16), + (unsigned int)opt->rdclass); + } + tsigname = NULL; + tsig = dns_message_gettsig(msg, &tsigname); + if (tsig != NULL) { + printf(";; PSEUDOSECTIONS: TSIG\n"); + } + } + if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) && !short_form) + { + printf("\n"); + result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION", + true, query); + if (result != ISC_R_SUCCESS) { + return result; + } + } + if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { + if (!short_form) { + printf("\n"); + } + result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER", + !short_form, query); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) && + !short_form) + { + printf("\n"); + result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY", + true, query); + if (result != ISC_R_SUCCESS) { + return result; + } + } + if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) && + !short_form) + { + printf("\n"); + result = printsection(msg, DNS_SECTION_ADDITIONAL, "ADDITIONAL", + true, query); + if (result != ISC_R_SUCCESS) { + return result; + } + } + if ((tsig != NULL) && !short_form) { + printf("\n"); + result = printrdata(msg, tsig, tsigname, "PSEUDOSECTION TSIG", + true); + if (result != ISC_R_SUCCESS) { + return result; + } + } + if (!short_form) { + printf("\n"); + } + + if (short_form && !default_lookups && + ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) + { + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + dns_name_format(query->lookup->name, namestr, sizeof(namestr)); + dns_rdatatype_format(query->lookup->rdtype, typestr, + sizeof(typestr)); + printf("%s has no %s record\n", namestr, typestr); + } + seen_error = force_error; + return result; +} + +static const char *optstring = "46aAc:dilnm:p:rst:vVwCDN:R:TUW:"; + +static void +pre_parse_args(int argc, char **argv) { + int c; + + while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { + switch (c) { + case 'm': + memdebugging = true; + if (strcasecmp("trace", isc_commandline_argument) == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + } else if (strcasecmp("record", + isc_commandline_argument) == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + } else if (strcasecmp("usage", + isc_commandline_argument) == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + } + break; + + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + case 'a': + break; + case 'A': + break; + case 'c': + break; + case 'C': + break; + case 'd': + break; + case 'D': + if (debugging) { + debugtiming = true; + } + debugging = true; + break; + case 'i': + break; + case 'l': + break; + case 'n': + break; + case 'N': + break; + case 'p': + break; + case 'r': + break; + case 'R': + break; + case 's': + break; + case 't': + break; + case 'T': + break; + case 'U': + break; + case 'v': + break; + case 'V': + printf("host %s\n", PACKAGE_VERSION); + exit(EXIT_SUCCESS); + break; + case 'w': + break; + case 'W': + break; + default: + show_usage(); + } + } + isc_commandline_reset = true; + isc_commandline_index = 1; +} + +static void +parse_args(bool is_batchfile, int argc, char **argv) { + char hostname[MXNAME]; + dig_lookup_t *lookup; + int c; + char store[MXNAME]; + isc_textregion_t tr; + isc_result_t result = ISC_R_SUCCESS; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + uint32_t serial = 0; + + UNUSED(is_batchfile); + + lookup = make_empty_lookup(); + + lookup->servfail_stops = false; + lookup->besteffort = false; + lookup->comments = false; + short_form = !verbose; + + while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { + switch (c) { + case 'l': + lookup->tcp_mode = true; + lookup->rdtype = dns_rdatatype_axfr; + lookup->rdtypeset = true; + fatalexit = 3; + break; + case 'v': + case 'd': + short_form = false; + break; + case 'r': + lookup->recurse = false; + break; + case 't': + if (strncasecmp(isc_commandline_argument, "ixfr=", 5) == + 0) + { + rdtype = dns_rdatatype_ixfr; + /* XXXMPA add error checking */ + serial = strtoul(isc_commandline_argument + 5, + NULL, 10); + result = ISC_R_SUCCESS; + } else { + tr.base = isc_commandline_argument; + tr.length = strlen(isc_commandline_argument); + result = dns_rdatatype_fromtext( + &rdtype, (isc_textregion_t *)&tr); + } + + if (result != ISC_R_SUCCESS) { + fatalexit = 2; + fatal("invalid type: %s\n", + isc_commandline_argument); + } + if (!lookup->rdtypeset || + lookup->rdtype != dns_rdatatype_axfr) + { + lookup->rdtype = rdtype; + } + lookup->rdtypeset = true; + if (rdtype == dns_rdatatype_axfr) { + /* -l -t any -v */ + list_type = dns_rdatatype_any; + short_form = false; + lookup->tcp_mode = true; + } else if (rdtype == dns_rdatatype_ixfr) { + lookup->ixfr_serial = serial; + lookup->tcp_mode = true; + list_type = rdtype; + } else if (rdtype == dns_rdatatype_any) { + if (!lookup->tcp_mode_set) { + lookup->tcp_mode = true; + } + } else { + list_type = rdtype; + } + list_addresses = false; + default_lookups = false; + break; + case 'c': + tr.base = isc_commandline_argument; + tr.length = strlen(isc_commandline_argument); + result = dns_rdataclass_fromtext( + &rdclass, (isc_textregion_t *)&tr); + + if (result != ISC_R_SUCCESS) { + fatalexit = 2; + fatal("invalid class: %s\n", + isc_commandline_argument); + } else { + lookup->rdclass = rdclass; + lookup->rdclassset = true; + } + default_lookups = false; + break; + case 'A': + list_almost_all = true; + FALLTHROUGH; + case 'a': + if (!lookup->rdtypeset || + lookup->rdtype != dns_rdatatype_axfr) + { + lookup->rdtype = dns_rdatatype_any; + } + list_type = dns_rdatatype_any; + list_addresses = false; + lookup->rdtypeset = true; + short_form = false; + default_lookups = false; + break; + case 'i': + /* deprecated */ + break; + case 'n': + /* deprecated */ + break; + case 'm': + /* Handled by pre_parse_args(). */ + break; + case 'w': + /* + * The timer routines are coded such that + * timeout==MAXINT doesn't enable the timer + */ + timeout = INT_MAX; + break; + case 'W': + timeout = atoi(isc_commandline_argument); + if (timeout < 1) { + timeout = 1; + } + break; + case 'R': + tries = atoi(isc_commandline_argument) + 1; + if (tries < 2) { + tries = 2; + } + break; + case 'T': + lookup->tcp_mode = true; + lookup->tcp_mode_set = true; + break; + case 'U': + lookup->tcp_mode = false; + lookup->tcp_mode_set = true; + break; + case 'C': + debug("showing all SOAs"); + lookup->rdtype = dns_rdatatype_ns; + lookup->rdtypeset = true; + lookup->rdclass = dns_rdataclass_in; + lookup->rdclassset = true; + lookup->ns_search_only = true; + lookup->trace_root = true; + lookup->identify_previous_line = true; + default_lookups = false; + break; + case 'N': + debug("setting NDOTS to %s", isc_commandline_argument); + ndots = atoi(isc_commandline_argument); + break; + case 'D': + /* Handled by pre_parse_args(). */ + break; + case '4': + /* Handled by pre_parse_args(). */ + break; + case '6': + /* Handled by pre_parse_args(). */ + break; + case 's': + lookup->servfail_stops = true; + break; + case 'p': + port = atoi(isc_commandline_argument); + port_set = true; + break; + } + } + + lookup->retries = tries; + + if (isc_commandline_index >= argc) { + show_usage(); + } + + strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname)); + + if (argc > isc_commandline_index + 1) { + set_nameserver(argv[isc_commandline_index + 1]); + debug("server is %s", argv[isc_commandline_index + 1]); + listed_server = true; + } else { + check_ra = true; + } + + lookup->pending = false; + if (get_reverse(store, sizeof(store), hostname, true) == ISC_R_SUCCESS) + { + strlcpy(lookup->textname, store, sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_ptr; + lookup->rdtypeset = true; + default_lookups = false; + } else { + strlcpy(lookup->textname, hostname, sizeof(lookup->textname)); + usesearch = true; + } + lookup->new_search = true; + ISC_LIST_APPEND(lookup_list, lookup, link); +} + +int +main(int argc, char **argv) { + tries = 2; + + ISC_LIST_INIT(lookup_list); + ISC_LIST_INIT(server_list); + ISC_LIST_INIT(search_list); + + fatalexit = 1; + + /* setup dighost callbacks */ + dighost_printmessage = printmessage; + dighost_received = received; + dighost_trying = trying; + dighost_shutdown = host_shutdown; + + debug("main()"); + progname = argv[0]; + pre_parse_args(argc, argv); + setup_libs(); + setup_system(ipv4only, ipv6only); + parse_args(false, argc, argv); + if (keyfile[0] != 0) { + setup_file_key(); + } else if (keysecret[0] != 0) { + setup_text_key(); + } + + isc_loopmgr_setup(loopmgr, run_loop, NULL); + isc_loopmgr_run(loopmgr); + + cancel_all(); + destroy_libs(); + + return (seen_error == 0) ? 0 : 1; +} diff --git a/bin/dig/host.rst b/bin/dig/host.rst new file mode 100644 index 0000000..71a736d --- /dev/null +++ b/bin/dig/host.rst @@ -0,0 +1,193 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: host +.. program:: host +.. _man_host: + +host - DNS lookup utility +------------------------- + +Synopsis +~~~~~~~~ + +:program:`host` [**-aACdlnrsTUwv**] [**-c** class] [**-N** ndots] [**-p** port] [**-R** number] [**-t** type] [**-W** wait] [**-m** flag] [ [**-4**] | [**-6**] ] [**-v**] [**-V**] {name} [server] + +Description +~~~~~~~~~~~ + +:program:`host` is a simple utility for performing DNS lookups. It is normally +used to convert names to IP addresses and vice versa. When no arguments +or options are given, :program:`host` prints a short summary of its +command-line arguments and options. + +``name`` is the domain name that is to be looked up. It can also be a +dotted-decimal IPv4 address or a colon-delimited IPv6 address, in which +case :program:`host` by default performs a reverse lookup for that address. +``server`` is an optional argument which is either the name or IP +address of the name server that :program:`host` should query instead of the +server or servers listed in ``/etc/resolv.conf``. + +Options +~~~~~~~ + +.. option:: -4 + + This option specifies that only IPv4 should be used for query transport. See also the :option:`-6` option. + +.. option:: -6 + + This option specifies that only IPv6 should be used for query transport. See also the :option:`-4` option. + +.. option:: -a + + The :option:`-a` ("all") option is normally equivalent to :option:`-v` :option:`-t ANY <-t>`. It + also affects the behavior of the :option:`-l` list zone option. + +.. option:: -A + + The :option:`-A` ("almost all") option is equivalent to :option:`-a`, except that RRSIG, + NSEC, and NSEC3 records are omitted from the output. + +.. option:: -c class + + This option specifies the query class, which can be used to lookup HS (Hesiod) or CH (Chaosnet) + class resource records. The default class is IN (Internet). + +.. option:: -C + + This option indicates that :iscman:`named` should check consistency, meaning that :program:`host` queries the SOA records for zone + ``name`` from all the listed authoritative name servers for that + zone. The list of name servers is defined by the NS records that are + found for the zone. + +.. option:: -d + + This option prints debugging traces, and is equivalent to the :option:`-v` verbose option. + +.. option:: -l + + This option tells :iscman:`named` to list the zone, meaning the :program:`host` command performs a zone transfer of zone + ``name`` and prints out the NS, PTR, and address records (A/AAAA). + + Together, the :option:`-l` :option:`-a` options print all records in the zone. + +.. option:: -N ndots + + This option specifies the number of dots (``ndots``) that have to be in ``name`` for it to be + considered absolute. The default value is that defined using the + ``ndots`` statement in ``/etc/resolv.conf``, or 1 if no ``ndots`` statement + is present. Names with fewer dots are interpreted as relative names, + and are searched for in the domains listed in the ``search`` or + ``domain`` directive in ``/etc/resolv.conf``. + +.. option:: -p port + + This option specifies the port to query on the server. The default is 53. + +.. option:: -r + + This option specifies a non-recursive query; setting this option clears the RD (recursion + desired) bit in the query. This means that the name server + receiving the query does not attempt to resolve ``name``. The :option:`-r` + option enables :program:`host` to mimic the behavior of a name server by + making non-recursive queries, and expecting to receive answers to + those queries that can be referrals to other name servers. + +.. option:: -R number + + This option specifies the number of retries for UDP queries. If ``number`` is negative or zero, + the number of retries is silently set to 1. The default value is 1, or + the value of the ``attempts`` option in ``/etc/resolv.conf``, if set. + +.. option:: -s + + This option tells :iscman:`named` *not* to send the query to the next nameserver if any server responds + with a SERVFAIL response, which is the reverse of normal stub + resolver behavior. + +.. option:: -t type + + This option specifies the query type. The ``type`` argument can be any recognized query type: + CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc. + + When no query type is specified, :program:`host` automatically selects an + appropriate query type. By default, it looks for A, AAAA, MX, and HTTPS + records. If the :option:`-C` option is given, queries are made for SOA + records. If ``name`` is a dotted-decimal IPv4 address or + colon-delimited IPv6 address, :program:`host` queries for PTR records. + + If a query type of IXFR is chosen, the starting serial number can be + specified by appending an equals sign (=), followed by the starting serial + number, e.g., :option:`-t IXFR=12345678 <-t>`. + +.. option:: -T, -U + + This option specifies TCP or UDP. By default, :program:`host` uses UDP when making queries; the + :option:`-T` option makes it use a TCP connection when querying the name + server. TCP is automatically selected for queries that require + it, such as zone transfer (AXFR) requests. Type ``ANY`` queries default + to TCP, but can be forced to use UDP initially via :option:`-U`. + +.. option:: -m flag + + This option sets memory usage debugging: the flag can be ``record``, ``usage``, or + ``trace``. The :option:`-m` option can be specified more than once to set + multiple flags. + +.. option:: -v + + This option sets verbose output, and is equivalent to the :option:`-d` debug option. Verbose output + can also be enabled by setting the ``debug`` option in + ``/etc/resolv.conf``. + +.. option:: -V + + This option prints the version number and exits. + +.. option:: -w + + This option sets "wait forever": the query timeout is set to the maximum possible. See + also the :option:`-W` option. + +.. option:: -W wait + + This options sets the length of the wait timeout, indicating that :iscman:`named` should wait for up to ``wait`` seconds for a reply. If ``wait`` is + less than 1, the wait interval is set to 1 second. + + By default, :program:`host` waits for 5 seconds for UDP responses and 10 + seconds for TCP connections. These defaults can be overridden by the + ``timeout`` option in ``/etc/resolv.conf``. + + See also the :option:`-w` option. + +IDN Support +~~~~~~~~~~~ + +If :program:`host` has been built with IDN (internationalized domain name) +support, it can accept and display non-ASCII domain names. :program:`host` +appropriately converts character encoding of a domain name before sending +a request to a DNS server or displaying a reply from the server. +To turn off IDN support, define the ``IDN_DISABLE`` +environment variable. IDN support is disabled if the variable is set +when :program:`host` runs. + +Files +~~~~~ + +``/etc/resolv.conf`` + +See Also +~~~~~~~~ + +:iscman:`dig(1) `, :iscman:`named(8) `. diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c new file mode 100644 index 0000000..5687f96 --- /dev/null +++ b/bin/dig/nslookup.c @@ -0,0 +1,979 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dighost.h" +#include "readline.h" + +static char cmdlinebuf[COMMSIZE]; +static char *cmdline = NULL; + +static bool short_form = true, tcpmode = false, tcpmode_set = false, + identify = false, stats = true, comments = true, + section_question = true, section_answer = true, + section_authority = true, section_additional = true, recurse = true, + aaonly = false, nofail = true, default_lookups = true, + a_noanswer = false; + +static bool interactive; + +static bool in_use = false; +static char defclass[MXRD] = "IN"; +static char deftype[MXRD] = "A"; +static int query_error = 1, print_error = 0; + +static char domainopt[DNS_NAME_MAXTEXT]; + +static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL", + "NXDOMAIN", "NOTIMP", "REFUSED", + "YXDOMAIN", "YXRRSET", "NXRRSET", + "NOTAUTH", "NOTZONE", "RESERVED11", + "RESERVED12", "RESERVED13", "RESERVED14", + "RESERVED15", "BADVERS" }; + +static const char *rtypetext[] = { + "rtype_0 = ", /* 0 */ + "internet address = ", /* 1 */ + "nameserver = ", /* 2 */ + "md = ", /* 3 */ + "mf = ", /* 4 */ + "canonical name = ", /* 5 */ + "soa = ", /* 6 */ + "mb = ", /* 7 */ + "mg = ", /* 8 */ + "mr = ", /* 9 */ + "rtype_10 = ", /* 10 */ + "protocol = ", /* 11 */ + "name = ", /* 12 */ + "hinfo = ", /* 13 */ + "minfo = ", /* 14 */ + "mail exchanger = ", /* 15 */ + "text = ", /* 16 */ + "rp = ", /* 17 */ + "afsdb = ", /* 18 */ + "x25 address = ", /* 19 */ + "isdn address = ", /* 20 */ + "rt = ", /* 21 */ + "nsap = ", /* 22 */ + "nsap_ptr = ", /* 23 */ + "signature = ", /* 24 */ + "key = ", /* 25 */ + "px = ", /* 26 */ + "gpos = ", /* 27 */ + "has AAAA address ", /* 28 */ + "loc = ", /* 29 */ + "next = ", /* 30 */ + "rtype_31 = ", /* 31 */ + "rtype_32 = ", /* 32 */ + "service = ", /* 33 */ + "rtype_34 = ", /* 34 */ + "naptr = ", /* 35 */ + "kx = ", /* 36 */ + "cert = ", /* 37 */ + "v6 address = ", /* 38 */ + "dname = ", /* 39 */ + "rtype_40 = ", /* 40 */ + "optional = " /* 41 */ +}; + +#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0])) + +static char * +rcode_totext(dns_rcode_t rcode) { + static char buf[sizeof("?65535")]; + union { + const char *consttext; + char *deconsttext; + } totext; + + if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) { + snprintf(buf, sizeof(buf), "?%u", rcode); + totext.deconsttext = buf; + } else { + totext.consttext = rcodetext[rcode]; + } + return totext.deconsttext; +} + +static void +printsoa(dns_rdata_t *rdata) { + dns_rdata_soa_t soa; + isc_result_t result; + char namebuf[DNS_NAME_FORMATSIZE]; + + result = dns_rdata_tostruct(rdata, &soa, NULL); + check_result(result, "dns_rdata_tostruct"); + + dns_name_format(&soa.origin, namebuf, sizeof(namebuf)); + printf("\torigin = %s\n", namebuf); + dns_name_format(&soa.contact, namebuf, sizeof(namebuf)); + printf("\tmail addr = %s\n", namebuf); + printf("\tserial = %u\n", soa.serial); + printf("\trefresh = %u\n", soa.refresh); + printf("\tretry = %u\n", soa.retry); + printf("\texpire = %u\n", soa.expire); + printf("\tminimum = %u\n", soa.minimum); + dns_rdata_freestruct(&soa); +} + +static void +printaddr(dns_rdata_t *rdata) { + isc_result_t result; + char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + isc_buffer_t b; + + isc_buffer_init(&b, text, sizeof(text)); + result = dns_rdata_totext(rdata, NULL, &b); + check_result(result, "dns_rdata_totext"); + printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b), + (char *)isc_buffer_base(&b)); +} + +static void +printrdata(dns_rdata_t *rdata) { + isc_result_t result; + isc_buffer_t *b = NULL; + unsigned int size = 1024; + bool done = false; + + if (rdata->type < N_KNOWN_RRTYPES) { + printf("%s", rtypetext[rdata->type]); + } else { + printf("rdata_%d = ", rdata->type); + } + + while (!done) { + isc_buffer_allocate(mctx, &b, size); + result = dns_rdata_totext(rdata, NULL, b); + if (result == ISC_R_SUCCESS) { + printf("%.*s\n", (int)isc_buffer_usedlength(b), + (char *)isc_buffer_base(b)); + done = true; + } else if (result != ISC_R_NOSPACE) { + check_result(result, "dns_rdata_totext"); + } + isc_buffer_free(&b); + INSIST(size <= (UINT_MAX / 2)); + size *= 2; + } +} + +static isc_result_t +printsection(dig_query_t *query, dns_message_t *msg, bool headers, + dns_section_t section) { + isc_result_t result, loopresult; + dns_name_t *name; + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + char namebuf[DNS_NAME_FORMATSIZE]; + + UNUSED(query); + UNUSED(headers); + + debug("printsection()"); + + result = dns_message_firstname(msg, section); + if (result == ISC_R_NOMORE) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + return result; + } + for (;;) { + name = NULL; + dns_message_currentname(msg, section, &name); + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + loopresult = dns_rdataset_first(rdataset); + while (loopresult == ISC_R_SUCCESS) { + dns_rdataset_current(rdataset, &rdata); + switch (rdata.type) { + case dns_rdatatype_a: + case dns_rdatatype_aaaa: + if (section != DNS_SECTION_ANSWER) { + goto def_short_section; + } + dns_name_format(name, namebuf, + sizeof(namebuf)); + printf("Name:\t%s\n", namebuf); + printaddr(&rdata); + break; + case dns_rdatatype_soa: + dns_name_format(name, namebuf, + sizeof(namebuf)); + printf("%s\n", namebuf); + printsoa(&rdata); + break; + default: + def_short_section: + dns_name_format(name, namebuf, + sizeof(namebuf)); + printf("%s\t", namebuf); + printrdata(&rdata); + break; + } + dns_rdata_reset(&rdata); + loopresult = dns_rdataset_next(rdataset); + } + } + result = dns_message_nextname(msg, section); + if (result == ISC_R_NOMORE) { + break; + } else if (result != ISC_R_SUCCESS) { + return result; + } + } + return ISC_R_SUCCESS; +} + +static isc_result_t +detailsection(dig_query_t *query, dns_message_t *msg, bool headers, + dns_section_t section) { + isc_result_t result, loopresult; + dns_name_t *name; + dns_rdataset_t *rdataset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + char namebuf[DNS_NAME_FORMATSIZE]; + + UNUSED(query); + + debug("detailsection()"); + + if (headers) { + switch (section) { + case DNS_SECTION_QUESTION: + puts(" QUESTIONS:"); + break; + case DNS_SECTION_ANSWER: + puts(" ANSWERS:"); + break; + case DNS_SECTION_AUTHORITY: + puts(" AUTHORITY RECORDS:"); + break; + case DNS_SECTION_ADDITIONAL: + puts(" ADDITIONAL RECORDS:"); + break; + } + } + + result = dns_message_firstname(msg, section); + if (result == ISC_R_NOMORE) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + return result; + } + for (;;) { + name = NULL; + dns_message_currentname(msg, section, &name); + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) + { + if (section == DNS_SECTION_QUESTION) { + dns_name_format(name, namebuf, sizeof(namebuf)); + printf("\t%s, ", namebuf); + dns_rdatatype_format(rdataset->type, namebuf, + sizeof(namebuf)); + printf("type = %s, ", namebuf); + dns_rdataclass_format(rdataset->rdclass, + namebuf, sizeof(namebuf)); + printf("class = %s\n", namebuf); + } + loopresult = dns_rdataset_first(rdataset); + while (loopresult == ISC_R_SUCCESS) { + dns_rdataset_current(rdataset, &rdata); + + dns_name_format(name, namebuf, sizeof(namebuf)); + printf(" -> %s\n", namebuf); + + switch (rdata.type) { + case dns_rdatatype_soa: + printsoa(&rdata); + break; + default: + printf("\t"); + printrdata(&rdata); + } + dns_rdata_reset(&rdata); + printf("\tttl = %u\n", rdataset->ttl); + loopresult = dns_rdataset_next(rdataset); + } + } + result = dns_message_nextname(msg, section); + if (result == ISC_R_NOMORE) { + break; + } else if (result != ISC_R_SUCCESS) { + return result; + } + } + return ISC_R_SUCCESS; +} + +static void +received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) { + UNUSED(bytes); + UNUSED(from); + UNUSED(query); +} + +static void +trying(char *frm, dig_lookup_t *lookup) { + UNUSED(frm); + UNUSED(lookup); +} + +static void +chase_cnamechain(dns_message_t *msg, dns_name_t *qname) { + isc_result_t result; + dns_rdataset_t *rdataset; + dns_rdata_cname_t cname; + dns_rdata_t rdata = DNS_RDATA_INIT; + unsigned int i = msg->counts[DNS_SECTION_ANSWER]; + + while (i-- > 0) { + rdataset = NULL; + result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname, + dns_rdatatype_cname, 0, NULL, + &rdataset); + if (result != ISC_R_SUCCESS) { + return; + } + result = dns_rdataset_first(rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdata_reset(&rdata); + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &cname, NULL); + check_result(result, "dns_rdata_tostruct"); + dns_name_copy(&cname.cname, qname); + dns_rdata_freestruct(&cname); + } +} + +static isc_result_t +printmessage(dig_query_t *query, const isc_buffer_t *msgbuf, dns_message_t *msg, + bool headers) { + UNUSED(msgbuf); + + /* I've we've gotten this far, we've reached a server. */ + query_error = 0; + + debug("printmessage()"); + + if (!default_lookups || query->lookup->rdtype == dns_rdatatype_a) { + char servtext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(&query->sockaddr, servtext, + sizeof(servtext)); + printf("Server:\t\t%s\n", query->userarg); + printf("Address:\t%s\n", servtext); + + puts(""); + } + + if (!short_form) { + puts("------------"); + /* detailheader(query, msg);*/ + detailsection(query, msg, true, DNS_SECTION_QUESTION); + detailsection(query, msg, true, DNS_SECTION_ANSWER); + detailsection(query, msg, true, DNS_SECTION_AUTHORITY); + detailsection(query, msg, true, DNS_SECTION_ADDITIONAL); + puts("------------"); + } + + if (msg->rcode != 0) { + char nametext[DNS_NAME_FORMATSIZE]; + dns_name_format(query->lookup->name, nametext, + sizeof(nametext)); + printf("** server can't find %s: %s\n", nametext, + rcode_totext(msg->rcode)); + debug("returning with rcode == 0"); + + /* the lookup failed */ + print_error |= 1; + return ISC_R_SUCCESS; + } + + if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) { + char namestr[DNS_NAME_FORMATSIZE]; + dig_lookup_t *lookup; + dns_fixedname_t fixed; + dns_name_t *name; + + /* Add AAAA lookup. */ + name = dns_fixedname_initname(&fixed); + dns_name_copy(query->lookup->name, name); + chase_cnamechain(msg, name); + dns_name_format(name, namestr, sizeof(namestr)); + lookup = clone_lookup(query->lookup, false); + if (lookup != NULL) { + strlcpy(lookup->textname, namestr, + sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_aaaa; + lookup->rdtypeset = true; + lookup->origin = NULL; + lookup->retries = tries; + ISC_LIST_APPEND(lookup_list, lookup, link); + } + } + + if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0 && + (!default_lookups || query->lookup->rdtype == dns_rdatatype_a)) + { + puts("Non-authoritative answer:"); + } + if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { + printsection(query, msg, headers, DNS_SECTION_ANSWER); + } else { + if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) + { + a_noanswer = true; + } else if (!default_lookups || + (query->lookup->rdtype == dns_rdatatype_aaaa && + a_noanswer)) + { + printf("*** Can't find %s: No answer\n", + query->lookup->textname); + } + } + + if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && + (query->lookup->rdtype != dns_rdatatype_a) && + (query->lookup->rdtype != dns_rdatatype_aaaa)) + { + puts("\nAuthoritative answers can be found from:"); + printsection(query, msg, headers, DNS_SECTION_AUTHORITY); + printsection(query, msg, headers, DNS_SECTION_ADDITIONAL); + } + return ISC_R_SUCCESS; +} + +static void +show_settings(bool full, bool serv_only) { + dig_server_t *srv; + isc_sockaddr_t sockaddr; + dig_searchlist_t *listent; + isc_result_t result; + + srv = ISC_LIST_HEAD(server_list); + + while (srv != NULL) { + char sockstr[ISC_SOCKADDR_FORMATSIZE]; + + result = get_address(srv->servername, port, &sockaddr); + check_result(result, "get_address"); + + isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr)); + printf("Default server: %s\nAddress: %s\n", srv->userarg, + sockstr); + if (!full) { + return; + } + srv = ISC_LIST_NEXT(srv, link); + } + if (serv_only) { + return; + } + printf("\nSet options:\n"); + printf(" %s\t\t\t%s\t\t%s\n", tcpmode ? "vc" : "novc", + short_form ? "nodebug" : "debug", debugging ? "d2" : "nod2"); + printf(" %s\t\t%s\n", usesearch ? "search" : "nosearch", + recurse ? "recurse" : "norecurse"); + printf(" timeout = %u\t\tretry = %d\tport = %u\tndots = %d\n", timeout, + tries, port, ndots); + printf(" querytype = %-8s\tclass = %s\n", deftype, defclass); + printf(" srchlist = "); + for (listent = ISC_LIST_HEAD(search_list); listent != NULL; + listent = ISC_LIST_NEXT(listent, link)) + { + printf("%s", listent->origin); + if (ISC_LIST_NEXT(listent, link) != NULL) { + printf("/"); + } + } + printf("\n"); +} + +static bool +testtype(char *typetext) { + isc_result_t result; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + + tr.base = typetext; + tr.length = strlen(typetext); + result = dns_rdatatype_fromtext(&rdtype, &tr); + if (result == ISC_R_SUCCESS) { + return true; + } else { + printf("unknown query type: %s\n", typetext); + return false; + } +} + +static bool +testclass(char *typetext) { + isc_result_t result; + isc_textregion_t tr; + dns_rdataclass_t rdclass; + + tr.base = typetext; + tr.length = strlen(typetext); + result = dns_rdataclass_fromtext(&rdclass, &tr); + if (result == ISC_R_SUCCESS) { + return true; + } else { + printf("unknown query class: %s\n", typetext); + return false; + } +} + +static void +set_port(const char *value) { + uint32_t n; + isc_result_t result = parse_uint(&n, value, 65535, "port"); + if (result == ISC_R_SUCCESS) { + port = (uint16_t)n; + port_set = true; + } +} + +static void +set_timeout(const char *value) { + uint32_t n; + isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout"); + if (result == ISC_R_SUCCESS) { + timeout = n; + } +} + +static void +set_tries(const char *value) { + uint32_t n; + isc_result_t result = parse_uint(&n, value, INT_MAX, "tries"); + if (result == ISC_R_SUCCESS) { + tries = n; + } +} + +static void +set_ndots(const char *value) { + uint32_t n; + isc_result_t result = parse_uint(&n, value, 128, "ndots"); + if (result == ISC_R_SUCCESS) { + ndots = n; + } +} + +static void +setoption(char *opt) { + size_t l = strlen(opt); + +#define CHECKOPT(A, N) \ + ((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0)) + + if (CHECKOPT("all", 3)) { + show_settings(true, false); + } else if (strncasecmp(opt, "class=", 6) == 0) { + if (testclass(&opt[6])) { + strlcpy(defclass, &opt[6], sizeof(defclass)); + } + } else if (strncasecmp(opt, "cl=", 3) == 0) { + if (testclass(&opt[3])) { + strlcpy(defclass, &opt[3], sizeof(defclass)); + } + } else if (strncasecmp(opt, "type=", 5) == 0) { + if (testtype(&opt[5])) { + strlcpy(deftype, &opt[5], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "ty=", 3) == 0) { + if (testtype(&opt[3])) { + strlcpy(deftype, &opt[3], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "querytype=", 10) == 0) { + if (testtype(&opt[10])) { + strlcpy(deftype, &opt[10], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "query=", 6) == 0) { + if (testtype(&opt[6])) { + strlcpy(deftype, &opt[6], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "qu=", 3) == 0) { + if (testtype(&opt[3])) { + strlcpy(deftype, &opt[3], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "q=", 2) == 0) { + if (testtype(&opt[2])) { + strlcpy(deftype, &opt[2], sizeof(deftype)); + default_lookups = false; + } + } else if (strncasecmp(opt, "domain=", 7) == 0) { + strlcpy(domainopt, &opt[7], sizeof(domainopt)); + set_search_domain(domainopt); + usesearch = true; + } else if (strncasecmp(opt, "do=", 3) == 0) { + strlcpy(domainopt, &opt[3], sizeof(domainopt)); + set_search_domain(domainopt); + usesearch = true; + } else if (strncasecmp(opt, "port=", 5) == 0) { + set_port(&opt[5]); + } else if (strncasecmp(opt, "po=", 3) == 0) { + set_port(&opt[3]); + } else if (strncasecmp(opt, "timeout=", 8) == 0) { + set_timeout(&opt[8]); + } else if (strncasecmp(opt, "t=", 2) == 0) { + set_timeout(&opt[2]); + } else if (CHECKOPT("recurse", 3)) { + recurse = true; + } else if (CHECKOPT("norecurse", 5)) { + recurse = false; + } else if (strncasecmp(opt, "retry=", 6) == 0) { + set_tries(&opt[6]); + } else if (strncasecmp(opt, "ret=", 4) == 0) { + set_tries(&opt[4]); + } else if (CHECKOPT("defname", 3)) { + usesearch = true; + } else if (CHECKOPT("nodefname", 5)) { + usesearch = false; + } else if (CHECKOPT("vc", 2)) { + tcpmode = true; + tcpmode_set = true; + } else if (CHECKOPT("novc", 4)) { + tcpmode = false; + tcpmode_set = true; + } else if (CHECKOPT("debug", 3)) { + short_form = false; + showsearch = true; + } else if (CHECKOPT("nodebug", 5)) { + short_form = true; + showsearch = false; + } else if (CHECKOPT("d2", 2)) { + debugging = true; + } else if (CHECKOPT("nod2", 4)) { + debugging = false; + } else if (CHECKOPT("search", 3)) { + usesearch = true; + } else if (CHECKOPT("nosearch", 5)) { + usesearch = false; + } else if (CHECKOPT("sil", 3)) { + /* deprecation_msg = false; */ + } else if (CHECKOPT("fail", 3)) { + nofail = false; + } else if (CHECKOPT("nofail", 5)) { + nofail = true; + } else if (strncasecmp(opt, "ndots=", 6) == 0) { + set_ndots(&opt[6]); + } else { + printf("*** Invalid option: %s\n", opt); + } +} + +static void +addlookup(char *opt) { + dig_lookup_t *lookup; + isc_result_t result; + isc_textregion_t tr; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + char store[MXNAME]; + + debug("addlookup()"); + + a_noanswer = false; + + tr.base = deftype; + tr.length = strlen(deftype); + result = dns_rdatatype_fromtext(&rdtype, &tr); + if (result != ISC_R_SUCCESS) { + printf("unknown query type: %s\n", deftype); + rdclass = dns_rdatatype_a; + } + tr.base = defclass; + tr.length = strlen(defclass); + result = dns_rdataclass_fromtext(&rdclass, &tr); + if (result != ISC_R_SUCCESS) { + printf("unknown query class: %s\n", defclass); + rdclass = dns_rdataclass_in; + } + lookup = make_empty_lookup(); + if (get_reverse(store, sizeof(store), opt, true) == ISC_R_SUCCESS) { + strlcpy(lookup->textname, store, sizeof(lookup->textname)); + lookup->rdtype = dns_rdatatype_ptr; + lookup->rdtypeset = true; + } else { + strlcpy(lookup->textname, opt, sizeof(lookup->textname)); + lookup->rdtype = rdtype; + lookup->rdtypeset = true; + } + lookup->rdclass = rdclass; + lookup->rdclassset = true; + lookup->trace = false; + lookup->trace_root = lookup->trace; + lookup->ns_search_only = false; + lookup->identify = identify; + lookup->recurse = recurse; + lookup->aaonly = aaonly; + lookup->retries = tries; + lookup->setqid = false; + lookup->qid = 0; + lookup->comments = comments; + if (lookup->rdtype == dns_rdatatype_any && !tcpmode_set) { + lookup->tcp_mode = true; + } else { + lookup->tcp_mode = tcpmode; + } + lookup->stats = stats; + lookup->section_question = section_question; + lookup->section_answer = section_answer; + lookup->section_authority = section_authority; + lookup->section_additional = section_additional; + lookup->new_search = true; + lookup->besteffort = false; + if (nofail) { + lookup->servfail_stops = false; + } + ISC_LIST_INIT(lookup->q); + ISC_LINK_INIT(lookup, link); + ISC_LIST_APPEND(lookup_list, lookup, link); + lookup->origin = NULL; + ISC_LIST_INIT(lookup->my_server_list); + debug("looking up %s", lookup->textname); +} + +static void +do_next_command(char *input) { + char *ptr, *arg, *last; + + if ((ptr = strtok_r(input, " \t\r\n", &last)) == NULL) { + return; + } + arg = strtok_r(NULL, " \t\r\n", &last); + if ((strcasecmp(ptr, "set") == 0) && (arg != NULL)) { + setoption(arg); + } else if ((strcasecmp(ptr, "server") == 0) || + (strcasecmp(ptr, "lserver") == 0)) + { + set_nameserver(arg); + check_ra = false; + show_settings(true, true); + } else if (strcasecmp(ptr, "exit") == 0) { + in_use = false; + } else if (strcasecmp(ptr, "help") == 0 || strcasecmp(ptr, "?") == 0) { + printf("The '%s' command is not yet implemented.\n", ptr); + } else if (strcasecmp(ptr, "finger") == 0 || + strcasecmp(ptr, "root") == 0 || strcasecmp(ptr, "ls") == 0 || + strcasecmp(ptr, "view") == 0) + { + printf("The '%s' command is not implemented.\n", ptr); + } else { + addlookup(ptr); + } +} + +static void +readline_next_command(void *arg) { + char *ptr = NULL; + + UNUSED(arg); + + isc_loopmgr_blocking(loopmgr); + ptr = readline("> "); + isc_loopmgr_nonblocking(loopmgr); + if (ptr == NULL) { + return; + } + + if (*ptr != 0) { + add_history(ptr); + strlcpy(cmdlinebuf, ptr, COMMSIZE); + cmdline = cmdlinebuf; + } + free(ptr); +} + +static void +fgets_next_command(void *arg) { + UNUSED(arg); + + cmdline = fgets(cmdlinebuf, COMMSIZE, stdin); +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " nslookup [-opt ...] # interactive mode " + "using default server\n"); + fprintf(stderr, " nslookup [-opt ...] - server # interactive mode " + "using 'server'\n"); + fprintf(stderr, " nslookup [-opt ...] host # just look up " + "'host' using default server\n"); + fprintf(stderr, " nslookup [-opt ...] host server # just look up " + "'host' using 'server'\n"); + exit(EXIT_FAILURE); +} + +static void +parse_args(int argc, char **argv) { + bool have_lookup = false; + + usesearch = true; + for (argc--, argv++; argc > 0 && argv[0] != NULL; argc--, argv++) { + debug("main parsing %s", argv[0]); + if (argv[0][0] == '-') { + if (strncasecmp(argv[0], "-ver", 4) == 0) { + printf("nslookup %s\n", PACKAGE_VERSION); + exit(EXIT_SUCCESS); + } else if (argv[0][1] != 0) { + setoption(&argv[0][1]); + } else { + have_lookup = true; + } + } else { + if (!have_lookup) { + have_lookup = true; + in_use = true; + addlookup(argv[0]); + } else { + if (argv[1] != NULL) { + usage(); + } + set_nameserver(argv[0]); + check_ra = false; + } + } + } +} + +static void +start_next_command(void); + +static void +process_next_command(void *arg ISC_ATTR_UNUSED) { + isc_loop_t *loop = isc_loop_main(loopmgr); + if (cmdline == NULL) { + in_use = false; + } else { + do_next_command(cmdline); + if (ISC_LIST_HEAD(lookup_list) != NULL) { + isc_async_run(loop, run_loop, NULL); + return; + } + } + + start_next_command(); +} + +static void +start_next_command(void) { + isc_loop_t *loop = isc_loop_main(loopmgr); + if (!in_use) { + isc_loopmgr_shutdown(loopmgr); + return; + } + + cmdline = NULL; + + isc_loopmgr_pause(loopmgr); + if (interactive) { + isc_work_enqueue(loop, readline_next_command, + process_next_command, loop); + } else { + isc_work_enqueue(loop, fgets_next_command, process_next_command, + loop); + } + isc_loopmgr_resume(loopmgr); +} + +static void +read_loop(void *arg) { + UNUSED(arg); + + start_next_command(); +} + +int +main(int argc, char **argv) { + interactive = isatty(0); + + ISC_LIST_INIT(lookup_list); + ISC_LIST_INIT(server_list); + ISC_LIST_INIT(search_list); + + check_ra = true; + + /* setup dighost callbacks */ + dighost_printmessage = printmessage; + dighost_received = received; + dighost_trying = trying; + dighost_shutdown = start_next_command; + + setup_libs(); + progname = argv[0]; + + setup_system(false, false); + parse_args(argc, argv); + if (keyfile[0] != 0) { + setup_file_key(); + } else if (keysecret[0] != 0) { + setup_text_key(); + } + if (domainopt[0] != '\0') { + set_search_domain(domainopt); + } + if (in_use) { + isc_loopmgr_setup(loopmgr, run_loop, NULL); + } else { + isc_loopmgr_setup(loopmgr, read_loop, NULL); + } + in_use = !in_use; + + isc_loopmgr_run(loopmgr); + + puts(""); + debug("done, and starting to shut down"); + cancel_all(); + destroy_libs(); + + return query_error | print_error; +} diff --git a/bin/dig/nslookup.rst b/bin/dig/nslookup.rst new file mode 100644 index 0000000..2b92aa7 --- /dev/null +++ b/bin/dig/nslookup.rst @@ -0,0 +1,208 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: nslookup +.. program:: nslookup +.. _man_nslookup: + +nslookup - query Internet name servers interactively +---------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`nslookup` [-option] [name | -] [server] + +Description +~~~~~~~~~~~ + +:program:`nslookup` is a program to query Internet domain name servers. +:program:`nslookup` has two modes: interactive and non-interactive. Interactive +mode allows the user to query name servers for information about various +hosts and domains or to print a list of hosts in a domain. +Non-interactive mode prints just the name and requested +information for a host or domain. + +Arguments +~~~~~~~~~ + +Interactive mode is entered in the following cases: + +a. when no arguments are given (the default name server is used); + +b. when the first argument is a hyphen (-) and the second argument is + the host name or Internet address of a name server. + +Non-interactive mode is used when the name or Internet address of the +host to be looked up is given as the first argument. The optional second +argument specifies the host name or address of a name server. + +Options can also be specified on the command line if they precede the +arguments and are prefixed with a hyphen. For example, to change the +default query type to host information, with an initial timeout of 10 +seconds, type: + +:: + + nslookup -query=hinfo -timeout=10 + +The ``-version`` option causes :program:`nslookup` to print the version number +and immediately exit. + +Interactive Commands +~~~~~~~~~~~~~~~~~~~~ + +``host [server]`` + This command looks up information for :iscman:`host` using the current default server or + using ``server``, if specified. If :iscman:`host` is an Internet address and the + query type is A or PTR, the name of the host is returned. If :iscman:`host` is + a name and does not have a trailing period (``.``), the search list is used + to qualify the name. + + To look up a host not in the current domain, append a period to the + name. + +``server domain`` | ``lserver domain`` + These commands change the default server to ``domain``; ``lserver`` uses the initial + server to look up information about ``domain``, while ``server`` uses the + current default server. If an authoritative answer cannot be found, + the names of servers that might have the answer are returned. + +``root`` + This command is not implemented. + +``finger`` + This command is not implemented. + +``ls`` + This command is not implemented. + +``view`` + This command is not implemented. + +``help`` + This command is not implemented. + +``?`` + This command is not implemented. + +``exit`` + This command exits the program. + +``set keyword[=value]`` + This command is used to change state information that affects the + lookups. Valid keywords are: + + ``all`` + This keyword prints the current values of the frequently used options to + ``set``. Information about the current default server and host is + also printed. + + ``class=value`` + This keyword changes the query class to one of: + + ``IN`` + the Internet class + + ``CH`` + the Chaos class + + ``HS`` + the Hesiod class + + ``ANY`` + wildcard + + The class specifies the protocol group of the information. The default + is ``IN``; the abbreviation for this keyword is ``cl``. + + ``nodebug`` + This keyword turns on or off the display of the full response packet, and any + intermediate response packets, when searching. The default for this keyword is + ``nodebug``; the abbreviation for this keyword is ``[no]deb``. + + ``nod2`` + This keyword turns debugging mode on or off. This displays more about what + nslookup is doing. The default is ``nod2``. + + ``domain=name`` + This keyword sets the search list to ``name``. + + ``nosearch`` + If the lookup request contains at least one period, but does not end + with a trailing period, this keyword appends the domain names in the domain + search list to the request until an answer is received. The default is ``search``. + + ``port=value`` + This keyword changes the default TCP/UDP name server port to ``value`` from + its default, port 53. The abbreviation for this keyword is ``po``. + + ``querytype=value`` | ``type=value`` + This keyword changes the type of the information query to ``value``. The + defaults are A and then AAAA; the abbreviations for these keywords are + ``q`` and ``ty``. + + Please note that it is only possible to specify one query type. Only the default + behavior looks up both when an alternative is not specified. + + ``norecurse`` + This keyword tells the name server to query other servers if it does not have + the information. The default is ``recurse``; the abbreviation for this + keyword is ``[no]rec``. + + ``ndots=number`` + This keyword sets the number of dots (label separators) in a domain that + disables searching. Absolute names always stop searching. + + ``retry=number`` + This keyword sets the number of retries to ``number``. + + ``timeout=number`` + This keyword changes the initial timeout interval to wait for a reply to + ``number``, in seconds. + + ``novc`` + This keyword indicates that a virtual circuit should always be used when sending requests to the server. + ``novc`` is the default. + + ``nofail`` + This keyword tries the next nameserver if a nameserver responds with SERVFAIL or + a referral (nofail), or terminates the query (fail) on such a response. The + default is ``nofail``. + +Return Values +~~~~~~~~~~~~~ + +:program:`nslookup` returns with an exit status of 1 if any query failed, and 0 +otherwise. + +IDN Support +~~~~~~~~~~~ + +If :program:`nslookup` has been built with IDN (internationalized domain name) +support, it can accept and display non-ASCII domain names. :program:`nslookup` +appropriately converts character encoding of a domain name before sending +a request to a DNS server or displaying a reply from the server. +To turn off IDN support, define the ``IDN_DISABLE`` +environment variable. IDN support is disabled if the variable is set +when :program:`nslookup` runs, or when the standard output is not a tty. + +Files +~~~~~ + +``/etc/resolv.conf`` + +See Also +~~~~~~~~ + +:iscman:`dig(1) `, :iscman:`host(1) `, :iscman:`named(8) `. diff --git a/bin/dig/readline.h b/bin/dig/readline.h new file mode 100644 index 0000000..5341994 --- /dev/null +++ b/bin/dig/readline.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/* + * A little wrapper around readline(), add_history() and free() to make using + * the readline code simpler. + */ + +#if defined(HAVE_READLINE_LIBEDIT) +#include +#elif defined(HAVE_READLINE_EDITLINE) +#include +#elif defined(HAVE_READLINE_READLINE) +/* Prevent deprecated functions being declared. */ +#define _FUNCTION_DEF 1 +/* Ensure rl_message() gets prototype. */ +#define USE_VARARGS 1 +#define PREFER_STDARG 1 +#include +#include +#endif + +#if !defined(HAVE_READLINE_LIBEDIT) && !defined(HAVE_READLINE_EDITLINE) && \ + !defined(HAVE_READLINE_READLINE) + +#include +#include + +#define RL_MAXCMD (128 * 1024) + +static inline char * +readline(const char *prompt) { + char *line, *buf = malloc(RL_MAXCMD); + fprintf(stdout, "%s", prompt); + fflush(stdout); + line = fgets(buf, RL_MAXCMD, stdin); + if (line == NULL) { + free(buf); + return NULL; + } + return buf; +} + +#define add_history(line) + +#endif diff --git a/bin/dnssec/Makefile.am b/bin/dnssec/Makefile.am new file mode 100644 index 0000000..0268fc1 --- /dev/null +++ b/bin/dnssec/Makefile.am @@ -0,0 +1,50 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(LIBDNS_CFLAGS) + +AM_CPPFLAGS += \ + -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" + +noinst_LTLIBRARIES = libdnssectool.la + +LDADD += \ + libdnssectool.la \ + $(LIBISC_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(LIBDNS_LIBS) \ + $(OPENSSL_LIBS) + +bin_PROGRAMS = \ + dnssec-cds \ + dnssec-dsfromkey \ + dnssec-importkey \ + dnssec-keyfromlabel \ + dnssec-keygen \ + dnssec-ksr \ + dnssec-revoke \ + dnssec-settime \ + dnssec-signzone \ + dnssec-verify + +libdnssectool_la_SOURCES = \ + dnssectool.h \ + dnssectool.c + +dnssec_keygen_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dnssec_keygen_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +dnssec_signzone_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dnssec_signzone_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in new file mode 100644 index 0000000..37dcf29 --- /dev/null +++ b/bin/dnssec/Makefile.in @@ -0,0 +1,1030 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +bin_PROGRAMS = dnssec-cds$(EXEEXT) dnssec-dsfromkey$(EXEEXT) \ + dnssec-importkey$(EXEEXT) dnssec-keyfromlabel$(EXEEXT) \ + dnssec-keygen$(EXEEXT) dnssec-ksr$(EXEEXT) \ + dnssec-revoke$(EXEEXT) dnssec-settime$(EXEEXT) \ + dnssec-signzone$(EXEEXT) dnssec-verify$(EXEEXT) +subdir = bin/dnssec +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdnssectool_la_LIBADD = +am_libdnssectool_la_OBJECTS = dnssectool.lo +libdnssectool_la_OBJECTS = $(am_libdnssectool_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +dnssec_cds_SOURCES = dnssec-cds.c +dnssec_cds_OBJECTS = dnssec-cds.$(OBJEXT) +dnssec_cds_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +dnssec_cds_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_dsfromkey_SOURCES = dnssec-dsfromkey.c +dnssec_dsfromkey_OBJECTS = dnssec-dsfromkey.$(OBJEXT) +dnssec_dsfromkey_LDADD = $(LDADD) +dnssec_dsfromkey_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_importkey_SOURCES = dnssec-importkey.c +dnssec_importkey_OBJECTS = dnssec-importkey.$(OBJEXT) +dnssec_importkey_LDADD = $(LDADD) +dnssec_importkey_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_keyfromlabel_SOURCES = dnssec-keyfromlabel.c +dnssec_keyfromlabel_OBJECTS = dnssec-keyfromlabel.$(OBJEXT) +dnssec_keyfromlabel_LDADD = $(LDADD) +dnssec_keyfromlabel_DEPENDENCIES = libdnssectool.la \ + $(am__DEPENDENCIES_2) $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) \ + $(am__DEPENDENCIES_1) +dnssec_keygen_SOURCES = dnssec-keygen.c +dnssec_keygen_OBJECTS = dnssec_keygen-dnssec-keygen.$(OBJEXT) +am__DEPENDENCIES_3 = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_keygen_DEPENDENCIES = $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_1) +dnssec_ksr_SOURCES = dnssec-ksr.c +dnssec_ksr_OBJECTS = dnssec-ksr.$(OBJEXT) +dnssec_ksr_LDADD = $(LDADD) +dnssec_ksr_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_revoke_SOURCES = dnssec-revoke.c +dnssec_revoke_OBJECTS = dnssec-revoke.$(OBJEXT) +dnssec_revoke_LDADD = $(LDADD) +dnssec_revoke_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_settime_SOURCES = dnssec-settime.c +dnssec_settime_OBJECTS = dnssec-settime.$(OBJEXT) +dnssec_settime_LDADD = $(LDADD) +dnssec_settime_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +dnssec_signzone_SOURCES = dnssec-signzone.c +dnssec_signzone_OBJECTS = dnssec_signzone-dnssec-signzone.$(OBJEXT) +dnssec_signzone_DEPENDENCIES = $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_1) +dnssec_verify_SOURCES = dnssec-verify.c +dnssec_verify_OBJECTS = dnssec-verify.$(OBJEXT) +dnssec_verify_LDADD = $(LDADD) +dnssec_verify_DEPENDENCIES = libdnssectool.la $(am__DEPENDENCIES_2) \ + $(LIBISCCFG_LIBS) $(LIBDNS_LIBS) $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/dnssec-cds.Po \ + ./$(DEPDIR)/dnssec-dsfromkey.Po \ + ./$(DEPDIR)/dnssec-importkey.Po \ + ./$(DEPDIR)/dnssec-keyfromlabel.Po ./$(DEPDIR)/dnssec-ksr.Po \ + ./$(DEPDIR)/dnssec-revoke.Po ./$(DEPDIR)/dnssec-settime.Po \ + ./$(DEPDIR)/dnssec-verify.Po \ + ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po \ + ./$(DEPDIR)/dnssec_signzone-dnssec-signzone.Po \ + ./$(DEPDIR)/dnssectool.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdnssectool_la_SOURCES) dnssec-cds.c dnssec-dsfromkey.c \ + dnssec-importkey.c dnssec-keyfromlabel.c dnssec-keygen.c \ + dnssec-ksr.c dnssec-revoke.c dnssec-settime.c \ + dnssec-signzone.c dnssec-verify.c +DIST_SOURCES = $(libdnssectool_la_SOURCES) dnssec-cds.c \ + dnssec-dsfromkey.c dnssec-importkey.c dnssec-keyfromlabel.c \ + dnssec-keygen.c dnssec-ksr.c dnssec-revoke.c dnssec-settime.c \ + dnssec-signzone.c dnssec-verify.c +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBISCCFG_CFLAGS) \ + $(LIBDNS_CFLAGS) -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = libdnssectool.la $(LIBISC_LIBS) $(LIBISCCFG_LIBS) \ + $(LIBDNS_LIBS) $(OPENSSL_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = libdnssectool.la +libdnssectool_la_SOURCES = \ + dnssectool.h \ + dnssectool.c + +dnssec_keygen_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dnssec_keygen_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +dnssec_signzone_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dnssec_signzone_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/dnssec/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/dnssec/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libdnssectool.la: $(libdnssectool_la_OBJECTS) $(libdnssectool_la_DEPENDENCIES) $(EXTRA_libdnssectool_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libdnssectool_la_OBJECTS) $(libdnssectool_la_LIBADD) $(LIBS) + +dnssec-cds$(EXEEXT): $(dnssec_cds_OBJECTS) $(dnssec_cds_DEPENDENCIES) $(EXTRA_dnssec_cds_DEPENDENCIES) + @rm -f dnssec-cds$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_cds_OBJECTS) $(dnssec_cds_LDADD) $(LIBS) + +dnssec-dsfromkey$(EXEEXT): $(dnssec_dsfromkey_OBJECTS) $(dnssec_dsfromkey_DEPENDENCIES) $(EXTRA_dnssec_dsfromkey_DEPENDENCIES) + @rm -f dnssec-dsfromkey$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_dsfromkey_OBJECTS) $(dnssec_dsfromkey_LDADD) $(LIBS) + +dnssec-importkey$(EXEEXT): $(dnssec_importkey_OBJECTS) $(dnssec_importkey_DEPENDENCIES) $(EXTRA_dnssec_importkey_DEPENDENCIES) + @rm -f dnssec-importkey$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_importkey_OBJECTS) $(dnssec_importkey_LDADD) $(LIBS) + +dnssec-keyfromlabel$(EXEEXT): $(dnssec_keyfromlabel_OBJECTS) $(dnssec_keyfromlabel_DEPENDENCIES) $(EXTRA_dnssec_keyfromlabel_DEPENDENCIES) + @rm -f dnssec-keyfromlabel$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_keyfromlabel_OBJECTS) $(dnssec_keyfromlabel_LDADD) $(LIBS) + +dnssec-keygen$(EXEEXT): $(dnssec_keygen_OBJECTS) $(dnssec_keygen_DEPENDENCIES) $(EXTRA_dnssec_keygen_DEPENDENCIES) + @rm -f dnssec-keygen$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_keygen_OBJECTS) $(dnssec_keygen_LDADD) $(LIBS) + +dnssec-ksr$(EXEEXT): $(dnssec_ksr_OBJECTS) $(dnssec_ksr_DEPENDENCIES) $(EXTRA_dnssec_ksr_DEPENDENCIES) + @rm -f dnssec-ksr$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_ksr_OBJECTS) $(dnssec_ksr_LDADD) $(LIBS) + +dnssec-revoke$(EXEEXT): $(dnssec_revoke_OBJECTS) $(dnssec_revoke_DEPENDENCIES) $(EXTRA_dnssec_revoke_DEPENDENCIES) + @rm -f dnssec-revoke$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_revoke_OBJECTS) $(dnssec_revoke_LDADD) $(LIBS) + +dnssec-settime$(EXEEXT): $(dnssec_settime_OBJECTS) $(dnssec_settime_DEPENDENCIES) $(EXTRA_dnssec_settime_DEPENDENCIES) + @rm -f dnssec-settime$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_settime_OBJECTS) $(dnssec_settime_LDADD) $(LIBS) + +dnssec-signzone$(EXEEXT): $(dnssec_signzone_OBJECTS) $(dnssec_signzone_DEPENDENCIES) $(EXTRA_dnssec_signzone_DEPENDENCIES) + @rm -f dnssec-signzone$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_signzone_OBJECTS) $(dnssec_signzone_LDADD) $(LIBS) + +dnssec-verify$(EXEEXT): $(dnssec_verify_OBJECTS) $(dnssec_verify_DEPENDENCIES) $(EXTRA_dnssec_verify_DEPENDENCIES) + @rm -f dnssec-verify$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dnssec_verify_OBJECTS) $(dnssec_verify_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-cds.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-dsfromkey.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-importkey.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-keyfromlabel.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-ksr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-revoke.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-settime.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec-verify.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssec_signzone-dnssec-signzone.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnssectool.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +dnssec_keygen-dnssec-keygen.o: dnssec-keygen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_keygen-dnssec-keygen.o -MD -MP -MF $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo -c -o dnssec_keygen-dnssec-keygen.o `test -f 'dnssec-keygen.c' || echo '$(srcdir)/'`dnssec-keygen.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo $(DEPDIR)/dnssec_keygen-dnssec-keygen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-keygen.c' object='dnssec_keygen-dnssec-keygen.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_keygen-dnssec-keygen.o `test -f 'dnssec-keygen.c' || echo '$(srcdir)/'`dnssec-keygen.c + +dnssec_keygen-dnssec-keygen.obj: dnssec-keygen.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_keygen-dnssec-keygen.obj -MD -MP -MF $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo -c -o dnssec_keygen-dnssec-keygen.obj `if test -f 'dnssec-keygen.c'; then $(CYGPATH_W) 'dnssec-keygen.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-keygen.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_keygen-dnssec-keygen.Tpo $(DEPDIR)/dnssec_keygen-dnssec-keygen.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-keygen.c' object='dnssec_keygen-dnssec-keygen.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_keygen_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_keygen-dnssec-keygen.obj `if test -f 'dnssec-keygen.c'; then $(CYGPATH_W) 'dnssec-keygen.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-keygen.c'; fi` + +dnssec_signzone-dnssec-signzone.o: dnssec-signzone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_signzone_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_signzone-dnssec-signzone.o -MD -MP -MF $(DEPDIR)/dnssec_signzone-dnssec-signzone.Tpo -c -o dnssec_signzone-dnssec-signzone.o `test -f 'dnssec-signzone.c' || echo '$(srcdir)/'`dnssec-signzone.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_signzone-dnssec-signzone.Tpo $(DEPDIR)/dnssec_signzone-dnssec-signzone.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-signzone.c' object='dnssec_signzone-dnssec-signzone.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_signzone_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_signzone-dnssec-signzone.o `test -f 'dnssec-signzone.c' || echo '$(srcdir)/'`dnssec-signzone.c + +dnssec_signzone-dnssec-signzone.obj: dnssec-signzone.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_signzone_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dnssec_signzone-dnssec-signzone.obj -MD -MP -MF $(DEPDIR)/dnssec_signzone-dnssec-signzone.Tpo -c -o dnssec_signzone-dnssec-signzone.obj `if test -f 'dnssec-signzone.c'; then $(CYGPATH_W) 'dnssec-signzone.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-signzone.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dnssec_signzone-dnssec-signzone.Tpo $(DEPDIR)/dnssec_signzone-dnssec-signzone.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnssec-signzone.c' object='dnssec_signzone-dnssec-signzone.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dnssec_signzone_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dnssec_signzone-dnssec-signzone.obj `if test -f 'dnssec-signzone.c'; then $(CYGPATH_W) 'dnssec-signzone.c'; else $(CYGPATH_W) '$(srcdir)/dnssec-signzone.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/dnssec-cds.Po + -rm -f ./$(DEPDIR)/dnssec-dsfromkey.Po + -rm -f ./$(DEPDIR)/dnssec-importkey.Po + -rm -f ./$(DEPDIR)/dnssec-keyfromlabel.Po + -rm -f ./$(DEPDIR)/dnssec-ksr.Po + -rm -f ./$(DEPDIR)/dnssec-revoke.Po + -rm -f ./$(DEPDIR)/dnssec-settime.Po + -rm -f ./$(DEPDIR)/dnssec-verify.Po + -rm -f ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po + -rm -f ./$(DEPDIR)/dnssec_signzone-dnssec-signzone.Po + -rm -f ./$(DEPDIR)/dnssectool.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/dnssec-cds.Po + -rm -f ./$(DEPDIR)/dnssec-dsfromkey.Po + -rm -f ./$(DEPDIR)/dnssec-importkey.Po + -rm -f ./$(DEPDIR)/dnssec-keyfromlabel.Po + -rm -f ./$(DEPDIR)/dnssec-ksr.Po + -rm -f ./$(DEPDIR)/dnssec-revoke.Po + -rm -f ./$(DEPDIR)/dnssec-settime.Po + -rm -f ./$(DEPDIR)/dnssec-verify.Po + -rm -f ./$(DEPDIR)/dnssec_keygen-dnssec-keygen.Po + -rm -f ./$(DEPDIR)/dnssec_signzone-dnssec-signzone.Po + -rm -f ./$(DEPDIR)/dnssectool.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-binPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool \ + clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am test-am test-local uninstall uninstall-am \ + uninstall-binPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/dnssec/dnssec-cds.c b/bin/dnssec/dnssec-cds.c new file mode 100644 index 0000000..811bcb2 --- /dev/null +++ b/bin/dnssec/dnssec-cds.c @@ -0,0 +1,1359 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Written by Tony Finch + * at Cambridge University Information Services + */ + +/*! \file */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-cds"; + +/* + * Infrastructure + */ +static isc_log_t *lctx = NULL; +static isc_mem_t *mctx = NULL; + +/* + * The domain we are working on + */ +static const char *namestr = NULL; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static dns_rdataclass_t rdclass = dns_rdataclass_in; + +static const char *startstr = NULL; /* from which we derive notbefore */ +static isc_stdtime_t notbefore = 0; /* restrict sig inception times */ +static dns_rdata_rrsig_t oldestsig; /* for recording inception time */ + +static int nkey; /* number of child zone DNSKEY records */ + +/* + * The validation strategy of this program is top-down. + * + * We start with an implicitly trusted authoritative dsset. + * + * The child DNSKEY RRset is scanned to find out which keys are + * authenticated by DS records, and the result is recorded in a key + * table as described later in this comment. + * + * The key table is used up to three times to verify the signatures on + * the child DNSKEY, CDNSKEY, and CDS RRsets. In this program, only keys + * that have matching DS records are used for validating signatures. + * + * For replay attack protection, signatures are ignored if their inception + * time is before the previously recorded inception time. We use the earliest + * signature so that another run of dnssec-cds with the same records will + * still accept all the signatures. + * + * A key table is an array of nkey keyinfo structures, like + * + * keyinfo_t key_tbl[nkey]; + * + * Each key is decoded into more useful representations, held in + * keyinfo->rdata + * keyinfo->dst + * + * If a key has no matching DS record then keyinfo->dst is NULL. + * + * The key algorithm and ID are saved in keyinfo->algo and + * keyinfo->tag for quicky skipping DS and RRSIG records that can't + * match. + */ +typedef struct keyinfo { + dns_rdata_t rdata; + dst_key_t *dst; + dns_secalg_t algo; + dns_keytag_t tag; +} keyinfo_t; + +/* A replaceable function that can generate a DS RRset from some input */ +typedef isc_result_t +ds_maker_func_t(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt, + dns_rdata_t *crdata); + +static dns_rdataset_t cdnskey_set = DNS_RDATASET_INIT; +static dns_rdataset_t cdnskey_sig = DNS_RDATASET_INIT; +static dns_rdataset_t cds_set = DNS_RDATASET_INIT; +static dns_rdataset_t cds_sig = DNS_RDATASET_INIT; +static dns_rdataset_t dnskey_set = DNS_RDATASET_INIT; +static dns_rdataset_t dnskey_sig = DNS_RDATASET_INIT; +static dns_rdataset_t old_ds_set = DNS_RDATASET_INIT; +static dns_rdataset_t new_ds_set = DNS_RDATASET_INIT; + +static keyinfo_t *old_key_tbl = NULL, *new_key_tbl = NULL; + +isc_buffer_t *new_ds_buf = NULL; /* backing store for new_ds_set */ + +static dns_db_t *child_db = NULL; +static dns_dbnode_t *child_node = NULL; +static dns_db_t *parent_db = NULL; +static dns_dbnode_t *parent_node = NULL; +static dns_db_t *update_db = NULL; +static dns_dbnode_t *update_node = NULL; +static dns_dbversion_t *update_version = NULL; +static bool cleanup_dst = false; +static bool print_mem_stats = false; + +static void +verbose_time(int level, const char *msg, isc_stdtime_t time) { + isc_result_t result; + isc_buffer_t timebuf; + char timestr[32]; + + if (verbose < level) { + return; + } + + isc_buffer_init(&timebuf, timestr, sizeof(timestr)); + result = dns_time64_totext(time, &timebuf); + check_result(result, "dns_time64_totext()"); + isc_buffer_putuint8(&timebuf, 0); + if (verbose < 3) { + vbprintf(level, "%s %s\n", msg, timestr); + } else { + vbprintf(level, "%s %s (%" PRIu32 ")\n", msg, timestr, time); + } +} + +static void +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; + + name = dns_fixedname_initname(&fixed); + namestr = setname; + + isc_buffer_init(&buf, setname, strlen(setname)); + isc_buffer_add(&buf, strlen(setname)); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize name %s", setname); + } +} + +static void +findset(dns_db_t *db, dns_dbnode_t *node, dns_rdatatype_t type, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { + isc_result_t result; + + dns_rdataset_init(rdataset); + if (sigrdataset != NULL) { + dns_rdataset_init(sigrdataset); + } + result = dns_db_findrdataset(db, node, NULL, type, 0, 0, rdataset, + sigrdataset); + if (result != ISC_R_NOTFOUND) { + check_result(result, "dns_db_findrdataset()"); + } +} + +static void +freeset(dns_rdataset_t *rdataset) { + if (dns_rdataset_isassociated(rdataset)) { + dns_rdataset_disassociate(rdataset); + } +} + +static void +freelist(dns_rdataset_t *rdataset) { + dns_rdatalist_t *rdlist; + dns_rdata_t *rdata; + + if (!dns_rdataset_isassociated(rdataset)) { + return; + } + + dns_rdatalist_fromrdataset(rdataset, &rdlist); + + for (rdata = ISC_LIST_HEAD(rdlist->rdata); rdata != NULL; + rdata = ISC_LIST_HEAD(rdlist->rdata)) + { + ISC_LIST_UNLINK(rdlist->rdata, rdata, link); + isc_mem_put(mctx, rdata, sizeof(*rdata)); + } + isc_mem_put(mctx, rdlist, sizeof(*rdlist)); + dns_rdataset_disassociate(rdataset); +} + +static void +free_all_sets(void) { + freeset(&cdnskey_set); + freeset(&cdnskey_sig); + freeset(&cds_set); + freeset(&cds_sig); + freeset(&dnskey_set); + freeset(&dnskey_sig); + freeset(&old_ds_set); + freelist(&new_ds_set); + if (new_ds_buf != NULL) { + isc_buffer_free(&new_ds_buf); + } +} + +static void +load_db(const char *filename, dns_db_t **dbp, dns_dbnode_t **nodep) { + isc_result_t result; + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, dbp); + check_result(result, "dns_db_create()"); + + result = dns_db_load(*dbp, filename, dns_masterformat_text, + DNS_MASTER_HINT); + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + fatal("can't load %s: %s", filename, isc_result_totext(result)); + } + + result = dns_db_findnode(*dbp, name, false, nodep); + if (result != ISC_R_SUCCESS) { + fatal("can't find %s node in %s", namestr, filename); + } +} + +static void +free_db(dns_db_t **dbp, dns_dbnode_t **nodep, dns_dbversion_t **versionp) { + if (*dbp != NULL) { + if (*nodep != NULL) { + dns_db_detachnode(*dbp, nodep); + } + if (versionp != NULL && *versionp != NULL) { + dns_db_closeversion(*dbp, versionp, false); + } + dns_db_detach(dbp); + } +} + +static void +load_child_sets(const char *file) { + load_db(file, &child_db, &child_node); + findset(child_db, child_node, dns_rdatatype_dnskey, &dnskey_set, + &dnskey_sig); + findset(child_db, child_node, dns_rdatatype_cdnskey, &cdnskey_set, + &cdnskey_sig); + findset(child_db, child_node, dns_rdatatype_cds, &cds_set, &cds_sig); + free_db(&child_db, &child_node, NULL); +} + +static void +get_dsset_name(char *filename, size_t size, const char *path, + const char *suffix) { + isc_result_t result; + isc_buffer_t buf; + size_t len; + + isc_buffer_init(&buf, filename, size); + + len = strlen(path); + + /* allow room for a trailing slash */ + if (isc_buffer_availablelength(&buf) <= len) { + fatal("%s: pathname too long", path); + } + isc_buffer_putstr(&buf, path); + + if (isc_file_isdirectory(path) == ISC_R_SUCCESS) { + const char *prefix = "dsset-"; + + if (path[len - 1] != '/') { + isc_buffer_putstr(&buf, "/"); + } + + if (isc_buffer_availablelength(&buf) < strlen(prefix)) { + fatal("%s: pathname too long", path); + } + isc_buffer_putstr(&buf, prefix); + + result = dns_name_tofilenametext(name, false, &buf); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&buf) == 0) { + fatal("%s: pathname too long", path); + } + } + /* allow room for a trailing nul */ + if (isc_buffer_availablelength(&buf) <= strlen(suffix)) { + fatal("%s: pathname too long", path); + } + isc_buffer_putstr(&buf, suffix); + isc_buffer_putuint8(&buf, 0); +} + +static void +load_parent_set(const char *path) { + isc_result_t result; + isc_time_t modtime; + char filename[PATH_MAX + 1]; + + get_dsset_name(filename, sizeof(filename), path, ""); + + result = isc_file_getmodtime(filename, &modtime); + if (result != ISC_R_SUCCESS) { + fatal("could not get modification time of %s: %s", filename, + isc_result_totext(result)); + } + notbefore = isc_time_seconds(&modtime); + if (startstr != NULL) { + isc_stdtime_t now = isc_stdtime_now(); + notbefore = strtotime(startstr, now, notbefore, NULL); + } + verbose_time(1, "child records must not be signed before", notbefore); + + load_db(filename, &parent_db, &parent_node); + findset(parent_db, parent_node, dns_rdatatype_ds, &old_ds_set, NULL); + + if (!dns_rdataset_isassociated(&old_ds_set)) { + fatal("could not find DS records for %s in %s", namestr, + filename); + } + + free_db(&parent_db, &parent_node, NULL); +} + +#define MAX_CDS_RDATA_TEXT_SIZE DNS_RDATA_MAXLENGTH * 2 + +static isc_buffer_t * +formatset(dns_rdataset_t *rdataset) { + isc_result_t result; + isc_buffer_t *buf = NULL; + dns_master_style_t *style = NULL; + unsigned int styleflags; + + styleflags = (rdataset->ttl == 0) ? DNS_STYLEFLAG_NO_TTL : 0; + + /* + * This style is for consistency with the output of dnssec-dsfromkey + * which just separates fields with spaces. The huge tab stop width + * eliminates any tab characters. + */ + result = dns_master_stylecreate(&style, styleflags, 0, 0, 0, 0, 0, + 1000000, 0, mctx); + check_result(result, "dns_master_stylecreate2 failed"); + + isc_buffer_allocate(mctx, &buf, MAX_CDS_RDATA_TEXT_SIZE); + result = dns_master_rdatasettotext(name, rdataset, style, NULL, buf); + dns_master_styledestroy(&style, mctx); + + if ((result == ISC_R_SUCCESS) && isc_buffer_availablelength(buf) < 1) { + result = ISC_R_NOSPACE; + } + + if (result != ISC_R_SUCCESS) { + isc_buffer_free(&buf); + check_result(result, "dns_rdataset_totext()"); + } + + isc_buffer_putuint8(buf, 0); + return buf; +} + +static void +write_parent_set(const char *path, const char *inplace, bool nsupdate, + dns_rdataset_t *rdataset) { + isc_result_t result; + isc_buffer_t *buf = NULL; + isc_region_t r; + isc_time_t filetime; + char backname[PATH_MAX + 1]; + char filename[PATH_MAX + 1]; + char tmpname[PATH_MAX + 1]; + FILE *fp = NULL; + + if (nsupdate && inplace == NULL) { + return; + } + + buf = formatset(rdataset); + isc_buffer_usedregion(buf, &r); + + /* + * Try to ensure a write error doesn't make a zone go insecure! + */ + if (inplace == NULL) { + printf("%s", (char *)r.base); + isc_buffer_free(&buf); + if (fflush(stdout) == EOF) { + fatal("error writing to stdout: %s", strerror(errno)); + } + return; + } + + if (inplace[0] != '\0') { + get_dsset_name(backname, sizeof(backname), path, inplace); + } + get_dsset_name(filename, sizeof(filename), path, ""); + get_dsset_name(tmpname, sizeof(tmpname), path, "-XXXXXXXXXX"); + + result = isc_file_openunique(tmpname, &fp); + if (result != ISC_R_SUCCESS) { + isc_buffer_free(&buf); + fatal("open %s: %s", tmpname, isc_result_totext(result)); + } + fprintf(fp, "%s", (char *)r.base); + isc_buffer_free(&buf); + if (fclose(fp) == EOF) { + int err = errno; + isc_file_remove(tmpname); + fatal("error writing to %s: %s", tmpname, strerror(err)); + } + + isc_time_set(&filetime, oldestsig.timesigned, 0); + result = isc_file_settime(tmpname, &filetime); + if (result != ISC_R_SUCCESS) { + isc_file_remove(tmpname); + fatal("can't set modification time of %s: %s", tmpname, + isc_result_totext(result)); + } + + if (inplace[0] != '\0') { + isc_file_rename(filename, backname); + } + isc_file_rename(tmpname, filename); +} + +typedef enum { LOOSE, TIGHT } strictness_t; + +/* + * Find out if any (C)DS record matches a particular (C)DNSKEY. + */ +static bool +match_key_dsset(keyinfo_t *ki, dns_rdataset_t *dsset, strictness_t strictness) { + isc_result_t result; + unsigned char dsbuf[DNS_DS_BUFFERSIZE]; + + for (result = dns_rdataset_first(dsset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(dsset)) + { + dns_rdata_ds_t ds; + dns_rdata_t dsrdata = DNS_RDATA_INIT; + dns_rdata_t newdsrdata = DNS_RDATA_INIT; + bool c; + + dns_rdataset_current(dsset, &dsrdata); + result = dns_rdata_tostruct(&dsrdata, &ds, NULL); + check_result(result, "dns_rdata_tostruct(DS)"); + + if (ki->tag != ds.key_tag || ki->algo != ds.algorithm) { + continue; + } + + result = dns_ds_buildrdata(name, &ki->rdata, ds.digest_type, + dsbuf, &newdsrdata); + if (result != ISC_R_SUCCESS) { + vbprintf(3, + "dns_ds_buildrdata(" + "keytag=%d, algo=%d, digest=%d): %s\n", + ds.key_tag, ds.algorithm, ds.digest_type, + isc_result_totext(result)); + continue; + } + /* allow for both DS and CDS */ + c = dsrdata.type != dns_rdatatype_ds; + dsrdata.type = dns_rdatatype_ds; + if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) { + vbprintf(1, "found matching %s %d %d %d\n", + c ? "CDS" : "DS", ds.key_tag, ds.algorithm, + ds.digest_type); + return true; + } else if (strictness == TIGHT) { + vbprintf(0, + "key does not match %s %d %d %d " + "when it looks like it should\n", + c ? "CDS" : "DS", ds.key_tag, ds.algorithm, + ds.digest_type); + return false; + } + } + + vbprintf(1, "no matching %s for %s %d %d\n", + dsset->type == dns_rdatatype_cds ? "CDS" : "DS", + ki->rdata.type == dns_rdatatype_cdnskey ? "CDNSKEY" : "DNSKEY", + ki->tag, ki->algo); + + return false; +} + +/* + * Find which (C)DNSKEY records match a (C)DS RRset. + * This creates a keyinfo_t key_tbl[nkey] array. + */ +static keyinfo_t * +match_keyset_dsset(dns_rdataset_t *keyset, dns_rdataset_t *dsset, + strictness_t strictness) { + isc_result_t result; + keyinfo_t *keytable, *ki; + int i; + + nkey = dns_rdataset_count(keyset); + + keytable = isc_mem_cget(mctx, nkey, sizeof(keytable[0])); + + for (result = dns_rdataset_first(keyset), i = 0, ki = keytable; + result == ISC_R_SUCCESS; + result = dns_rdataset_next(keyset), i++, ki++) + { + dns_rdata_dnskey_t dnskey; + dns_rdata_t *keyrdata; + isc_region_t r; + + INSIST(i < nkey); + keyrdata = &ki->rdata; + + dns_rdata_init(keyrdata); + dns_rdataset_current(keyset, keyrdata); + + result = dns_rdata_tostruct(keyrdata, &dnskey, NULL); + check_result(result, "dns_rdata_tostruct(DNSKEY)"); + ki->algo = dnskey.algorithm; + + dns_rdata_toregion(keyrdata, &r); + ki->tag = dst_region_computeid(&r); + + ki->dst = NULL; + if (!match_key_dsset(ki, dsset, strictness)) { + continue; + } + + result = dns_dnssec_keyfromrdata(name, keyrdata, mctx, + &ki->dst); + if (result != ISC_R_SUCCESS) { + vbprintf(3, + "dns_dnssec_keyfromrdata(" + "keytag=%d, algo=%d): %s\n", + ki->tag, ki->algo, isc_result_totext(result)); + } + } + + return keytable; +} + +static void +free_keytable(keyinfo_t **keytable_p) { + keyinfo_t *keytable = *keytable_p; + *keytable_p = NULL; + keyinfo_t *ki; + int i; + + REQUIRE(keytable != NULL); + + for (i = 0, ki = keytable; i < nkey; i++, ki++) { + if (ki->dst != NULL) { + dst_key_free(&ki->dst); + } + } + + isc_mem_cput(mctx, keytable, nkey, sizeof(keytable[0])); +} + +/* + * Find out which keys have signed an RRset. Keys that do not match a + * DS record are skipped. + * + * The return value is an array with nkey elements, one for each key, + * either zero if the key was skipped or did not sign the RRset, or + * otherwise the key algorithm. This is used by the signature coverage + * check functions below. + */ +static dns_secalg_t * +matching_sigs(keyinfo_t *keytbl, dns_rdataset_t *rdataset, + dns_rdataset_t *sigset) { + isc_result_t result; + dns_secalg_t *algo; + int i; + + REQUIRE(keytbl != NULL); + + algo = isc_mem_cget(mctx, nkey, sizeof(algo[0])); + + for (result = dns_rdataset_first(sigset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(sigset)) + { + dns_rdata_t sigrdata = DNS_RDATA_INIT; + dns_rdata_rrsig_t sig; + + dns_rdataset_current(sigset, &sigrdata); + result = dns_rdata_tostruct(&sigrdata, &sig, NULL); + check_result(result, "dns_rdata_tostruct(RRSIG)"); + + /* + * Replay attack protection: check against current age limit + */ + if (isc_serial_lt(sig.timesigned, notbefore)) { + vbprintf(1, "skip RRSIG by key %d: too old\n", + sig.keyid); + continue; + } + + for (i = 0; i < nkey; i++) { + keyinfo_t *ki = &keytbl[i]; + if (sig.keyid != ki->tag || sig.algorithm != ki->algo || + !dns_name_equal(&sig.signer, name)) + { + continue; + } + if (ki->dst == NULL) { + vbprintf(1, + "skip RRSIG by key %d:" + " no matching (C)DS\n", + sig.keyid); + continue; + } + + result = dns_dnssec_verify(name, rdataset, ki->dst, + false, 0, mctx, &sigrdata, + NULL); + + if (result != ISC_R_SUCCESS && + result != DNS_R_FROMWILDCARD) + { + vbprintf(1, + "skip RRSIG by key %d:" + " verification failed: %s\n", + sig.keyid, isc_result_totext(result)); + continue; + } + + vbprintf(1, "found RRSIG by key %d\n", ki->tag); + algo[i] = sig.algorithm; + + /* + * Replay attack protection: work out next age limit, + * only after the signature has been verified + */ + if (oldestsig.timesigned == 0 || + isc_serial_lt(sig.timesigned, oldestsig.timesigned)) + { + verbose_time(2, "this is the oldest so far", + sig.timesigned); + oldestsig = sig; + } + } + } + + return algo; +} + +/* + * Consume the result of matching_sigs(). When checking records + * fetched from the child zone, any working signature is enough. + */ +static bool +signed_loose(dns_secalg_t *algo) { + bool ok = false; + int i; + for (i = 0; i < nkey; i++) { + if (algo[i] != 0) { + ok = true; + } + } + isc_mem_cput(mctx, algo, nkey, sizeof(algo[0])); + return ok; +} + +/* + * Consume the result of matching_sigs(). To ensure that the new DS + * RRset does not break the chain of trust to the DNSKEY RRset, every + * key algorithm in the DS RRset must have a signature in the DNSKEY + * RRset. + */ +static bool +signed_strict(dns_rdataset_t *dsset, dns_secalg_t *algo) { + isc_result_t result; + bool all_ok = true; + + for (result = dns_rdataset_first(dsset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(dsset)) + { + dns_rdata_t dsrdata = DNS_RDATA_INIT; + dns_rdata_ds_t ds; + bool ds_ok; + int i; + + dns_rdataset_current(dsset, &dsrdata); + result = dns_rdata_tostruct(&dsrdata, &ds, NULL); + check_result(result, "dns_rdata_tostruct(DS)"); + + ds_ok = false; + for (i = 0; i < nkey; i++) { + if (algo[i] == ds.algorithm) { + ds_ok = true; + } + } + if (!ds_ok) { + vbprintf(0, + "missing signature for algorithm %d " + "(key %d)\n", + ds.algorithm, ds.key_tag); + all_ok = false; + } + } + + isc_mem_cput(mctx, algo, nkey, sizeof(algo[0])); + return all_ok; +} + +/* + * This basically copies the rdata into the buffer, but going via the + * unpacked struct lets us change the rdatatype. (The dns_rdata_cds_t + * and dns_rdata_ds_t types are aliases.) + */ +static isc_result_t +ds_from_cds(isc_buffer_t *buf, dns_rdata_t *rds, dns_dsdigest_t dt, + dns_rdata_t *cds) { + isc_result_t result; + dns_rdata_ds_t ds; + + REQUIRE(buf != NULL); + + result = dns_rdata_tostruct(cds, &ds, NULL); + check_result(result, "dns_rdata_tostruct(CDS)"); + ds.common.rdtype = dns_rdatatype_ds; + + if (ds.digest_type != dt) { + return ISC_R_IGNORE; + } + + return dns_rdata_fromstruct(rds, rdclass, dns_rdatatype_ds, &ds, buf); +} + +static isc_result_t +ds_from_cdnskey(isc_buffer_t *buf, dns_rdata_t *ds, dns_dsdigest_t dt, + dns_rdata_t *cdnskey) { + isc_result_t result; + isc_region_t r; + + REQUIRE(buf != NULL); + + isc_buffer_availableregion(buf, &r); + if (r.length < DNS_DS_BUFFERSIZE) { + return ISC_R_NOSPACE; + } + + result = dns_ds_buildrdata(name, cdnskey, dt, r.base, ds); + if (result == ISC_R_SUCCESS) { + isc_buffer_add(buf, DNS_DS_BUFFERSIZE); + } + + return result; +} + +static isc_result_t +append_new_ds_set(ds_maker_func_t *ds_from_rdata, isc_buffer_t *buf, + dns_rdatalist_t *dslist, dns_dsdigest_t dt, + dns_rdataset_t *crdset) { + isc_result_t result; + + for (result = dns_rdataset_first(crdset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(crdset)) + { + dns_rdata_t crdata = DNS_RDATA_INIT; + dns_rdata_t *ds = NULL; + + dns_rdataset_current(crdset, &crdata); + + ds = isc_mem_get(mctx, sizeof(*ds)); + dns_rdata_init(ds); + + result = ds_from_rdata(buf, ds, dt, &crdata); + + switch (result) { + case ISC_R_SUCCESS: + ISC_LIST_APPEND(dslist->rdata, ds, link); + break; + case ISC_R_IGNORE: + isc_mem_put(mctx, ds, sizeof(*ds)); + continue; + case ISC_R_NOSPACE: + isc_mem_put(mctx, ds, sizeof(*ds)); + return result; + default: + isc_mem_put(mctx, ds, sizeof(*ds)); + check_result(result, "ds_from_rdata()"); + } + } + + return ISC_R_SUCCESS; +} + +static void +make_new_ds_set(ds_maker_func_t *ds_from_rdata, uint32_t ttl, + dns_rdataset_t *crdset) { + unsigned int size = 16; + + for (;;) { + isc_result_t result = ISC_R_SUCCESS; + dns_rdatalist_t *dslist = NULL; + size_t n; + + dslist = isc_mem_get(mctx, sizeof(*dslist)); + dns_rdatalist_init(dslist); + dslist->rdclass = rdclass; + dslist->type = dns_rdatatype_ds; + dslist->ttl = ttl; + + dns_rdataset_init(&new_ds_set); + dns_rdatalist_tordataset(dslist, &new_ds_set); + + isc_buffer_allocate(mctx, &new_ds_buf, size); + + n = sizeof(dtype) / sizeof(dtype[0]); + for (size_t i = 0; i < n && dtype[i] != 0; i++) { + result = append_new_ds_set(ds_from_rdata, new_ds_buf, + dslist, dtype[i], crdset); + if (result != ISC_R_SUCCESS) { + break; + } + } + if (result == ISC_R_SUCCESS) { + return; + } + + vbprintf(2, "doubling DS list buffer size from %u\n", size); + freelist(&new_ds_set); + isc_buffer_free(&new_ds_buf); + size *= 2; + } +} + +static int +rdata_cmp(const void *rdata1, const void *rdata2) { + return dns_rdata_compare((const dns_rdata_t *)rdata1, + (const dns_rdata_t *)rdata2); +} + +/* + * Ensure that every key identified by the DS RRset has the same set of + * digest types. + */ +static bool +consistent_digests(dns_rdataset_t *dsset) { + isc_result_t result; + dns_rdata_t *arrdata; + dns_rdata_ds_t *ds; + dns_keytag_t key_tag; + dns_secalg_t algorithm; + bool match; + int i, j, n, d; + + /* + * First sort the dsset. DS rdata fields are tag, algorithm, + * digest, so sorting them brings together all the records for + * each key. + */ + + n = dns_rdataset_count(dsset); + + arrdata = isc_mem_cget(mctx, n, sizeof(dns_rdata_t)); + + for (result = dns_rdataset_first(dsset), i = 0; result == ISC_R_SUCCESS; + result = dns_rdataset_next(dsset), i++) + { + dns_rdata_init(&arrdata[i]); + dns_rdataset_current(dsset, &arrdata[i]); + } + + qsort(arrdata, n, sizeof(dns_rdata_t), rdata_cmp); + + /* + * Convert sorted arrdata to more accessible format + */ + ds = isc_mem_cget(mctx, n, sizeof(dns_rdata_ds_t)); + + for (i = 0; i < n; i++) { + result = dns_rdata_tostruct(&arrdata[i], &ds[i], NULL); + check_result(result, "dns_rdata_tostruct(DS)"); + } + + /* + * Count number of digest types (d) for first key + */ + key_tag = ds[0].key_tag; + algorithm = ds[0].algorithm; + for (d = 0, i = 0; i < n; i++, d++) { + if (ds[i].key_tag != key_tag || ds[i].algorithm != algorithm) { + break; + } + } + + /* + * Check subsequent keys match the first one + */ + match = true; + while (i < n) { + key_tag = ds[i].key_tag; + algorithm = ds[i].algorithm; + for (j = 0; j < d && i + j < n; j++) { + if (ds[i + j].key_tag != key_tag || + ds[i + j].algorithm != algorithm || + ds[i + j].digest_type != ds[j].digest_type) + { + match = false; + } + } + i += d; + } + + /* + * Done! + */ + isc_mem_cput(mctx, ds, n, sizeof(dns_rdata_ds_t)); + isc_mem_cput(mctx, arrdata, n, sizeof(dns_rdata_t)); + + return match; +} + +static void +print_diff(const char *cmd, dns_rdataset_t *rdataset) { + isc_buffer_t *buf; + isc_region_t r; + unsigned char *nl; + size_t len; + + buf = formatset(rdataset); + isc_buffer_usedregion(buf, &r); + + while ((nl = memchr(r.base, '\n', r.length)) != NULL) { + len = nl - r.base + 1; + printf("update %s %.*s", cmd, (int)len, (char *)r.base); + isc_region_consume(&r, len); + } + + isc_buffer_free(&buf); +} + +static void +update_diff(const char *cmd, uint32_t ttl, dns_rdataset_t *addset, + dns_rdataset_t *delset) { + isc_result_t result; + dns_rdataset_t diffset; + uint32_t save; + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, &update_db); + check_result(result, "dns_db_create()"); + + result = dns_db_newversion(update_db, &update_version); + check_result(result, "dns_db_newversion()"); + + result = dns_db_findnode(update_db, name, true, &update_node); + check_result(result, "dns_db_findnode()"); + + dns_rdataset_init(&diffset); + + result = dns_db_addrdataset(update_db, update_node, update_version, 0, + addset, DNS_DBADD_MERGE, NULL); + check_result(result, "dns_db_addrdataset()"); + + result = dns_db_subtractrdataset(update_db, update_node, update_version, + delset, 0, &diffset); + if (result == DNS_R_UNCHANGED) { + save = addset->ttl; + addset->ttl = ttl; + print_diff(cmd, addset); + addset->ttl = save; + } else if (result != DNS_R_NXRRSET) { + check_result(result, "dns_db_subtractrdataset()"); + diffset.ttl = ttl; + print_diff(cmd, &diffset); + dns_rdataset_disassociate(&diffset); + } + + free_db(&update_db, &update_node, &update_version); +} + +static void +nsdiff(uint32_t ttl, dns_rdataset_t *oldset, dns_rdataset_t *newset) { + if (ttl == 0) { + vbprintf(1, "warning: no TTL in nsupdate script\n"); + } + update_diff("add", ttl, newset, oldset); + update_diff("del", 0, oldset, newset); + if (verbose > 0) { + printf("show\nsend\nanswer\n"); + } else { + printf("send\n"); + } + if (fflush(stdout) == EOF) { + fatal("write stdout: %s", strerror(errno)); + } +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s options [options] -f -d \n", + program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "Options:\n" + " -a digest algorithm (SHA-1 / " + "SHA-256 / SHA-384)\n" + " -c of domain (default IN)\n" + " -D prefer CDNSKEY records instead " + "of CDS\n" + " -d where to find parent dsset- " + "file\n" + " -f child DNSKEY+CDNSKEY+CDS+RRSIG " + "records\n" + " -i[extension] update dsset- file in place\n" + " -s oldest permitted child " + "signatures\n" + " -u emit nsupdate script\n" + " -T TTL of DS records\n" + " -V print version\n" + " -v \n"); + exit(EXIT_FAILURE); +} + +static void +cleanup(void) { + free_db(&child_db, &child_node, NULL); + free_db(&parent_db, &parent_node, NULL); + free_db(&update_db, &update_node, &update_version); + if (old_key_tbl != NULL) { + free_keytable(&old_key_tbl); + } + if (new_key_tbl != NULL) { + free_keytable(&new_key_tbl); + } + free_all_sets(); + if (lctx != NULL) { + cleanup_logging(&lctx); + } + if (cleanup_dst) { + dst_lib_destroy(); + } + if (mctx != NULL) { + if (print_mem_stats && verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_destroy(&mctx); + } +} + +int +main(int argc, char *argv[]) { + const char *child_path = NULL; + const char *ds_path = NULL; + const char *inplace = NULL; + isc_result_t result; + bool prefer_cdnskey = false; + bool nsupdate = false; + uint32_t ttl = 0; + int ch; + char *endp; + + setfatalcallback(cleanup); + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + +#define OPTIONS "a:c:Dd:f:i:ms:T:uv:V" + while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { + switch (ch) { + case 'a': + add_dtype(strtodsdigest(isc_commandline_argument)); + break; + case 'c': + rdclass = strtoclass(isc_commandline_argument); + break; + case 'D': + prefer_cdnskey = true; + break; + case 'd': + ds_path = isc_commandline_argument; + break; + case 'f': + child_path = isc_commandline_argument; + break; + case 'i': + /* + * This is a bodge to make the argument + * optional, so that it works just like sed(1). + */ + if (isc_commandline_argument == + argv[isc_commandline_index - 1]) + { + isc_commandline_index--; + inplace = ""; + } else { + inplace = isc_commandline_argument; + } + break; + case 'm': + isc_mem_debugging = ISC_MEM_DEBUGTRACE | + ISC_MEM_DEBUGRECORD; + break; + case 's': + startstr = isc_commandline_argument; + break; + case 'T': + ttl = strtottl(isc_commandline_argument); + break; + case 'u': + nsupdate = true; + break; + case 'V': + /* Does not return. */ + version(program); + break; + case 'v': + verbose = strtoul(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + default: + usage(); + break; + } + } + argv += isc_commandline_index; + argc -= isc_commandline_index; + + if (argc != 1) { + usage(); + } + initname(argv[0]); + + /* + * Default digest type if none specified. + */ + if (dtype[0] == 0) { + dtype[0] = DNS_DSDIGEST_SHA256; + } + + setup_logging(mctx, &lctx); + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", + isc_result_totext(result)); + } + cleanup_dst = true; + + if (ds_path == NULL) { + fatal("missing -d DS pathname"); + } + load_parent_set(ds_path); + + /* + * Preserve the TTL if it wasn't overridden. + */ + if (ttl == 0) { + ttl = old_ds_set.ttl; + } + + if (child_path == NULL) { + fatal("path to file containing child data must be specified"); + } + + load_child_sets(child_path); + + /* + * Check child records have accompanying RRSIGs and DNSKEYs + */ + + if (!dns_rdataset_isassociated(&dnskey_set) || + !dns_rdataset_isassociated(&dnskey_sig)) + { + fatal("could not find signed DNSKEY RRset for %s", namestr); + } + + if (dns_rdataset_isassociated(&cdnskey_set) && + !dns_rdataset_isassociated(&cdnskey_sig)) + { + fatal("missing RRSIG CDNSKEY records for %s", namestr); + } + if (dns_rdataset_isassociated(&cds_set) && + !dns_rdataset_isassociated(&cds_sig)) + { + fatal("missing RRSIG CDS records for %s", namestr); + } + + vbprintf(1, "which child DNSKEY records match parent DS records?\n"); + old_key_tbl = match_keyset_dsset(&dnskey_set, &old_ds_set, LOOSE); + + /* + * We have now identified the keys that are allowed to + * authenticate the DNSKEY RRset (RFC 4035 section 5.2 bullet + * 2), and CDNSKEY and CDS RRsets (RFC 7344 section 4.1 bullet + * 2). + */ + + vbprintf(1, "verify DNSKEY signature(s)\n"); + if (!signed_loose(matching_sigs(old_key_tbl, &dnskey_set, &dnskey_sig))) + { + fatal("could not validate child DNSKEY RRset for %s", namestr); + } + + if (dns_rdataset_isassociated(&cdnskey_set)) { + vbprintf(1, "verify CDNSKEY signature(s)\n"); + if (!signed_loose(matching_sigs(old_key_tbl, &cdnskey_set, + &cdnskey_sig))) + { + fatal("could not validate child CDNSKEY RRset for %s", + namestr); + } + } + if (dns_rdataset_isassociated(&cds_set)) { + vbprintf(1, "verify CDS signature(s)\n"); + if (!signed_loose( + matching_sigs(old_key_tbl, &cds_set, &cds_sig))) + { + fatal("could not validate child CDS RRset for %s", + namestr); + } + } + + free_keytable(&old_key_tbl); + + /* + * Report the result of the replay attack protection checks + * used for the output file timestamp + */ + if (oldestsig.timesigned != 0 && verbose > 0) { + char type[32]; + dns_rdatatype_format(oldestsig.covered, type, sizeof(type)); + verbose_time(1, "child signature inception time", + oldestsig.timesigned); + vbprintf(2, "from RRSIG %s by key %d\n", type, oldestsig.keyid); + } + + /* + * Successfully do nothing if there's neither CDNSKEY nor CDS + * RFC 7344 section 4.1 first paragraph + */ + if (!dns_rdataset_isassociated(&cdnskey_set) && + !dns_rdataset_isassociated(&cds_set)) + { + vbprintf(1, "%s has neither CDS nor CDNSKEY records\n", + namestr); + write_parent_set(ds_path, inplace, nsupdate, &old_ds_set); + goto cleanup; + } + + /* + * Make DS records from the CDS or CDNSKEY records + * Prefer CDS if present, unless run with -D + */ + if (prefer_cdnskey && dns_rdataset_isassociated(&cdnskey_set)) { + make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set); + } else if (dns_rdataset_isassociated(&cds_set)) { + make_new_ds_set(ds_from_cds, ttl, &cds_set); + } else { + make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set); + } + + /* + * Try to use CDNSKEY records if the CDS records are missing + * or did not match. + */ + if (dns_rdataset_count(&new_ds_set) == 0 && + dns_rdataset_isassociated(&cdnskey_set)) + { + vbprintf(1, "CDS records have no allowed digest types; " + "using CDNSKEY instead\n"); + freelist(&new_ds_set); + isc_buffer_free(&new_ds_buf); + make_new_ds_set(ds_from_cdnskey, ttl, &cdnskey_set); + } + if (dns_rdataset_count(&new_ds_set) == 0) { + fatal("CDS records at %s do not match any -a digest types", + namestr); + } + + /* + * Now we have a candidate DS RRset, we need to check it + * won't break the delegation. + */ + vbprintf(1, "which child DNSKEY records match new DS records?\n"); + new_key_tbl = match_keyset_dsset(&dnskey_set, &new_ds_set, TIGHT); + + if (!consistent_digests(&new_ds_set)) { + fatal("CDS records at %s do not cover each key " + "with the same set of digest types", + namestr); + } + + vbprintf(1, "verify DNSKEY signature(s)\n"); + if (!signed_strict(&new_ds_set, matching_sigs(new_key_tbl, &dnskey_set, + &dnskey_sig))) + { + fatal("could not validate child DNSKEY RRset " + "with new DS records for %s", + namestr); + } + + free_keytable(&new_key_tbl); + + /* + * OK, it's all good! + */ + if (nsupdate) { + nsdiff(ttl, &old_ds_set, &new_ds_set); + } + + write_parent_set(ds_path, inplace, nsupdate, &new_ds_set); + +cleanup: + print_mem_stats = true; + cleanup(); + + return 0; +} diff --git a/bin/dnssec/dnssec-cds.rst b/bin/dnssec/dnssec-cds.rst new file mode 100644 index 0000000..09960e9 --- /dev/null +++ b/bin/dnssec/dnssec-cds.rst @@ -0,0 +1,221 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-cds +.. program:: dnssec-cds +.. _man_dnssec-cds: + +dnssec-cds - change DS records for a child zone based on CDS/CDNSKEY +-------------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-cds` [**-a** alg...] [**-c** class] [**-D**] {**-d** dsset-file} {**-f** child-file} [**-i**[extension]] [**-s** start-time] [**-T** ttl] [**-u**] [**-v** level] [**-V**] {domain} + +Description +~~~~~~~~~~~ + +The :program:`dnssec-cds` command changes DS records at a delegation point +based on CDS or CDNSKEY records published in the child zone. If both CDS +and CDNSKEY records are present in the child zone, the CDS is preferred. +This enables a child zone to inform its parent of upcoming changes to +its key-signing keys (KSKs); by polling periodically with :program:`dnssec-cds`, the +parent can keep the DS records up-to-date and enable automatic rolling +of KSKs. + +Two input files are required. The :option:`-f child-file <-f>` option specifies a +file containing the child's CDS and/or CDNSKEY records, plus RRSIG and +DNSKEY records so that they can be authenticated. The :option:`-d path <-d>` option +specifies the location of a file containing the current DS records. For +example, this could be a ``dsset-`` file generated by +:iscman:`dnssec-signzone`, or the output of :iscman:`dnssec-dsfromkey`, or the +output of a previous run of :program:`dnssec-cds`. + +The :program:`dnssec-cds` command uses special DNSSEC validation logic +specified by :rfc:`7344`. It requires that the CDS and/or CDNSKEY records +be validly signed by a key represented in the existing DS records. This +is typically the pre-existing KSK. + +For protection against replay attacks, the signatures on the child +records must not be older than they were on a previous run of +:program:`dnssec-cds`. Their age is obtained from the modification time of the +``dsset-`` file, or from the :option:`-s` option. + +To protect against breaking the delegation, :program:`dnssec-cds` ensures that +the DNSKEY RRset can be verified by every key algorithm in the new DS +RRset, and that the same set of keys are covered by every DS digest +type. + +By default, replacement DS records are written to the standard output; +with the :option:`-i` option the input file is overwritten in place. The +replacement DS records are the same as the existing records, when no +change is required. The output can be empty if the CDS/CDNSKEY records +specify that the child zone wants to be insecure. + +.. warning:: + + Be careful not to delete the DS records when :program:`dnssec-cds` fails! + +Alternatively, :option`dnssec-cds -u` writes an :iscman:`nsupdate` script to the +standard output. The :option:`-u` and :option:`-i` options can be used together to +maintain a ``dsset-`` file as well as emit an :iscman:`nsupdate` script. + +Options +~~~~~~~ + +.. option:: -a algorithm + + When converting CDS records to DS records, this option specifies + the acceptable digest algorithms. This option can be repeated, so + that multiple digest types are allowed. If none of the CDS records + use an acceptable digest type, :program:`dnssec-cds` will try to use CDNSKEY + records instead; if there are no CDNSKEY records, it reports an error. + + When converting CDNSKEY records to DS records, this option specifies the + digest algorithm to use. It can be repeated, so that multiple DS records + are created for each CDNSKEY records. + + The algorithm must be one of SHA-1, SHA-256, or SHA-384. These values + are case-insensitive, and the hyphen may be omitted. If no algorithm + is specified, the default is SHA-256 only. + +.. option:: -c class + + This option specifies the DNS class of the zones. + +.. option:: -D + + This option generates DS records from CDNSKEY records if both CDS and CDNSKEY + records are present in the child zone. By default CDS records are + preferred. + +.. option:: -d path + + This specifies the location of the parent DS records. The path can be the name of a file + containing the DS records; if it is a directory, :program:`dnssec-cds` + looks for a ``dsset-`` file for the domain inside the directory. + + To protect against replay attacks, child records are rejected if they + were signed earlier than the modification time of the ``dsset-`` + file. This can be adjusted with the :option:`-s` option. + +.. option:: -f child-file + + This option specifies the file containing the child's CDS and/or CDNSKEY records, plus its + DNSKEY records and the covering RRSIG records, so that they can be + authenticated. + + The examples below describe how to generate this file. + +.. option:: -i extension + + This option updates the ``dsset-`` file in place, instead of writing DS records to + the standard output. + + There must be no space between the :option:`-i` and the extension. If + no extension is provided, the old ``dsset-`` is discarded. If an + extension is present, a backup of the old ``dsset-`` file is kept + with the extension appended to its filename. + + To protect against replay attacks, the modification time of the + ``dsset-`` file is set to match the signature inception time of the + child records, provided that it is later than the file's current + modification time. + +.. option:: -s start-time + + This option specifies the date and time after which RRSIG records become + acceptable. This can be either an absolute or a relative time. An + absolute start time is indicated by a number in YYYYMMDDHHMMSS + notation; 20170827133700 denotes 13:37:00 UTC on August 27th, 2017. A + time relative to the ``dsset-`` file is indicated with ``-N``, which is N + seconds before the file modification time. A time relative to the + current time is indicated with ``now+N``. + + If no start-time is specified, the modification time of the + ``dsset-`` file is used. + +.. option:: -T ttl + + This option specifies a TTL to be used for new DS records. If not specified, the + default is the TTL of the old DS records. If they had no explicit TTL, + the new DS records also have no explicit TTL. + +.. option:: -u + + This option writes an :iscman:`nsupdate` script to the standard output, instead of + printing the new DS reords. The output is empty if no change is + needed. + + Note: The TTL of new records needs to be specified: it can be done in the + original ``dsset-`` file, with the :option:`-T` option, or using the + :iscman:`nsupdate` ``ttl`` command. + +.. option:: -V + + This option prints version information. + +.. option:: -v level + + This option sets the debugging level. Level 1 is intended to be usefully verbose + for general users; higher levels are intended for developers. + +``domain`` + This indicates the name of the delegation point/child zone apex. + +Exit Status +~~~~~~~~~~~ + +The :program:`dnssec-cds` command exits 0 on success, or non-zero if an error +occurred. + +If successful, the DS records may or may not need to be +changed. + +Examples +~~~~~~~~ + +Before running :iscman:`dnssec-signzone`, ensure that the delegations +are up-to-date by running :program:`dnssec-cds` on every ``dsset-`` file. + +To fetch the child records required by :program:`dnssec-cds`, invoke +:iscman:`dig` as in the script below. It is acceptable if the :iscman:`dig` fails, since +:program:`dnssec-cds` performs all the necessary checking. + +:: + + for f in dsset-* + do + d=${f#dsset-} + dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS | + dnssec-cds -i -f /dev/stdin -d $f $d + done + +When the parent zone is automatically signed by :iscman:`named`, +:program:`dnssec-cds` can be used with :iscman:`nsupdate` to maintain a delegation as follows. +The ``dsset-`` file allows the script to avoid having to fetch and +validate the parent DS records, and it maintains the replay attack +protection time. + +:: + + dig +dnssec +noall +answer $d DNSKEY $d CDNSKEY $d CDS | + dnssec-cds -u -i -f /dev/stdin -d $f $d | + nsupdate -l + +See Also +~~~~~~~~ + +:iscman:`dig(1) `, :iscman:`dnssec-settime(8) `, :iscman:`dnssec-signzone(8) `, :iscman:`nsupdate(1) `, BIND 9 Administrator +Reference Manual, :rfc:`7344`. diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c new file mode 100644 index 0000000..f20eb1a --- /dev/null +++ b/bin/dnssec/dnssec-dsfromkey.c @@ -0,0 +1,565 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-dsfromkey"; + +static dns_rdataclass_t rdclass; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static isc_mem_t *mctx = NULL; +static uint32_t ttl; +static bool emitttl = false; +static unsigned int split_width = 0; + +static isc_result_t +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; + + name = dns_fixedname_initname(&fixed); + + isc_buffer_init(&buf, setname, strlen(setname)); + isc_buffer_add(&buf, strlen(setname)); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + return result; +} + +static void +db_load_from_stream(dns_db_t *db, FILE *fp) { + isc_result_t result; + dns_rdatacallbacks_t callbacks; + + dns_rdatacallbacks_init(&callbacks); + result = dns_db_beginload(db, &callbacks); + if (result != ISC_R_SUCCESS) { + fatal("dns_db_beginload failed: %s", isc_result_totext(result)); + } + + result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks, + mctx); + if (result != ISC_R_SUCCESS) { + fatal("can't load from input: %s", isc_result_totext(result)); + } + + result = dns_db_endload(db, &callbacks); + if (result != ISC_R_SUCCESS) { + fatal("dns_db_endload failed: %s", isc_result_totext(result)); + } +} + +static isc_result_t +loadset(const char *filename, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + char setname[DNS_NAME_FORMATSIZE]; + + dns_name_format(name, setname, sizeof(setname)); + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, &db); + if (result != ISC_R_SUCCESS) { + fatal("can't create database"); + } + + if (strcmp(filename, "-") == 0) { + db_load_from_stream(db, stdin); + filename = "input"; + } else { + result = dns_db_load(db, filename, dns_masterformat_text, 0); + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + fatal("can't load %s: %s", filename, + isc_result_totext(result)); + } + } + + result = dns_db_findnode(db, name, false, &node); + if (result != ISC_R_SUCCESS) { + fatal("can't find %s node in %s", setname, filename); + } + + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, + rdataset, NULL); + + if (result == ISC_R_NOTFOUND) { + fatal("no DNSKEY RR for %s in %s", setname, filename); + } else if (result != ISC_R_SUCCESS) { + fatal("dns_db_findrdataset"); + } + + if (node != NULL) { + dns_db_detachnode(db, &node); + } + if (db != NULL) { + dns_db_detach(&db); + } + return result; +} + +static isc_result_t +loadkeyset(char *dirname, dns_rdataset_t *rdataset) { + isc_result_t result; + char filename[PATH_MAX + 1]; + isc_buffer_t buf; + + dns_rdataset_init(rdataset); + + isc_buffer_init(&buf, filename, sizeof(filename)); + if (dirname != NULL) { + /* allow room for a trailing slash */ + if (strlen(dirname) >= isc_buffer_availablelength(&buf)) { + return ISC_R_NOSPACE; + } + isc_buffer_putstr(&buf, dirname); + if (dirname[strlen(dirname) - 1] != '/') { + isc_buffer_putstr(&buf, "/"); + } + } + + if (isc_buffer_availablelength(&buf) < 7) { + return ISC_R_NOSPACE; + } + isc_buffer_putstr(&buf, "keyset-"); + + result = dns_name_tofilenametext(name, false, &buf); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&buf) == 0) { + return ISC_R_NOSPACE; + } + isc_buffer_putuint8(&buf, 0); + + return loadset(filename, rdataset); +} + +static void +loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, + dns_rdata_t *rdata) { + isc_result_t result; + dst_key_t *key = NULL; + isc_buffer_t keyb; + isc_region_t r; + + dns_rdata_init(rdata); + + isc_buffer_init(&keyb, key_buf, key_buf_size); + + result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx, + &key); + if (result != ISC_R_SUCCESS) { + fatal("can't load %s.key: %s", filename, + isc_result_totext(result)); + } + + if (verbose > 2) { + char keystr[DST_KEY_FORMATSIZE]; + + dst_key_format(key, keystr, sizeof(keystr)); + fprintf(stderr, "%s: %s\n", program, keystr); + } + + result = dst_key_todns(key, &keyb); + if (result != ISC_R_SUCCESS) { + fatal("can't decode key"); + } + + isc_buffer_usedregion(&keyb, &r); + dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey, + &r); + + rdclass = dst_key_class(key); + + name = dns_fixedname_initname(&fixed); + dns_name_copy(dst_key_name(key), name); + + dst_key_free(&key); +} + +static void +logkey(dns_rdata_t *rdata) { + isc_result_t result; + dst_key_t *key = NULL; + isc_buffer_t buf; + char keystr[DST_KEY_FORMATSIZE]; + + isc_buffer_init(&buf, rdata->data, rdata->length); + isc_buffer_add(&buf, rdata->length); + result = dst_key_fromdns(name, rdclass, &buf, mctx, &key); + if (result != ISC_R_SUCCESS) { + return; + } + + dst_key_format(key, keystr, sizeof(keystr)); + fprintf(stderr, "%s: %s\n", program, keystr); + + dst_key_free(&key); +} + +static void +emit(dns_dsdigest_t dt, bool showall, bool cds, dns_rdata_t *rdata) { + isc_result_t result; + unsigned char buf[DNS_DS_BUFFERSIZE]; + char text_buf[DST_KEY_MAXTEXTSIZE]; + char name_buf[DNS_NAME_MAXWIRE]; + char class_buf[10]; + isc_buffer_t textb, nameb, classb; + isc_region_t r; + dns_rdata_t ds; + dns_rdata_dnskey_t dnskey; + + isc_buffer_init(&textb, text_buf, sizeof(text_buf)); + isc_buffer_init(&nameb, name_buf, sizeof(name_buf)); + isc_buffer_init(&classb, class_buf, sizeof(class_buf)); + + dns_rdata_init(&ds); + + result = dns_rdata_tostruct(rdata, &dnskey, NULL); + if (result != ISC_R_SUCCESS) { + fatal("can't convert DNSKEY"); + } + + if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) { + return; + } + + if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && !showall) { + return; + } + + result = dns_ds_buildrdata(name, rdata, dt, buf, &ds); + if (result != ISC_R_SUCCESS) { + fatal("can't build record"); + } + + result = dns_name_totext(name, 0, &nameb); + if (result != ISC_R_SUCCESS) { + fatal("can't print name"); + } + + result = dns_rdata_tofmttext(&ds, (dns_name_t *)NULL, 0, 0, split_width, + "", &textb); + + if (result != ISC_R_SUCCESS) { + fatal("can't print rdata"); + } + + result = dns_rdataclass_totext(rdclass, &classb); + if (result != ISC_R_SUCCESS) { + fatal("can't print class"); + } + + isc_buffer_usedregion(&nameb, &r); + printf("%.*s ", (int)r.length, r.base); + + if (emitttl) { + printf("%u ", ttl); + } + + isc_buffer_usedregion(&classb, &r); + printf("%.*s", (int)r.length, r.base); + + if (cds) { + printf(" CDS "); + } else { + printf(" DS "); + } + + isc_buffer_usedregion(&textb, &r); + printf("%.*s\n", (int)r.length, r.base); +} + +static void +emits(bool showall, bool cds, dns_rdata_t *rdata) { + unsigned int i, n; + + n = sizeof(dtype) / sizeof(dtype[0]); + for (i = 0; i < n; i++) { + if (dtype[i] != 0) { + emit(dtype[i], showall, cds, rdata); + } + } +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, " %s [options] -f zonefile [zonename]\n\n", program); + fprintf(stderr, " %s [options] -s dnsname\n\n", program); + fprintf(stderr, " %s [-h|-V]\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "Options:\n" + " -1: digest algorithm SHA-1\n" + " -2: digest algorithm SHA-256\n" + " -a algorithm: digest algorithm (SHA-1, SHA-256 or " + "SHA-384)\n" + " -A: include all keys in DS set, not just KSKs (-f " + "only)\n" + " -c class: rdata class for DS set (default IN) (-f " + "or -s only)\n" + " -C: print CDS records\n" + " -f zonefile: read keys from a zone file\n" + " -h: print help information\n" + " -K directory: where to find key or keyset files\n" + " -w split base64 rdata text into chunks\n" + " -s: read keys from keyset- file\n" + " -T: TTL of output records (omitted by default)\n" + " -v level: verbosity\n" + " -V: print version information\n"); + fprintf(stderr, "Output: DS or CDS RRs\n"); + + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) { + char *classname = NULL; + char *filename = NULL, *dir = NULL, *namestr; + char *endp, *arg1; + int ch; + bool cds = false; + bool usekeyset = false; + bool showall = false; + isc_result_t result; + isc_log_t *log = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata; + + dns_rdata_init(&rdata); + + if (argc == 1) { + usage(); + } + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + +#define OPTIONS "12Aa:Cc:d:Ff:K:l:sT:v:whV" + while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { + switch (ch) { + case '1': + add_dtype(DNS_DSDIGEST_SHA1); + break; + case '2': + add_dtype(DNS_DSDIGEST_SHA256); + break; + case 'A': + showall = true; + break; + case 'a': + add_dtype(strtodsdigest(isc_commandline_argument)); + break; + case 'C': + cds = true; + break; + case 'c': + classname = isc_commandline_argument; + break; + case 'd': + fprintf(stderr, + "%s: the -d option is deprecated; " + "use -K\n", + program); + /* fall through */ + case 'K': + dir = isc_commandline_argument; + if (strlen(dir) == 0U) { + fatal("directory must be non-empty string"); + } + break; + case 'f': + filename = isc_commandline_argument; + break; + case 'l': + fatal("-l option (DLV lookaside) is obsolete"); + break; + case 's': + usekeyset = true; + break; + case 'T': + emitttl = true; + ttl = strtottl(isc_commandline_argument); + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case 'w': + split_width = UINT_MAX; + break; + case 'F': + /* Reserved for FIPS mode */ + FALLTHROUGH; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + rdclass = strtoclass(classname); + + if (usekeyset && filename != NULL) { + fatal("cannot use both -s and -f"); + } + + /* When not using -f, -A is implicit */ + if (filename == NULL) { + showall = true; + } + + /* Default digest type if none specified. */ + if (dtype[0] == 0) { + dtype[0] = DNS_DSDIGEST_SHA256; + } + + /* + * Use local variable arg1 so that clang can correctly analyse + * reachable paths rather than 'argc < isc_commandline_index + 1'. + */ + arg1 = argv[isc_commandline_index]; + if (arg1 == NULL && filename == NULL) { + fatal("the key file name was not specified"); + } + if (arg1 != NULL && argv[isc_commandline_index + 1] != NULL) { + fatal("extraneous arguments"); + } + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", + isc_result_totext(result)); + } + + setup_logging(mctx, &log); + + dns_rdataset_init(&rdataset); + + if (usekeyset || filename != NULL) { + if (arg1 == NULL) { + /* using file name as the zone name */ + namestr = filename; + } else { + namestr = arg1; + } + + result = initname(namestr); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize name %s", namestr); + } + + if (usekeyset) { + result = loadkeyset(dir, &rdataset); + } else { + INSIST(filename != NULL); + result = loadset(filename, &rdataset); + } + + if (result != ISC_R_SUCCESS) { + fatal("could not load DNSKEY set: %s\n", + isc_result_totext(result)); + } + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + dns_rdata_init(&rdata); + dns_rdataset_current(&rdataset, &rdata); + + if (verbose > 2) { + logkey(&rdata); + } + + emits(showall, cds, &rdata); + } + } else { + unsigned char key_buf[DST_KEY_MAXSIZE]; + + loadkey(arg1, key_buf, DST_KEY_MAXSIZE, &rdata); + + emits(showall, cds, &rdata); + } + + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + cleanup_logging(&log); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_destroy(&mctx); + + fflush(stdout); + if (ferror(stdout)) { + fprintf(stderr, "write error\n"); + return 1; + } else { + return 0; + } +} diff --git a/bin/dnssec/dnssec-dsfromkey.rst b/bin/dnssec/dnssec-dsfromkey.rst new file mode 100644 index 0000000..9ca025a --- /dev/null +++ b/bin/dnssec/dnssec-dsfromkey.rst @@ -0,0 +1,159 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-dsfromkey +.. program:: dnssec-dsfromkey +.. _man_dnssec-dsfromkey: + +dnssec-dsfromkey - DNSSEC DS RR generation tool +----------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-K** directory] {keyfile} + +:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-c** class] [**-A**] {**-f** file} [dnsname] + +:program:`dnssec-dsfromkey` [ **-1** | **-2** | **-a** alg ] [ **-C** ] [**-T** TTL] [**-v** level] [**-c** class] [**-K** directory] {**-s**} {dnsname} + +:program:`dnssec-dsfromkey` [ **-h** | **-V** ] + +Description +~~~~~~~~~~~ + +The :program:`dnssec-dsfromkey` command outputs DS (Delegation Signer) resource records +(RRs), or CDS (Child DS) RRs with the :option:`-C` option. + +By default, only KSKs are converted (keys with flags = 257). The +:option:`-A` option includes ZSKs (flags = 256). Revoked keys are never +included. + +The input keys can be specified in a number of ways: + +By default, :program:`dnssec-dsfromkey` reads a key file named in the format +``Knnnn.+aaa+iiiii.key``, as generated by :iscman:`dnssec-keygen`. + +With the :option:`-f file <-f>` option, :program:`dnssec-dsfromkey` reads keys from a zone +file or partial zone file (which can contain just the DNSKEY records). + +With the :option:`-s` option, :program:`dnssec-dsfromkey` reads a ``keyset-`` file, +as generated by :iscman:`dnssec-keygen` :option:`-C`. + +Options +~~~~~~~ + +.. option:: -1 + + This option is an abbreviation for :option:`-a SHA1 <-a>`. + +.. option:: -2 + + This option is an abbreviation for :option:`-a SHA-256 <-a>`. + +.. option:: -a algorithm + + This option specifies a digest algorithm to use when converting DNSKEY records to + DS records. This option can be repeated, so that multiple DS records + are created for each DNSKEY record. + + The algorithm must be one of SHA-1, SHA-256, or SHA-384. These values + are case-insensitive, and the hyphen may be omitted. If no algorithm + is specified, the default is SHA-256. + +.. option:: -A + + This option indicates that ZSKs are to be included when generating DS records. Without this option, only + keys which have the KSK flag set are converted to DS records and + printed. This option is only useful in :option:`-f` zone file mode. + +.. option:: -c class + + This option specifies the DNS class; the default is IN. This option is only useful in :option:`-s` keyset + or :option:`-f` zone file mode. + +.. option:: -C + + This option generates CDS records rather than DS records. + +.. option:: -f file + + This option sets zone file mode, in which the final dnsname argument of :program:`dnssec-dsfromkey` is the + DNS domain name of a zone whose master file can be read from + ``file``. If the zone name is the same as ``file``, then it may be + omitted. + + If ``file`` is ``-``, then the zone data is read from the standard + input. This makes it possible to use the output of the :iscman:`dig` + command as input, as in: + + ``dig dnskey example.com | dnssec-dsfromkey -f - example.com`` + +.. option:: -h + + This option prints usage information. + +.. option:: -K directory + + This option tells BIND 9 to look for key files or ``keyset-`` files in ``directory``. + +.. option:: -s + + This option enables keyset mode, in which the final dnsname argument from :program:`dnssec-dsfromkey` is the DNS + domain name used to locate a ``keyset-`` file. + +.. option:: -T TTL + + This option specifies the TTL of the DS records. By default the TTL is omitted. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -V + + This option prints version information. + +Example +~~~~~~~ + +To build the SHA-256 DS RR from the ``Kexample.com.+003+26160`` keyfile, +issue the following command: + +``dnssec-dsfromkey -2 Kexample.com.+003+26160`` + +The command returns something similar to: + +``example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0C5EA0B94`` + +Files +~~~~~ + +The keyfile can be designated by the key identification +``Knnnn.+aaa+iiiii`` or the full file name ``Knnnn.+aaa+iiiii.key``, as +generated by :iscman:`dnssec-keygen`. + +The keyset file name is built from the ``directory``, the string +``keyset-``, and the ``dnsname``. + +Caveat +~~~~~~ + +A keyfile error may return "file not found," even if the file exists. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, :iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, +:rfc:`3658` (DS RRs), :rfc:`4509` (SHA-256 for DS RRs), +:rfc:`6605` (SHA-384 for DS RRs), :rfc:`7344` (CDS and CDNSKEY RRs). diff --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c new file mode 100644 index 0000000..f21172a --- /dev/null +++ b/bin/dnssec/dnssec-importkey.c @@ -0,0 +1,475 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-importkey"; + +static dns_rdataclass_t rdclass; +static dns_fixedname_t fixed; +static dns_name_t *name = NULL; +static isc_mem_t *mctx = NULL; +static bool setpub = false, setdel = false; +static bool setttl = false; +static isc_stdtime_t pub = 0, del = 0; +static dns_ttl_t ttl = 0; +static isc_stdtime_t syncadd = 0, syncdel = 0; +static bool setsyncadd = false; +static bool setsyncdel = false; + +static isc_result_t +initname(char *setname) { + isc_result_t result; + isc_buffer_t buf; + + name = dns_fixedname_initname(&fixed); + + isc_buffer_init(&buf, setname, strlen(setname)); + isc_buffer_add(&buf, strlen(setname)); + result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + return result; +} + +static void +db_load_from_stream(dns_db_t *db, FILE *fp) { + isc_result_t result; + dns_rdatacallbacks_t callbacks; + + dns_rdatacallbacks_init(&callbacks); + result = dns_db_beginload(db, &callbacks); + if (result != ISC_R_SUCCESS) { + fatal("dns_db_beginload failed: %s", isc_result_totext(result)); + } + + result = dns_master_loadstream(fp, name, name, rdclass, 0, &callbacks, + mctx); + if (result != ISC_R_SUCCESS) { + fatal("can't load from input: %s", isc_result_totext(result)); + } + + result = dns_db_endload(db, &callbacks); + if (result != ISC_R_SUCCESS) { + fatal("dns_db_endload failed: %s", isc_result_totext(result)); + } +} + +static isc_result_t +loadset(const char *filename, dns_rdataset_t *rdataset) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + char setname[DNS_NAME_FORMATSIZE]; + + dns_name_format(name, setname, sizeof(setname)); + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, &db); + if (result != ISC_R_SUCCESS) { + fatal("can't create database"); + } + + if (strcmp(filename, "-") == 0) { + db_load_from_stream(db, stdin); + filename = "input"; + } else { + result = dns_db_load(db, filename, dns_masterformat_text, + DNS_MASTER_NOTTL); + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + fatal("can't load %s: %s", filename, + isc_result_totext(result)); + } + } + + result = dns_db_findnode(db, name, false, &node); + if (result != ISC_R_SUCCESS) { + fatal("can't find %s node in %s", setname, filename); + } + + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, + rdataset, NULL); + + if (result == ISC_R_NOTFOUND) { + fatal("no DNSKEY RR for %s in %s", setname, filename); + } else if (result != ISC_R_SUCCESS) { + fatal("dns_db_findrdataset"); + } + + if (node != NULL) { + dns_db_detachnode(db, &node); + } + if (db != NULL) { + dns_db_detach(&db); + } + return result; +} + +static void +loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, + dns_rdata_t *rdata) { + isc_result_t result; + dst_key_t *key = NULL; + isc_buffer_t keyb; + isc_region_t r; + + dns_rdata_init(rdata); + + isc_buffer_init(&keyb, key_buf, key_buf_size); + + result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, mctx, + &key); + if (result != ISC_R_SUCCESS) { + fatal("invalid keyfile name %s: %s", filename, + isc_result_totext(result)); + } + + if (verbose > 2) { + char keystr[DST_KEY_FORMATSIZE]; + + dst_key_format(key, keystr, sizeof(keystr)); + fprintf(stderr, "%s: %s\n", program, keystr); + } + + result = dst_key_todns(key, &keyb); + if (result != ISC_R_SUCCESS) { + fatal("can't decode key"); + } + + isc_buffer_usedregion(&keyb, &r); + dns_rdata_fromregion(rdata, dst_key_class(key), dns_rdatatype_dnskey, + &r); + + rdclass = dst_key_class(key); + + name = dns_fixedname_initname(&fixed); + dns_name_copy(dst_key_name(key), name); + + dst_key_free(&key); +} + +static void +emit(const char *dir, dns_rdata_t *rdata) { + isc_result_t result; + char keystr[DST_KEY_FORMATSIZE]; + char pubname[1024]; + char priname[1024]; + isc_buffer_t buf; + dst_key_t *key = NULL, *tmp = NULL; + + isc_buffer_init(&buf, rdata->data, rdata->length); + isc_buffer_add(&buf, rdata->length); + result = dst_key_fromdns(name, rdclass, &buf, mctx, &key); + if (result != ISC_R_SUCCESS) { + fatal("dst_key_fromdns: %s", isc_result_totext(result)); + } + + isc_buffer_init(&buf, pubname, sizeof(pubname)); + result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build public key filename: %s", + isc_result_totext(result)); + } + isc_buffer_init(&buf, priname, sizeof(priname)); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build private key filename: %s", + isc_result_totext(result)); + } + + result = dst_key_fromfile( + dst_key_name(key), dst_key_id(key), dst_key_alg(key), + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, dir, mctx, &tmp); + if (result == ISC_R_SUCCESS) { + if (dst_key_isprivate(tmp) && !dst_key_isexternal(tmp)) { + fatal("Private key already exists in %s", priname); + } + dst_key_free(&tmp); + } + + dst_key_setexternal(key, true); + if (setpub) { + dst_key_settime(key, DST_TIME_PUBLISH, pub); + } + if (setdel) { + dst_key_settime(key, DST_TIME_DELETE, del); + } + if (setsyncadd) { + dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); + } + if (setsyncdel) { + dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); + } + + if (setttl) { + dst_key_setttl(key, ttl); + } + + result = dst_key_tofile(key, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, dir); + if (result != ISC_R_SUCCESS) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + printf("%s\n", pubname); + + isc_buffer_clear(&buf); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build private key filename: %s", + isc_result_totext(result)); + } + printf("%s\n", priname); + dst_key_free(&key); +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); + fprintf(stderr, " %s options -f file [keyname]\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -f file: read key from zone file\n"); + fprintf(stderr, " -K : directory in which to store " + "the key files\n"); + fprintf(stderr, " -L ttl: set default key TTL\n"); + fprintf(stderr, " -v \n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, " -h: print usage and exit\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set/unset key " + "publication date\n"); + fprintf(stderr, " -P sync date/[+-]offset/none: set/unset " + "CDS and CDNSKEY publication date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set/unset key " + "deletion date\n"); + fprintf(stderr, " -D sync date/[+-]offset/none: set/unset " + "CDS and CDNSKEY deletion date\n"); + + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) { + char *classname = NULL; + char *filename = NULL, *dir = NULL, *namestr; + char *endp; + int ch; + isc_result_t result; + isc_log_t *log = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata; + isc_stdtime_t now = isc_stdtime_now(); + + dns_rdata_init(&rdata); + + if (argc == 1) { + usage(); + } + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + +#define CMDLINE_FLAGS "D:f:hK:L:P:v:V" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'D': + /* -Dsync ? */ + if (isoptarg("sync", argv, usage)) { + if (setsyncdel) { + fatal("-D sync specified more than " + "once"); + } + + syncdel = strtotime(isc_commandline_argument, + now, now, &setsyncdel); + break; + } + /* -Ddnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setdel) { + fatal("-D specified more than once"); + } + + del = strtotime(isc_commandline_argument, now, now, + &setdel); + break; + case 'K': + dir = isc_commandline_argument; + if (strlen(dir) == 0U) { + fatal("directory must be non-empty string"); + } + break; + case 'L': + ttl = strtottl(isc_commandline_argument); + setttl = true; + break; + case 'P': + /* -Psync ? */ + if (isoptarg("sync", argv, usage)) { + if (setsyncadd) { + fatal("-P sync specified more than " + "once"); + } + + syncadd = strtotime(isc_commandline_argument, + now, now, &setsyncadd); + break; + } + /* -Pdnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setpub) { + fatal("-P specified more than once"); + } + + pub = strtotime(isc_commandline_argument, now, now, + &setpub); + break; + case 'f': + filename = isc_commandline_argument; + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + rdclass = strtoclass(classname); + + if (argc < isc_commandline_index + 1 && filename == NULL) { + fatal("the key file name was not specified"); + } + if (argc > isc_commandline_index + 1) { + fatal("extraneous arguments"); + } + + result = dst_lib_init(mctx, NULL); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", + isc_result_totext(result)); + } + + setup_logging(mctx, &log); + + dns_rdataset_init(&rdataset); + + if (filename != NULL) { + if (argc < isc_commandline_index + 1) { + /* using filename as zone name */ + namestr = filename; + } else { + namestr = argv[isc_commandline_index]; + } + + result = initname(namestr); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize name %s", namestr); + } + + result = loadset(filename, &rdataset); + + if (result != ISC_R_SUCCESS) { + fatal("could not load DNSKEY set: %s\n", + isc_result_totext(result)); + } + + for (result = dns_rdataset_first(&rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + dns_rdata_init(&rdata); + dns_rdataset_current(&rdataset, &rdata); + emit(dir, &rdata); + } + } else { + unsigned char key_buf[DST_KEY_MAXSIZE]; + + loadkey(argv[isc_commandline_index], key_buf, DST_KEY_MAXSIZE, + &rdata); + + emit(dir, &rdata); + } + + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + cleanup_logging(&log); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_destroy(&mctx); + + fflush(stdout); + if (ferror(stdout)) { + fprintf(stderr, "write error\n"); + return 1; + } else { + return 0; + } +} diff --git a/bin/dnssec/dnssec-importkey.rst b/bin/dnssec/dnssec-importkey.rst new file mode 100644 index 0000000..8f6a6b3 --- /dev/null +++ b/bin/dnssec/dnssec-importkey.rst @@ -0,0 +1,142 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-importkey +.. program:: dnssec-importkey +.. _man_dnssec-importkey: + +dnssec-importkey - import DNSKEY records from external systems so they can be managed +------------------------------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-importkey` [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** sync date/offset] [**-D** date/offset] [**-D** sync date/offset] [**-h**] [**-v** level] [**-V**] {keyfile} + +:program:`dnssec-importkey` {**-f** filename} [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** sync date/offset] [**-D** date/offset] [**-D** sync date/offset] [**-h**] [**-v** level] [**-V**] [dnsname] + +Description +~~~~~~~~~~~ + +:program:`dnssec-importkey` reads a public DNSKEY record and generates a pair +of .key/.private files. The DNSKEY record may be read from an +existing .key file, in which case a corresponding .private file is +generated, or it may be read from any other file or from the standard +input, in which case both .key and .private files are generated. + +The newly created .private file does *not* contain private key data, and +cannot be used for signing. However, having a .private file makes it +possible to set publication (:option:`-P`) and deletion (:option:`-D`) times for the +key, which means the public key can be added to and removed from the +DNSKEY RRset on schedule even if the true private key is stored offline. + +Options +~~~~~~~ + +.. option:: -f filename + + This option indicates the zone file mode. Instead of a public keyfile name, the argument is the + DNS domain name of a zone master file, which can be read from + ``filename``. If the domain name is the same as ``filename``, then it may be + omitted. + + If ``filename`` is set to ``"-"``, then the zone data is read from the + standard input. + +.. option:: -K directory + + This option sets the directory in which the key files are to reside. + +.. option:: -L ttl + + This option sets the default TTL to use for this key when it is converted into a + DNSKEY RR. This is the TTL used when the key is imported into a zone, + unless there was already a DNSKEY RRset in + place, in which case the existing TTL takes precedence. Setting the default TTL to ``0`` or ``none`` + removes it from the key. + +.. option:: -h + + This option emits a usage message and exits. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -V + + This option prints version information. + +Timing Options +~~~~~~~~~~~~~~ + +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by ``+`` or ``-`` and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes ``y``, ``mo``, ``w``, +``d``, ``h``, or ``mi``, so that it is computed in years (defined as +365 24-hour days, ignoring leap years), months (defined as 30 24-hour +days), weeks, days, hours, or minutes, respectively. Without a suffix, +the offset is computed in seconds. + +To explicitly prevent a date from being set, use ``none``, ``never``, +or ``unset``. + +All these formats are case-insensitive. + +.. option:: -P date/offset + + This option sets the date on which a key is to be published to the zone. After + that date, the key is included in the zone but is not used + to sign it. + + .. program:: dnssec-importkey -P + .. option:: sync date/offset + + This option sets the date on which CDS and CDNSKEY records that match this key + are to be published to the zone. + +.. program:: dnssec-importkey + +.. option:: -D date/offset + + This option sets the date on which the key is to be deleted. After that date, the + key is no longer included in the zone. (However, it may remain in the key + repository.) + + .. program:: dnssec-importkey -D + .. option:: sync date/offset + + This option sets the date on which the CDS and CDNSKEY records that match this + key are to be deleted. + +.. program:: dnssec-importkey + + +Files +~~~~~ + +A keyfile can be designed by the key identification ``Knnnn.+aaa+iiiii`` +or the full file name ``Knnnn.+aaa+iiiii.key``, as generated by +:iscman:`dnssec-keygen`. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, :iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, +:rfc:`5011`. diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c new file mode 100644 index 0000000..33d576c --- /dev/null +++ b/bin/dnssec/dnssec-keyfromlabel.c @@ -0,0 +1,759 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dnssectool.h" + +#define MAX_RSA 4096 /* should be long enough... */ + +const char *program = "dnssec-keyfromlabel"; + +static uint16_t tag_min = 0, tag_max = 0xffff; + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s -l label [options] name\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "Required options:\n"); + fprintf(stderr, " -l label: label of the key pair\n"); + fprintf(stderr, " name: owner of the key\n"); + fprintf(stderr, "Other options:\n"); + fprintf(stderr, " -a algorithm: \n" + " RSASHA1 |\n" + " NSEC3RSASHA1 |\n" + " RSASHA256 | RSASHA512 |\n" + " ECDSAP256SHA256 | ECDSAP384SHA384 |\n" + " ED25519 | ED448\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -c class (default: IN)\n"); + fprintf(stderr, " -E :\n"); + fprintf(stderr, " name of an OpenSSL engine to use\n"); + fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); + fprintf(stderr, " -K directory: directory in which to place " + "key files\n"); + fprintf(stderr, " -k: generate a TYPE=KEY key\n"); + fprintf(stderr, " -L ttl: default key TTL\n"); + fprintf(stderr, " -M :: allowed Key ID range\n"); + fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | " + "OTHER\n"); + fprintf(stderr, " (DNSKEY generation defaults to ZONE\n"); + fprintf(stderr, " -p protocol: default: 3 [dnssec]\n"); + fprintf(stderr, " -t type: " + "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " + "(default: AUTHCONF)\n"); + fprintf(stderr, " -y: permit keys that might collide\n"); + fprintf(stderr, " -v verbose level\n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, "Date options:\n"); + fprintf(stderr, " -P date/[+-]offset: set key publication date\n"); + fprintf(stderr, " -P sync date/[+-]offset: set CDS and CDNSKEY " + "publication date\n"); + fprintf(stderr, " -A date/[+-]offset: set key activation date\n"); + fprintf(stderr, " -R date/[+-]offset: set key revocation date\n"); + fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset: set key deletion date\n"); + fprintf(stderr, " -D sync date/[+-]offset: set CDS and CDNSKEY " + "deletion date\n"); + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting" + " all dates\n"); + fprintf(stderr, " -S : generate a successor to an existing " + "key\n"); + fprintf(stderr, " -i : prepublication interval for " + "successor key " + "(default: 30 days)\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) { + char *algname = NULL, *freeit = NULL; + char *nametype = NULL, *type = NULL; + const char *directory = NULL; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; + const char *engine = NULL; + char *classname = NULL; + char *endp; + dst_key_t *key = NULL; + dns_fixedname_t fname; + dns_name_t *name; + uint16_t flags = 0, kskflag = 0, revflag = 0; + dns_secalg_t alg; + bool oldstyle = false; + isc_mem_t *mctx = NULL; + int ch; + int protocol = -1, signatory = 0; + isc_result_t ret; + isc_textregion_t r; + char filename[255]; + isc_buffer_t buf; + isc_log_t *log = NULL; + dns_rdataclass_t rdclass; + int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; + char *label = NULL; + dns_ttl_t ttl = 0; + isc_stdtime_t publish = 0, activate = 0, revoke = 0; + isc_stdtime_t inactive = 0, deltime = 0; + int prepub = -1; + bool setpub = false, setact = false; + bool setrev = false, setinact = false; + bool setdel = false, setttl = false; + bool unsetpub = false, unsetact = false; + bool unsetrev = false, unsetinact = false; + bool unsetdel = false; + bool genonly = false; + bool use_nsec3 = false; + bool avoid_collisions = true; + bool exact; + unsigned char c; + isc_stdtime_t syncadd = 0, syncdel = 0; + bool unsetsyncadd = false, setsyncadd = false; + bool unsetsyncdel = false, setsyncdel = false; + isc_stdtime_t now = isc_stdtime_now(); + + if (argc == 1) { + usage(); + } + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + +#define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:M:n:P:p:R:S:t:v:Vy" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '3': + use_nsec3 = true; + break; + case 'a': + algname = isc_commandline_argument; + break; + case 'C': + oldstyle = true; + break; + case 'c': + classname = isc_commandline_argument; + break; + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') { + kskflag = DNS_KEYFLAG_KSK; + } else if (toupper(c) == 'R') { + revflag = DNS_KEYFLAG_REVOKE; + } else { + fatal("unknown flag '%s'", + isc_commandline_argument); + } + break; + case 'K': + directory = isc_commandline_argument; + ret = try_dir(directory); + if (ret != ISC_R_SUCCESS) { + fatal("cannot open directory %s: %s", directory, + isc_result_totext(ret)); + } + break; + case 'k': + options |= DST_TYPE_KEY; + break; + case 'L': + ttl = strtottl(isc_commandline_argument); + setttl = true; + break; + case 'l': + label = isc_mem_strdup(mctx, isc_commandline_argument); + break; + case 'M': { + unsigned long ul; + tag_min = ul = strtoul(isc_commandline_argument, &endp, + 10); + if (*endp != ':' || ul > 0xffff) { + fatal("-M range invalid"); + } + tag_max = ul = strtoul(endp + 1, &endp, 10); + if (*endp != '\0' || ul > 0xffff || tag_max <= tag_min) + { + fatal("-M range invalid"); + } + break; + } + case 'n': + nametype = isc_commandline_argument; + break; + case 'p': + protocol = strtol(isc_commandline_argument, &endp, 10); + if (*endp != '\0' || protocol < 0 || protocol > 255) { + fatal("-p must be followed by a number " + "[0..255]"); + } + break; + case 't': + type = isc_commandline_argument; + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case 'y': + avoid_collisions = false; + break; + case 'G': + genonly = true; + break; + case 'P': + /* -Psync ? */ + if (isoptarg("sync", argv, usage)) { + if (unsetsyncadd || setsyncadd) { + fatal("-P sync specified more than " + "once"); + } + + syncadd = strtotime(isc_commandline_argument, + now, now, &setsyncadd); + unsetsyncadd = !setsyncadd; + break; + } + /* -Pdnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setpub || unsetpub) { + fatal("-P specified more than once"); + } + + publish = strtotime(isc_commandline_argument, now, now, + &setpub); + unsetpub = !setpub; + break; + case 'A': + if (setact || unsetact) { + fatal("-A specified more than once"); + } + + activate = strtotime(isc_commandline_argument, now, now, + &setact); + unsetact = !setact; + break; + case 'R': + if (setrev || unsetrev) { + fatal("-R specified more than once"); + } + + revoke = strtotime(isc_commandline_argument, now, now, + &setrev); + unsetrev = !setrev; + break; + case 'I': + if (setinact || unsetinact) { + fatal("-I specified more than once"); + } + + inactive = strtotime(isc_commandline_argument, now, now, + &setinact); + unsetinact = !setinact; + break; + case 'D': + /* -Dsync ? */ + if (isoptarg("sync", argv, usage)) { + if (unsetsyncdel || setsyncdel) { + fatal("-D sync specified more than " + "once"); + } + + syncdel = strtotime(isc_commandline_argument, + now, now, &setsyncdel); + unsetsyncdel = !setsyncdel; + break; + } + /* -Ddnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setdel || unsetdel) { + fatal("-D specified more than once"); + } + + deltime = strtotime(isc_commandline_argument, now, now, + &setdel); + unsetdel = !setdel; + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + break; + case 'F': + /* Reserved for FIPS mode */ + FALLTHROUGH; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + ret = dst_lib_init(mctx, engine); + if (ret != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", isc_result_totext(ret)); + } + + setup_logging(mctx, &log); + + if (predecessor == NULL) { + if (label == NULL) { + fatal("the key label was not specified"); + } + if (argc < isc_commandline_index + 1) { + fatal("the key name was not specified"); + } + if (argc > isc_commandline_index + 1) { + fatal("extraneous arguments"); + } + + name = dns_fixedname_initname(&fname); + isc_buffer_init(&buf, argv[isc_commandline_index], + strlen(argv[isc_commandline_index])); + isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + if (ret != ISC_R_SUCCESS) { + fatal("invalid key name %s: %s", + argv[isc_commandline_index], + isc_result_totext(ret)); + } + + if (strchr(label, ':') == NULL) { + char *l; + int len; + + len = strlen(label) + 8; + l = isc_mem_allocate(mctx, len); + snprintf(l, len, "pkcs11:%s", label); + isc_mem_free(mctx, label); + label = l; + } + + if (algname == NULL) { + fatal("no algorithm specified"); + } + + r.base = algname; + r.length = strlen(algname); + ret = dns_secalg_fromtext(&alg, &r); + if (ret != ISC_R_SUCCESS) { + fatal("unknown algorithm %s", algname); + } + + if (use_nsec3) { + switch (alg) { + case DST_ALG_RSASHA1: + alg = DST_ALG_NSEC3RSASHA1; + break; + case DST_ALG_NSEC3RSASHA1: + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + case DST_ALG_ECDSA256: + case DST_ALG_ECDSA384: + case DST_ALG_ED25519: + case DST_ALG_ED448: + break; + default: + fatal("%s is incompatible with NSEC3; " + "do not use the -3 option", + algname); + } + } + + if (type != NULL && (options & DST_TYPE_KEY) != 0) { + if (strcasecmp(type, "NOAUTH") == 0) { + flags |= DNS_KEYTYPE_NOAUTH; + } else if (strcasecmp(type, "NOCONF") == 0) { + flags |= DNS_KEYTYPE_NOCONF; + } else if (strcasecmp(type, "NOAUTHCONF") == 0) { + flags |= (DNS_KEYTYPE_NOAUTH | + DNS_KEYTYPE_NOCONF); + } else if (strcasecmp(type, "AUTHCONF") == 0) { + /* nothing */ + } else { + fatal("invalid type %s", type); + } + } + + if (!oldstyle && prepub > 0) { + if (setpub && setact && (activate - prepub) < publish) { + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + } + + if (!setpub && !setact) { + setpub = setact = true; + publish = now; + activate = now + prepub; + } else if (setpub && !setact) { + setact = true; + activate = publish + prepub; + } else if (setact && !setpub) { + setpub = true; + publish = activate - prepub; + } + + if ((activate - prepub) < now) { + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } + } else { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (prepub == -1) { + prepub = (30 * 86400); + } + + if (algname != NULL) { + fatal("-S and -a cannot be used together"); + } + if (nametype != NULL) { + fatal("-S and -n cannot be used together"); + } + if (type != NULL) { + fatal("-S and -t cannot be used together"); + } + if (setpub || unsetpub) { + fatal("-S and -P cannot be used together"); + } + if (setact || unsetact) { + fatal("-S and -A cannot be used together"); + } + if (use_nsec3) { + fatal("-S and -3 cannot be used together"); + } + if (oldstyle) { + fatal("-S and -C cannot be used together"); + } + if (genonly) { + fatal("-S and -G cannot be used together"); + } + + ret = dst_key_fromnamedfile(predecessor, directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + mctx, &prevkey); + if (ret != ISC_R_SUCCESS) { + fatal("Invalid keyfile %s: %s", predecessor, + isc_result_totext(ret)); + } + if (!dst_key_isprivate(prevkey)) { + fatal("%s is not a private key", predecessor); + } + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { + fatal("Key %s has incompatible format version %d.%d\n\t" + "It is not possible to generate a successor key.", + keystr, major, minor); + } + + ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (ret != ISC_R_SUCCESS) { + fatal("Key %s has no activation date.\n\t" + "You must use dnssec-settime -A to set one " + "before generating a successor.", + keystr); + } + + ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); + if (ret != ISC_R_SUCCESS) { + fatal("Key %s has no inactivation date.\n\t" + "You must use dnssec-settime -I to set one " + "before generating a successor.", + keystr); + } + + publish = activate - prepub; + if (publish < now) { + fatal("Key %s becomes inactive\n\t" + "sooner than the prepublication period " + "for the new key ends.\n\t" + "Either change the inactivation date with " + "dnssec-settime -I,\n\t" + "or use the -i option to set a shorter " + "prepublication interval.", + keystr); + } + + ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (ret != ISC_R_SUCCESS) { + fprintf(stderr, + "%s: WARNING: Key %s has no removal " + "date;\n\t it will remain in the zone " + "indefinitely after rollover.\n\t " + "You can use dnssec-settime -D to " + "change this.\n", + program, keystr); + } + + setpub = setact = true; + } + + if (nametype == NULL) { + if ((options & DST_TYPE_KEY) != 0) { /* KEY */ + fatal("no nametype specified"); + } + flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ + } else if (strcasecmp(nametype, "zone") == 0) { + flags |= DNS_KEYOWNER_ZONE; + } else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ + if (strcasecmp(nametype, "host") == 0 || + strcasecmp(nametype, "entity") == 0) + { + flags |= DNS_KEYOWNER_ENTITY; + } else if (strcasecmp(nametype, "user") == 0) { + /* no owner flags */ + } else { + fatal("invalid KEY nametype %s", nametype); + } + } else if (strcasecmp(nametype, "other") != 0) { /* DNSKEY */ + fatal("invalid DNSKEY nametype %s", nametype); + } + + rdclass = strtoclass(classname); + + if (directory == NULL) { + directory = "."; + } + + if ((options & DST_TYPE_KEY) != 0) { /* KEY */ + flags |= signatory; + } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + flags |= kskflag; + flags |= revflag; + } + + if (protocol == -1) { + protocol = DNS_KEYPROTO_DNSSEC; + } else if ((options & DST_TYPE_KEY) == 0 && + protocol != DNS_KEYPROTO_DNSSEC) + { + fatal("invalid DNSKEY protocol: %d", protocol); + } + + isc_buffer_init(&buf, filename, sizeof(filename) - 1); + + /* associate the key */ + ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass, engine, + label, NULL, mctx, &key); + + if (ret != ISC_R_SUCCESS) { + char namestr[DNS_NAME_FORMATSIZE]; + char algstr[DNS_SECALG_FORMATSIZE]; + dns_name_format(name, namestr, sizeof(namestr)); + dns_secalg_format(alg, algstr, sizeof(algstr)); + fatal("failed to get key %s/%s: %s", namestr, algstr, + isc_result_totext(ret)); + UNREACHABLE(); + exit(EXIT_FAILURE); + } + + /* + * Set key timing metadata (unless using -C) + * + * Publish and activation dates are set to "now" by default, but + * can be overridden. Creation date is always set to "now". + */ + if (!oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, now); + + if (genonly && (setpub || setact)) { + fatal("cannot use -G together with -P or -A options"); + } + + if (setpub) { + dst_key_settime(key, DST_TIME_PUBLISH, publish); + } else if (setact) { + dst_key_settime(key, DST_TIME_PUBLISH, activate); + } else if (!genonly && !unsetpub) { + dst_key_settime(key, DST_TIME_PUBLISH, now); + } + + if (setact) { + dst_key_settime(key, DST_TIME_ACTIVATE, activate); + } else if (!genonly && !unsetact) { + dst_key_settime(key, DST_TIME_ACTIVATE, now); + } + + if (setrev) { + if (kskflag == 0) { + fprintf(stderr, + "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + } + dst_key_settime(key, DST_TIME_REVOKE, revoke); + } + + if (setinact) { + dst_key_settime(key, DST_TIME_INACTIVE, inactive); + } + + if (setdel) { + dst_key_settime(key, DST_TIME_DELETE, deltime); + } + if (setsyncadd) { + dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); + } + if (setsyncdel) { + dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); + } + } else { + if (setpub || setact || setrev || setinact || setdel || + unsetpub || unsetact || unsetrev || unsetinact || + unsetdel || genonly || setsyncadd || setsyncdel) + { + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + } + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* Set default key TTL */ + if (setttl) { + dst_key_setttl(key, ttl); + } + + /* + * Do not overwrite an existing key. Warn LOUDLY if there + * is a risk of ID collision due to this key or another key + * being revoked. + */ + if (key_collision(key, name, directory, mctx, tag_min, tag_max, &exact)) + { + isc_buffer_clear(&buf); + ret = dst_key_buildfilename(key, 0, directory, &buf); + if (ret != ISC_R_SUCCESS) { + fatal("dst_key_buildfilename returned: %s\n", + isc_result_totext(ret)); + } + if (exact) { + fatal("%s: %s already exists\n", program, filename); + } + + if (avoid_collisions) { + fatal("%s: %s could collide with another key upon " + "revokation\n", + program, filename); + } + + fprintf(stderr, + "%s: WARNING: Key %s could collide with " + "another key upon revokation. If you plan " + "to revoke keys, destroy this key and " + "generate a different one.\n", + program, filename); + } + + ret = dst_key_tofile(key, options, directory); + if (ret != ISC_R_SUCCESS) { + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); + fatal("failed to write key %s: %s\n", keystr, + isc_result_totext(ret)); + } + + isc_buffer_clear(&buf); + ret = dst_key_buildfilename(key, 0, NULL, &buf); + if (ret != ISC_R_SUCCESS) { + fatal("dst_key_buildfilename returned: %s\n", + isc_result_totext(ret)); + } + printf("%s\n", filename); + dst_key_free(&key); + if (prevkey != NULL) { + dst_key_free(&prevkey); + } + + cleanup_logging(&log); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_free(mctx, label); + isc_mem_destroy(&mctx); + + if (freeit != NULL) { + free(freeit); + } + + return 0; +} diff --git a/bin/dnssec/dnssec-keyfromlabel.rst b/bin/dnssec/dnssec-keyfromlabel.rst new file mode 100644 index 0000000..ea5164d --- /dev/null +++ b/bin/dnssec/dnssec-keyfromlabel.rst @@ -0,0 +1,301 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-keyfromlabel +.. program:: dnssec-keyfromlabel +.. _man_dnssec-keyfromlabel: + +dnssec-keyfromlabel - DNSSEC key generation tool +------------------------------------------------ + +Synopsis +~~~~~~~~ + +:program:`dnssec-keyfromlabel` {**-l** label} [**-3**] [**-a** algorithm] [**-A** date/offset] [**-c** class] [**-D** date/offset] [**-D** sync date/offset] [**-E** engine] [**-f** flag] [**-G**] [**-I** date/offset] [**-i** interval] [**-k**] [**-K** directory] [**-L** ttl] [**-M** tag_min:tag_max] [**-n** nametype] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-R** date/offset] [**-S** key] [**-t** type] [**-v** level] [**-V**] [**-y**] {name} + +Description +~~~~~~~~~~~ + +:program:`dnssec-keyfromlabel` generates a pair of key files that reference a +key object stored in a cryptographic hardware service module (HSM). The +private key file can be used for DNSSEC signing of zone data as if it +were a conventional signing key created by :iscman:`dnssec-keygen`, but the +key material is stored within the HSM and the actual signing takes +place there. + +The ``name`` of the key is specified on the command line. This must +match the name of the zone for which the key is being generated. + +Options +~~~~~~~ + +.. option:: -a algorithm + + This option selects the cryptographic algorithm. The value of ``algorithm`` must + be one of RSASHA1, NSEC3RSASHA1, RSASHA256, RSASHA512, + ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448. + + These values are case-insensitive. In some cases, abbreviations are + supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for + ECDSAP384SHA384. If RSASHA1 is specified along with the :option:`-3` + option, then NSEC3RSASHA1 is used instead. + + This option is mandatory except when using the + :option:`-S` option, which copies the algorithm from the predecessory key. + + .. versionchanged:: 9.12.0 + The default value RSASHA1 for newly generated keys was removed. + +.. option:: -3 + + This option uses an NSEC3-capable algorithm to generate a DNSSEC key. If this + option is used with an algorithm that has both NSEC and NSEC3 + versions, then the NSEC3 version is used; for example, + ``dnssec-keygen -3a RSASHA1`` specifies the NSEC3RSASHA1 algorithm. + +.. option:: -E engine + + This option specifies the cryptographic hardware to use. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -l label + + This option specifies the label for a key pair in the crypto hardware. + + When BIND 9 is built with OpenSSL-based PKCS#11 support, the label is + an arbitrary string that identifies a particular key. It may be + preceded by an optional OpenSSL engine name, followed by a colon, as + in ``pkcs11:keylabel``. + +.. option:: -n nametype + + This option specifies the owner type of the key. The value of ``nametype`` must + either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY + (for a key associated with a host (KEY)), USER (for a key associated + with a user (KEY)), or OTHER (DNSKEY). These values are + case-insensitive. + +.. option:: -C + + This option enables compatibility mode, which generates an old-style key, without any metadata. + By default, :program:`dnssec-keyfromlabel` includes the key's creation + date in the metadata stored with the private key; other dates may + be set there as well, including publication date, activation date, etc. Keys + that include this data may be incompatible with older versions of + BIND; the :option:`-C` option suppresses them. + +.. option:: -c class + + This option indicates that the DNS record containing the key should have the + specified class. If not specified, class IN is used. + +.. option:: -f flag + + This option sets the specified flag in the ``flag`` field of the KEY/DNSKEY record. + The only recognized flags are KSK (Key-Signing Key) and REVOKE. + +.. option:: -G + + This option generates a key, but does not publish it or sign with it. This option is + incompatible with :option:`-P` and :option:`-A`. + +.. option:: -h + + This option prints a short summary of the options and arguments to + :program:`dnssec-keyfromlabel`. + +.. option:: -K directory + + This option sets the directory in which the key files are to be written. + +.. option:: -k + + This option generates KEY records rather than DNSKEY records. + +.. option:: -L ttl + + This option sets the default TTL to use for this key when it is converted into a + DNSKEY RR. This is the TTL used when the key is imported into a zone, + unless there was already a DNSKEY RRset in + place, in which case the existing TTL would take precedence. Setting + the default TTL to ``0`` or ``none`` removes it. + +.. option:: -M tag_min:tag_max + + This option sets the range of key tag values + that ``dnssec-keyfromlabel`` will accept. If the key tag of the new + key or the key tag of the revoked version of the new key is + outside this range, the new key will be rejected. This is + designed to be used when generating keys in a multi-signer + scenario, where each operator is given a range of key tags to + prevent collisions among different operators. The valid + values for ``tag_min`` and ``tag_max`` are [0..65535]. The + default allows all key tag values to be accepted. + +.. option:: -p protocol + + This option sets the protocol value for the key. The protocol is a number between + 0 and 255. The default is 3 (DNSSEC). Other possible values for this + argument are listed in :rfc:`2535` and its successors. + +.. option:: -S key + + This option generates a key as an explicit successor to an existing key. The name, + algorithm, size, and type of the key are set to match the + predecessor. The activation date of the new key is set to the + inactivation date of the existing one. The publication date is + set to the activation date minus the prepublication interval, which + defaults to 30 days. + +.. option:: -t type + + This option indicates the type of the key. ``type`` must be one of AUTHCONF, + NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers + to the ability to authenticate data, and CONF to the ability to encrypt + data. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -V + + This option prints version information. + +.. option:: -y + + This option allows DNSSEC key files to be generated even if the key ID would + collide with that of an existing key, in the event of either key + being revoked. (This is only safe to enable if + :rfc:`5011` trust anchor maintenance is not used with either of the keys + involved.) + +Timing Options +~~~~~~~~~~~~~~ + +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by ``+`` or ``-`` and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes ``y``, ``mo``, ``w``, +``d``, ``h``, or ``mi``, so that it is computed in years (defined as +365 24-hour days, ignoring leap years), months (defined as 30 24-hour +days), weeks, days, hours, or minutes, respectively. Without a suffix, +the offset is computed in seconds. + +To explicitly prevent a date from being set, use ``none``, ``never``, +or ``unset``. + +All these formats are case-insensitive. + +.. option:: -P date/offset + + This option sets the date on which a key is to be published to the zone. After + that date, the key is included in the zone but is not used + to sign it. If not set, and if the :option:`-G` option has not been used, the + default is the current date. + + .. program:: dnssec-keyfromlabel -P + .. option:: sync date/offset + + This option sets the date on which CDS and CDNSKEY records that match this key + are to be published to the zone. + +.. program:: dnssec-keyfromlabel + +.. option:: -A date/offset + + This option sets the date on which the key is to be activated. After that date, + the key is included in the zone and used to sign it. If not set, + and if the :option:`-G` option has not been used, the default is the current date. + +.. option:: -R date/offset + + This option sets the date on which the key is to be revoked. After that date, the + key is flagged as revoked. It is included in the zone and + is used to sign it. + +.. option:: -I date/offset + + This option sets the date on which the key is to be retired. After that date, the + key is still included in the zone, but it is not used to + sign it. + +.. option:: -D date/offset + + This option sets the date on which the key is to be deleted. After that date, the + key is no longer included in the zone. (However, it may remain in the key + repository.) + + .. program:: dnssec-keyfromlabel -D + .. option:: sync date/offset + + This option sets the date on which the CDS and CDNSKEY records that match this + key are to be deleted. + +.. program:: dnssec-keyfromlabel + +.. option:: -i interval + + This option sets the prepublication interval for a key. If set, then the + publication and activation dates must be separated by at least this + much time. If the activation date is specified but the publication + date is not, the publication date defaults to this much time + before the activation date; conversely, if the publication date is + specified but not the activation date, activation is set to + this much time after publication. + + If the key is being created as an explicit successor to another key, + then the default prepublication interval is 30 days; otherwise it is + zero. + + As with date offsets, if the argument is followed by one of the + suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is + measured in years, months, weeks, days, hours, or minutes, + respectively. Without a suffix, the interval is measured in seconds. + +Generated Key Files +~~~~~~~~~~~~~~~~~~~ + +When :program:`dnssec-keyfromlabel` completes successfully, it prints a string +of the form ``Knnnn.+aaa+iiiii`` to the standard output. This is an +identification string for the key files it has generated. + +- ``nnnn`` is the key name. + +- ``aaa`` is the numeric representation of the algorithm. + +- ``iiiii`` is the key identifier (or footprint). + +:program:`dnssec-keyfromlabel` creates two files, with names based on the +printed string. ``Knnnn.+aaa+iiiii.key`` contains the public key, and +``Knnnn.+aaa+iiiii.private`` contains the private key. + +The ``.key`` file contains a DNS KEY record that can be inserted into a +zone file (directly or with an $INCLUDE statement). + +The ``.private`` file contains algorithm-specific fields. For obvious +security reasons, this file does not have general read permission. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, :iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, +:rfc:`4034`, :rfc:`7512`. diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c new file mode 100644 index 0000000..1b1be2c --- /dev/null +++ b/bin/dnssec/dnssec-keygen.c @@ -0,0 +1,1336 @@ +/* + * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + * + * Portions Copyright (C) Network Associates, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*! \file */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 +#include +#include +#endif + +#include "dnssectool.h" + +const char *program = "dnssec-keygen"; + +/* + * These are are set here for backwards compatibility. They are + * raised to 2048 in FIPS mode. + */ +static int min_rsa = 1024; +static int min_dh = 128; + +isc_log_t *lctx = NULL; + +noreturn static void +usage(void); + +static void +progress(int p); + +struct keygen_ctx { + const char *predecessor; + const char *policy; + const char *configfile; + const char *directory; + dns_keystore_t *keystore; + char *algname; + char *nametype; + char *type; + int protocol; + int size; + uint16_t tag_min; + uint16_t tag_max; + int signatory; + dns_rdataclass_t rdclass; + int options; + int dbits; + dns_ttl_t ttl; + bool wantzsk; + bool wantksk; + bool wantrev; + dns_secalg_t alg; + /* timing data */ + int prepub; + isc_stdtime_t now; + isc_stdtime_t publish; + isc_stdtime_t activate; + isc_stdtime_t inactive; + isc_stdtime_t revokekey; + isc_stdtime_t deltime; + isc_stdtime_t syncadd; + isc_stdtime_t syncdel; + bool setpub; + bool setact; + bool setinact; + bool setrev; + bool setdel; + bool setsyncadd; + bool setsyncdel; + bool unsetpub; + bool unsetact; + bool unsetinact; + bool unsetrev; + bool unsetdel; + /* how to generate the key */ + bool setttl; + bool use_nsec3; + bool genonly; + bool showprogress; + bool quiet; + bool oldstyle; + /* state */ + time_t lifetime; + bool ksk; + bool zsk; +}; + +typedef struct keygen_ctx keygen_ctx_t; + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] name\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, " name: owner of the key\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -K : write keys into directory\n"); + fprintf(stderr, " -k : generate keys for dnssec-policy\n"); + fprintf(stderr, " -l : configuration file with dnssec-policy " + "statement\n"); + fprintf(stderr, " -a :\n"); + if (!isc_fips_mode()) { + fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n"); + } + fprintf(stderr, " RSASHA256 | RSASHA512 |\n"); + fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n"); + fprintf(stderr, " ED25519 | ED448\n"); + fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); + fprintf(stderr, " -b :\n"); + if (!isc_fips_mode()) { + fprintf(stderr, " RSASHA1:\t[%d..%d]\n", min_rsa, + MAX_RSA); + fprintf(stderr, " NSEC3RSASHA1:\t[%d..%d]\n", min_rsa, + MAX_RSA); + } + fprintf(stderr, " RSASHA256:\t[%d..%d]\n", min_rsa, MAX_RSA); + fprintf(stderr, " RSASHA512:\t[%d..%d]\n", min_rsa, MAX_RSA); + fprintf(stderr, " ECDSAP256SHA256:\tignored\n"); + fprintf(stderr, " ECDSAP384SHA384:\tignored\n"); + fprintf(stderr, " ED25519:\tignored\n"); + fprintf(stderr, " ED448:\tignored\n"); + fprintf(stderr, " (key size defaults are set according to\n" + " algorithm and usage (ZSK or KSK)\n"); + fprintf(stderr, " -n : ZONE | HOST | ENTITY | " + "USER | OTHER\n"); + fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); + fprintf(stderr, " -c : (default: IN)\n"); + fprintf(stderr, " -d (0 => max, default)\n"); + fprintf(stderr, " -E :\n"); + fprintf(stderr, " name of an OpenSSL engine to use\n"); + fprintf(stderr, " -f : ZSK | KSK | REVOKE\n"); + fprintf(stderr, " -F: FIPS mode\n"); + fprintf(stderr, " -L : default key TTL\n"); + fprintf(stderr, " -M :: allowed Key ID range\n"); + fprintf(stderr, " -p : (default: 3 [dnssec])\n"); + fprintf(stderr, " -s : strength value this key signs DNS " + "records with (default: 0)\n"); + fprintf(stderr, " -T : DNSKEY | KEY (default: DNSKEY; " + "use KEY for SIG(0))\n"); + fprintf(stderr, " -t : " + "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " + "(default: AUTHCONF)\n"); + fprintf(stderr, " -h: print usage and exit\n"); + fprintf(stderr, " -m :\n"); + fprintf(stderr, " usage | trace | record\n"); + fprintf(stderr, " -v : set verbosity level (0 - 10)\n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set key publication date " + "(default: now)\n"); + fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY " + "publication date\n"); + fprintf(stderr, " -A date/[+-]offset/none: set key activation date " + "(default: now)\n"); + fprintf(stderr, " -R date/[+-]offset/none: set key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n"); + fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY " + "deletion date\n"); + + fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); + fprintf(stderr, " -C: generate a backward-compatible key, omitting " + "all dates\n"); + fprintf(stderr, " -S : generate a successor to an existing " + "key\n"); + fprintf(stderr, " -i : prepublication interval for " + "successor key " + "(default: 30 days)\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit(EXIT_FAILURE); +} + +static void +progress(int p) { + char c = '*'; + + switch (p) { + case 0: + c = '.'; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + break; + case 3: + c = ' '; + break; + default: + break; + } + (void)putc(c, stderr); + (void)fflush(stderr); +} + +static void +keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { + char filename[255]; + char algstr[DNS_SECALG_FORMATSIZE]; + uint16_t flags = 0; + int param = 0; + bool null_key = false; + bool conflict = false; + bool show_progress = false; + isc_buffer_t buf; + dns_name_t *name; + dns_fixedname_t fname; + isc_result_t ret; + dst_key_t *key = NULL; + dst_key_t *prevkey = NULL; + + UNUSED(argc); + + dns_secalg_format(ctx->alg, algstr, sizeof(algstr)); + + if (ctx->predecessor == NULL) { + if (ctx->prepub == -1) { + ctx->prepub = 0; + } + + name = dns_fixedname_initname(&fname); + isc_buffer_init(&buf, argv[isc_commandline_index], + strlen(argv[isc_commandline_index])); + isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + if (ret != ISC_R_SUCCESS) { + fatal("invalid key name %s: %s", + argv[isc_commandline_index], + isc_result_totext(ret)); + } + + if (!dst_algorithm_supported(ctx->alg)) { + fatal("unsupported algorithm: %s", algstr); + } + + if (isc_fips_mode()) { + /* verify only in FIPS mode */ + switch (ctx->alg) { + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + fatal("unsupported algorithm: %s", algstr); + default: + break; + } + } + + if (ctx->use_nsec3) { + switch (ctx->alg) { + case DST_ALG_RSASHA1: + ctx->alg = DST_ALG_NSEC3RSASHA1; + break; + case DST_ALG_NSEC3RSASHA1: + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + case DST_ALG_ECDSA256: + case DST_ALG_ECDSA384: + case DST_ALG_ED25519: + case DST_ALG_ED448: + break; + default: + fatal("algorithm %s is incompatible with NSEC3" + ", do not use the -3 option", + algstr); + } + } + + if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) { + if (strcasecmp(ctx->type, "NOAUTH") == 0) { + flags |= DNS_KEYTYPE_NOAUTH; + } else if (strcasecmp(ctx->type, "NOCONF") == 0) { + flags |= DNS_KEYTYPE_NOCONF; + } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) { + flags |= (DNS_KEYTYPE_NOAUTH | + DNS_KEYTYPE_NOCONF); + if (ctx->size < 0) { + ctx->size = 0; + } + } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) { + /* nothing */ + } else { + fatal("invalid type %s", ctx->type); + } + } + + if (ctx->size < 0) { + switch (ctx->alg) { + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + if (isc_fips_mode()) { + fatal("key size not specified (-b " + "option)"); + } + FALLTHROUGH; + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + ctx->size = 2048; + if (verbose > 0) { + fprintf(stderr, + "key size not " + "specified; defaulting" + " to %d\n", + ctx->size); + } + break; + case DST_ALG_ECDSA256: + case DST_ALG_ECDSA384: + case DST_ALG_ED25519: + case DST_ALG_ED448: + break; + default: + fatal("key size not specified (-b option)"); + } + } + + if (!ctx->oldstyle && ctx->prepub > 0) { + if (ctx->setpub && ctx->setact && + (ctx->activate - ctx->prepub) < ctx->publish) + { + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + } + + if (!ctx->setpub && !ctx->setact) { + ctx->setpub = ctx->setact = true; + ctx->publish = ctx->now; + ctx->activate = ctx->now + ctx->prepub; + } else if (ctx->setpub && !ctx->setact) { + ctx->setact = true; + ctx->activate = ctx->publish + ctx->prepub; + } else if (ctx->setact && !ctx->setpub) { + ctx->setpub = true; + ctx->publish = ctx->activate - ctx->prepub; + } + + if ((ctx->activate - ctx->prepub) < ctx->now) { + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } + } else { + char keystr[DST_KEY_FORMATSIZE]; + isc_stdtime_t when; + int major, minor; + + if (ctx->prepub == -1) { + ctx->prepub = (30 * 86400); + } + + if (ctx->alg != 0) { + fatal("-S and -a cannot be used together"); + } + if (ctx->size >= 0) { + fatal("-S and -b cannot be used together"); + } + if (ctx->nametype != NULL) { + fatal("-S and -n cannot be used together"); + } + if (ctx->type != NULL) { + fatal("-S and -t cannot be used together"); + } + if (ctx->setpub || ctx->unsetpub) { + fatal("-S and -P cannot be used together"); + } + if (ctx->setact || ctx->unsetact) { + fatal("-S and -A cannot be used together"); + } + if (ctx->use_nsec3) { + fatal("-S and -3 cannot be used together"); + } + if (ctx->oldstyle) { + fatal("-S and -C cannot be used together"); + } + if (ctx->genonly) { + fatal("-S and -G cannot be used together"); + } + + ret = dst_key_fromnamedfile( + ctx->predecessor, ctx->directory, + (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE), + mctx, &prevkey); + if (ret != ISC_R_SUCCESS) { + fatal("Invalid keyfile %s: %s", ctx->predecessor, + isc_result_totext(ret)); + } + if (!dst_key_isprivate(prevkey)) { + fatal("%s is not a private key", ctx->predecessor); + } + + name = dst_key_name(prevkey); + ctx->alg = dst_key_alg(prevkey); + ctx->size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { + fatal("Key %s has incompatible format version %d.%d\n\t" + "It is not possible to generate a successor key.", + keystr, major, minor); + } + + ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); + if (ret != ISC_R_SUCCESS) { + fatal("Key %s has no activation date.\n\t" + "You must use dnssec-settime -A to set one " + "before generating a successor.", + keystr); + } + + ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, + &ctx->activate); + if (ret != ISC_R_SUCCESS) { + fatal("Key %s has no inactivation date.\n\t" + "You must use dnssec-settime -I to set one " + "before generating a successor.", + keystr); + } + + ctx->publish = ctx->activate - ctx->prepub; + if (ctx->publish < ctx->now) { + fatal("Key %s becomes inactive\n\t" + "sooner than the prepublication period " + "for the new key ends.\n\t" + "Either change the inactivation date with " + "dnssec-settime -I,\n\t" + "or use the -i option to set a shorter " + "prepublication interval.", + keystr); + } + + ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); + if (ret != ISC_R_SUCCESS) { + fprintf(stderr, + "%s: WARNING: Key %s has no removal " + "date;\n\t it will remain in the zone " + "indefinitely after rollover.\n\t " + "You can use dnssec-settime -D to " + "change this.\n", + program, keystr); + } + + ctx->setpub = ctx->setact = true; + } + + switch (ctx->alg) { + case DNS_KEYALG_RSASHA1: + case DNS_KEYALG_NSEC3RSASHA1: + if (isc_fips_mode()) { + fatal("SHA1 based keys not supported in FIPS mode"); + } + FALLTHROUGH; + case DNS_KEYALG_RSASHA256: + case DNS_KEYALG_RSASHA512: + if (ctx->size != 0 && + (ctx->size < min_rsa || ctx->size > MAX_RSA)) + { + fatal("RSA key size %d out of range", ctx->size); + } + break; + case DST_ALG_ECDSA256: + ctx->size = 256; + break; + case DST_ALG_ECDSA384: + ctx->size = 384; + break; + case DST_ALG_ED25519: + ctx->size = 256; + break; + case DST_ALG_ED448: + ctx->size = 456; + break; + } + + if (ctx->nametype == NULL) { + if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */ + fatal("no nametype specified"); + } + flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ + } else if (strcasecmp(ctx->nametype, "zone") == 0) { + flags |= DNS_KEYOWNER_ZONE; + } else if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */ + if (strcasecmp(ctx->nametype, "host") == 0 || + strcasecmp(ctx->nametype, "entity") == 0) + { + flags |= DNS_KEYOWNER_ENTITY; + } else if (strcasecmp(ctx->nametype, "user") == 0) { + /* no owner flags */ + } else { + fatal("invalid KEY nametype %s", ctx->nametype); + } + } else if (strcasecmp(ctx->nametype, "other") != 0) { /* DNSKEY */ + fatal("invalid DNSKEY nametype %s", ctx->nametype); + } + + if (ctx->directory == NULL) { + ctx->directory = "."; + } + + if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */ + flags |= ctx->signatory; + } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ + if (ctx->ksk || ctx->wantksk) { + flags |= DNS_KEYFLAG_KSK; + } + if (ctx->wantrev) { + flags |= DNS_KEYFLAG_REVOKE; + } + } + + if (ctx->protocol == -1) { + ctx->protocol = DNS_KEYPROTO_DNSSEC; + } else if ((ctx->options & DST_TYPE_KEY) == 0 && + ctx->protocol != DNS_KEYPROTO_DNSSEC) + { + fatal("invalid DNSKEY protocol: %d", ctx->protocol); + } + + if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { + if (ctx->size > 0) { + fatal("specified null key with non-zero size"); + } + } + + switch (ctx->alg) { + case DNS_KEYALG_RSASHA1: + case DNS_KEYALG_NSEC3RSASHA1: + case DNS_KEYALG_RSASHA256: + case DNS_KEYALG_RSASHA512: + show_progress = true; + break; + + case DST_ALG_ECDSA256: + case DST_ALG_ECDSA384: + case DST_ALG_ED25519: + case DST_ALG_ED448: + show_progress = true; + break; + } + + if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY && + (ctx->options & DST_TYPE_KEY) != 0) + { + null_key = true; + } + + isc_buffer_init(&buf, filename, sizeof(filename) - 1); + + do { + conflict = false; + + if (!ctx->quiet && show_progress) { + fprintf(stderr, "Generating key pair."); + } + + if (ctx->keystore != NULL && ctx->policy != NULL) { + ret = dns_keystore_keygen( + ctx->keystore, name, ctx->policy, ctx->rdclass, + mctx, ctx->alg, ctx->size, flags, &key); + } else if (!ctx->quiet && show_progress) { + ret = dst_key_generate(name, ctx->alg, ctx->size, param, + flags, ctx->protocol, + ctx->rdclass, NULL, mctx, &key, + &progress); + } else { + ret = dst_key_generate(name, ctx->alg, ctx->size, param, + flags, ctx->protocol, + ctx->rdclass, NULL, mctx, &key, + NULL); + } + + if (!ctx->quiet && show_progress) { + putc('\n', stderr); + fflush(stderr); + } + + if (ret != ISC_R_SUCCESS) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namestr, sizeof(namestr)); + fatal("failed to generate key %s/%s: %s\n", namestr, + algstr, isc_result_totext(ret)); + } + + dst_key_setbits(key, ctx->dbits); + + /* + * Set key timing metadata (unless using -C) + * + * Creation date is always set to "now". + * + * For a new key without an explicit predecessor, publish + * and activation dates are set to "now" by default, but + * can both be overridden. + * + * For a successor key, activation is set to match the + * predecessor's inactivation date. Publish is set to 30 + * days earlier than that (XXX: this should be configurable). + * If either of the resulting dates are in the past, that's + * an error; the inactivation date of the predecessor key + * must be updated before a successor key can be created. + */ + if (!ctx->oldstyle) { + dst_key_settime(key, DST_TIME_CREATED, ctx->now); + + if (ctx->genonly && (ctx->setpub || ctx->setact)) { + fatal("cannot use -G together with " + "-P or -A options"); + } + + if (ctx->setpub) { + dst_key_settime(key, DST_TIME_PUBLISH, + ctx->publish); + } else if (ctx->setact && !ctx->unsetpub) { + dst_key_settime(key, DST_TIME_PUBLISH, + ctx->activate - ctx->prepub); + } else if (!ctx->genonly && !ctx->unsetpub) { + dst_key_settime(key, DST_TIME_PUBLISH, + ctx->now); + } + + if (ctx->setact) { + dst_key_settime(key, DST_TIME_ACTIVATE, + ctx->activate); + } else if (!ctx->genonly && !ctx->unsetact) { + dst_key_settime(key, DST_TIME_ACTIVATE, + ctx->now); + } + + if (ctx->setrev) { + if (!ctx->wantksk) { + fprintf(stderr, + "%s: warning: Key is " + "not flagged as a KSK, but -R " + "was used. Revoking a ZSK is " + "legal, but undefined.\n", + program); + } + dst_key_settime(key, DST_TIME_REVOKE, + ctx->revokekey); + } + + if (ctx->setinact) { + dst_key_settime(key, DST_TIME_INACTIVE, + ctx->inactive); + } + + if (ctx->setdel) { + if (ctx->setinact && + ctx->deltime < ctx->inactive) + { + fprintf(stderr, + "%s: warning: Key is " + "scheduled to be deleted " + "before it is scheduled to be " + "made inactive.\n", + program); + } + dst_key_settime(key, DST_TIME_DELETE, + ctx->deltime); + } + + if (ctx->setsyncadd) { + dst_key_settime(key, DST_TIME_SYNCPUBLISH, + ctx->syncadd); + } + + if (ctx->setsyncdel) { + dst_key_settime(key, DST_TIME_SYNCDELETE, + ctx->syncdel); + } + } else { + if (ctx->setpub || ctx->setact || ctx->setrev || + ctx->setinact || ctx->setdel || ctx->unsetpub || + ctx->unsetact || ctx->unsetrev || ctx->unsetinact || + ctx->unsetdel || ctx->genonly || ctx->setsyncadd || + ctx->setsyncdel) + { + fatal("cannot use -C together with " + "-P, -A, -R, -I, -D, or -G options"); + } + /* + * Compatibility mode: Private-key-format + * should be set to 1.2. + */ + dst_key_setprivateformat(key, 1, 2); + } + + /* Set the default key TTL */ + if (ctx->setttl) { + dst_key_setttl(key, ctx->ttl); + } + + /* Set dnssec-policy related metadata */ + if (ctx->policy != NULL) { + dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime); + dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk); + dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk); + } + + /* + * Do not overwrite an existing key, or create a key + * if there is a risk of ID collision due to this key + * or another key being revoked. + */ + if (key_collision(key, name, ctx->directory, mctx, ctx->tag_min, + ctx->tag_max, NULL)) + { + conflict = true; + if (null_key) { + dst_key_free(&key); + break; + } + + if (verbose > 0) { + isc_buffer_clear(&buf); + ret = dst_key_buildfilename( + key, 0, ctx->directory, &buf); + if (ret == ISC_R_SUCCESS) { + fprintf(stderr, + "%s: %s already exists, or " + "might collide with another " + "key upon revokation. " + "Generating a new key\n", + program, filename); + } + } + + dst_key_free(&key); + } + } while (conflict); + + if (conflict) { + fatal("cannot generate a null key due to possible key ID " + "collision"); + } + + if (ctx->predecessor != NULL && prevkey != NULL) { + dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key)); + dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey)); + + ret = dst_key_tofile(prevkey, ctx->options, ctx->directory); + if (ret != ISC_R_SUCCESS) { + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(prevkey, keystr, sizeof(keystr)); + fatal("failed to update predecessor %s: %s\n", keystr, + isc_result_totext(ret)); + } + } + + ret = dst_key_tofile(key, ctx->options, ctx->directory); + if (ret != ISC_R_SUCCESS) { + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); + fatal("failed to write key %s: %s\n", keystr, + isc_result_totext(ret)); + } + + isc_buffer_clear(&buf); + ret = dst_key_buildfilename(key, 0, NULL, &buf); + if (ret != ISC_R_SUCCESS) { + fatal("dst_key_buildfilename returned: %s\n", + isc_result_totext(ret)); + } + printf("%s\n", filename); + + dst_key_free(&key); + if (prevkey != NULL) { + dst_key_free(&prevkey); + } +} + +static void +check_keystore_options(keygen_ctx_t *ctx) { + ctx->directory = dns_keystore_directory(ctx->keystore, NULL); + if (ctx->directory != NULL) { + isc_result_t ret = try_dir(ctx->directory); + if (ret != ISC_R_SUCCESS) { + fatal("cannot open directory %s: %s", ctx->directory, + isc_result_totext(ret)); + } + } +} + +int +main(int argc, char **argv) { + char *algname = NULL, *freeit = NULL; + char *classname = NULL; + char *endp; + isc_mem_t *mctx = NULL; + isc_result_t ret; + isc_textregion_t r; + const char *engine = NULL; + unsigned char c; + int ch; + bool set_fips_mode = false; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + OSSL_PROVIDER *fips = NULL, *base = NULL; +#endif + + keygen_ctx_t ctx = { + .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, + .prepub = -1, + .protocol = -1, + .size = -1, + .now = isc_stdtime_now(), + }; + + if (argc == 1) { + usage(); + } + + isc_commandline_errprint = false; + + /* + * Process memory debugging argument first. + */ +#define CMDLINE_FLAGS \ + "3A:a:b:Cc:D:d:E:Ff:GhI:i:K:k:L:l:M:m:n:P:p:qR:r:S:s:" \ + "T:t:v:V" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + } + if (strcasecmp(isc_commandline_argument, "trace") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + } + if (strcasecmp(isc_commandline_argument, "usage") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + } + break; + default: + break; + } + } + isc_commandline_reset = true; + + isc_mem_create(&mctx); + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '3': + ctx.use_nsec3 = true; + break; + case 'a': + algname = isc_commandline_argument; + break; + case 'b': + ctx.size = strtol(isc_commandline_argument, &endp, 10); + if (*endp != '\0' || ctx.size < 0) { + fatal("-b requires a non-negative number"); + } + break; + case 'C': + ctx.oldstyle = true; + break; + case 'c': + classname = isc_commandline_argument; + break; + case 'd': + ctx.dbits = strtol(isc_commandline_argument, &endp, 10); + if (*endp != '\0' || ctx.dbits < 0) { + fatal("-d requires a non-negative number"); + } + break; + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + c = (unsigned char)(isc_commandline_argument[0]); + if (toupper(c) == 'K') { + ctx.wantksk = true; + } else if (toupper(c) == 'Z') { + ctx.wantzsk = true; + } else if (toupper(c) == 'R') { + ctx.wantrev = true; + } else { + fatal("unknown flag '%s'", + isc_commandline_argument); + } + break; + case 'K': + ctx.directory = isc_commandline_argument; + ret = try_dir(ctx.directory); + if (ret != ISC_R_SUCCESS) { + fatal("cannot open directory %s: %s", + ctx.directory, isc_result_totext(ret)); + } + break; + case 'k': + ctx.policy = isc_commandline_argument; + break; + case 'L': + ctx.ttl = strtottl(isc_commandline_argument); + ctx.setttl = true; + break; + case 'l': + ctx.configfile = isc_commandline_argument; + break; + case 'n': + ctx.nametype = isc_commandline_argument; + break; + case 'M': { + unsigned long ul; + ctx.tag_min = ul = strtoul(isc_commandline_argument, + &endp, 10); + if (*endp != ':' || ul > 0xffff) { + fatal("-M range invalid"); + } + ctx.tag_max = ul = strtoul(endp + 1, &endp, 10); + if (*endp != '\0' || ul > 0xffff || + ctx.tag_max <= ctx.tag_min) + { + fatal("-M range invalid"); + } + break; + } + case 'm': + break; + case 'p': + ctx.protocol = strtol(isc_commandline_argument, &endp, + 10); + if (*endp != '\0' || ctx.protocol < 0 || + ctx.protocol > 255) + { + fatal("-p must be followed by a number " + "[0..255]"); + } + break; + case 'q': + ctx.quiet = true; + break; + case 'r': + fatal("The -r option has been deprecated.\n" + "System random data is always used.\n"); + break; + case 's': + ctx.signatory = strtol(isc_commandline_argument, &endp, + 10); + if (*endp != '\0' || ctx.signatory < 0 || + ctx.signatory > 15) + { + fatal("-s must be followed by a number " + "[0..15]"); + } + break; + case 'T': + if (strcasecmp(isc_commandline_argument, "KEY") == 0) { + ctx.options |= DST_TYPE_KEY; + } else if (strcasecmp(isc_commandline_argument, + "DNSKE" + "Y") == 0) + { + /* default behavior */ + } else { + fatal("unknown type '%s'", + isc_commandline_argument); + } + break; + case 't': + ctx.type = isc_commandline_argument; + break; + case 'v': + endp = NULL; + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case 'G': + ctx.genonly = true; + break; + case 'P': + /* -Psync ? */ + if (isoptarg("sync", argv, usage)) { + if (ctx.setsyncadd) { + fatal("-P sync specified more than " + "once"); + } + + ctx.syncadd = strtotime( + isc_commandline_argument, ctx.now, + ctx.now, &ctx.setsyncadd); + break; + } + (void)isoptarg("dnskey", argv, usage); + if (ctx.setpub || ctx.unsetpub) { + fatal("-P specified more than once"); + } + + ctx.publish = strtotime(isc_commandline_argument, + ctx.now, ctx.now, &ctx.setpub); + ctx.unsetpub = !ctx.setpub; + break; + case 'A': + if (ctx.setact || ctx.unsetact) { + fatal("-A specified more than once"); + } + + ctx.activate = strtotime(isc_commandline_argument, + ctx.now, ctx.now, &ctx.setact); + ctx.unsetact = !ctx.setact; + break; + case 'R': + if (ctx.setrev || ctx.unsetrev) { + fatal("-R specified more than once"); + } + + ctx.revokekey = strtotime(isc_commandline_argument, + ctx.now, ctx.now, + &ctx.setrev); + ctx.unsetrev = !ctx.setrev; + break; + case 'I': + if (ctx.setinact || ctx.unsetinact) { + fatal("-I specified more than once"); + } + + ctx.inactive = strtotime(isc_commandline_argument, + ctx.now, ctx.now, + &ctx.setinact); + ctx.unsetinact = !ctx.setinact; + break; + case 'D': + /* -Dsync ? */ + if (isoptarg("sync", argv, usage)) { + if (ctx.setsyncdel) { + fatal("-D sync specified more than " + "once"); + } + + ctx.syncdel = strtotime( + isc_commandline_argument, ctx.now, + ctx.now, &ctx.setsyncdel); + break; + } + (void)isoptarg("dnskey", argv, usage); + if (ctx.setdel || ctx.unsetdel) { + fatal("-D specified more than once"); + } + + ctx.deltime = strtotime(isc_commandline_argument, + ctx.now, ctx.now, &ctx.setdel); + ctx.unsetdel = !ctx.setdel; + break; + case 'S': + ctx.predecessor = isc_commandline_argument; + break; + case 'i': + ctx.prepub = strtottl(isc_commandline_argument); + break; + case 'F': + set_fips_mode = true; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + if (!isatty(0)) { + ctx.quiet = true; + } + + if (set_fips_mode) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips == NULL) { + ERR_clear_error(); + fatal("Failed to load FIPS provider"); + } + base = OSSL_PROVIDER_load(NULL, "base"); + if (base == NULL) { + OSSL_PROVIDER_unload(fips); + ERR_clear_error(); + fatal("Failed to load base provider"); + } +#endif + if (!isc_fips_mode()) { + if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } + } + } + + ret = dst_lib_init(mctx, engine); + if (ret != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", isc_result_totext(ret)); + } + + /* + * After dst_lib_init which will set FIPS mode if requested + * at build time. The minumums are both raised to 2048. + */ + if (isc_fips_mode()) { + min_rsa = min_dh = 2048; + } + + setup_logging(mctx, &lctx); + + ctx.rdclass = strtoclass(classname); + + if (ctx.configfile == NULL || ctx.configfile[0] == '\0') { + ctx.configfile = NAMED_CONFFILE; + } + + if (ctx.predecessor == NULL) { + if (argc < isc_commandline_index + 1) { + fatal("the key name was not specified"); + } + if (argc > isc_commandline_index + 1) { + fatal("extraneous arguments"); + } + } + + if (ctx.predecessor == NULL && ctx.policy == NULL) { + if (algname == NULL) { + fatal("no algorithm specified"); + } + r.base = algname; + r.length = strlen(algname); + ret = dns_secalg_fromtext(&ctx.alg, &r); + if (ret != ISC_R_SUCCESS) { + fatal("unknown algorithm %s", algname); + } + if (!dst_algorithm_supported(ctx.alg)) { + fatal("unsupported algorithm: %s", algname); + } + } + + if (ctx.policy != NULL) { + if (ctx.nametype != NULL) { + fatal("-k and -n cannot be used together"); + } + if (ctx.predecessor != NULL) { + fatal("-k and -S cannot be used together"); + } + if (ctx.oldstyle) { + fatal("-k and -C cannot be used together"); + } + if (ctx.setttl) { + fatal("-k and -L cannot be used together"); + } + if (ctx.prepub > 0) { + fatal("-k and -i cannot be used together"); + } + if (ctx.size != -1) { + fatal("-k and -b cannot be used together"); + } + if (ctx.wantrev) { + fatal("-k and -fR cannot be used together"); + } + if (ctx.options & DST_TYPE_KEY) { + fatal("-k and -T KEY cannot be used together"); + } + if (ctx.use_nsec3) { + fatal("-k and -3 cannot be used together"); + } + + ctx.options |= DST_TYPE_STATE; + + if (strcmp(ctx.policy, "default") == 0) { + ctx.use_nsec3 = false; + ctx.alg = DST_ALG_ECDSA256; + ctx.size = 0; + ctx.ttl = 3600; + ctx.setttl = true; + ctx.ksk = true; + ctx.zsk = true; + ctx.lifetime = 0; + ctx.tag_min = 0; + ctx.tag_max = 0xffff; + + keygen(&ctx, mctx, argc, argv); + } else { + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + dns_kasp_t *kasp = NULL; + dns_kasp_key_t *kaspkey = NULL; + + RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &parser) == + ISC_R_SUCCESS); + if (cfg_parse_file(parser, ctx.configfile, + &cfg_type_namedconf, + &config) != ISC_R_SUCCESS) + { + fatal("unable to load dnssec-policy '%s' from " + "'%s'", + ctx.policy, ctx.configfile); + } + + kasp_from_conf(config, mctx, lctx, ctx.policy, + ctx.directory, engine, &kasp); + if (kasp == NULL) { + fatal("failed to load dnssec-policy '%s'", + ctx.policy); + } + if (ISC_LIST_EMPTY(dns_kasp_keys(kasp))) { + fatal("dnssec-policy '%s' has no keys " + "configured", + ctx.policy); + } + + ctx.ttl = dns_kasp_dnskeyttl(kasp); + ctx.setttl = true; + + for (kaspkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); + kaspkey != NULL; + kaspkey = ISC_LIST_NEXT(kaspkey, link)) + { + ctx.use_nsec3 = false; + ctx.alg = dns_kasp_key_algorithm(kaspkey); + ctx.size = dns_kasp_key_size(kaspkey); + ctx.ksk = dns_kasp_key_ksk(kaspkey); + ctx.zsk = dns_kasp_key_zsk(kaspkey); + ctx.lifetime = dns_kasp_key_lifetime(kaspkey); + ctx.keystore = dns_kasp_key_keystore(kaspkey); + if (ctx.keystore != NULL) { + check_keystore_options(&ctx); + } + ctx.tag_min = dns_kasp_key_tagmin(kaspkey); + ctx.tag_max = dns_kasp_key_tagmax(kaspkey); + if ((ctx.ksk && !ctx.wantksk && ctx.wantzsk) || + (ctx.zsk && !ctx.wantzsk && ctx.wantksk)) + { + continue; + } + keygen(&ctx, mctx, argc, argv); + } + + dns_kasp_detach(&kasp); + cfg_obj_destroy(parser, &config); + cfg_parser_destroy(&parser); + } + } else { + keygen(&ctx, mctx, argc, argv); + } + + cleanup_logging(&lctx); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_destroy(&mctx); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + if (base != NULL) { + OSSL_PROVIDER_unload(base); + } + if (fips != NULL) { + OSSL_PROVIDER_unload(fips); + } +#endif + if (freeit != NULL) { + free(freeit); + } + + return 0; +} diff --git a/bin/dnssec/dnssec-keygen.rst b/bin/dnssec/dnssec-keygen.rst new file mode 100644 index 0000000..bd9ad6a --- /dev/null +++ b/bin/dnssec/dnssec-keygen.rst @@ -0,0 +1,372 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-keygen +.. program:: dnssec-keygen +.. _man_dnssec-keygen: + +dnssec-keygen: DNSSEC key generation tool +----------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-keygen` [**-3**] [**-A** date/offset] [**-a** algorithm] [**-b** keysize] [**-C**] [**-c** class] [**-D** date/offset] [**-d** bits] [**-D** sync date/offset] [**-E** engine] [**-f** flag] [**-F**] [**-G**] [**-h**] [**-I** date/offset] [**-i** interval] [**-K** directory] [**-k** policy] [**-L** ttl] [**-l** file] [**-n** nametype] [**-M** tag_min:tag_max] [**-P** date/offset] [**-P** sync date/offset] [**-p** protocol] [**-q**] [**-R** date/offset] [**-S** key] [**-s** strength] [**-T** rrtype] [**-t** type] [**-V**] [**-v** level] {name} + +Description +~~~~~~~~~~~ + +:program:`dnssec-keygen` generates keys for DNSSEC (Secure DNS), as defined in +:rfc:`2535` and :rfc:`4034`. + +The ``name`` of the key is specified on the command line. For DNSSEC +keys, this must match the name of the zone for which the key is being +generated. + +Options +~~~~~~~ + +.. option:: -3 + + This option uses an NSEC3-capable algorithm to generate a DNSSEC key. If this + option is used with an algorithm that has both NSEC and NSEC3 + versions, then the NSEC3 version is selected; for example, + ``dnssec-keygen -3 -a RSASHA1`` specifies the NSEC3RSASHA1 algorithm. + +.. option:: -a algorithm + + This option selects the cryptographic algorithm. For DNSSEC keys, the value of + ``algorithm`` must be one of RSASHA1, NSEC3RSASHA1, RSASHA256, + RSASHA512, ECDSAP256SHA256, ECDSAP384SHA384, ED25519, or ED448. + + These values are case-insensitive. In some cases, abbreviations are + supported, such as ECDSA256 for ECDSAP256SHA256 and ECDSA384 for + ECDSAP384SHA384. If RSASHA1 is specified along with the :option:`-3` + option, NSEC3RSASHA1 is used instead. + + This parameter *must* be specified except when using the :option:`-S` + option, which copies the algorithm from the predecessor key. + + In prior releases, HMAC algorithms could be generated for use as TSIG + keys, but that feature was removed in BIND 9.13.0. Use + :iscman:`tsig-keygen` to generate TSIG keys. + +.. option:: -b keysize + + This option specifies the number of bits in the key. The choice of key size + depends on the algorithm used: RSA keys must be between 1024 and 4096 + bits; Diffie-Hellman keys must be between 128 and 4096 bits. Elliptic + curve algorithms do not need this parameter. + + If the key size is not specified, some algorithms have pre-defined + defaults. For example, RSA keys for use as DNSSEC zone-signing keys + have a default size of 1024 bits; RSA keys for use as key-signing + keys (KSKs, generated with :option:`-f KSK <-f>`) default to 2048 bits. + +.. option:: -C + + This option enables compatibility mode, which generates an old-style key, without any timing + metadata. By default, :program:`dnssec-keygen` includes the key's + creation date in the metadata stored with the private key; other + dates may be set there as well, including publication date, activation date, + etc. Keys that include this data may be incompatible with older + versions of BIND; the :option:`-C` option suppresses them. + +.. option:: -c class + + This option indicates that the DNS record containing the key should have the + specified class. If not specified, class IN is used. + +.. option:: -d bits + + This option specifies the key size in bits. For the algorithms RSASHA1, NSEC3RSASA1, RSASHA256, and + RSASHA512 the key size must be between 1024 and 4096 bits; DH size is between 128 + and 4096 bits. This option is ignored for algorithms ECDSAP256SHA256, + ECDSAP384SHA384, ED25519, and ED448. + +.. option:: -E engine + + This option specifies the cryptographic hardware to use, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -f flag + + This option sets the specified flag in the flag field of the KEY/DNSKEY record. + The only recognized flags are ZSK (Zone-Signing Key), KSK (Key-Signing Key) + and REVOKE. + + Note that ZSK is not a physical flag in the DNSKEY record, it is merely used + to explicitly tell that you want to create a ZSK. Setting :option:`-f` in + conjunction with :option:`-k` will result in generating keys that only + match the given role set with this option. + +.. option:: -F + + This options turns on FIPS (US Federal Information Processing Standards) + mode if the underlying crytographic library supports running in FIPS + mode. + +.. option:: -G + + This option generates a key, but does not publish it or sign with it. This option is + incompatible with :option:`-P` and :option:`-A`. + +.. option:: -h + + This option prints a short summary of the options and arguments to + :program:`dnssec-keygen`. + +.. option:: -K directory + + This option sets the directory in which the key files are to be written. + +.. option:: -k policy + + This option creates keys for a specific ``dnssec-policy``. If a policy uses multiple keys, + :program:`dnssec-keygen` generates multiple keys. This also + creates a ".state" file to keep track of the key state. + + This option creates keys according to the ``dnssec-policy`` configuration, hence + it cannot be used at the same time as many of the other options that + :program:`dnssec-keygen` provides. + +.. option:: -L ttl + + This option sets the default TTL to use for this key when it is converted into a + DNSKEY RR. This is the TTL used when the key is imported into a zone, + unless there was already a DNSKEY RRset in + place, in which case the existing TTL takes precedence. If this + value is not set and there is no existing DNSKEY RRset, the TTL + defaults to the SOA TTL. Setting the default TTL to ``0`` or ``none`` + is the same as leaving it unset. + +.. option:: -l file + + This option provides a configuration file that contains a ``dnssec-policy`` statement + (matching the policy set with :option:`-k`). + +.. option:: -M tag_min:tag_max + + This option sets the range of acceptable key tag values that ``dnssec-keygen`` + will produce. If the key tag of the new key or the key tag of + the revoked version of the new key is outside this range, + the new key will be rejected and another new key will be generated. + This is designed to be used when generating keys in a multi-signer + scenario, where each operator is given a range of key tags to + prevent collisions among different operators. The valid values + for ``tag_min`` and ``tag_max`` are [0..65535]. The default allows all + key tag values to be produced. This option is ignored when ``-k policy`` + is specified. + +.. option:: -n nametype + + This option specifies the owner type of the key. The value of ``nametype`` must + either be ZONE (for a DNSSEC zone key (KEY/DNSKEY)), HOST or ENTITY + (for a key associated with a host (KEY)), USER (for a key associated + with a user (KEY)), or OTHER (DNSKEY). These values are + case-insensitive. The default is ZONE for DNSKEY generation. + +.. option:: -p protocol + + This option sets the protocol value for the generated key, for use with + :option:`-T KEY <-T>`. The protocol is a number between 0 and 255. The default + is 3 (DNSSEC). Other possible values for this argument are listed in + :rfc:`2535` and its successors. + +.. option:: -q + + This option sets quiet mode, which suppresses unnecessary output, including progress + indication. Without this option, when :program:`dnssec-keygen` is run + interactively to generate an RSA or DSA key pair, it prints a + string of symbols to ``stderr`` indicating the progress of the key + generation. A ``.`` indicates that a random number has been found which + passed an initial sieve test; ``+`` means a number has passed a single + round of the Miller-Rabin primality test; and a space ( ) means that the + number has passed all the tests and is a satisfactory key. + +.. option:: -S key + + This option creates a new key which is an explicit successor to an existing key. + The name, algorithm, size, and type of the key are set to match + the existing key. The activation date of the new key is set to + the inactivation date of the existing one. The publication date is + set to the activation date minus the prepublication interval, + which defaults to 30 days. + +.. option:: -s strength + + This option specifies the strength value of the key. The strength is a number + between 0 and 15, and currently has no defined purpose in DNSSEC. + +.. option:: -T rrtype + + This option specifies the resource record type to use for the key. ``rrtype`` + must be either DNSKEY or KEY. The default is DNSKEY when using a + DNSSEC algorithm, but it can be overridden to KEY for use with + SIG(0). + +.. option:: -t type + + This option indicates the type of the key for use with :option:`-T KEY <-T>`. ``type`` + must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default + is AUTHCONF. AUTH refers to the ability to authenticate data, and + CONF to the ability to encrypt data. + +.. option:: -V + + This option prints version information. + +.. option:: -v level + + This option sets the debugging level. + +Timing Options +~~~~~~~~~~~~~~ + +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by ``+`` or ``-`` and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes ``y``, ``mo``, ``w``, +``d``, ``h``, or ``mi``, so that it is computed in years (defined as +365 24-hour days, ignoring leap years), months (defined as 30 24-hour +days), weeks, days, hours, or minutes, respectively. Without a suffix, +the offset is computed in seconds. + +To unset a date, use ``none``, ``never``, or ``unset``. + +.. option:: -P date/offset + + This option sets the date on which a key is to be published to the zone. After + that date, the key is included in the zone but is not used + to sign it. If not set, and if the :option:`-G` option has not been used, the + default is the current date. + + .. program:: dnssec-keygen -P + .. option:: sync date/offset + + This option sets the date on which CDS and CDNSKEY records that match this key + are to be published to the zone. + +.. program:: dnssec-keygen + +.. option:: -A date/offset + + This option sets the date on which the key is to be activated. After that date, + the key is included in the zone and used to sign it. If not set, + and if the :option:`-G` option has not been used, the default is the current date. If set, + and :option:`-P` is not set, the publication date is set to the + activation date minus the prepublication interval. + +.. option:: -R date/offset + + This option sets the date on which the key is to be revoked. After that date, the + key is flagged as revoked. It is included in the zone and + is used to sign it. + +.. option:: -I date/offset + + This option sets the date on which the key is to be retired. After that date, the + key is still included in the zone, but it is not used to + sign it. + + +.. option:: -D date/offset + + This option sets the date on which the key is to be deleted. After that date, the + key is no longer included in the zone. (However, it may remain in the key + repository.) + + .. program:: dnssec-keygen -D + .. option:: sync date/offset + + This option sets the date on which the CDS and CDNSKEY records that match this + key are to be deleted. + +.. program:: dnssec-keygen + +.. option:: -i interval + + This option sets the prepublication interval for a key. If set, then the + publication and activation dates must be separated by at least this + much time. If the activation date is specified but the publication + date is not, the publication date defaults to this much time + before the activation date; conversely, if the publication date is + specified but not the activation date, activation is set to + this much time after publication. + + If the key is being created as an explicit successor to another key, + then the default prepublication interval is 30 days; otherwise it is + zero. + + As with date offsets, if the argument is followed by one of the + suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is + measured in years, months, weeks, days, hours, or minutes, + respectively. Without a suffix, the interval is measured in seconds. + +Generated Keys +~~~~~~~~~~~~~~ + +When :program:`dnssec-keygen` completes successfully, it prints a string of the +form ``Knnnn.+aaa+iiiii`` to the standard output. This is an +identification string for the key it has generated. + +- ``nnnn`` is the key name. + +- ``aaa`` is the numeric representation of the algorithm. + +- ``iiiii`` is the key identifier (or footprint). + +:program:`dnssec-keygen` creates two files, with names based on the printed +string. ``Knnnn.+aaa+iiiii.key`` contains the public key, and +``Knnnn.+aaa+iiiii.private`` contains the private key. + +The ``.key`` file contains a DNSKEY or KEY record. When a zone is being +signed by :iscman:`named` or :option:`dnssec-signzone -S`, DNSKEY records are +included automatically. In other cases, the ``.key`` file can be +inserted into a zone file manually or with an ``$INCLUDE`` statement. + +The ``.private`` file contains algorithm-specific fields. For obvious +security reasons, this file does not have general read permission. + +Example +~~~~~~~ + +To generate an ECDSAP256SHA256 zone-signing key for the zone +``example.com``, issue the command: + +``dnssec-keygen -a ECDSAP256SHA256 example.com`` + +The command prints a string of the form: + +``Kexample.com.+013+26160`` + +In this example, :program:`dnssec-keygen` creates the files +``Kexample.com.+013+26160.key`` and ``Kexample.com.+013+26160.private``. + +To generate a matching key-signing key, issue the command: + +``dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com`` + +See Also +~~~~~~~~ + +:iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, :rfc:`2539`, +:rfc:`2845`, :rfc:`4034`. diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c new file mode 100644 index 0000000..ac12cd5 --- /dev/null +++ b/bin/dnssec/dnssec-ksr.c @@ -0,0 +1,1483 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dnssectool.h" + +const char *program = "dnssec-ksr"; + +/* + * Infrastructure + */ +static isc_log_t *lctx = NULL; +static isc_mem_t *mctx = NULL; +const char *engine = NULL; +/* + * The domain we are working on + */ +static const char *namestr = NULL; +static dns_fixedname_t fname; +static dns_name_t *name = NULL; +/* + * KSR context + */ +struct ksr_ctx { + const char *policy; + const char *configfile; + const char *file; + const char *keydir; + dns_keystore_t *keystore; + isc_stdtime_t now; + isc_stdtime_t start; + isc_stdtime_t end; + bool setstart; + bool setend; + /* keygen */ + bool ksk; + dns_ttl_t ttl; + dns_secalg_t alg; + int size; + time_t lifetime; + time_t parentpropagation; + time_t propagation; + time_t publishsafety; + time_t retiresafety; + time_t sigrefresh; + time_t sigvalidity; + time_t signdelay; + time_t ttlds; + time_t ttlsig; +}; +typedef struct ksr_ctx ksr_ctx_t; + +/* + * These are set here for backwards compatibility. + * They are raised to 2048 in FIPS mode. + */ +static int min_rsa = 1024; +static int min_dh = 128; + +#define KSR_LINESIZE 1500 /* should be long enough for any DNSKEY record */ +#define DATETIME_INDEX 25 + +#define MAXWIRE (64 * 1024) + +#define STR(t) ((t).value.as_textregion.base) + +#define READLINE(lex, opt, token) + +#define NEXTTOKEN(lex, opt, token) \ + { \ + ret = isc_lex_gettoken(lex, opt, token); \ + if (ret != ISC_R_SUCCESS) \ + goto cleanup; \ + } + +#define BADTOKEN() \ + { \ + ret = ISC_R_UNEXPECTEDTOKEN; \ + goto cleanup; \ + } + +#define CHECK(r) \ + ret = (r); \ + if (ret != ISC_R_SUCCESS) { \ + goto fail; \ + } + +isc_bufferlist_t cleanup_list = ISC_LIST_INITIALIZER; + +static void +usage(int ret) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s options [options] \n", program); + fprintf(stderr, "\n"); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -E : name of an OpenSSL engine to use\n"); + fprintf(stderr, " -e : end date\n"); + fprintf(stderr, " -F: FIPS mode\n"); + fprintf(stderr, " -f: KSR file to sign\n"); + fprintf(stderr, " -i : start date\n"); + fprintf(stderr, " -K : key directory\n"); + fprintf(stderr, " -k : name of a DNSSEC policy\n"); + fprintf(stderr, " -l : file with dnssec-policy config\n"); + fprintf(stderr, " -h: print usage and exit\n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, " -v : set verbosity level\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Commands:\n"); + fprintf(stderr, " keygen: pregenerate ZSKs\n"); + fprintf(stderr, " request: create a Key Signing Request (KSR)\n"); + fprintf(stderr, " sign: sign a KSR, creating a Signed Key " + "Response (SKR)\n"); + exit(ret); +} + +static isc_stdtime_t +between(isc_stdtime_t t, isc_stdtime_t start, isc_stdtime_t end) { + isc_stdtime_t r = end; + if (t > 0 && t > start && t < end) { + r = t; + } + return r; +} + +static void +checkparams(ksr_ctx_t *ksr, const char *command) { + if (ksr->configfile == NULL) { + fatal("%s requires a configuration file", command); + } + if (ksr->policy == NULL) { + fatal("%s requires a dnssec-policy", command); + } + if (!ksr->setend) { + fatal("%s requires an end date", command); + } + if (!ksr->setstart) { + ksr->start = ksr->now; + } + if (ksr->keydir == NULL) { + ksr->keydir = "."; + } +} + +static void +getkasp(ksr_ctx_t *ksr, dns_kasp_t **kasp) { + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + + RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &parser) == ISC_R_SUCCESS); + if (cfg_parse_file(parser, ksr->configfile, &cfg_type_namedconf, + &config) != ISC_R_SUCCESS) + { + fatal("unable to load dnssec-policy '%s' from '%s'", + ksr->policy, ksr->configfile); + } + kasp_from_conf(config, mctx, lctx, ksr->policy, ksr->keydir, engine, + kasp); + if (*kasp == NULL) { + fatal("failed to load dnssec-policy '%s'", ksr->policy); + } + if (ISC_LIST_EMPTY(dns_kasp_keys(*kasp))) { + fatal("dnssec-policy '%s' has no keys configured", ksr->policy); + } + cfg_obj_destroy(parser, &config); + cfg_parser_destroy(&parser); +} + +static int +keyalgtag_cmp(const void *k1, const void *k2) { + dns_dnsseckey_t **key1 = (dns_dnsseckey_t **)k1; + dns_dnsseckey_t **key2 = (dns_dnsseckey_t **)k2; + if (dst_key_alg((*key1)->key) < dst_key_alg((*key2)->key)) { + return -1; + } else if (dst_key_alg((*key1)->key) > dst_key_alg((*key2)->key)) { + return 1; + } else if (dst_key_id((*key1)->key) < dst_key_id((*key2)->key)) { + return -1; + } else if (dst_key_id((*key1)->key) > dst_key_id((*key2)->key)) { + return 1; + } + return 0; +} + +static void +get_dnskeys(ksr_ctx_t *ksr, dns_dnsseckeylist_t *keys) { + dns_dnsseckeylist_t keys_read; + dns_dnsseckey_t **keys_sorted; + int i = 0, n = 0; + isc_result_t ret; + + ISC_LIST_INIT(*keys); + ISC_LIST_INIT(keys_read); + ret = dns_dnssec_findmatchingkeys(name, NULL, ksr->keydir, NULL, + ksr->now, mctx, &keys_read); + if (ret != ISC_R_SUCCESS && ret != ISC_R_NOTFOUND) { + fatal("failed to load existing keys from %s: %s", ksr->keydir, + isc_result_totext(ret)); + } + /* Sort on keytag. */ + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(keys_read); dk != NULL; + dk = ISC_LIST_NEXT(dk, link)) + { + n++; + } + keys_sorted = isc_mem_cget(mctx, n, sizeof(dns_dnsseckey_t *)); + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(keys_read); dk != NULL; + dk = ISC_LIST_NEXT(dk, link), i++) + { + keys_sorted[i] = dk; + } + qsort(keys_sorted, n, sizeof(dns_dnsseckey_t *), keyalgtag_cmp); + while (!ISC_LIST_EMPTY(keys_read)) { + dns_dnsseckey_t *key = ISC_LIST_HEAD(keys_read); + ISC_LIST_UNLINK(keys_read, key, link); + } + /* Save sorted list in 'keys' */ + for (i = 0; i < n; i++) { + ISC_LIST_APPEND(*keys, keys_sorted[i], link); + } + INSIST(ISC_LIST_EMPTY(keys_read)); + isc_mem_cput(mctx, keys_sorted, n, sizeof(dns_dnsseckey_t *)); +} + +static void +setcontext(ksr_ctx_t *ksr, dns_kasp_t *kasp) { + ksr->parentpropagation = dns_kasp_parentpropagationdelay(kasp); + ksr->propagation = dns_kasp_zonepropagationdelay(kasp); + ksr->publishsafety = dns_kasp_publishsafety(kasp); + ksr->retiresafety = dns_kasp_retiresafety(kasp); + ksr->sigvalidity = dns_kasp_sigvalidity_dnskey(kasp); + ksr->sigrefresh = dns_kasp_sigrefresh(kasp); + ksr->signdelay = dns_kasp_signdelay(kasp); + ksr->ttl = dns_kasp_dnskeyttl(kasp); + ksr->ttlds = dns_kasp_dsttl(kasp); + ksr->ttlsig = dns_kasp_zonemaxttl(kasp, true); +} + +static void +cleanup(dns_dnsseckeylist_t *keys, dns_kasp_t *kasp) { + while (!ISC_LIST_EMPTY(*keys)) { + dns_dnsseckey_t *key = ISC_LIST_HEAD(*keys); + ISC_LIST_UNLINK(*keys, key, link); + dst_key_free(&key->key); + dns_dnsseckey_destroy(mctx, &key); + } + dns_kasp_detach(&kasp); + + isc_buffer_t *cbuf = ISC_LIST_HEAD(cleanup_list); + while (cbuf != NULL) { + isc_buffer_t *nbuf = ISC_LIST_NEXT(cbuf, link); + ISC_LIST_UNLINK(cleanup_list, cbuf, link); + isc_buffer_free(&cbuf); + cbuf = nbuf; + } +} + +static void +progress(int p) { + char c = '*'; + switch (p) { + case 0: + c = '.'; + break; + case 1: + c = '+'; + break; + case 2: + c = '*'; + break; + case 3: + c = ' '; + break; + default: + break; + } + (void)putc(c, stderr); + (void)fflush(stderr); +} + +static void +freerrset(dns_rdataset_t *rdataset) { + dns_rdatalist_t *rdlist; + dns_rdata_t *rdata; + + if (!dns_rdataset_isassociated(rdataset)) { + return; + } + + dns_rdatalist_fromrdataset(rdataset, &rdlist); + + for (rdata = ISC_LIST_HEAD(rdlist->rdata); rdata != NULL; + rdata = ISC_LIST_HEAD(rdlist->rdata)) + { + ISC_LIST_UNLINK(rdlist->rdata, rdata, link); + isc_mem_put(mctx, rdata, sizeof(*rdata)); + } + isc_mem_put(mctx, rdlist, sizeof(*rdlist)); + dns_rdataset_disassociate(rdataset); +} + +static void +create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey, + dns_dnsseckeylist_t *keys, isc_stdtime_t inception, + isc_stdtime_t active, isc_stdtime_t *expiration) { + bool conflict = false; + bool freekey = false; + bool show_progress = true; + char algstr[DNS_SECALG_FORMATSIZE]; + char filename[PATH_MAX + 1]; + char timestr[26]; /* Minimal buf as per ctime_r() spec. */ + dst_key_t *key = NULL; + int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE); + isc_buffer_t buf; + isc_result_t ret; + isc_stdtime_t prepub; + uint16_t flags = DNS_KEYOWNER_ZONE; + + isc_stdtime_tostring(inception, timestr, sizeof(timestr)); + + /* ZSK or KSK? */ + if (ksr->ksk) { + flags |= DNS_KEYFLAG_KSK; + } + + /* Check algorithm and size. */ + dns_secalg_format(ksr->alg, algstr, sizeof(algstr)); + if (!dst_algorithm_supported(ksr->alg)) { + fatal("unsupported algorithm: %s", algstr); + } + INSIST(ksr->size >= 0); + switch (ksr->alg) { + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + if (isc_fips_mode()) { + /* verify-only in FIPS mode */ + fatal("unsupported algorithm: %s", algstr); + } + FALLTHROUGH; + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + if (ksr->size != 0 && + (ksr->size < min_rsa || ksr->size > MAX_RSA)) + { + fatal("RSA key size %d out of range", ksr->size); + } + break; + case DST_ALG_ECDSA256: + ksr->size = 256; + break; + case DST_ALG_ECDSA384: + ksr->size = 384; + break; + case DST_ALG_ED25519: + ksr->size = 256; + break; + case DST_ALG_ED448: + ksr->size = 456; + break; + default: + show_progress = false; + break; + } + + isc_buffer_init(&buf, filename, sizeof(filename) - 1); + + /* Check existing keys. */ + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(*keys); dk != NULL; + dk = ISC_LIST_NEXT(dk, link)) + { + isc_stdtime_t act = 0, inact = 0; + + if (!dns_kasp_key_match(kaspkey, dk)) { + continue; + } + (void)dst_key_gettime(dk->key, DST_TIME_ACTIVATE, &act); + (void)dst_key_gettime(dk->key, DST_TIME_INACTIVE, &inact); + /* + * If this key's activation time is set after the inception + * time, it is not eligble for the current bundle. + */ + if (act > inception) { + continue; + } + /* + * If this key's inactive time is set before the inception + * time, it is not eligble for the current bundle. + */ + if (inact > 0 && inception >= inact) { + continue; + } + + /* Found matching existing key. */ + if (verbose > 0 && show_progress) { + fprintf(stderr, + "Selecting key pair for bundle %s: ", timestr); + fflush(stderr); + } + key = dk->key; + *expiration = inact; + goto output; + } + + /* No existing keys match. */ + do { + conflict = false; + + if (verbose > 0 && show_progress) { + fprintf(stderr, + "Generating key pair for bundle %s: ", timestr); + } + if (ksr->keystore != NULL && ksr->policy != NULL) { + ret = dns_keystore_keygen( + ksr->keystore, name, ksr->policy, + dns_rdataclass_in, mctx, ksr->alg, ksr->size, + flags, &key); + } else if (show_progress) { + ret = dst_key_generate(name, ksr->alg, ksr->size, 0, + flags, DNS_KEYPROTO_DNSSEC, + dns_rdataclass_in, NULL, mctx, + &key, &progress); + fflush(stderr); + } else { + ret = dst_key_generate(name, ksr->alg, ksr->size, 0, + flags, DNS_KEYPROTO_DNSSEC, + dns_rdataclass_in, NULL, mctx, + &key, NULL); + } + + if (ret != ISC_R_SUCCESS) { + fatal("failed to generate key %s/%s: %s\n", namestr, + algstr, isc_result_totext(ret)); + } + + /* Do not overwrite an existing key. */ + if (key_collision(key, name, ksr->keydir, mctx, + dns_kasp_key_tagmin(kaspkey), + dns_kasp_key_tagmax(kaspkey), NULL)) + { + conflict = true; + if (verbose > 0) { + isc_buffer_clear(&buf); + ret = dst_key_buildfilename(key, 0, ksr->keydir, + &buf); + if (ret == ISC_R_SUCCESS) { + fprintf(stderr, + "%s: %s already exists, or " + "might collide with another " + "key upon revokation. " + "Generating a new key\n", + program, filename); + } + } + dst_key_free(&key); + } + } while (conflict); + + freekey = true; + + /* Set key timing metadata. */ + prepub = ksr->ttl + ksr->publishsafety + ksr->propagation; + dst_key_setttl(key, ksr->ttl); + dst_key_setnum(key, DST_NUM_LIFETIME, ksr->lifetime); + dst_key_setbool(key, DST_BOOL_KSK, ksr->ksk); + dst_key_setbool(key, DST_BOOL_ZSK, !ksr->ksk); + dst_key_settime(key, DST_TIME_CREATED, ksr->now); + dst_key_settime(key, DST_TIME_PUBLISH, (active - prepub)); + dst_key_settime(key, DST_TIME_ACTIVATE, active); + if (ksr->ksk) { + dns_keymgr_settime_syncpublish(key, kasp, + (inception == ksr->start)); + } + + if (ksr->lifetime > 0) { + isc_stdtime_t inactive = (active + ksr->lifetime); + isc_stdtime_t remove; + + if (ksr->ksk) { + remove = ksr->ttlds + ksr->parentpropagation + + ksr->retiresafety; + dst_key_settime(key, DST_TIME_SYNCDELETE, inactive); + } else { + remove = ksr->ttlsig + ksr->propagation + + ksr->retiresafety + ksr->signdelay; + } + dst_key_settime(key, DST_TIME_INACTIVE, inactive); + dst_key_settime(key, DST_TIME_DELETE, (inactive + remove)); + *expiration = inactive; + } else { + *expiration = 0; + } + + ret = dst_key_tofile(key, options, ksr->keydir); + if (ret != ISC_R_SUCCESS) { + char keystr[DST_KEY_FORMATSIZE]; + dst_key_format(key, keystr, sizeof(keystr)); + fatal("failed to write key %s: %s\n", keystr, + isc_result_totext(ret)); + } + +output: + isc_buffer_clear(&buf); + ret = dst_key_buildfilename(key, 0, NULL, &buf); + if (ret != ISC_R_SUCCESS) { + fatal("dst_key_buildfilename returned: %s\n", + isc_result_totext(ret)); + } + printf("%s\n", filename); + fflush(stdout); + if (freekey) { + dst_key_free(&key); + } +} + +static void +print_rdata(dns_rdataset_t *rrset) { + isc_buffer_t target; + isc_region_t r; + isc_result_t ret; + char buf[4096]; + + isc_buffer_init(&target, buf, sizeof(buf)); + ret = dns_rdataset_totext(rrset, name, false, false, &target); + if (ret != ISC_R_SUCCESS) { + fatal("failed to print rdata"); + } + isc_buffer_usedregion(&target, &r); + fprintf(stdout, "%.*s", (int)r.length, (char *)r.base); +} + +static isc_stdtime_t +print_dnskeys(dns_kasp_key_t *kaspkey, dns_ttl_t ttl, dns_dnsseckeylist_t *keys, + isc_stdtime_t inception, isc_stdtime_t next_inception) { + char algstr[DNS_SECALG_FORMATSIZE]; + char timestr[26]; /* Minimal buf as per ctime_r() spec. */ + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t rdataset = DNS_RDATASET_INIT; + isc_result_t ret = ISC_R_SUCCESS; + isc_stdtime_t next_bundle = next_inception; + + isc_stdtime_tostring(inception, timestr, sizeof(timestr)); + dns_secalg_format(dns_kasp_key_algorithm(kaspkey), algstr, + sizeof(algstr)); + + /* Fetch matching key pair. */ + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + dns_rdatalist_init(rdatalist); + rdatalist->rdclass = dns_rdataclass_in; + rdatalist->type = dns_rdatatype_dnskey; + rdatalist->ttl = ttl; + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(*keys); dk != NULL; + dk = ISC_LIST_NEXT(dk, link)) + { + isc_stdtime_t pub = 0, del = 0; + + (void)dst_key_gettime(dk->key, DST_TIME_PUBLISH, &pub); + (void)dst_key_gettime(dk->key, DST_TIME_DELETE, &del); + + /* Determine next bundle. */ + if (pub > 0 && pub > inception && pub < next_bundle) { + next_bundle = pub; + } + if (del > 0 && del > inception && del < next_bundle) { + next_bundle = del; + } + /* Find matching key. */ + if (!dns_kasp_key_match(kaspkey, dk)) { + continue; + } + if (pub > inception) { + continue; + } + if (del != 0 && inception >= del) { + continue; + } + /* Found matching key pair, add DNSKEY record to RRset. */ + isc_buffer_t buf; + isc_buffer_t *newbuf = NULL; + dns_rdata_t *rdata = NULL; + isc_region_t r; + unsigned char rdatabuf[DST_KEY_MAXSIZE]; + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + dns_rdata_init(rdata); + isc_buffer_init(&buf, rdatabuf, sizeof(rdatabuf)); + CHECK(dst_key_todns(dk->key, &buf)); + isc_buffer_usedregion(&buf, &r); + isc_buffer_allocate(mctx, &newbuf, r.length); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_fromregion(rdata, dns_rdataclass_in, + dns_rdatatype_dnskey, &r); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(cleanup_list, newbuf, link); + isc_buffer_clear(newbuf); + } + /* Error if no key pair found. */ + if (ISC_LIST_EMPTY(rdatalist->rdata)) { + fatal("no %s/%s zsk key pair found for bundle %s", namestr, + algstr, timestr); + } + + /* All good, print DNSKEY RRset. */ + dns_rdatalist_tordataset(rdatalist, &rdataset); + print_rdata(&rdataset); + +fail: + /* Cleanup */ + freerrset(&rdataset); + + if (ret != ISC_R_SUCCESS) { + fatal("failed to print %s/%s zsk key pair found for bundle %s", + namestr, algstr, timestr); + } + + return next_bundle; +} + +static isc_stdtime_t +sign_rrset(ksr_ctx_t *ksr, isc_stdtime_t inception, isc_stdtime_t expiration, + dns_rdataset_t *rrset, dns_dnsseckeylist_t *keys) { + dns_rdatalist_t *rrsiglist = NULL; + dns_rdataset_t rrsigset = DNS_RDATASET_INIT; + isc_result_t ret; + isc_stdtime_t next_bundle = expiration; + + UNUSED(ksr); + + /* Bundle header */ + if (rrset->type == dns_rdatatype_dnskey) { + char timestr[26]; /* Minimal buf as per ctime_r() spec. */ + char utc[sizeof("YYYYMMDDHHSSMM")]; + isc_buffer_t timebuf; + isc_buffer_t b; + isc_region_t r; + isc_buffer_init(&timebuf, timestr, sizeof(timestr)); + isc_stdtime_tostring(inception, timestr, sizeof(timestr)); + isc_buffer_init(&b, utc, sizeof(utc)); + ret = dns_time32_totext(inception, &b); + if (ret != ISC_R_SUCCESS) { + fatal("failed to convert bundle time32 to text: %s", + isc_result_totext(ret)); + } + isc_buffer_usedregion(&b, &r); + fprintf(stdout, ";; SignedKeyResponse 1.0 %.*s (%s)\n", + (int)r.length, r.base, timestr); + } + + /* RRset */ + print_rdata(rrset); + + /* Signatures */ + rrsiglist = isc_mem_get(mctx, sizeof(*rrsiglist)); + dns_rdatalist_init(rrsiglist); + rrsiglist->rdclass = dns_rdataclass_in; + rrsiglist->type = dns_rdatatype_rrsig; + rrsiglist->ttl = rrset->ttl; + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(*keys); dk != NULL; + dk = ISC_LIST_NEXT(dk, link)) + { + isc_buffer_t buf; + isc_buffer_t *newbuf = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t *rrsig = NULL; + isc_region_t rs; + unsigned char rdatabuf[SIG_FORMATSIZE]; + isc_stdtime_t clockskew = inception - 3600; + + isc_stdtime_t pub = 0, act = 0, inact = 0, del = 0; + + /* Determine next bundle. */ + (void)dst_key_gettime(dk->key, DST_TIME_PUBLISH, &pub); + (void)dst_key_gettime(dk->key, DST_TIME_ACTIVATE, &act); + (void)dst_key_gettime(dk->key, DST_TIME_INACTIVE, &inact); + (void)dst_key_gettime(dk->key, DST_TIME_DELETE, &del); + next_bundle = between(pub, inception, next_bundle); + next_bundle = between(act, inception, next_bundle); + next_bundle = between(inact, inception, next_bundle); + next_bundle = between(del, inception, next_bundle); + + if (act > inception) { + continue; + } + if (inact != 0 && inception >= inact) { + continue; + } + + rrsig = isc_mem_get(mctx, sizeof(*rrsig)); + dns_rdata_init(rrsig); + isc_buffer_init(&buf, rdatabuf, sizeof(rdatabuf)); + ret = dns_dnssec_sign(name, rrset, dk->key, &clockskew, + &expiration, mctx, &buf, &rdata); + if (ret != ISC_R_SUCCESS) { + fatal("failed to sign KSR"); + } + isc_buffer_usedregion(&buf, &rs); + isc_buffer_allocate(mctx, &newbuf, rs.length); + isc_buffer_putmem(newbuf, rs.base, rs.length); + isc_buffer_usedregion(newbuf, &rs); + dns_rdata_fromregion(rrsig, dns_rdataclass_in, + dns_rdatatype_rrsig, &rs); + ISC_LIST_APPEND(rrsiglist->rdata, rrsig, link); + ISC_LIST_APPEND(cleanup_list, newbuf, link); + isc_buffer_clear(newbuf); + } + dns_rdatalist_tordataset(rrsiglist, &rrsigset); + print_rdata(&rrsigset); + freerrset(&rrsigset); + + return next_bundle; +} + +/* + * Create the DNSKEY, CDS, and CDNSKEY records beloing to the KSKs + * listed in 'keys'. + */ +static isc_stdtime_t +get_keymaterial(ksr_ctx_t *ksr, dns_kasp_t *kasp, isc_stdtime_t inception, + isc_stdtime_t next_inception, dns_dnsseckeylist_t *keys, + dns_rdataset_t *dnskeyset, dns_rdataset_t *cdnskeyset, + dns_rdataset_t *cdsset) { + dns_kasp_digestlist_t digests = dns_kasp_digests(kasp); + dns_rdatalist_t *dnskeylist = isc_mem_get(mctx, sizeof(*dnskeylist)); + dns_rdatalist_t *cdnskeylist = isc_mem_get(mctx, sizeof(*cdnskeylist)); + dns_rdatalist_t *cdslist = isc_mem_get(mctx, sizeof(*cdslist)); + isc_result_t ret = ISC_R_SUCCESS; + isc_stdtime_t next_bundle = next_inception; + + dns_rdatalist_init(dnskeylist); + dnskeylist->rdclass = dns_rdataclass_in; + dnskeylist->type = dns_rdatatype_dnskey; + dnskeylist->ttl = ksr->ttl; + + dns_rdatalist_init(cdnskeylist); + cdnskeylist->rdclass = dns_rdataclass_in; + cdnskeylist->type = dns_rdatatype_cdnskey; + cdnskeylist->ttl = ksr->ttl; + + dns_rdatalist_init(cdslist); + cdslist->rdclass = dns_rdataclass_in; + cdslist->type = dns_rdatatype_cds; + cdslist->ttl = ksr->ttl; + + for (dns_dnsseckey_t *dk = ISC_LIST_HEAD(*keys); dk != NULL; + dk = ISC_LIST_NEXT(dk, link)) + { + bool published = true; + isc_buffer_t buf; + isc_buffer_t *newbuf; + dns_rdata_t *rdata; + isc_region_t r; + isc_region_t rcds; + isc_stdtime_t pub = 0, del = 0; + unsigned char kskbuf[DST_KEY_MAXSIZE]; + unsigned char cdnskeybuf[DST_KEY_MAXSIZE]; + unsigned char cdsbuf[DNS_DS_BUFFERSIZE]; + + /* KSK */ + (void)dst_key_gettime(dk->key, DST_TIME_PUBLISH, &pub); + (void)dst_key_gettime(dk->key, DST_TIME_DELETE, &del); + next_bundle = between(pub, inception, next_bundle); + next_bundle = between(del, inception, next_bundle); + + if (pub > inception) { + published = false; + } + if (del != 0 && inception >= del) { + published = false; + } + + if (published) { + newbuf = NULL; + rdata = isc_mem_get(mctx, sizeof(*rdata)); + dns_rdata_init(rdata); + + isc_buffer_init(&buf, kskbuf, sizeof(kskbuf)); + CHECK(dst_key_todns(dk->key, &buf)); + isc_buffer_usedregion(&buf, &r); + isc_buffer_allocate(mctx, &newbuf, r.length); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_fromregion(rdata, dns_rdataclass_in, + dns_rdatatype_dnskey, &r); + ISC_LIST_APPEND(dnskeylist->rdata, rdata, link); + ISC_LIST_APPEND(cleanup_list, newbuf, link); + isc_buffer_clear(newbuf); + } + + published = true; + if (dns_kasp_cdnskey(kasp) || !ISC_LIST_EMPTY(digests)) { + pub = 0; + del = 0; + (void)dst_key_gettime(dk->key, DST_TIME_SYNCPUBLISH, + &pub); + (void)dst_key_gettime(dk->key, DST_TIME_SYNCDELETE, + &del); + + next_bundle = between(pub, inception, next_bundle); + next_bundle = between(del, inception, next_bundle); + + if (pub != 0 && pub > inception) { + published = false; + } + if (del != 0 && inception >= del) { + published = false; + } + } else { + published = false; + } + + if (!published) { + continue; + } + + /* CDNSKEY */ + newbuf = NULL; + rdata = isc_mem_get(mctx, sizeof(*rdata)); + dns_rdata_init(rdata); + + isc_buffer_init(&buf, cdnskeybuf, sizeof(cdnskeybuf)); + CHECK(dst_key_todns(dk->key, &buf)); + isc_buffer_usedregion(&buf, &r); + isc_buffer_allocate(mctx, &newbuf, r.length); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_fromregion(rdata, dns_rdataclass_in, + dns_rdatatype_cdnskey, &r); + if (dns_kasp_cdnskey(kasp)) { + ISC_LIST_APPEND(cdnskeylist->rdata, rdata, link); + } + ISC_LIST_APPEND(cleanup_list, newbuf, link); + isc_buffer_clear(newbuf); + + /* CDS */ + for (dns_kasp_digest_t *alg = ISC_LIST_HEAD(digests); + alg != NULL; alg = ISC_LIST_NEXT(alg, link)) + { + isc_buffer_t *newbuf2 = NULL; + dns_rdata_t *rdata2 = NULL; + dns_rdata_t cds = DNS_RDATA_INIT; + + rdata2 = isc_mem_get(mctx, sizeof(*rdata2)); + dns_rdata_init(rdata2); + + CHECK(dns_ds_buildrdata(name, rdata, alg->digest, + cdsbuf, &cds)); + cds.type = dns_rdatatype_cds; + dns_rdata_toregion(&cds, &rcds); + isc_buffer_allocate(mctx, &newbuf2, rcds.length); + isc_buffer_putmem(newbuf2, rcds.base, rcds.length); + isc_buffer_usedregion(newbuf2, &rcds); + dns_rdata_fromregion(rdata2, dns_rdataclass_in, + dns_rdatatype_cds, &rcds); + ISC_LIST_APPEND(cdslist->rdata, rdata2, link); + ISC_LIST_APPEND(cleanup_list, newbuf2, link); + isc_buffer_clear(newbuf2); + } + + if (!dns_kasp_cdnskey(kasp)) { + isc_mem_put(mctx, rdata, sizeof(*rdata)); + } + } + /* All good */ + dns_rdatalist_tordataset(dnskeylist, dnskeyset); + dns_rdatalist_tordataset(cdnskeylist, cdnskeyset); + dns_rdatalist_tordataset(cdslist, cdsset); + + return next_bundle; + +fail: + fatal("failed to create KSK/CDS/CDNSKEY"); + return 0; +} + +static void +sign_bundle(ksr_ctx_t *ksr, dns_kasp_t *kasp, isc_stdtime_t inception, + isc_stdtime_t next_inception, dns_rdatalist_t *zsklist, + dns_dnsseckeylist_t *keys) { + isc_stdtime_t expiration = inception + ksr->sigvalidity; + isc_stdtime_t next_bundle = next_inception; + dns_rdataset_t zsk; + + dns_rdataset_init(&zsk); + dns_rdatalist_tordataset(zsklist, &zsk); + + while (inception <= next_inception) { + isc_stdtime_t next_time = next_bundle; + + /* DNSKEY RRset */ + dns_rdatalist_t *dnskeylist; + dnskeylist = isc_mem_get(mctx, sizeof(*dnskeylist)); + dns_rdatalist_init(dnskeylist); + dnskeylist->rdclass = dns_rdataclass_in; + dnskeylist->type = dns_rdatatype_dnskey; + dnskeylist->ttl = ksr->ttl; + + dns_rdataset_t ksk, cdnskey, cds, rrset; + dns_rdataset_init(&ksk); + dns_rdataset_init(&cdnskey); + dns_rdataset_init(&cds); + dns_rdataset_init(&rrset); + next_time = get_keymaterial(ksr, kasp, inception, next_time, + keys, &ksk, &cdnskey, &cds); + if (next_bundle > next_time) { + next_bundle = next_time; + } + + for (isc_result_t r = dns_rdatalist_first(&ksk); + r == ISC_R_SUCCESS; r = dns_rdatalist_next(&ksk)) + { + dns_rdata_t *clone = isc_mem_get(mctx, sizeof(*clone)); + dns_rdata_init(clone); + dns_rdatalist_current(&ksk, clone); + ISC_LIST_APPEND(dnskeylist->rdata, clone, link); + } + + for (isc_result_t r = dns_rdatalist_first(&zsk); + r == ISC_R_SUCCESS; r = dns_rdatalist_next(&zsk)) + { + dns_rdata_t *clone = isc_mem_get(mctx, sizeof(*clone)); + dns_rdata_init(clone); + dns_rdatalist_current(&zsk, clone); + ISC_LIST_APPEND(dnskeylist->rdata, clone, link); + } + + dns_rdatalist_tordataset(dnskeylist, &rrset); + next_time = sign_rrset(ksr, inception, expiration, &rrset, + keys); + if (next_bundle > next_time) { + next_bundle = next_time; + } + freerrset(&ksk); + freerrset(&rrset); + + /* CDNSKEY */ + if (dns_rdataset_count(&cdnskey) > 0) { + (void)sign_rrset(ksr, inception, expiration, &cdnskey, + keys); + } + freerrset(&cdnskey); + + /* CDS */ + if (dns_rdataset_count(&cds) > 0) { + (void)sign_rrset(ksr, inception, expiration, &cds, + keys); + } + freerrset(&cds); + + /* Next response bundle. */ + inception = expiration - ksr->sigrefresh; + if (inception > next_bundle) { + inception = next_bundle; + } + expiration = inception + ksr->sigvalidity; + next_bundle = expiration; + } + + freerrset(&zsk); +} + +static isc_result_t +parse_dnskey(isc_lex_t *lex, char *owner, isc_buffer_t *buf, dns_ttl_t *ttl) { + dns_fixedname_t dfname; + dns_name_t *dname = NULL; + dns_rdataclass_t rdclass = dns_rdataclass_in; + isc_buffer_t b; + isc_result_t ret; + isc_token_t token; + unsigned int opt = ISC_LEXOPT_EOL; + + isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); + + /* Read the domain name */ + if (!strcmp(owner, "@")) { + BADTOKEN(); + } + + dname = dns_fixedname_initname(&dfname); + isc_buffer_init(&b, owner, strlen(owner)); + isc_buffer_add(&b, strlen(owner)); + ret = dns_name_fromtext(dname, &b, dns_rootname, 0, NULL); + if (ret != ISC_R_SUCCESS) { + return ret; + } + if (dns_name_compare(dname, name) != 0) { + return DNS_R_BADOWNERNAME; + } + isc_buffer_clear(&b); + + /* Read the next word: either TTL, class, or type */ + NEXTTOKEN(lex, opt, &token); + if (token.type != isc_tokentype_string) { + BADTOKEN(); + } + + /* If it's a TTL, read the next one */ + ret = dns_ttl_fromtext(&token.value.as_textregion, ttl); + if (ret == ISC_R_SUCCESS) { + NEXTTOKEN(lex, opt, &token); + } + if (token.type != isc_tokentype_string) { + BADTOKEN(); + } + + /* If it's a class, read the next one */ + ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion); + if (ret == ISC_R_SUCCESS) { + NEXTTOKEN(lex, opt, &token); + } + if (token.type != isc_tokentype_string) { + BADTOKEN(); + } + + /* Must be the type */ + if (strcasecmp(STR(token), "DNSKEY") != 0) { + BADTOKEN(); + } + + ret = dns_rdata_fromtext(NULL, rdclass, dns_rdatatype_dnskey, lex, name, + 0, mctx, buf, NULL); + +cleanup: + isc_lex_setcomments(lex, 0); + return ret; +} + +static void +keygen(ksr_ctx_t *ksr) { + dns_kasp_t *kasp = NULL; + dns_dnsseckeylist_t keys; + bool noop = true; + + /* Check parameters */ + checkparams(ksr, "keygen"); + /* Get the policy */ + getkasp(ksr, &kasp); + /* Get existing keys */ + get_dnskeys(ksr, &keys); + /* Set context */ + setcontext(ksr, kasp); + /* Key generation */ + for (dns_kasp_key_t *kk = ISC_LIST_HEAD(dns_kasp_keys(kasp)); + kk != NULL; kk = ISC_LIST_NEXT(kk, link)) + { + if (dns_kasp_key_ksk(kk) && !ksr->ksk) { + /* only ZSKs allowed */ + continue; + } else if (dns_kasp_key_zsk(kk) && ksr->ksk) { + /* only KSKs allowed */ + continue; + } + ksr->alg = dns_kasp_key_algorithm(kk); + ksr->lifetime = dns_kasp_key_lifetime(kk); + ksr->keystore = dns_kasp_key_keystore(kk); + ksr->size = dns_kasp_key_size(kk); + noop = false; + + for (isc_stdtime_t inception = ksr->start, act = ksr->start; + inception < ksr->end; inception += ksr->lifetime) + { + create_key(ksr, kasp, kk, &keys, inception, act, &act); + if (ksr->lifetime == 0) { + /* unlimited lifetime, but not infinite loop */ + break; + } + } + } + if (noop) { + fatal("no keys created for policy '%s'", ksr->policy); + } + /* Cleanup */ + cleanup(&keys, kasp); +} + +static void +request(ksr_ctx_t *ksr) { + char timestr[26]; /* Minimal buf as per ctime_r() spec. */ + dns_dnsseckeylist_t keys; + dns_kasp_t *kasp = NULL; + isc_stdtime_t next = 0; + isc_stdtime_t inception = 0; + + /* Check parameters */ + checkparams(ksr, "request"); + /* Get the policy */ + getkasp(ksr, &kasp); + /* Get keys */ + get_dnskeys(ksr, &keys); + /* Set context */ + setcontext(ksr, kasp); + /* Create request */ + inception = ksr->start; + while (inception <= ksr->end) { + char utc[sizeof("YYYYMMDDHHSSMM")]; + isc_buffer_t b; + isc_region_t r; + isc_result_t ret; + + isc_stdtime_tostring(inception, timestr, sizeof(timestr)); + isc_buffer_init(&b, utc, sizeof(utc)); + ret = dns_time32_totext(inception, &b); + if (ret != ISC_R_SUCCESS) { + fatal("failed to convert bundle time32 to text: %s", + isc_result_totext(ret)); + } + isc_buffer_usedregion(&b, &r); + fprintf(stdout, ";; KeySigningRequest 1.0 %.*s (%s)\n", + (int)r.length, r.base, timestr); + + next = ksr->end + 1; + for (dns_kasp_key_t *kk = ISC_LIST_HEAD(dns_kasp_keys(kasp)); + kk != NULL; kk = ISC_LIST_NEXT(kk, link)) + { + /* + * Output the DNSKEY records for the current bundle + * that starts at 'inception. The 'next' variable is + * updated to the start time of the + * next bundle, determined by the earliest publication + * or withdrawal of a key that is after the current + * inception. + */ + if (dns_kasp_key_ksk(kk)) { + /* We only want ZSKs in the request. */ + continue; + } + + next = print_dnskeys(kk, ksr->ttl, &keys, inception, + next); + } + inception = next; + } + + isc_stdtime_tostring(ksr->now, timestr, sizeof(timestr)); + fprintf(stdout, ";; KeySigningRequest 1.0 generated at %s by %s\n", + timestr, PACKAGE_VERSION); + + /* Cleanup */ + cleanup(&keys, kasp); +} + +static void +sign(ksr_ctx_t *ksr) { + char timestr[26]; /* Minimal buf as per ctime_r() spec. */ + bool have_bundle = false; + dns_dnsseckeylist_t keys; + dns_kasp_t *kasp = NULL; + dns_rdatalist_t *rdatalist = NULL; + isc_result_t ret; + isc_stdtime_t inception; + isc_lex_t *lex = NULL; + isc_lexspecials_t specials; + isc_token_t token; + unsigned int opt = ISC_LEXOPT_EOL; + + /* Check parameters */ + checkparams(ksr, "sign"); + if (ksr->file == NULL) { + fatal("'sign' requires a KSR file"); + } + /* Get the policy */ + getkasp(ksr, &kasp); + /* Get keys */ + get_dnskeys(ksr, &keys); + /* Set context */ + setcontext(ksr, kasp); + /* Sign request */ + inception = ksr->start; + isc_lex_create(mctx, KSR_LINESIZE, &lex); + memset(specials, 0, sizeof(specials)); + specials['('] = 1; + specials[')'] = 1; + specials['"'] = 1; + isc_lex_setspecials(lex, specials); + ret = isc_lex_openfile(lex, ksr->file); + if (ret != ISC_R_SUCCESS) { + fatal("unable to open KSR file %s: %s", ksr->file, + isc_result_totext(ret)); + } + + for (ret = isc_lex_gettoken(lex, opt, &token); ret == ISC_R_SUCCESS; + ret = isc_lex_gettoken(lex, opt, &token)) + { + if (token.type != isc_tokentype_string) { + fatal("bad KSR file %s(%lu): syntax error", ksr->file, + isc_lex_getsourceline(lex)); + } + + if (strcmp(STR(token), ";;") == 0) { + char bundle[KSR_LINESIZE]; + isc_stdtime_t next_inception; + + CHECK(isc_lex_gettoken(lex, opt, &token)); + if (token.type != isc_tokentype_string || + strcmp(STR(token), "KeySigningRequest") != 0) + { + fatal("bad KSR file %s(%lu): expected " + "'KeySigningRequest'", + ksr->file, isc_lex_getsourceline(lex)); + } + + CHECK(isc_lex_gettoken(lex, opt, &token)); + if (token.type != isc_tokentype_string) { + fatal("bad KSR file %s(%lu): expected string", + ksr->file, isc_lex_getsourceline(lex)); + } + + if (strcmp(STR(token), "1.0") != 0) { + fatal("bad KSR file %s(%lu): expected version", + ksr->file, isc_lex_getsourceline(lex)); + } + + CHECK(isc_lex_gettoken(lex, opt, &token)); + if (token.type != isc_tokentype_string) { + fatal("bad KSR file %s(%lu): expected datetime", + ksr->file, isc_lex_getsourceline(lex)); + } + if (strcmp(STR(token), "generated") == 0) { + /* Final bundle */ + goto readline; + } + + /* Date and time of bundle */ + sscanf(STR(token), "%s", bundle); + next_inception = strtotime(bundle, ksr->now, ksr->now, + NULL); + + if (have_bundle) { + /* Sign previous bundle */ + sign_bundle(ksr, kasp, inception, + next_inception, rdatalist, &keys); + fprintf(stdout, "\n"); + } + + /* Start next bundle */ + rdatalist = isc_mem_get(mctx, sizeof(*rdatalist)); + dns_rdatalist_init(rdatalist); + rdatalist->rdclass = dns_rdataclass_in; + rdatalist->type = dns_rdatatype_dnskey; + rdatalist->ttl = ksr->ttl; + + inception = next_inception; + have_bundle = true; + + readline: + /* Read remainder of header line */ + do { + ret = isc_lex_gettoken(lex, opt, &token); + if (ret != ISC_R_SUCCESS) { + fatal("bad KSR file %s(%lu): bad " + "header (%s)", + ksr->file, + isc_lex_getsourceline(lex), + isc_result_totext(ret)); + } + } while (token.type != isc_tokentype_eol); + } else { + /* Parse DNSKEY */ + dns_ttl_t ttl = ksr->ttl; + isc_buffer_t buf; + isc_buffer_t *newbuf = NULL; + dns_rdata_t *rdata = NULL; + isc_region_t r; + u_char rdatabuf[DST_KEY_MAXSIZE]; + + INSIST(rdatalist != NULL); + + rdata = isc_mem_get(mctx, sizeof(*rdata)); + dns_rdata_init(rdata); + isc_buffer_init(&buf, rdatabuf, sizeof(rdatabuf)); + ret = parse_dnskey(lex, STR(token), &buf, &ttl); + if (ret != ISC_R_SUCCESS) { + fatal("bad KSR file %s(%lu): bad DNSKEY (%s)", + ksr->file, isc_lex_getsourceline(lex), + isc_result_totext(ret)); + } + isc_buffer_usedregion(&buf, &r); + isc_buffer_allocate(mctx, &newbuf, r.length); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_fromregion(rdata, dns_rdataclass_in, + dns_rdatatype_dnskey, &r); + if (rdatalist != NULL && ttl < rdatalist->ttl) { + rdatalist->ttl = ttl; + } + + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(cleanup_list, newbuf, link); + isc_buffer_clear(newbuf); + } + } + + if (ret != ISC_R_EOF) { + fatal("bad KSR file %s(%lu): trailing garbage data", ksr->file, + isc_lex_getsourceline(lex)); + } + + /* Final bundle */ + if (have_bundle && rdatalist != NULL) { + sign_bundle(ksr, kasp, inception, ksr->end, rdatalist, &keys); + } else { + fatal("bad KSR file %s(%lu): no bundles", ksr->file, + isc_lex_getsourceline(lex)); + } + + /* Bundle footer */ + isc_stdtime_tostring(ksr->now, timestr, sizeof(timestr)); + fprintf(stdout, ";; SignedKeyResponse 1.0 generated at %s by %s\n", + timestr, PACKAGE_VERSION); + +fail: + isc_lex_destroy(&lex); + cleanup(&keys, kasp); +} + +int +main(int argc, char *argv[]) { + isc_result_t ret; + isc_buffer_t buf; + int ch; + char *endp; + bool set_fips_mode = false; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + OSSL_PROVIDER *fips = NULL, *base = NULL; +#endif + ksr_ctx_t ksr = { + .now = isc_stdtime_now(), + }; + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + +#define OPTIONS "E:e:Ff:hi:K:k:l:ov:V" + while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'e': + ksr.end = strtotime(isc_commandline_argument, ksr.now, + ksr.now, &ksr.setend); + break; + case 'F': + set_fips_mode = true; + break; + case 'f': + ksr.file = isc_commandline_argument; + break; + case 'h': + usage(0); + break; + case 'i': + ksr.start = strtotime(isc_commandline_argument, ksr.now, + ksr.now, &ksr.setstart); + break; + case 'K': + ksr.keydir = isc_commandline_argument; + ret = try_dir(ksr.keydir); + if (ret != ISC_R_SUCCESS) { + fatal("cannot open directory %s: %s", + ksr.keydir, isc_result_totext(ret)); + } + break; + case 'k': + ksr.policy = isc_commandline_argument; + break; + case 'l': + ksr.configfile = isc_commandline_argument; + break; + case 'o': + ksr.ksk = true; + break; + case 'V': + version(program); + break; + case 'v': + verbose = strtoul(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + default: + usage(1); + break; + } + } + argv += isc_commandline_index; + argc -= isc_commandline_index; + + if (argc != 2) { + fatal("must provide a command and zone name"); + } + + ret = dst_lib_init(mctx, engine); + if (ret != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", isc_result_totext(ret)); + } + + /* + * After dst_lib_init which will set FIPS mode if requested + * at build time. The minumums are both raised to 2048. + */ + if (isc_fips_mode()) { + min_rsa = min_dh = 2048; + } + + setup_logging(mctx, &lctx); + + if (set_fips_mode) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips == NULL) { + fatal("Failed to load FIPS provider"); + } + base = OSSL_PROVIDER_load(NULL, "base"); + if (base == NULL) { + OSSL_PROVIDER_unload(fips); + fatal("Failed to load base provider"); + } +#endif + if (!isc_fips_mode()) { + if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } + } + } + + /* zone */ + namestr = argv[1]; + name = dns_fixedname_initname(&fname); + isc_buffer_init(&buf, argv[1], strlen(argv[1])); + isc_buffer_add(&buf, strlen(argv[1])); + ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); + if (ret != ISC_R_SUCCESS) { + fatal("invalid zone name %s: %s", argv[1], + isc_result_totext(ret)); + } + + /* command */ + if (strcmp(argv[0], "keygen") == 0) { + keygen(&ksr); + } else if (strcmp(argv[0], "request") == 0) { + request(&ksr); + } else if (strcmp(argv[0], "sign") == 0) { + sign(&ksr); + } else { + fatal("unknown command '%s'", argv[0]); + } + + exit(0); +} diff --git a/bin/dnssec/dnssec-ksr.rst b/bin/dnssec/dnssec-ksr.rst new file mode 100644 index 0000000..3dcb8aa --- /dev/null +++ b/bin/dnssec/dnssec-ksr.rst @@ -0,0 +1,172 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-ksr +.. program:: dnssec-ksr +.. _man_dnssec-ksr: + +dnssec-ksr - Create signed key response (SKR) files for offline KSK setups +-------------------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-ksr` [**-E** engine] [**-e** date/offset] [**-F**] [**-f** file] [**-h**] [**-i** date/offset] [**-K** directory] [**-k** policy] [**-l** file] [**-o**] [**-V**] [**-v** level] {command} {zone} + +Description +~~~~~~~~~~~ + +The :program:`dnssec-ksr` can be used to issue several commands that are needed +to generate presigned RRsets for a zone where the private key file of the Key +Signing Key (KSK) is typically offline. This requires Zone Signing Keys +(ZSKs) to be pregenerated, and the DNSKEY, CDNSKEY, and CDS RRsets to be +already signed in advance. + +The latter is done by creating Key Signing Requests (KSRs) that can be imported +to the environment where the KSK is available. Once there, this program can +create Signed Key Responses (SKRs) that can be loaded by an authoritative DNS +server. + +Options +~~~~~~~ + +.. option:: -E engine + + This option specifies the cryptographic hardware to use, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -e date/offset + + This option sets the end date for which keys or SKRs need to be generated + (depending on the command). + +.. option:: -F + + This options turns on FIPS (US Federal Information Processing Standards) + mode if the underlying crytographic library supports running in FIPS + mode. + +.. option:: -f + + This option sets the SKR file to be signed when issuing a ``sign`` command. + +.. option:: -h + + This option prints a short summary of the options and arguments to + :program:`dnssec-ksr`. + +.. option:: -i date/offset + + This option sets the start date for which keys or SKRs need to be generated + (depending on the command). + +.. option:: -K directory + + This option sets the directory in which the key files are to be read or + written (depending on the command). + +.. option:: -k policy + + This option sets the specific ``dnssec-policy`` for which keys need to + be generated, or signed. + +.. option:: -l file + + This option provides a configuration file that contains a ``dnssec-policy`` + statement (matching the policy set with :option:`-k`). + +.. option:: -o + + Normally when pregenerating keys, ZSKs are created. When this option is + set, create KSKs instead. + +.. option:: -V + + This option prints version information. + +.. option:: -v level + + This option sets the debugging level. Level 1 is intended to be usefully + verbose for general users; higher levels are intended for developers. + +``command`` + + The KSR command to be executed. See below for the available commands. + +``zone`` + + The name of the zone for which the KSR command is being executed. + +Commands +~~~~~~~~ + +.. option:: keygen + + Pregenerate a number of keys, given a DNSSEC policy and an interval. The + number of generated keys depends on the interval and the key lifetime. + +.. option:: request + + Create a Key Signing Request (KSR), given a DNSSEC policy and an interval. + This will generate a file with a number of key bundles, where each bundle + contains the currently published ZSKs (according to the timing metadata). + +.. option:: sign + + Sign a Key Signing Request (KSR), given a DNSSEC policy and an interval, + creating a Signed Key Response (SKR). This will add the corresponding DNSKEY, + CDS, and CDNSKEY records for the KSK that is being used for signing. + +Exit Status +~~~~~~~~~~~ + +The :program:`dnssec-ksr` command exits 0 on success, or non-zero if an error +occurred. + +Examples +~~~~~~~~ + +When you need to generate ZSKs for the zone "example.com" for the next year, +given a ``dnssec-policy`` named "mypolicy": + +:: + + dnssec-ksr -i now -e +1y -k mypolicy -l named.conf keygen example.com + +Creating a KSR for the same zone and period can be done with: + +:: + + dnssec-ksr -i now -e +1y -k mypolicy -l named.conf request example.com > ksr.txt + +Typically you would now transfer the KSR to the system that has access to +the KSK. + +Signing the KSR created above can be done with: + +:: + + dnssec-ksr -i now -e +1y -k kskpolicy -l named.conf -f ksr.txt sign example.com + +Make sure that the DNSSEC parameters in ``kskpolicy`` match those +in ``mypolicy``. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, +:iscman:`dnssec-signzone(8) `, +BIND 9 Administrator Reference Manual. diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c new file mode 100644 index 0000000..01595a1 --- /dev/null +++ b/bin/dnssec/dnssec-revoke.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-revoke"; + +static isc_mem_t *mctx = NULL; + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); + fprintf(stderr, " -f: force overwrite\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, " -K directory: use directory for key files\n"); + fprintf(stderr, " -r: remove old keyfiles after " + "creating revoked version\n"); + fprintf(stderr, " -v level: set level of verbosity\n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) { + isc_result_t result; + const char *engine = NULL; + char const *filename = NULL; + char *dir = NULL; + char newname[1024], oldname[1024]; + char keystr[DST_KEY_FORMATSIZE]; + char *endp; + int ch; + dst_key_t *key = NULL; + uint32_t flags; + isc_buffer_t buf; + bool force = false; + bool removefile = false; + bool id = false; + + if (argc == 1) { + usage(); + } + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + + while ((ch = isc_commandline_parse(argc, argv, "E:fK:rRhv:V")) != -1) { + switch (ch) { + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = true; + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + dir = isc_mem_strdup(mctx, isc_commandline_argument); + break; + case 'r': + removefile = true; + break; + case 'R': + id = true; + break; + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + if (argc < isc_commandline_index + 1 || + argv[isc_commandline_index] == NULL) + { + fatal("The key file name was not specified"); + } + if (argc > isc_commandline_index + 1) { + fatal("Extraneous arguments"); + } + + if (dir != NULL) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &dir, &filename); + if (result != ISC_R_SUCCESS) { + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + } + if (strcmp(dir, ".") == 0) { + isc_mem_free(mctx, dir); + dir = NULL; + } + } + + result = dst_lib_init(mctx, engine); + if (result != ISC_R_SUCCESS) { + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + } + + result = dst_key_fromnamedfile( + filename, dir, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &key); + if (result != ISC_R_SUCCESS) { + fatal("Invalid keyfile name %s: %s", filename, + isc_result_totext(result)); + } + + if (id) { + fprintf(stdout, "%u\n", dst_key_rid(key)); + goto cleanup; + } + dst_key_format(key, keystr, sizeof(keystr)); + + if (verbose > 2) { + fprintf(stderr, "%s: %s\n", program, keystr); + } + + if (force) { + set_keyversion(key); + } else { + check_keyversion(key, keystr); + } + + flags = dst_key_flags(key); + if ((flags & DNS_KEYFLAG_REVOKE) == 0) { + isc_stdtime_t now = isc_stdtime_now(); + + if ((flags & DNS_KEYFLAG_KSK) == 0) { + fprintf(stderr, + "%s: warning: Key is not flagged " + "as a KSK. Revoking a ZSK is " + "legal, but undefined.\n", + program); + } + + dst_key_settime(key, DST_TIME_REVOKE, now); + + dst_key_setflags(key, flags | DNS_KEYFLAG_REVOKE); + + isc_buffer_init(&buf, newname, sizeof(newname)); + dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); + + if (access(newname, F_OK) == 0 && !force) { + fatal("Key file %s already exists; " + "use -f to force overwrite", + newname); + } + + result = dst_key_tofile(key, DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, + dir); + if (result != ISC_R_SUCCESS) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + + isc_buffer_clear(&buf); + dst_key_buildfilename(key, 0, dir, &buf); + printf("%s\n", newname); + + /* + * Remove old key file, if told to (and if + * it isn't the same as the new file) + */ + if (removefile) { + isc_buffer_init(&buf, oldname, sizeof(oldname)); + dst_key_setflags(key, flags & ~DNS_KEYFLAG_REVOKE); + dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); + if (strcmp(oldname, newname) == 0) { + goto cleanup; + } + (void)unlink(oldname); + isc_buffer_clear(&buf); + dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); + (void)unlink(oldname); + } + } else { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Key %s is already revoked", keystr); + } + +cleanup: + dst_key_free(&key); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + if (dir != NULL) { + isc_mem_free(mctx, dir); + } + isc_mem_destroy(&mctx); + + return 0; +} diff --git a/bin/dnssec/dnssec-revoke.rst b/bin/dnssec/dnssec-revoke.rst new file mode 100644 index 0000000..052865f --- /dev/null +++ b/bin/dnssec/dnssec-revoke.rst @@ -0,0 +1,78 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-revoke +.. program:: dnssec-revoke +.. _man_dnssec-revoke: + +dnssec-revoke - set the REVOKED bit on a DNSSEC key +--------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-revoke` [**-hr**] [**-v** level] [**-V**] [**-K** directory] [**-E** engine] [**-f**] [**-R**] {keyfile} + +Description +~~~~~~~~~~~ + +:program:`dnssec-revoke` reads a DNSSEC key file, sets the REVOKED bit on the +key as defined in :rfc:`5011`, and creates a new pair of key files +containing the now-revoked key. + +Options +~~~~~~~ + +.. option:: -h + + This option emits a usage message and exits. + +.. option:: -K directory + + This option sets the directory in which the key files are to reside. + +.. option:: -r + + This option indicates to remove the original keyset files after writing the new keyset files. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -V + + This option prints version information. + +.. option:: -E engine + + This option specifies the cryptographic hardware to use, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -f + + This option indicates a forced overwrite and causes :program:`dnssec-revoke` to write the new key pair, + even if a file already exists matching the algorithm and key ID of + the revoked key. + +.. option:: -R + + This option prints the key tag of the key with the REVOKE bit set, but does not + revoke the key. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, BIND 9 Administrator Reference Manual, :rfc:`5011`. diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c new file mode 100644 index 0000000..f61b63a --- /dev/null +++ b/bin/dnssec/dnssec-settime.c @@ -0,0 +1,964 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-settime"; + +static isc_mem_t *mctx = NULL; + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s [options] keyfile\n\n", program); + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + fprintf(stderr, "General options:\n"); + fprintf(stderr, " -E engine: specify OpenSSL engine\n"); + fprintf(stderr, " -f: force update of old-style " + "keys\n"); + fprintf(stderr, " -K directory: set key file location\n"); + fprintf(stderr, " -L ttl: set default key TTL\n"); + fprintf(stderr, " -v level: set level of verbosity\n"); + fprintf(stderr, " -V: print version information\n"); + fprintf(stderr, " -h: help\n"); + fprintf(stderr, "Timing options:\n"); + fprintf(stderr, " -P date/[+-]offset/none: set/unset key " + "publication date\n"); + fprintf(stderr, " -P ds date/[+-]offset/none: set/unset " + "DS publication date\n"); + fprintf(stderr, " -P sync date/[+-]offset/none: set/unset " + "CDS and CDNSKEY publication date\n"); + fprintf(stderr, " -A date/[+-]offset/none: set/unset key " + "activation date\n"); + fprintf(stderr, " -R date/[+-]offset/none: set/unset key " + "revocation date\n"); + fprintf(stderr, " -I date/[+-]offset/none: set/unset key " + "inactivation date\n"); + fprintf(stderr, " -D date/[+-]offset/none: set/unset key " + "deletion date\n"); + fprintf(stderr, " -D ds date/[+-]offset/none: set/unset " + "DS deletion date\n"); + fprintf(stderr, " -D sync date/[+-]offset/none: set/unset " + "CDS and CDNSKEY deletion date\n"); + fprintf(stderr, " -S : generate a successor to an existing " + "key\n"); + fprintf(stderr, " -i : prepublication interval for " + "successor key " + "(default: 30 days)\n"); + fprintf(stderr, "Key state options:\n"); + fprintf(stderr, " -s: update key state file (default no)\n"); + fprintf(stderr, " -g state: set the goal state for this key\n"); + fprintf(stderr, " -d state date/[+-]offset: set the DS state\n"); + fprintf(stderr, " -k state date/[+-]offset: set the DNSKEY state\n"); + fprintf(stderr, " -r state date/[+-]offset: set the RRSIG (KSK) " + "state\n"); + fprintf(stderr, " -z state date/[+-]offset: set the RRSIG (ZSK) " + "state\n"); + fprintf(stderr, "Printing options:\n"); + fprintf(stderr, " -p C/P/Psync/A/R/I/D/Dsync/all: print a " + "particular time value or values\n"); + fprintf(stderr, " -u: print times in unix epoch " + "format\n"); + fprintf(stderr, "Output:\n"); + fprintf(stderr, " K++.key, " + "K++.private\n"); + + exit(EXIT_FAILURE); +} + +static void +printtime(dst_key_t *key, int type, const char *tag, bool epoch, FILE *stream) { + isc_result_t result; + isc_stdtime_t when; + + if (tag != NULL) { + fprintf(stream, "%s: ", tag); + } + + result = dst_key_gettime(key, type, &when); + if (result == ISC_R_NOTFOUND) { + fprintf(stream, "UNSET\n"); + } else if (epoch) { + fprintf(stream, "%d\n", (int)when); + } else { + time_t now = when; + struct tm t, *tm = localtime_r(&now, &t); + unsigned int flen; + char timebuf[80]; + + if (tm == NULL) { + fprintf(stream, "INVALID\n"); + return; + } + + flen = strftime(timebuf, sizeof(timebuf), + "%a %b %e %H:%M:%S %Y", tm); + INSIST(flen > 0U && flen < sizeof(timebuf)); + fprintf(stream, "%s\n", timebuf); + } +} + +static void +writekey(dst_key_t *key, const char *directory, bool write_state) { + char newname[1024]; + char keystr[DST_KEY_FORMATSIZE]; + isc_buffer_t buf; + isc_result_t result; + int options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE; + + if (write_state) { + options |= DST_TYPE_STATE; + } + + isc_buffer_init(&buf, newname, sizeof(newname)); + result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build public key filename: %s", + isc_result_totext(result)); + } + + result = dst_key_tofile(key, options, directory); + if (result != ISC_R_SUCCESS) { + dst_key_format(key, keystr, sizeof(keystr)); + fatal("Failed to write key %s: %s", keystr, + isc_result_totext(result)); + } + printf("%s\n", newname); + + isc_buffer_clear(&buf); + result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build private key filename: %s", + isc_result_totext(result)); + } + printf("%s\n", newname); + + if (write_state) { + isc_buffer_clear(&buf); + result = dst_key_buildfilename(key, DST_TYPE_STATE, directory, + &buf); + if (result != ISC_R_SUCCESS) { + fatal("Failed to build key state filename: %s", + isc_result_totext(result)); + } + printf("%s\n", newname); + } +} + +int +main(int argc, char **argv) { + isc_result_t result; + const char *engine = NULL; + const char *filename = NULL; + char *directory = NULL; + char keystr[DST_KEY_FORMATSIZE]; + char *endp, *p; + int ch; + const char *predecessor = NULL; + dst_key_t *prevkey = NULL; + dst_key_t *key = NULL; + dns_name_t *name = NULL; + dns_secalg_t alg = 0; + unsigned int size = 0; + uint16_t flags = 0; + int prepub = -1; + int options; + dns_ttl_t ttl = 0; + isc_stdtime_t dstime = 0, dnskeytime = 0; + isc_stdtime_t krrsigtime = 0, zrrsigtime = 0; + isc_stdtime_t pub = 0, act = 0, rev = 0, inact = 0, del = 0; + isc_stdtime_t prevact = 0, previnact = 0, prevdel = 0; + dst_key_state_t goal = DST_KEY_STATE_NA; + dst_key_state_t ds = DST_KEY_STATE_NA; + dst_key_state_t dnskey = DST_KEY_STATE_NA; + dst_key_state_t krrsig = DST_KEY_STATE_NA; + dst_key_state_t zrrsig = DST_KEY_STATE_NA; + bool setgoal = false, setds = false, setdnskey = false; + bool setkrrsig = false, setzrrsig = false; + bool setdstime = false, setdnskeytime = false; + bool setkrrsigtime = false, setzrrsigtime = false; + bool setpub = false, setact = false; + bool setrev = false, setinact = false; + bool setdel = false, setttl = false; + bool unsetpub = false, unsetact = false; + bool unsetrev = false, unsetinact = false; + bool unsetdel = false; + bool printcreate = false, printpub = false; + bool printact = false, printrev = false; + bool printinact = false, printdel = false; + bool force = false; + bool epoch = false; + bool changed = false; + bool write_state = false; + isc_log_t *log = NULL; + isc_stdtime_t syncadd = 0, syncdel = 0; + bool unsetsyncadd = false, setsyncadd = false; + bool unsetsyncdel = false, setsyncdel = false; + bool printsyncadd = false, printsyncdel = false; + isc_stdtime_t dsadd = 0, dsdel = 0; + bool unsetdsadd = false, setdsadd = false; + bool unsetdsdel = false, setdsdel = false; + bool printdsadd = false, printdsdel = false; + isc_stdtime_t now = isc_stdtime_now(); + + options = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE; + + if (argc == 1) { + usage(); + } + + isc_mem_create(&mctx); + + setup_logging(mctx, &log); + + isc_commandline_errprint = false; + +#define CMDLINE_FLAGS "A:D:d:E:fg:hI:i:K:k:L:P:p:R:r:S:suv:Vz:" + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'A': + if (setact || unsetact) { + fatal("-A specified more than once"); + } + + changed = true; + act = strtotime(isc_commandline_argument, now, now, + &setact); + unsetact = !setact; + break; + case 'D': + /* -Dsync ? */ + if (isoptarg("sync", argv, usage)) { + if (unsetsyncdel || setsyncdel) { + fatal("-D sync specified more than " + "once"); + } + + changed = true; + syncdel = strtotime(isc_commandline_argument, + now, now, &setsyncdel); + unsetsyncdel = !setsyncdel; + break; + } + /* -Dds ? */ + if (isoptarg("ds", argv, usage)) { + if (unsetdsdel || setdsdel) { + fatal("-D ds specified more than once"); + } + + changed = true; + dsdel = strtotime(isc_commandline_argument, now, + now, &setdsdel); + unsetdsdel = !setdsdel; + break; + } + /* -Ddnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setdel || unsetdel) { + fatal("-D specified more than once"); + } + + changed = true; + del = strtotime(isc_commandline_argument, now, now, + &setdel); + unsetdel = !setdel; + break; + case 'd': + if (setds) { + fatal("-d specified more than once"); + } + + ds = strtokeystate(isc_commandline_argument); + setds = true; + /* time */ + (void)isoptarg(isc_commandline_argument, argv, usage); + dstime = strtotime(isc_commandline_argument, now, now, + &setdstime); + break; + case 'E': + engine = isc_commandline_argument; + break; + case 'f': + force = true; + break; + case 'g': + if (setgoal) { + fatal("-g specified more than once"); + } + + goal = strtokeystate(isc_commandline_argument); + if (goal != DST_KEY_STATE_NA && + goal != DST_KEY_STATE_HIDDEN && + goal != DST_KEY_STATE_OMNIPRESENT) + { + fatal("-g must be either none, hidden, or " + "omnipresent"); + } + setgoal = true; + break; + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + case 'I': + if (setinact || unsetinact) { + fatal("-I specified more than once"); + } + + changed = true; + inact = strtotime(isc_commandline_argument, now, now, + &setinact); + unsetinact = !setinact; + break; + case 'i': + prepub = strtottl(isc_commandline_argument); + break; + case 'K': + /* + * We don't have to copy it here, but do it to + * simplify cleanup later + */ + directory = isc_mem_strdup(mctx, + isc_commandline_argument); + break; + case 'k': + if (setdnskey) { + fatal("-k specified more than once"); + } + + dnskey = strtokeystate(isc_commandline_argument); + setdnskey = true; + /* time */ + (void)isoptarg(isc_commandline_argument, argv, usage); + dnskeytime = strtotime(isc_commandline_argument, now, + now, &setdnskeytime); + break; + case 'L': + ttl = strtottl(isc_commandline_argument); + setttl = true; + break; + case 'P': + /* -Psync ? */ + if (isoptarg("sync", argv, usage)) { + if (unsetsyncadd || setsyncadd) { + fatal("-P sync specified more than " + "once"); + } + + changed = true; + syncadd = strtotime(isc_commandline_argument, + now, now, &setsyncadd); + unsetsyncadd = !setsyncadd; + break; + } + /* -Pds ? */ + if (isoptarg("ds", argv, usage)) { + if (unsetdsadd || setdsadd) { + fatal("-P ds specified more than once"); + } + + changed = true; + dsadd = strtotime(isc_commandline_argument, now, + now, &setdsadd); + unsetdsadd = !setdsadd; + break; + } + /* -Pdnskey ? */ + (void)isoptarg("dnskey", argv, usage); + if (setpub || unsetpub) { + fatal("-P specified more than once"); + } + + changed = true; + pub = strtotime(isc_commandline_argument, now, now, + &setpub); + unsetpub = !setpub; + break; + case 'p': + p = isc_commandline_argument; + if (!strcasecmp(p, "all")) { + printcreate = true; + printpub = true; + printact = true; + printrev = true; + printinact = true; + printdel = true; + printsyncadd = true; + printsyncdel = true; + printdsadd = true; + printdsdel = true; + break; + } + + do { + switch (*p++) { + case 'A': + printact = true; + break; + case 'C': + printcreate = true; + break; + case 'D': + if (!strncmp(p, "sync", 4)) { + p += 4; + printsyncdel = true; + break; + } + if (!strncmp(p, "ds", 2)) { + p += 2; + printdsdel = true; + break; + } + printdel = true; + break; + case 'I': + printinact = true; + break; + case 'P': + if (!strncmp(p, "sync", 4)) { + p += 4; + printsyncadd = true; + break; + } + if (!strncmp(p, "ds", 2)) { + p += 2; + printdsadd = true; + break; + } + printpub = true; + break; + case 'R': + printrev = true; + break; + case ' ': + break; + default: + usage(); + break; + } + } while (*p != '\0'); + break; + case 'R': + if (setrev || unsetrev) { + fatal("-R specified more than once"); + } + + changed = true; + rev = strtotime(isc_commandline_argument, now, now, + &setrev); + unsetrev = !setrev; + break; + case 'r': + if (setkrrsig) { + fatal("-r specified more than once"); + } + + krrsig = strtokeystate(isc_commandline_argument); + setkrrsig = true; + /* time */ + (void)isoptarg(isc_commandline_argument, argv, usage); + krrsigtime = strtotime(isc_commandline_argument, now, + now, &setkrrsigtime); + break; + case 'S': + predecessor = isc_commandline_argument; + break; + case 's': + write_state = true; + break; + case 'u': + epoch = true; + break; + case 'V': + /* Does not return. */ + version(program); + case 'v': + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("-v must be followed by a number"); + } + break; + case 'z': + if (setzrrsig) { + fatal("-z specified more than once"); + } + + zrrsig = strtokeystate(isc_commandline_argument); + setzrrsig = true; + (void)isoptarg(isc_commandline_argument, argv, usage); + zrrsigtime = strtotime(isc_commandline_argument, now, + now, &setzrrsigtime); + break; + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + if (argc < isc_commandline_index + 1 || + argv[isc_commandline_index] == NULL) + { + fatal("The key file name was not specified"); + } + if (argc > isc_commandline_index + 1) { + fatal("Extraneous arguments"); + } + + if ((setgoal || setds || setdnskey || setkrrsig || setzrrsig) && + !write_state) + { + fatal("Options -g, -d, -k, -r and -z require -s to be set"); + } + + result = dst_lib_init(mctx, engine); + if (result != ISC_R_SUCCESS) { + fatal("Could not initialize dst: %s", + isc_result_totext(result)); + } + + if (predecessor != NULL) { + int major, minor; + + if (prepub == -1) { + prepub = (30 * 86400); + } + + if (setpub || unsetpub) { + fatal("-S and -P cannot be used together"); + } + if (setact || unsetact) { + fatal("-S and -A cannot be used together"); + } + + result = dst_key_fromnamedfile(predecessor, directory, options, + mctx, &prevkey); + if (result != ISC_R_SUCCESS) { + fatal("Invalid keyfile %s: %s", filename, + isc_result_totext(result)); + } + if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey)) + { + fatal("%s is not a private key", filename); + } + + name = dst_key_name(prevkey); + alg = dst_key_alg(prevkey); + size = dst_key_size(prevkey); + flags = dst_key_flags(prevkey); + + dst_key_format(prevkey, keystr, sizeof(keystr)); + dst_key_getprivateformat(prevkey, &major, &minor); + if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { + fatal("Predecessor has incompatible format " + "version %d.%d\n\t", + major, minor); + } + + result = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &prevact); + if (result != ISC_R_SUCCESS) { + fatal("Predecessor has no activation date. " + "You must set one before\n\t" + "generating a successor."); + } + + result = dst_key_gettime(prevkey, DST_TIME_INACTIVE, + &previnact); + if (result != ISC_R_SUCCESS) { + fatal("Predecessor has no inactivation date. " + "You must set one before\n\t" + "generating a successor."); + } + + pub = previnact - prepub; + act = previnact; + + if ((previnact - prepub) < now && prepub != 0) { + fatal("Time until predecessor inactivation is\n\t" + "shorter than the prepublication interval. " + "Either change\n\t" + "predecessor inactivation date, or use the -i " + "option to set\n\t" + "a shorter prepublication interval."); + } + + result = dst_key_gettime(prevkey, DST_TIME_DELETE, &prevdel); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "%s: warning: Predecessor has no " + "removal date;\n\t" + "it will remain in the zone " + "indefinitely after rollover.\n", + program); + } else if (prevdel < previnact) { + fprintf(stderr, + "%s: warning: Predecessor is " + "scheduled to be deleted\n\t" + "before it is scheduled to be " + "inactive.\n", + program); + } + + changed = setpub = setact = true; + } else { + if (prepub < 0) { + prepub = 0; + } + + if (prepub > 0) { + if (setpub && setact && (act - prepub) < pub) { + fatal("Activation and publication dates " + "are closer together than the\n\t" + "prepublication interval."); + } + + if (setpub && !setact) { + setact = true; + act = pub + prepub; + } else if (setact && !setpub) { + setpub = true; + pub = act - prepub; + } + + if ((act - prepub) < now) { + fatal("Time until activation is shorter " + "than the\n\tprepublication interval."); + } + } + } + + if (directory != NULL) { + filename = argv[isc_commandline_index]; + } else { + result = isc_file_splitpath(mctx, argv[isc_commandline_index], + &directory, &filename); + if (result != ISC_R_SUCCESS) { + fatal("cannot process filename %s: %s", + argv[isc_commandline_index], + isc_result_totext(result)); + } + } + + result = dst_key_fromnamedfile(filename, directory, options, mctx, + &key); + if (result != ISC_R_SUCCESS) { + fatal("Invalid keyfile %s: %s", filename, + isc_result_totext(result)); + } + + if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) { + fatal("%s is not a private key", filename); + } + + dst_key_format(key, keystr, sizeof(keystr)); + + if (predecessor != NULL) { + if (!dns_name_equal(name, dst_key_name(key))) { + fatal("Key name mismatch"); + } + if (alg != dst_key_alg(key)) { + fatal("Key algorithm mismatch"); + } + if (size != dst_key_size(key)) { + fatal("Key size mismatch"); + } + if (flags != dst_key_flags(key)) { + fatal("Key flags mismatch"); + } + } + + prevdel = previnact = 0; + if ((setdel && setinact && del < inact) || + (dst_key_gettime(key, DST_TIME_INACTIVE, &previnact) == + ISC_R_SUCCESS && + setdel && !setinact && !unsetinact && del < previnact) || + (dst_key_gettime(key, DST_TIME_DELETE, &prevdel) == ISC_R_SUCCESS && + setinact && !setdel && !unsetdel && prevdel < inact) || + (!setdel && !unsetdel && !setinact && !unsetinact && prevdel != 0 && + prevdel < previnact)) + { + fprintf(stderr, + "%s: warning: Key is scheduled to " + "be deleted before it is\n\t" + "scheduled to be inactive.\n", + program); + } + + if (force) { + set_keyversion(key); + } else { + check_keyversion(key, keystr); + } + + if (verbose > 2) { + fprintf(stderr, "%s: %s\n", program, keystr); + } + + /* + * Set time values. + */ + if (setpub) { + dst_key_settime(key, DST_TIME_PUBLISH, pub); + } else if (unsetpub) { + dst_key_unsettime(key, DST_TIME_PUBLISH); + } + + if (setact) { + dst_key_settime(key, DST_TIME_ACTIVATE, act); + } else if (unsetact) { + dst_key_unsettime(key, DST_TIME_ACTIVATE); + } + + if (setrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) { + fprintf(stderr, + "%s: warning: Key %s is already " + "revoked; changing the revocation date " + "will not affect this.\n", + program, keystr); + } + if ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0) { + fprintf(stderr, + "%s: warning: Key %s is not flagged as " + "a KSK, but -R was used. Revoking a " + "ZSK is legal, but undefined.\n", + program, keystr); + } + dst_key_settime(key, DST_TIME_REVOKE, rev); + } else if (unsetrev) { + if ((dst_key_flags(key) & DNS_KEYFLAG_REVOKE) != 0) { + fprintf(stderr, + "%s: warning: Key %s is already " + "revoked; removing the revocation date " + "will not affect this.\n", + program, keystr); + } + dst_key_unsettime(key, DST_TIME_REVOKE); + } + + if (setinact) { + dst_key_settime(key, DST_TIME_INACTIVE, inact); + } else if (unsetinact) { + dst_key_unsettime(key, DST_TIME_INACTIVE); + } + + if (setdel) { + dst_key_settime(key, DST_TIME_DELETE, del); + } else if (unsetdel) { + dst_key_unsettime(key, DST_TIME_DELETE); + } + + if (setsyncadd) { + dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd); + } else if (unsetsyncadd) { + dst_key_unsettime(key, DST_TIME_SYNCPUBLISH); + } + + if (setsyncdel) { + dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel); + } else if (unsetsyncdel) { + dst_key_unsettime(key, DST_TIME_SYNCDELETE); + } + + if (setdsadd) { + dst_key_settime(key, DST_TIME_DSPUBLISH, dsadd); + } else if (unsetdsadd) { + dst_key_unsettime(key, DST_TIME_DSPUBLISH); + } + + if (setdsdel) { + dst_key_settime(key, DST_TIME_DSDELETE, dsdel); + } else if (unsetdsdel) { + dst_key_unsettime(key, DST_TIME_DSDELETE); + } + + if (setttl) { + dst_key_setttl(key, ttl); + } + + if (predecessor != NULL && prevkey != NULL) { + dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key)); + dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey)); + } + + /* + * No metadata changes were made but we're forcing an upgrade + * to the new format anyway: use "-P now -A now" as the default + */ + if (force && !changed) { + dst_key_settime(key, DST_TIME_PUBLISH, now); + dst_key_settime(key, DST_TIME_ACTIVATE, now); + changed = true; + } + + /* + * Make sure the key state goals are written. + */ + if (write_state) { + if (setgoal) { + if (goal == DST_KEY_STATE_NA) { + dst_key_unsetstate(key, DST_KEY_GOAL); + } else { + dst_key_setstate(key, DST_KEY_GOAL, goal); + } + changed = true; + } + if (setds) { + if (ds == DST_KEY_STATE_NA) { + dst_key_unsetstate(key, DST_KEY_DS); + dst_key_unsettime(key, DST_TIME_DS); + } else { + dst_key_setstate(key, DST_KEY_DS, ds); + dst_key_settime(key, DST_TIME_DS, dstime); + } + changed = true; + } + if (setdnskey) { + if (dnskey == DST_KEY_STATE_NA) { + dst_key_unsetstate(key, DST_KEY_DNSKEY); + dst_key_unsettime(key, DST_TIME_DNSKEY); + } else { + dst_key_setstate(key, DST_KEY_DNSKEY, dnskey); + dst_key_settime(key, DST_TIME_DNSKEY, + dnskeytime); + } + changed = true; + } + if (setkrrsig) { + if (krrsig == DST_KEY_STATE_NA) { + dst_key_unsetstate(key, DST_KEY_KRRSIG); + dst_key_unsettime(key, DST_TIME_KRRSIG); + } else { + dst_key_setstate(key, DST_KEY_KRRSIG, krrsig); + dst_key_settime(key, DST_TIME_KRRSIG, + krrsigtime); + } + changed = true; + } + if (setzrrsig) { + if (zrrsig == DST_KEY_STATE_NA) { + dst_key_unsetstate(key, DST_KEY_ZRRSIG); + dst_key_unsettime(key, DST_TIME_ZRRSIG); + } else { + dst_key_setstate(key, DST_KEY_ZRRSIG, zrrsig); + dst_key_settime(key, DST_TIME_ZRRSIG, + zrrsigtime); + } + changed = true; + } + } + + if (!changed && setttl) { + changed = true; + } + + /* + * Print out time values, if -p was used. + */ + if (printcreate) { + printtime(key, DST_TIME_CREATED, "Created", epoch, stdout); + } + + if (printpub) { + printtime(key, DST_TIME_PUBLISH, "Publish", epoch, stdout); + } + + if (printact) { + printtime(key, DST_TIME_ACTIVATE, "Activate", epoch, stdout); + } + + if (printrev) { + printtime(key, DST_TIME_REVOKE, "Revoke", epoch, stdout); + } + + if (printinact) { + printtime(key, DST_TIME_INACTIVE, "Inactive", epoch, stdout); + } + + if (printdel) { + printtime(key, DST_TIME_DELETE, "Delete", epoch, stdout); + } + + if (printsyncadd) { + printtime(key, DST_TIME_SYNCPUBLISH, "SYNC Publish", epoch, + stdout); + } + + if (printsyncdel) { + printtime(key, DST_TIME_SYNCDELETE, "SYNC Delete", epoch, + stdout); + } + + if (printdsadd) { + printtime(key, DST_TIME_DSPUBLISH, "DS Publish", epoch, stdout); + } + + if (printdsdel) { + printtime(key, DST_TIME_DSDELETE, "DS Delete", epoch, stdout); + } + + if (changed) { + writekey(key, directory, write_state); + if (predecessor != NULL && prevkey != NULL) { + writekey(prevkey, directory, write_state); + } + } + + if (prevkey != NULL) { + dst_key_free(&prevkey); + } + dst_key_free(&key); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + cleanup_logging(&log); + isc_mem_free(mctx, directory); + isc_mem_destroy(&mctx); + + return 0; +} diff --git a/bin/dnssec/dnssec-settime.rst b/bin/dnssec/dnssec-settime.rst new file mode 100644 index 0000000..5cb4ea8 --- /dev/null +++ b/bin/dnssec/dnssec-settime.rst @@ -0,0 +1,271 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-settime +.. program:: dnssec-settime +.. _man_dnssec-settime: + +dnssec-settime: set the key timing metadata for a DNSSEC key +------------------------------------------------------------ + +Synopsis +~~~~~~~~ + +:program:`dnssec-settime` [**-f**] [**-K** directory] [**-L** ttl] [**-P** date/offset] [**-P** ds date/offset] [**-P** sync date/offset] [**-A** date/offset] [**-R** date/offset] [**-I** date/offset] [**-D** date/offset] [**-D** ds date/offset] [**-D** sync date/offset] [**-S** key] [**-i** interval] [**-h**] [**-V**] [**-v** level] [**-E** engine] {keyfile} [**-s**] [**-g** state] [**-d** state date/offset] [**-k** state date/offset] [**-r** state date/offset] [**-z** state date/offset] + +Description +~~~~~~~~~~~ + +:program:`dnssec-settime` reads a DNSSEC private key file and sets the key +timing metadata as specified by the :option:`-P`, :option:`-A`, :option:`-R`, +:option:`-I`, and :option:`-D` options. The metadata can then be used by +:iscman:`dnssec-signzone` or other signing software to determine when a key is +to be published, whether it should be used for signing a zone, etc. + +If none of these options is set on the command line, +:program:`dnssec-settime` simply prints the key timing metadata already stored +in the key. + +When key metadata fields are changed, both files of a key pair +(``Knnnn.+aaa+iiiii.key`` and ``Knnnn.+aaa+iiiii.private``) are +regenerated. + +Metadata fields are stored in the private file. A +human-readable description of the metadata is also placed in comments in +the key file. The private file's permissions are always set to be +inaccessible to anyone other than the owner (mode 0600). + +When working with state files, it is possible to update the timing metadata in +those files as well with :option:`-s`. With this option, it is also possible +to update key states with :option:`-d` (DS), :option:`-k` (DNSKEY), :option:`-r` +(RRSIG of KSK), or :option:`-z` (RRSIG of ZSK). Allowed states are HIDDEN, +RUMOURED, OMNIPRESENT, and UNRETENTIVE. + +The goal state of the key can also be set with :option:`-g`. This should be either +HIDDEN or OMNIPRESENT, representing whether the key should be removed from the +zone or published. + +It is NOT RECOMMENDED to manipulate state files manually, except for testing +purposes. + +Options +~~~~~~~ + +.. option:: -f + + This option forces an update of an old-format key with no metadata fields. Without + this option, :program:`dnssec-settime` fails when attempting to update a + legacy key. With this option, the key is recreated in the new + format, but with the original key data retained. The key's creation + date is set to the present time. If no other values are + specified, then the key's publication and activation dates are also + set to the present time. + +.. option:: -K directory + + This option sets the directory in which the key files are to reside. + +.. option:: -L ttl + + This option sets the default TTL to use for this key when it is converted into a + DNSKEY RR. This is the TTL used when the key is imported into a zone, + unless there was already a DNSKEY RRset in + place, in which case the existing TTL takes precedence. If this + value is not set and there is no existing DNSKEY RRset, the TTL + defaults to the SOA TTL. Setting the default TTL to ``0`` or ``none`` + removes it from the key. + +.. option:: -h + + This option emits a usage message and exits. + +.. option:: -V + + This option prints version information. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -E engine + + This option specifies the cryptographic hardware to use, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +Timing Options +~~~~~~~~~~~~~~ + +Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS +(which is the format used inside key files), +or 'Day Mon DD HH:MM:SS YYYY' (as printed by ``dnssec-settime -p``), +or UNIX epoch time (as printed by ``dnssec-settime -up``), +or the literal ``now``. + +The argument can be followed by ``+`` or ``-`` and an offset from the +given time. The literal ``now`` can be omitted before an offset. The +offset can be followed by one of the suffixes ``y``, ``mo``, ``w``, +``d``, ``h``, or ``mi``, so that it is computed in years (defined as +365 24-hour days, ignoring leap years), months (defined as 30 24-hour +days), weeks, days, hours, or minutes, respectively. Without a suffix, +the offset is computed in seconds. + +To unset a date, use ``none``, ``never``, or ``unset``. + +All these formats are case-insensitive. + +.. option:: -P date/offset + + This option sets the date on which a key is to be published to the zone. After + that date, the key is included in the zone but is not used + to sign it. + + .. program:: dnssec-settime -P + .. option:: ds date/offset + + This option sets the date on which DS records that match this key have been + seen in the parent zone. + + .. option:: sync date/offset + + This option sets the date on which CDS and CDNSKEY records that match this key + are to be published to the zone. + +.. program:: dnssec-settime + +.. option:: -A date/offset + + This option sets the date on which the key is to be activated. After that date, + the key is included in the zone and used to sign it. + +.. option:: -R date/offset + + This option sets the date on which the key is to be revoked. After that date, the + key is flagged as revoked. It is included in the zone and + is used to sign it. + +.. option:: -I date/offset + + This option sets the date on which the key is to be retired. After that date, the + key is still included in the zone, but it is not used to + sign it. + +.. option:: -D date/offset + + This option sets the date on which the key is to be deleted. After that date, the + key is no longer included in the zone. (However, it may remain in the key + repository.) + + .. program:: dnssec-settime -D + .. option:: ds date/offset + + This option sets the date on which the DS records that match this key have + been seen removed from the parent zone. + + .. option:: sync date/offset + + This option sets the date on which the CDS and CDNSKEY records that match this + key are to be deleted. + +.. program:: dnssec-settime + +.. option:: -S predecessor key + + This option selects a key for which the key being modified is an explicit + successor. The name, algorithm, size, and type of the predecessor key + must exactly match those of the key being modified. The activation + date of the successor key is set to the inactivation date of the + predecessor. The publication date is set to the activation date + minus the prepublication interval, which defaults to 30 days. + +.. option:: -i interval + + This option sets the prepublication interval for a key. If set, then the + publication and activation dates must be separated by at least this + much time. If the activation date is specified but the publication + date is not, the publication date defaults to this much time + before the activation date; conversely, if the publication date is + specified but not the activation date, activation is set to + this much time after publication. + + If the key is being created as an explicit successor to another key, + then the default prepublication interval is 30 days; otherwise it is + zero. + + As with date offsets, if the argument is followed by one of the + suffixes ``y``, ``mo``, ``w``, ``d``, ``h``, or ``mi``, the interval is + measured in years, months, weeks, days, hours, or minutes, + respectively. Without a suffix, the interval is measured in seconds. + +Key State Options +~~~~~~~~~~~~~~~~~ + +To test dnssec-policy it may be necessary to construct keys with artificial +state information; these options are used by the testing framework for that +purpose, but should never be used in production. + +Known key states are HIDDEN, RUMOURED, OMNIPRESENT, and UNRETENTIVE. + +.. option:: -s + + This option indicates that when setting key timing data, the state file should also be updated. + +.. option:: -g state + + This option sets the goal state for this key. Must be HIDDEN or OMNIPRESENT. + +.. option:: -d state date/offset + + This option sets the DS state for this key as of the specified date, offset from the current date. + +.. option:: -k state date/offset + + This option sets the DNSKEY state for this key as of the specified date, offset from the current date. + +.. option:: -r state date/offset + + This option sets the RRSIG (KSK) state for this key as of the specified date, offset from the current date. + +.. option:: -z state date/offset + + This option sets the RRSIG (ZSK) state for this key as of the specified date, offset from the current date. + +Printing Options +~~~~~~~~~~~~~~~~ + +:program:`dnssec-settime` can also be used to print the timing metadata +associated with a key. + +.. option:: -u + + This option indicates that times should be printed in Unix epoch format. + +.. option:: -p C/P/Pds/Psync/A/R/I/D/Dds/Dsync/all + + This option prints a specific metadata value or set of metadata values. + The :option:`-p` option may be followed by one or more of the following letters or + strings to indicate which value or values to print: ``C`` for the + creation date, ``P`` for the publication date, ``Pds` for the DS publication + date, ``Psync`` for the CDS and CDNSKEY publication date, ``A`` for the + activation date, ``R`` for the revocation date, ``I`` for the inactivation + date, ``D`` for the deletion date, ``Dds`` for the DS deletion date, + and ``Dsync`` for the CDS and CDNSKEY deletion date. To print all of the + metadata, use ``all``. + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, :iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, +:rfc:`5011`. diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c new file mode 100644 index 0000000..c71d416 --- /dev/null +++ b/bin/dnssec/dnssec-signzone.c @@ -0,0 +1,4179 @@ +/* + * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + * + * Portions Copyright (C) Network Associates, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*! \file */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 +#include +#include +#endif + +#include "dnssectool.h" + +const char *program = "dnssec-signzone"; + +typedef struct hashlist hashlist_t; + +static int nsec_datatype = dns_rdatatype_nsec; + +#define check_dns_dbiterator_current(result) \ + check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \ + "dns_dbiterator_current()") + +#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3) +#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) + +#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) + +#define BUFSIZE 2048 +#define MAXDSKEYS 8 + +#define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453) +#define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0) +#define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1) + +#define SOA_SERIAL_KEEP 0 +#define SOA_SERIAL_INCREMENT 1 +#define SOA_SERIAL_UNIXTIME 2 +#define SOA_SERIAL_DATE 3 + +static dns_dnsseckeylist_t keylist; +static unsigned int keycount = 0; +static isc_rwlock_t keylist_lock; +static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now; +static int cycle = -1; +static int jitter = 0; +static bool tryverify = false; +static bool printstats = false; +static isc_mem_t *mctx = NULL; +static dns_ttl_t zone_soa_min_ttl; +static dns_ttl_t soa_ttl; +static FILE *outfp = NULL; +static char *tempfile = NULL; +static const dns_master_style_t *masterstyle; +static dns_masterformat_t inputformat = dns_masterformat_text; +static dns_masterformat_t outputformat = dns_masterformat_text; +static uint32_t rawversion = 1, serialnum = 0; +static bool snset = false; +static atomic_uint_fast32_t nsigned = 0, nretained = 0, ndropped = 0; +static atomic_uint_fast32_t nverified = 0, nverifyfailed = 0; +static const char *directory = NULL, *dsdir = NULL; +static isc_mutex_t namelock; +static isc_nm_t *netmgr = NULL; +static isc_loopmgr_t *loopmgr = NULL; +static dns_db_t *gdb; /* The database */ +static dns_dbversion_t *gversion; /* The database version */ +static dns_dbiterator_t *gdbiter; /* The database iterator */ +static dns_rdataclass_t gclass; /* The class */ +static dns_name_t *gorigin; /* The database origin */ +static int nsec3flags = 0; +static dns_iterations_t nsec3iter = 0U; +static unsigned char saltbuf[255]; +static unsigned char *gsalt = saltbuf; +static size_t salt_length = 0; +static unsigned int nloops = 0; +static atomic_bool shuttingdown; +static atomic_bool finished; +static bool nokeys = false; +static bool removefile = false; +static bool generateds = false; +static bool ignore_kskflag = false; +static bool keyset_kskonly = false; +static dns_master_style_t *dsstyle = NULL; +static unsigned int serialformat = SOA_SERIAL_KEEP; +static unsigned int hash_length = 0; +static bool unknownalg = false; +static bool disable_zone_check = false; +static bool update_chain = false; +static bool set_keyttl = false; +static dns_ttl_t keyttl; +static bool smartsign = false; +static bool remove_orphansigs = false; +static bool remove_inactkeysigs = false; +static bool output_dnssec_only = false; +static bool output_stdout = false; +static bool set_maxttl = false; +static dns_ttl_t maxttl = 0; +static bool no_max_check = false; +static const char *sync_records = "cdnskey,cds:sha-256"; + +#define INCSTAT(counter) \ + if (printstats) { \ + atomic_fetch_add_relaxed(&counter, 1); \ + } + +/*% + * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy. + */ +static dns_name_t * +savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) { + dns_name_t *result; + + result = dns_fixedname_initname(fzonecut); + dns_name_copy(name, result); + + return result; +} + +static void +dumpnode(dns_name_t *name, dns_dbnode_t *node) { + dns_rdataset_t rds; + dns_rdatasetiter_t *iter = NULL; + isc_buffer_t *buffer = NULL; + isc_region_t r; + isc_result_t result; + unsigned int bufsize = 4096; + + if (!output_dnssec_only) { + return; + } + + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &iter); + check_result(result, "dns_db_allrdatasets"); + + dns_rdataset_init(&rds); + + isc_buffer_allocate(mctx, &buffer, bufsize); + + for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(iter)) + { + dns_rdatasetiter_current(iter, &rds); + + if (rds.type != dns_rdatatype_rrsig && + rds.type != dns_rdatatype_nsec && + rds.type != dns_rdatatype_nsec3 && + rds.type != dns_rdatatype_nsec3param && + (!smartsign || rds.type != dns_rdatatype_dnskey)) + { + dns_rdataset_disassociate(&rds); + continue; + } + + for (;;) { + result = dns_master_rdatasettotext( + name, &rds, masterstyle, NULL, buffer); + if (result != ISC_R_NOSPACE) { + break; + } + + bufsize <<= 1; + isc_buffer_free(&buffer); + isc_buffer_allocate(mctx, &buffer, bufsize); + } + check_result(result, "dns_master_rdatasettotext"); + + isc_buffer_usedregion(buffer, &r); + result = isc_stdio_write(r.base, 1, r.length, outfp, NULL); + check_result(result, "isc_stdio_write"); + isc_buffer_clear(buffer); + + dns_rdataset_disassociate(&rds); + } + + isc_buffer_free(&buffer); + dns_rdatasetiter_destroy(&iter); +} + +static void +lock_and_dumpnode(dns_name_t *name, dns_dbnode_t *node) { + if (!output_dnssec_only) { + return; + } + + LOCK(&namelock); + dumpnode(name, node); + UNLOCK(&namelock); +} + +/*% + * Sign the given RRset with given key, and add the signature record to the + * given tuple. + */ +static void +signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key, + dns_ttl_t ttl, dns_diff_t *add, const char *logmsg) { + isc_result_t result; + isc_stdtime_t jendtime, expiry; + char keystr[DST_KEY_FORMATSIZE]; + dns_rdata_t trdata = DNS_RDATA_INIT; + unsigned char array[BUFSIZE]; + isc_buffer_t b; + dns_difftuple_t *tuple; + + dst_key_format(key, keystr, sizeof(keystr)); + vbprintf(1, "\t%s %s\n", logmsg, keystr); + + if (rdataset->type == dns_rdatatype_dnskey) { + expiry = dnskey_endtime; + } else { + expiry = endtime; + } + + jendtime = (jitter != 0) ? expiry - isc_random_uniform(jitter) : expiry; + isc_buffer_init(&b, array, sizeof(array)); + result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime, + mctx, &b, &trdata); + if (result != ISC_R_SUCCESS) { + fatal("dnskey '%s' failed to sign data: %s", keystr, + isc_result_totext(result)); + } + INCSTAT(nsigned); + + if (tryverify) { + result = dns_dnssec_verify(name, rdataset, key, true, 0, mctx, + &trdata, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { + vbprintf(3, "\tsignature verified\n"); + INCSTAT(nverified); + } else { + vbprintf(3, "\tsignature failed to verify\n"); + INCSTAT(nverifyfailed); + } + } + + tuple = NULL; + result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, + &trdata, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(add, &tuple); +} + +static bool +issigningkey(dns_dnsseckey_t *key) { + return key->force_sign || key->hint_sign; +} + +static bool +ispublishedkey(dns_dnsseckey_t *key) { + return (key->force_publish || key->hint_publish) && !key->hint_remove; +} + +static bool +iszonekey(dns_dnsseckey_t *key) { + return dns_name_equal(dst_key_name(key->key), gorigin) && + dst_key_iszonekey(key->key); +} + +static bool +isksk(dns_dnsseckey_t *key) { + return key->ksk; +} + +static bool +iszsk(dns_dnsseckey_t *key) { + return ignore_kskflag || !key->ksk; +} + +/*% + * Find the key that generated an RRSIG, if it is in the key list. If + * so, return a pointer to it, otherwise return NULL. + * + * No locking is performed here, this must be done by the caller. + */ +static dns_dnsseckey_t * +keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) { + dns_dnsseckey_t *key; + + for (key = ISC_LIST_HEAD(keylist); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + if (rrsig->keyid == dst_key_id(key->key) && + rrsig->algorithm == dst_key_alg(key->key) && + dns_name_equal(&rrsig->signer, dst_key_name(key->key))) + { + return key; + } + } + return NULL; +} + +/*% + * Finds the key that generated a RRSIG, if possible. First look at the keys + * that we've loaded already, and then see if there's a key on disk. + */ +static dns_dnsseckey_t * +keythatsigned(dns_rdata_rrsig_t *rrsig) { + isc_result_t result; + dst_key_t *pubkey = NULL, *privkey = NULL; + dns_dnsseckey_t *key = NULL; + + RWLOCK(&keylist_lock, isc_rwlocktype_read); + key = keythatsigned_unlocked(rrsig); + RWUNLOCK(&keylist_lock, isc_rwlocktype_read); + if (key != NULL) { + return key; + } + + /* + * We did not find the key in our list. Get a write lock now, since + * we may be modifying the bits. We could do the tryupgrade() dance, + * but instead just get a write lock and check once again to see if + * it is on our list. It's possible someone else may have added it + * after all. + */ + isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write); + key = keythatsigned_unlocked(rrsig); + if (key != NULL) { + isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); + return key; + } + + result = dst_key_fromfile(&rrsig->signer, rrsig->keyid, + rrsig->algorithm, DST_TYPE_PUBLIC, directory, + mctx, &pubkey); + if (result != ISC_R_SUCCESS) { + isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); + return NULL; + } + + result = dst_key_fromfile( + &rrsig->signer, rrsig->keyid, rrsig->algorithm, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, directory, mctx, &privkey); + if (result == ISC_R_SUCCESS) { + dst_key_free(&pubkey); + dns_dnsseckey_create(mctx, &privkey, &key); + } else { + dns_dnsseckey_create(mctx, &pubkey, &key); + key->pubkey = true; + } + + key->index = keycount++; + ISC_LIST_APPEND(keylist, key, link); + + isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write); + return key; +} + +/*% + * Check to see if we expect to find a key at this name. If we see a RRSIG + * and can't find the signing key that we expect to find, we drop the rrsig. + * I'm not sure if this is completely correct, but it seems to work. + */ +static bool +expecttofindkey(dns_name_t *name) { + unsigned int options = DNS_DBFIND_NOWILD; + dns_fixedname_t fname; + isc_result_t result; + char namestr[DNS_NAME_FORMATSIZE]; + + dns_fixedname_init(&fname); + result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options, + 0, NULL, dns_fixedname_name(&fname), NULL, NULL); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_NXDOMAIN: + case DNS_R_NXRRSET: + return true; + case DNS_R_DELEGATION: + case DNS_R_CNAME: + case DNS_R_DNAME: + return false; + default: + break; + } + dns_name_format(name, namestr, sizeof(namestr)); + fatal("failure looking for '%s DNSKEY' in database: %s", namestr, + isc_result_totext(result)); + UNREACHABLE(); + return false; /* removes a warning */ +} + +static bool +setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, + dns_rdata_t *rrsig) { + isc_result_t result; + result = dns_dnssec_verify(name, set, key, false, 0, mctx, rrsig, NULL); + if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { + INCSTAT(nverified); + return true; + } else { + INCSTAT(nverifyfailed); + return false; + } +} + +/*% + * Signs a set. Goes through contortions to decide if each RRSIG should + * be dropped or retained, and then determines if any new SIGs need to + * be generated. + */ +static void +signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, + dns_rdataset_t *set) { + dns_rdataset_t sigset; + dns_rdata_t sigrdata = DNS_RDATA_INIT; + dns_rdata_rrsig_t rrsig; + dns_dnsseckey_t *key; + isc_result_t result; + bool nosigs = false; + bool *wassignedby, *nowsignedby; + int arraysize; + dns_difftuple_t *tuple; + dns_ttl_t ttl; + int i; + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + char sigstr[SIG_FORMATSIZE]; + + dns_name_format(name, namestr, sizeof(namestr)); + dns_rdatatype_format(set->type, typestr, sizeof(typestr)); + + ttl = ISC_MIN(set->ttl, endtime - starttime); + + dns_rdataset_init(&sigset); + result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig, + set->type, 0, &sigset, NULL); + if (result == ISC_R_NOTFOUND) { + vbprintf(2, "no existing signatures for %s/%s\n", namestr, + typestr); + result = ISC_R_SUCCESS; + nosigs = true; + } + if (result != ISC_R_SUCCESS) { + fatal("failed while looking for '%s RRSIG %s': %s", namestr, + typestr, isc_result_totext(result)); + } + + vbprintf(1, "%s/%s:\n", namestr, typestr); + + arraysize = keycount; + if (!nosigs) { + arraysize += dns_rdataset_count(&sigset); + } + wassignedby = isc_mem_cget(mctx, arraysize, sizeof(bool)); + nowsignedby = isc_mem_cget(mctx, arraysize, sizeof(bool)); + + for (i = 0; i < arraysize; i++) { + wassignedby[i] = nowsignedby[i] = false; + } + + if (nosigs) { + result = ISC_R_NOMORE; + } else { + result = dns_rdataset_first(&sigset); + } + + while (result == ISC_R_SUCCESS) { + bool expired, refresh, future, offline; + bool keep = false, resign = false; + + dns_rdataset_current(&sigset, &sigrdata); + + result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL); + check_result(result, "dns_rdata_tostruct"); + + future = isc_serial_lt(now, rrsig.timesigned); + + key = keythatsigned(&rrsig); + offline = (key != NULL) ? key->pubkey : false; + sig_format(&rrsig, sigstr, sizeof(sigstr)); + expired = isc_serial_gt(now, rrsig.timeexpire); + refresh = isc_serial_gt(now + cycle, rrsig.timeexpire); + + if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) { + /* rrsig is dropped and not replaced */ + vbprintf(2, + "\trrsig by %s dropped - " + "invalid validity period\n", + sigstr); + } else if (key == NULL && !future && + expecttofindkey(&rrsig.signer)) + { + /* rrsig is dropped and not replaced */ + vbprintf(2, + "\trrsig by %s dropped - " + "private dnskey not found\n", + sigstr); + } else if (key == NULL || future) { + keep = (!expired && !remove_orphansigs); + vbprintf(2, "\trrsig by %s %s - dnskey not found\n", + keep ? "retained" : "dropped", sigstr); + } else if (!dns_dnssec_keyactive(key->key, now) && + remove_inactkeysigs) + { + keep = false; + vbprintf(2, "\trrsig by %s dropped - key inactive\n", + sigstr); + } else if (issigningkey(key)) { + wassignedby[key->index] = true; + + if (!refresh && rrsig.originalttl == set->ttl && + setverifies(name, set, key->key, &sigrdata)) + { + vbprintf(2, "\trrsig by %s retained\n", sigstr); + keep = true; + } else if (offline) { + vbprintf(2, + "\trrsig by %s retained - private key " + "missing\n", + sigstr); + keep = true; + } else { + vbprintf(2, "\trrsig by %s dropped - %s\n", + sigstr, + refresh ? "refresh" + : rrsig.originalttl != set->ttl + ? "ttl change" + : "failed to " + "verify"); + resign = true; + } + } else if (!ispublishedkey(key) && remove_orphansigs) { + vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", + sigstr); + } else if (iszonekey(key)) { + wassignedby[key->index] = true; + + if (!refresh && rrsig.originalttl == set->ttl && + setverifies(name, set, key->key, &sigrdata)) + { + vbprintf(2, "\trrsig by %s retained\n", sigstr); + keep = true; + } else if (offline) { + vbprintf(2, + "\trrsig by %s retained - private key " + "missing\n", + sigstr); + keep = true; + } else { + vbprintf(2, "\trrsig by %s dropped - %s\n", + sigstr, + refresh ? "refresh" + : rrsig.originalttl != set->ttl + ? "ttl change" + : "failed to " + "verify"); + } + } else if (!refresh) { + vbprintf(2, "\trrsig by %s retained\n", sigstr); + keep = true; + } else { + vbprintf(2, "\trrsig by %s %s\n", sigstr, + expired ? "expired" : "needs refresh"); + } + + if (keep) { + if (key != NULL) { + nowsignedby[key->index] = true; + } + INCSTAT(nretained); + if (sigset.ttl != ttl) { + vbprintf(2, "\tfixing ttl %s\n", sigstr); + tuple = NULL; + result = dns_difftuple_create( + mctx, DNS_DIFFOP_DELRESIGN, name, + sigset.ttl, &sigrdata, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(del, &tuple); + result = dns_difftuple_create( + mctx, DNS_DIFFOP_ADDRESIGN, name, ttl, + &sigrdata, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(add, &tuple); + } + } else { + tuple = NULL; + vbprintf(2, "\tremoving signature by %s\n", sigstr); + result = dns_difftuple_create( + mctx, DNS_DIFFOP_DELRESIGN, name, sigset.ttl, + &sigrdata, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(del, &tuple); + INCSTAT(ndropped); + } + + if (resign) { + INSIST(!keep); + + signwithkey(name, set, key->key, ttl, add, + "resigning with dnskey"); + nowsignedby[key->index] = true; + } + + dns_rdata_reset(&sigrdata); + dns_rdata_freestruct(&rrsig); + result = dns_rdataset_next(&sigset); + } + if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } + + check_result(result, "dns_rdataset_first/next"); + if (dns_rdataset_isassociated(&sigset)) { + dns_rdataset_disassociate(&sigset); + } + + for (key = ISC_LIST_HEAD(keylist); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + if (REVOKE(key->key) && set->type != dns_rdatatype_dnskey) { + continue; + } + + if (nowsignedby[key->index]) { + continue; + } + + if (!issigningkey(key)) { + continue; + } + + if ((set->type == dns_rdatatype_cds || + set->type == dns_rdatatype_cdnskey || + set->type == dns_rdatatype_dnskey) && + dns_name_equal(name, gorigin)) + { + bool have_ksk; + dns_dnsseckey_t *curr; + + have_ksk = isksk(key); + for (curr = ISC_LIST_HEAD(keylist); curr != NULL; + curr = ISC_LIST_NEXT(curr, link)) + { + if (dst_key_alg(key->key) != + dst_key_alg(curr->key)) + { + continue; + } + if (REVOKE(curr->key)) { + continue; + } + if (isksk(curr)) { + have_ksk = true; + } + } + if (isksk(key) || !have_ksk || + (iszsk(key) && !keyset_kskonly)) + { + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } + } else if (iszsk(key)) { + /* + * Sign with the ZSK unless there is a predecessor + * key that already signs this RRset. + */ + bool have_pre_sig = false; + dns_dnsseckey_t *curr; + uint32_t pre; + isc_result_t ret = dst_key_getnum( + key->key, DST_NUM_PREDECESSOR, &pre); + if (ret == ISC_R_SUCCESS) { + /* + * This key has a predecessor, look for the + * corresponding key in the keylist. The + * key we are looking for must be: + * - From the same cryptographic algorithm. + * - Have the ZSK type (iszsk). + * - Have key ID equal to the predecessor id. + * - Have a successor that matches 'key' id. + */ + for (curr = ISC_LIST_HEAD(keylist); + curr != NULL; + curr = ISC_LIST_NEXT(curr, link)) + { + uint32_t suc; + + if (dst_key_alg(key->key) != + dst_key_alg(curr->key) || + !iszsk(curr) || + dst_key_id(curr->key) != pre) + { + continue; + } + ret = dst_key_getnum(curr->key, + DST_NUM_SUCCESSOR, + &suc); + if (ret != ISC_R_SUCCESS || + dst_key_id(key->key) != suc) + { + continue; + } + + /* + * curr is the predecessor we were + * looking for. Check if this key + * signs this RRset. + */ + if (nowsignedby[curr->index]) { + have_pre_sig = true; + } + } + } + + /* + * If we have a signature of a predecessor key, + * skip signing with this key. + */ + if (!have_pre_sig) { + signwithkey(name, set, key->key, ttl, add, + "signing with dnskey"); + } + } + } + + isc_mem_cput(mctx, wassignedby, arraysize, sizeof(bool)); + isc_mem_cput(mctx, nowsignedby, arraysize, sizeof(bool)); +} + +struct hashlist { + unsigned char *hashbuf; + size_t entries; + size_t size; + size_t length; +}; + +static void +hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) { + l->entries = 0; + l->length = length + 1; + + if (nodes != 0) { + l->size = nodes; + l->hashbuf = malloc(l->size * l->length); + if (l->hashbuf == NULL) { + l->size = 0; + } + } else { + l->size = 0; + l->hashbuf = NULL; + } +} + +static void +hashlist_free(hashlist_t *l) { + if (l->hashbuf) { + free(l->hashbuf); + l->hashbuf = NULL; + l->entries = 0; + l->length = 0; + l->size = 0; + } +} + +static void +hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len) { + REQUIRE(len <= l->length); + + if (l->entries == l->size) { + l->size = l->size * 2 + 100; + l->hashbuf = realloc(l->hashbuf, l->size * l->length); + if (l->hashbuf == NULL) { + fatal("unable to grow hashlist: out of memory"); + } + } + memset(l->hashbuf + l->entries * l->length, 0, l->length); + memmove(l->hashbuf + l->entries * l->length, hash, len); + l->entries++; +} + +static void +hashlist_add_dns_name(hashlist_t *l, + /*const*/ dns_name_t *name, unsigned int hashalg, + unsigned int iterations, const unsigned char *salt, + size_t salt_len, bool speculative) { + char nametext[DNS_NAME_FORMATSIZE]; + unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; + unsigned int len; + size_t i; + + len = isc_iterated_hash(hash, hashalg, iterations, salt, (int)salt_len, + name->ndata, name->length); + if (verbose) { + dns_name_format(name, nametext, sizeof nametext); + for (i = 0; i < len; i++) { + fprintf(stderr, "%02x", hash[i]); + } + fprintf(stderr, " %s\n", nametext); + } + hash[len++] = speculative ? 1 : 0; + hashlist_add(l, hash, len); +} + +static int +hashlist_comp(const void *a, const void *b) { + return memcmp(a, b, hash_length + 1); +} + +static void +hashlist_sort(hashlist_t *l) { + INSIST(l->hashbuf != NULL || l->length == 0); + if (l->length > 0) { + qsort(l->hashbuf, l->entries, l->length, hashlist_comp); + } +} + +static bool +hashlist_hasdup(hashlist_t *l) { + unsigned char *current; + unsigned char *next = l->hashbuf; + size_t entries = l->entries; + + /* + * Skip initial speculative wild card hashes. + */ + while (entries > 0U && next[l->length - 1] != 0U) { + next += l->length; + entries--; + } + + current = next; + while (entries-- > 1U) { + next += l->length; + if (next[l->length - 1] != 0) { + continue; + } + if (isc_safe_memequal(current, next, l->length - 1)) { + return true; + } + current = next; + } + return false; +} + +static const unsigned char * +hashlist_findnext(const hashlist_t *l, + const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { + size_t entries = l->entries; + const unsigned char *next = bsearch(hash, l->hashbuf, l->entries, + l->length, hashlist_comp); + INSIST(next != NULL); + + do { + if (next < l->hashbuf + (l->entries - 1) * l->length) { + next += l->length; + } else { + next = l->hashbuf; + } + if (next[l->length - 1] == 0) { + break; + } + } while (entries-- > 1U); + INSIST(entries != 0U); + return next; +} + +static bool +hashlist_exists(const hashlist_t *l, + const unsigned char hash[NSEC3_MAX_HASH_LENGTH]) { + if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp)) { + return true; + } else { + return false; + } +} + +static void +addnowildcardhash(hashlist_t *l, + /*const*/ dns_name_t *name, unsigned int hashalg, + unsigned int iterations, const unsigned char *salt, + size_t salt_len) { + dns_fixedname_t fixed; + dns_name_t *wild; + dns_dbnode_t *node = NULL; + isc_result_t result; + char namestr[DNS_NAME_FORMATSIZE]; + + wild = dns_fixedname_initname(&fixed); + + result = dns_name_concatenate(dns_wildcardname, name, wild, NULL); + if (result == ISC_R_NOSPACE) { + return; + } + check_result(result, "addnowildcardhash: dns_name_concatenate()"); + + result = dns_db_findnode(gdb, wild, false, &node); + if (result == ISC_R_SUCCESS) { + dns_db_detachnode(gdb, &node); + return; + } + + if (verbose) { + dns_name_format(wild, namestr, sizeof(namestr)); + fprintf(stderr, "adding no-wildcardhash for %s\n", namestr); + } + + hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len, + true); +} + +static void +opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass, + dns_db_t **dbp) { + char filename[PATH_MAX]; + isc_buffer_t b; + isc_result_t result; + + isc_buffer_init(&b, filename, sizeof(filename)); + if (dsdir != NULL) { + /* allow room for a trailing slash */ + if (strlen(dsdir) >= isc_buffer_availablelength(&b)) { + fatal("path '%s' is too long", dsdir); + } + isc_buffer_putstr(&b, dsdir); + if (dsdir[strlen(dsdir) - 1] != '/') { + isc_buffer_putstr(&b, "/"); + } + } + if (strlen(prefix) > isc_buffer_availablelength(&b)) { + fatal("path '%s' is too long", dsdir); + } + isc_buffer_putstr(&b, prefix); + result = dns_name_tofilenametext(name, false, &b); + check_result(result, "dns_name_tofilenametext()"); + if (isc_buffer_availablelength(&b) == 0) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namestr, sizeof(namestr)); + fatal("name '%s' is too long", namestr); + } + isc_buffer_putuint8(&b, 0); + + result = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, + dns_dbtype_zone, rdclass, 0, NULL, dbp); + check_result(result, "dns_db_create()"); + + result = dns_db_load(*dbp, filename, inputformat, DNS_MASTER_HINT); + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + dns_db_detach(dbp); + } +} + +/*% + * Load the DS set for a child zone, if a dsset-* file can be found. + * If not, try to find a keyset-* file from an earlier version of + * dnssec-signzone, and build DS records from that. + */ +static isc_result_t +loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) { + dns_db_t *db = NULL; + dns_dbversion_t *ver = NULL; + dns_dbnode_t *node = NULL; + isc_result_t result; + dns_rdataset_t keyset; + dns_rdata_t key, ds; + unsigned char dsbuf[DNS_DS_BUFFERSIZE]; + dns_diff_t diff; + dns_difftuple_t *tuple = NULL; + + opendb("dsset-", name, gclass, &db); + if (db != NULL) { + result = dns_db_findnode(db, name, false, &node); + if (result == ISC_R_SUCCESS) { + dns_rdataset_init(dsset); + result = dns_db_findrdataset(db, node, NULL, + dns_rdatatype_ds, 0, 0, + dsset, NULL); + dns_db_detachnode(db, &node); + if (result == ISC_R_SUCCESS) { + vbprintf(2, "found DS records\n"); + dsset->ttl = ttl; + dns_db_detach(&db); + return result; + } + } + dns_db_detach(&db); + } + + /* No DS records found; try again, looking for DNSKEY records */ + opendb("keyset-", name, gclass, &db); + if (db == NULL) { + return ISC_R_NOTFOUND; + } + + result = dns_db_findnode(db, name, false, &node); + if (result != ISC_R_SUCCESS) { + dns_db_detach(&db); + return result; + } + + dns_rdataset_init(&keyset); + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0, + &keyset, NULL); + if (result != ISC_R_SUCCESS) { + dns_db_detachnode(db, &node); + dns_db_detach(&db); + return result; + } + vbprintf(2, "found DNSKEY records\n"); + + result = dns_db_newversion(db, &ver); + check_result(result, "dns_db_newversion"); + dns_diff_init(mctx, &diff); + + for (result = dns_rdataset_first(&keyset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(&keyset)) + { + dns_rdata_init(&key); + dns_rdata_init(&ds); + dns_rdataset_current(&keyset, &key); + result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256, + dsbuf, &ds); + check_result(result, "dns_ds_buildrdata"); + + result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name, + ttl, &ds, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(&diff, &tuple); + } + + result = dns_diff_apply(&diff, db, ver); + check_result(result, "dns_diff_apply"); + dns_diff_clear(&diff); + + dns_db_closeversion(db, &ver, true); + + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0, + dsset, NULL); + check_result(result, "dns_db_findrdataset"); + + dns_rdataset_disassociate(&keyset); + dns_db_detachnode(db, &node); + dns_db_detach(&db); + return result; +} + +static bool +secure(dns_name_t *name, dns_dbnode_t *node) { + dns_rdataset_t dsset; + isc_result_t result; + + if (dns_name_equal(name, gorigin)) { + return false; + } + + dns_rdataset_init(&dsset); + result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, + 0, &dsset, NULL); + if (dns_rdataset_isassociated(&dsset)) { + dns_rdataset_disassociate(&dsset); + } + + return result == ISC_R_SUCCESS; +} + +static bool +is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, + dns_name_t *name, dns_dbnode_t *node, uint32_t *ttlp) { + dns_rdataset_t nsset; + isc_result_t result; + + if (dns_name_equal(name, origin)) { + return false; + } + + dns_rdataset_init(&nsset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, 0, 0, + &nsset, NULL); + if (dns_rdataset_isassociated(&nsset)) { + if (ttlp != NULL) { + *ttlp = nsset.ttl; + } + dns_rdataset_disassociate(&nsset); + } + + return result == ISC_R_SUCCESS; +} + +/*% + * Return true if version 'ver' of database 'db' contains a DNAME RRset at + * 'node'; return false otherwise. + */ +static bool +has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) { + dns_rdataset_t dnameset; + isc_result_t result; + + dns_rdataset_init(&dnameset); + result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0, + &dnameset, NULL); + if (dns_rdataset_isassociated(&dnameset)) { + dns_rdataset_disassociate(&dnameset); + } + + return result == ISC_R_SUCCESS; +} + +/*% + * Signs all records at a name. + */ +static void +signname(dns_dbnode_t *node, bool apex, dns_name_t *name) { + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatasetiter_t *rdsiter; + bool isdelegation = false; + dns_diff_t del, add; + char namestr[DNS_NAME_FORMATSIZE]; + + dns_rdataset_init(&rdataset); + dns_name_format(name, namestr, sizeof(namestr)); + + /* + * Determine if this is a delegation point. + */ + if (is_delegation(gdb, gversion, gorigin, name, node, NULL)) { + isdelegation = true; + } + + /* + * Now iterate through the rdatasets. + */ + dns_diff_init(mctx, &del); + dns_diff_init(mctx, &add); + rdsiter = NULL; + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + result = dns_rdatasetiter_first(rdsiter); + while (result == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, &rdataset); + + /* If this is a RRSIG set, skip it. */ + if (rdataset.type == dns_rdatatype_rrsig) { + goto skip; + } + + /* + * If this name is a delegation point, skip all records + * except NSEC and DS sets. Otherwise check that there + * isn't a DS record. + */ + if (isdelegation) { + if (rdataset.type != nsec_datatype && + rdataset.type != dns_rdatatype_ds) + { + goto skip; + } + } else if (rdataset.type == dns_rdatatype_ds) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namebuf, sizeof(namebuf)); + fatal("'%s': found DS RRset without NS RRset\n", + namebuf); + } else if (rdataset.type == dns_rdatatype_dnskey && !apex) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namebuf, sizeof(namebuf)); + fatal("'%s': Non-apex DNSKEY RRset\n", namebuf); + } + + signset(&del, &add, node, name, &rdataset); + + skip: + dns_rdataset_disassociate(&rdataset); + result = dns_rdatasetiter_next(rdsiter); + } + if (result != ISC_R_NOMORE) { + fatal("rdataset iteration for name '%s' failed: %s", namestr, + isc_result_totext(result)); + } + + dns_rdatasetiter_destroy(&rdsiter); + + result = dns_diff_applysilently(&del, gdb, gversion); + if (result != ISC_R_SUCCESS) { + fatal("failed to delete SIGs at node '%s': %s", namestr, + isc_result_totext(result)); + } + + result = dns_diff_applysilently(&add, gdb, gversion); + if (result != ISC_R_SUCCESS) { + fatal("failed to add SIGs at node '%s': %s", namestr, + isc_result_totext(result)); + } + + dns_diff_clear(&del); + dns_diff_clear(&add); +} + +/* + * See if the node contains any non RRSIG/NSEC records and report to + * caller. Clean out extraneous RRSIG records for node. + */ +static bool +active_node(dns_dbnode_t *node) { + dns_rdatasetiter_t *rdsiter = NULL; + dns_rdatasetiter_t *rdsiter2 = NULL; + bool active = false; + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatatype_t type; + dns_rdatatype_t covers; + bool found; + + dns_rdataset_init(&rdataset); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + result = dns_rdatasetiter_first(rdsiter); + while (result == ISC_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, &rdataset); + if (rdataset.type != dns_rdatatype_nsec && + rdataset.type != dns_rdatatype_nsec3 && + rdataset.type != dns_rdatatype_rrsig) + { + active = true; + } + dns_rdataset_disassociate(&rdataset); + if (!active) { + result = dns_rdatasetiter_next(rdsiter); + } else { + result = ISC_R_NOMORE; + } + } + if (result != ISC_R_NOMORE) { + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + } + + if (!active && nsec_datatype == dns_rdatatype_nsec) { + /*% + * The node is empty of everything but NSEC / RRSIG records. + */ + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + result = dns_db_deleterdataset(gdb, node, gversion, + rdataset.type, + rdataset.covers); + check_result(result, "dns_db_deleterdataset()"); + dns_rdataset_disassociate(&rdataset); + } + if (result != ISC_R_NOMORE) { + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + } + } else { + /* + * Delete RRSIGs for types that no longer exist. + */ + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter2); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + type = rdataset.type; + covers = rdataset.covers; + dns_rdataset_disassociate(&rdataset); + /* + * Delete the NSEC chain if we are signing with + * NSEC3. + */ + if (nsec_datatype == dns_rdatatype_nsec3 && + (type == dns_rdatatype_nsec || + covers == dns_rdatatype_nsec)) + { + result = dns_db_deleterdataset( + gdb, node, gversion, type, covers); + check_result(result, "dns_db_deleterdataset(" + "nsec/rrsig)"); + continue; + } + if (type != dns_rdatatype_rrsig) { + continue; + } + found = false; + for (result = dns_rdatasetiter_first(rdsiter2); + !found && result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter2)) + { + dns_rdatasetiter_current(rdsiter2, &rdataset); + if (rdataset.type == covers) { + found = true; + } + dns_rdataset_disassociate(&rdataset); + } + if (!found) { + if (result != ISC_R_NOMORE) { + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + } + result = dns_db_deleterdataset( + gdb, node, gversion, type, covers); + check_result(result, "dns_db_deleterdataset(" + "rrsig)"); + } else if (result != ISC_R_NOMORE && + result != ISC_R_SUCCESS) + { + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + } + } + if (result != ISC_R_NOMORE) { + fatal("rdataset iteration failed: %s", + isc_result_totext(result)); + } + dns_rdatasetiter_destroy(&rdsiter2); + } + dns_rdatasetiter_destroy(&rdsiter); + + return active; +} + +/*% + * Extracts the minimum TTL from the SOA record, and the SOA record's TTL. + */ +static void +get_soa_ttls(void) { + dns_rdataset_t soaset; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + + name = dns_fixedname_initname(&fname); + dns_rdataset_init(&soaset); + result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa, 0, 0, + NULL, name, &soaset, NULL); + if (result != ISC_R_SUCCESS) { + fatal("failed to find an SOA at the zone apex: %s", + isc_result_totext(result)); + } + + result = dns_rdataset_first(&soaset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(&soaset, &rdata); + soa_ttl = soaset.ttl; + zone_soa_min_ttl = ISC_MIN(dns_soa_getminimum(&rdata), soa_ttl); + if (set_maxttl) { + zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl); + soa_ttl = ISC_MIN(soa_ttl, maxttl); + } + dns_rdataset_disassociate(&soaset); +} + +/*% + * Increment (or set if nonzero) the SOA serial + */ +static isc_result_t +setsoaserial(uint32_t serial, dns_updatemethod_t method) { + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + uint32_t old_serial, new_serial = 0; + dns_updatemethod_t used = dns_updatemethod_none; + + result = dns_db_getoriginnode(gdb, &node); + if (result != ISC_R_SUCCESS) { + return result; + } + + dns_rdataset_init(&rdataset); + + result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_soa, 0, + 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = dns_rdataset_first(&rdataset); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + dns_rdataset_current(&rdataset, &rdata); + + old_serial = dns_soa_getserial(&rdata); + + if (method == dns_updatemethod_date || + method == dns_updatemethod_unixtime) + { + new_serial = dns_update_soaserial(old_serial, method, &used); + } else if (serial != 0 || method == dns_updatemethod_none) { + /* Set SOA serial to the value provided. */ + new_serial = serial; + used = method; + } else { + new_serial = dns_update_soaserial(old_serial, method, &used); + } + + if (method != used) { + fprintf(stderr, + "%s: warning: Serial number would not advance, " + "using increment method instead\n", + program); + } + + /* If the new serial is not likely to cause a zone transfer + * (a/ixfr) from servers having the old serial, warn the user. + * + * RFC1982 section 7 defines the maximum increment to be + * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single + * comparison. (5 - 6 == (2^32)-1, not negative-one) + */ + if (new_serial == old_serial || (new_serial - old_serial) > 0x7fffffffU) + { + fprintf(stderr, + "%s: warning: Serial number not advanced, " + "zone may not transfer\n", + program); + } + + dns_soa_setserial(new_serial, &rdata); + + result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_soa, + 0); + check_result(result, "dns_db_deleterdataset"); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, 0, NULL); + check_result(result, "dns_db_addrdataset"); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + +cleanup: + dns_rdataset_disassociate(&rdataset); + if (node != NULL) { + dns_db_detachnode(gdb, &node); + } + dns_rdata_reset(&rdata); + + return result; +} + +/*% + * Set up the iterator and global state before starting the tasks. + */ +static void +presign(void) { + isc_result_t result; + + gdbiter = NULL; + result = dns_db_createiterator(gdb, 0, &gdbiter); + check_result(result, "dns_db_createiterator()"); +} + +/*% + * Clean up the iterator and global state after the tasks complete. + */ +static void +postsign(void) { + dns_dbiterator_destroy(&gdbiter); +} + +/*% + * Sign the apex of the zone. + * Note the origin may not be the first node if there are out of zone + * records. + */ +static void +signapex(void) { + dns_dbnode_t *node = NULL; + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + + name = dns_fixedname_initname(&fixed); + result = dns_dbiterator_seek(gdbiter, gorigin); + check_result(result, "dns_dbiterator_seek()"); + result = dns_dbiterator_current(gdbiter, &node, name); + check_dns_dbiterator_current(result); + signname(node, true, name); + dumpnode(name, node); + dns_db_detachnode(gdb, &node); + result = dns_dbiterator_first(gdbiter); + if (result == ISC_R_NOMORE) { + atomic_store(&finished, true); + } else if (result != ISC_R_SUCCESS) { + fatal("failure iterating database: %s", + isc_result_totext(result)); + } +} + +static void +abortwork(void *arg) { + UNUSED(arg); + + atomic_store(&shuttingdown, true); +} + +/*% + * Assigns a node to a worker thread. This is protected by the main task's + * lock. + */ +static void +assignwork(void *arg) { + dns_fixedname_t fname; + dns_name_t *name = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t nsec; + bool found; + isc_result_t result; + static dns_name_t *zonecut = NULL; /* Protected by namelock. */ + static dns_fixedname_t fzonecut; /* Protected by namelock. */ + static unsigned int ended = 0; /* Protected by namelock. */ + + UNUSED(arg); + + if (atomic_load(&shuttingdown)) { + return; + } + + LOCK(&namelock); + if (atomic_load(&finished)) { + ended++; + if (ended == nloops) { + isc_loopmgr_shutdown(loopmgr); + } + UNLOCK(&namelock); + return; + } + + name = dns_fixedname_initname(&fname); + node = NULL; + found = false; + while (!found) { + result = dns_dbiterator_current(gdbiter, &node, name); + check_dns_dbiterator_current(result); + /* + * The origin was handled by signapex(). + */ + if (dns_name_equal(name, gorigin)) { + dns_db_detachnode(gdb, &node); + goto next; + } + /* + * Sort the zone data from the glue and out-of-zone data. + * For NSEC zones nodes with zone data have NSEC records. + * For NSEC3 zones the NSEC3 nodes are zone data but + * outside of the zone name space. For the rest we need + * to track the bottom of zone cuts. + * Nodes which don't need to be signed are dumped here. + */ + dns_rdataset_init(&nsec); + result = dns_db_findrdataset(gdb, node, gversion, nsec_datatype, + 0, 0, &nsec, NULL); + if (dns_rdataset_isassociated(&nsec)) { + dns_rdataset_disassociate(&nsec); + } + if (result == ISC_R_SUCCESS) { + found = true; + } else if (nsec_datatype == dns_rdatatype_nsec3) { + if (dns_name_issubdomain(name, gorigin) && + (zonecut == NULL || + !dns_name_issubdomain(name, zonecut))) + { + if (is_delegation(gdb, gversion, gorigin, name, + node, NULL)) + { + zonecut = savezonecut(&fzonecut, name); + if (!OPTOUT(nsec3flags) || + secure(name, node)) + { + found = true; + } + } else if (has_dname(gdb, gversion, node)) { + zonecut = savezonecut(&fzonecut, name); + found = true; + } else { + found = true; + } + } + } + + if (!found) { + dumpnode(name, node); + dns_db_detachnode(gdb, &node); + } + + next: + result = dns_dbiterator_next(gdbiter); + if (result == ISC_R_NOMORE) { + atomic_store(&finished, true); + break; + } else if (result != ISC_R_SUCCESS) { + fatal("failure iterating database: %s", + isc_result_totext(result)); + } + } + if (!found) { + ended++; + if (ended == nloops) { + isc_loopmgr_shutdown(loopmgr); + } + UNLOCK(&namelock); + return; + } + + UNLOCK(&namelock); + + signname(node, false, dns_fixedname_name(&fname)); + + /*% + * Write a node to the output file, and restart the worker task. + */ + lock_and_dumpnode(dns_fixedname_name(&fname), node); + dns_db_detachnode(gdb, &node); + + isc_async_current(assignwork, NULL); +} + +/*% + * Update / remove the DS RRset. Preserve RRSIG(DS) if possible. + */ +static void +add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) { + dns_rdataset_t dsset; + dns_rdataset_t sigdsset; + isc_result_t result; + + dns_rdataset_init(&dsset); + dns_rdataset_init(&sigdsset); + result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds, 0, + 0, &dsset, &sigdsset); + if (result == ISC_R_SUCCESS) { + dns_rdataset_disassociate(&dsset); + result = dns_db_deleterdataset(gdb, node, gversion, + dns_rdatatype_ds, 0); + check_result(result, "dns_db_deleterdataset"); + } + + result = loadds(name, nsttl, &dsset); + if (result == ISC_R_SUCCESS) { + result = dns_db_addrdataset(gdb, node, gversion, 0, &dsset, 0, + NULL); + check_result(result, "dns_db_addrdataset"); + dns_rdataset_disassociate(&dsset); + if (dns_rdataset_isassociated(&sigdsset)) { + dns_rdataset_disassociate(&sigdsset); + } + } else if (dns_rdataset_isassociated(&sigdsset)) { + result = dns_db_deleterdataset(gdb, node, gversion, + dns_rdatatype_rrsig, + dns_rdatatype_ds); + check_result(result, "dns_db_deleterdataset"); + dns_rdataset_disassociate(&sigdsset); + } +} + +/* + * Remove records of the given type and their signatures. + */ +static void +remove_records(dns_dbnode_t *node, dns_rdatatype_t which, bool checknsec) { + isc_result_t result; + dns_rdatatype_t type, covers; + dns_rdatasetiter_t *rdsiter = NULL; + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + + /* + * Delete any records of the given type at the apex. + */ + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + type = rdataset.type; + covers = rdataset.covers; + dns_rdataset_disassociate(&rdataset); + if (type == which || covers == which) { + if (which == dns_rdatatype_nsec && checknsec && + !update_chain) + { + fatal("Zone contains NSEC records. Use -u " + "to update to NSEC3."); + } + if (which == dns_rdatatype_nsec3param && checknsec && + !update_chain) + { + fatal("Zone contains NSEC3 chains. Use -u " + "to update to NSEC."); + } + result = dns_db_deleterdataset(gdb, node, gversion, + type, covers); + check_result(result, "dns_db_deleterdataset()"); + } + } + dns_rdatasetiter_destroy(&rdsiter); +} + +/* + * Remove signatures covering the given type. If type == 0, + * then remove all signatures, unless this is a delegation, in + * which case remove all signatures except for DS or nsec_datatype + */ +static void +remove_sigs(dns_dbnode_t *node, bool delegation, dns_rdatatype_t which) { + isc_result_t result; + dns_rdatatype_t type, covers; + dns_rdatasetiter_t *rdsiter = NULL; + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + type = rdataset.type; + covers = rdataset.covers; + dns_rdataset_disassociate(&rdataset); + + if (type != dns_rdatatype_rrsig) { + continue; + } + + if (which == 0 && delegation && + (dns_rdatatype_atparent(covers) || + (nsec_datatype == dns_rdatatype_nsec && + covers == nsec_datatype))) + { + continue; + } + + if (which != 0 && covers != which) { + continue; + } + + result = dns_db_deleterdataset(gdb, node, gversion, type, + covers); + check_result(result, "dns_db_deleterdataset()"); + } + dns_rdatasetiter_destroy(&rdsiter); +} + +/*% + * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records. + */ +static void +nsecify(void) { + dns_dbiterator_t *dbiter = NULL; + dns_dbnode_t *node = NULL, *nextnode = NULL; + dns_fixedname_t fname, fnextname, fzonecut; + dns_name_t *name, *nextname, *zonecut; + dns_rdataset_t rdataset; + dns_rdatasetiter_t *rdsiter = NULL; + dns_rdatatype_t type, covers; + bool done = false; + isc_result_t result; + uint32_t nsttl = 0; + + dns_rdataset_init(&rdataset); + name = dns_fixedname_initname(&fname); + nextname = dns_fixedname_initname(&fnextname); + zonecut = NULL; + + /* + * Remove any NSEC3 chains. + */ + result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); + check_result(result, "dns_db_createiterator()"); + for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter)) + { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + type = rdataset.type; + covers = rdataset.covers; + dns_rdataset_disassociate(&rdataset); + result = dns_db_deleterdataset(gdb, node, gversion, + type, covers); + check_result(result, "dns_db_deleterdataset(nsec3param/" + "rrsig)"); + } + dns_rdatasetiter_destroy(&rdsiter); + dns_db_detachnode(gdb, &node); + } + dns_dbiterator_destroy(&dbiter); + + result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); + check_result(result, "dns_db_createiterator()"); + + result = dns_dbiterator_first(dbiter); + check_result(result, "dns_dbiterator_first()"); + + while (!done) { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + /* + * Skip out-of-zone records. + */ + if (!dns_name_issubdomain(name, gorigin)) { + result = dns_dbiterator_next(dbiter); + if (result == ISC_R_NOMORE) { + done = true; + } else { + check_result(result, "dns_dbiterator_next()"); + } + dns_db_detachnode(gdb, &node); + continue; + } + + if (dns_name_equal(name, gorigin)) { + remove_records(node, dns_rdatatype_nsec3param, true); + /* Clean old rrsigs at apex. */ + (void)active_node(node); + } + + if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) { + zonecut = savezonecut(&fzonecut, name); + remove_sigs(node, true, 0); + if (generateds) { + add_ds(name, node, nsttl); + } + } else if (has_dname(gdb, gversion, node)) { + zonecut = savezonecut(&fzonecut, name); + } + + result = dns_dbiterator_next(dbiter); + nextnode = NULL; + while (result == ISC_R_SUCCESS) { + bool active = false; + result = dns_dbiterator_current(dbiter, &nextnode, + nextname); + check_dns_dbiterator_current(result); + active = active_node(nextnode); + if (!active) { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (!dns_name_issubdomain(nextname, gorigin) || + (zonecut != NULL && + dns_name_issubdomain(nextname, zonecut))) + { + remove_sigs(nextnode, false, 0); + remove_records(nextnode, dns_rdatatype_nsec, + false); + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + dns_db_detachnode(gdb, &nextnode); + break; + } + if (result == ISC_R_NOMORE) { + dns_name_clone(gorigin, nextname); + done = true; + } else if (result != ISC_R_SUCCESS) { + fatal("iterating through the database failed: %s", + isc_result_totext(result)); + } + dns_dbiterator_pause(dbiter); + result = dns_nsec_build(gdb, gversion, node, nextname, + zone_soa_min_ttl); + check_result(result, "dns_nsec_build()"); + dns_db_detachnode(gdb, &node); + } + + dns_dbiterator_destroy(&dbiter); +} + +static void +addnsec3param(const unsigned char *salt, size_t salt_len, + dns_iterations_t iterations) { + dns_dbnode_t *node = NULL; + dns_rdata_nsec3param_t nsec3param; + unsigned char nsec3parambuf[5 + 255]; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_buffer_t b; + isc_result_t result; + + dns_rdataset_init(&rdataset); + + nsec3param.common.rdclass = gclass; + nsec3param.common.rdtype = dns_rdatatype_nsec3param; + ISC_LINK_INIT(&nsec3param.common, link); + nsec3param.mctx = NULL; + nsec3param.flags = 0; + nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1; + nsec3param.iterations = iterations; + nsec3param.salt_length = (unsigned char)salt_len; + nsec3param.salt = UNCONST(salt); + + isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf)); + result = dns_rdata_fromstruct(&rdata, gclass, dns_rdatatype_nsec3param, + &nsec3param, &b); + check_result(result, "dns_rdata_fromstruct()"); + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = rdata.rdclass; + rdatalist.type = rdata.type; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + + result = dns_db_findnode(gdb, gorigin, true, &node); + check_result(result, "dns_db_findnode(gorigin)"); + + /* + * Delete any current NSEC3PARAM records. + */ + result = dns_db_deleterdataset(gdb, node, gversion, + dns_rdatatype_nsec3param, 0); + if (result == DNS_R_UNCHANGED) { + result = ISC_R_SUCCESS; + } + check_result(result, "dddnsec3param: dns_db_deleterdataset()"); + + result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, + DNS_DBADD_MERGE, NULL); + if (result == DNS_R_UNCHANGED) { + result = ISC_R_SUCCESS; + } + check_result(result, "addnsec3param: dns_db_addrdataset()"); + dns_db_detachnode(gdb, &node); +} + +static void +addnsec3(dns_name_t *name, dns_dbnode_t *node, const unsigned char *salt, + size_t salt_len, unsigned int iterations, hashlist_t *hashlist, + dns_ttl_t ttl) { + unsigned char hash[NSEC3_MAX_HASH_LENGTH]; + const unsigned char *nexthash; + unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE]; + dns_fixedname_t hashname; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_result_t result; + dns_dbnode_t *nsec3node = NULL; + char namebuf[DNS_NAME_FORMATSIZE]; + size_t hash_len; + + dns_name_format(name, namebuf, sizeof(namebuf)); + + dns_fixedname_init(&hashname); + dns_rdataset_init(&rdataset); + + dns_name_downcase(name, name, NULL); + result = dns_nsec3_hashname(&hashname, hash, &hash_len, name, gorigin, + dns_hash_sha1, iterations, salt, salt_len); + check_result(result, "addnsec3: dns_nsec3_hashname()"); + nexthash = hashlist_findnext(hashlist, hash); + result = dns_nsec3_buildrdata( + gdb, gversion, node, + unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1, nsec3flags, + iterations, salt, salt_len, nexthash, ISC_SHA1_DIGESTLENGTH, + nsec3buffer, &rdata); + check_result(result, "addnsec3: dns_nsec3_buildrdata()"); + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = rdata.rdclass; + rdatalist.type = rdata.type; + rdatalist.ttl = ttl; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname), true, + &nsec3node); + check_result(result, "addnsec3: dns_db_findnode()"); + result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset, 0, + NULL); + if (result == DNS_R_UNCHANGED) { + result = ISC_R_SUCCESS; + } + check_result(result, "addnsec3: dns_db_addrdataset()"); + dns_db_detachnode(gdb, &nsec3node); +} + +/*% + * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list. + * + * Extract the hash from the first label of 'name' then see if it + * is in hashlist. If 'name' is not in the hashlist then delete the + * any NSEC3 records which have the same parameters as the chain we + * are building. + * + * XXXMPA Should we also check that it of the form <hash>.<origin>? + */ +static void +nsec3clean(dns_name_t *name, dns_dbnode_t *node, unsigned int hashalg, + unsigned int iterations, const unsigned char *salt, size_t salt_len, + hashlist_t *hashlist) { + dns_label_t label; + dns_rdata_nsec3_t nsec3; + dns_rdata_t rdata, delrdata; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset, delrdataset; + bool delete_rrsigs = false; + isc_buffer_t target; + isc_result_t result; + unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1]; + bool exists; + + /* + * Get the first label. + */ + dns_name_getlabel(name, 0, &label); + + /* + * We want just the label contents. + */ + isc_region_consume(&label, 1); + + /* + * Decode base32hex string. + */ + isc_buffer_init(&target, hash, sizeof(hash) - 1); + result = isc_base32hex_decoderegion(&label, &target); + if (result != ISC_R_SUCCESS) { + return; + } + + hash[isc_buffer_usedlength(&target)] = 0; + + exists = hashlist_exists(hashlist, hash); + + /* + * Verify that the NSEC3 parameters match the current ones + * otherwise we are dealing with a different NSEC3 chain. + */ + dns_rdataset_init(&rdataset); + dns_rdataset_init(&delrdataset); + + result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + return; + } + + /* + * Delete any NSEC3 records which are not part of the current + * NSEC3 chain. + */ + for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(&rdataset)) + { + dns_rdata_init(&rdata); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct"); + if (exists && nsec3.hash == hashalg && + nsec3.iterations == iterations && + nsec3.salt_length == salt_len && + isc_safe_memequal(nsec3.salt, salt, salt_len)) + { + continue; + } + dns_rdatalist_init(&rdatalist); + rdatalist.rdclass = rdata.rdclass; + rdatalist.type = rdata.type; + if (set_maxttl) { + rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl); + } + dns_rdata_init(&delrdata); + dns_rdata_clone(&rdata, &delrdata); + ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link); + dns_rdatalist_tordataset(&rdatalist, &delrdataset); + result = dns_db_subtractrdataset(gdb, node, gversion, + &delrdataset, 0, NULL); + dns_rdataset_disassociate(&delrdataset); + if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) { + check_result(result, "dns_db_subtractrdataset(NSEC3)"); + } + delete_rrsigs = true; + } + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_NOMORE) { + check_result(result, "dns_rdataset_first/next"); + } + + if (!delete_rrsigs) { + return; + } + /* + * Delete the NSEC3 RRSIGs + */ + result = dns_db_deleterdataset(gdb, node, gversion, dns_rdatatype_rrsig, + dns_rdatatype_nsec3); + if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED) { + check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))"); + } +} + +static void +rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add, + dns_diff_t *del) { + isc_result_t result; + unsigned int count1 = 0; + dns_rdataset_t tmprdataset; + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + + dns_name_format(name, namestr, sizeof(namestr)); + dns_rdatatype_format(rdataset->type, typestr, sizeof(typestr)); + + dns_rdataset_init(&tmprdataset); + for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_rdata_t rdata1 = DNS_RDATA_INIT; + unsigned int count2 = 0; + + count1++; + dns_rdataset_current(rdataset, &rdata1); + dns_rdataset_clone(rdataset, &tmprdataset); + for (result = dns_rdataset_first(&tmprdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&tmprdataset)) + { + dns_rdata_t rdata2 = DNS_RDATA_INIT; + dns_difftuple_t *tuple = NULL; + count2++; + dns_rdataset_current(&tmprdataset, &rdata2); + if (count1 < count2 && + dns_rdata_casecompare(&rdata1, &rdata2) == 0) + { + vbprintf(2, "removing duplicate at %s/%s\n", + namestr, typestr); + result = dns_difftuple_create( + mctx, DNS_DIFFOP_DELRESIGN, name, + rdataset->ttl, &rdata2, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(del, &tuple); + } else if (set_maxttl && rdataset->ttl > maxttl) { + vbprintf(2, + "reducing ttl of %s/%s " + "from %d to %d\n", + namestr, typestr, rdataset->ttl, + maxttl); + result = dns_difftuple_create( + mctx, DNS_DIFFOP_DELRESIGN, name, + rdataset->ttl, &rdata2, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(del, &tuple); + tuple = NULL; + result = dns_difftuple_create( + mctx, DNS_DIFFOP_ADDRESIGN, name, + maxttl, &rdata2, &tuple); + check_result(result, "dns_difftuple_create"); + dns_diff_append(add, &tuple); + } + } + dns_rdataset_disassociate(&tmprdataset); + } +} + +static void +cleanup_zone(void) { + isc_result_t result; + dns_dbiterator_t *dbiter = NULL; + dns_rdatasetiter_t *rdsiter = NULL; + dns_diff_t add, del; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_fixedname_t fname; + dns_name_t *name; + + dns_diff_init(mctx, &add); + dns_diff_init(mctx, &del); + name = dns_fixedname_initname(&fname); + dns_rdataset_init(&rdataset); + + result = dns_db_createiterator(gdb, 0, &dbiter); + check_result(result, "dns_db_createiterator()"); + + for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter)) + { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + result = dns_db_allrdatasets(gdb, node, gversion, 0, 0, + &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) + { + dns_rdatasetiter_current(rdsiter, &rdataset); + rrset_cleanup(name, &rdataset, &add, &del); + dns_rdataset_disassociate(&rdataset); + } + if (result != ISC_R_NOMORE) { + fatal("rdatasets iteration failed."); + } + dns_rdatasetiter_destroy(&rdsiter); + dns_db_detachnode(gdb, &node); + } + if (result != ISC_R_NOMORE) { + fatal("zone iteration failed."); + } + + result = dns_diff_applysilently(&del, gdb, gversion); + check_result(result, "dns_diff_applysilently"); + + result = dns_diff_applysilently(&add, gdb, gversion); + check_result(result, "dns_diff_applysilently"); + + dns_diff_clear(&del); + dns_diff_clear(&add); + dns_dbiterator_destroy(&dbiter); +} + +/* + * Generate NSEC3 records for the zone. + */ +static void +nsec3ify(unsigned int hashalg, dns_iterations_t iterations, + const unsigned char *salt, size_t salt_len, hashlist_t *hashlist) { + dns_dbiterator_t *dbiter = NULL; + dns_dbnode_t *node = NULL, *nextnode = NULL; + dns_fixedname_t fname, fnextname, fzonecut; + dns_name_t *name, *nextname, *zonecut; + dns_rdataset_t rdataset; + int order; + bool active; + bool done = false; + isc_result_t result; + uint32_t nsttl = 0; + unsigned int count, nlabels; + + dns_rdataset_init(&rdataset); + name = dns_fixedname_initname(&fname); + nextname = dns_fixedname_initname(&fnextname); + zonecut = NULL; + + /* + * Walk the zone generating the hash names. + */ + result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); + check_result(result, "dns_db_createiterator()"); + + result = dns_dbiterator_first(dbiter); + check_result(result, "dns_dbiterator_first()"); + + while (!done) { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + /* + * Skip out-of-zone records. + */ + if (!dns_name_issubdomain(name, gorigin)) { + result = dns_dbiterator_next(dbiter); + if (result == ISC_R_NOMORE) { + done = true; + } else { + check_result(result, "dns_dbiterator_next()"); + } + dns_db_detachnode(gdb, &node); + continue; + } + + if (dns_name_equal(name, gorigin)) { + remove_records(node, dns_rdatatype_nsec, true); + /* Clean old rrsigs at apex. */ + (void)active_node(node); + } + + if (has_dname(gdb, gversion, node)) { + zonecut = savezonecut(&fzonecut, name); + } + + result = dns_dbiterator_next(dbiter); + nextnode = NULL; + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(dbiter, &nextnode, + nextname); + check_dns_dbiterator_current(result); + active = active_node(nextnode); + if (!active) { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (!dns_name_issubdomain(nextname, gorigin) || + (zonecut != NULL && + dns_name_issubdomain(nextname, zonecut))) + { + remove_sigs(nextnode, false, 0); + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (is_delegation(gdb, gversion, gorigin, nextname, + nextnode, &nsttl)) + { + zonecut = savezonecut(&fzonecut, nextname); + remove_sigs(nextnode, true, 0); + if (generateds) { + add_ds(nextname, nextnode, nsttl); + } + if (OPTOUT(nsec3flags) && + !secure(nextname, nextnode)) + { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + } else if (has_dname(gdb, gversion, nextnode)) { + zonecut = savezonecut(&fzonecut, nextname); + } + dns_db_detachnode(gdb, &nextnode); + break; + } + if (result == ISC_R_NOMORE) { + dns_name_copy(gorigin, nextname); + done = true; + } else if (result != ISC_R_SUCCESS) { + fatal("iterating through the database failed: %s", + isc_result_totext(result)); + } + dns_name_downcase(name, name, NULL); + hashlist_add_dns_name(hashlist, name, hashalg, iterations, salt, + salt_len, false); + dns_db_detachnode(gdb, &node); + /* + * Add hashes for empty nodes. Use closest encloser logic. + * The closest encloser either has data or is a empty + * node for another span so we don't add + * it here. Empty labels on nextname are within the span. + */ + dns_name_downcase(nextname, nextname, NULL); + dns_name_fullcompare(name, nextname, &order, &nlabels); + addnowildcardhash(hashlist, name, hashalg, iterations, salt, + salt_len); + count = dns_name_countlabels(nextname); + while (count > nlabels + 1) { + count--; + dns_name_split(nextname, count, NULL, nextname); + hashlist_add_dns_name(hashlist, nextname, hashalg, + iterations, salt, salt_len, + false); + addnowildcardhash(hashlist, nextname, hashalg, + iterations, salt, salt_len); + } + } + dns_dbiterator_destroy(&dbiter); + + /* + * We have all the hashes now so we can sort them. + */ + hashlist_sort(hashlist); + + /* + * Check for duplicate hashes. If found the salt needs to + * be changed. + */ + if (hashlist_hasdup(hashlist)) { + fatal("Duplicate hash detected. Pick a different salt."); + } + + /* + * Generate the nsec3 records. + */ + zonecut = NULL; + done = false; + + addnsec3param(salt, salt_len, iterations); + + /* + * Clean out NSEC3 records which don't match this chain. + */ + result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter); + check_result(result, "dns_db_createiterator()"); + + for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; + result = dns_dbiterator_next(dbiter)) + { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + nsec3clean(name, node, hashalg, iterations, salt, salt_len, + hashlist); + dns_db_detachnode(gdb, &node); + } + dns_dbiterator_destroy(&dbiter); + + /* + * Generate / complete the new chain. + */ + result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter); + check_result(result, "dns_db_createiterator()"); + + result = dns_dbiterator_first(dbiter); + check_result(result, "dns_dbiterator_first()"); + + while (!done) { + result = dns_dbiterator_current(dbiter, &node, name); + check_dns_dbiterator_current(result); + /* + * Skip out-of-zone records. + */ + if (!dns_name_issubdomain(name, gorigin)) { + result = dns_dbiterator_next(dbiter); + if (result == ISC_R_NOMORE) { + done = true; + } else { + check_result(result, "dns_dbiterator_next()"); + } + dns_db_detachnode(gdb, &node); + continue; + } + + if (has_dname(gdb, gversion, node)) { + zonecut = savezonecut(&fzonecut, name); + } + + result = dns_dbiterator_next(dbiter); + nextnode = NULL; + while (result == ISC_R_SUCCESS) { + result = dns_dbiterator_current(dbiter, &nextnode, + nextname); + check_dns_dbiterator_current(result); + active = active_node(nextnode); + if (!active) { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (!dns_name_issubdomain(nextname, gorigin) || + (zonecut != NULL && + dns_name_issubdomain(nextname, zonecut))) + { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + if (is_delegation(gdb, gversion, gorigin, nextname, + nextnode, NULL)) + { + zonecut = savezonecut(&fzonecut, nextname); + if (OPTOUT(nsec3flags) && + !secure(nextname, nextnode)) + { + dns_db_detachnode(gdb, &nextnode); + result = dns_dbiterator_next(dbiter); + continue; + } + } else if (has_dname(gdb, gversion, nextnode)) { + zonecut = savezonecut(&fzonecut, nextname); + } + dns_db_detachnode(gdb, &nextnode); + break; + } + if (result == ISC_R_NOMORE) { + dns_name_copy(gorigin, nextname); + done = true; + } else if (result != ISC_R_SUCCESS) { + fatal("iterating through the database failed: %s", + isc_result_totext(result)); + } + /* + * We need to pause here to release the lock on the database. + */ + dns_dbiterator_pause(dbiter); + addnsec3(name, node, salt, salt_len, iterations, hashlist, + zone_soa_min_ttl); + dns_db_detachnode(gdb, &node); + /* + * Add NSEC3's for empty nodes. Use closest encloser logic. + */ + dns_name_fullcompare(name, nextname, &order, &nlabels); + count = dns_name_countlabels(nextname); + while (count > nlabels + 1) { + count--; + dns_name_split(nextname, count, NULL, nextname); + addnsec3(nextname, NULL, salt, salt_len, iterations, + hashlist, zone_soa_min_ttl); + } + } + dns_dbiterator_destroy(&dbiter); +} + +/*% + * Load the zone file from disk + */ +static void +loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { + isc_buffer_t b; + int len; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + len = strlen(origin); + isc_buffer_init(&b, origin, len); + isc_buffer_add(&b, len); + + name = dns_fixedname_initname(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fatal("failed converting name '%s' to dns format: %s", origin, + isc_result_totext(result)); + } + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, db); + check_result(result, "dns_db_create()"); + + result = dns_db_load(*db, file, inputformat, 0); + if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { + fatal("failed loading zone from '%s': %s", file, + isc_result_totext(result)); + } +} + +/*% + * Finds all public zone keys in the zone, and attempts to load the + * private keys from disk. + */ +static void +loadzonekeys(bool preserve_keys, bool load_public) { + dns_dbnode_t *node; + dns_dbversion_t *currentversion = NULL; + isc_result_t result; + dns_rdataset_t rdataset, keysigs, soasigs; + + node = NULL; + result = dns_db_findnode(gdb, gorigin, false, &node); + if (result != ISC_R_SUCCESS) { + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + } + + dns_db_currentversion(gdb, ¤tversion); + + dns_rdataset_init(&rdataset); + dns_rdataset_init(&soasigs); + dns_rdataset_init(&keysigs); + + /* Make note of the keys which signed the SOA, if any */ + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_soa, 0, 0, &rdataset, + &soasigs); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* Preserve the TTL of the DNSKEY RRset, if any */ + dns_rdataset_disassociate(&rdataset); + result = dns_db_findrdataset(gdb, node, currentversion, + dns_rdatatype_dnskey, 0, 0, &rdataset, + &keysigs); + + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + if (set_keyttl && keyttl != rdataset.ttl) { + fprintf(stderr, + "User-specified TTL %u conflicts " + "with existing DNSKEY RRset TTL.\n", + keyttl); + fprintf(stderr, + "Imported keys will use the RRSet " + "TTL %u instead.\n", + rdataset.ttl); + } + keyttl = rdataset.ttl; + + /* Load keys corresponding to the existing DNSKEY RRset. */ + result = dns_dnssec_keylistfromrdataset( + gorigin, NULL, directory, mctx, &rdataset, &keysigs, &soasigs, + preserve_keys, load_public, &keylist); + if (result != ISC_R_SUCCESS) { + fatal("failed to load the zone keys: %s", + isc_result_totext(result)); + } + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + if (dns_rdataset_isassociated(&keysigs)) { + dns_rdataset_disassociate(&keysigs); + } + if (dns_rdataset_isassociated(&soasigs)) { + dns_rdataset_disassociate(&soasigs); + } + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, ¤tversion, false); +} + +static void +loadexplicitkeys(char *keyfiles[], int n, bool setksk) { + isc_result_t result; + int i; + + for (i = 0; i < n; i++) { + dns_dnsseckey_t *key = NULL; + dst_key_t *newkey = NULL; + + result = dst_key_fromnamedfile( + keyfiles[i], directory, + DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, mctx, &newkey); + if (result != ISC_R_SUCCESS) { + fatal("cannot load dnskey %s: %s", keyfiles[i], + isc_result_totext(result)); + } + + if (!dns_name_equal(gorigin, dst_key_name(newkey))) { + fatal("key %s not at origin\n", keyfiles[i]); + } + + if (!dst_key_isprivate(newkey)) { + fatal("cannot sign zone with non-private dnskey %s", + keyfiles[i]); + } + + /* Skip any duplicates */ + for (key = ISC_LIST_HEAD(keylist); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + if (dst_key_id(key->key) == dst_key_id(newkey) && + dst_key_alg(key->key) == dst_key_alg(newkey)) + { + break; + } + } + + if (key == NULL) { + /* We haven't seen this key before */ + dns_dnsseckey_create(mctx, &newkey, &key); + ISC_LIST_APPEND(keylist, key, link); + key->source = dns_keysource_user; + } else { + dst_key_free(&key->key); + key->key = newkey; + } + + key->force_publish = true; + key->force_sign = true; + + if (setksk) { + key->ksk = true; + } + } +} + +static void +report(const char *format, ...) { + if (!quiet) { + FILE *out = output_stdout ? stderr : stdout; + char buf[4096]; + va_list args; + + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + fprintf(out, "%s\n", buf); + } +} + +static void +clear_keylist(dns_dnsseckeylist_t *list) { + dns_dnsseckey_t *key; + while (!ISC_LIST_EMPTY(*list)) { + key = ISC_LIST_HEAD(*list); + ISC_LIST_UNLINK(*list, key, link); + dns_dnsseckey_destroy(mctx, &key); + } +} + +static void +add_digest(char *str, size_t dlen, dns_kasp_digestlist_t *digests, + bool *cdnskey) { + isc_result_t result; + isc_textregion_t r; + dns_dsdigest_t alg; + dns_kasp_digest_t *digest; + + if (dlen == 7 && strncmp(str, "cdnskey", dlen) == 0) { + *cdnskey = true; + return; + } + + if (dlen < 5 || strncmp(str, "cds:", 4) != 0) { + fatal("digest must specify cds:algorithm ('%.*s')", (int)dlen, + str); + } + + r.base = str + 4; + r.length = dlen - 4; + result = dns_dsdigest_fromtext(&alg, &r); + if (result == DNS_R_UNKNOWN) { + fatal("bad digest '%.*s'", (int)dlen, str); + } else if (result != ISC_R_SUCCESS) { + fatal("bad digest '%.*s': %s", (int)dlen, str, + isc_result_totext(result)); + } else if (!dst_ds_digest_supported(alg)) { + fatal("unsupported digest '%.*s'", (int)dlen, str); + } + + /* Suppress duplicates */ + for (dns_kasp_digest_t *d = ISC_LIST_HEAD(*digests); d != NULL; + d = ISC_LIST_NEXT(d, link)) + { + if (d->digest == alg) { + return; + } + } + + digest = isc_mem_get(mctx, sizeof(*digest)); + digest->digest = alg; + ISC_LINK_INIT(digest, link); + ISC_LIST_APPEND(*digests, digest, link); +} + +static void +build_final_keylist(void) { + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_dbversion_t *ver = NULL; + dns_diff_t diff; + dns_dnsseckeylist_t rmkeys, matchkeys; + char name[DNS_NAME_FORMATSIZE]; + dns_rdataset_t cdsset, cdnskeyset, soaset; + dns_kasp_digestlist_t digests; + dns_kasp_digest_t *d, *d_next; + bool cdnskey = false; + + ISC_LIST_INIT(rmkeys); + ISC_LIST_INIT(matchkeys); + ISC_LIST_INIT(digests); + + dns_rdataset_init(&soaset); + dns_rdataset_init(&cdsset); + dns_rdataset_init(&cdnskeyset); + + if (strlen(sync_records) > 0) { + const char delim = ','; + char *digest; + char *s; + size_t dlen; + + digest = UNCONST(sync_records); + next_digest: + s = strchr(digest, delim); + if (s == NULL) { + dlen = strlen(digest); + add_digest(digest, dlen, &digests, &cdnskey); + goto findkeys; + } + dlen = s - digest; + add_digest(digest, dlen, &digests, &cdnskey); + digest = s + 1; + goto next_digest; + } + +findkeys: + /* + * Find keys that match this zone in the key repository. + */ + result = dns_dnssec_findmatchingkeys(gorigin, NULL, directory, NULL, + now, mctx, &matchkeys); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + } + check_result(result, "dns_dnssec_findmatchingkeys"); + + result = dns_db_newversion(gdb, &ver); + check_result(result, "dns_db_newversion"); + + result = dns_db_getoriginnode(gdb, &node); + check_result(result, "dns_db_getoriginnode"); + + /* Get the CDS rdataset */ + result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds, + dns_rdatatype_none, 0, &cdsset, NULL); + if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) { + dns_rdataset_disassociate(&cdsset); + } + + /* Get the CDNSKEY rdataset */ + result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey, + dns_rdatatype_none, 0, &cdnskeyset, NULL); + if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) { + dns_rdataset_disassociate(&cdnskeyset); + } + + dns_diff_init(mctx, &diff); + + /* + * Update keylist with information from from the key repository. + */ + dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl, + &diff, mctx, report); + + /* + * Update keylist with sync records. + */ + + dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset, now, + &digests, cdnskey, keyttl, &diff, mctx); + + dns_name_format(gorigin, name, sizeof(name)); + + result = dns_diff_applysilently(&diff, gdb, ver); + if (result != ISC_R_SUCCESS) { + fatal("failed to update DNSKEY RRset at node '%s': %s", name, + isc_result_totext(result)); + } + + dns_db_detachnode(gdb, &node); + dns_db_closeversion(gdb, &ver, true); + + dns_diff_clear(&diff); + + if (dns_rdataset_isassociated(&cdsset)) { + dns_rdataset_disassociate(&cdsset); + } + if (dns_rdataset_isassociated(&cdnskeyset)) { + dns_rdataset_disassociate(&cdnskeyset); + } + + clear_keylist(&rmkeys); + clear_keylist(&matchkeys); + + for (d = ISC_LIST_HEAD(digests); d != NULL; d = d_next) { + d_next = ISC_LIST_NEXT(d, link); + ISC_LIST_UNLINK(digests, d, link); + isc_mem_put(mctx, d, sizeof(*d)); + } + INSIST(ISC_LIST_EMPTY(digests)); +} + +static void +warnifallksk(dns_db_t *db) { + dns_dbversion_t *currentversion = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + isc_result_t result; + dns_rdata_dnskey_t dnskey; + bool have_non_ksk = false; + + dns_db_currentversion(db, ¤tversion); + + result = dns_db_findnode(db, gorigin, false, &node); + if (result != ISC_R_SUCCESS) { + fatal("failed to find the zone's origin: %s", + isc_result_totext(result)); + } + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(db, node, currentversion, + dns_rdatatype_dnskey, 0, 0, &rdataset, + NULL); + if (result != ISC_R_SUCCESS) { + fatal("failed to find keys at the zone apex: %s", + isc_result_totext(result)); + } + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first"); + while (result == ISC_R_SUCCESS) { + dns_rdata_reset(&rdata); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &dnskey, NULL); + check_result(result, "dns_rdata_tostruct"); + if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) { + have_non_ksk = true; + result = ISC_R_NOMORE; + } else { + result = dns_rdataset_next(&rdataset); + } + dns_rdata_freestruct(&dnskey); + } + dns_rdataset_disassociate(&rdataset); + dns_db_detachnode(db, &node); + dns_db_closeversion(db, ¤tversion, false); + if (!have_non_ksk && !ignore_kskflag) { + if (disable_zone_check) { + fprintf(stderr, + "%s: warning: No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'.\n", + program); + } else { + fatal("No non-KSK DNSKEY found; " + "supply a ZSK or use '-z'."); + } + } +} + +static void +set_nsec3params(bool update, bool set_salt, bool set_optout, bool set_iter) { + isc_result_t result; + dns_dbversion_t *ver = NULL; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_nsec3_t nsec3; + dns_fixedname_t fname; + dns_name_t *hashname; + unsigned char orig_salt[255]; + size_t orig_saltlen; + dns_hash_t orig_hash; + uint16_t orig_iter; + + dns_db_currentversion(gdb, &ver); + dns_rdataset_init(&rdataset); + + orig_saltlen = sizeof(orig_salt); + result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL, + &orig_iter, orig_salt, + &orig_saltlen); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + nsec_datatype = dns_rdatatype_nsec3; + + if (!update && set_salt) { + if (salt_length != orig_saltlen || + !isc_safe_memequal(saltbuf, orig_salt, salt_length)) + { + fatal("An NSEC3 chain exists with a different salt. " + "Use -u to update it."); + } + } else if (!set_salt) { + salt_length = orig_saltlen; + memmove(saltbuf, orig_salt, orig_saltlen); + gsalt = saltbuf; + } + + if (!update && set_iter) { + if (nsec3iter != orig_iter) { + fatal("An NSEC3 chain exists with different " + "iterations. Use -u to update it."); + } + } else if (!set_iter) { + nsec3iter = orig_iter; + } + + /* + * Find an NSEC3 record to get the current OPTOUT value. + * (This assumes all NSEC3 records agree.) + */ + + hashname = dns_fixedname_initname(&fname); + result = dns_nsec3_hashname(&fname, NULL, NULL, gorigin, gorigin, + dns_hash_sha1, orig_iter, orig_salt, + orig_saltlen); + check_result(result, "dns_nsec3_hashname"); + + result = dns_db_findnsec3node(gdb, hashname, false, &node); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3, 0, 0, + &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = dns_rdataset_first(&rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(&rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &nsec3, NULL); + check_result(result, "dns_rdata_tostruct"); + + if (!update && set_optout) { + if (nsec3flags != nsec3.flags) { + fatal("An NSEC3 chain exists with%s OPTOUT. " + "Use -u -%s to %s it.", + OPTOUT(nsec3.flags) ? "" : "out", + OPTOUT(nsec3.flags) ? "AA" : "A", + OPTOUT(nsec3.flags) ? "clear" : "set"); + } + } else if (!set_optout) { + nsec3flags = nsec3.flags; + } + + dns_rdata_freestruct(&nsec3); + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + if (node != NULL) { + dns_db_detachnode(gdb, &node); + } + dns_db_closeversion(gdb, &ver, false); +} + +static void +writeset(const char *prefix, dns_rdatatype_t type) { + char *filename; + char namestr[DNS_NAME_FORMATSIZE]; + dns_db_t *db = NULL; + dns_dbversion_t *dbversion = NULL; + dns_diff_t diff; + dns_difftuple_t *tuple = NULL; + dns_name_t *name; + dns_rdata_t rdata, ds; + bool have_ksk = false; + bool have_non_ksk = false; + isc_buffer_t b; + isc_buffer_t namebuf; + isc_region_t r; + isc_result_t result; + dns_dnsseckey_t *key, *curr; + unsigned char dsbuf[DNS_DS_BUFFERSIZE]; + unsigned char keybuf[DST_KEY_MAXSIZE]; + unsigned int filenamelen; + const dns_master_style_t *style = (type == dns_rdatatype_dnskey) + ? masterstyle + : dsstyle; + + isc_buffer_init(&namebuf, namestr, sizeof(namestr)); + result = dns_name_tofilenametext(gorigin, false, &namebuf); + check_result(result, "dns_name_tofilenametext"); + isc_buffer_putuint8(&namebuf, 0); + filenamelen = strlen(prefix) + strlen(namestr) + 1; + if (dsdir != NULL) { + filenamelen += strlen(dsdir) + 1; + } + filename = isc_mem_get(mctx, filenamelen); + if (dsdir != NULL) { + snprintf(filename, filenamelen, "%s/", dsdir); + } else { + filename[0] = 0; + } + strlcat(filename, prefix, filenamelen); + strlcat(filename, namestr, filenamelen); + + dns_diff_init(mctx, &diff); + + name = gorigin; + + for (key = ISC_LIST_HEAD(keylist); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + if (REVOKE(key->key)) { + continue; + } + if (isksk(key)) { + have_ksk = true; + have_non_ksk = false; + } else { + have_ksk = false; + have_non_ksk = true; + } + for (curr = ISC_LIST_HEAD(keylist); curr != NULL; + curr = ISC_LIST_NEXT(curr, link)) + { + if (dst_key_alg(key->key) != dst_key_alg(curr->key)) { + continue; + } + if (REVOKE(curr->key)) { + continue; + } + if (isksk(curr)) { + have_ksk = true; + } else { + have_non_ksk = true; + } + } + if (have_ksk && have_non_ksk && !isksk(key)) { + continue; + } + dns_rdata_init(&rdata); + dns_rdata_init(&ds); + isc_buffer_init(&b, keybuf, sizeof(keybuf)); + result = dst_key_todns(key->key, &b); + check_result(result, "dst_key_todns"); + isc_buffer_usedregion(&b, &r); + dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r); + if (type != dns_rdatatype_dnskey) { + result = dns_ds_buildrdata(gorigin, &rdata, + DNS_DSDIGEST_SHA256, dsbuf, + &ds); + check_result(result, "dns_ds_buildrdata"); + result = dns_difftuple_create(mctx, + DNS_DIFFOP_ADDRESIGN, + name, 0, &ds, &tuple); + } else { + result = dns_difftuple_create( + mctx, DNS_DIFFOP_ADDRESIGN, gorigin, + zone_soa_min_ttl, &rdata, &tuple); + } + check_result(result, "dns_difftuple_create"); + dns_diff_append(&diff, &tuple); + } + + result = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname, + dns_dbtype_zone, gclass, 0, NULL, &db); + check_result(result, "dns_db_create"); + + result = dns_db_newversion(db, &dbversion); + check_result(result, "dns_db_newversion"); + + result = dns_diff_apply(&diff, db, dbversion); + check_result(result, "dns_diff_apply"); + dns_diff_clear(&diff); + + result = dns_master_dump(mctx, db, dbversion, style, filename, + dns_masterformat_text, NULL); + check_result(result, "dns_master_dump"); + + isc_mem_put(mctx, filename, filenamelen); + + dns_db_closeversion(db, &dbversion, false); + dns_db_detach(&db); +} + +static void +print_time(FILE *fp) { + time_t currenttime = time(NULL); + struct tm t, *tm = localtime_r(¤ttime, &t); + unsigned int flen; + char timebuf[80]; + + if (tm == NULL || outputformat != dns_masterformat_text) { + return; + } + + flen = strftime(timebuf, sizeof(timebuf), "%a %b %e %H:%M:%S %Y", tm); + INSIST(flen > 0U && flen < sizeof(timebuf)); + fprintf(fp, "; File written on %s\n", timebuf); +} + +static void +print_version(FILE *fp) { + if (outputformat != dns_masterformat_text) { + return; + } + + fprintf(fp, "; %s version %s\n", program, PACKAGE_VERSION); +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\t%s [options] zonefile [keys]\n", program); + + fprintf(stderr, "\n"); + + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + + fprintf(stderr, "Options: (default value in parenthesis) \n"); + fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n" + "\t\tfor the zone and determines how they are to " + "be used\n"); + fprintf(stderr, "\t-K directory:\n"); + fprintf(stderr, "\t\tdirectory to find key files (.)\n"); + fprintf(stderr, "\t-d directory:\n"); + fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n"); + fprintf(stderr, "\t-F:\tFIPS mode\n"); + fprintf(stderr, "\t-g:\t"); + fprintf(stderr, "update DS records based on child zones' " + "dsset-* files\n"); + fprintf(stderr, "\t-G sync-records:\t"); + fprintf(stderr, "what CDNSKEY and CDS to publish\n"); + fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n"); + fprintf(stderr, "\t\tRRSIG start time " + "- absolute|offset (now - 1 hour)\n"); + fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); + fprintf(stderr, "\t\tRRSIG end time " + "- absolute|from start|from now " + "(now + 30 days)\n"); + fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n"); + fprintf(stderr, "\t\tDNSKEY RRSIG end " + "- absolute|from start|from now " + "(matches -e)\n"); + fprintf(stderr, "\t-i interval:\n"); + fprintf(stderr, "\t\tcycle interval - resign " + "if < interval from end ( (end-start)/4 )\n"); + fprintf(stderr, "\t-j jitter:\n"); + fprintf(stderr, "\t\trandomize signature end time up to jitter " + "seconds\n"); + fprintf(stderr, "\t-v debuglevel (0)\n"); + fprintf(stderr, "\t-q quiet\n"); + fprintf(stderr, "\t-V:\tprint version information\n"); + fprintf(stderr, "\t-o origin:\n"); + fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); + fprintf(stderr, "\t-f outfile:\n"); + fprintf(stderr, "\t\tfile the signed zone is written in " + "(zonefile + .signed)\n"); + fprintf(stderr, "\t-I format:\n"); + fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); + fprintf(stderr, "\t-O format:\n"); + fprintf(stderr, "\t\tfile format of signed zone file (text)\n"); + fprintf(stderr, "\t-N format:\n"); + fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n"); + fprintf(stderr, "\t-D:\n"); + fprintf(stderr, "\t\toutput only DNSSEC-related records\n"); + fprintf(stderr, "\t-a:\t"); + fprintf(stderr, "verify generated signatures\n"); + fprintf(stderr, "\t-c class (IN)\n"); + fprintf(stderr, "\t-E engine:\n"); + fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); + fprintf(stderr, "\t-P:\t"); + fprintf(stderr, "disable post-sign verification\n"); + fprintf(stderr, "\t-Q:\t"); + fprintf(stderr, "remove signatures from keys that are no " + "longer active\n"); + fprintf(stderr, "\t-R:\t"); + fprintf(stderr, "remove signatures from keys that no longer exist\n"); + fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); + fprintf(stderr, "\t-t:\t"); + fprintf(stderr, "print statistics\n"); + fprintf(stderr, "\t-u:\t"); + fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n"); + fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n"); + fprintf(stderr, "\t-z:\tsign all records with KSKs\n"); + fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n" + "\t\twith older versions of dnssec-signzone -g\n"); + fprintf(stderr, "\t-n ncpus (number of cpus present)\n"); + fprintf(stderr, "\t-k key_signing_key\n"); + fprintf(stderr, "\t-3 NSEC3 salt\n"); + fprintf(stderr, "\t-H NSEC3 iterations (10)\n"); + fprintf(stderr, "\t-A NSEC3 optout\n"); + + fprintf(stderr, "\n"); + + fprintf(stderr, "Signing Keys: "); + fprintf(stderr, "(default: all zone keys that have private keys)\n"); + fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n"); + + exit(EXIT_FAILURE); +} + +static void +removetempfile(void) { + if (removefile) { + isc_file_remove(tempfile); + } +} + +static void +print_stats(isc_time_t *timer_start, isc_time_t *timer_finish, + isc_time_t *sign_start, isc_time_t *sign_finish) { + uint64_t time_us; /* Time in microseconds */ + uint64_t time_ms; /* Time in milliseconds */ + uint64_t sig_ms; /* Signatures per millisecond */ + FILE *out = output_stdout ? stderr : stdout; + + fprintf(out, "Signatures generated: %10" PRIuFAST32 "\n", + atomic_load(&nsigned)); + fprintf(out, "Signatures retained: %10" PRIuFAST32 "\n", + atomic_load(&nretained)); + fprintf(out, "Signatures dropped: %10" PRIuFAST32 "\n", + atomic_load(&ndropped)); + fprintf(out, "Signatures successfully verified: %10" PRIuFAST32 "\n", + atomic_load(&nverified)); + fprintf(out, "Signatures unsuccessfully verified: %10" PRIuFAST32 "\n", + atomic_load(&nverifyfailed)); + + time_us = isc_time_microdiff(sign_finish, sign_start); + time_ms = time_us / 1000; + fprintf(out, "Signing time in seconds: %7u.%03u\n", + (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000)); + if (time_us > 0) { + sig_ms = ((uint64_t)atomic_load(&nsigned) * 1000000000) / + time_us; + fprintf(out, "Signatures per second: %7u.%03u\n", + (unsigned int)sig_ms / 1000, + (unsigned int)sig_ms % 1000); + } + + time_us = isc_time_microdiff(timer_finish, timer_start); + time_ms = time_us / 1000; + fprintf(out, "Runtime in seconds: %7u.%03u\n", + (unsigned int)(time_ms / 1000), (unsigned int)(time_ms % 1000)); +} + +int +main(int argc, char *argv[]) { + int ch; + char *startstr = NULL, *endstr = NULL, *classname = NULL; + char *dnskey_endstr = NULL; + char *origin = NULL, *file = NULL, *output = NULL; + char *inputformatstr = NULL, *outputformatstr = NULL; + char *serialformatstr = NULL; + char *dskeyfile[MAXDSKEYS]; + int ndskeys = 0; + char *endp; + isc_time_t timer_start, timer_finish; + isc_time_t sign_start, sign_finish; + dns_dnsseckey_t *key; + isc_result_t result, vresult; + isc_log_t *log = NULL; + const char *engine = NULL; + bool free_output = false; + int tempfilelen = 0; + dns_rdataclass_t rdclass; + hashlist_t hashlist; + bool make_keyset = false; + bool set_salt = false; + bool set_optout = false; + bool set_iter = false; + bool nonsecify = false; + bool set_fips_mode = false; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + OSSL_PROVIDER *fips = NULL, *base = NULL; +#endif + + atomic_init(&shuttingdown, false); + atomic_init(&finished, false); + + /* Unused letters: Bb G J q Yy (and F is reserved). */ +#define CMDLINE_FLAGS \ + "3:AaCc:Dd:E:e:f:FgG:hH:i:I:j:J:K:k:L:l:m:M:n:N:o:O:PpQqRr:s:ST:tuUv:" \ + "VX:xzZ:" + + /* + * Process memory debugging argument first. + */ + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + } + if (strcasecmp(isc_commandline_argument, "trace") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + } + if (strcasecmp(isc_commandline_argument, "usage") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + } + break; + default: + break; + } + } + isc_commandline_reset = true; + + masterstyle = &dns_master_style_explicitttl; + + isc_commandline_errprint = false; + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '3': + set_salt = true; + nsec_datatype = dns_rdatatype_nsec3; + if (strcmp(isc_commandline_argument, "-") != 0) { + isc_buffer_t target; + char *sarg; + + sarg = isc_commandline_argument; + isc_buffer_init(&target, saltbuf, + sizeof(saltbuf)); + result = isc_hex_decodestring(sarg, &target); + check_result(result, "isc_hex_decodestring(" + "salt)"); + salt_length = isc_buffer_usedlength(&target); + } + break; + + case 'A': + set_optout = true; + if (OPTOUT(nsec3flags)) { + nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT; + } else { + nsec3flags |= DNS_NSEC3FLAG_OPTOUT; + } + break; + + case 'a': + tryverify = true; + break; + + case 'C': + make_keyset = true; + break; + + case 'c': + classname = isc_commandline_argument; + break; + + case 'd': + dsdir = isc_commandline_argument; + if (strlen(dsdir) == 0U) { + fatal("DS directory must be non-empty string"); + } + result = try_dir(dsdir); + if (result != ISC_R_SUCCESS) { + fatal("cannot open directory %s: %s", dsdir, + isc_result_totext(result)); + } + break; + + case 'D': + output_dnssec_only = true; + break; + + case 'E': + engine = isc_commandline_argument; + break; + + case 'e': + endstr = isc_commandline_argument; + break; + + case 'f': + output = isc_commandline_argument; + if (strcmp(output, "-") == 0) { + output_stdout = true; + } + break; + + case 'g': + generateds = true; + break; + + case 'G': + sync_records = isc_commandline_argument; + break; + + case 'H': + set_iter = true; + /* too-many is NOT DOCUMENTED */ + if (strcmp(isc_commandline_argument, "too-many") == 0) { + nsec3iter = 51; + no_max_check = true; + break; + } + nsec3iter = strtoul(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("iterations must be numeric"); + } + if (nsec3iter > 0xffffU) { + fatal("iterations too big"); + } + break; + + case 'I': + inputformatstr = isc_commandline_argument; + break; + + case 'i': + endp = NULL; + cycle = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0' || cycle < 0) { + fatal("cycle period must be numeric and " + "positive"); + } + break; + + case 'j': + endp = NULL; + jitter = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0' || jitter < 0) { + fatal("jitter must be numeric and positive"); + } + break; + + case 'J': + journal = isc_commandline_argument; + break; + + case 'K': + directory = isc_commandline_argument; + break; + + case 'k': + if (ndskeys == MAXDSKEYS) { + fatal("too many key-signing keys specified"); + } + dskeyfile[ndskeys++] = isc_commandline_argument; + break; + + case 'L': + snset = true; + endp = NULL; + serialnum = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "source serial number " + "must be numeric"); + exit(EXIT_FAILURE); + } + break; + + case 'l': + fatal("-l option (DLV lookaside) is obsolete"); + break; + + case 'M': + endp = NULL; + set_maxttl = true; + maxttl = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fprintf(stderr, "maximum TTL " + "must be numeric"); + exit(EXIT_FAILURE); + } + break; + + case 'm': + break; + + case 'N': + serialformatstr = isc_commandline_argument; + break; + + case 'n': + endp = NULL; + nloops = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0' || nloops > INT32_MAX) { + fatal("number of cpus must be numeric"); + } + break; + + case 'O': + outputformatstr = isc_commandline_argument; + break; + + case 'o': + origin = isc_commandline_argument; + break; + + case 'P': + disable_zone_check = true; + break; + + case 'p': + fatal("The -p option has been deprecated.\n"); + break; + + case 'Q': + remove_inactkeysigs = true; + break; + + case 'R': + remove_orphansigs = true; + break; + + case 'r': + fatal("The -r options has been deprecated.\n"); + break; + + case 'S': + smartsign = true; + break; + + case 's': + startstr = isc_commandline_argument; + break; + + case 'T': + endp = NULL; + set_keyttl = true; + keyttl = strtottl(isc_commandline_argument); + break; + + case 't': + printstats = true; + break; + + case 'U': /* Undocumented for testing only. */ + unknownalg = true; + break; + + case 'u': + update_chain = true; + break; + + case 'v': + endp = NULL; + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("verbose level must be numeric"); + } + break; + + case 'q': + quiet = true; + break; + + case 'X': + dnskey_endstr = isc_commandline_argument; + break; + + case 'x': + keyset_kskonly = true; + break; + + case 'z': + ignore_kskflag = true; + break; + + case 'F': + set_fips_mode = true; + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + case 'Z': /* Undocumented test options */ + if (!strcmp(isc_commandline_argument, "nonsecify")) { + nonsecify = true; + } + break; + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + now = isc_stdtime_now(); + + if (startstr != NULL) { + starttime = strtotime(startstr, now, now, NULL); + } else { + starttime = now - 3600; /* Allow for some clock skew. */ + } + + if (endstr != NULL) { + endtime = strtotime(endstr, now, starttime, NULL); + } else { + endtime = starttime + (30 * 24 * 60 * 60); + } + + if (dnskey_endstr != NULL) { + dnskey_endtime = strtotime(dnskey_endstr, now, starttime, NULL); + if (endstr != NULL && dnskey_endtime == endtime) { + fprintf(stderr, "WARNING: -e and -X were both set, " + "but have identical values.\n"); + } + } else { + dnskey_endtime = endtime; + } + + if (cycle == -1) { + cycle = (endtime - starttime) / 4; + } + + if (nloops == 0) { + nloops = isc_os_ncpus(); + } + vbprintf(4, "using %d cpus\n", nloops); + + rdclass = strtoclass(classname); + + if (directory == NULL) { + directory = "."; + } + + isc_managers_create(&mctx, nloops, &loopmgr, &netmgr); + + if (set_fips_mode) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips == NULL) { + ERR_clear_error(); + fatal("Failed to load FIPS provider"); + } + base = OSSL_PROVIDER_load(NULL, "base"); + if (base == NULL) { + OSSL_PROVIDER_unload(fips); + ERR_clear_error(); + fatal("Failed to load base provider"); + } +#endif + if (!isc_fips_mode()) { + if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } + } + } + + result = dst_lib_init(mctx, engine); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", + isc_result_totext(result)); + } + + setup_logging(mctx, &log); + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argc < 1) { + usage(); + } + + file = argv[0]; + + argc -= 1; + argv += 1; + + if (origin == NULL) { + origin = file; + } + + if (output == NULL) { + size_t size; + free_output = true; + size = strlen(file) + strlen(".signed") + 1; + output = isc_mem_allocate(mctx, size); + snprintf(output, size, "%s.signed", file); + } + + if (inputformatstr != NULL) { + if (strcasecmp(inputformatstr, "text") == 0) { + inputformat = dns_masterformat_text; + } else if (strcasecmp(inputformatstr, "raw") == 0) { + inputformat = dns_masterformat_raw; + } else if (strncasecmp(inputformatstr, "raw=", 4) == 0) { + inputformat = dns_masterformat_raw; + fprintf(stderr, "WARNING: input format version " + "ignored\n"); + } else { + fatal("unknown file format: %s", inputformatstr); + } + } + + if (outputformatstr != NULL) { + if (strcasecmp(outputformatstr, "text") == 0) { + outputformat = dns_masterformat_text; + } else if (strcasecmp(outputformatstr, "full") == 0) { + outputformat = dns_masterformat_text; + masterstyle = &dns_master_style_full; + } else if (strcasecmp(outputformatstr, "raw") == 0) { + outputformat = dns_masterformat_raw; + } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { + char *end; + + outputformat = dns_masterformat_raw; + rawversion = strtol(outputformatstr + 4, &end, 10); + if (end == outputformatstr + 4 || *end != '\0' || + rawversion > 1U) + { + fprintf(stderr, "unknown raw format version\n"); + exit(EXIT_FAILURE); + } + } else { + fatal("unknown file format: %s", outputformatstr); + } + } + + if (serialformatstr != NULL) { + if (strcasecmp(serialformatstr, "keep") == 0) { + serialformat = SOA_SERIAL_KEEP; + } else if (strcasecmp(serialformatstr, "increment") == 0 || + strcasecmp(serialformatstr, "incr") == 0) + { + serialformat = SOA_SERIAL_INCREMENT; + } else if (strcasecmp(serialformatstr, "unixtime") == 0) { + serialformat = SOA_SERIAL_UNIXTIME; + } else if (strcasecmp(serialformatstr, "date") == 0) { + serialformat = SOA_SERIAL_DATE; + } else { + fatal("unknown soa serial format: %s", serialformatstr); + } + } + + if (output_dnssec_only && outputformat != dns_masterformat_text) { + fatal("option -D can only be used with \"-O text\""); + } + + if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP) { + fatal("option -D can only be used with \"-N keep\""); + } + + if (output_dnssec_only && set_maxttl) { + fatal("option -D cannot be used with -M"); + } + + result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL, 0, 24, + 0, 0, 0, 8, 0xffffffff, mctx); + check_result(result, "dns_master_stylecreate"); + + gdb = NULL; + timer_start = isc_time_now(); + loadzone(file, origin, rdclass, &gdb); + if (journal != NULL) { + loadjournal(mctx, gdb, journal); + } + gorigin = dns_db_origin(gdb); + gclass = dns_db_class(gdb); + get_soa_ttls(); + + if (set_maxttl && set_keyttl && keyttl > maxttl) { + fprintf(stderr, + "%s: warning: Specified key TTL %u " + "exceeds maximum zone TTL; reducing to %u\n", + program, keyttl, maxttl); + keyttl = maxttl; + } + + if (!set_keyttl) { + keyttl = soa_ttl; + } + + /* + * Check for any existing NSEC3 parameters in the zone, + * and use them as defaults if -u was not specified. + */ + if (update_chain && !set_optout && !set_iter && !set_salt) { + nsec_datatype = dns_rdatatype_nsec; + } else { + set_nsec3params(update_chain, set_salt, set_optout, set_iter); + } + + /* + * We need to do this early on, as we start messing with the list + * of keys rather early. + */ + ISC_LIST_INIT(keylist); + isc_rwlock_init(&keylist_lock); + + /* + * Fill keylist with: + * 1) Keys listed in the DNSKEY set that have + * private keys associated, *if* no keys were + * set on the command line. + * 2) ZSKs set on the command line + * 3) KSKs set on the command line + * 4) Any keys remaining in the DNSKEY set which + * do not have private keys associated and were + * not specified on the command line. + */ + if (argc == 0 || smartsign) { + loadzonekeys(!smartsign, false); + } + loadexplicitkeys(argv, argc, false); + loadexplicitkeys(dskeyfile, ndskeys, true); + loadzonekeys(!smartsign, true); + + /* + * If we're doing smart signing, look in the key repository for + * key files with metadata, and merge them with the keylist + * we have now. + */ + if (smartsign) { + build_final_keylist(); + } + + /* Now enumerate the key list */ + for (key = ISC_LIST_HEAD(keylist); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + key->index = keycount++; + } + + if (keycount == 0) { + if (disable_zone_check) { + fprintf(stderr, + "%s: warning: No keys specified " + "or found\n", + program); + } else { + fatal("No signing keys specified or found."); + } + nokeys = true; + } + + warnifallksk(gdb); + + if (IS_NSEC3) { + bool answer; + + hash_length = dns_nsec3_hashlength(dns_hash_sha1); + hashlist_init(&hashlist, + dns_db_nodecount(gdb, dns_dbtree_main) * 2, + hash_length); + result = dns_nsec_nseconly(gdb, gversion, NULL, &answer); + if (result == ISC_R_NOTFOUND) { + fprintf(stderr, + "%s: warning: NSEC3 generation " + "requested with no DNSKEY; ignoring\n", + program); + } else if (result != ISC_R_SUCCESS) { + check_result(result, "dns_nsec_nseconly"); + } else if (answer) { + fatal("NSEC3 generation requested with " + "NSEC-only DNSKEY"); + } + + if (nsec3iter > dns_nsec3_maxiterations()) { + if (no_max_check) { + fprintf(stderr, + "Ignoring max iterations check.\n"); + } else { + fatal("NSEC3 iterations too big. Maximum " + "iterations allowed %u.", + dns_nsec3_maxiterations()); + } + } + } else { + hashlist_init(&hashlist, 0, 0); /* silence clang */ + } + + gversion = NULL; + result = dns_db_newversion(gdb, &gversion); + check_result(result, "dns_db_newversion()"); + + switch (serialformat) { + case SOA_SERIAL_INCREMENT: + setsoaserial(0, dns_updatemethod_increment); + break; + case SOA_SERIAL_UNIXTIME: + setsoaserial(now, dns_updatemethod_unixtime); + break; + case SOA_SERIAL_DATE: + setsoaserial(now, dns_updatemethod_date); + break; + case SOA_SERIAL_KEEP: + default: + /* do nothing */ + break; + } + + /* Remove duplicates and cap TTLs at maxttl */ + cleanup_zone(); + + if (!nonsecify) { + if (IS_NSEC3) { + nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length, + &hashlist); + } else { + nsecify(); + } + } + + if (!nokeys) { + writeset("dsset-", dns_rdatatype_ds); + if (make_keyset) { + writeset("keyset-", dns_rdatatype_dnskey); + } + } + + if (output_stdout) { + outfp = stdout; + if (outputformatstr == NULL) { + masterstyle = &dns_master_style_full; + } + } else { + tempfilelen = strlen(output) + 20; + tempfile = isc_mem_get(mctx, tempfilelen); + + result = isc_file_mktemplate(output, tempfile, tempfilelen); + check_result(result, "isc_file_mktemplate"); + + result = isc_file_openunique(tempfile, &outfp); + if (result != ISC_R_SUCCESS) { + fatal("failed to open temporary output file: %s", + isc_result_totext(result)); + } + removefile = true; + setfatalcallback(&removetempfile); + } + + print_time(outfp); + print_version(outfp); + + isc_mutex_init(&namelock); + + presign(); + sign_start = isc_time_now(); + signapex(); + if (!atomic_load(&finished)) { + /* + * There is more work to do. Spread it out over multiple + * processors if possible. + */ + isc_loopmgr_setup(loopmgr, assignwork, NULL); + isc_loopmgr_teardown(loopmgr, abortwork, NULL); + isc_loopmgr_run(loopmgr); + + if (!atomic_load(&finished)) { + fatal("process aborted by user"); + } + } + postsign(); + sign_finish = isc_time_now(); + + if (disable_zone_check) { + vresult = ISC_R_SUCCESS; + } else { + vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, + NULL, mctx, ignore_kskflag, + keyset_kskonly, report); + if (vresult != ISC_R_SUCCESS) { + fprintf(output_stdout ? stderr : stdout, + "Zone verification failed (%s)\n", + isc_result_totext(vresult)); + } + } + + if (!output_dnssec_only) { + dns_masterrawheader_t header; + dns_master_initrawheader(&header); + if (rawversion == 0U) { + header.flags = DNS_MASTERRAW_COMPAT; + } else if (snset) { + header.flags = DNS_MASTERRAW_SOURCESERIALSET; + header.sourceserial = serialnum; + } + result = dns_master_dumptostream(mctx, gdb, gversion, + masterstyle, outputformat, + &header, outfp); + check_result(result, "dns_master_dumptostream"); + } + + if (!output_stdout) { + result = isc_stdio_close(outfp); + check_result(result, "isc_stdio_close"); + removefile = false; + + if (vresult == ISC_R_SUCCESS) { + result = isc_file_rename(tempfile, output); + if (result != ISC_R_SUCCESS) { + fatal("failed to rename temp file to %s: %s", + output, isc_result_totext(result)); + } + printf("%s\n", output); + } else { + isc_file_remove(tempfile); + } + } + + dns_db_closeversion(gdb, &gversion, false); + dns_db_detach(&gdb); + + hashlist_free(&hashlist); + + while (!ISC_LIST_EMPTY(keylist)) { + key = ISC_LIST_HEAD(keylist); + ISC_LIST_UNLINK(keylist, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + if (tempfilelen != 0) { + isc_mem_put(mctx, tempfile, tempfilelen); + } + + if (free_output) { + isc_mem_free(mctx, output); + } + + dns_master_styledestroy(&dsstyle, mctx); + + cleanup_logging(&log); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + if (base != NULL) { + OSSL_PROVIDER_unload(base); + } + if (fips != NULL) { + OSSL_PROVIDER_unload(fips); + } +#endif + + isc_managers_destroy(&mctx, &loopmgr, &netmgr); + + if (printstats) { + timer_finish = isc_time_now(); + print_stats(&timer_start, &timer_finish, &sign_start, + &sign_finish); + } + isc_mutex_destroy(&namelock); + + return vresult == ISC_R_SUCCESS ? 0 : 1; +} diff --git a/bin/dnssec/dnssec-signzone.rst b/bin/dnssec/dnssec-signzone.rst new file mode 100644 index 0000000..54824d9 --- /dev/null +++ b/bin/dnssec/dnssec-signzone.rst @@ -0,0 +1,459 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-signzone +.. program:: dnssec-signzone +.. _man_dnssec-signzone: + +dnssec-signzone - DNSSEC zone signing tool +------------------------------------------ + +Synopsis +~~~~~~~~ + +:program:`dnssec-signzone` [**-a**] [**-c** class] [**-d** directory] [**-D**] [**-E** engine] [**-e** end-time] [**-f** output-file] [**-F**] [**-g**] [**-G sync-records**] [**-h**] [**-i** interval] [**-I** input-format] [**-j** jitter] [**-J** filename] [**-K** directory] [**-k** key] [**-L** serial] [**-M** maxttl] [**-N** soa-serial-format] [**-o** origin] [**-O** output-format] [**-P**] [**-Q**] [**-q**] [**-R**] [**-S**] [**-s** start-time] [**-T** ttl] [**-t**] [**-u**] [**-v** level] [**-V**] [**-X** extended end-time] [**-x**] [**-z**] [**-3** salt] [**-H** iterations] [**-A**] {zonefile} [key...] + +Description +~~~~~~~~~~~ + +:program:`dnssec-signzone` signs a zone; it generates NSEC and RRSIG records +and produces a signed version of the zone. The security status of +delegations from the signed zone (that is, whether the child zones are +secure) is determined by the presence or absence of a ``keyset`` +file for each child zone. + +Options +~~~~~~~ + +.. option:: -a + + This option verifies all generated signatures. + +.. option:: -c class + + This option specifies the DNS class of the zone. + +.. option:: -C + + This option sets compatibility mode, in which a ``keyset-zonename`` file is generated in addition + to ``dsset-zonename`` when signing a zone, for use by older versions + of :program:`dnssec-signzone`. + +.. option:: -d directory + + This option indicates the directory where BIND 9 should look for ``dsset-`` or ``keyset-`` files. + +.. option:: -D + + This option indicates that only those record types automatically managed by + :program:`dnssec-signzone`, i.e., RRSIG, NSEC, NSEC3 and NSEC3PARAM records, should be included in the output. + If smart signing (:option:`-S`) is used, DNSKEY records are also included. + The resulting file can be included in the original zone file with + ``$INCLUDE``. This option cannot be combined with :option:`-O raw <-O>` + or serial-number updating. + +.. option:: -E engine + + This option specifies the hardware to use for cryptographic + operations, such as a secure key store used for signing, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -F + + This options turns on FIPS (US Federal Information Processing Standards) + mode if the underlying crytographic library supports running in FIPS + mode. + +.. option:: -g + + This option indicates that DS records for child zones should be generated from a ``dsset-`` or ``keyset-`` + file. Existing DS records are removed. + +.. option:: -G sync-records + + This option indicates which CDS and CDNSKEY records should be generated. ``sync-records`` is a + comma-separated string with the following allowed items: ``cdnskey``, and ``cds:``, + where ``digest-type`` is an allowed algorithm such as SHA-256 (2), or SHA-384 (4). + Only works in combination with smart signing (``-S``). + +.. option:: -J filename + + This option tells :program:`dnssec-signzone` to read the journal from the given file + when loading the zone file. + +.. option:: -K directory + + This option specifies the directory to search for DNSSEC keys. If not + specified, it defaults to the current directory. + +.. option:: -k key + + This option tells BIND 9 to treat the specified key as a key-signing key, ignoring any key flags. This + option may be specified multiple times. + +.. option:: -M maxttl + + This option sets the maximum TTL for the signed zone. Any TTL higher than ``maxttl`` + in the input zone is reduced to ``maxttl`` in the output. This + provides certainty as to the largest possible TTL in the signed zone, + which is useful to know when rolling keys. The maxttl is the longest + possible time before signatures that have been retrieved by resolvers + expire from resolver caches. Zones that are signed with this + option should be configured to use a matching ``max-zone-ttl`` in + :iscman:`named.conf`. (Note: This option is incompatible with :option:`-D`, + because it modifies non-DNSSEC data in the output zone.) + +.. option:: -s start-time + + This option specifies the date and time when the generated RRSIG records become + valid. This can be either an absolute or relative time. An absolute + start time is indicated by a number in YYYYMMDDHHMMSS notation; + 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative + start time is indicated by ``+N``, which is N seconds from the current + time. If no ``start-time`` is specified, the current time minus 1 + hour (to allow for clock skew) is used. + +.. option:: -e end-time + + This option specifies the date and time when the generated RRSIG records expire. As + with ``start-time``, an absolute time is indicated in YYYYMMDDHHMMSS + notation. A time relative to the start time is indicated with ``+N``, + which is N seconds from the start time. A time relative to the + current time is indicated with ``now+N``. If no ``end-time`` is + specified, 30 days from the start time is the default. + ``end-time`` must be later than ``start-time``. + +.. option:: -X extended end-time + + This option specifies the date and time when the generated RRSIG records for the + DNSKEY RRset expire. This is to be used in cases when the DNSKEY + signatures need to persist longer than signatures on other records; + e.g., when the private component of the KSK is kept offline and the + KSK signature is to be refreshed manually. + + As with ``end-time``, an absolute time is indicated in + YYYYMMDDHHMMSS notation. A time relative to the start time is + indicated with ``+N``, which is N seconds from the start time. A time + relative to the current time is indicated with ``now+N``. If no + ``extended end-time`` is specified, the value of ``end-time`` is used + as the default. (``end-time``, in turn, defaults to 30 days from the + start time.) ``extended end-time`` must be later than ``start-time``. + +.. option:: -f output-file + + This option indicates the name of the output file containing the signed zone. The default + is to append ``.signed`` to the input filename. If ``output-file`` is + set to ``-``, then the signed zone is written to the standard + output, with a default output format of ``full``. + +.. option:: -h + + This option prints a short summary of the options and arguments to + :program:`dnssec-signzone`. + +.. option:: -V + + This option prints version information. + +.. option:: -i interval + + This option indicates that, when a previously signed zone is passed as input, records may be + re-signed. The ``interval`` option specifies the cycle interval as an + offset from the current time, in seconds. If a RRSIG record expires + after the cycle interval, it is retained; otherwise, it is considered + to be expiring soon and it is replaced. + + The default cycle interval is one quarter of the difference between + the signature end and start times. So if neither ``end-time`` nor + ``start-time`` is specified, :program:`dnssec-signzone` generates + signatures that are valid for 30 days, with a cycle interval of 7.5 + days. Therefore, if any existing RRSIG records are due to expire in + less than 7.5 days, they are replaced. + + Note that the calculation of cycle interval is based upon the validity + period of the replacement signatures that would be generated by + ``dnssec-signzone``, not on the valid lifetimes of the input RRSIGs being + considered for pre-expiry replacement. + +.. option:: -I input-format + + This option sets the format of the input zone file. Possible formats are + ``text`` (the default), and ``raw``. This option is primarily + intended to be used for dynamic signed zones, so that the dumped zone + file in a non-text format containing updates can be signed directly. + This option is not useful for non-dynamic zones. + +.. option:: -j jitter + + When signing a zone with a fixed signature lifetime, all RRSIG + records issued at the time of signing expire simultaneously. If the + zone is incrementally signed, i.e., a previously signed zone is passed + as input to the signer, all expired signatures must be regenerated + at approximately the same time. The ``jitter`` option specifies a jitter + window that is used to randomize the signature expire time, thus + spreading incremental signature regeneration over time. + + Signature lifetime jitter also, to some extent, benefits validators and + servers by spreading out cache expiration, i.e., if large numbers of + RRSIGs do not expire at the same time from all caches, there is + less congestion than if all validators need to refetch at around the + same time. + +.. option:: -L serial + + When writing a signed zone to "raw" format, this option sets the "source + serial" value in the header to the specified ``serial`` number. (This is + expected to be used primarily for testing purposes.) + +.. option:: -n ncpus + + This option specifies the number of threads to use. By default, one thread is + started for each detected CPU. + +.. option:: -N soa-serial-format + + This option sets the SOA serial number format of the signed zone. Possible formats are + ``keep`` (the default), ``increment``, ``unixtime``, and + ``date``. + + **keep** + This format indicates that the SOA serial number should not be modified. + + **increment** + This format increments the SOA serial number using :rfc:`1982` arithmetic. + + **unixtime** + This format sets the SOA serial number to the number of seconds + since the beginning of the Unix epoch, unless the serial + number is already greater than or equal to that value, in + which case it is simply incremented by one. + + **date** + This format sets the SOA serial number to today's date, in + YYYYMMDDNN format, unless the serial number is already greater + than or equal to that value, in which case it is simply + incremented by one. + +.. option:: -o origin + + This option sets the zone origin. If not specified, the name of the zone file is + assumed to be the origin. + +.. option:: -O output-format + + This option sets the format of the output file containing the signed + zone. Possible formats are ``text`` (the default), which is the standard + textual representation of the zone; ``full``, which is text output in a + format suitable for processing by external scripts; and ``raw`` and + ``raw=N``, which store the zone in binary formats for rapid loading by + :iscman:`named`. ``raw=N`` specifies the format version of the raw zone file: + if N is 0, the raw file can be read by any version of :iscman:`named`; if N is + 1, the file can be read by release 9.9.0 or higher. The default is 1. + +.. option:: -P + + This option disables post-sign verification tests. + + The post-sign verification tests ensure that for each algorithm in + use there is at least one non-revoked self-signed KSK key, that all + revoked KSK keys are self-signed, and that all records in the zone + are signed by the algorithm. This option skips these tests. + +.. option:: -Q + + This option removes signatures from keys that are no longer active. + + Normally, when a previously signed zone is passed as input to the + signer, and a DNSKEY record has been removed and replaced with a new + one, signatures from the old key that are still within their validity + period are retained. This allows the zone to continue to validate + with cached copies of the old DNSKEY RRset. The :option:`-Q` option forces + :program:`dnssec-signzone` to remove signatures from keys that are no longer + active. This enables ZSK rollover using the procedure described in + :rfc:`6781#section-4.1.1.1` ("Pre-Publish Zone Signing Key Rollover"). + +.. option:: -q + + This option enables quiet mode, which suppresses unnecessary output. Without this option, when + :program:`dnssec-signzone` is run it prints three pieces of information to standard output: the number of + keys in use; the algorithms used to verify the zone was signed correctly and + other status information; and the filename containing the signed + zone. With the option that output is suppressed, leaving only the filename. + +.. option:: -R + + This option removes signatures from keys that are no longer published. + + This option is similar to :option:`-Q`, except it forces + :program:`dnssec-signzone` to remove signatures from keys that are no longer + published. This enables ZSK rollover using the procedure described in + :rfc:`6781#section-4.1.1.2` ("Double Signature Zone Signing Key + Rollover"). + +.. option:: -S + + This option enables smart signing, which instructs :program:`dnssec-signzone` to search the key + repository for keys that match the zone being signed, and to include + them in the zone if appropriate. + + When a key is found, its timing metadata is examined to determine how + it should be used, according to the following rules. Each successive + rule takes priority over the prior ones: + + If no timing metadata has been set for the key, the key is + published in the zone and used to sign the zone. + + If the key's publication date is set and is in the past, the key + is published in the zone. + + If the key's activation date is set and is in the past, the key is + published (regardless of publication date) and used to sign the + zone. + + If the key's revocation date is set and is in the past, and the key + is published, then the key is revoked, and the revoked key is used + to sign the zone. + + If either the key's unpublication or deletion date is set and + in the past, the key is NOT published or used to sign the zone, + regardless of any other metadata. + + If the key's sync publication date is set and is in the past, + synchronization records (type CDS and/or CDNSKEY) are created. + + If the key's sync deletion date is set and is in the past, + synchronization records (type CDS and/or CDNSKEY) are removed. + +.. option:: -T ttl + + This option specifies a TTL to be used for new DNSKEY records imported into the + zone from the key repository. If not specified, the default is the + TTL value from the zone's SOA record. This option is ignored when + signing without :option:`-S`, since DNSKEY records are not imported from + the key repository in that case. It is also ignored if there are any + pre-existing DNSKEY records at the zone apex, in which case new + records' TTL values are set to match them, or if any of the + imported DNSKEY records had a default TTL value. In the event of a + conflict between TTL values in imported keys, the shortest one is + used. + +.. option:: -t + + This option prints statistics at completion. + +.. option:: -u + + This option updates the NSEC/NSEC3 chain when re-signing a previously signed zone. + With this option, a zone signed with NSEC can be switched to NSEC3, + or a zone signed with NSEC3 can be switched to NSEC or to NSEC3 with + different parameters. Without this option, :program:`dnssec-signzone` + retains the existing chain when re-signing. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -x + + This option indicates that BIND 9 should only sign the DNSKEY, CDNSKEY, and CDS RRsets with key-signing keys, + and should omit signatures from zone-signing keys. + +.. option:: -z + + This option indicates that BIND 9 should ignore the KSK flag on keys when determining what to sign. This causes + KSK-flagged keys to sign all records, not just the DNSKEY RRset. + +.. option:: -3 salt + + This option generates an NSEC3 chain with the given hex-encoded salt. A dash + (-) can be used to indicate that no salt is to be used when + generating the NSEC3 chain. + + .. note:: + ``-3 -`` is the recommended configuration. Adding salt provides no practical benefits. + See :rfc:`9276`. + +.. option:: -H iterations + + This option indicates that, when generating an NSEC3 chain, BIND 9 should use this many iterations. The default + is 0. + + .. warning:: + Values greater than 0 cause interoperability issues and also increase the risk of CPU-exhausting DoS attacks. + See :rfc:`9276`. + +.. option:: -A + + This option indicates that, when generating an NSEC3 chain, BIND 9 should set the OPTOUT flag on all NSEC3 + records and should not generate NSEC3 records for insecure delegations. + + .. warning:: + Do not use this option unless all its implications are fully understood. This option is intended only for extremely large zones (comparable to ``com.``) with sparse secure delegations. + See :rfc:`9276`. + +.. option:: -AA + + This option turns the OPTOUT flag off for + all records. This is useful when using the :option:`-u` option to modify an + NSEC3 chain which previously had OPTOUT set. + +.. option:: zonefile + + This option sets the file containing the zone to be signed. + +.. option:: key + + This option specifies which keys should be used to sign the zone. If no keys are + specified, the zone is examined for DNSKEY records at the + zone apex. If these records are found and there are matching private keys in + the current directory, they are used for signing. + +Example +~~~~~~~ + +The following command signs the ``example.com`` zone with the +ECDSAP256SHA256 key generated by :iscman:`dnssec-keygen` +(Kexample.com.+013+17247). Because the :option:`-S` option is not being used, +the zone's keys must be in the master file (``db.example.com``). This +invocation looks for ``dsset`` files in the current directory, so that +DS records can be imported from them (:option:`-g`). + +:: + + % dnssec-signzone -g -o example.com db.example.com \ + Kexample.com.+013+17247 + db.example.com.signed + % + +In the above example, :program:`dnssec-signzone` creates the file +``db.example.com.signed``. This file should be referenced in a zone +statement in the :iscman:`named.conf` file. + +This example re-signs a previously signed zone with default parameters. +The private keys are assumed to be in the current directory. + +:: + + % cp db.example.com.signed db.example.com + % dnssec-signzone -o example.com db.example.com + db.example.com.signed + % + +See Also +~~~~~~~~ + +:iscman:`dnssec-keygen(8) `, BIND 9 Administrator Reference Manual, :rfc:`4033`, +:rfc:`6781`. diff --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c new file mode 100644 index 0000000..f71f005 --- /dev/null +++ b/bin/dnssec/dnssec-verify.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dnssectool.h" + +const char *program = "dnssec-verify"; + +static isc_stdtime_t now; +static isc_mem_t *mctx = NULL; +static dns_masterformat_t inputformat = dns_masterformat_text; +static dns_db_t *gdb = NULL; /* The database */ +static dns_dbversion_t *gversion = NULL; /* The database version */ +static dns_rdataclass_t gclass; /* The class */ +static dns_name_t *gorigin = NULL; /* The database origin */ +static bool ignore_kskflag = false; +static bool keyset_kskonly = false; + +static void +report(const char *format, ...) { + if (!quiet) { + char buf[4096]; + va_list args; + + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + fprintf(stdout, "%s\n", buf); + } +} + +/*% + * Load the zone file from disk + */ +static void +loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { + isc_buffer_t b; + int len; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + + len = strlen(origin); + isc_buffer_init(&b, origin, len); + isc_buffer_add(&b, len); + + name = dns_fixedname_initname(&fname); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fatal("failed converting name '%s' to dns format: %s", origin, + isc_result_totext(result)); + } + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + rdclass, 0, NULL, db); + check_result(result, "dns_db_create()"); + + result = dns_db_load(*db, file, inputformat, 0); + switch (result) { + case DNS_R_SEENINCLUDE: + case ISC_R_SUCCESS: + break; + case DNS_R_NOTZONETOP: + /* + * Comparing pointers (vs. using strcmp()) is intentional: we + * want to check whether -o was supplied on the command line, + * not whether origin and file contain the same string. + */ + if (origin == file) { + fatal("failed loading zone '%s' from file '%s': " + "use -o to specify a different zone origin", + origin, file); + } + FALLTHROUGH; + default: + fatal("failed loading zone from '%s': %s", file, + isc_result_totext(result)); + } +} + +noreturn static void +usage(void); + +static void +usage(void) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\t%s [options] zonefile [keys]\n", program); + + fprintf(stderr, "\n"); + + fprintf(stderr, "Version: %s\n", PACKAGE_VERSION); + + fprintf(stderr, "Options: (default value in parenthesis) \n"); + fprintf(stderr, "\t-v debuglevel (0)\n"); + fprintf(stderr, "\t-q quiet\n"); + fprintf(stderr, "\t-V:\tprint version information\n"); + fprintf(stderr, "\t-o origin:\n"); + fprintf(stderr, "\t\tzone origin (name of zonefile)\n"); + fprintf(stderr, "\t-I format:\n"); + fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); + fprintf(stderr, "\t-c class (IN)\n"); + fprintf(stderr, "\t-E engine:\n"); + fprintf(stderr, "\t\tname of an OpenSSL engine to use\n"); + fprintf(stderr, "\t-x:\tDNSKEY record signed with KSKs only, " + "not ZSKs\n"); + fprintf(stderr, "\t-z:\tAll records signed with KSKs\n"); + exit(EXIT_SUCCESS); +} + +int +main(int argc, char *argv[]) { + char *origin = NULL, *file = NULL; + char *inputformatstr = NULL; + isc_result_t result; + isc_log_t *log = NULL; + const char *engine = NULL; + char *classname = NULL; + dns_rdataclass_t rdclass; + char *endp; + int ch; + +#define CMDLINE_FLAGS "c:E:hJ:m:o:I:qv:Vxz" + + /* + * Process memory debugging argument first. + */ + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'm': + if (strcasecmp(isc_commandline_argument, "record") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + } + if (strcasecmp(isc_commandline_argument, "trace") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGTRACE; + } + if (strcasecmp(isc_commandline_argument, "usage") == 0) + { + isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; + } + break; + default: + break; + } + } + isc_commandline_reset = true; + + isc_mem_create(&mctx); + + isc_commandline_errprint = false; + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case 'c': + classname = isc_commandline_argument; + break; + + case 'E': + engine = isc_commandline_argument; + break; + + case 'I': + inputformatstr = isc_commandline_argument; + break; + + case 'J': + journal = isc_commandline_argument; + break; + + case 'm': + break; + + case 'o': + origin = isc_commandline_argument; + break; + + case 'v': + endp = NULL; + verbose = strtol(isc_commandline_argument, &endp, 0); + if (*endp != '\0') { + fatal("verbose level must be numeric"); + } + break; + + case 'q': + quiet = true; + break; + + case 'x': + keyset_kskonly = true; + break; + + case 'z': + ignore_kskflag = true; + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + } + FALLTHROUGH; + + case 'h': + /* Does not return. */ + usage(); + + case 'V': + /* Does not return. */ + version(program); + + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + result = dst_lib_init(mctx, engine); + if (result != ISC_R_SUCCESS) { + fatal("could not initialize dst: %s", + isc_result_totext(result)); + } + + now = isc_stdtime_now(); + + rdclass = strtoclass(classname); + + setup_logging(mctx, &log); + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argc < 1) { + usage(); + } + + file = argv[0]; + + argc -= 1; + argv += 1; + + POST(argc); + POST(argv); + + if (origin == NULL) { + origin = file; + } + + if (inputformatstr != NULL) { + if (strcasecmp(inputformatstr, "text") == 0) { + inputformat = dns_masterformat_text; + } else if (strcasecmp(inputformatstr, "raw") == 0) { + inputformat = dns_masterformat_raw; + } else { + fatal("unknown file format: %s\n", inputformatstr); + } + } + + gdb = NULL; + report("Loading zone '%s' from file '%s'\n", origin, file); + loadzone(file, origin, rdclass, &gdb); + if (journal != NULL) { + loadjournal(mctx, gdb, journal); + } + gorigin = dns_db_origin(gdb); + gclass = dns_db_class(gdb); + + gversion = NULL; + result = dns_db_newversion(gdb, &gversion); + check_result(result, "dns_db_newversion()"); + + result = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin, NULL, mctx, + ignore_kskflag, keyset_kskonly, report); + + dns_db_closeversion(gdb, &gversion, false); + dns_db_detach(&gdb); + + cleanup_logging(&log); + dst_lib_destroy(); + if (verbose > 10) { + isc_mem_stats(mctx, stdout); + } + isc_mem_destroy(&mctx); + + return result == ISC_R_SUCCESS ? 0 : 1; +} diff --git a/bin/dnssec/dnssec-verify.rst b/bin/dnssec/dnssec-verify.rst new file mode 100644 index 0000000..7f55353 --- /dev/null +++ b/bin/dnssec/dnssec-verify.rst @@ -0,0 +1,112 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: dnssec-verify +.. program:: dnssec-verify +.. _man_dnssec-verify: + +dnssec-verify - DNSSEC zone verification tool +--------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`dnssec-verify` [**-c** class] [**-E** engine] [**-I** input-format] [**-J** filename] [**-o** origin] [**-q**] [**-v** level] [**-V**] [**-x**] [**-z**] {zonefile} + +Description +~~~~~~~~~~~ + +:program:`dnssec-verify` verifies that a zone is fully signed for each +algorithm found in the DNSKEY RRset for the zone, and that the +NSEC/NSEC3 chains are complete. + +Options +~~~~~~~ + +.. option:: -c class + + This option specifies the DNS class of the zone. + +.. option:: -E engine + + This option specifies the cryptographic hardware to use, when applicable. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -I input-format + + This option sets the format of the input zone file. Possible formats are ``text`` + (the default) and ``raw``. This option is primarily intended to be used + for dynamic signed zones, so that the dumped zone file in a non-text + format containing updates can be verified independently. + This option is not useful for non-dynamic zones. + +.. option:: -J filename + + This option tells :program:`dnssec-verify` to read the journal from the given file + when loading the zone file. + +.. option:: -o origin + + This option indicates the zone origin. If not specified, the name of the zone file is + assumed to be the origin. + +.. option:: -v level + + This option sets the debugging level. + +.. option:: -V + + This option prints version information. + +.. option:: -q + + This option sets quiet mode, which suppresses output. Without this option, when :program:`dnssec-verify` + is run it prints to standard output the number of keys in use, the + algorithms used to verify the zone was signed correctly, and other status + information. With this option, all non-error output is suppressed, and only the exit + code indicates success. + +.. option:: -x + + This option verifies only that the DNSKEY RRset is signed with key-signing keys. + Without this flag, it is assumed that the DNSKEY RRset is signed + by all active keys. When this flag is set, it is not an error if + the DNSKEY RRset is not signed by zone-signing keys. This corresponds + to the :option:`-x option in dnssec-signzone `. + +.. option:: -z + + This option indicates that the KSK flag on the keys should be ignored when determining whether the zone is + correctly signed. Without this flag, it is assumed that there is + a non-revoked, self-signed DNSKEY with the KSK flag set for each + algorithm, and that RRsets other than DNSKEY RRset are signed with + a different DNSKEY without the KSK flag set. + + With this flag set, BIND 9 only requires that for each algorithm, there + be at least one non-revoked, self-signed DNSKEY, regardless of + the KSK flag state, and that other RRsets be signed by a + non-revoked key for the same algorithm that includes the self-signed + key; the same key may be used for both purposes. This corresponds to + the :option:`-z option in dnssec-signzone `. + +.. option:: zonefile + + This option indicates the file containing the zone to be signed. + +See Also +~~~~~~~~ + +:iscman:`dnssec-signzone(8) `, BIND 9 Administrator Reference Manual, :rfc:`4033`. diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c new file mode 100644 index 0000000..f7faa13 --- /dev/null +++ b/bin/dnssec/dnssectool.c @@ -0,0 +1,702 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/*% + * DNSSEC Support Routines. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dnssectool.h" + +#define KEYSTATES_NVALUES 4 +static const char *keystates[KEYSTATES_NVALUES] = { + "hidden", + "rumoured", + "omnipresent", + "unretentive", +}; + +int verbose = 0; +bool quiet = false; +const char *journal = NULL; +dns_dsdigest_t dtype[8]; + +static fatalcallback_t *fatalcallback = NULL; + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: fatal: ", program); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + if (fatalcallback != NULL) { + (*fatalcallback)(); + } + _exit(EXIT_FAILURE); +} + +void +setfatalcallback(fatalcallback_t *callback) { + fatalcallback = callback; +} + +void +check_result(isc_result_t result, const char *message) { + if (result != ISC_R_SUCCESS) { + fatal("%s: %s", message, isc_result_totext(result)); + } +} + +void +vbprintf(int level, const char *fmt, ...) { + va_list ap; + if (level > verbose) { + return; + } + va_start(ap, fmt); + fprintf(stderr, "%s: ", program); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +void +version(const char *name) { + printf("%s %s\n", name, PACKAGE_VERSION); + exit(EXIT_SUCCESS); +} + +void +sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { + char namestr[DNS_NAME_FORMATSIZE]; + char algstr[DNS_NAME_FORMATSIZE]; + + dns_name_format(&sig->signer, namestr, sizeof(namestr)); + dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); + snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); +} + +void +setup_logging(isc_mem_t *mctx, isc_log_t **logp) { + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + isc_log_t *log = NULL; + int level; + + if (verbose < 0) { + verbose = 0; + } + switch (verbose) { + case 0: + /* + * We want to see warnings about things like out-of-zone + * data in the master file even when not verbose. + */ + level = ISC_LOG_WARNING; + break; + case 1: + level = ISC_LOG_INFO; + break; + default: + level = ISC_LOG_DEBUG(verbose - 2 + 1); + break; + } + + isc_log_create(mctx, &log, &logconfig); + isc_log_setcontext(log); + dns_log_init(log); + dns_log_setcontext(log); + isc_log_settag(logconfig, program); + + /* + * Set up a channel similar to default_stderr except: + * - the logging level is passed in + * - the program name and logging level are printed + * - no time stamp is printed + */ + destination.file.stream = stderr; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level, + &destination, + ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL); + + RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) == + ISC_R_SUCCESS); + + *logp = log; +} + +void +cleanup_logging(isc_log_t **logp) { + isc_log_t *log; + + REQUIRE(logp != NULL); + + log = *logp; + *logp = NULL; + + if (log == NULL) { + return; + } + + isc_log_destroy(&log); + isc_log_setcontext(NULL); + dns_log_setcontext(NULL); +} + +static isc_stdtime_t +time_units(isc_stdtime_t offset, char *suffix, const char *str) { + switch (suffix[0]) { + case 'Y': + case 'y': + return offset * (365 * 24 * 3600); + case 'M': + case 'm': + switch (suffix[1]) { + case 'O': + case 'o': + return offset * (30 * 24 * 3600); + case 'I': + case 'i': + return offset * 60; + case '\0': + fatal("'%s' ambiguous: use 'mi' for minutes " + "or 'mo' for months", + str); + default: + fatal("time value %s is invalid", str); + } + UNREACHABLE(); + break; + case 'W': + case 'w': + return offset * (7 * 24 * 3600); + case 'D': + case 'd': + return offset * (24 * 3600); + case 'H': + case 'h': + return offset * 3600; + case 'S': + case 's': + case '\0': + return offset; + default: + fatal("time value %s is invalid", str); + } + UNREACHABLE(); + return 0; /* silence compiler warning */ +} + +static bool +isnone(const char *str) { + return (strcasecmp(str, "none") == 0) || + (strcasecmp(str, "never") == 0) || + (strcasecmp(str, "unset") == 0); +} + +dns_ttl_t +strtottl(const char *str) { + const char *orig = str; + dns_ttl_t ttl; + char *endp; + + if (isnone(str)) { + return (dns_ttl_t)0; + } + + ttl = strtol(str, &endp, 0); + if (ttl == 0 && endp == str) { + fatal("TTL must be numeric"); + } + ttl = time_units(ttl, endp, orig); + return ttl; +} + +dst_key_state_t +strtokeystate(const char *str) { + if (isnone(str)) { + return DST_KEY_STATE_NA; + } + + for (int i = 0; i < KEYSTATES_NVALUES; i++) { + if (keystates[i] != NULL && strcasecmp(str, keystates[i]) == 0) + { + return (dst_key_state_t)i; + } + } + fatal("unknown key state %s", str); +} + +isc_stdtime_t +strtotime(const char *str, int64_t now, int64_t base, bool *setp) { + int64_t val, offset; + isc_result_t result; + const char *orig = str; + char *endp; + size_t n; + struct tm tm; + + if (isnone(str)) { + SET_IF_NOT_NULL(setp, false); + return (isc_stdtime_t)0; + } + + SET_IF_NOT_NULL(setp, true); + + if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') { + return (isc_stdtime_t)0; + } + + /* + * We accept times in the following formats: + * now([+-]offset) + * YYYYMMDD([+-]offset) + * YYYYMMDDhhmmss([+-]offset) + * Day Mon DD HH:MM:SS YYYY([+-]offset) + * 1234567890([+-]offset) + * [+-]offset + */ + n = strspn(str, "0123456789"); + if ((n == 8u || n == 14u) && + (str[n] == '\0' || str[n] == '-' || str[n] == '+')) + { + char timestr[15]; + + strlcpy(timestr, str, sizeof(timestr)); + timestr[n] = 0; + if (n == 8u) { + strlcat(timestr, "000000", sizeof(timestr)); + } + result = dns_time64_fromtext(timestr, &val); + if (result != ISC_R_SUCCESS) { + fatal("time value %s is invalid: %s", orig, + isc_result_totext(result)); + } + base = val; + str += n; + } else if (n == 10u && + (str[n] == '\0' || str[n] == '-' || str[n] == '+')) + { + base = strtoll(str, &endp, 0); + str += 10; + } else if (strncmp(str, "now", 3) == 0) { + base = now; + str += 3; + } else if (str[0] >= 'A' && str[0] <= 'Z') { + /* parse ctime() format as written by `dnssec-settime -p` */ + endp = isc_tm_strptime(str, "%a %b %d %H:%M:%S %Y", &tm); + if (endp != str + 24) { + fatal("time value %s is invalid", orig); + } + base = mktime(&tm); + str += 24; + } + + if (str[0] == '\0') { + return (isc_stdtime_t)base; + } else if (str[0] == '+') { + offset = strtol(str + 1, &endp, 0); + offset = time_units((isc_stdtime_t)offset, endp, orig); + val = base + offset; + } else if (str[0] == '-') { + offset = strtol(str + 1, &endp, 0); + offset = time_units((isc_stdtime_t)offset, endp, orig); + val = base - offset; + } else { + fatal("time value %s is invalid", orig); + } + + return (isc_stdtime_t)val; +} + +dns_rdataclass_t +strtoclass(const char *str) { + isc_textregion_t r; + dns_rdataclass_t rdclass; + isc_result_t result; + + if (str == NULL) { + return dns_rdataclass_in; + } + r.base = UNCONST(str); + r.length = strlen(str); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + fatal("unknown class %s", str); + } + return rdclass; +} + +unsigned int +strtodsdigest(const char *str) { + isc_textregion_t r; + dns_dsdigest_t alg; + isc_result_t result; + + r.base = UNCONST(str); + r.length = strlen(str); + result = dns_dsdigest_fromtext(&alg, &r); + if (result != ISC_R_SUCCESS) { + fatal("unknown DS algorithm %s", str); + } + return alg; +} + +static int +cmp_dtype(const void *ap, const void *bp) { + int a = *(const uint8_t *)ap; + int b = *(const uint8_t *)bp; + return a - b; +} + +void +add_dtype(unsigned int dt) { + unsigned int i, n; + + /* ensure there is space for a zero terminator */ + n = sizeof(dtype) / sizeof(dtype[0]) - 1; + for (i = 0; i < n; i++) { + if (dtype[i] == dt) { + return; + } + if (dtype[i] == 0) { + dtype[i] = dt; + qsort(dtype, i + 1, 1, cmp_dtype); + return; + } + } + fatal("too many -a digest type arguments"); +} + +isc_result_t +try_dir(const char *dirname) { + isc_result_t result; + isc_dir_t d; + + isc_dir_init(&d); + result = isc_dir_open(&d, dirname); + if (result == ISC_R_SUCCESS) { + isc_dir_close(&d); + } + return result; +} + +/* + * Check private key version compatibility. + */ +void +check_keyversion(dst_key_t *key, char *keystr) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ + + if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) { + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force upgrade to new version.", + keystr, major, minor); + } + if (minor > DST_MINOR_VERSION) { + fatal("Key %s has incompatible format version %d.%d, " + "use -f to force downgrade to current version.", + keystr, major, minor); + } +} + +void +set_keyversion(dst_key_t *key) { + int major, minor; + dst_key_getprivateformat(key, &major, &minor); + INSIST(major <= DST_MAJOR_VERSION); + + if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) { + dst_key_setprivateformat(key, DST_MAJOR_VERSION, + DST_MINOR_VERSION); + } + + /* + * If the key is from a version older than 1.3, set + * set the creation date + */ + if (major < 1 || (major == 1 && minor <= 2)) { + isc_stdtime_t now = isc_stdtime_now(); + dst_key_settime(key, DST_TIME_CREATED, now); + } +} + +bool +key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, + isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact) { + isc_result_t result; + bool conflict = false; + dns_dnsseckeylist_t matchkeys; + dns_dnsseckey_t *key = NULL; + uint16_t id, oldid; + uint32_t rid, roldid; + dns_secalg_t alg; + isc_stdtime_t now = isc_stdtime_now(); + + SET_IF_NOT_NULL(exact, false); + + id = dst_key_id(dstkey); + rid = dst_key_rid(dstkey); + alg = dst_key_alg(dstkey); + + if (min != max) { + if (id < min || id > max) { + fprintf(stderr, "Key ID %d outside of [%u..%u]\n", id, + min, max); + return true; + } + if (rid < min || rid > max) { + fprintf(stderr, + "Revoked Key ID %d (for tag %d) outside of " + "[%u..%u]\n", + rid, id, min, max); + return true; + } + } + + ISC_LIST_INIT(matchkeys); + result = dns_dnssec_findmatchingkeys(name, NULL, dir, NULL, now, mctx, + &matchkeys); + if (result == ISC_R_NOTFOUND) { + return false; + } + + while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { + key = ISC_LIST_HEAD(matchkeys); + if (dst_key_alg(key->key) != alg) { + goto next; + } + + oldid = dst_key_id(key->key); + roldid = dst_key_rid(key->key); + + if (oldid == rid || roldid == id || id == oldid) { + conflict = true; + if (id != oldid) { + if (verbose > 1) { + fprintf(stderr, + "Key ID %d could " + "collide with %d\n", + id, oldid); + } + } else { + if (exact != NULL) { + *exact = true; + } + if (verbose > 1) { + fprintf(stderr, "Key ID %d exists\n", + id); + } + } + } + + next: + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + /* Finish freeing the list */ + while (!ISC_LIST_EMPTY(matchkeys)) { + key = ISC_LIST_HEAD(matchkeys); + ISC_LIST_UNLINK(matchkeys, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + + return conflict; +} + +bool +isoptarg(const char *arg, char **argv, void (*usage)(void)) { + if (!strcasecmp(isc_commandline_argument, arg)) { + if (argv[isc_commandline_index] == NULL) { + fprintf(stderr, "%s: missing argument -%c %s\n", + program, isc_commandline_option, + isc_commandline_argument); + usage(); + } + isc_commandline_argument = argv[isc_commandline_index]; + /* skip to next argument */ + isc_commandline_index++; + return true; + } + return false; +} + +void +loadjournal(isc_mem_t *mctx, dns_db_t *db, const char *file) { + dns_journal_t *jnl = NULL; + isc_result_t result; + + result = dns_journal_open(mctx, file, DNS_JOURNAL_READ, &jnl); + if (result == ISC_R_NOTFOUND) { + fprintf(stderr, "%s: journal file %s not found\n", program, + file); + goto cleanup; + } else if (result != ISC_R_SUCCESS) { + fatal("unable to open journal %s: %s\n", file, + isc_result_totext(result)); + } + + if (dns_journal_empty(jnl)) { + dns_journal_destroy(&jnl); + return; + } + + result = dns_journal_rollforward(jnl, db, 0); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + break; + + case ISC_R_NOTFOUND: + case ISC_R_RANGE: + fatal("journal %s out of sync with zone", file); + + default: + fatal("journal %s: %s\n", file, isc_result_totext(result)); + } + +cleanup: + dns_journal_destroy(&jnl); +} + +void +kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *lctx, + const char *name, const char *keydir, const char *engine, + dns_kasp_t **kaspp) { + isc_result_t result = ISC_R_NOTFOUND; + const cfg_listelt_t *element; + const cfg_obj_t *kasps = NULL; + dns_kasp_t *kasp = NULL, *kasp_next; + dns_kasplist_t kasplist; + const cfg_obj_t *keystores = NULL; + dns_keystore_t *ks = NULL, *ks_next; + dns_keystorelist_t kslist; + + ISC_LIST_INIT(kasplist); + ISC_LIST_INIT(kslist); + + (void)cfg_map_get(config, "key-store", &keystores); + for (element = cfg_list_first(keystores); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *kconfig = cfg_listelt_value(element); + ks = NULL; + result = cfg_keystore_fromconfig(kconfig, mctx, lctx, engine, + &kslist, NULL); + if (result != ISC_R_SUCCESS) { + fatal("failed to configure key-store '%s': %s", + cfg_obj_asstring(cfg_tuple_get(kconfig, "name")), + isc_result_totext(result)); + } + } + /* Default key-directory key store. */ + ks = NULL; + (void)cfg_keystore_fromconfig(NULL, mctx, lctx, engine, &kslist, &ks); + INSIST(ks != NULL); + if (keydir != NULL) { + /* '-K keydir' takes priority */ + dns_keystore_setdirectory(ks, keydir); + } + dns_keystore_detach(&ks); + + (void)cfg_map_get(config, "dnssec-policy", &kasps); + for (element = cfg_list_first(kasps); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *kconfig = cfg_listelt_value(element); + kasp = NULL; + if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")), + name) != 0) + { + continue; + } + + result = cfg_kasp_fromconfig(kconfig, NULL, true, mctx, lctx, + &kslist, &kasplist, &kasp); + if (result != ISC_R_SUCCESS) { + fatal("failed to configure dnssec-policy '%s': %s", + cfg_obj_asstring(cfg_tuple_get(kconfig, "name")), + isc_result_totext(result)); + } + INSIST(kasp != NULL); + dns_kasp_freeze(kasp); + break; + } + + *kaspp = kasp; + + /* + * Cleanup kasp list. + */ + for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { + kasp_next = ISC_LIST_NEXT(kasp, link); + ISC_LIST_UNLINK(kasplist, kasp, link); + dns_kasp_detach(&kasp); + } + + /* + * Cleanup keystore list. + */ + for (ks = ISC_LIST_HEAD(kslist); ks != NULL; ks = ks_next) { + ks_next = ISC_LIST_NEXT(ks, link); + ISC_LIST_UNLINK(kslist, ks, link); + dns_keystore_detach(&ks); + } +} diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h new file mode 100644 index 0000000..8b0f038 --- /dev/null +++ b/bin/dnssec/dnssectool.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#define MAX_RSA 4096 /* should be long enough... */ +#define MAX_DH 4096 /* should be long enough... */ + +/*! verbosity: set by -v and -q option in each program, defined in dnssectool.c + */ +extern int verbose; +extern bool quiet; + +/*! program name, statically initialized in each program */ +extern const char *program; + +/*! journal file */ +extern const char *journal; + +/*! + * List of DS digest types used by dnssec-cds and dnssec-dsfromkey, + * defined in dnssectool.c. Filled in by add_dtype() from -a + * arguments, sorted (so that DS records are in a canonical order) and + * terminated by a zero. The size of the array is an arbitrary limit + * which should be greater than the number of known digest types. + */ +extern uint8_t dtype[8]; + +typedef void(fatalcallback_t)(void); + +noreturn void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +void +setfatalcallback(fatalcallback_t *callback); + +void +check_result(isc_result_t result, const char *message); + +void +vbprintf(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); + +noreturn void +version(const char *program); + +void +sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size); +#define SIG_FORMATSIZE \ + (DNS_NAME_FORMATSIZE + DNS_SECALG_FORMATSIZE + sizeof("65535")) + +void +setup_logging(isc_mem_t *mctx, isc_log_t **logp); + +void +cleanup_logging(isc_log_t **logp); + +dns_ttl_t +strtottl(const char *str); + +dst_key_state_t +strtokeystate(const char *str); + +isc_stdtime_t +strtotime(const char *str, int64_t now, int64_t base, bool *setp); + +dns_rdataclass_t +strtoclass(const char *str); + +unsigned int +strtodsdigest(const char *str); + +void +add_dtype(unsigned int dt); + +isc_result_t +try_dir(const char *dirname); + +void +check_keyversion(dst_key_t *key, char *keystr); + +void +set_keyversion(dst_key_t *key); + +bool +key_collision(dst_key_t *key, dns_name_t *name, const char *dir, + isc_mem_t *mctx, uint16_t min, uint16_t max, bool *exact); + +bool +isoptarg(const char *arg, char **argv, void (*usage)(void)); + +void +loadjournal(isc_mem_t *mctx, dns_db_t *db, const char *journal); + +void +kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *lctx, + const char *name, const char *keydir, const char *engine, + dns_kasp_t **kaspp); diff --git a/bin/named/Makefile.am b/bin/named/Makefile.am new file mode 100644 index 0000000..291bab5 --- /dev/null +++ b/bin/named/Makefile.am @@ -0,0 +1,127 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + -I$(top_builddir)/include \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBISCCC_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(OPENSSL_CFLAGS) \ + $(LIBCAP_CFLAGS) \ + $(LMDB_CFLAGS) \ + $(MAXMINDDB_CFLAGS) \ + $(DNSTAP_CFLAGS) \ + $(LIBUV_CFLAGS) \ + $(LIBSYSTEMD_CFLAGS) \ + $(ZLIB_CFLAGS) + +if HAVE_JSON_C +AM_CPPFLAGS += \ + $(JSON_C_CFLAGS) +endif HAVE_JSON_C + +if HAVE_LIBNGHTTP2 +AM_CPPFLAGS += \ + $(LIBNGHTTP2_CFLAGS) +endif HAVE_LIBNGHTTP2 + +if HAVE_LIBXML2 +AM_CPPFLAGS += \ + $(LIBXML2_CFLAGS) +endif HAVE_LIBXML2 + +AM_CPPFLAGS += \ + -DNAMED_LOCALSTATEDIR=\"${localstatedir}\" \ + -DNAMED_SYSCONFDIR=\"${sysconfdir}\" + +sbin_PROGRAMS = named + +nodist_named_SOURCES = xsl.c +BUILT_SOURCES += xsl.c +CLEANFILES += xsl.c + +EXTRA_DIST = bind9.xsl + +xsl.c: bind9.xsl Makefile + (echo 'const char xslmsg[] =' && \ + $(SED) -e 's,\",\\\",g' \ + -e 's,^,\",' \ + -e 's,$$,\\n\",' && \ + echo ";") \ + < "${srcdir}/bind9.xsl" > $@ + +named_SOURCES = \ + builtin.c \ + config.c \ + control.c \ + controlconf.c \ + dlz_dlopen_driver.c \ + fuzz.c \ + log.c \ + logconf.c \ + main.c \ + os.c \ + server.c \ + statschannel.c \ + tkeyconf.c \ + transportconf.c \ + tsigconf.c \ + zoneconf.c \ + include/dlz/dlz_dlopen_driver.h \ + include/named/builtin.h \ + include/named/config.h \ + include/named/control.h \ + include/named/fuzz.h \ + include/named/geoip.h \ + include/named/globals.h \ + include/named/log.h \ + include/named/logconf.h \ + include/named/main.h \ + include/named/os.h \ + include/named/server.h \ + include/named/smf_globals.h \ + include/named/statschannel.h \ + include/named/tkeyconf.h \ + include/named/transportconf.h \ + include/named/tsigconf.h \ + include/named/types.h \ + include/named/zoneconf.h \ + xsl_p.h + +if HAVE_GEOIP2 +AM_CPPFLAGS += \ + -DMAXMINDDB_PREFIX=\"@MAXMINDDB_PREFIX@\" +named_SOURCES += \ + geoip.c +endif + +named_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) \ + $(LIBISCCC_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(OPENSSL_LIBS) \ + $(LIBCAP_LIBS) \ + $(LMDB_LIBS) \ + $(MAXMINDDB_LIBS) \ + $(DNSTAP_LIBS) \ + $(LIBUV_LIBS) \ + $(LIBSYSTEMD_LIBS) \ + $(ZLIB_LIBS) + +if HAVE_JSON_C +named_LDADD += \ + $(JSON_C_LIBS) +endif HAVE_JSON_C + +if HAVE_LIBNGHTTP2 +named_LDADD += \ + $(LIBNGHTTP2_LIBS) +endif HAVE_LIBNGHTTP2 + +if HAVE_LIBXML2 +named_LDADD += \ + $(LIBXML2_LIBS) +endif HAVE_LIBXML2 diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in new file mode 100644 index 0000000..b4d9da4 --- /dev/null +++ b/bin/named/Makefile.in @@ -0,0 +1,975 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +@HAVE_JSON_C_TRUE@am__append_2 = \ +@HAVE_JSON_C_TRUE@ $(JSON_C_CFLAGS) + +@HAVE_LIBNGHTTP2_TRUE@am__append_3 = \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_CFLAGS) + +@HAVE_LIBXML2_TRUE@am__append_4 = \ +@HAVE_LIBXML2_TRUE@ $(LIBXML2_CFLAGS) + +sbin_PROGRAMS = named$(EXEEXT) +@HAVE_GEOIP2_TRUE@am__append_5 = \ +@HAVE_GEOIP2_TRUE@ -DMAXMINDDB_PREFIX=\"@MAXMINDDB_PREFIX@\" + +@HAVE_GEOIP2_TRUE@am__append_6 = \ +@HAVE_GEOIP2_TRUE@ geoip.c + +@HAVE_JSON_C_TRUE@am__append_7 = \ +@HAVE_JSON_C_TRUE@ $(JSON_C_LIBS) + +@HAVE_LIBNGHTTP2_TRUE@am__append_8 = \ +@HAVE_LIBNGHTTP2_TRUE@ $(LIBNGHTTP2_LIBS) + +@HAVE_LIBXML2_TRUE@am__append_9 = \ +@HAVE_LIBXML2_TRUE@ $(LIBXML2_LIBS) + +subdir = bin/named +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am__named_SOURCES_DIST = builtin.c config.c control.c controlconf.c \ + dlz_dlopen_driver.c fuzz.c log.c logconf.c main.c os.c \ + server.c statschannel.c tkeyconf.c transportconf.c tsigconf.c \ + zoneconf.c include/dlz/dlz_dlopen_driver.h \ + include/named/builtin.h include/named/config.h \ + include/named/control.h include/named/fuzz.h \ + include/named/geoip.h include/named/globals.h \ + include/named/log.h include/named/logconf.h \ + include/named/main.h include/named/os.h include/named/server.h \ + include/named/smf_globals.h include/named/statschannel.h \ + include/named/tkeyconf.h include/named/transportconf.h \ + include/named/tsigconf.h include/named/types.h \ + include/named/zoneconf.h xsl_p.h geoip.c +@HAVE_GEOIP2_TRUE@am__objects_1 = geoip.$(OBJEXT) +am_named_OBJECTS = builtin.$(OBJEXT) config.$(OBJEXT) \ + control.$(OBJEXT) controlconf.$(OBJEXT) \ + dlz_dlopen_driver.$(OBJEXT) fuzz.$(OBJEXT) log.$(OBJEXT) \ + logconf.$(OBJEXT) main.$(OBJEXT) os.$(OBJEXT) server.$(OBJEXT) \ + statschannel.$(OBJEXT) tkeyconf.$(OBJEXT) \ + transportconf.$(OBJEXT) tsigconf.$(OBJEXT) zoneconf.$(OBJEXT) \ + $(am__objects_1) +nodist_named_OBJECTS = xsl.$(OBJEXT) +named_OBJECTS = $(am_named_OBJECTS) $(nodist_named_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JSON_C_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +@HAVE_LIBNGHTTP2_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) +@HAVE_LIBXML2_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1) +named_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) \ + $(LIBNS_LIBS) $(LIBISCCC_LIBS) $(LIBISCCFG_LIBS) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4) \ + $(am__DEPENDENCIES_5) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/builtin.Po ./$(DEPDIR)/config.Po \ + ./$(DEPDIR)/control.Po ./$(DEPDIR)/controlconf.Po \ + ./$(DEPDIR)/dlz_dlopen_driver.Po ./$(DEPDIR)/fuzz.Po \ + ./$(DEPDIR)/geoip.Po ./$(DEPDIR)/log.Po ./$(DEPDIR)/logconf.Po \ + ./$(DEPDIR)/main.Po ./$(DEPDIR)/os.Po ./$(DEPDIR)/server.Po \ + ./$(DEPDIR)/statschannel.Po ./$(DEPDIR)/tkeyconf.Po \ + ./$(DEPDIR)/transportconf.Po ./$(DEPDIR)/tsigconf.Po \ + ./$(DEPDIR)/xsl.Po ./$(DEPDIR)/zoneconf.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(named_SOURCES) $(nodist_named_SOURCES) +DIST_SOURCES = $(am__named_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include -I$(top_builddir)/include $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) $(LIBNS_CFLAGS) $(LIBISCCC_CFLAGS) \ + $(LIBISCCFG_CFLAGS) $(OPENSSL_CFLAGS) $(LIBCAP_CFLAGS) \ + $(LMDB_CFLAGS) $(MAXMINDDB_CFLAGS) $(DNSTAP_CFLAGS) \ + $(LIBUV_CFLAGS) $(LIBSYSTEMD_CFLAGS) $(ZLIB_CFLAGS) \ + $(am__append_2) $(am__append_3) $(am__append_4) \ + -DNAMED_LOCALSTATEDIR=\"${localstatedir}\" \ + -DNAMED_SYSCONFDIR=\"${sysconfdir}\" $(am__append_5) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = xsl.c +CLEANFILES = xsl.c +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +nodist_named_SOURCES = xsl.c +EXTRA_DIST = bind9.xsl +named_SOURCES = builtin.c config.c control.c controlconf.c \ + dlz_dlopen_driver.c fuzz.c log.c logconf.c main.c os.c \ + server.c statschannel.c tkeyconf.c transportconf.c tsigconf.c \ + zoneconf.c include/dlz/dlz_dlopen_driver.h \ + include/named/builtin.h include/named/config.h \ + include/named/control.h include/named/fuzz.h \ + include/named/geoip.h include/named/globals.h \ + include/named/log.h include/named/logconf.h \ + include/named/main.h include/named/os.h include/named/server.h \ + include/named/smf_globals.h include/named/statschannel.h \ + include/named/tkeyconf.h include/named/transportconf.h \ + include/named/tsigconf.h include/named/types.h \ + include/named/zoneconf.h xsl_p.h $(am__append_6) +named_LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBNS_LIBS) \ + $(LIBISCCC_LIBS) $(LIBISCCFG_LIBS) $(OPENSSL_LIBS) \ + $(LIBCAP_LIBS) $(LMDB_LIBS) $(MAXMINDDB_LIBS) $(DNSTAP_LIBS) \ + $(LIBUV_LIBS) $(LIBSYSTEMD_LIBS) $(ZLIB_LIBS) $(am__append_7) \ + $(am__append_8) $(am__append_9) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/named/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/named/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +named$(EXEEXT): $(named_OBJECTS) $(named_DEPENDENCIES) $(EXTRA_named_DEPENDENCIES) + @rm -f named$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(named_OBJECTS) $(named_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtin.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/control.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/controlconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlz_dlopen_driver.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geoip.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statschannel.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tkeyconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transportconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsigconf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoneconf.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/builtin.Po + -rm -f ./$(DEPDIR)/config.Po + -rm -f ./$(DEPDIR)/control.Po + -rm -f ./$(DEPDIR)/controlconf.Po + -rm -f ./$(DEPDIR)/dlz_dlopen_driver.Po + -rm -f ./$(DEPDIR)/fuzz.Po + -rm -f ./$(DEPDIR)/geoip.Po + -rm -f ./$(DEPDIR)/log.Po + -rm -f ./$(DEPDIR)/logconf.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/os.Po + -rm -f ./$(DEPDIR)/server.Po + -rm -f ./$(DEPDIR)/statschannel.Po + -rm -f ./$(DEPDIR)/tkeyconf.Po + -rm -f ./$(DEPDIR)/transportconf.Po + -rm -f ./$(DEPDIR)/tsigconf.Po + -rm -f ./$(DEPDIR)/xsl.Po + -rm -f ./$(DEPDIR)/zoneconf.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/builtin.Po + -rm -f ./$(DEPDIR)/config.Po + -rm -f ./$(DEPDIR)/control.Po + -rm -f ./$(DEPDIR)/controlconf.Po + -rm -f ./$(DEPDIR)/dlz_dlopen_driver.Po + -rm -f ./$(DEPDIR)/fuzz.Po + -rm -f ./$(DEPDIR)/geoip.Po + -rm -f ./$(DEPDIR)/log.Po + -rm -f ./$(DEPDIR)/logconf.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/os.Po + -rm -f ./$(DEPDIR)/server.Po + -rm -f ./$(DEPDIR)/statschannel.Po + -rm -f ./$(DEPDIR)/tkeyconf.Po + -rm -f ./$(DEPDIR)/transportconf.Po + -rm -f ./$(DEPDIR)/tsigconf.Po + -rm -f ./$(DEPDIR)/xsl.Po + -rm -f ./$(DEPDIR)/zoneconf.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-sbinPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir doc-am doc-local dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-sbinPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +xsl.c: bind9.xsl Makefile + (echo 'const char xslmsg[] =' && \ + $(SED) -e 's,\",\\\",g' \ + -e 's,^,\",' \ + -e 's,$$,\\n\",' && \ + echo ";") \ + < "${srcdir}/bind9.xsl" > $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl new file mode 100644 index 0000000..ae1820d --- /dev/null +++ b/bin/named/bind9.xsl @@ -0,0 +1,1043 @@ + + + + + + + + + + + + + + + + + + + ISC BIND 9 Statistics + + +
+

ISC Bind 9 Configuration and Statistics

+
+

Alternate statistics views: All, + Status, + Server, + Zones, + Incoming Zone Transfers, + Network, + Memory and + Traffic Size

+
+

Server Status

+ + + + + + + + + + + + + + + + + +
Boot time: + +
Last reconfigured: + +
Current time: + +
Server version: + +
+
+ + +

Incoming Requests by DNS Opcode

+ +
+ [cannot display chart] +
+
+ + + + + + even + odd + + + + + + + + + + + +
+ + + +
Total: + +
+
+
+ + + +

Incoming Queries by Query Type

+
+ [cannot display chart] +
+
+ + + + + + even + odd + + + + + + + + + + + +
+ + + +
Total: + +
+
+
+ +

Outgoing Queries per view

+ +

View

+ + + + + + +
[no data to display]
+
+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+
+ +

Server Statistics

+ + + +
[no data to display]
+
+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+ + +

Zone Maintenance Statistics

+ + +
[no data to display]
+
+ + + + + + even + odd + + + + + + + +
+ + + +
+
+ +

Resolver Statistics (Common)

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+ + +

Resolver Statistics for View

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+ + +

ADB Statistics for View

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+ + +

Cache Statistics for View

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+ + +

Cache DB RRsets for View

+ + + + + even + odd + + + + + + + +
+ + + +
+
+
+
+ +

Traffic Size Statistics

+
+ +

UDP Requests Received

+ + + + + even + odd + + + + + + + + +
+ + + +
+
+
+ +

UDP Responses Sent

+ + + + + even + odd + + + + + + + + +
+ + + +
+
+
+ +

TCP Requests Received

+ + + + + even + odd + + + + + + + + +
+ + + +
+
+
+ +

TCP Responses Sent

+ + + + + even + odd + + + + + + + + +
+ + + +
+
+
+ +

Socket I/O Statistics

+ + + + + even + odd + + + + + + + +
+ + + +
+
+
+ + +

Zones for View

+ + + + + + + even + odd + + + + + + + + + + + + +
NameClassTypeSerialLoadedExpiresRefresh
+
+
+ +

Received QTYPES per view/zone

+ +

View

+ + + + + +

Zone

+ + + + + + +
[no data to display]
+
+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+
+
+ +

Response Codes per view/zone

+ +

View

+ + + + + +

Zone

+ + + + + + +
[no data to display]
+
+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+
+
+ +

Glue cache statistics

+ +

View

+ + + + + +

Zone

+ + + + + + even + odd + + + + + + + +
+ + + +
+
+
+
+
+ + +

Incoming Zone Transfers for View

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + even + odd + + + + + + + + + + + + + + + + + + + + + + + + +
Zone NameZone TypeLocal SerialRemote SerialIXFRFirst RefreshStateAdditional Refresh QueuedLocal AddressRemote AddressSOA TransportTransportTSIG Key NameDuration (s)Messages ReceivedRecords ReceivedBytes ReceivedTransfer Rate (B/s)
+
+
+ +

Memory Usage Summary

+ + + + + even + odd + + + + + + + +
+ + + +
+
+
+ +

Memory Contexts

+ + + + + + + + + + + + + + + even + odd + + + + + + + + + + + + +
IDNameReferencesInUsePoolsHiWaterLoWater
+ + + + + + + + + + + + + +
+
+
+ + + + + diff --git a/bin/named/builtin.c b/bin/named/builtin.c new file mode 100644 index 0000000..f8f6536 --- /dev/null +++ b/bin/named/builtin.c @@ -0,0 +1,1293 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file + * \brief + * The built-in "version", "hostname", "id", "authors" and "empty" databases. + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BDBNODE_MAGIC ISC_MAGIC('B', 'D', 'B', 'N') +#define VALID_BDBNODE(bdbl) ISC_MAGIC_VALID(bdbl, BDBNODE_MAGIC) + +/*% + * Note that "impmagic" is not the first four bytes of the struct, so + * ISC_MAGIC_VALID cannot be used here. + */ +#define BDB_MAGIC ISC_MAGIC('B', 'D', 'B', '-') +#define VALID_BDB(bdb) ((bdb) != NULL && (bdb)->common.impmagic == BDB_MAGIC) + +#define BDB_DNS64 0x00000001U + +typedef struct bdbimplementation { + unsigned int flags; + dns_dbimplementation_t *dbimp; +} bdbimplementation_t; + +typedef struct bdbnode bdbnode_t; +typedef struct bdb { + dns_db_t common; + bdbimplementation_t *implementation; + isc_result_t (*lookup)(bdbnode_t *node); + char *server; + char *contact; +} bdb_t; + +struct bdbnode { + unsigned int magic; + isc_refcount_t references; + bdb_t *bdb; + ISC_LIST(dns_rdatalist_t) lists; + ISC_LIST(isc_buffer_t) buffers; + dns_name_t *name; + ISC_LINK(bdbnode_t) link; + dns_rdatacallbacks_t callbacks; +}; + +typedef struct bdb_rdatasetiter { + dns_rdatasetiter_t common; + dns_rdatalist_t *current; +} bdb_rdatasetiter_t; + +static isc_result_t +findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG); + +static void +attachnode(dns_db_t *db, dns_dbnode_t *source, + dns_dbnode_t **targetp DNS__DB_FLARG); + +static void +detachnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG); + +/* + * Helper functions to convert text to wire forma. + */ +static isc_result_t +putrdata(bdbnode_t *node, dns_rdatatype_t typeval, dns_ttl_t ttl, + const unsigned char *rdatap, unsigned int rdlen) { + dns_rdatalist_t *rdatalist = NULL; + dns_rdata_t *rdata = NULL; + isc_buffer_t *rdatabuf = NULL; + isc_mem_t *mctx = NULL; + isc_region_t region; + + mctx = node->bdb->common.mctx; + + rdatalist = ISC_LIST_HEAD(node->lists); + while (rdatalist != NULL) { + if (rdatalist->type == typeval) { + break; + } + rdatalist = ISC_LIST_NEXT(rdatalist, link); + } + + if (rdatalist == NULL) { + rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); + dns_rdatalist_init(rdatalist); + rdatalist->rdclass = node->bdb->common.rdclass; + rdatalist->type = typeval; + rdatalist->ttl = ttl; + ISC_LIST_APPEND(node->lists, rdatalist, link); + } else if (rdatalist->ttl != ttl) { + return DNS_R_BADTTL; + } + + rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); + + isc_buffer_allocate(mctx, &rdatabuf, rdlen); + region.base = UNCONST(rdatap); + region.length = rdlen; + isc_buffer_copyregion(rdatabuf, ®ion); + isc_buffer_usedregion(rdatabuf, ®ion); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type, + ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + ISC_LIST_APPEND(node->buffers, rdatabuf, link); + + return ISC_R_SUCCESS; +} + +static isc_result_t +putrr(bdbnode_t *node, const char *type, dns_ttl_t ttl, const char *data) { + isc_result_t result; + dns_rdatatype_t typeval; + isc_lex_t *lex = NULL; + isc_mem_t *mctx = NULL; + const dns_name_t *origin = NULL; + isc_buffer_t *rb = NULL; + isc_buffer_t b; + + REQUIRE(VALID_BDBNODE(node)); + REQUIRE(type != NULL); + REQUIRE(data != NULL); + + mctx = node->bdb->common.mctx; + origin = &node->bdb->common.origin; + + isc_constregion_t r = { .base = type, .length = strlen(type) }; + result = dns_rdatatype_fromtext(&typeval, (isc_textregion_t *)&r); + if (result != ISC_R_SUCCESS) { + return result; + } + + isc_lex_create(mctx, 64, &lex); + + size_t datalen = strlen(data); + isc_buffer_constinit(&b, data, datalen); + isc_buffer_add(&b, datalen); + + result = isc_lex_openbuffer(lex, &b); + if (result != ISC_R_SUCCESS) { + return result; + } + + isc_buffer_allocate(mctx, &rb, DNS_RDATA_MAXLENGTH); + result = dns_rdata_fromtext(NULL, node->bdb->common.rdclass, typeval, + lex, origin, 0, mctx, rb, &node->callbacks); + isc_lex_destroy(&lex); + + if (result == ISC_R_SUCCESS) { + result = putrdata(node, typeval, ttl, isc_buffer_base(rb), + isc_buffer_usedlength(rb)); + } + + isc_buffer_free(&rb); + + return result; +} + +/* Reasonable default SOA values */ +#define DEFAULT_REFRESH 28800U /* 8 hours */ +#define DEFAULT_RETRY 7200U /* 2 hours */ +#define DEFAULT_EXPIRE 604800U /* 7 days */ +#define DEFAULT_MINIMUM 86400U /* 1 day */ +#define DEFAULT_TTL (60 * 60 * 24) + +static isc_result_t +putsoa(bdbnode_t *node, const char *mname, const char *rname, uint32_t serial) { + char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; + int n; + + REQUIRE(mname != NULL); + REQUIRE(rname != NULL); + + n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname, + serial, DEFAULT_REFRESH, DEFAULT_RETRY, DEFAULT_EXPIRE, + DEFAULT_MINIMUM); + if (n >= (int)sizeof(str) || n < 0) { + return ISC_R_NOSPACE; + } + return putrr(node, "SOA", DEFAULT_TTL, str); +} + +static isc_result_t +puttxt(bdbnode_t *node, const char *text) { + unsigned char buf[256]; + unsigned int len = strlen(text); + + if (len > 255) { + len = 255; /* Silently truncate */ + } + buf[0] = len; + memmove(&buf[1], text, len); + return putrdata(node, dns_rdatatype_txt, 0, buf, len + 1); +} + +/* + * Builtin database implementation functions. + */ + +/* Precomputed HEX * 16 or 1 table. */ +static const unsigned char hex16[256] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*00*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*10*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*20*/ + 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 1, 1, 1, 1, 1, 1, /*30*/ + 1, 160, 176, 192, 208, 224, 240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*50*/ + 1, 160, 176, 192, 208, 224, 240, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*60*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*70*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*A0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*B0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*C0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*D0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*E0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /*F0*/ +}; + +static const unsigned char decimal[] = "0123456789"; +static const unsigned char ipv4only[] = "\010ipv4only\004arpa"; + +static size_t +dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) { + size_t i, j = 0; + + for (i = 0; i < 4U; i++) { + unsigned char c = v[start++]; + if (start == 7U) { + start++; + } + if (c > 99) { + rdata[j++] = 3; + rdata[j++] = decimal[c / 100]; + c = c % 100; + rdata[j++] = decimal[c / 10]; + c = c % 10; + rdata[j++] = decimal[c]; + } else if (c > 9) { + rdata[j++] = 2; + rdata[j++] = decimal[c / 10]; + c = c % 10; + rdata[j++] = decimal[c]; + } else { + rdata[j++] = 1; + rdata[j++] = decimal[c]; + } + } + memmove(&rdata[j], "\07in-addr\04arpa", 14); + return j + 14; +} + +static isc_result_t +dns64_cname(const dns_name_t *zone, const dns_name_t *name, bdbnode_t *node) { + size_t zlen, nlen, j, len; + unsigned char v[16], n; + unsigned int i; + unsigned char rdata[sizeof("123.123.123.123.in-addr.arpa.")]; + unsigned char *ndata; + + /* + * The combined length of the zone and name is 74. + * + * The minimum zone length is 10 ((3)ip6(4)arpa(0)). + * + * The length of name should always be even as we are expecting + * a series of nibbles. + */ + zlen = zone->length; + nlen = name->length; + if ((zlen + nlen) > 74U || zlen < 10U || (nlen % 2) != 0U) { + return ISC_R_NOTFOUND; + } + + /* + * Check that name is a series of nibbles. + * Compute the byte values that correspond to the nibbles as we go. + * + * Shift the final result 4 bits, by setting 'i' to 1, if we if we + * have a odd number of nibbles so that "must be zero" tests below + * are byte aligned and we correctly return ISC_R_NOTFOUND or + * ISC_R_SUCCESS. We will not generate a CNAME in this case. + */ + ndata = name->ndata; + i = (nlen % 4) == 2U ? 1 : 0; + j = nlen; + memset(v, 0, sizeof(v)); + while (j != 0U) { + INSIST((i / 2) < sizeof(v)); + if (ndata[0] != 1) { + return ISC_R_NOTFOUND; + } + n = hex16[ndata[1] & 0xff]; + if (n == 1) { + return ISC_R_NOTFOUND; + } + v[i / 2] = n | (v[i / 2] >> 4); + j -= 2; + ndata += 2; + i++; + } + + /* + * If we get here then we know name only consisted of nibbles. + * Now we need to determine if the name exists or not and whether + * it corresponds to a empty node in the zone or there should be + * a CNAME. + */ +#define ZLEN(x) (10 + (x) / 2) + switch (zlen) { + case ZLEN(32): /* prefix len 32 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 16U && v[(nlen - 1) / 4 - 4] != 0) { + return ISC_R_NOTFOUND; + } + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 8, rdata); + break; + case ZLEN(40): /* prefix len 40 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 12U && v[(nlen - 1) / 4 - 3] != 0) { + return ISC_R_NOTFOUND; + } + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 6, rdata); + break; + case ZLEN(48): /* prefix len 48 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 8U && v[(nlen - 1) / 4 - 2] != 0) { + return ISC_R_NOTFOUND; + } + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 5, rdata); + break; + case ZLEN(56): /* prefix len 56 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (nlen > 4U && v[(nlen - 1) / 4 - 1] != 0) { + return ISC_R_NOTFOUND; + } + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 4, rdata); + break; + case ZLEN(64): /* prefix len 64 */ + /* + * The nibbles that map to this byte must be zero for 'name' + * to exist in the zone. + */ + if (v[(nlen - 1) / 4] != 0) { + return ISC_R_NOTFOUND; + } + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 3, rdata); + break; + case ZLEN(96): /* prefix len 96 */ + /* + * If the total length is not 74 then this is a empty node + * so return success. + */ + if (nlen + zlen != 74U) { + return ISC_R_SUCCESS; + } + len = dns64_rdata(v, 0, rdata); + break; + default: + /* + * This should never be reached unless someone adds a + * zone declaration with this internal type to named.conf. + */ + return ISC_R_NOTFOUND; + } + + /* + * Reverse of 192.0.0.170 or 192.0.0.171 maps to ipv4only.arpa. + */ + if ((v[0] == 170 || v[0] == 171) && v[1] == 0 && v[2] == 0 && + v[3] == 192) + { + return putrdata(node, dns_rdatatype_ptr, 3600, ipv4only, + sizeof(ipv4only)); + } + + return putrdata(node, dns_rdatatype_cname, 600, rdata, + (unsigned int)len); +} + +static isc_result_t +builtin_lookup(bdb_t *bdb, const dns_name_t *name, bdbnode_t *node) { + if (name->labels == 0 && name->length == 0) { + return bdb->lookup(node); + } else if ((node->bdb->implementation->flags & BDB_DNS64) != 0) { + return dns64_cname(&bdb->common.origin, name, node); + } else { + return ISC_R_NOTFOUND; + } +} + +static isc_result_t +builtin_authority(bdb_t *bdb, bdbnode_t *node) { + isc_result_t result; + const char *contact = "hostmaster"; + const char *server = "@"; + + if (bdb->server != NULL) { + server = bdb->server; + } + if (bdb->contact != NULL) { + contact = bdb->contact; + } + + result = putsoa(node, server, contact, 0); + if (result != ISC_R_SUCCESS) { + return ISC_R_FAILURE; + } + + result = putrr(node, "NS", 0, server); + if (result != ISC_R_SUCCESS) { + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +version_lookup(bdbnode_t *node) { + if (named_g_server->version_set) { + if (named_g_server->version == NULL) { + return ISC_R_SUCCESS; + } else { + return puttxt(node, named_g_server->version); + } + } else { + return puttxt(node, PACKAGE_VERSION); + } +} + +static isc_result_t +hostname_lookup(bdbnode_t *node) { + if (named_g_server->hostname_set) { + if (named_g_server->hostname == NULL) { + return ISC_R_SUCCESS; + } else { + return puttxt(node, named_g_server->hostname); + } + } else { + char buf[256]; + if (gethostname(buf, sizeof(buf)) != 0) { + return ISC_R_FAILURE; + } + return puttxt(node, buf); + } +} + +static isc_result_t +authors_lookup(bdbnode_t *node) { + isc_result_t result; + const char **p = NULL; + static const char *authors[] = { + "Mark Andrews", "Curtis Blackburn", + "James Brister", "Ben Cottrell", + "John H. DuBois III", "Francis Dupont", + "Michael Graff", "Andreas Gustafsson", + "Bob Halley", "Evan Hunt", + "JINMEI Tatuya", "Witold Krecicki", + "David Lawrence", "Scott Mann", + "Danny Mayer", "Aydin Mercan", + "Damien Neil", "Matt Nelson", + "Jeremy C. Reed", "Michael Sawyer", + "Brian Wellington", NULL + }; + + /* + * If a version string is specified, disable the authors.bind zone. + */ + if (named_g_server->version_set) { + return ISC_R_SUCCESS; + } + + for (p = authors; *p != NULL; p++) { + result = puttxt(node, *p); + if (result != ISC_R_SUCCESS) { + return result; + } + } + return ISC_R_SUCCESS; +} + +static isc_result_t +id_lookup(bdbnode_t *node) { + if (named_g_server->sctx->usehostname) { + char buf[256]; + if (gethostname(buf, sizeof(buf)) != 0) { + return ISC_R_FAILURE; + } + return puttxt(node, buf); + } else if (named_g_server->sctx->server_id != NULL) { + return puttxt(node, named_g_server->sctx->server_id); + } else { + return ISC_R_SUCCESS; + } +} + +static isc_result_t +empty_lookup(bdbnode_t *node) { + UNUSED(node); + + return ISC_R_SUCCESS; +} + +static isc_result_t +ipv4only_lookup(bdbnode_t *node) { + isc_result_t result; + unsigned char data[2][4] = { { 192, 0, 0, 170 }, { 192, 0, 0, 171 } }; + + for (int i = 0; i < 2; i++) { + result = putrdata(node, dns_rdatatype_a, 3600, data[i], 4); + if (result != ISC_R_SUCCESS) { + return result; + } + } + return ISC_R_SUCCESS; +} + +static isc_result_t +ipv4reverse_lookup(bdbnode_t *node) { + isc_result_t result; + + result = putrdata(node, dns_rdatatype_ptr, 3600, ipv4only, + sizeof(ipv4only)); + return result; +} + +/* + * Rdataset implementation methods. An rdataset in the builtin databases is + * implemented as an rdatalist which holds a reference to the dbnode, + * to prevent the node being freed while the rdataset is still in use, so + * we need local implementations of clone and disassociate but the rest of + * the implementation can be the same as dns_rdatalist.. + */ +static void +disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) { + dns_dbnode_t *node = rdataset->rdlist.node; + bdbnode_t *bdbnode = (bdbnode_t *)node; + dns_db_t *db = (dns_db_t *)bdbnode->bdb; + + detachnode(db, &node DNS__DB_FLARG_PASS); + dns_rdatalist_disassociate(rdataset DNS__DB_FLARG_PASS); +} + +static void +rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) { + dns_dbnode_t *node = source->rdlist.node; + bdbnode_t *bdbnode = (bdbnode_t *)node; + dns_db_t *db = (dns_db_t *)bdbnode->bdb; + + dns_rdatalist_clone(source, target DNS__DB_FLARG_PASS); + attachnode(db, node, &target->rdlist.node DNS__DB_FLARG_PASS); +} + +static dns_rdatasetmethods_t bdb_rdataset_methods = { + .disassociate = disassociate, + .first = dns_rdatalist_first, + .next = dns_rdatalist_next, + .current = dns_rdatalist_current, + .clone = rdataset_clone, + .count = dns_rdatalist_count, + .addnoqname = dns_rdatalist_addnoqname, + .getnoqname = dns_rdatalist_getnoqname, +}; + +static void +new_rdataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, + dns_rdataset_t *rdataset) { + dns_rdatalist_tordataset(rdatalist, rdataset); + + rdataset->methods = &bdb_rdataset_methods; + dns_db_attachnode(db, node, &rdataset->rdlist.node); +} + +/* + * Rdataset iterator methods + */ + +static void +rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { + bdb_rdatasetiter_t *bdbiterator = (bdb_rdatasetiter_t *)(*iteratorp); + detachnode(bdbiterator->common.db, + &bdbiterator->common.node DNS__DB_FLARG_PASS); + isc_mem_put(bdbiterator->common.db->mctx, bdbiterator, + sizeof(bdb_rdatasetiter_t)); + *iteratorp = NULL; +} + +static isc_result_t +rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { + bdb_rdatasetiter_t *bdbiterator = (bdb_rdatasetiter_t *)iterator; + bdbnode_t *bdbnode = (bdbnode_t *)iterator->node; + + if (ISC_LIST_EMPTY(bdbnode->lists)) { + return ISC_R_NOMORE; + } + bdbiterator->current = ISC_LIST_HEAD(bdbnode->lists); + return ISC_R_SUCCESS; +} + +static isc_result_t +rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { + bdb_rdatasetiter_t *bdbiterator = (bdb_rdatasetiter_t *)iterator; + + bdbiterator->current = ISC_LIST_NEXT(bdbiterator->current, link); + if (bdbiterator->current == NULL) { + return ISC_R_NOMORE; + } else { + return ISC_R_SUCCESS; + } +} + +static void +rdatasetiter_current(dns_rdatasetiter_t *iterator, + dns_rdataset_t *rdataset DNS__DB_FLARG) { + bdb_rdatasetiter_t *bdbiterator = (bdb_rdatasetiter_t *)iterator; + + new_rdataset(bdbiterator->current, iterator->db, iterator->node, + rdataset); +} + +static dns_rdatasetitermethods_t rdatasetiter_methods = { + rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, + rdatasetiter_current +}; + +/* + * Database implementation methods + */ +static void +destroy(dns_db_t *db) { + bdb_t *bdb = (bdb_t *)db; + isc_refcount_destroy(&bdb->common.references); + + if (bdb->server != NULL) { + isc_mem_free(named_g_mctx, bdb->server); + } + if (bdb->contact != NULL) { + isc_mem_free(named_g_mctx, bdb->contact); + } + + bdb->common.magic = 0; + bdb->common.impmagic = 0; + + dns_name_free(&bdb->common.origin, bdb->common.mctx); + + isc_mem_putanddetach(&bdb->common.mctx, bdb, sizeof(bdb_t)); +} + +/* + * A dummy 'version' value is used so that dns_db_createversion() + * can return a non-NULL version to the caller, but there can only be + * one version of these databases, so the version value is never used. + */ +static int dummy; + +static void +currentversion(dns_db_t *db, dns_dbversion_t **versionp) { + bdb_t *bdb = (bdb_t *)db; + + REQUIRE(VALID_BDB(bdb)); + + *versionp = (void *)&dummy; + return; +} + +static void +attachversion(dns_db_t *db, dns_dbversion_t *source, + dns_dbversion_t **targetp) { + bdb_t *bdb = (bdb_t *)db; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(source != NULL && source == (void *)&dummy); + REQUIRE(targetp != NULL && *targetp == NULL); + + *targetp = source; + return; +} + +static void +closeversion(dns_db_t *db, dns_dbversion_t **versionp, + bool commit DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(versionp != NULL && *versionp == (void *)&dummy); + REQUIRE(!commit); + + *versionp = NULL; +} + +static isc_result_t +createnode(bdb_t *bdb, bdbnode_t **nodep) { + bdbnode_t *node = NULL; + + REQUIRE(VALID_BDB(bdb)); + + node = isc_mem_get(bdb->common.mctx, sizeof(bdbnode_t)); + *node = (bdbnode_t){ + .lists = ISC_LIST_INITIALIZER, + .buffers = ISC_LIST_INITIALIZER, + .link = ISC_LINK_INITIALIZER, + }; + + dns_db_attach((dns_db_t *)bdb, (dns_db_t **)&node->bdb); + dns_rdatacallbacks_init(&node->callbacks); + + isc_refcount_init(&node->references, 1); + node->magic = BDBNODE_MAGIC; + + *nodep = node; + return ISC_R_SUCCESS; +} + +static void +destroynode(bdbnode_t *node) { + dns_rdatalist_t *list = NULL; + dns_rdata_t *rdata = NULL; + isc_buffer_t *b = NULL; + bdb_t *bdb = NULL; + isc_mem_t *mctx = NULL; + + bdb = node->bdb; + mctx = bdb->common.mctx; + + while (!ISC_LIST_EMPTY(node->lists)) { + list = ISC_LIST_HEAD(node->lists); + while (!ISC_LIST_EMPTY(list->rdata)) { + rdata = ISC_LIST_HEAD(list->rdata); + ISC_LIST_UNLINK(list->rdata, rdata, link); + isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); + } + ISC_LIST_UNLINK(node->lists, list, link); + isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); + } + + while (!ISC_LIST_EMPTY(node->buffers)) { + b = ISC_LIST_HEAD(node->buffers); + ISC_LIST_UNLINK(node->buffers, b, link); + isc_buffer_free(&b); + } + + if (node->name != NULL) { + dns_name_free(node->name, mctx); + isc_mem_put(mctx, node->name, sizeof(dns_name_t)); + } + + node->magic = 0; + isc_mem_put(mctx, node, sizeof(bdbnode_t)); + dns_db_detach((dns_db_t **)(void *)&bdb); +} + +static isc_result_t +getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + bdbnode_t *node = NULL; + isc_result_t result; + dns_name_t relname; + dns_name_t *name = NULL; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(nodep != NULL && *nodep == NULL); + + dns_name_init(&relname, NULL); + name = &relname; + + result = createnode(bdb, &node); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = builtin_lookup(bdb, name, node); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + destroynode(node); + return result; + } + + result = builtin_authority(bdb, node); + if (result != ISC_R_SUCCESS) { + destroynode(node); + return result; + } + + *nodep = node; + return ISC_R_SUCCESS; +} + +static isc_result_t +findnode(dns_db_t *db, const dns_name_t *name, bool create, + dns_dbnode_t **nodep DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + bdbnode_t *node = NULL; + isc_result_t result; + bool isorigin; + dns_name_t relname; + unsigned int labels; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(nodep != NULL && *nodep == NULL); + + UNUSED(create); + + isorigin = dns_name_equal(name, &bdb->common.origin); + + labels = dns_name_countlabels(name) - dns_name_countlabels(&db->origin); + dns_name_init(&relname, NULL); + dns_name_getlabelsequence(name, 0, labels, &relname); + name = &relname; + + result = createnode(bdb, &node); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = builtin_lookup(bdb, name, node); + if (result != ISC_R_SUCCESS && (!isorigin || result != ISC_R_NOTFOUND)) + { + destroynode(node); + return result; + } + + if (isorigin) { + result = builtin_authority(bdb, node); + if (result != ISC_R_SUCCESS) { + destroynode(node); + return result; + } + } + + *nodep = node; + return ISC_R_SUCCESS; +} + +static isc_result_t +find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_fixedname_t fname; + dns_rdataset_t xrdataset; + dns_name_t *xname = NULL; + unsigned int nlabels, olabels, i; + bool dns64; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(nodep == NULL || *nodep == NULL); + REQUIRE(version == NULL || version == (void *)&dummy); + + if (!dns_name_issubdomain(name, &db->origin)) { + return DNS_R_NXDOMAIN; + } + + olabels = dns_name_countlabels(&db->origin); + nlabels = dns_name_countlabels(name); + + xname = dns_fixedname_initname(&fname); + + if (rdataset == NULL) { + dns_rdataset_init(&xrdataset); + rdataset = &xrdataset; + } + + result = DNS_R_NXDOMAIN; + dns64 = ((bdb->implementation->flags & BDB_DNS64) != 0); + for (i = (dns64 ? nlabels : olabels); i <= nlabels; i++) { + /* + * Look up the next label. + */ + dns_name_getlabelsequence(name, nlabels - i, i, xname); + result = findnode(db, xname, false, &node DNS__DB_FLARG_PASS); + if (result == ISC_R_NOTFOUND) { + /* + * No data at zone apex? + */ + if (i == olabels) { + return DNS_R_BADDB; + } + result = DNS_R_NXDOMAIN; + continue; + } + if (result != ISC_R_SUCCESS) { + return result; + } + + /* + * DNS64 zones don't have DNAME or NS records. + */ + if (dns64) { + goto skip; + } + + /* + * Look for a DNAME at the current label, unless this is + * the qname. + */ + if (i < nlabels) { + result = findrdataset( + db, node, version, dns_rdatatype_dname, 0, now, + rdataset, sigrdataset DNS__DB_FLARG_PASS); + if (result == ISC_R_SUCCESS) { + result = DNS_R_DNAME; + break; + } + } + + /* + * Look for an NS at the current label, unless this is the + * origin or glue is ok. + */ + if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { + result = findrdataset( + db, node, version, dns_rdatatype_ns, 0, now, + rdataset, sigrdataset DNS__DB_FLARG_PASS); + if (result == ISC_R_SUCCESS) { + if (i == nlabels && type == dns_rdatatype_any) { + result = DNS_R_ZONECUT; + dns_rdataset_disassociate(rdataset); + if (sigrdataset != NULL && + dns_rdataset_isassociated( + sigrdataset)) + { + dns_rdataset_disassociate( + sigrdataset); + } + } else { + result = DNS_R_DELEGATION; + } + break; + } + } + + /* + * If the current name is not the qname, add another label + * and try again. + */ + if (i < nlabels) { + destroynode(node); + node = NULL; + continue; + } + + skip: + /* + * If we're looking for ANY, we're done. + */ + if (type == dns_rdatatype_any) { + result = ISC_R_SUCCESS; + break; + } + + /* + * Look for the qtype. + */ + result = findrdataset(db, node, version, type, 0, now, rdataset, + sigrdataset DNS__DB_FLARG_PASS); + if (result == ISC_R_SUCCESS) { + break; + } + + /* + * Look for a CNAME. + */ + if (type != dns_rdatatype_cname) { + result = findrdataset( + db, node, version, dns_rdatatype_cname, 0, now, + rdataset, sigrdataset DNS__DB_FLARG_PASS); + if (result == ISC_R_SUCCESS) { + result = DNS_R_CNAME; + break; + } + } + + result = DNS_R_NXRRSET; + break; + } + + if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) { + dns_rdataset_disassociate(rdataset); + } + + if (foundname != NULL) { + dns_name_copy(xname, foundname); + } + + if (nodep != NULL) { + *nodep = node; + } else if (node != NULL) { + detachnode(db, &node DNS__DB_FLARG_PASS); + } + + return result; +} + +static void +attachnode(dns_db_t *db, dns_dbnode_t *source, + dns_dbnode_t **targetp DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + bdbnode_t *node = (bdbnode_t *)source; + + REQUIRE(VALID_BDB(bdb)); + + isc_refcount_increment(&node->references); + + *targetp = source; +} + +static void +detachnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { + bdb_t *bdb = (bdb_t *)db; + bdbnode_t *node = NULL; + + REQUIRE(VALID_BDB(bdb)); + REQUIRE(nodep != NULL && *nodep != NULL); + + node = (bdbnode_t *)(*nodep); + *nodep = NULL; + + if (isc_refcount_decrement(&node->references) == 1) { + destroynode(node); + } +} + +static isc_result_t +findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + bdbnode_t *bdbnode = (bdbnode_t *)node; + dns_rdatalist_t *list = NULL; + + REQUIRE(VALID_BDBNODE(bdbnode)); + + UNUSED(version); + UNUSED(covers); + UNUSED(now); + UNUSED(sigrdataset); + + if (type == dns_rdatatype_rrsig) { + return ISC_R_NOTIMPLEMENTED; + } + + list = ISC_LIST_HEAD(bdbnode->lists); + while (list != NULL) { + if (list->type == type) { + break; + } + list = ISC_LIST_NEXT(list, link); + } + if (list == NULL) { + return ISC_R_NOTFOUND; + } + + new_rdataset(list, db, node, rdataset); + + return ISC_R_SUCCESS; +} + +static isc_result_t +allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { + bdb_rdatasetiter_t *iterator = NULL; + + REQUIRE(version == NULL || version == &dummy); + + iterator = isc_mem_get(db->mctx, sizeof(bdb_rdatasetiter_t)); + *iterator = (bdb_rdatasetiter_t){ + .common.methods = &rdatasetiter_methods, + .common.db = db, + .common.version = version, + .common.options = options, + .common.now = now, + .common.magic = DNS_RDATASETITER_MAGIC, + }; + + attachnode(db, node, &iterator->common.node DNS__DB_FLARG_PASS); + + *iteratorp = (dns_rdatasetiter_t *)iterator; + + return ISC_R_SUCCESS; +} + +static dns_dbmethods_t bdb_methods = { + .destroy = destroy, + .currentversion = currentversion, + .attachversion = attachversion, + .closeversion = closeversion, + .attachnode = attachnode, + .detachnode = detachnode, + .findrdataset = findrdataset, + .allrdatasets = allrdatasets, + .getoriginnode = getoriginnode, + .findnode = findnode, + .find = find, +}; + +static isc_result_t +create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, + dns_rdataclass_t rdclass, unsigned int argc, char *argv[], + void *implementation, dns_db_t **dbp) { + isc_result_t result; + bool needargs = false; + bdb_t *bdb = NULL; + + REQUIRE(implementation != NULL); + + if (type != dns_dbtype_zone) { + return ISC_R_NOTIMPLEMENTED; + } + + bdb = isc_mem_get(mctx, sizeof(*bdb)); + *bdb = (bdb_t){ + .common = { .methods = &bdb_methods, .rdclass = rdclass }, + .implementation = implementation, + }; + + isc_refcount_init(&bdb->common.references, 1); + isc_mem_attach(mctx, &bdb->common.mctx); + dns_name_init(&bdb->common.origin, NULL); + dns_name_dupwithoffsets(origin, mctx, &bdb->common.origin); + + INSIST(argc >= 1); + if (strcmp(argv[0], "authors") == 0) { + bdb->lookup = authors_lookup; + } else if (strcmp(argv[0], "hostname") == 0) { + bdb->lookup = hostname_lookup; + } else if (strcmp(argv[0], "id") == 0) { + bdb->lookup = id_lookup; + } else if (strcmp(argv[0], "version") == 0) { + bdb->lookup = version_lookup; + } else if (strcmp(argv[0], "dns64") == 0) { + needargs = true; + bdb->lookup = empty_lookup; + } else if (strcmp(argv[0], "empty") == 0) { + needargs = true; + bdb->lookup = empty_lookup; + } else if (strcmp(argv[0], "ipv4only") == 0) { + needargs = true; + bdb->lookup = ipv4only_lookup; + } else { + needargs = true; + bdb->lookup = ipv4reverse_lookup; + } + + if (needargs) { + if (argc != 3) { + result = DNS_R_SYNTAX; + goto cleanup; + } + + bdb->server = isc_mem_strdup(named_g_mctx, argv[1]); + bdb->contact = isc_mem_strdup(named_g_mctx, argv[2]); + } else if (argc != 1) { + result = DNS_R_SYNTAX; + goto cleanup; + } + + bdb->common.magic = DNS_DB_MAGIC; + bdb->common.impmagic = BDB_MAGIC; + + *dbp = (dns_db_t *)bdb; + + return ISC_R_SUCCESS; + +cleanup: + dns_name_free(&bdb->common.origin, mctx); + if (bdb->server != NULL) { + isc_mem_free(named_g_mctx, bdb->server); + } + if (bdb->contact != NULL) { + isc_mem_free(named_g_mctx, bdb->contact); + } + + isc_mem_putanddetach(&bdb->common.mctx, bdb, sizeof(bdb_t)); + return result; +} + +/* + * Builtin database registration functions + */ +static bdbimplementation_t builtin = { .flags = 0 }; +static bdbimplementation_t dns64 = { .flags = BDB_DNS64 }; + +isc_result_t +named_builtin_init(void) { + isc_result_t result; + + result = dns_db_register("_builtin", create, &builtin, named_g_mctx, + &builtin.dbimp); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_db_register("_dns64", create, &dns64, named_g_mctx, + &dns64.dbimp); + if (result != ISC_R_SUCCESS) { + dns_db_unregister(&builtin.dbimp); + return result; + } + + return ISC_R_SUCCESS; +} + +void +named_builtin_deinit(void) { + if (builtin.dbimp != NULL) { + dns_db_unregister(&builtin.dbimp); + } + if (dns64.dbimp != NULL) { + dns_db_unregister(&dns64.dbimp); + } +} diff --git a/bin/named/config.c b/bin/named/config.c new file mode 100644 index 0000000..c72ca9f --- /dev/null +++ b/bin/named/config.c @@ -0,0 +1,956 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +/*% default configuration */ +static char defaultconf[] = "\ +options {\n\ + answer-cookie true;\n\ + automatic-interface-scan yes;\n\ +# blackhole {none;};\n\ + cookie-algorithm siphash24;\n\ +# directory \n\ + dnssec-policy \"none\";\n\ + dump-file \"named_dump.db\";\n\ + edns-udp-size 1232;\n" +#if defined(HAVE_GEOIP2) + "\ + geoip-directory \"" MAXMINDDB_PREFIX "/share/GeoIP\";\n" +#elif defined(HAVE_GEOIP2) + "\ + geoip-directory \".\";\n" +#endif /* if defined(HAVE_GEOIP2) */ + "\ + heartbeat-interval 60;\n\ + interface-interval 60;\n\ + listen-on {any;};\n\ + listen-on-v6 {any;};\n\ + match-mapped-addresses no;\n\ + max-ixfr-ratio 100%;\n\ + max-rsa-exponent-size 0; /* no limit */\n\ + max-udp-size 1232;\n\ + memstatistics-file \"named.memstats\";\n\ + nocookie-udp-size 4096;\n\ + notify-rate 20;\n\ + nta-lifetime 3600;\n\ + nta-recheck 300;\n\ +# pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\ + port 53;\n" +#if HAVE_SO_REUSEPORT_LB + "\ + reuseport yes;\n" +#else + "\ + reuseport no;\n" +#endif + "\ + tls-port 853;\n" +#if HAVE_LIBNGHTTP2 + "\ + http-port 80;\n\ + https-port 443;\n\ + http-listener-clients 300;\n\ + http-streams-per-connection 100;\n" +#endif + "\ + prefetch 2 9;\n\ +# querylog ;\n\ + recursing-file \"named.recursing\";\n\ + recursive-clients 1000;\n\ + request-nsid false;\n\ + resolver-query-timeout 10;\n\ +# responselog ;\n\ + rrset-order { order random; };\n\ + secroots-file \"named.secroots\";\n\ + send-cookie true;\n\ + serial-query-rate 20;\n\ + server-id none;\n\ + session-keyalg hmac-sha256;\n\ +# session-keyfile \"" NAMED_LOCALSTATEDIR "/run/named/session.key\";\n\ + session-keyname local-ddns;\n\ + startup-notify-rate 20;\n\ + sig0checks-quota 1;\n\ + sig0key-checks-limit 16;\n\ + sig0message-checks-limit 2;\n\ + statistics-file \"named.stats\";\n\ + tcp-advertised-timeout 300;\n\ + tcp-clients 150;\n\ + tcp-idle-timeout 300;\n\ + tcp-initial-timeout 300;\n\ + tcp-keepalive-timeout 300;\n\ + tcp-listen-queue 10;\n\ + tcp-receive-buffer 0;\n\ + tcp-send-buffer 0;\n\ +# tkey-domain \n\ +# tkey-gssapi-credential \n\ + transfer-message-size 20480;\n\ + transfers-in 10;\n\ + transfers-out 10;\n\ + transfers-per-ns 2;\n\ + trust-anchor-telemetry yes;\n\ + udp-receive-buffer 0;\n\ + udp-send-buffer 0;\n\ + update-quota 100;\n\ +\n\ + /* view */\n\ + allow-new-zones no;\n\ + allow-notify {none;};\n\ + allow-proxy {none;};\n\ + allow-proxy-on {any;};\n\ + allow-query-cache { localnets; localhost; };\n\ + allow-query-cache-on { any; };\n\ + allow-recursion { localnets; localhost; };\n\ + allow-recursion-on { any; };\n\ + allow-update-forwarding {none;};\n\ + auth-nxdomain false;\n\ + check-dup-records warn;\n\ + check-mx warn;\n\ + check-names primary fail;\n\ + check-names response ignore;\n\ + check-names secondary warn;\n\ + check-spf warn;\n\ + check-svcb yes;\n\ + clients-per-query 10;\n\ + dnssec-accept-expired no;\n\ + dnssec-validation " VALIDATION_DEFAULT "; \n" +#ifdef USE_DNSRPS + " dnsrps-library \"" DNSRPS_LIBRPZ_PATH "\";\n" +#endif /* ifdef USE_DNSRPS */ +#ifdef HAVE_DNSTAP + " dnstap-identity hostname;\n" +#endif /* ifdef HAVE_DNSTAP */ + "\ + fetch-quota-params 100 0.1 0.3 0.7;\n\ + fetches-per-server 0;\n\ + fetches-per-zone 0;\n\ + lame-ttl 0;\n" +#ifdef HAVE_LMDB + " lmdb-mapsize 32M;\n" +#endif /* ifdef HAVE_LMDB */ + " max-cache-size 90%;\n\ + max-cache-ttl 604800; /* 1 week */\n\ + max-clients-per-query 100;\n\ + max-ncache-ttl 10800; /* 3 hours */\n\ + max-recursion-depth 7;\n\ + max-recursion-queries 50;\n\ + max-query-count 200;\n\ + max-query-restarts 11;\n\ + max-stale-ttl 86400; /* 1 day */\n\ + message-compression yes;\n\ + min-ncache-ttl 0; /* 0 hours */\n\ + min-cache-ttl 0; /* 0 seconds */\n\ + minimal-any false;\n\ + minimal-responses no-auth-recursive;\n\ + notify-source *;\n\ + notify-source-v6 *;\n\ + nsec3-test-zone no;\n\ + parental-source *;\n\ + parental-source-v6 *;\n\ + provide-ixfr true;\n\ + qname-minimization relaxed;\n\ + query-source address *;\n\ + query-source-v6 address *;\n\ + recursion true;\n\ + request-expire true;\n\ + request-ixfr true;\n\ + require-server-cookie no;\n\ + root-key-sentinel yes;\n\ + servfail-ttl 1;\n\ +# sortlist \n\ + stale-answer-client-timeout off;\n\ + stale-answer-enable false;\n\ + stale-answer-ttl 30; /* 30 seconds */\n\ + stale-cache-enable false;\n\ + stale-refresh-time 30; /* 30 seconds */\n\ + synth-from-dnssec yes;\n\ +# topology \n\ + transfer-format many-answers;\n\ + resolver-use-dns64 false;\n\ + v6-bias 50;\n\ + zero-no-soa-ttl-cache no;\n\ +\n\ + /* zone */\n\ + allow-query {any;};\n\ + allow-query-on {any;};\n\ + allow-transfer {none;};\n\ +# also-notify \n\ + check-integrity yes;\n\ + check-mx-cname warn;\n\ + check-sibling yes;\n\ + check-srv-cname warn;\n\ + check-wildcard yes;\n\ + dialup no;\n\ + dnssec-loadkeys-interval 60;\n\ +# forward \n\ +# forwarders \n\ +# inline-signing no;\n\ + ixfr-from-differences false;\n\ + max-journal-size default;\n\ + max-records 0;\n\ + max-records-per-type 100;\n\ + max-refresh-time 2419200; /* 4 weeks */\n\ + max-retry-time 1209600; /* 2 weeks */\n\ + max-types-per-name 100;\n\ + max-transfer-idle-in 60;\n\ + max-transfer-idle-out 60;\n\ + max-transfer-time-in 120;\n\ + max-transfer-time-out 120;\n\ + min-refresh-time 300;\n\ + min-retry-time 500;\n\ + min-transfer-rate-in 10240 5;\n\ + multi-master no;\n\ + notify yes;\n\ + notify-delay 5;\n\ + notify-to-soa no;\n\ + serial-update-method increment;\n\ + sig-signing-nodes 100;\n\ + sig-signing-signatures 10;\n\ + sig-signing-type 65534;\n\ + transfer-source *;\n\ + transfer-source-v6 *;\n\ + try-tcp-refresh yes; /* BIND 8 compat */\n\ + zero-no-soa-ttl yes;\n\ + zone-statistics terse;\n\ +};\n\ +" + + "#\n\ +# Zones in the \"_bind\" view are NOT counted in the count of zones.\n\ +#\n\ +view \"_bind\" chaos {\n\ + recursion no;\n\ + notify no;\n\ + allow-new-zones no;\n\ + max-cache-size 2M;\n\ +\n\ + # Prevent use of this zone in DNS amplified reflection DoS attacks\n\ + rate-limit {\n\ + responses-per-second 3;\n\ + slip 0;\n\ + min-table-size 10;\n\ + };\n\ +\n\ + zone \"version.bind\" chaos {\n\ + type primary;\n\ + database \"_builtin version\";\n\ + };\n\ +\n\ + zone \"hostname.bind\" chaos {\n\ + type primary;\n\ + database \"_builtin hostname\";\n\ + };\n\ +\n\ + zone \"authors.bind\" chaos {\n\ + type primary;\n\ + database \"_builtin authors\";\n\ + };\n\ +\n\ + zone \"id.server\" chaos {\n\ + type primary;\n\ + database \"_builtin id\";\n\ + };\n\ +};\n\ +" + "#\n\ +# Built-in DNSSEC key and signing policies.\n\ +#\n\ +dnssec-policy \"default\" {\n\ + keys {\n\ + csk key-directory lifetime unlimited algorithm 13;\n\ + };\n\ +\n\ + cdnskey yes;\n\ + cds-digest-types { 2; };\n\ + dnskey-ttl " DNS_KASP_KEY_TTL ";\n\ + inline-signing yes;\n\ + offline-ksk no;\n\ + publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\ + retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\ + purge-keys " DNS_KASP_PURGE_KEYS "; \n\ + signatures-jitter " DNS_KASP_SIG_JITTER "; \n\ + signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\ + signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\ + signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\ + max-zone-ttl " DNS_KASP_ZONE_MAXTTL "; \n\ + zone-propagation-delay " DNS_KASP_ZONE_PROPDELAY "; \n\ + parent-ds-ttl " DNS_KASP_DS_TTL "; \n\ + parent-propagation-delay " DNS_KASP_PARENT_PROPDELAY "; \n\ +};\n\ +\n\ +dnssec-policy \"insecure\" {\n\ + max-zone-ttl 0; \n\ + keys { };\n\ + inline-signing yes;\n\ +};\n\ +\n\ +" + "#\n\ +# Default trusted key(s), used if \n\ +# \"dnssec-validation auto;\" is set and\n\ +# " NAMED_SYSCONFDIR "/bind.keys doesn't exist).\n\ +#\n\ +# BEGIN TRUST ANCHORS\n" + + /* Imported from bind.keys.h: */ + TRUST_ANCHORS + + "# END TRUST ANCHORS\n\ +\n\ +remote-servers " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\ + 2801:1b8:10::b; # b.root-servers.net\n\ + 2001:500:2::c; # c.root-servers.net\n\ + 2001:500:2f::f; # f.root-servers.net\n\ + 2001:500:12::d0d; # g.root-servers.net\n\ + 2001:7fd::1; # k.root-servers.net\n\ + 2620:0:2830:202::132; # xfr.cjr.dns.icann.org\n\ + 2620:0:2d0:202::132; # xfr.lax.dns.icann.org\n\ + 170.247.170.2; # b.root-servers.net\n\ + 192.33.4.12; # c.root-servers.net\n\ + 192.5.5.241; # f.root-servers.net\n\ + 192.112.36.4; # g.root-servers.net\n\ + 193.0.14.129; # k.root-servers.net\n\ + 192.0.47.132; # xfr.cjr.dns.icann.org\n\ + 192.0.32.132; # xfr.lax.dns.icann.org\n\ +};\n\ +"; + +isc_result_t +named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) { + isc_buffer_t b; + + isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1); + isc_buffer_add(&b, sizeof(defaultconf) - 1); + return cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf, + CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | + CFG_PCTX_NOEXPERIMENTAL, + conf); +} + +const char * +named_config_getdefault(void) { + return defaultconf; +} + +isc_result_t +named_config_get(cfg_obj_t const *const *maps, const char *name, + const cfg_obj_t **obj) { + int i; + + for (i = 0; maps[i] != NULL; i++) { + if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS) { + return ISC_R_SUCCESS; + } + } + return ISC_R_NOTFOUND; +} + +isc_result_t +named_checknames_get(const cfg_obj_t **maps, const char *const names[], + const cfg_obj_t **obj) { + const cfg_listelt_t *element; + const cfg_obj_t *checknames; + const cfg_obj_t *type; + const cfg_obj_t *value; + int i; + + REQUIRE(maps != NULL); + REQUIRE(names != NULL); + REQUIRE(obj != NULL && *obj == NULL); + + for (i = 0; maps[i] != NULL; i++) { + checknames = NULL; + if (cfg_map_get(maps[i], "check-names", &checknames) == + ISC_R_SUCCESS) + { + /* + * Zone map entry is not a list. + */ + if (checknames != NULL && !cfg_obj_islist(checknames)) { + *obj = checknames; + return ISC_R_SUCCESS; + } + for (element = cfg_list_first(checknames); + element != NULL; element = cfg_list_next(element)) + { + value = cfg_listelt_value(element); + type = cfg_tuple_get(value, "type"); + + for (size_t j = 0; names[j] != NULL; j++) { + if (strcasecmp(cfg_obj_asstring(type), + names[j]) == 0) + { + *obj = cfg_tuple_get(value, + "mode"); + return ISC_R_SUCCESS; + } + } + } + } + } + return ISC_R_NOTFOUND; +} + +int +named_config_listcount(const cfg_obj_t *list) { + const cfg_listelt_t *e; + int i = 0; + + for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e)) { + i++; + } + + return i; +} + +isc_result_t +named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, + dns_rdataclass_t *classp) { + isc_textregion_t r; + isc_result_t result; + + if (!cfg_obj_isstring(classobj)) { + *classp = defclass; + return ISC_R_SUCCESS; + } + r.base = UNCONST(cfg_obj_asstring(classobj)); + r.length = strlen(r.base); + result = dns_rdataclass_fromtext(classp, &r); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(classobj, named_g_lctx, ISC_LOG_ERROR, + "unknown class '%s'", r.base); + } + return result; +} + +isc_result_t +named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, + dns_rdatatype_t *typep) { + isc_textregion_t r; + isc_result_t result; + + if (!cfg_obj_isstring(typeobj)) { + *typep = deftype; + return ISC_R_SUCCESS; + } + r.base = UNCONST(cfg_obj_asstring(typeobj)); + r.length = strlen(r.base); + result = dns_rdatatype_fromtext(typep, &r); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(typeobj, named_g_lctx, ISC_LOG_ERROR, + "unknown type '%s'", r.base); + } + return result; +} + +dns_zonetype_t +named_config_getzonetype(const cfg_obj_t *zonetypeobj) { + dns_zonetype_t ztype = dns_zone_none; + const char *str; + + str = cfg_obj_asstring(zonetypeobj); + if (strcasecmp(str, "primary") == 0 || strcasecmp(str, "master") == 0) { + ztype = dns_zone_primary; + } else if (strcasecmp(str, "secondary") == 0 || + strcasecmp(str, "slave") == 0) + { + ztype = dns_zone_secondary; + } else if (strcasecmp(str, "mirror") == 0) { + ztype = dns_zone_mirror; + } else if (strcasecmp(str, "stub") == 0) { + ztype = dns_zone_stub; + } else if (strcasecmp(str, "static-stub") == 0) { + ztype = dns_zone_staticstub; + } else if (strcasecmp(str, "redirect") == 0) { + ztype = dns_zone_redirect; + } else { + UNREACHABLE(); + } + return ztype; +} + +isc_result_t +named_config_getremotesdef(const cfg_obj_t *cctx, const char *list, + const char *name, const cfg_obj_t **ret) { + isc_result_t result; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *elt; + + REQUIRE(cctx != NULL); + REQUIRE(name != NULL); + REQUIRE(ret != NULL && *ret == NULL); + + result = cfg_map_get(cctx, list, &obj); + if (result != ISC_R_SUCCESS) { + return result; + } + elt = cfg_list_first(obj); + while (elt != NULL) { + obj = cfg_listelt_value(elt); + if (strcasecmp(cfg_obj_asstring(cfg_tuple_get(obj, "name")), + name) == 0) + { + *ret = obj; + return ISC_R_SUCCESS; + } + elt = cfg_list_next(elt); + } + return ISC_R_NOTFOUND; +} + +static isc_result_t +named_config_getname(isc_mem_t *mctx, const cfg_obj_t *obj, + dns_name_t **namep) { + REQUIRE(namep != NULL && *namep == NULL); + + const char *objstr; + isc_result_t result; + isc_buffer_t b; + dns_fixedname_t fname; + + if (!cfg_obj_isstring(obj)) { + *namep = NULL; + return ISC_R_SUCCESS; + } + + *namep = isc_mem_get(mctx, sizeof(**namep)); + dns_name_init(*namep, NULL); + + objstr = cfg_obj_asstring(obj); + isc_buffer_constinit(&b, objstr, strlen(objstr)); + isc_buffer_add(&b, strlen(objstr)); + dns_fixedname_init(&fname); + result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, + 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, *namep, sizeof(**namep)); + *namep = NULL; + return result; + } + dns_name_dup(dns_fixedname_name(&fname), mctx, *namep); + + return ISC_R_SUCCESS; +} + +#define grow_array(mctx, array, newlen, oldlen) \ + if (newlen >= oldlen) { \ + array = isc_mem_creget(mctx, array, oldlen, newlen + 16, \ + sizeof(array[0])); \ + oldlen = newlen + 16; \ + } + +#define shrink_array(mctx, array, newlen, oldlen) \ + if (newlen < oldlen) { \ + array = isc_mem_creget(mctx, array, oldlen, newlen, \ + sizeof(array[0])); \ + oldlen = newlen; \ + } + +static const char *remotesnames[4] = { "remote-servers", "parental-agents", + "primaries", "masters" }; + +isc_result_t +named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, + isc_mem_t *mctx, dns_ipkeylist_t *ipkl) { + uint32_t addrcount = 0, srccount = 0; + uint32_t keycount = 0, tlscount = 0; + uint32_t listcount = 0, l = 0, i = 0; + uint32_t stackcount = 0, pushed = 0; + isc_result_t result; + const cfg_listelt_t *element; + const cfg_obj_t *addrlist; + const cfg_obj_t *portobj; + const cfg_obj_t *src4obj; + const cfg_obj_t *src6obj; + in_port_t port = (in_port_t)0; + in_port_t def_port; + in_port_t def_tlsport; + isc_sockaddr_t src4; + isc_sockaddr_t src6; + isc_sockaddr_t *addrs = NULL; + isc_sockaddr_t *sources = NULL; + dns_name_t **keys = NULL; + dns_name_t **tlss = NULL; + struct { + const char *name; + in_port_t port; + isc_sockaddr_t *src4s; + isc_sockaddr_t *src6s; + } *lists = NULL; + struct { + const cfg_listelt_t *element; + in_port_t port; + isc_sockaddr_t src4; + isc_sockaddr_t src6; + } *stack = NULL; + + REQUIRE(ipkl != NULL); + REQUIRE(ipkl->count == 0); + REQUIRE(ipkl->addrs == NULL); + REQUIRE(ipkl->keys == NULL); + REQUIRE(ipkl->tlss == NULL); + REQUIRE(ipkl->labels == NULL); + REQUIRE(ipkl->allocated == 0); + + /* + * Get system defaults. + */ + result = named_config_getport(config, "port", &def_port); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = named_config_getport(config, "tls-port", &def_tlsport); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + +newlist: + addrlist = cfg_tuple_get(list, "addresses"); + portobj = cfg_tuple_get(list, "port"); + src4obj = cfg_tuple_get(list, "source"); + src6obj = cfg_tuple_get(list, "source-v6"); + + if (cfg_obj_isuint32(portobj)) { + uint32_t val = cfg_obj_asuint32(portobj); + if (val > UINT16_MAX) { + cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", val); + result = ISC_R_RANGE; + goto cleanup; + } + port = (in_port_t)val; + } + + if (src4obj != NULL && cfg_obj_issockaddr(src4obj)) { + src4 = *cfg_obj_assockaddr(src4obj); + } else { + isc_sockaddr_any(&src4); + } + + if (src6obj != NULL && cfg_obj_issockaddr(src6obj)) { + src6 = *cfg_obj_assockaddr(src6obj); + } else { + isc_sockaddr_any6(&src6); + } + + element = cfg_list_first(addrlist); +resume: + for (; element != NULL; element = cfg_list_next(element)) { + const cfg_obj_t *addr; + const cfg_obj_t *key; + const cfg_obj_t *tls; + + addr = cfg_tuple_get(cfg_listelt_value(element), + "remoteselement"); + key = cfg_tuple_get(cfg_listelt_value(element), "key"); + tls = cfg_tuple_get(cfg_listelt_value(element), "tls"); + + if (!cfg_obj_issockaddr(addr)) { + const char *listname = cfg_obj_asstring(addr); + isc_result_t tresult; + uint32_t j; + + /* Grow lists? */ + grow_array(mctx, lists, l, listcount); + + /* Seen? */ + for (j = 0; j < l; j++) { + if (strcasecmp(lists[j].name, listname) == 0) { + break; + } + } + if (j < l) { + continue; + } + list = NULL; + tresult = ISC_R_NOTFOUND; + for (size_t n = 0; n < ARRAY_SIZE(remotesnames); n++) { + tresult = named_config_getremotesdef( + config, remotesnames[n], listname, + &list); + if (tresult == ISC_R_SUCCESS) { + break; + } + } + if (tresult == ISC_R_NOTFOUND) { + cfg_obj_log(addr, named_g_lctx, ISC_LOG_ERROR, + "remote-servers \"%s\" not found", + listname); + } + if (tresult != ISC_R_SUCCESS) { + result = tresult; + goto cleanup; + } + lists[l++].name = listname; + /* Grow stack? */ + grow_array(mctx, stack, pushed, stackcount); + /* + * We want to resume processing this list on the + * next element. + */ + stack[pushed].element = cfg_list_next(element); + stack[pushed].port = port; + stack[pushed].src4 = src4; + stack[pushed].src6 = src6; + pushed++; + goto newlist; + } + + grow_array(mctx, addrs, i, addrcount); + grow_array(mctx, keys, i, keycount); + grow_array(mctx, tlss, i, tlscount); + grow_array(mctx, sources, i, srccount); + + addrs[i] = *cfg_obj_assockaddr(addr); + + result = named_config_getname(mctx, key, &keys[i]); + if (result != ISC_R_SUCCESS) { + i++; /* Increment here so that cleanup on error works. + */ + goto cleanup; + } + + result = named_config_getname(mctx, tls, &tlss[i]); + if (result != ISC_R_SUCCESS) { + i++; /* Increment here so that cleanup on error works. + */ + goto cleanup; + } + + /* If the port is unset, take it from one of the upper levels */ + if (isc_sockaddr_getport(&addrs[i]) == 0) { + in_port_t addr_port = port; + + /* If unset, use the default port or tls-port */ + if (addr_port == 0) { + if (tlss[i] != NULL) { + addr_port = def_tlsport; + } else { + addr_port = def_port; + } + } + + isc_sockaddr_setport(&addrs[i], addr_port); + } + + switch (isc_sockaddr_pf(&addrs[i])) { + case PF_INET: + sources[i] = src4; + break; + case PF_INET6: + sources[i] = src6; + break; + default: + i++; /* Increment here so that cleanup on error works. + */ + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; + } + + i++; + } + if (pushed != 0) { + pushed--; + element = stack[pushed].element; + port = stack[pushed].port; + src4 = stack[pushed].src4; + src6 = stack[pushed].src6; + goto resume; + } + + shrink_array(mctx, addrs, i, addrcount); + shrink_array(mctx, keys, i, keycount); + shrink_array(mctx, tlss, i, tlscount); + shrink_array(mctx, sources, i, srccount); + + if (lists != NULL) { + isc_mem_cput(mctx, lists, listcount, sizeof(lists[0])); + } + if (stack != NULL) { + isc_mem_cput(mctx, stack, stackcount, sizeof(stack[0])); + } + + INSIST(keycount == addrcount); + INSIST(tlscount == addrcount); + INSIST(srccount == addrcount); + + ipkl->addrs = addrs; + ipkl->keys = keys; + ipkl->tlss = tlss; + ipkl->sources = sources; + ipkl->count = addrcount; + ipkl->allocated = addrcount; + + return ISC_R_SUCCESS; + +cleanup: + if (addrs != NULL) { + isc_mem_cput(mctx, addrs, addrcount, sizeof(addrs[0])); + } + if (keys != NULL) { + for (size_t j = 0; j < i; j++) { + if (keys[j] == NULL) { + continue; + } + if (dns_name_dynamic(keys[j])) { + dns_name_free(keys[j], mctx); + } + isc_mem_put(mctx, keys[j], sizeof(*keys[j])); + } + isc_mem_cput(mctx, keys, keycount, sizeof(keys[0])); + } + if (tlss != NULL) { + for (size_t j = 0; j < i; j++) { + if (tlss[j] == NULL) { + continue; + } + if (dns_name_dynamic(tlss[j])) { + dns_name_free(tlss[j], mctx); + } + isc_mem_put(mctx, tlss[j], sizeof(*tlss[j])); + } + isc_mem_cput(mctx, tlss, tlscount, sizeof(tlss[0])); + } + if (sources != NULL) { + isc_mem_cput(mctx, sources, srccount, sizeof(sources[0])); + } + if (lists != NULL) { + isc_mem_cput(mctx, lists, listcount, sizeof(lists[0])); + } + if (stack != NULL) { + isc_mem_cput(mctx, stack, stackcount, sizeof(stack[0])); + } + return result; +} + +isc_result_t +named_config_getport(const cfg_obj_t *config, const char *type, + in_port_t *portp) { + const cfg_obj_t *maps[3]; + const cfg_obj_t *options = NULL; + const cfg_obj_t *portobj = NULL; + isc_result_t result; + int i; + + (void)cfg_map_get(config, "options", &options); + i = 0; + if (options != NULL) { + maps[i++] = options; + } + maps[i++] = named_g_defaults; + maps[i] = NULL; + + result = named_config_get(maps, type, &portobj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { + cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, + "port '%u' out of range", + cfg_obj_asuint32(portobj)); + return ISC_R_RANGE; + } + *portp = (in_port_t)cfg_obj_asuint32(portobj); + return ISC_R_SUCCESS; +} + +struct keyalgorithms { + const char *str; + enum { + hmacnone, + hmacmd5, + hmacsha1, + hmacsha224, + hmacsha256, + hmacsha384, + hmacsha512 + } hmac; + unsigned int type; + uint16_t size; +} algorithms[] = { { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, + { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 }, + { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 }, + { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 }, + { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 }, + { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 }, + { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 }, + { NULL, hmacnone, DST_ALG_UNKNOWN, 0 } }; + +isc_result_t +named_config_getkeyalgorithm(const char *str, unsigned int *typep, + uint16_t *digestbits) { + int i; + size_t len = 0; + uint16_t bits; + isc_result_t result; + + for (i = 0; algorithms[i].str != NULL; i++) { + len = strlen(algorithms[i].str); + if (strncasecmp(algorithms[i].str, str, len) == 0 && + (str[len] == '\0' || + (algorithms[i].size != 0 && str[len] == '-'))) + { + break; + } + } + if (algorithms[i].str == NULL) { + return ISC_R_NOTFOUND; + } + if (str[len] == '-') { + result = isc_parse_uint16(&bits, str + len + 1, 10); + if (result != ISC_R_SUCCESS) { + return result; + } + if (bits > algorithms[i].size) { + return ISC_R_RANGE; + } + } else if (algorithms[i].size == 0) { + bits = 128; + } else { + bits = algorithms[i].size; + } + SET_IF_NOT_NULL(typep, algorithms[i].type); + SET_IF_NOT_NULL(digestbits, bits); + return ISC_R_SUCCESS; +} diff --git a/bin/named/control.c b/bin/named/control.c new file mode 100644 index 0000000..27abec7 --- /dev/null +++ b/bin/named/control.c @@ -0,0 +1,310 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_LIBSCF +#include +#endif /* ifdef HAVE_LIBSCF */ + +static isc_result_t +getcommand(isc_lex_t *lex, char **cmdp) { + isc_result_t result; + isc_token_t token; + + REQUIRE(cmdp != NULL && *cmdp == NULL); + + result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF, &token); + if (result != ISC_R_SUCCESS) { + return result; + } + + isc_lex_ungettoken(lex, &token); + + if (token.type != isc_tokentype_string) { + return ISC_R_FAILURE; + } + + *cmdp = token.value.as_textregion.base; + + return ISC_R_SUCCESS; +} + +static bool +command_compare(const char *str, const char *command) { + return strcasecmp(str, command) == 0; +} + +/*% + * This function is called to process the incoming command + * when a control channel message is received. + */ +isc_result_t +named_control_docommand(isccc_sexpr_t *message, bool readonly, + isc_buffer_t **text) { + isccc_sexpr_t *data; + char *cmdline = NULL; + char *command = NULL; + isc_result_t result; + int log_level; + isc_buffer_t src; + isc_lex_t *lex = NULL; +#ifdef HAVE_LIBSCF + named_smf_want_disable = 0; +#endif /* ifdef HAVE_LIBSCF */ + + data = isccc_alist_lookup(message, "_data"); + if (!isccc_alist_alistp(data)) { + /* + * No data section. + */ + return ISC_R_FAILURE; + } + + result = isccc_cc_lookupstring(data, "type", &cmdline); + if (result != ISC_R_SUCCESS) { + /* + * We have no idea what this is. + */ + return result; + } + + isc_lex_create(named_g_mctx, strlen(cmdline), &lex); + + isc_buffer_init(&src, cmdline, strlen(cmdline)); + isc_buffer_add(&src, strlen(cmdline)); + result = isc_lex_openbuffer(lex, &src); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = getcommand(lex, &command); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* + * Compare the 'command' parameter against all known control commands. + */ + if ((command_compare(command, NAMED_COMMAND_NULL) && + strlen(cmdline) == 4) || + command_compare(command, NAMED_COMMAND_STATUS)) + { + log_level = ISC_LOG_DEBUG(1); + } else { + log_level = ISC_LOG_INFO; + } + + /* + * If this listener should have read-only access, reject + * restricted commands here. rndc nta is handled specially + * below. + */ + if (readonly && !command_compare(command, NAMED_COMMAND_NTA) && + !command_compare(command, NAMED_COMMAND_NULL) && + !command_compare(command, NAMED_COMMAND_STATUS) && + !command_compare(command, NAMED_COMMAND_SHOWZONE) && + !command_compare(command, NAMED_COMMAND_TESTGEN) && + !command_compare(command, NAMED_COMMAND_ZONESTATUS)) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, log_level, + "rejecting restricted control channel " + "command '%s'", + cmdline); + result = ISC_R_FAILURE; + goto cleanup; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, log_level, + "received control channel command '%s'", cmdline); + + /* + * After the lengthy "halt" and "stop", the commands are + * handled in alphabetical order of the NAMED_COMMAND_ macros. + */ + if (command_compare(command, NAMED_COMMAND_HALT)) { +#ifdef HAVE_LIBSCF + /* + * If we are managed by smf(5), AND in chroot, then + * we cannot connect to the smf repository, so just + * return with an appropriate message back to rndc. + */ + if (named_smf_got_instance == 1 && named_smf_chroot == 1) { + result = named_smf_add_message(text); + goto cleanup; + } + /* + * If we are managed by smf(5) but not in chroot, + * try to disable ourselves the smf way. + */ + if (named_smf_got_instance == 1 && named_smf_chroot == 0) { + named_smf_want_disable = 1; + } + /* + * If named_smf_got_instance = 0, named_smf_chroot is + * not relevant and we fall through to shutdown below. + */ +#endif /* ifdef HAVE_LIBSCF */ + /* Do not flush master files */ + named_server_flushonshutdown(named_g_server, false); + named_os_shutdownmsg(cmdline, *text); + isc_loopmgr_shutdown(named_g_loopmgr); + result = ISC_R_SHUTTINGDOWN; + } else if (command_compare(command, NAMED_COMMAND_STOP)) { + /* + * "stop" is the same as "halt" except it does + * flush master files. + */ +#ifdef HAVE_LIBSCF + if (named_smf_got_instance == 1 && named_smf_chroot == 1) { + result = named_smf_add_message(text); + goto cleanup; + } + if (named_smf_got_instance == 1 && named_smf_chroot == 0) { + named_smf_want_disable = 1; + } +#endif /* ifdef HAVE_LIBSCF */ + named_server_flushonshutdown(named_g_server, true); + named_os_shutdownmsg(cmdline, *text); + isc_loopmgr_shutdown(named_g_loopmgr); + result = ISC_R_SHUTTINGDOWN; + } else if (command_compare(command, NAMED_COMMAND_ADDZONE) || + command_compare(command, NAMED_COMMAND_MODZONE)) + { + result = named_server_changezone(named_g_server, cmdline, text); + } else if (command_compare(command, NAMED_COMMAND_DELZONE)) { + result = named_server_delzone(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_DNSSEC)) { + result = named_server_dnssec(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_DNSTAP) || + command_compare(command, NAMED_COMMAND_DNSTAPREOPEN)) + { + result = named_server_dnstap(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_DUMPDB)) { + result = named_server_dumpdb(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_DUMPSTATS)) { + result = named_server_dumpstats(named_g_server); + } else if (command_compare(command, NAMED_COMMAND_FETCHLIMIT)) { + result = named_server_fetchlimit(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_FLUSH)) { + result = named_server_flushcache(named_g_server, lex); + } else if (command_compare(command, NAMED_COMMAND_FLUSHNAME)) { + result = named_server_flushnode(named_g_server, lex, false); + } else if (command_compare(command, NAMED_COMMAND_FLUSHTREE)) { + result = named_server_flushnode(named_g_server, lex, true); + } else if (command_compare(command, NAMED_COMMAND_FREEZE)) { + result = named_server_freeze(named_g_server, true, lex, text); + } else if (command_compare(command, NAMED_COMMAND_SKR)) { + result = named_server_skr(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_LOADKEYS) || + command_compare(command, NAMED_COMMAND_SIGN)) + { + result = named_server_rekey(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_MEMPROF)) { + result = named_server_togglememprof(lex); + } else if (command_compare(command, NAMED_COMMAND_MKEYS)) { + result = named_server_mkeys(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_NOTIFY)) { + result = named_server_notifycommand(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_NOTRACE)) { + named_g_debuglevel = 0; + isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); + result = ISC_R_SUCCESS; + } else if (command_compare(command, NAMED_COMMAND_NTA)) { + result = named_server_nta(named_g_server, lex, readonly, text); + } else if (command_compare(command, NAMED_COMMAND_NULL)) { + result = ISC_R_SUCCESS; + } else if (command_compare(command, NAMED_COMMAND_QUERYLOG)) { + result = named_server_setortoggle(named_g_server, + "query logging", + NS_SERVER_LOGQUERIES, lex); + } else if (command_compare(command, NAMED_COMMAND_RECONFIG)) { + result = named_server_reconfigcommand(named_g_server); + } else if (command_compare(command, NAMED_COMMAND_RECURSING)) { + result = named_server_dumprecursing(named_g_server); + } else if (command_compare(command, NAMED_COMMAND_REFRESH)) { + result = named_server_refreshcommand(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_RELOAD)) { + result = named_server_reloadcommand(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_RESETSTATS)) { + result = named_server_resetstatscommand(named_g_server, lex, + text); + } else if (command_compare(command, NAMED_COMMAND_RESPONSELOG)) { + result = named_server_setortoggle(named_g_server, + "response logging", + NS_SERVER_LOGRESPONSES, lex); + } else if (command_compare(command, NAMED_COMMAND_RETRANSFER)) { + result = named_server_retransfercommand(named_g_server, lex, + text); + } else if (command_compare(command, NAMED_COMMAND_SCAN)) { + named_server_scan_interfaces(named_g_server); + result = ISC_R_SUCCESS; + } else if (command_compare(command, NAMED_COMMAND_SECROOTS)) { + result = named_server_dumpsecroots(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_SERVESTALE)) { + result = named_server_servestale(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_SHOWZONE)) { + result = named_server_showzone(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_SIGNING)) { + result = named_server_signing(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_STATUS)) { + result = named_server_status(named_g_server, text); + } else if (command_compare(command, NAMED_COMMAND_SYNC)) { + result = named_server_sync(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_TCPTIMEOUTS)) { + result = named_server_tcptimeouts(lex, text); + } else if (command_compare(command, NAMED_COMMAND_TESTGEN)) { + result = named_server_testgen(lex, text); + } else if (command_compare(command, NAMED_COMMAND_THAW) || + command_compare(command, NAMED_COMMAND_UNFREEZE)) + { + result = named_server_freeze(named_g_server, false, lex, text); + } else if (command_compare(command, NAMED_COMMAND_TRACE)) { + result = named_server_setdebuglevel(named_g_server, lex); + } else if (command_compare(command, NAMED_COMMAND_VALIDATION)) { + result = named_server_validation(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_ZONESTATUS)) { + result = named_server_zonestatus(named_g_server, lex, text); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING, + "unknown control channel command '%s'", command); + result = DNS_R_UNKNOWNCOMMAND; + } + +cleanup: + if (lex != NULL) { + isc_lex_destroy(&lex); + } + + return result; +} diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c new file mode 100644 index 0000000..612454e --- /dev/null +++ b/bin/named/controlconf.c @@ -0,0 +1,1386 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* Add -DNAMED_CONTROLCONF_TRACE=1 to CFLAGS for detailed reference tracing */ + +typedef struct controlkey controlkey_t; +typedef ISC_LIST(controlkey_t) controlkeylist_t; + +typedef struct controlconnection controlconnection_t; +typedef ISC_LIST(controlconnection_t) controlconnectionlist_t; + +typedef struct controllistener controllistener_t; +typedef ISC_LIST(controllistener_t) controllistenerlist_t; + +struct controlkey { + char *keyname; + uint32_t algorithm; + isc_region_t secret; + ISC_LINK(controlkey_t) link; +}; + +struct controlconnection { + isc_refcount_t references; + isccc_ccmsg_t ccmsg; + controllistener_t *listener; + isccc_sexpr_t *ctrl; + isc_buffer_t *buffer; + isc_buffer_t *text; + isccc_sexpr_t *request; + isccc_sexpr_t *response; + uint32_t alg; + isccc_region_t secret; + uint32_t nonce; + isc_stdtime_t now; + isc_result_t result; + ISC_LINK(controlconnection_t) link; + bool shuttingdown; +}; + +struct controllistener { + named_controls_t *controls; + isc_mem_t *mctx; + isc_sockaddr_t address; + isc_nmsocket_t *sock; + dns_acl_t *acl; + bool shuttingdown; + isc_refcount_t references; + controlkeylist_t keys; + controlconnectionlist_t connections; + isc_socktype_t type; + uint32_t perm; + uint32_t owner; + uint32_t group; + bool readonly; + ISC_LINK(controllistener_t) link; +}; + +struct named_controls { + named_server_t *server; + controllistenerlist_t listeners; + bool shuttingdown; + isc_mutex_t symtab_lock; + isccc_symtab_t *symtab; +}; + +static isc_result_t +control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg); +static void +control_recvmessage(isc_nmhandle_t *handle, isc_result_t result, void *arg); +static void +conn_cleanup(controlconnection_t *conn); +static void +conn_free(controlconnection_t *conn); +static void +conn_shutdown(controlconnection_t *conn); + +#if NAMED_CONTROLCONF_TRACE +#define controllistener_ref(ptr) \ + controllistener__ref(ptr, __func__, __FILE__, __LINE__) +#define controllistener_unref(ptr) \ + controllistener__unref(ptr, __func__, __FILE__, __LINE__) +#define controllistener_attach(ptr, ptrp) \ + controllistener__attach(ptr, ptrp, __func__, __FILE__, __LINE__) +#define controllistener_detach(ptrp) \ + controllistener__detach(ptrp, __func__, __FILE__, __LINE__) +ISC_REFCOUNT_TRACE_DECL(controllistener); + +#define controlconnection_ref(ptr) \ + controlconnection__ref(ptr, __func__, __FILE__, __LINE__) +#define controlconnection_unref(ptr) \ + controlconnection__unref(ptr, __func__, __FILE__, __LINE__) +#define controlconnection_attach(ptr, ptrp) \ + controlconnection__attach(ptr, ptrp, __func__, __FILE__, __LINE__) +#define controlconnection_detach(ptrp) \ + controlconnection__detach(ptrp, __func__, __FILE__, __LINE__) +ISC_REFCOUNT_TRACE_DECL(controlconnection); +#else +ISC_REFCOUNT_DECL(controllistener); +ISC_REFCOUNT_DECL(controlconnection); +#endif + +#define CLOCKSKEW 300 + +#define CHECK(x) \ + { \ + result = (x); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } + +static void +free_controlkey(controlkey_t *key, isc_mem_t *mctx) { + if (key->keyname != NULL) { + isc_mem_free(mctx, key->keyname); + } + if (key->secret.base != NULL) { + isc_mem_put(mctx, key->secret.base, key->secret.length); + } + isc_mem_put(mctx, key, sizeof(*key)); +} + +static void +free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) { + while (!ISC_LIST_EMPTY(*keylist)) { + controlkey_t *key = ISC_LIST_HEAD(*keylist); + ISC_LIST_UNLINK(*keylist, key, link); + free_controlkey(key, mctx); + } +} + +static void +free_listener(controllistener_t *listener) { + REQUIRE(listener->shuttingdown); + REQUIRE(ISC_LIST_EMPTY(listener->connections)); + REQUIRE(listener->sock == NULL); + + free_controlkeylist(&listener->keys, listener->mctx); + + if (listener->acl != NULL) { + dns_acl_detach(&listener->acl); + } + + isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); +} + +#if NAMED_CONTROLCONF_TRACE +ISC_REFCOUNT_TRACE_IMPL(controllistener, free_listener); +ISC_REFCOUNT_TRACE_IMPL(controlconnection, conn_free); +#else +ISC_REFCOUNT_IMPL(controllistener, free_listener); +ISC_REFCOUNT_IMPL(controlconnection, conn_free); +#endif + +static void +shutdown_listener(controllistener_t *listener) { + controlconnection_t *conn = NULL; + controlconnection_t *next = NULL; + + /* Don't shutdown the same listener twice */ + if (listener->shuttingdown) { + return; + } + listener->shuttingdown = true; + + for (conn = ISC_LIST_HEAD(listener->connections); conn != NULL; + conn = next) + { + /* + * 'conn' is likely to be freed by the conn_shutdown() call. + */ + next = ISC_LIST_NEXT(conn, link); + conn_shutdown(conn); + } + + ISC_LIST_UNLINK(listener->controls->listeners, listener, link); + + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE, + "stopping command channel on %s", socktext); + + isc_nm_stoplistening(listener->sock); + isc_nmsocket_close(&listener->sock); + controllistener_detach(&listener); +} + +static bool +address_ok(isc_sockaddr_t *sockaddr, controllistener_t *listener) { + dns_aclenv_t *env = + ns_interfacemgr_getaclenv(named_g_server->interfacemgr); + isc_netaddr_t netaddr; + isc_result_t result; + int match; + + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + + result = dns_acl_match(&netaddr, NULL, listener->acl, env, &match, + NULL); + return result == ISC_R_SUCCESS && match > 0; +} + +static void +control_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + controlconnection_t *conn = (controlconnection_t *)arg; + + if (conn->shuttingdown) { + /* The connection is shuttingdown */ + result = ISC_R_SHUTTINGDOWN; + } + + if (result == ISC_R_SUCCESS) { + /* Everything is peachy, continue reading from the socket */ + isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage, + conn); + /* Detach the sending reference */ + controlconnection_detach(&conn); + return; + } + + if (result != ISC_R_SHUTTINGDOWN) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(handle); + + isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING, + "error sending command response to %s: %s", + socktext, isc_result_totext(result)); + } + + /* Shutdown the reading */ + conn_shutdown(conn); + + /* Detach the sending reference */ + controlconnection_detach(&conn); +} + +static void +log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t peeraddr = isc_nmhandle_peeraddr(ccmsg->handle); + + isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_ERROR, + "invalid command from %s: %s", socktext, + isc_result_totext(result)); +} + +static void +conn_cleanup(controlconnection_t *conn) { + controllistener_t *listener = conn->listener; + + if (conn->response != NULL) { + isccc_sexpr_free(&conn->response); + } + if (conn->request != NULL) { + isccc_sexpr_free(&conn->request); + } + if (conn->secret.rstart != NULL) { + isc_mem_put(listener->mctx, conn->secret.rstart, + REGION_SIZE(conn->secret)); + } + if (conn->text != NULL) { + isc_buffer_free(&conn->text); + } +} + +static void +control_respond(controlconnection_t *conn) { + controllistener_t *listener = conn->listener; + isccc_sexpr_t *data = NULL; + isc_buffer_t b; + isc_region_t r; + isc_result_t result; + + result = isccc_cc_createresponse(conn->request, conn->now, + conn->now + 60, &conn->response); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + if (conn->result == ISC_R_SHUTTINGDOWN) { + result = ISC_R_SUCCESS; + } else { + result = conn->result; + } + + data = isccc_alist_lookup(conn->response, "_data"); + if (data != NULL) { + if (isccc_cc_defineuint32(data, "result", result) == NULL) { + goto cleanup; + } + } + + if (result != ISC_R_SUCCESS) { + if (data != NULL) { + const char *estr = isc_result_totext(result); + if (isccc_cc_definestring(data, "err", estr) == NULL) { + goto cleanup; + } + } + } + + if (isc_buffer_usedlength(conn->text) > 0) { + if (data != NULL) { + char *str = (char *)isc_buffer_base(conn->text); + if (isccc_cc_definestring(data, "text", str) == NULL) { + goto cleanup; + } + } + } + + conn->ctrl = isccc_alist_lookup(conn->response, "_ctrl"); + if (conn->ctrl == NULL || + isccc_cc_defineuint32(conn->ctrl, "_nonce", conn->nonce) == NULL) + { + goto cleanup; + } + + if (conn->buffer == NULL) { + isc_buffer_allocate(listener->mctx, &conn->buffer, 2 * 2048); + } + + isc_buffer_clear(conn->buffer); + /* Skip the length field (4 bytes) */ + isc_buffer_add(conn->buffer, 4); + + result = isccc_cc_towire(conn->response, &conn->buffer, conn->alg, + &conn->secret); + if (result != ISC_R_SUCCESS) { + return; + } + + isc_buffer_init(&b, conn->buffer->base, 4); + isc_buffer_putuint32(&b, conn->buffer->used - 4); + + r.base = conn->buffer->base; + r.length = conn->buffer->used; + + /* Attach the sending reference */ + controlconnection_ref(conn); + isccc_ccmsg_sendmessage(&conn->ccmsg, &r, control_senddone, conn); + +cleanup: + conn_cleanup(conn); +} + +static void +control_command(void *arg) { + controlconnection_t *conn = (controlconnection_t *)arg; + + /* Don't run the command if we already started the shutdown */ + if (!conn->shuttingdown) { + conn->result = named_control_docommand( + conn->request, conn->listener->readonly, &conn->text); + control_respond(conn); + } + + /* Detach the control command reference */ + controlconnection_detach(&conn); +} + +static void +conn_shutdown(controlconnection_t *conn) { + /* Don't shutdown the same controlconnection twice */ + if (conn->shuttingdown) { + return; + } + conn->shuttingdown = true; + + /* + * Close the TCP connection to make sure that no read callback will be + * called for it ever again. + */ + isccc_ccmsg_disconnect(&conn->ccmsg); + + /* Detach the reading reference */ + controlconnection_detach(&conn); +} + +static void +control_recvmessage(isc_nmhandle_t *handle ISC_ATTR_UNUSED, isc_result_t result, + void *arg) { + controlconnection_t *conn = (controlconnection_t *)arg; + controllistener_t *listener = conn->listener; + controlkey_t *key = NULL; + isccc_time_t sent; + isccc_time_t exp; + uint32_t nonce; + + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + for (key = ISC_LIST_HEAD(listener->keys); key != NULL; + key = ISC_LIST_NEXT(key, link)) + { + isccc_region_t ccregion; + + isccc_ccmsg_toregion(&conn->ccmsg, &ccregion); + conn->secret.rstart = isc_mem_get(listener->mctx, + key->secret.length); + memmove(conn->secret.rstart, key->secret.base, + key->secret.length); + conn->secret.rend = conn->secret.rstart + key->secret.length; + conn->alg = key->algorithm; + result = isccc_cc_fromwire(&ccregion, &conn->request, conn->alg, + &conn->secret); + if (result == ISC_R_SUCCESS) { + break; + } + isc_mem_put(listener->mctx, conn->secret.rstart, + REGION_SIZE(conn->secret)); + } + + if (key == NULL) { + result = ISCCC_R_BADAUTH; + goto cleanup; + } + + /* We shouldn't be getting a reply. */ + if (isccc_cc_isreply(conn->request)) { + result = ISC_R_FAILURE; + goto cleanup; + } + + conn->now = isc_stdtime_now(); + + /* + * Limit exposure to replay attacks. + */ + conn->ctrl = isccc_alist_lookup(conn->request, "_ctrl"); + if (!isccc_alist_alistp(conn->ctrl)) { + result = ISC_R_FAILURE; + goto cleanup; + } + + if (isccc_cc_lookupuint32(conn->ctrl, "_tim", &sent) == ISC_R_SUCCESS) { + if ((sent + CLOCKSKEW) < conn->now || + (sent - CLOCKSKEW) > conn->now) + { + result = ISCCC_R_CLOCKSKEW; + goto cleanup; + } + } else { + result = ISC_R_FAILURE; + goto cleanup; + } + + /* + * Expire messages that are too old. + */ + if (isccc_cc_lookupuint32(conn->ctrl, "_exp", &exp) == ISC_R_SUCCESS && + conn->now > exp) + { + result = ISCCC_R_EXPIRED; + goto cleanup; + } + + /* + * Duplicate suppression (required for UDP). + */ + LOCK(&listener->controls->symtab_lock); + isccc_cc_cleansymtab(listener->controls->symtab, conn->now); + result = isccc_cc_checkdup(listener->controls->symtab, conn->request, + conn->now); + UNLOCK(&listener->controls->symtab_lock); + if (result != ISC_R_SUCCESS) { + if (result == ISC_R_EXISTS) { + result = ISCCC_R_DUPLICATE; + } + goto cleanup; + } + + if (conn->nonce != 0 && + (isccc_cc_lookupuint32(conn->ctrl, "_nonce", &nonce) != + ISC_R_SUCCESS || + conn->nonce != nonce)) + { + result = ISCCC_R_BADAUTH; + goto cleanup; + } + + isc_buffer_allocate(listener->mctx, &conn->text, 2 * 2048); + + if (conn->nonce == 0) { + /* + * Establish nonce. + */ + while (conn->nonce == 0) { + isc_nonce_buf(&conn->nonce, sizeof(conn->nonce)); + } + conn->result = ISC_R_SUCCESS; + control_respond(conn); + return; + } + + /* Attach the command reference */ + controlconnection_ref(conn); + + /* Trigger the command asynchronously. */ + isc_async_run(named_g_mainloop, control_command, conn); + + return; + +cleanup: + switch (result) { + case ISC_R_SHUTTINGDOWN: + case ISC_R_EOF: + break; + default: + log_invalid(&conn->ccmsg, result); + } + + conn_shutdown(conn); +} + +static void +conn_free(controlconnection_t *conn) { + /* Make sure that the connection was shutdown first */ + REQUIRE(conn->shuttingdown); + + controllistener_t *listener = conn->listener; + + isccc_ccmsg_invalidate(&conn->ccmsg); + + conn_cleanup(conn); + + if (conn->buffer != NULL) { + isc_buffer_free(&conn->buffer); + } + + ISC_LIST_UNLINK(listener->connections, conn, link); +#ifdef ENABLE_AFL + if (named_g_fuzz_type == isc_fuzz_rndc) { + named_fuzz_notify(); + } +#endif /* ifdef ENABLE_AFL */ + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3), + "freeing control connection"); + + isc_mem_put(listener->mctx, conn, sizeof(*conn)); + + controllistener_detach(&listener); +} + +static void +newconnection(controllistener_t *listener, isc_nmhandle_t *handle) { + /* Don't create new connection if we are shutting down */ + if (listener->shuttingdown) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3), + "rejected new control connection: %s", + isc_result_totext(ISC_R_SHUTTINGDOWN)); + return; + } + + controlconnection_t *conn = isc_mem_get(listener->mctx, sizeof(*conn)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_DEBUG(3), + "allocate new control connection"); + + *conn = (controlconnection_t){ + .alg = DST_ALG_UNKNOWN, + .references = ISC_REFCOUNT_INITIALIZER(1), + .listener = controllistener_ref(listener), + .link = ISC_LINK_INITIALIZER, + }; + + /* isccc_ccmsg_init() attaches to the handle */ + isccc_ccmsg_init(listener->mctx, handle, &conn->ccmsg); + + /* Set a 32 KiB upper limit on incoming message. */ + isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768); + + ISC_LIST_APPEND(listener->connections, conn, link); + + /* The reading reference has been initialized in the initializer */ + isccc_ccmsg_readmessage(&conn->ccmsg, control_recvmessage, conn); +} + +static isc_result_t +control_newconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + controllistener_t *listener = arg; + isc_sockaddr_t peeraddr; + + if (result != ISC_R_SUCCESS) { + if (result == ISC_R_SHUTTINGDOWN) { + shutdown_listener(listener); + } + return result; + } + + peeraddr = isc_nmhandle_peeraddr(handle); + if (!address_ok(&peeraddr, listener)) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING, + "rejected command channel message from %s", + socktext); + return ISC_R_FAILURE; + } + + newconnection(listener, handle); + return ISC_R_SUCCESS; +} + +static void +controls_shutdown(named_controls_t *controls) { + controllistener_t *listener = NULL; + controllistener_t *next = NULL; + + for (listener = ISC_LIST_HEAD(controls->listeners); listener != NULL; + listener = next) + { + /* + * As listeners shut down, they will call their callbacks. + */ + next = ISC_LIST_NEXT(listener, link); + shutdown_listener(listener); + } +} + +void +named_controls_shutdown(named_controls_t *controls) { + /* + * Don't ever shutdown the controls twice. + * + * NOTE: This functions is called when the server is shutting down, but + * controls_shutdown() can and will be called multiple times - on each + * reconfiguration, the listeners will be torn down and recreated again, + * see named_controls_configure() for details. + */ + if (controls->shuttingdown) { + return; + } + controls->shuttingdown = true; + + controls_shutdown(controls); +} + +static isc_result_t +cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname, + const cfg_obj_t **objp) { + const cfg_listelt_t *element = NULL; + const char *str = NULL; + const cfg_obj_t *obj = NULL; + + for (element = cfg_list_first(keylist); element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(cfg_map_getname(obj)); + if (strcasecmp(str, keyname) == 0) { + break; + } + } + if (element == NULL) { + return ISC_R_NOTFOUND; + } + obj = cfg_listelt_value(element); + *objp = obj; + return ISC_R_SUCCESS; +} + +static void +controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx, + controlkeylist_t *keyids) { + const cfg_listelt_t *element = NULL; + char *newstr = NULL; + const char *str = NULL; + const cfg_obj_t *obj = NULL; + controlkey_t *key = NULL; + + for (element = cfg_list_first(keylist); element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + newstr = isc_mem_strdup(mctx, str); + key = isc_mem_get(mctx, sizeof(*key)); + key->keyname = newstr; + key->algorithm = DST_ALG_UNKNOWN; + key->secret.base = NULL; + key->secret.length = 0; + ISC_LINK_INIT(key, link); + ISC_LIST_APPEND(*keyids, key, link); + newstr = NULL; + } +} + +static void +register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist, + controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) { + controlkey_t *keyid = NULL, *next = NULL; + const cfg_obj_t *keydef = NULL; + char secret[1024]; + isc_buffer_t b; + isc_result_t result; + + /* + * Find the keys corresponding to the keyids used by this listener. + */ + for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) { + next = ISC_LIST_NEXT(keyid, link); + + result = cfgkeylist_find(keylist, keyid->keyname, &keydef); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING, + "couldn't find key '%s' for use with " + "command channel %s", + keyid->keyname, socktext); + ISC_LIST_UNLINK(*keyids, keyid, link); + free_controlkey(keyid, mctx); + } else { + const cfg_obj_t *algobj = NULL; + const cfg_obj_t *secretobj = NULL; + const char *algstr = NULL; + const char *secretstr = NULL; + unsigned int algtype; + + (void)cfg_map_get(keydef, "algorithm", &algobj); + (void)cfg_map_get(keydef, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); + + algstr = cfg_obj_asstring(algobj); + secretstr = cfg_obj_asstring(secretobj); + + result = named_config_getkeyalgorithm(algstr, &algtype, + NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(control, named_g_lctx, + ISC_LOG_WARNING, + "unsupported algorithm '%s' in " + "key '%s' for use with command " + "channel %s", + algstr, keyid->keyname, socktext); + ISC_LIST_UNLINK(*keyids, keyid, link); + free_controlkey(keyid, mctx); + continue; + } + + keyid->algorithm = algtype; + isc_buffer_init(&b, secret, sizeof(secret)); + result = isc_base64_decodestring(secretstr, &b); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(keydef, named_g_lctx, + ISC_LOG_WARNING, + "secret for key '%s' on " + "command channel %s: %s", + keyid->keyname, socktext, + isc_result_totext(result)); + ISC_LIST_UNLINK(*keyids, keyid, link); + free_controlkey(keyid, mctx); + continue; + } + + keyid->secret.length = isc_buffer_usedlength(&b); + keyid->secret.base = isc_mem_get(mctx, + keyid->secret.length); + memmove(keyid->secret.base, isc_buffer_base(&b), + keyid->secret.length); + } + } +} + +static isc_result_t +get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { + isc_result_t result; + cfg_parser_t *pctx = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *algobj = NULL; + const cfg_obj_t *secretobj = NULL; + const char *algstr = NULL; + const char *secretstr = NULL; + controlkey_t *keyid = NULL; + char secret[1024]; + unsigned int algtype; + isc_buffer_t b; + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, + "configuring command channel from '%s'", named_g_keyfile); + if (!isc_file_exists(named_g_keyfile)) { + return ISC_R_FILENOTFOUND; + } + + CHECK(cfg_parser_create(mctx, named_g_lctx, &pctx)); + CHECK(cfg_parse_file(pctx, named_g_keyfile, &cfg_type_rndckey, + &config)); + CHECK(cfg_map_get(config, "key", &key)); + + keyid = isc_mem_get(mctx, sizeof(*keyid)); + keyid->keyname = isc_mem_strdup(mctx, + cfg_obj_asstring(cfg_map_getname(key))); + keyid->secret.base = NULL; + keyid->secret.length = 0; + keyid->algorithm = DST_ALG_UNKNOWN; + ISC_LINK_INIT(keyid, link); + if (keyid->keyname == NULL) { + CHECK(ISC_R_NOMEMORY); + } + + CHECK(isccfg_check_key(key, named_g_lctx)); + + (void)cfg_map_get(key, "algorithm", &algobj); + (void)cfg_map_get(key, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); + + algstr = cfg_obj_asstring(algobj); + secretstr = cfg_obj_asstring(secretobj); + + result = named_config_getkeyalgorithm(algstr, &algtype, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, + "unsupported algorithm '%s' in " + "key '%s' for use with command " + "channel", + algstr, keyid->keyname); + goto cleanup; + } + + keyid->algorithm = algtype; + isc_buffer_init(&b, secret, sizeof(secret)); + result = isc_base64_decodestring(secretstr, &b); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, + "secret for key '%s' on command channel: %s", + keyid->keyname, isc_result_totext(result)); + goto cleanup; + } + + keyid->secret.length = isc_buffer_usedlength(&b); + keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); + memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); + ISC_LIST_APPEND(*keyids, keyid, link); + keyid = NULL; + result = ISC_R_SUCCESS; + +cleanup: + if (keyid != NULL) { + free_controlkey(keyid, mctx); + } + if (config != NULL) { + cfg_obj_destroy(pctx, &config); + } + if (pctx != NULL) { + cfg_parser_destroy(&pctx); + } + return result; +} + +/* + * Ensures that both '*global_keylistp' and '*control_keylistp' are + * valid or both are NULL. + */ +static void +get_key_info(const cfg_obj_t *config, const cfg_obj_t *control, + const cfg_obj_t **global_keylistp, + const cfg_obj_t **control_keylistp) { + isc_result_t result; + const cfg_obj_t *control_keylist = NULL; + const cfg_obj_t *global_keylist = NULL; + + REQUIRE(global_keylistp != NULL && *global_keylistp == NULL); + REQUIRE(control_keylistp != NULL && *control_keylistp == NULL); + + control_keylist = cfg_tuple_get(control, "keys"); + + if (!cfg_obj_isvoid(control_keylist) && + cfg_list_first(control_keylist) != NULL) + { + result = cfg_map_get(config, "key", &global_keylist); + + if (result == ISC_R_SUCCESS) { + *global_keylistp = global_keylist; + *control_keylistp = control_keylist; + } + } +} + +static void +update_listener(named_controls_t *cp, controllistener_t **listenerp, + const cfg_obj_t *control, const cfg_obj_t *config, + isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, + const char *socktext, isc_socktype_t type) { + controllistener_t *listener = NULL; + const cfg_obj_t *allow = NULL; + const cfg_obj_t *global_keylist = NULL; + const cfg_obj_t *control_keylist = NULL; + dns_acl_t *new_acl = NULL; + controlkeylist_t keys; + isc_result_t result = ISC_R_SUCCESS; + + for (listener = ISC_LIST_HEAD(cp->listeners); listener != NULL; + listener = ISC_LIST_NEXT(listener, link)) + { + if (isc_sockaddr_equal(addr, &listener->address)) { + break; + } + } + + if (listener == NULL) { + *listenerp = NULL; + return; + } + + /* + * There is already a listener for this sockaddr. + * Update the access list and key information. + * + * First try to deal with the key situation. There are a few + * possibilities: + * (a) It had an explicit keylist and still has an explicit keylist. + * (b) It had an automagic key and now has an explicit keylist. + * (c) It had an explicit keylist and now needs an automagic key. + * (d) It has an automagic key and still needs the automagic key. + * + * (c) and (d) are the annoying ones. The caller needs to know + * that it should use the automagic configuration for key information + * in place of the named.conf configuration. + * + * XXXDCL There is one other hazard that has not been dealt with, + * the problem that if a key change is being caused by a control + * channel reload, then the response will be with the new key + * and not able to be decrypted by the client. + */ + if (control != NULL) { + get_key_info(config, control, &global_keylist, + &control_keylist); + } + + if (control_keylist != NULL) { + INSIST(global_keylist != NULL); + + ISC_LIST_INIT(keys); + controlkeylist_fromcfg(control_keylist, listener->mctx, &keys); + free_controlkeylist(&listener->keys, listener->mctx); + listener->keys = keys; + register_keys(control, global_keylist, &listener->keys, + listener->mctx, socktext); + } else { + free_controlkeylist(&listener->keys, listener->mctx); + result = get_rndckey(listener->mctx, &listener->keys); + } + + if (result != ISC_R_SUCCESS && global_keylist != NULL) { + /* + * This message might be a little misleading since the + * "new keys" might in fact be identical to the old ones, + * but tracking whether they are identical just for the + * sake of avoiding this message would be too much trouble. + */ + if (control != NULL) { + cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING, + "couldn't install new keys for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING, + "couldn't install new keys for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + } + } + + /* + * Now, keep the old access list unless a new one can be made. + */ + if (control != NULL && type == isc_socktype_tcp) { + allow = cfg_tuple_get(control, "allow"); + result = cfg_acl_fromconfig(allow, config, named_g_lctx, + aclconfctx, listener->mctx, 0, + &new_acl); + } else { + result = dns_acl_any(listener->mctx, &new_acl); + } + + if (control != NULL) { + const cfg_obj_t *readonly = NULL; + + readonly = cfg_tuple_get(control, "read-only"); + if (!cfg_obj_isvoid(readonly)) { + listener->readonly = cfg_obj_asboolean(readonly); + } + } + + if (result == ISC_R_SUCCESS) { + dns_acl_detach(&listener->acl); + dns_acl_attach(new_acl, &listener->acl); + dns_acl_detach(&new_acl); + /* XXXDCL say the old acl is still used? */ + } else if (control != NULL) { + cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING, + "couldn't install new acl for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING, + "couldn't install new acl for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + } + + *listenerp = listener; +} + +static void +add_listener(named_controls_t *cp, controllistener_t **listenerp, + const cfg_obj_t *control, const cfg_obj_t *config, + isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, + const char *socktext, isc_socktype_t type) { + isc_mem_t *mctx = cp->server->mctx; + controllistener_t *listener = NULL; + const cfg_obj_t *allow = NULL; + const cfg_obj_t *global_keylist = NULL; + const cfg_obj_t *control_keylist = NULL; + dns_acl_t *new_acl = NULL; + isc_result_t result = ISC_R_SUCCESS; + int pf; + + /* Don't create new listener if we are shutting down */ + if (cp->shuttingdown) { + result = ISC_R_SHUTTINGDOWN; + goto shuttingdown; + } + + listener = isc_mem_get(mctx, sizeof(*listener)); + *listener = (controllistener_t){ .controls = cp, + .address = *addr, + .type = type }; + isc_mem_attach(mctx, &listener->mctx); + ISC_LINK_INIT(listener, link); + ISC_LIST_INIT(listener->keys); + ISC_LIST_INIT(listener->connections); + isc_refcount_init(&listener->references, 1); + + /* + * Make the ACL. + */ + if (control != NULL && type == isc_socktype_tcp) { + const cfg_obj_t *readonly = NULL; + + allow = cfg_tuple_get(control, "allow"); + CHECK(cfg_acl_fromconfig(allow, config, named_g_lctx, + aclconfctx, mctx, 0, &new_acl)); + + readonly = cfg_tuple_get(control, "read-only"); + if (!cfg_obj_isvoid(readonly)) { + listener->readonly = cfg_obj_asboolean(readonly); + } + } else { + CHECK(dns_acl_any(mctx, &new_acl)); + } + + dns_acl_attach(new_acl, &listener->acl); + dns_acl_detach(&new_acl); + + if (config != NULL) { + get_key_info(config, control, &global_keylist, + &control_keylist); + } + + if (control_keylist != NULL) { + controlkeylist_fromcfg(control_keylist, listener->mctx, + &listener->keys); + register_keys(control, global_keylist, &listener->keys, + listener->mctx, socktext); + } else { + result = get_rndckey(mctx, &listener->keys); + if (result != ISC_R_SUCCESS && control != NULL) { + cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING, + "couldn't install keys for " + "command channel %s: %s", + socktext, isc_result_totext(result)); + } + } + + pf = isc_sockaddr_pf(&listener->address); + if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || + (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) + { + CHECK(ISC_R_FAMILYNOSUPPORT); + } + + CHECK(isc_nm_listentcp(named_g_netmgr, ISC_NM_LISTEN_ONE, + &listener->address, control_newconn, listener, 5, + NULL, &listener->sock)); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE, + "command channel listening on %s", socktext); + *listenerp = listener; + return; + +cleanup: + isc_refcount_decrement(&listener->references); + listener->shuttingdown = true; + free_listener(listener); + +shuttingdown: + if (control != NULL) { + cfg_obj_log(control, named_g_lctx, ISC_LOG_WARNING, + "couldn't add command channel %s: %s", socktext, + isc_result_totext(result)); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_NOTICE, + "couldn't add command channel %s: %s", socktext, + isc_result_totext(result)); + } + + *listenerp = NULL; +} + +isc_result_t +named_controls_configure(named_controls_t *cp, const cfg_obj_t *config, + cfg_aclconfctx_t *aclconfctx) { + controllistener_t *listener = NULL; + controllistenerlist_t new_listeners; + const cfg_obj_t *controlslist = NULL; + const cfg_listelt_t *element, *element2; + char socktext[ISC_SOCKADDR_FORMATSIZE]; + + ISC_LIST_INIT(new_listeners); + + /* + * Get the list of named.conf 'controls' statements. + */ + (void)cfg_map_get(config, "controls", &controlslist); + + /* + * Run through the new control channel list, noting sockets that + * are already being listened on and moving them to the new list. + * + * Identifying duplicate addr/port combinations is left to either + * the underlying config code, or to the bind attempt getting an + * address-in-use error. + */ + if (controlslist != NULL) { + for (element = cfg_list_first(controlslist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *controls = NULL; + const cfg_obj_t *inetcontrols = NULL; + const cfg_obj_t *unixcontrols = NULL; + + controls = cfg_listelt_value(element); + + (void)cfg_map_get(controls, "unix", &unixcontrols); + if (unixcontrols != NULL) { + cfg_obj_log(controls, named_g_lctx, + ISC_LOG_ERROR, + "UNIX domain sockets are not " + "supported"); + return ISC_R_FAILURE; + } + + (void)cfg_map_get(controls, "inet", &inetcontrols); + if (inetcontrols == NULL) { + continue; + } + + for (element2 = cfg_list_first(inetcontrols); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + const cfg_obj_t *control = NULL; + const cfg_obj_t *obj = NULL; + isc_sockaddr_t addr; + + /* + * The parser handles BIND 8 configuration file + * syntax, so it allows inet phrases with no + * keys{} clause. + */ + control = cfg_listelt_value(element2); + + obj = cfg_tuple_get(control, "address"); + addr = *cfg_obj_assockaddr(obj); + if (isc_sockaddr_getport(&addr) == 0) { + isc_sockaddr_setport( + &addr, NAMED_CONTROL_PORT); + } + + isc_sockaddr_format(&addr, socktext, + sizeof(socktext)); + + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, + ISC_LOG_DEBUG(9), + "processing control channel %s", + socktext); + + update_listener(cp, &listener, control, config, + &addr, aclconfctx, socktext, + isc_socktype_tcp); + + if (listener != NULL) { + /* + * Remove the listener from the old + * list, so it won't be shut down. + */ + ISC_LIST_UNLINK(cp->listeners, listener, + link); + } else { + /* + * This is a new listener. + */ + add_listener(cp, &listener, control, + config, &addr, aclconfctx, + socktext, + isc_socktype_tcp); + } + + if (listener != NULL) { + ISC_LIST_APPEND(new_listeners, listener, + link); + } + } + } + } else { + int i; + + for (i = 0; i < 2; i++) { + isc_sockaddr_t addr; + + if (i == 0) { + struct in_addr localhost; + + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + continue; + } + localhost.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(&addr, &localhost, 0); + } else { + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + continue; + } + isc_sockaddr_fromin6(&addr, &in6addr_loopback, + 0); + } + isc_sockaddr_setport(&addr, NAMED_CONTROL_PORT); + + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + + update_listener(cp, &listener, NULL, NULL, &addr, NULL, + socktext, isc_socktype_tcp); + + if (listener != NULL) { + /* + * Remove the listener from the old + * list, so it won't be shut down. + */ + ISC_LIST_UNLINK(cp->listeners, listener, link); + } else { + /* + * This is a new listener. + */ + add_listener(cp, &listener, NULL, NULL, &addr, + NULL, socktext, isc_socktype_tcp); + } + + if (listener != NULL) { + ISC_LIST_APPEND(new_listeners, listener, link); + } + } + } + + /* + * named_control_shutdown() will stop whatever is on the global + * listeners list, which currently only has whatever sockaddrs + * were in the previous configuration (if any) that do not + * remain in the current configuration. + */ + controls_shutdown(cp); + + /* + * Put all of the valid listeners on the listeners list. + * Anything already on listeners in the process of shutting + * down will be taken care of by listen_done(). + */ + ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); + return ISC_R_SUCCESS; +} + +isc_result_t +named_controls_create(named_server_t *server, named_controls_t **ctrlsp) { + isc_mem_t *mctx = server->mctx; + isc_result_t result; + named_controls_t *controls = isc_mem_get(mctx, sizeof(*controls)); + + *controls = (named_controls_t){ + .server = server, + }; + + ISC_LIST_INIT(controls->listeners); + + isc_mutex_init(&controls->symtab_lock); + LOCK(&controls->symtab_lock); + result = isccc_cc_createsymtab(&controls->symtab); + UNLOCK(&controls->symtab_lock); + + if (result != ISC_R_SUCCESS) { + isc_mutex_destroy(&controls->symtab_lock); + isc_mem_put(server->mctx, controls, sizeof(*controls)); + return result; + } + *ctrlsp = controls; + return ISC_R_SUCCESS; +} + +void +named_controls_destroy(named_controls_t **ctrlsp) { + named_controls_t *controls = *ctrlsp; + *ctrlsp = NULL; + + REQUIRE(controls->shuttingdown); + REQUIRE(ISC_LIST_EMPTY(controls->listeners)); + + LOCK(&controls->symtab_lock); + isccc_symtab_destroy(&controls->symtab); + UNLOCK(&controls->symtab_lock); + isc_mutex_destroy(&controls->symtab_lock); + isc_mem_put(controls->server->mctx, controls, sizeof(*controls)); +} diff --git a/bin/named/dlz_dlopen_driver.c b/bin/named/dlz_dlopen_driver.c new file mode 100644 index 0000000..5e67555 --- /dev/null +++ b/bin/named/dlz_dlopen_driver.c @@ -0,0 +1,550 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static dns_sdlzimplementation_t *dlz_dlopen = NULL; + +typedef struct dlopen_data { + isc_mem_t *mctx; + char *dl_path; + char *dlzname; + uv_lib_t dl_handle; + void *dbdata; + unsigned int flags; + isc_mutex_t lock; + int version; + bool in_configure; + + dlz_dlopen_version_t *dlz_version; + dlz_dlopen_create_t *dlz_create; + dlz_dlopen_findzonedb_t *dlz_findzonedb; + dlz_dlopen_lookup_t *dlz_lookup; + dlz_dlopen_authority_t *dlz_authority; + dlz_dlopen_allnodes_t *dlz_allnodes; + dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr; + dlz_dlopen_newversion_t *dlz_newversion; + dlz_dlopen_closeversion_t *dlz_closeversion; + dlz_dlopen_configure_t *dlz_configure; + dlz_dlopen_ssumatch_t *dlz_ssumatch; + dlz_dlopen_addrdataset_t *dlz_addrdataset; + dlz_dlopen_subrdataset_t *dlz_subrdataset; + dlz_dlopen_delrdataset_t *dlz_delrdataset; + dlz_dlopen_destroy_t *dlz_destroy; +} dlopen_data_t; + +/* Modules can choose whether they are lock-safe or not. */ +#define MAYBE_LOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + !cd->in_configure) \ + LOCK(&cd->lock); \ + } while (0) + +#define MAYBE_UNLOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + !cd->in_configure) \ + UNLOCK(&cd->lock); \ + } while (0) + +/* + * Log a message at the given level. + */ +static void +dlopen_log(int level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, + ISC_LOG_DEBUG(level), fmt, ap); + va_end(ap); +} + +/* + * SDLZ methods + */ + +static isc_result_t +dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, + dns_sdlzallnodes_t *allnodes) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_allnodes == NULL) { + return ISC_R_NOPERM; + } + + MAYBE_LOCK(cd); + result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); + MAYBE_UNLOCK(cd); + return result; +} + +static isc_result_t +dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, + const char *client) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_allowzonexfr == NULL) { + return ISC_R_NOPERM; + } + + MAYBE_LOCK(cd); + result = cd->dlz_allowzonexfr(cd->dbdata, name, client); + MAYBE_UNLOCK(cd); + return result; +} + +static isc_result_t +dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, + dns_sdlzlookup_t *lookup) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_authority == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + MAYBE_LOCK(cd); + result = cd->dlz_authority(zone, cd->dbdata, lookup); + MAYBE_UNLOCK(cd); + return result; +} + +static isc_result_t +dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo); + MAYBE_UNLOCK(cd); + return result; +} + +static isc_result_t +dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, + void *dbdata, dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods, + clientinfo); + MAYBE_UNLOCK(cd); + return result; +} + +/* + * Load a symbol from the library + */ +static void * +dl_load_symbol(dlopen_data_t *cd, const char *symbol, bool mandatory) { + void *ptr = NULL; + int r = uv_dlsym(&cd->dl_handle, symbol, &ptr); + if (r != 0) { + const char *errmsg = uv_dlerror(&cd->dl_handle); + if (errmsg == NULL) { + errmsg = "returned function pointer is NULL"; + } + if (mandatory) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: library '%s' is missing " + "required symbol '%s': %s", + cd->dl_path, symbol, errmsg); + } + } + + return ptr; +} + +static void +dlopen_dlz_destroy(void *driverarg, void *dbdata); + +/* + * Called at startup for each dlopen zone in named.conf + */ +static isc_result_t +dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], + void *driverarg, void **dbdata) { + dlopen_data_t *cd; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_FAILURE; + int r; + + UNUSED(driverarg); + + if (argc < 2) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen driver for '%s' needs a path to " + "the shared library", + dlzname); + return ISC_R_FAILURE; + } + + isc_mem_create(&mctx); + cd = isc_mem_get(mctx, sizeof(*cd)); + *cd = (dlopen_data_t){ + .mctx = mctx, + .dl_path = isc_mem_strdup(mctx, argv[1]), + .dlzname = isc_mem_strdup(mctx, dlzname), + }; + + /* Initialize the lock */ + isc_mutex_init(&cd->lock); + + r = uv_dlopen(cd->dl_path, &cd->dl_handle); + if (r != 0) { + const char *errmsg = uv_dlerror(&cd->dl_handle); + if (errmsg == NULL) { + errmsg = "unknown error"; + } + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen failed to open library '%s': %s", + cd->dl_path, errmsg); + result = ISC_R_FAILURE; + goto failed; + } + + /* Find the symbols */ + cd->dlz_version = + (dlz_dlopen_version_t *)dl_load_symbol(cd, "dlz_version", true); + cd->dlz_create = (dlz_dlopen_create_t *)dl_load_symbol(cd, "dlz_create", + true); + cd->dlz_lookup = (dlz_dlopen_lookup_t *)dl_load_symbol(cd, "dlz_lookup", + true); + cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)dl_load_symbol( + cd, "dlz_findzonedb", true); + + if (cd->dlz_create == NULL || cd->dlz_version == NULL || + cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) + { + /* We're missing a required symbol */ + result = ISC_R_FAILURE; + goto failed; + } + + cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)dl_load_symbol( + cd, "dlz_allowzonexfr", false); + cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)dl_load_symbol( + cd, "dlz_allnodes", (cd->dlz_allowzonexfr != NULL)); + cd->dlz_authority = (dlz_dlopen_authority_t *)dl_load_symbol( + cd, "dlz_authority", false); + cd->dlz_newversion = (dlz_dlopen_newversion_t *)dl_load_symbol( + cd, "dlz_newversion", false); + cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)dl_load_symbol( + cd, "dlz_closeversion", (cd->dlz_newversion != NULL)); + cd->dlz_configure = (dlz_dlopen_configure_t *)dl_load_symbol( + cd, "dlz_configure", false); + cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)dl_load_symbol( + cd, "dlz_ssumatch", false); + cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)dl_load_symbol( + cd, "dlz_addrdataset", false); + cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)dl_load_symbol( + cd, "dlz_subrdataset", false); + cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)dl_load_symbol( + cd, "dlz_delrdataset", false); + cd->dlz_destroy = (dlz_dlopen_destroy_t *)dl_load_symbol( + cd, "dlz_destroy", false); + + /* Check the version of the API is the same */ + cd->version = cd->dlz_version(&cd->flags); + if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || + cd->version > DLZ_DLOPEN_VERSION) + { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: %s: incorrect driver API version %d, " + "requires %d", + cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); + result = ISC_R_FAILURE; + goto failed; + } + + /* + * Call the library's create function. Note that this is an + * extended version of dlz create, with the addition of + * named function pointers for helper functions that the + * driver will need. This avoids the need for the backend to + * link the BIND9 libraries + */ + MAYBE_LOCK(cd); + result = cd->dlz_create(dlzname, argc - 1, argv + 1, &cd->dbdata, "log", + dlopen_log, "putrr", dns_sdlz_putrr, + "putnamedrr", dns_sdlz_putnamedrr, + "writeable_zone", dns_dlz_writeablezone, NULL); + MAYBE_UNLOCK(cd); + if (result != ISC_R_SUCCESS) { + goto failed; + } + + *dbdata = cd; + + return ISC_R_SUCCESS; + +failed: + dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); + + dlopen_dlz_destroy(NULL, cd); + + return result; +} + +/* + * Called when bind is shutting down + */ +static void +dlopen_dlz_destroy(void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + + UNUSED(driverarg); + + if (cd->dlz_destroy && cd->dbdata) { + MAYBE_LOCK(cd); + cd->dlz_destroy(cd->dbdata); + MAYBE_UNLOCK(cd); + } + + uv_dlclose(&cd->dl_handle); + isc_mutex_destroy(&cd->lock); + isc_mem_free(cd->mctx, cd->dl_path); + isc_mem_free(cd->mctx, cd->dlzname); + isc_mem_putanddetach(&cd->mctx, cd, sizeof(*cd)); +} + +/* + * Called to start a transaction + */ +static isc_result_t +dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, + void **versionp) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + MAYBE_LOCK(cd); + result = cd->dlz_newversion(zone, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); + return result; +} + +/* + * Called to end a transaction + */ +static void +dlopen_dlz_closeversion(const char *zone, bool commit, void *driverarg, + void *dbdata, void **versionp) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) { + *versionp = NULL; + return; + } + + MAYBE_LOCK(cd); + cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); +} + +/* + * Called on startup to configure any writeable zones + */ +static isc_result_t +dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg, + void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_configure == NULL) { + return ISC_R_SUCCESS; + } + + MAYBE_LOCK(cd); + cd->in_configure = true; + result = cd->dlz_configure(view, dlzdb, cd->dbdata); + cd->in_configure = false; + MAYBE_UNLOCK(cd); + + return result; +} + +/* + * Check for authority to change a name. + */ +static bool +dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, + unsigned char *keydata, void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + bool ret; + + UNUSED(driverarg); + + if (cd->dlz_ssumatch == NULL) { + return false; + } + + MAYBE_LOCK(cd); + ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, + keydata, cd->dbdata); + MAYBE_UNLOCK(cd); + + return ret; +} + +/* + * Add an rdataset. + */ +static isc_result_t +dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_addrdataset == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + MAYBE_LOCK(cd); + result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return result; +} + +/* + * Subtract an rdataset. + */ +static isc_result_t +dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_subrdataset == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + MAYBE_LOCK(cd); + result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return result; +} + +/* + * Delete a rdataset. + */ +static isc_result_t +dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_delrdataset == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + MAYBE_LOCK(cd); + result = cd->dlz_delrdataset(name, type, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return result; +} + +static dns_sdlzmethods_t dlz_dlopen_methods = { + dlopen_dlz_create, dlopen_dlz_destroy, dlopen_dlz_findzonedb, + dlopen_dlz_lookup, dlopen_dlz_authority, dlopen_dlz_allnodes, + dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion, + dlopen_dlz_configure, dlopen_dlz_ssumatch, dlopen_dlz_addrdataset, + dlopen_dlz_subrdataset, dlopen_dlz_delrdataset +}; + +/* + * Register driver with BIND + */ +isc_result_t +dlz_dlopen_init(isc_mem_t *mctx) { + isc_result_t result; + + dlopen_log(2, "Registering DLZ_dlopen driver"); + + result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, + DNS_SDLZFLAG_RELATIVEOWNER | + DNS_SDLZFLAG_RELATIVERDATA | + DNS_SDLZFLAG_THREADSAFE, + mctx, &dlz_dlopen); + + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR("dns_sdlzregister() failed: %s", + isc_result_totext(result)); + result = ISC_R_UNEXPECTED; + } + + return result; +} + +/* + * Unregister the driver + */ +void +dlz_dlopen_clear(void) { + dlopen_log(2, "Unregistering DLZ_dlopen driver"); + if (dlz_dlopen != NULL) { + dns_sdlzunregister(&dlz_dlopen); + } +} diff --git a/bin/named/fuzz.c b/bin/named/fuzz.c new file mode 100644 index 0000000..3133f54 --- /dev/null +++ b/bin/named/fuzz.c @@ -0,0 +1,782 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include + +#include + +#ifdef ENABLE_AFL +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* + * We are using pthreads directly because we might be using it with + * unthreaded version of BIND, where all thread functions are + * mocks. Since AFL for now only works on Linux it's not a problem. + */ +static pthread_cond_t cond; +static pthread_mutex_t mutex; +static bool ready; + +/* + * In "client:" mode, this thread reads fuzzed query messages from AFL + * from standard input and sends it to named's listening port (DNS) that + * is passed in the -A client:
: option. It can be used to + * test named from the client side. + */ +static void * +fuzz_thread_client(void *arg) { + char *host; + char *port; + struct sockaddr_in servaddr; + int sockfd; + void *buf; + + UNUSED(arg); + + /* + * Parse named -A argument in the "address:port" syntax. Due to + * the syntax used, this only supports IPv4 addresses. + */ + host = strdup(named_g_fuzz_addr); + RUNTIME_CHECK(host != NULL); + + port = strchr(host, ':'); + RUNTIME_CHECK(port != NULL); + *port = 0; + ++port; + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1); + servaddr.sin_port = htons(atoi(port)); + + free(host); + + /* + * Wait for named to start. This is set in run_server() in the + * named thread. + */ + while (!named_g_run_done) { + usleep(10000); + } + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + RUNTIME_CHECK(sockfd != -1); + + buf = malloc(65536); + RUNTIME_CHECK(buf != NULL); + + /* + * Processing fuzzed packets 100,000 times before shutting down + * the app. + */ +#ifdef __AFL_LOOP + for (int loop = 0; loop < 100000; loop++) { +#else /* ifdef __AFL_LOOP */ + { +#endif /* ifdef __AFL_LOOP */ + ssize_t length; + ssize_t sent; + + length = read(0, buf, 65536); + if (length <= 0) { + usleep(1000000); + goto next; + } + + /* + * Ignore packets that are larger than 4096 bytes. + */ + if (length > 4096) { + /* + * AFL_CMIN doesn't support persistent mode, so + * shutdown the server. + */ + if (getenv("AFL_CMIN")) { + free(buf); + close(sockfd); + named_server_flushonshutdown(named_g_server, + false); + isc_loopmgr_shutdown(named_g_loopmgr); + return NULL; + } + raise(SIGSTOP); + goto next; + } + + RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); + + ready = false; + + sent = sendto(sockfd, buf, length, 0, + (struct sockaddr *)&servaddr, sizeof(servaddr)); + RUNTIME_CHECK(sent == length); + + /* + * Read the reply message from named to unclog it. Don't + * bother if there isn't a reply. + */ + (void)recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL); + + while (!ready) { + pthread_cond_wait(&cond, &mutex); + } + + RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); + next:; + } + + free(buf); + close(sockfd); + + named_server_flushonshutdown(named_g_server, false); + isc_loopmgr_shutdown(named_g_loopmgr); + + return NULL; +} + +/* + * In "resolver:" mode, this thread reads fuzzed reply messages from AFL + * from standard input. It also sets up a listener as a remote + * authoritative server and sends a driver query to the client side of + * named(resolver). When named(resolver) connects to this authoritative + * server, this thread writes the fuzzed reply message from AFL to it. + * + * -A resolver:::: + * + * Here, : is where named(resolver) is listening on. + * : is where the thread is supposed to setup the + * authoritative server. This address should be configured via the root + * zone to be the authoritiative server for aaaaaaaaaa.example. + * + * named(resolver) when being fuzzed will not cache answers. + */ +static void * +fuzz_thread_resolver(void *arg) { + char *sqtype, *shost, *sport, *rhost, *rport; + struct sockaddr_in servaddr, recaddr, recvaddr; + /* + * Query for aaaaaaaaaa.example./A in wire format with RD=1, + * EDNS and DO=1. 0x88, 0x0c at the start is the ID field which + * will be updated for each query. + */ + char respacket[] = { 0x88, 0x0c, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0a, 0x61, 0x61, 0x61, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x07, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }; + /* + * Response for example./DNSKEY in wire format. Note that RRSIGs + * were generated with this DNSKEY that are used as seeds for + * AFL in the DNSSEC fuzzing job. So the DNSKEY content of this + * message must not change, or the corresponding RRSIGs will + * have to be updated. 0x8d, 0xf6 at the start is the ID field + * which will be made to match the query. + */ + const uint8_t dnskey_wf[] = { + 0x8d, 0xf6, 0x84, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x01, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x00, 0x00, 0x30, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x30, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x08, 0x01, 0x00, 0x03, + 0x08, 0x03, 0x01, 0x00, 0x01, 0xbd, 0x81, 0xdc, 0x7f, 0x16, + 0xd4, 0x81, 0x7c, 0x1f, 0x9f, 0x6a, 0x68, 0xdd, 0xd4, 0xda, + 0x48, 0xd9, 0x1c, 0xbd, 0xa6, 0x46, 0x1a, 0xf0, 0xb4, 0xb9, + 0xec, 0x3d, 0x6c, 0x0b, 0x57, 0xc7, 0xd6, 0x54, 0x66, 0xe6, + 0x6c, 0xd5, 0x90, 0x3a, 0x78, 0x7d, 0x7f, 0x78, 0x80, 0xa2, + 0x89, 0x61, 0x6d, 0x8a, 0x2b, 0xcd, 0x0a, 0x77, 0x7a, 0xad, + 0xc9, 0x61, 0x53, 0x53, 0x8c, 0x99, 0x72, 0x86, 0x14, 0x74, + 0x9c, 0x49, 0x2a, 0x47, 0x23, 0xf7, 0x02, 0x07, 0x73, 0x1c, + 0x5c, 0x2e, 0xb4, 0x9a, 0xa4, 0xd7, 0x98, 0x42, 0xc3, 0xd2, + 0xfe, 0xbf, 0xf3, 0xb3, 0x6a, 0x52, 0x92, 0xd5, 0xfa, 0x47, + 0x00, 0xe3, 0xd9, 0x59, 0x31, 0x95, 0x48, 0x40, 0xfc, 0x06, + 0x73, 0x90, 0xc6, 0x73, 0x96, 0xba, 0x29, 0x91, 0xe2, 0xac, + 0xa3, 0xa5, 0x6d, 0x91, 0x6d, 0x52, 0xb9, 0x34, 0xba, 0x68, + 0x4f, 0xad, 0xf0, 0xc3, 0xf3, 0x1d, 0x6d, 0x61, 0x76, 0xe5, + 0x3d, 0xa3, 0x9b, 0x2a, 0x0c, 0x92, 0xb3, 0x78, 0x6b, 0xf1, + 0x20, 0xd6, 0x90, 0xb7, 0xac, 0xe2, 0xf8, 0x2b, 0x94, 0x10, + 0x79, 0xce, 0xa8, 0x60, 0x42, 0xea, 0x6a, 0x18, 0x2f, 0xc0, + 0xd8, 0x05, 0x0a, 0x3b, 0x06, 0x0f, 0x02, 0x7e, 0xff, 0x33, + 0x46, 0xee, 0xb6, 0x21, 0x25, 0x90, 0x63, 0x4b, 0x3b, 0x5e, + 0xb2, 0x72, 0x3a, 0xcb, 0x91, 0x41, 0xf4, 0x20, 0x50, 0x78, + 0x1c, 0x93, 0x95, 0xda, 0xfa, 0xae, 0x85, 0xc5, 0xd7, 0x6b, + 0x92, 0x0c, 0x70, 0x6b, 0xe4, 0xb7, 0x29, 0x3a, 0x2e, 0x18, + 0x88, 0x82, 0x33, 0x7c, 0xa8, 0xea, 0xb8, 0x31, 0x8f, 0xaf, + 0x50, 0xc5, 0x9c, 0x08, 0x56, 0x8f, 0x09, 0x76, 0x4e, 0xdf, + 0x97, 0x75, 0x9d, 0x00, 0x52, 0x7f, 0xdb, 0xec, 0x30, 0xcb, + 0x1c, 0x4c, 0x2a, 0x21, 0x93, 0xc4, 0x6d, 0x85, 0xa9, 0x40, + 0x3b, 0xc0, 0x0c, 0x00, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x01, + 0x2c, 0x01, 0x1b, 0x00, 0x30, 0x08, 0x01, 0x00, 0x00, 0x01, + 0x2c, 0x67, 0x74, 0x85, 0x80, 0x58, 0xb3, 0xc5, 0x17, 0x36, + 0x90, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, + 0x45, 0xac, 0xd3, 0x82, 0x69, 0xf3, 0x10, 0x3a, 0x97, 0x2c, + 0x6a, 0xa9, 0x78, 0x99, 0xea, 0xb0, 0xcc, 0xf7, 0xaf, 0x33, + 0x51, 0x5b, 0xdf, 0x77, 0x04, 0x18, 0x14, 0x99, 0x61, 0xeb, + 0x8d, 0x76, 0x3f, 0xd1, 0x71, 0x14, 0x43, 0x80, 0x53, 0xc2, + 0x3b, 0x9f, 0x09, 0x4f, 0xb3, 0x51, 0x04, 0x89, 0x0e, 0xc8, + 0x54, 0x12, 0xcd, 0x07, 0x20, 0xbe, 0x94, 0xc2, 0xda, 0x99, + 0xdd, 0x1e, 0xf8, 0xb0, 0x84, 0x2e, 0xf9, 0x19, 0x35, 0x36, + 0xf5, 0xd0, 0x5d, 0x82, 0x18, 0x74, 0xa0, 0x00, 0xb6, 0x15, + 0x57, 0x40, 0x5f, 0x78, 0x2d, 0x27, 0xac, 0xc7, 0x8a, 0x29, + 0x55, 0xa9, 0xcd, 0xbc, 0xf7, 0x3e, 0xff, 0xae, 0x1a, 0x5a, + 0x1d, 0xac, 0x0d, 0x78, 0x0e, 0x08, 0x33, 0x6c, 0x59, 0x70, + 0x40, 0xb9, 0x65, 0xbd, 0x35, 0xbb, 0x9a, 0x70, 0xdc, 0x93, + 0x66, 0xb0, 0xef, 0xfe, 0xf0, 0x32, 0xa6, 0xee, 0xb7, 0x03, + 0x89, 0xa2, 0x4d, 0xe0, 0xf1, 0x20, 0xdf, 0x39, 0xe8, 0xe3, + 0xcc, 0x95, 0xe9, 0x9a, 0xad, 0xbf, 0xbd, 0x7c, 0xf7, 0xd7, + 0xde, 0x47, 0x9e, 0xf6, 0x17, 0xbb, 0x84, 0xa9, 0xed, 0xf2, + 0x45, 0x61, 0x6d, 0x13, 0x0b, 0x06, 0x29, 0x50, 0xde, 0xfd, + 0x42, 0xb0, 0x66, 0x2c, 0x1c, 0x2b, 0x63, 0xcb, 0x4e, 0xb9, + 0x31, 0xc4, 0xea, 0xd2, 0x07, 0x3a, 0x08, 0x79, 0x19, 0x4b, + 0x4c, 0x50, 0x97, 0x02, 0xd7, 0x26, 0x41, 0x2f, 0xdd, 0x57, + 0xaa, 0xb0, 0xa0, 0x21, 0x4e, 0x74, 0xb6, 0x97, 0x4b, 0x8b, + 0x09, 0x9c, 0x3d, 0x29, 0xfb, 0x12, 0x27, 0x47, 0x8f, 0xb8, + 0xc5, 0x8e, 0x65, 0xcd, 0xca, 0x2f, 0xba, 0xf5, 0x3e, 0xec, + 0x56, 0xc3, 0xc9, 0xa1, 0x62, 0x7d, 0xf2, 0x9f, 0x90, 0x16, + 0x1d, 0xbf, 0x97, 0x28, 0xe1, 0x92, 0xb1, 0x53, 0xab, 0xc4, + 0xe0, 0x99, 0xbb, 0x19, 0x90, 0x7c, 0x00, 0x00, 0x29, 0x10, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 + }; + + int sockfd; + int listenfd; + int loop; + uint16_t qtype; + char *buf, *rbuf; + char *nameptr; + unsigned int i; + uint8_t llen; + uint64_t seed; + + UNUSED(arg); + + /* + * Parse named -A argument in the "qtype:saddress:sport:raddress:rport" + * syntax. Due to the syntax used, this only supports IPv4 addresses. + */ + sqtype = strdup(named_g_fuzz_addr); + RUNTIME_CHECK(sqtype != NULL); + + shost = strchr(sqtype, ':'); + RUNTIME_CHECK(shost != NULL); + *shost = 0; + shost++; + + sport = strchr(shost, ':'); + RUNTIME_CHECK(sport != NULL); + *sport = 0; + sport++; + + rhost = strchr(sport, ':'); + RUNTIME_CHECK(rhost != NULL); + *rhost = 0; + rhost++; + + rport = strchr(rhost, ':'); + RUNTIME_CHECK(rport != NULL); + *rport = 0; + rport++; + + /* + * Patch in the qtype into the question section of respacket. + */ + qtype = atoi(sqtype); + respacket[32] = (qtype >> 8) & 0xff; + respacket[33] = qtype & 0xff; + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + RUNTIME_CHECK(inet_pton(AF_INET, shost, &servaddr.sin_addr) == 1); + servaddr.sin_port = htons(atoi(sport)); + + memset(&recaddr, 0, sizeof(recaddr)); + recaddr.sin_family = AF_INET; + RUNTIME_CHECK(inet_pton(AF_INET, rhost, &recaddr.sin_addr) == 1); + recaddr.sin_port = htons(atoi(rport)); + + free(sqtype); + + /* + * Wait for named to start. This is set in run_server() in the + * named thread. + */ + while (!named_g_run_done) { + usleep(10000); + } + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + RUNTIME_CHECK(sockfd != -1); + + listenfd = socket(AF_INET, SOCK_DGRAM, 0); + RUNTIME_CHECK(listenfd != -1); + + RUNTIME_CHECK(bind(listenfd, (struct sockaddr *)&recaddr, + sizeof(struct sockaddr_in)) == 0); + + buf = malloc(65536); + rbuf = malloc(65536); + RUNTIME_CHECK(buf != NULL); + RUNTIME_CHECK(rbuf != NULL); + + seed = 42; + + /* + * Processing fuzzed packets 100,000 times before shutting down + * the app. + */ + for (loop = 0; loop < 100000; loop++) { + ssize_t length; + ssize_t sent; + unsigned short id; + socklen_t socklen; + + memset(buf, 0, 12); + length = read(0, buf, 65536); + if (length <= 0) { + usleep(1000000); + continue; + } + + if (length > 4096) { + if (getenv("AFL_CMIN")) { + free(buf); + free(rbuf); + close(sockfd); + close(listenfd); + named_server_flushonshutdown(named_g_server, + false); + isc_loopmgr_shutdown(named_g_loopmgr); + return NULL; + } + raise(SIGSTOP); + continue; + } + + if (length < 12) { + length = 12; + } + + RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); + + ready = false; + + /* Use a unique query ID. */ + seed = 1664525 * seed + 1013904223; + id = seed & 0xffff; + respacket[0] = (id >> 8) & 0xff; + respacket[1] = id & 0xff; + + /* + * Flush any pending data on the authoritative server. + */ + socklen = sizeof(recvaddr); + (void)recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT, + (struct sockaddr *)&recvaddr, &socklen); + + /* + * Send a fixed client query to named(resolver) of + * aaaaaaaaaa.example./A. This is the starting query + * driver. + */ + sent = sendto(sockfd, respacket, sizeof(respacket), 0, + (struct sockaddr *)&servaddr, sizeof(servaddr)); + RUNTIME_CHECK(sent == sizeof(respacket)); + + /* + * named(resolver) will process the query above and send + * an upstream query to the authoritative server. We + * handle that here as the upstream authoritative server + * on listenfd. + */ + socklen = sizeof(recvaddr); + sent = recvfrom(listenfd, rbuf, 65536, 0, + (struct sockaddr *)&recvaddr, &socklen); + RUNTIME_CHECK(sent > 0); + + /* + * Copy QID and set QR so that response is always + * accepted by named(resolver). + */ + buf[0] = rbuf[0]; + buf[1] = rbuf[1]; + buf[2] |= 0x80; + + /* + * NOTE: We are not copying the QNAME or setting + * rcode=NOERROR each time. So the resolver may fail the + * client query (driver) / wander due to this. AA flag + * may also not be set based on the contents of the AFL + * fuzzed packet. + */ + + /* + * A hack - set QTYPE to the one from query so that we + * can easily share packets between instances. If we + * write over something else we'll get FORMERR anyway. + */ + + /* Skip DNS header to get to the name */ + nameptr = buf + 12; + + /* Skip the name to get to the qtype */ + i = 0; + while (((llen = nameptr[i]) != 0) && (i < 255) && + (((nameptr + i + 1 + llen) - buf) < length)) + { + i += 1 + llen; + } + + if (i <= 255) { + nameptr += 1 + i; + /* Patch the qtype */ + if ((nameptr - buf) < (length - 2)) { + *nameptr++ = (qtype >> 8) & 0xff; + *nameptr++ = qtype & 0xff; + } + /* Patch the qclass */ + if ((nameptr - buf) < (length - 2)) { + *nameptr++ = 0; + *nameptr++ = 1; + } + } + + /* + * Send the reply to named(resolver). + */ + sent = sendto(listenfd, buf, length, 0, + (struct sockaddr *)&recvaddr, sizeof(recvaddr)); + RUNTIME_CHECK(sent == length); + + /* We might get additional questions here (e.g. for CNAME). */ + for (;;) { + fd_set fds; + struct timeval tv; + int rv; + int max; + + FD_ZERO(&fds); + FD_SET(listenfd, &fds); + FD_SET(sockfd, &fds); + tv.tv_sec = 10; + tv.tv_usec = 0; + max = (listenfd > sockfd ? listenfd : sockfd) + 1; + + rv = select(max, &fds, NULL, NULL, &tv); + RUNTIME_CHECK(rv > 0); + + if (FD_ISSET(sockfd, &fds)) { + /* + * It's the reply from named(resolver) + * to the client(query driver), so we're + * done. + */ + (void)recvfrom(sockfd, buf, 65536, 0, NULL, + NULL); + break; + } + + /* + * We've got additional question (eg. due to + * CNAME). Bounce it - setting QR flag and + * NOERROR rcode and sending it back. + */ + length = recvfrom(listenfd, buf, 65536, 0, + (struct sockaddr *)&recvaddr, + &socklen); + + /* + * If this is a DNSKEY query, send the DNSKEY, + * otherwise, bounce the query. + */ + + /* Skip DNS header to get to the name */ + nameptr = buf + 12; + + /* Skip the name to get to the qtype */ + i = 0; + while (((llen = nameptr[i]) != 0) && (i < 255) && + (((nameptr + i + 1 + llen) - buf) < length)) + { + i += 1 + llen; + } + + if (i <= 255) { + nameptr += 1 + i; + /* + * Patch in the DNSKEY reply without + * touching the ID field. Note that we + * don't compare the name in the + * question section in the query, but we + * don't expect to receive any query for + * type DNSKEY but for the name + * "example." + */ + if ((nameptr - buf) < (length - 2)) { + uint8_t hb, lb; + hb = *nameptr++; + lb = *nameptr++; + qtype = (hb << 8) | lb; + + if (qtype == 48) { + memmove(buf + 2, dnskey_wf + 2, + sizeof(dnskey_wf) - 2); + length = sizeof(dnskey_wf); + } + } + } + + buf[2] |= 0x80; + buf[3] &= 0xF0; + sent = sendto(listenfd, buf, length, 0, + (struct sockaddr *)&recvaddr, + sizeof(recvaddr)); + RUNTIME_CHECK(sent == length); + } + + while (!ready) { + pthread_cond_wait(&cond, &mutex); + } + + RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); + } + + free(buf); + free(rbuf); + close(sockfd); + close(listenfd); + named_server_flushonshutdown(named_g_server, false); + isc_loopmgr_shutdown(named_g_loopmgr); + +#ifdef __AFL_LOOP + /* + * This is here just for the signature, that's how AFL detects + * if it's a 'persistent mode' binary. It has to occur somewhere + * in the file, that's all. < wpk_> AFL checks the binary for + * this signature ("##SIG_AFL_PERSISTENT##") and runs the binary + * in persistent mode if it's present. + */ + __AFL_LOOP(0); +#endif /* ifdef __AFL_LOOP */ + + return NULL; +} + +/* + * In "tcp:", "http:" and "rndc:" modes, this thread reads fuzzed query + * blobs from AFL from standard input and sends it to the corresponding + * TCP listening port of named (port 53 DNS, or the HTTP statistics + * channels listener or the rndc port) that is passed in the -A + * :
: option. It can be used to test named from the + * client side. + */ +static void * +fuzz_thread_tcp(void *arg) { + char *host; + char *port; + struct sockaddr_in servaddr; + int sockfd; + char *buf; + int loop; + + UNUSED(arg); + + /* + * Parse named -A argument in the "address:port" syntax. Due to + * the syntax used, this only supports IPv4 addresses. + */ + host = strdup(named_g_fuzz_addr); + RUNTIME_CHECK(host != NULL); + + port = strchr(host, ':'); + RUNTIME_CHECK(port != NULL); + *port = 0; + ++port; + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + RUNTIME_CHECK(inet_pton(AF_INET, host, &servaddr.sin_addr) == 1); + servaddr.sin_port = htons(atoi(port)); + + free(host); + + /* + * Wait for named to start. This is set in run_server() in the + * named thread. + */ + while (!named_g_run_done) { + usleep(10000); + } + + buf = malloc(65539); + RUNTIME_CHECK(buf != NULL); + + /* + * Processing fuzzed packets 100,000 times before shutting down + * the app. + */ + for (loop = 0; loop < 100000; loop++) { + ssize_t length; + ssize_t sent; + int yes; + int r; + + if (named_g_fuzz_type == isc_fuzz_tcpclient) { + /* + * To fuzz DNS TCP client we have to put 16-bit + * message length preceding the start of packet. + */ + length = read(0, buf + 2, 65535); + buf[0] = (length >> 8) & 0xff; + buf[1] = length & 0xff; + length += 2; + } else { + /* + * Other types of TCP clients such as HTTP, etc. + */ + length = read(0, buf, 65535); + } + if (length <= 0) { + usleep(1000000); + continue; + } + if (named_g_fuzz_type == isc_fuzz_http) { + /* + * This guarantees that the request will be + * processed. + */ + INSIST(length <= 65535); + buf[length++] = '\r'; + buf[length++] = '\n'; + buf[length++] = '\r'; + buf[length++] = '\n'; + } + + RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); + + ready = false; + yes = 1; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + RUNTIME_CHECK(sockfd != -1); + RUNTIME_CHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(int)) == 0); + + do { + r = connect(sockfd, (struct sockaddr *)&servaddr, + sizeof(servaddr)); + if (r != 0) { + usleep(10000); + } + } while (r != 0); + + /* + * Send the fuzzed query blob to the target server. + */ + sent = write(sockfd, buf, length); + RUNTIME_CHECK(sent == length); + + close(sockfd); + + while (!ready) { + pthread_cond_wait(&cond, &mutex); + } + + RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); + } + + free(buf); + close(sockfd); + named_server_flushonshutdown(named_g_server, false); + isc_loopmgr_shutdown(named_g_loopmgr); + + return NULL; +} + +#endif /* ENABLE_AFL */ + +/* + * named has finished processing a message and has sent the + * reply. Signal the fuzz thread using the condition variable, to read + * and process the next item from AFL. + */ +void +named_fuzz_notify(void) { +#ifdef ENABLE_AFL + if (getenv("AFL_CMIN")) { + named_server_flushonshutdown(named_g_server, false); + isc_loopmgr_shutdown(named_g_loopmgr); + return; + } + + raise(SIGSTOP); + + RUNTIME_CHECK(pthread_mutex_lock(&mutex) == 0); + + ready = true; + + RUNTIME_CHECK(pthread_cond_signal(&cond) == 0); + RUNTIME_CHECK(pthread_mutex_unlock(&mutex) == 0); +#endif /* ENABLE_AFL */ +} + +void +named_fuzz_setup(void) { +#ifdef ENABLE_AFL + if (getenv("__AFL_PERSISTENT") || getenv("AFL_CMIN")) { + pthread_t thread; + void *(fn) = NULL; + + switch (named_g_fuzz_type) { + case isc_fuzz_client: + fn = fuzz_thread_client; + break; + + case isc_fuzz_http: + case isc_fuzz_tcpclient: + case isc_fuzz_rndc: + fn = fuzz_thread_tcp; + break; + + case isc_fuzz_resolver: + fn = fuzz_thread_resolver; + break; + + default: + RUNTIME_CHECK(fn != NULL); + } + + RUNTIME_CHECK(pthread_mutex_init(&mutex, NULL) == 0); + RUNTIME_CHECK(pthread_cond_init(&cond, NULL) == 0); + RUNTIME_CHECK(pthread_create(&thread, NULL, fn, NULL) == 0); + } +#endif /* ENABLE_AFL */ +} diff --git a/bin/named/geoip.c b/bin/named/geoip.c new file mode 100644 index 0000000..6dd40df --- /dev/null +++ b/bin/named/geoip.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#if defined(HAVE_GEOIP2) +#include +#endif /* if defined(HAVE_GEOIP2) */ + +#include +#include +#include + +#include + +#include +#include + +static dns_geoip_databases_t geoip_table; + +#if defined(HAVE_GEOIP2) +static MMDB_s geoip_country, geoip_city, geoip_as, geoip_isp, geoip_domain; + +static MMDB_s * +open_geoip2(const char *dir, const char *dbfile, MMDB_s *mmdb) { + char pathbuf[PATH_MAX]; + unsigned int n; + int ret; + + n = snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dir, dbfile); + if (n >= sizeof(pathbuf)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "GeoIP2 database '%s/%s': path too long", dir, + dbfile); + return NULL; + } + + ret = MMDB_open(pathbuf, MMDB_MODE_MMAP, mmdb); + if (ret == MMDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "opened GeoIP2 database '%s'", pathbuf); + return mmdb; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "unable to open GeoIP2 database '%s' (status %d)", + pathbuf, ret); + + return NULL; +} +#endif /* HAVE_GEOIP2 */ + +void +named_geoip_init(void) { +#if defined(HAVE_GEOIP2) + if (named_g_geoip == NULL) { + named_g_geoip = &geoip_table; + } +#else /* if defined(HAVE_GEOIP2) */ + return; +#endif /* if defined(HAVE_GEOIP2) */ +} + +void +named_geoip_load(char *dir) { +#if defined(HAVE_GEOIP2) + REQUIRE(dir != NULL); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "looking for GeoIP2 databases in '%s'", dir); + + named_g_geoip->country = open_geoip2(dir, "GeoIP2-Country.mmdb", + &geoip_country); + if (named_g_geoip->country == NULL) { + named_g_geoip->country = open_geoip2( + dir, "GeoLite2-Country.mmdb", &geoip_country); + } + + named_g_geoip->city = open_geoip2(dir, "GeoIP2-City.mmdb", &geoip_city); + if (named_g_geoip->city == NULL) { + named_g_geoip->city = open_geoip2(dir, "GeoLite2-City.mmdb", + &geoip_city); + } + + named_g_geoip->as = open_geoip2(dir, "GeoIP2-ASN.mmdb", &geoip_as); + if (named_g_geoip->as == NULL) { + named_g_geoip->as = open_geoip2(dir, "GeoLite2-ASN.mmdb", + &geoip_as); + } + + named_g_geoip->isp = open_geoip2(dir, "GeoIP2-ISP.mmdb", &geoip_isp); + named_g_geoip->domain = open_geoip2(dir, "GeoIP2-Domain.mmdb", + &geoip_domain); +#else /* if defined(HAVE_GEOIP2) */ + UNUSED(dir); + + return; +#endif /* if defined(HAVE_GEOIP2) */ +} + +void +named_geoip_unload(void) { +#ifdef HAVE_GEOIP2 + if (named_g_geoip->country != NULL) { + MMDB_close(named_g_geoip->country); + named_g_geoip->country = NULL; + } + if (named_g_geoip->city != NULL) { + MMDB_close(named_g_geoip->city); + named_g_geoip->city = NULL; + } + if (named_g_geoip->as != NULL) { + MMDB_close(named_g_geoip->as); + named_g_geoip->as = NULL; + } + if (named_g_geoip->isp != NULL) { + MMDB_close(named_g_geoip->isp); + named_g_geoip->isp = NULL; + } + if (named_g_geoip->domain != NULL) { + MMDB_close(named_g_geoip->domain); + named_g_geoip->domain = NULL; + } +#endif /* ifdef HAVE_GEOIP2 */ +} + +void +named_geoip_shutdown(void) { +#ifdef HAVE_GEOIP2 + named_geoip_unload(); +#endif /* HAVE_GEOIP2 */ +} diff --git a/bin/named/include/dlz/dlz_dlopen_driver.h b/bin/named/include/dlz/dlz_dlopen_driver.h new file mode 100644 index 0000000..64d6388 --- /dev/null +++ b/bin/named/include/dlz/dlz_dlopen_driver.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +isc_result_t +dlz_dlopen_init(isc_mem_t *mctx); + +void +dlz_dlopen_clear(void); diff --git a/bin/named/include/named/builtin.h b/bin/named/include/named/builtin.h new file mode 100644 index 0000000..6885101 --- /dev/null +++ b/bin/named/include/named/builtin.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +#include +#include + +#include +#include + +/*** + *** Functions + ***/ + +/* Initialization functions for builtin zone databases */ +isc_result_t +named_builtin_init(void); + +void +named_builtin_deinit(void); diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h new file mode 100644 index 0000000..0be3b12 --- /dev/null +++ b/bin/named/include/named/config.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +#include +#include + +#include + +#define DEFAULT_IANA_ROOT_ZONE_PRIMARIES "_default_iana_root_zone_primaries" + +isc_result_t +named_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf); + +const char * +named_config_getdefault(void); + +isc_result_t +named_config_get(cfg_obj_t const *const *maps, const char *name, + const cfg_obj_t **obj); + +isc_result_t +named_checknames_get(const cfg_obj_t **maps, const char *const names[], + const cfg_obj_t **obj); + +int +named_config_listcount(const cfg_obj_t *list); + +isc_result_t +named_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass, + dns_rdataclass_t *classp); + +isc_result_t +named_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype, + dns_rdatatype_t *typep); + +dns_zonetype_t +named_config_getzonetype(const cfg_obj_t *zonetypeobj); + +isc_result_t +named_config_getremotesdef(const cfg_obj_t *cctx, const char *list, + const char *name, const cfg_obj_t **ret); + +isc_result_t +named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, + isc_mem_t *mctx, dns_ipkeylist_t *ipkl); + +isc_result_t +named_config_getport(const cfg_obj_t *config, const char *type, + in_port_t *portp); + +isc_result_t +named_config_getkeyalgorithm(const char *str, unsigned int *typep, + uint16_t *digestbits); diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h new file mode 100644 index 0000000..6010820 --- /dev/null +++ b/bin/named/include/named/control.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file + * \brief + * The name server command channel. + */ + +#include + +#include + +#include + +#include + +#define NAMED_CONTROL_PORT 953 + +#define NAMED_COMMAND_ADDZONE "addzone" +#define NAMED_COMMAND_DELZONE "delzone" +#define NAMED_COMMAND_DNSSEC "dnssec" +#define NAMED_COMMAND_DNSTAP "dnstap" +#define NAMED_COMMAND_DNSTAPREOPEN "dnstap-reopen" +#define NAMED_COMMAND_DUMPDB "dumpdb" +#define NAMED_COMMAND_DUMPSTATS "stats" +#define NAMED_COMMAND_FETCHLIMIT "fetchlimit" +#define NAMED_COMMAND_FLUSH "flush" +#define NAMED_COMMAND_FLUSHNAME "flushname" +#define NAMED_COMMAND_FLUSHTREE "flushtree" +#define NAMED_COMMAND_FREEZE "freeze" +#define NAMED_COMMAND_HALT "halt" +#define NAMED_COMMAND_LOADKEYS "loadkeys" +#define NAMED_COMMAND_MEMPROF "memprof" +#define NAMED_COMMAND_MKEYS "managed-keys" +#define NAMED_COMMAND_MODZONE "modzone" +#define NAMED_COMMAND_NOTIFY "notify" +#define NAMED_COMMAND_NOTRACE "notrace" +#define NAMED_COMMAND_NTA "nta" +#define NAMED_COMMAND_NULL "null" +#define NAMED_COMMAND_QUERYLOG "querylog" +#define NAMED_COMMAND_RECONFIG "reconfig" +#define NAMED_COMMAND_RECURSING "recursing" +#define NAMED_COMMAND_REFRESH "refresh" +#define NAMED_COMMAND_RELOAD "reload" +#define NAMED_COMMAND_RESETSTATS "reset-stats" +#define NAMED_COMMAND_RESPONSELOG "responselog" +#define NAMED_COMMAND_RETRANSFER "retransfer" +#define NAMED_COMMAND_SCAN "scan" +#define NAMED_COMMAND_SECROOTS "secroots" +#define NAMED_COMMAND_SERVESTALE "serve-stale" +#define NAMED_COMMAND_SHOWZONE "showzone" +#define NAMED_COMMAND_SIGN "sign" +#define NAMED_COMMAND_SIGNING "signing" +#define NAMED_COMMAND_SKR "skr" +#define NAMED_COMMAND_STATUS "status" +#define NAMED_COMMAND_STOP "stop" +#define NAMED_COMMAND_SYNC "sync" +#define NAMED_COMMAND_TCPTIMEOUTS "tcp-timeouts" +#define NAMED_COMMAND_TESTGEN "testgen" +#define NAMED_COMMAND_THAW "thaw" +#define NAMED_COMMAND_TRACE "trace" +#define NAMED_COMMAND_UNFREEZE "unfreeze" +#define NAMED_COMMAND_VALIDATION "validation" +#define NAMED_COMMAND_ZONESTATUS "zonestatus" + +isc_result_t +named_controls_create(named_server_t *server, named_controls_t **ctrlsp); +/*%< + * Create an initial, empty set of command channels for 'server'. + */ + +void +named_controls_destroy(named_controls_t **ctrlsp); +/*%< + * Destroy a set of command channels. + * + * Requires: + * Shutdown of the channels has completed. + */ + +isc_result_t +named_controls_configure(named_controls_t *controls, const cfg_obj_t *config, + cfg_aclconfctx_t *aclconfctx); +/*%< + * Configure zero or more command channels into 'controls' + * as defined in the configuration parse tree 'config'. + * The channels will evaluate ACLs in the context of + * 'aclconfctx'. + */ + +void +named_controls_shutdown(named_controls_t *controls); +/*%< + * Initiate shutdown of all the command channels in 'controls'. + */ + +isc_result_t +named_control_docommand(isccc_sexpr_t *message, bool readonly, + isc_buffer_t **text); diff --git a/bin/named/include/named/fuzz.h b/bin/named/include/named/fuzz.h new file mode 100644 index 0000000..69af8da --- /dev/null +++ b/bin/named/include/named/fuzz.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#pragma once + +void +named_fuzz_notify(void); + +void +named_fuzz_setup(void); diff --git a/bin/named/include/named/geoip.h b/bin/named/include/named/geoip.h new file mode 100644 index 0000000..d1852ef --- /dev/null +++ b/bin/named/include/named/geoip.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +extern dns_geoip_databases_t *named_g_geoip; + +void +named_geoip_init(void); + +void +named_geoip_load(char *dir); + +void +named_geoip_unload(void); + +void +named_geoip_shutdown(void); diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h new file mode 100644 index 0000000..25d03ff --- /dev/null +++ b/bin/named/include/named/globals.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#undef EXTERN +#undef INIT +#ifdef NAMED_MAIN +#define EXTERN +#define INIT(v) = (v) +#else /* ifdef NAMED_MAIN */ +#define EXTERN extern +#define INIT(v) +#endif /* ifdef NAMED_MAIN */ + +#ifndef NAMED_RUN_PID_DIR +#define NAMED_RUN_PID_DIR 1 +#endif /* ifndef NAMED_RUN_PID_DIR */ + +EXTERN isc_mem_t *named_g_mctx INIT(NULL); +EXTERN unsigned int named_g_cpus INIT(0); +EXTERN isc_loop_t *named_g_mainloop INIT(NULL); +EXTERN isc_loopmgr_t *named_g_loopmgr INIT(NULL); +EXTERN bool named_g_loopmgr_running INIT(false); +EXTERN dns_dispatchmgr_t *named_g_dispatchmgr INIT(NULL); +EXTERN unsigned int named_g_cpus_detected INIT(1); + +#ifdef ENABLE_AFL +EXTERN bool named_g_run_done INIT(false); +#endif /* ifdef ENABLE_AFL */ +/* + * XXXRTH We're going to want multiple timer managers eventually. One + * for really short timers, another for client timers, and one + * for zone timers. + */ +EXTERN isc_nm_t *named_g_netmgr INIT(NULL); +EXTERN cfg_parser_t *named_g_parser INIT(NULL); +EXTERN cfg_parser_t *named_g_addparser INIT(NULL); +EXTERN const char *named_g_version INIT(PACKAGE_VERSION); +EXTERN const char *named_g_product INIT(PACKAGE_NAME); +EXTERN const char *named_g_description INIT(PACKAGE_DESCRIPTION); +EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID); +EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS); +EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER); +EXTERN in_port_t named_g_port INIT(0); +EXTERN in_port_t named_g_tlsport INIT(0); +EXTERN in_port_t named_g_httpsport INIT(0); +EXTERN in_port_t named_g_httpport INIT(0); + +EXTERN in_port_t named_g_http_listener_clients INIT(0); +EXTERN in_port_t named_g_http_streams_per_conn INIT(0); + +EXTERN named_server_t *named_g_server INIT(NULL); + +/* + * Logging. + */ +EXTERN isc_log_t *named_g_lctx INIT(NULL); +EXTERN isc_logcategory_t *named_g_categories INIT(NULL); +EXTERN isc_logmodule_t *named_g_modules INIT(NULL); +EXTERN unsigned int named_g_debuglevel INIT(0); + +/* + * Current configuration information. + */ +EXTERN cfg_obj_t *named_g_config INIT(NULL); +EXTERN const cfg_obj_t *named_g_defaults INIT(NULL); +EXTERN const char *named_g_conffile INIT(NAMED_SYSCONFDIR "/named.conf"); +EXTERN const char *named_g_defaultbindkeys INIT(NULL); +EXTERN const char *named_g_keyfile INIT(NAMED_SYSCONFDIR "/rndc.key"); + +EXTERN bool named_g_conffileset INIT(false); +EXTERN cfg_aclconfctx_t *named_g_aclconfctx INIT(NULL); + +/* + * Misc. + */ +EXTERN bool named_g_coreok INIT(true); +EXTERN const char *named_g_chrootdir INIT(NULL); +EXTERN bool named_g_foreground INIT(false); +EXTERN bool named_g_logstderr INIT(false); +EXTERN bool named_g_nosyslog INIT(false); +EXTERN const char *named_g_logfile INIT(NULL); + +EXTERN const char *named_g_defaultsessionkeyfile INIT(NAMED_LOCALSTATEDIR + "/run/named/" + "session.key"); + +#if NAMED_RUN_PID_DIR +EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/named/" + "named.pid"); +#else /* if NAMED_RUN_PID_DIR */ +EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/" + "named.pid"); +#endif /* if NAMED_RUN_PID_DIR */ + +EXTERN const char *named_g_username INIT(NULL); + +EXTERN const char *named_g_engine INIT(NULL); + +EXTERN isc_time_t named_g_boottime; +EXTERN isc_time_t named_g_configtime; +EXTERN bool named_g_memstatistics INIT(false); +EXTERN bool named_g_keepstderr INIT(false); + +EXTERN unsigned int named_g_tat_interval INIT(24 * 3600); +EXTERN unsigned int named_g_maxcachesize INIT(0); + +#if defined(HAVE_GEOIP2) +EXTERN dns_geoip_databases_t *named_g_geoip INIT(NULL); +#endif /* if defined(HAVE_GEOIP2) */ + +EXTERN const char *named_g_fuzz_addr INIT(NULL); +EXTERN isc_fuzztype_t named_g_fuzz_type INIT(isc_fuzz_none); + +EXTERN dns_acl_t *named_g_mapped INIT(NULL); + +#undef EXTERN +#undef INIT diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h new file mode 100644 index 0000000..f18e93a --- /dev/null +++ b/bin/named/include/named/log.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include + +#include /* Required for named_g_(categories|modules). */ + +/* Unused slot 0. */ +#define NAMED_LOGCATEGORY_UNMATCHED (&named_g_categories[1]) + +/* + * Backwards compatibility. + */ +#define NAMED_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL + +#define NAMED_LOGMODULE_MAIN (&named_g_modules[0]) +#define NAMED_LOGMODULE_SERVER (&named_g_modules[1]) +#define NAMED_LOGMODULE_CONTROL (&named_g_modules[2]) + +isc_result_t +named_log_init(bool safe); +/*% + * Initialize the logging system and set up an initial default + * logging default configuration that will be used until the + * config file has been read. + * + * If 'safe' is true, use a default configuration that refrains + * from opening files. This is to avoid creating log files + * as root. + */ + +void +named_log_setdefaultchannels(isc_logconfig_t *lcfg); +/*% + * Set up logging channels according to the named defaults, which + * may differ from the logging library defaults. Currently, + * this just means setting up default_debug. + */ + +void +named_log_setsafechannels(isc_logconfig_t *lcfg); +/*% + * Like named_log_setdefaultchannels(), but omits any logging to files. + */ + +void +named_log_setdefaultsslkeylogfile(isc_logconfig_t *lcfg); +/*% + * If the SSLKEYLOGFILE environment variable is set, sets up a default + * logging channel for writing TLS pre-master secrets to the path stored + * in that environment variable (for debugging purposes). + */ + +isc_result_t +named_log_setdefaultcategory(isc_logconfig_t *lcfg); +/*% + * Set up "category default" to go to the right places. + */ + +isc_result_t +named_log_setunmatchedcategory(isc_logconfig_t *lcfg); +/*% + * Set up "category unmatched" to go to the right places. + */ + +void +named_log_shutdown(void); diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h new file mode 100644 index 0000000..65add46 --- /dev/null +++ b/bin/named/include/named/logconf.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +isc_result_t +named_logconfig(isc_logconfig_t *logconf, const cfg_obj_t *logstmt); +/*%< + * Set up the logging configuration in '*logconf' according to + * the named.conf data in 'logstmt'. + */ diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h new file mode 100644 index 0000000..bed5dd9 --- /dev/null +++ b/bin/named/include/named/main.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include + +/*! \file */ + +#ifdef ISC_MAIN_HOOK +#define main(argc, argv) bindmain(argc, argv) +#endif /* ifdef ISC_MAIN_HOOK */ + +/* + * Commandline arguments for named; + */ +#define NAMED_MAIN_ARGS "46A:c:Cd:D:E:fFgL:M:m:n:N:p:sS:t:T:U:u:vVx:X:" + +noreturn void +named_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +void +named_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +void +named_main_setmemstats(const char *); + +void +named_main_shutdown(void *arg, int signum); diff --git a/bin/named/include/named/os.h b/bin/named/include/named/os.h new file mode 100644 index 0000000..a150872 --- /dev/null +++ b/bin/named/include/named/os.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include + +void +named_os_init(const char *progname); + +void +named_os_daemonize(void); + +void +named_os_opendevnull(void); + +void +named_os_closedevnull(void); + +void +named_os_chroot(const char *root); + +void +named_os_inituserinfo(const char *username); + +void +named_os_changeuser(bool permanent); + +void +named_os_restoreuser(void); + +uid_t +named_os_uid(void); + +void +named_os_adjustnofile(void); + +void +named_os_minprivs(void); + +FILE * +named_os_openfile(const char *filename, mode_t mode, bool switch_user); + +void +named_os_writepidfile(const char *filename, bool first_time); + +void +named_os_shutdown(void); + +void +named_os_shutdownmsg(char *command, isc_buffer_t *text); + +void +named_os_tzset(void); + +void +named_os_started(void); + +const char * +named_os_uname(void); diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h new file mode 100644 index 0000000..2172013 --- /dev/null +++ b/bin/named/include/named/server.h @@ -0,0 +1,412 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/*% + * Name server state. Better here than in lots of separate global variables. + */ +struct named_server { + unsigned int magic; + isc_mem_t *mctx; + + ns_server_t *sctx; + + char *statsfile; /*%< Statistics file name */ + char *dumpfile; /*%< Dump file name */ + char *secrootsfile; /*%< Secroots file name */ + char *bindkeysfile; /*%< bind.keys file name */ + char *recfile; /*%< Recursive file name */ + bool version_set; /*%< User has set version */ + char *version; /*%< User-specified version */ + bool hostname_set; /*%< User has set hostname */ + char *hostname; /*%< User-specified hostname */ +#ifdef USE_DNSRPS + char *dnsrpslib; +#endif /* ifdef USE_DNSRPS */ + + /* Server data structures. */ + dns_loadmgr_t *loadmgr; + dns_zonemgr_t *zonemgr; + dns_viewlist_t viewlist; + dns_kasplist_t kasplist; + dns_keystorelist_t keystorelist; + ns_interfacemgr_t *interfacemgr; + dns_db_t *in_roothints; + + isc_timer_t *interface_timer; + isc_timer_t *heartbeat_timer; + isc_timer_t *pps_timer; + isc_timer_t *tat_timer; + + uint32_t interface_interval; + uint32_t heartbeat_interval; + + atomic_int reload_status; + + bool flushonshutdown; + + named_cachelist_t cachelist; /*%< Possibly shared caches + * */ + isc_stats_t *zonestats; /*% Zone management stats */ + isc_stats_t *resolverstats; /*% Resolver stats */ + isc_stats_t *sockstats; /*%< Socket stats */ + + named_controls_t *controls; /*%< Control channels */ + unsigned int dispatchgen; + named_dispatchlist_t dispatches; + + named_statschannellist_t statschannels; + + dst_key_t *sessionkey; + char *session_keyfile; + dns_name_t *session_keyname; + unsigned int session_keyalg; + uint16_t session_keybits; + bool interface_auto; + unsigned char secret[32]; /*%< Server Cookie Secret */ + ns_cookiealg_t cookiealg; + + dns_dtenv_t *dtenv; /*%< Dnstap environment */ + + isc_tlsctx_cache_t *tlsctx_server_cache; + isc_tlsctx_cache_t *tlsctx_client_cache; + + isc_signal_t *sighup; +}; + +#define NAMED_SERVER_MAGIC ISC_MAGIC('S', 'V', 'E', 'R') +#define NAMED_SERVER_VALID(s) ISC_MAGIC_VALID(s, NAMED_SERVER_MAGIC) + +void +named_server_create(isc_mem_t *mctx, named_server_t **serverp); +/*%< + * Create a server object with default settings. + * This function either succeeds or causes the program to exit + * with a fatal error. + */ + +void +named_server_destroy(named_server_t **serverp); +/*%< + * Destroy a server object, freeing its memory. + */ + +void +named_server_reloadwanted(void *arg, int signum); +/*%< + * Inform a server that a reload is wanted. This function + * may be called asynchronously, from outside the server's task. + * If a reload is already scheduled or in progress, the call + * is ignored. + */ + +void +named_server_scan_interfaces(named_server_t *server); +/*%< + * Trigger a interface scan. + * Must only be called when running under server->task. + */ + +void +named_server_flushonshutdown(named_server_t *server, bool flush); +/*%< + * Inform the server that the zones should be flushed to disk on shutdown. + */ + +isc_result_t +named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); +/*%< + * Act on a "reload" command from the command channel. + */ + +isc_result_t +named_server_resetstatscommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); +/*%< + * Act on a "reset-stats" command from the command channel. + */ + +isc_result_t +named_server_reconfigcommand(named_server_t *server); +/*%< + * Act on a "reconfig" command from the command channel. + */ + +isc_result_t +named_server_notifycommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); +/*%< + * Act on a "notify" command from the command channel. + */ + +isc_result_t +named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); +/*%< + * Act on a "refresh" command from the command channel. + */ + +isc_result_t +named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); +/*%< + * Act on a "retransfer" command from the command channel. + */ + +isc_result_t +named_server_setortoggle(named_server_t *server, const char *optname, + unsigned int option, isc_lex_t *lex); +/*%< + * Enable/disable, or toggle, a server option via the command channel. + * 'option' is the option value to be changed (for example, + * NS_SERVER_LOGQUERIES or NS_SERVER_LOGRESPOSNES) and 'optname' is the + * option's human-readable name for logging purposes ("query logging" + * or "response logging"). + * + * If an explicit argument to enable the option was provided + * (i.e., "on", "enable", "true", or "yes") or an explicit argument + * to disable it ("off", "disable", "false", or "no"), it will be used. + * + * If no argument is provided, the option's current state will be reversed. + */ + +/*% + * Save the current NTAs for all views to files. + */ +isc_result_t +named_server_saventa(named_server_t *server); + +/*% + * Load NTAs for all views from files. + */ +isc_result_t +named_server_loadnta(named_server_t *server); + +/*% + * Dump the current statistics to the statistics file. + */ +isc_result_t +named_server_dumpstats(named_server_t *server); + +/*% + * Dump the current cache to the dump file. + */ +isc_result_t +named_server_dumpdb(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Dump the current security roots to the secroots file. + */ +isc_result_t +named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Change or increment the server debug level. + */ +isc_result_t +named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex); + +/*% + * Flush the server's cache(s) + */ +isc_result_t +named_server_flushcache(named_server_t *server, isc_lex_t *lex); + +/*% + * Flush a particular name from the server's cache. If 'tree' is false, + * also flush the name from the ADB and badcache. If 'tree' is true, also + * flush all the names under the specified name. + */ +isc_result_t +named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree); + +/*% + * Report the server's status. + */ +isc_result_t +named_server_status(named_server_t *server, isc_buffer_t **text); + +/*% + * Enable or disable updates for a zone. + */ +isc_result_t +named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Dump zone updates to disk, optionally removing the journal file + */ +isc_result_t +named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Update a zone's DNSKEY set from the key repository. If + * the command that triggered the call to this function was "sign", + * then force a full signing of the zone. If it was "loadkeys", + * then don't sign the zone; any needed changes to signatures can + * take place incrementally. + */ +isc_result_t +named_server_rekey(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Dump the current recursive queries. + */ +isc_result_t +named_server_dumprecursing(named_server_t *server); + +/*% + * Enable or disable dnssec validation. + */ +isc_result_t +named_server_validation(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Add a zone to a running process, or modify an existing zone + */ +isc_result_t +named_server_changezone(named_server_t *server, char *command, + isc_buffer_t **text); + +/*% + * Deletes a zone from a running process + */ +isc_result_t +named_server_delzone(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Show current configuration for a given zone + */ +isc_result_t +named_server_showzone(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Lists the status of the signing records for a given zone. + */ +isc_result_t +named_server_signing(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Lists the DNSSEC status for a given zone. + */ +isc_result_t +named_server_dnssec(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Lists status information for a given zone (e.g., name, type, files, + * load time, expiry, etc). + */ +isc_result_t +named_server_zonestatus(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Adds/updates a Negative Trust Anchor (NTA) for a specified name and + * duration, in a particular view if specified, or in all views. + */ +isc_result_t +named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, + isc_buffer_t **text); + +/*% + * Generates a test sequence that is only for use in system tests. The + * argument is the size of required output in bytes. + */ +isc_result_t +named_server_testgen(isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Force fefresh or print status for managed keys zones. + */ +isc_result_t +named_server_mkeys(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Close and reopen DNSTAP output file. + */ +isc_result_t +named_server_dnstap(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Display or update tcp-{initial,idle,keepalive,advertised}-timeout options. + */ +isc_result_t +named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Control whether stale answers are served or not when configured in + * named.conf. + */ +isc_result_t +named_server_servestale(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Report fetch-limited ADB server addresses. + */ +isc_result_t +named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + +/*% + * Import SKR file for offline KSK signing. + */ +isc_result_t +named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Toggle memory profiling if supported. + */ +isc_result_t +named_server_togglememprof(isc_lex_t *lex); + +/*% + * Get status of memory profiling. + */ +const char * +named_server_getmemprof(void); diff --git a/bin/named/include/named/smf_globals.h b/bin/named/include/named/smf_globals.h new file mode 100644 index 0000000..b052822 --- /dev/null +++ b/bin/named/include/named/smf_globals.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include + +#undef EXTERN +#undef INIT +#ifdef NAMED_MAIN +#define EXTERN +#define INIT(v) = (v) +#else /* ifdef NAMED_MAIN */ +#define EXTERN extern +#define INIT(v) +#endif /* ifdef NAMED_MAIN */ + +EXTERN unsigned int named_smf_got_instance INIT(0); +EXTERN unsigned int named_smf_chroot INIT(0); +EXTERN unsigned int named_smf_want_disable INIT(0); + +isc_result_t +named_smf_add_message(isc_buffer_t **text); +isc_result_t +named_smf_get_instance(char **name, int debug, isc_mem_t *mctx); + +#undef EXTERN +#undef INIT diff --git a/bin/named/include/named/statschannel.h b/bin/named/include/named/statschannel.h new file mode 100644 index 0000000..8cce670 --- /dev/null +++ b/bin/named/include/named/statschannel.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file + * \brief + * The statistics channels built-in the name server. + */ + +#include + +#include + +#include + +#define NAMED_STATSCHANNEL_HTTPPORT 80 + +isc_result_t +named_statschannels_configure(named_server_t *server, const cfg_obj_t *config, + cfg_aclconfctx_t *aclconfctx); +/*%< + * [Re]configure the statistics channels. + * + * If it is no longer there but was previously configured, destroy + * it here. + * + * If the IP address or port has changed, destroy the old server + * and create a new one. + */ + +void +named_statschannels_shutdown(named_server_t *server); +/*%< + * Initiate shutdown of all the statistics channel listeners. + */ + +isc_result_t +named_stats_dump(named_server_t *server, FILE *fp); +/*%< + * Dump statistics counters managed by the server to the file fp. + */ diff --git a/bin/named/include/named/tkeyconf.h b/bin/named/include/named/tkeyconf.h new file mode 100644 index 0000000..79639d6 --- /dev/null +++ b/bin/named/include/named/tkeyconf.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +named_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, + dns_tkeyctx_t **tctxp); +/*%< + * Create a TKEY context and configure it, including the default DH key + * and default domain, according to 'options'. + * + * Requires: + *\li 'cfg' is a valid configuration options object. + *\li 'mctx' is not NULL + *\li 'tctx' is not NULL + *\li '*tctx' is NULL + * + * Returns: + *\li ISC_R_SUCCESS + *\li ISC_R_NOMEMORY + */ + +ISC_LANG_ENDDECLS diff --git a/bin/named/include/named/transportconf.h b/bin/named/include/named/transportconf.h new file mode 100644 index 0000000..1e472ff --- /dev/null +++ b/bin/named/include/named/transportconf.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +#include + +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +named_transports_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_transport_list_t **listp); +/*%< + * Create a list of transport objects (DoT or DoH) and configure them + * according to 'key-file', 'cert-file', 'ca-file' or 'hostname' + * statements. + * + * Requires: + * \li 'config' is not NULL. + * \li 'vconfig' is not NULL. + * \li 'mctx' is not NULL + * \li 'listp' is not NULL, and '*listp' is NULL + * + */ + +ISC_LANG_ENDDECLS diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h new file mode 100644 index 0000000..240eebe --- /dev/null +++ b/bin/named/include/named/tsigconf.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +named_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_tsigkeyring_t **ringp); +/*%< + * Create a TSIG key ring and configure it according to the 'key' + * statements in the global and view configuration objects. + * + * Requires: + * \li 'config' is not NULL. + * \li 'vconfig' is not NULL. + * \li 'mctx' is not NULL + * \li 'ringp' is not NULL, and '*ringp' is NULL + * + * Returns: + * \li ISC_R_SUCCESS + * \li ISC_R_NOMEMORY + */ + +ISC_LANG_ENDDECLS diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h new file mode 100644 index 0000000..585c141 --- /dev/null +++ b/bin/named/include/named/types.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +typedef struct named_cache named_cache_t; +typedef ISC_LIST(named_cache_t) named_cachelist_t; +typedef struct named_server named_server_t; +typedef struct named_xmld named_xmld_t; +typedef struct named_xmldmgr named_xmldmgr_t; +typedef struct named_controls named_controls_t; +typedef struct named_dispatch named_dispatch_t; +typedef ISC_LIST(named_dispatch_t) named_dispatchlist_t; +typedef struct named_statschannel named_statschannel_t; +typedef ISC_LIST(named_statschannel_t) named_statschannellist_t; + +/*% + * Used for server->reload_status as printed by `rndc status` + */ +typedef enum { + NAMED_RELOAD_DONE, + NAMED_RELOAD_IN_PROGRESS, + NAMED_RELOAD_FAILED, +} named_reload_t; diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h new file mode 100644 index 0000000..1eb059b --- /dev/null +++ b/bin/named/include/named/zoneconf.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include + +#include +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, + const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, + dns_kasplist_t *kasplist, dns_keystorelist_t *keystores, + dns_zone_t *zone, dns_zone_t *raw); +/*%< + * Configure or reconfigure a zone according to the named.conf + * data. + * + * The zone origin is not configured, it is assumed to have been set + * at zone creation time. + * + * Require: + * \li 'ac' to point to an initialized cfg_aclconfctx_t. + * \li 'kasplist' to be initialized. + * \li 'zone' to be initialized. + */ + +bool +named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig, + const cfg_obj_t *vconfig, const cfg_obj_t *config, + dns_kasplist_t *kasplist); +/*%< + * If 'zone' can be safely reconfigured according to the configuration + * data in 'zconfig', return true. If the configuration data is so + * different from the current zone state that the zone needs to be destroyed + * and recreated, return false. + */ + +bool +named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, + const cfg_obj_t *config, dns_kasplist_t *kasplist); +/*%< + * Determine if zone uses inline-signing. This is true if inline-signing + * is set to yes, in the zone clause or in the zone's dnssec-policy clause. + * By default, dnssec-policy uses inline-signing. + */ + +isc_result_t +named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name); +/*%> + * configure a DLZ zone, setting up the database methods and calling + * postload to load the origin values + * + * Require: + * \li 'dlzdatabase' to be a valid dlz database + * \li 'zone' to be initialized. + * \li 'rdclass' to be a valid rdataclass + * \li 'name' to be a valid zone origin name + */ + +ISC_LANG_ENDDECLS diff --git a/bin/named/log.c b/bin/named/log.c new file mode 100644 index 0000000..f8723a0 --- /dev/null +++ b/bin/named/log.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include +#include + +#include + +#include + +#include + +#include + +#ifndef ISC_FACILITY +#define ISC_FACILITY LOG_DAEMON +#endif /* ifndef ISC_FACILITY */ + +/*% + * When adding a new category, be sure to add the appropriate + * \#define to and to update the list in + * bin/check/check-tool.c. + */ +static isc_logcategory_t categories[] = { { "", 0 }, + { "unmatched", 0 }, + { NULL, 0 } }; + +/*% + * When adding a new module, be sure to add the appropriate + * \#define to . + */ +static isc_logmodule_t modules[] = { + { "main", 0 }, { "server", 0 }, { "control", 0 }, { NULL, 0 } +}; + +isc_result_t +named_log_init(bool safe) { + isc_result_t result; + isc_logconfig_t *lcfg = NULL; + isc_mem_t *log_mctx = NULL; + + named_g_categories = categories; + named_g_modules = modules; + + /* + * Setup a logging context. + */ + isc_mem_create(&log_mctx); + isc_mem_setname(log_mctx, "named_log"); + isc_log_create(log_mctx, &named_g_lctx, &lcfg); + isc_mem_detach(&log_mctx); + + /* + * named-checktool.c:setup_logging() needs to be kept in sync. + */ + isc_log_registercategories(named_g_lctx, named_g_categories); + isc_log_registermodules(named_g_lctx, named_g_modules); + isc_log_setcontext(named_g_lctx); + dns_log_init(named_g_lctx); + dns_log_setcontext(named_g_lctx); + cfg_log_init(named_g_lctx); + ns_log_init(named_g_lctx); + ns_log_setcontext(named_g_lctx); + + if (safe) { + named_log_setsafechannels(lcfg); + } else { + named_log_setdefaultchannels(lcfg); + } + + result = named_log_setdefaultcategory(lcfg); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + named_log_setdefaultsslkeylogfile(lcfg); + + return ISC_R_SUCCESS; + +cleanup: + isc_log_destroy(&named_g_lctx); + isc_log_setcontext(NULL); + dns_log_setcontext(NULL); + + return result; +} + +void +named_log_setdefaultchannels(isc_logconfig_t *lcfg) { + isc_logdestination_t destination; + + /* + * By default, the logging library makes "default_debug" log to + * stderr. In BIND, we want to override this and log to named.run + * instead, unless the -g option was given. + */ + if (!named_g_logstderr) { + destination.file.stream = NULL; + destination.file.name = "named.run"; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TOFILE, + ISC_LOG_DYNAMIC, &destination, + ISC_LOG_PRINTTIME | ISC_LOG_DEBUGONLY); + } + + if (named_g_logfile != NULL) { + destination.file.stream = NULL; + destination.file.name = named_g_logfile; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE, + ISC_LOG_DYNAMIC, &destination, + ISC_LOG_PRINTTIME | + ISC_LOG_PRINTCATEGORY | + ISC_LOG_PRINTLEVEL); + } + +#if ISC_FACILITY != LOG_DAEMON + destination.facility = ISC_FACILITY; + isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG, + ISC_LOG_INFO, &destination, 0); +#endif /* if ISC_FACILITY != LOG_DAEMON */ + + /* + * Set the initial debug level. + */ + isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); +} + +void +named_log_setsafechannels(isc_logconfig_t *lcfg) { + isc_logdestination_t destination; + + if (!named_g_logstderr) { + isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TONULL, + ISC_LOG_DYNAMIC, NULL, 0); + + /* + * Setting the debug level to zero should get the output + * discarded a bit faster. + */ + isc_log_setdebuglevel(named_g_lctx, 0); + } else { + isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); + } + + if (named_g_logfile != NULL) { + destination.file.stream = NULL; + destination.file.name = named_g_logfile; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE, + ISC_LOG_DYNAMIC, &destination, + ISC_LOG_PRINTTIME | + ISC_LOG_PRINTCATEGORY | + ISC_LOG_PRINTLEVEL); + } + +#if ISC_FACILITY != LOG_DAEMON + destination.facility = ISC_FACILITY; + isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG, + ISC_LOG_INFO, &destination, 0); +#endif /* if ISC_FACILITY != LOG_DAEMON */ +} + +/* + * If the SSLKEYLOGFILE environment variable is set, TLS pre-master secrets are + * logged (for debugging purposes) to the file whose path is provided in that + * variable. Set up a default logging channel which maintains up to 10 files + * containing TLS pre-master secrets, each up to 100 MB in size. If the + * SSLKEYLOGFILE environment variable is set to the string "config", suppress + * creation of the default channel, allowing custom logging channel + * configuration for TLS pre-master secrets to be provided via the "logging" + * stanza in the configuration file. + */ +void +named_log_setdefaultsslkeylogfile(isc_logconfig_t *lcfg) { + const char *sslkeylogfile_path = getenv("SSLKEYLOGFILE"); + isc_logdestination_t destination = { + .file = { + .name = sslkeylogfile_path, + .versions = 10, + .suffix = isc_log_rollsuffix_timestamp, + .maximum_size = 100 * 1024 * 1024, + }, + }; + isc_result_t result; + + if (sslkeylogfile_path == NULL || + strcmp(sslkeylogfile_path, "config") == 0) + { + return; + } + + isc_log_createchannel(lcfg, "default_sslkeylogfile", ISC_LOG_TOFILE, + ISC_LOG_INFO, &destination, 0); + result = isc_log_usechannel(lcfg, "default_sslkeylogfile", + ISC_LOGCATEGORY_SSLKEYLOG, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +isc_result_t +named_log_setdefaultcategory(isc_logconfig_t *lcfg) { + isc_result_t result = ISC_R_SUCCESS; + + result = isc_log_usechannel(lcfg, "default_debug", + ISC_LOGCATEGORY_DEFAULT, NULL); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + if (!named_g_logstderr) { + if (named_g_logfile != NULL) { + result = isc_log_usechannel(lcfg, "default_logfile", + ISC_LOGCATEGORY_DEFAULT, + NULL); + } else if (!named_g_nosyslog) { + result = isc_log_usechannel(lcfg, "default_syslog", + ISC_LOGCATEGORY_DEFAULT, + NULL); + } + } + +cleanup: + return result; +} + +isc_result_t +named_log_setunmatchedcategory(isc_logconfig_t *lcfg) { + isc_result_t result; + + result = isc_log_usechannel(lcfg, "null", NAMED_LOGCATEGORY_UNMATCHED, + NULL); + return result; +} + +void +named_log_shutdown(void) { + isc_log_destroy(&named_g_lctx); + isc_log_setcontext(NULL); + dns_log_setcontext(NULL); +} diff --git a/bin/named/logconf.c b/bin/named/logconf.c new file mode 100644 index 0000000..2729a20 --- /dev/null +++ b/bin/named/logconf.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +/*% + * Set up a logging category according to the named.conf data + * in 'ccat' and add it to 'logconfig'. + */ +static isc_result_t +category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) { + isc_result_t result; + const char *catname; + isc_logcategory_t *category; + isc_logmodule_t *module; + const cfg_obj_t *destinations = NULL; + const cfg_listelt_t *element = NULL; + + catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name")); + category = isc_log_categorybyname(named_g_lctx, catname); + if (category == NULL) { + cfg_obj_log(ccat, named_g_lctx, ISC_LOG_ERROR, + "unknown logging category '%s' ignored", catname); + /* + * Allow further processing by returning success. + */ + return ISC_R_SUCCESS; + } + + if (logconfig == NULL) { + return ISC_R_SUCCESS; + } + + module = NULL; + + destinations = cfg_tuple_get(ccat, "destinations"); + for (element = cfg_list_first(destinations); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *channel = cfg_listelt_value(element); + const char *channelname = cfg_obj_asstring(channel); + + result = isc_log_usechannel(logconfig, channelname, category, + module); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, CFG_LOGCATEGORY_CONFIG, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "logging channel '%s': %s", channelname, + isc_result_totext(result)); + return result; + } + } + return ISC_R_SUCCESS; +} + +/*% + * Set up a logging channel according to the named.conf data + * in 'cchan' and add it to 'logconfig'. + */ +static isc_result_t +channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig) { + isc_result_t result = ISC_R_SUCCESS; + isc_logdestination_t dest; + unsigned int type; + unsigned int flags = 0; + int level; + const char *channelname; + const cfg_obj_t *fileobj = NULL; + const cfg_obj_t *syslogobj = NULL; + const cfg_obj_t *nullobj = NULL; + const cfg_obj_t *stderrobj = NULL; + const cfg_obj_t *severity = NULL; + int i; + + channelname = cfg_obj_asstring(cfg_map_getname(channel)); + + (void)cfg_map_get(channel, "file", &fileobj); + (void)cfg_map_get(channel, "syslog", &syslogobj); + (void)cfg_map_get(channel, "null", &nullobj); + (void)cfg_map_get(channel, "stderr", &stderrobj); + + i = 0; + if (fileobj != NULL) { + i++; + } + if (syslogobj != NULL) { + i++; + } + if (nullobj != NULL) { + i++; + } + if (stderrobj != NULL) { + i++; + } + + if (i != 1) { + cfg_obj_log(channel, named_g_lctx, ISC_LOG_ERROR, + "channel '%s': exactly one of file, syslog, " + "null, and stderr must be present", + channelname); + return ISC_R_FAILURE; + } + + type = ISC_LOG_TONULL; + + if (fileobj != NULL) { + const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file"); + const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size"); + const cfg_obj_t *versionsobj = cfg_tuple_get(fileobj, + "versions"); + const cfg_obj_t *suffixobj = cfg_tuple_get(fileobj, "suffix"); + int32_t versions = ISC_LOG_ROLLNEVER; + isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; + off_t size = 0; + uint64_t maxoffset; + + /* + * off_t is a signed integer type, so the maximum + * value is all 1s except for the MSB. + */ + switch (sizeof(off_t)) { + case 4: + maxoffset = 0x7fffffffULL; + break; + case 8: + maxoffset = 0x7fffffffffffffffULL; + break; + default: + UNREACHABLE(); + } + + type = ISC_LOG_TOFILE; + + if (versionsobj != NULL && cfg_obj_isuint32(versionsobj)) { + versions = cfg_obj_asuint32(versionsobj); + } else if (versionsobj != NULL && + cfg_obj_isstring(versionsobj) && + strcasecmp(cfg_obj_asstring(versionsobj), + "unlimited") == 0) + { + versions = ISC_LOG_ROLLINFINITE; + } + if (sizeobj != NULL && cfg_obj_isuint64(sizeobj) && + cfg_obj_asuint64(sizeobj) < maxoffset) + { + size = (off_t)cfg_obj_asuint64(sizeobj); + } + if (suffixobj != NULL && cfg_obj_isstring(suffixobj) && + strcasecmp(cfg_obj_asstring(suffixobj), "timestamp") == 0) + { + suffix = isc_log_rollsuffix_timestamp; + } + + dest.file.stream = NULL; + dest.file.name = cfg_obj_asstring(pathobj); + dest.file.versions = versions; + dest.file.suffix = suffix; + dest.file.maximum_size = size; + } else if (syslogobj != NULL) { + int facility = LOG_DAEMON; + + type = ISC_LOG_TOSYSLOG; + + if (cfg_obj_isstring(syslogobj)) { + const char *facilitystr = cfg_obj_asstring(syslogobj); + (void)isc_syslog_facilityfromstring(facilitystr, + &facility); + } + dest.facility = facility; + } else if (stderrobj != NULL) { + type = ISC_LOG_TOFILEDESC; + dest.file.stream = stderr; + dest.file.name = NULL; + dest.file.versions = ISC_LOG_ROLLNEVER; + dest.file.suffix = isc_log_rollsuffix_increment; + dest.file.maximum_size = 0; + } + + /* + * Munge flags. + */ + { + const cfg_obj_t *printcat = NULL; + const cfg_obj_t *printsev = NULL; + const cfg_obj_t *printtime = NULL; + const cfg_obj_t *buffered = NULL; + + (void)cfg_map_get(channel, "print-category", &printcat); + (void)cfg_map_get(channel, "print-severity", &printsev); + (void)cfg_map_get(channel, "print-time", &printtime); + (void)cfg_map_get(channel, "buffered", &buffered); + + if (printcat != NULL && cfg_obj_asboolean(printcat)) { + flags |= ISC_LOG_PRINTCATEGORY; + } + if (printsev != NULL && cfg_obj_asboolean(printsev)) { + flags |= ISC_LOG_PRINTLEVEL; + } + if (buffered != NULL && cfg_obj_asboolean(buffered)) { + flags |= ISC_LOG_BUFFERED; + } + if (printtime != NULL && cfg_obj_isboolean(printtime)) { + if (cfg_obj_asboolean(printtime)) { + flags |= ISC_LOG_PRINTTIME; + } + } else if (printtime != NULL) { /* local/iso8601/iso8601-utc */ + const char *s = cfg_obj_asstring(printtime); + flags |= ISC_LOG_PRINTTIME; + if (strcasecmp(s, "iso8601") == 0) { + flags |= ISC_LOG_ISO8601; + } else if (strcasecmp(s, "iso8601-utc") == 0) { + flags |= ISC_LOG_ISO8601 | ISC_LOG_UTC; + } + } + } + + level = ISC_LOG_INFO; + if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) { + if (cfg_obj_isstring(severity)) { + const char *str = cfg_obj_asstring(severity); + if (strcasecmp(str, "critical") == 0) { + level = ISC_LOG_CRITICAL; + } else if (strcasecmp(str, "error") == 0) { + level = ISC_LOG_ERROR; + } else if (strcasecmp(str, "warning") == 0) { + level = ISC_LOG_WARNING; + } else if (strcasecmp(str, "notice") == 0) { + level = ISC_LOG_NOTICE; + } else if (strcasecmp(str, "info") == 0) { + level = ISC_LOG_INFO; + } else if (strcasecmp(str, "dynamic") == 0) { + level = ISC_LOG_DYNAMIC; + } + } else { + /* debug */ + level = cfg_obj_asuint32(severity); + } + } + + if (logconfig != NULL) { + isc_log_createchannel(logconfig, channelname, type, level, + &dest, flags); + } + + if (type == ISC_LOG_TOFILE) { + FILE *fp; + + /* + * Test to make sure that file is a plain file. + * Fix defect #22771 + */ + result = isc_file_isplainfile(dest.file.name); + if (result == ISC_R_SUCCESS || result == ISC_R_FILENOTFOUND) { + /* + * Test that the file can be opened, since + * isc_log_open() can't effectively report + * failures when called in isc_log_doit(). + */ + result = isc_stdio_open(dest.file.name, "a", &fp); + if (result != ISC_R_SUCCESS) { + if (logconfig != NULL && !named_g_nosyslog) { + syslog(LOG_ERR, + "isc_stdio_open '%s' failed: " + "%s", + dest.file.name, + isc_result_totext(result)); + } + } else { + (void)isc_stdio_close(fp); + } + goto done; + } + if (logconfig != NULL && !named_g_nosyslog) { + syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s", + dest.file.name, isc_result_totext(result)); + } + } + +done: + return result; +} + +isc_result_t +named_logconfig(isc_logconfig_t *logconfig, const cfg_obj_t *logstmt) { + isc_result_t result; + const cfg_obj_t *channels = NULL; + const cfg_obj_t *categories = NULL; + const cfg_listelt_t *element; + bool default_set = false; + bool unmatched_set = false; + const cfg_obj_t *catname; + + if (logconfig != NULL) { + named_log_setdefaultchannels(logconfig); + named_log_setdefaultsslkeylogfile(logconfig); + } + + (void)cfg_map_get(logstmt, "channel", &channels); + for (element = cfg_list_first(channels); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *channel = cfg_listelt_value(element); + CHECK(channel_fromconf(channel, logconfig)); + } + + (void)cfg_map_get(logstmt, "category", &categories); + for (element = cfg_list_first(categories); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *category = cfg_listelt_value(element); + CHECK(category_fromconf(category, logconfig)); + if (!default_set) { + catname = cfg_tuple_get(category, "name"); + if (strcmp(cfg_obj_asstring(catname), "default") == 0) { + default_set = true; + } + } + if (!unmatched_set) { + catname = cfg_tuple_get(category, "name"); + if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0) + { + unmatched_set = true; + } + } + } + + if (logconfig != NULL && !default_set) { + CHECK(named_log_setdefaultcategory(logconfig)); + } + + if (logconfig != NULL && !unmatched_set) { + CHECK(named_log_setunmatchedcategory(logconfig)); + } + + return ISC_R_SUCCESS; + +cleanup: + return result; +} diff --git a/bin/named/main.c b/bin/named/main.c new file mode 100644 index 0000000..ed414f9 --- /dev/null +++ b/bin/named/main.c @@ -0,0 +1,1645 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DNSTAP +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_GPERFTOOLS_PROFILER +#include +#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ + +#ifdef HAVE_JSON_C +#include +#endif /* HAVE_JSON_C */ + +#ifdef HAVE_GEOIP2 +#include +#endif /* ifdef HAVE_GEOIP2 */ + +/* + * Defining NAMED_MAIN provides storage declarations (rather than extern) + * for variables in named/globals.h. + */ +#define NAMED_MAIN 1 + +#include + +#include +#include +#include +#include +#include /* Explicit, though named/log.h includes it. */ +#include +#include +#include +#include +#ifdef HAVE_LIBSCF +#include +#endif /* ifdef HAVE_LIBSCF */ + +#include +#include +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 +#include +#include +#endif +#ifdef HAVE_LIBXML2 +#include +#include +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_ZLIB +#include +#endif /* ifdef HAVE_ZLIB */ +#ifdef HAVE_LIBNGHTTP2 +#include +#endif + +/* On DragonFly BSD the header does not provide jemalloc API */ +#if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) +#include +#include /* For M_VERSION */ +#elif defined(HAVE_JEMALLOC) +#include +#endif + +/* + * Include header files for database drivers here. + */ +/* #include "xxdb.h" */ + +extern unsigned int dns_zone_mkey_hour; +extern unsigned int dns_zone_mkey_day; +extern unsigned int dns_zone_mkey_month; + +static bool want_stats = false; +static char program_name[NAME_MAX] = "named"; +static char absolute_conffile[PATH_MAX]; +static char saved_command_line[4096] = { 0 }; +static char ellipsis[5] = { 0 }; +static char version[512]; +static int maxudp = 0; + +/* + * -T options: + */ +static bool cookiealwaysvalid = false; +static bool dropedns = false; +static bool ednsformerr = false; +static bool ednsnotimp = false; +static bool ednsrefused = false; +static bool fixedlocal = false; +static bool noaa = false; +static bool noedns = false; +static bool nonearest = false; +static bool nosoa = false; +static bool notcp = false; +static bool sigvalinsecs = false; +static bool transferinsecs = false; +static bool transferslowly = false; +static bool transferstuck = false; + +/* + * -4 and -6 + */ +static bool disable6 = false; +static bool disable4 = false; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 +static OSSL_PROVIDER *fips = NULL, *base = NULL; +#endif + +void +named_main_earlywarning(const char *format, ...) { + va_list args; + + va_start(args, format); + if (named_g_lctx != NULL) { + isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_WARNING, format, + args); + } else { + fprintf(stderr, "%s: ", program_name); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); + } + va_end(args); +} + +void +named_main_earlyfatal(const char *format, ...) { + va_list args; + + va_start(args, format); + if (named_g_lctx != NULL) { + isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, + args); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, + "exiting (due to early fatal error)"); + } else { + fprintf(stderr, "%s: ", program_name); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); + } + va_end(args); + + _exit(EXIT_FAILURE); +} + +noreturn static void +assertion_failed(const char *file, int line, isc_assertiontype_t type, + const char *cond); + +static void +assertion_failed(const char *file, int line, isc_assertiontype_t type, + const char *cond) { + /* + * Handle assertion failures. + */ + + if (named_g_lctx != NULL) { + /* + * Reset the assertion callback in case it is the log + * routines causing the assertion. + */ + isc_assertion_setcallback(NULL); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, + "%s:%d: %s(%s) failed", file, line, + isc_assertion_typetotext(type), cond); + isc_backtrace_log(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, + "exiting (due to assertion failure)"); + } else { + fprintf(stderr, "%s:%d: %s(%s) failed\n", file, line, + isc_assertion_typetotext(type), cond); + fflush(stderr); + } + + if (named_g_coreok) { + abort(); + } + _exit(EXIT_FAILURE); +} + +noreturn static void +library_fatal_error(const char *file, int line, const char *func, + const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0); + +static void +library_fatal_error(const char *file, int line, const char *func, + const char *format, va_list args) { + /* + * Handle isc_error_fatal() calls from our libraries. + */ + + if (named_g_lctx != NULL) { + /* + * Reset the error callback in case it is the log + * routines causing the assertion. + */ + isc_error_setfatal(NULL); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, + "%s:%d:%s(): fatal error: ", file, line, func); + isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, format, + args); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, + "exiting (due to fatal error in library)"); + } else { + fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); + } + + if (named_g_coreok) { + abort(); + } + _exit(EXIT_FAILURE); +} + +static void +library_unexpected_error(const char *file, int line, const char *func, + const char *format, va_list args) + ISC_FORMAT_PRINTF(3, 0); + +static void +library_unexpected_error(const char *file, int line, const char *func, + const char *format, va_list args) { + /* + * Handle isc_error_unexpected() calls from our libraries. + */ + + if (named_g_lctx != NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR, + "%s:%d:%s(): unexpected error: ", file, line, + func); + isc_log_vwrite(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_ERROR, format, + args); + } else { + fprintf(stderr, "%s:%d:%s(): fatal error: ", file, line, func); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +static void +usage(void) { + fprintf(stderr, "usage: named [-4|-6] [-c conffile] [-d debuglevel] " + "[-D comment] [-E engine]\n" + " [-f|-g] [-L logfile] [-n number_of_cpus] " + "[-p port] [-s]\n" + " [-S sockets] [-t chrootdir] [-u " + "username] [-U listeners]\n" + " [-m " + "{usage|trace|record}]\n" + " [-M fill|nofill]\n" + "usage: named [-v|-V|-C]\n"); +} + +static void +save_command_line(int argc, char *argv[]) { + int i; + char *dst = saved_command_line; + char *eob = saved_command_line + sizeof(saved_command_line) - 1; + char *rollback = dst; + + for (i = 1; i < argc && dst < eob; i++) { + char *src = argv[i]; + bool quoted = false; + + rollback = dst; + *dst++ = ' '; + + while (*src != '\0' && dst < eob) { + if (isalnum(*(unsigned char *)src) || *src == ',' || + *src == '-' || *src == '_' || *src == '.' || + *src == '/') + { + *dst++ = *src++; + } else if (isprint(*(unsigned char *)src)) { + if (dst + 2 >= eob) { + goto add_ellipsis; + } + *dst++ = '\\'; + *dst++ = *src++; + } else { + /* + * Control character found in the input, + * quote the whole arg and restart + */ + if (!quoted) { + dst = rollback; + src = argv[i]; + + if (dst + 3 >= eob) { + goto add_ellipsis; + } + + *dst++ = ' '; + *dst++ = '$'; + *dst++ = '\''; + + quoted = true; + continue; + } else { + char tmp[5]; + int c = snprintf(tmp, sizeof(tmp), + "\\%03o", *src++); + if (dst + c >= eob) { + goto add_ellipsis; + } + memmove(dst, tmp, c); + dst += c; + } + } + } + if (quoted) { + if (dst == eob) { + goto add_ellipsis; + } + *dst++ = '\''; + } + } + + if (dst < eob) { + return; + } +add_ellipsis: + dst = rollback; + *dst = '\0'; + strlcpy(ellipsis, " ...", sizeof(ellipsis)); +} + +static int +parse_int(char *arg, const char *desc) { + char *endp; + int tmp; + long int ltmp; + + ltmp = strtol(arg, &endp, 10); + tmp = (int)ltmp; + if (*endp != '\0') { + named_main_earlyfatal("%s '%s' must be numeric", desc, arg); + } + if (tmp < 0 || tmp != ltmp) { + named_main_earlyfatal("%s '%s' out of range", desc, arg); + } + return tmp; +} + +static struct flag_def { + const char *name; + unsigned int value; + bool negate; +} mem_debug_flags[] = { { "none", 0, false }, + { "trace", ISC_MEM_DEBUGTRACE, false }, + { "record", ISC_MEM_DEBUGRECORD, false }, + { "usage", ISC_MEM_DEBUGUSAGE, false }, + { NULL, 0, false } }, + mem_context_flags[] = { { "fill", ISC_MEMFLAG_FILL, false }, + { "nofill", ISC_MEMFLAG_FILL, true }, + { NULL, 0, false } }; + +static void +set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) { + bool clear = false; + + for (;;) { + const struct flag_def *def; + const char *end = strchr(arg, ','); + int arglen; + if (end == NULL) { + end = arg + strlen(arg); + } + arglen = (int)(end - arg); + for (def = defs; def->name != NULL; def++) { + if (arglen == (int)strlen(def->name) && + memcmp(arg, def->name, arglen) == 0) + { + if (def->value == 0) { + clear = true; + } + if (def->negate) { + *ret &= ~(def->value); + } else { + *ret |= def->value; + } + goto found; + } + } + named_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg); + found: + if (clear || (*end == '\0')) { + break; + } + arg = end + 1; + } + + if (clear) { + *ret = 0; + } +} + +static void +list_dnssec_algorithms(isc_buffer_t *b) { + for (dst_algorithm_t i = DST_ALG_UNKNOWN; i < DST_MAX_ALGS; i++) { + if (i == DST_ALG_GSSAPI || + (i >= DST_ALG_HMAC_FIRST && i <= DST_ALG_HMAC_LAST)) + { + continue; + } + if (dst_algorithm_supported(i)) { + isc_buffer_putstr(b, " "); + (void)dns_secalg_totext(i, b); + } + } +} + +static void +list_ds_algorithms(isc_buffer_t *b) { + for (size_t i = 0; i < 256; i++) { + if (dst_ds_digest_supported(i)) { + isc_buffer_putstr(b, " "); + (void)dns_dsdigest_totext(i, b); + } + } +} + +static void +list_hmac_algorithms(isc_buffer_t *b) { + isc_buffer_t sb = *b; + for (dst_algorithm_t i = DST_ALG_HMAC_FIRST; i <= DST_ALG_HMAC_LAST; + i++) + { + if (i == DST_ALG_GSSAPI) { + continue; + } + if (dst_algorithm_supported(i)) { + isc_buffer_putstr(b, " "); + isc_buffer_putstr(b, dst_hmac_algorithm_totext(i)); + } + } + for (unsigned char *s = isc_buffer_used(&sb); s != isc_buffer_used(b); + s++) + { + *s = toupper(*s); + } +} + +static void +logit(isc_buffer_t *b) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "%.*s", + (int)isc_buffer_usedlength(b), + (char *)isc_buffer_base(b)); +} + +static void +printit(isc_buffer_t *b) { + printf("%.*s\n", (int)isc_buffer_usedlength(b), + (char *)isc_buffer_base(b)); +} + +static void +format_supported_algorithms(void (*emit)(isc_buffer_t *b)) { + isc_buffer_t b; + char buf[512]; + + isc_buffer_init(&b, buf, sizeof(buf)); + isc_buffer_putstr(&b, "DNSSEC algorithms:"); + list_dnssec_algorithms(&b); + (*emit)(&b); + + isc_buffer_init(&b, buf, sizeof(buf)); + isc_buffer_putstr(&b, "DS algorithms:"); + list_ds_algorithms(&b); + (*emit)(&b); + + isc_buffer_init(&b, buf, sizeof(buf)); + isc_buffer_putstr(&b, "HMAC algorithms:"); + list_hmac_algorithms(&b); + (*emit)(&b); + + isc_buffer_init(&b, buf, sizeof(buf)); + isc_buffer_printf(&b, "TKEY mode 2 support (Diffie-Hellman): %s", "no"); + (*emit)(&b); + + isc_buffer_init(&b, buf, sizeof(buf)); + isc_buffer_printf(&b, "TKEY mode 3 support (GSS-API): %s", + dst_algorithm_supported(DST_ALG_GSSAPI) ? "yes" + : "no"); + (*emit)(&b); +} + +static void +printversion(bool verbose) { + char rndcconf[PATH_MAX], *dot = NULL; + isc_mem_t *mctx = NULL; + isc_result_t result; + isc_buffer_t b; + char buf[512]; +#if defined(HAVE_GEOIP2) + cfg_parser_t *parser = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *defaults = NULL, *obj = NULL; +#endif /* if defined(HAVE_GEOIP2) */ + + printf("%s%s \n", PACKAGE_STRING, PACKAGE_DESCRIPTION, + PACKAGE_SRCID); + + if (!verbose) { + return; + } + + printf("running on %s\n", named_os_uname()); + printf("built by %s with %s\n", PACKAGE_BUILDER, PACKAGE_CONFIGARGS); +#ifdef __clang__ + printf("compiled by CLANG %s\n", __VERSION__); +#else /* ifdef __clang__ */ +#if defined(__ICC) || defined(__INTEL_COMPILER) + printf("compiled by ICC %s\n", __VERSION__); +#else /* if defined(__ICC) || defined(__INTEL_COMPILER) */ +#ifdef __GNUC__ + printf("compiled by GCC %s\n", __VERSION__); +#endif /* ifdef __GNUC__ */ +#endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */ +#endif /* ifdef __clang__ */ +#ifdef __SUNPRO_C + printf("compiled by Solaris Studio %x\n", __SUNPRO_C); +#endif /* ifdef __SUNPRO_C */ + printf("compiled with OpenSSL version: %s\n", OPENSSL_VERSION_TEXT); +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */ + printf("linked to OpenSSL version: %s\n", + OpenSSL_version(OPENSSL_VERSION)); + +#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ + * 0x10100000L */ + printf("linked to OpenSSL version: %s\n", + SSLeay_version(SSLEAY_VERSION)); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + printf("compiled with libuv version: %d.%d.%d\n", UV_VERSION_MAJOR, + UV_VERSION_MINOR, UV_VERSION_PATCH); + printf("linked to libuv version: %s\n", uv_version_string()); + printf("compiled with %s version: %s\n", RCU_FLAVOR, RCU_VERSION); +#if defined(JEMALLOC_VERSION) + printf("compiled with jemalloc version: %u.%u.%u\n", + JEMALLOC_VERSION_MAJOR, JEMALLOC_VERSION_MINOR, + JEMALLOC_VERSION_BUGFIX); +#elif defined(M_VERSION) + printf("compiled with system jemalloc version: %u\n", M_VERSION); +#endif +#if HAVE_LIBNGHTTP2 + nghttp2_info *nginfo = NULL; + printf("compiled with libnghttp2 version: %s\n", NGHTTP2_VERSION); + nginfo = nghttp2_version(1); + printf("linked to libnghttp2 version: %s\n", nginfo->version_str); +#endif +#ifdef HAVE_LIBXML2 + printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION); + printf("linked to libxml2 version: %s\n", xmlParserVersion); +#endif /* ifdef HAVE_LIBXML2 */ +#if defined(HAVE_JSON_C) + printf("compiled with json-c version: %s\n", JSON_C_VERSION); + printf("linked to json-c version: %s\n", json_c_version()); +#endif /* if defined(HAVE_JSON_C) */ +#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) + printf("compiled with zlib version: %s\n", ZLIB_VERSION); + printf("linked to zlib version: %s\n", zlibVersion()); +#endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */ +#if defined(HAVE_GEOIP2) + /* Unfortunately, no version define on link time */ + printf("linked to maxminddb version: %s\n", MMDB_lib_version()); +#endif /* if defined(HAVE_GEOIP2) */ +#if defined(HAVE_DNSTAP) + printf("compiled with protobuf-c version: %s\n", PROTOBUF_C_VERSION); + printf("linked to protobuf-c version: %s\n", protobuf_c_version()); +#endif /* if defined(HAVE_DNSTAP) */ + printf("threads support is enabled\n"); + + isc_mem_create(&mctx); + result = dst_lib_init(mctx, named_g_engine); + if (result == ISC_R_SUCCESS) { + isc_buffer_init(&b, buf, sizeof(buf)); + format_supported_algorithms(printit); + printf("\n"); + dst_lib_destroy(); + } else { + printf("DST initialization failure: %s\n", + isc_result_totext(result)); + } + + /* + * The default rndc.conf and rndc.key paths are in the same + * directory, but named only has rndc.key defined internally. + * We construct the rndc.conf path from it. + */ + strlcpy(rndcconf, named_g_keyfile, sizeof(rndcconf)); + dot = strrchr(rndcconf, '.'); + if (dot != NULL) { + size_t len = dot - rndcconf + 1; + snprintf(dot + 1, PATH_MAX - len, "conf"); + } + + /* + * Print default configuration paths. + */ + printf("default paths:\n"); + printf(" named configuration: %s\n", named_g_conffile); + printf(" rndc configuration: %s\n", rndcconf); + printf(" nsupdate session key: %s\n", named_g_defaultsessionkeyfile); + printf(" named PID file: %s\n", named_g_defaultpidfile); +#if defined(HAVE_GEOIP2) +#define RTC(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) + RTC(cfg_parser_create(mctx, named_g_lctx, &parser)); + RTC(named_config_parsedefaults(parser, &config)); + RTC(cfg_map_get(config, "options", &defaults)); + RTC(cfg_map_get(defaults, "geoip-directory", &obj)); + if (cfg_obj_isstring(obj)) { + printf(" geoip-directory: %s\n", cfg_obj_asstring(obj)); + } + cfg_obj_destroy(parser, &config); + cfg_parser_destroy(&parser); + isc_mem_detach(&mctx); +#endif /* HAVE_GEOIP2 */ +} + +static void +parse_fuzz_arg(void) { + if (!strncmp(isc_commandline_argument, "client:", 7)) { + named_g_fuzz_addr = isc_commandline_argument + 7; + named_g_fuzz_type = isc_fuzz_client; + } else if (!strncmp(isc_commandline_argument, "tcp:", 4)) { + named_g_fuzz_addr = isc_commandline_argument + 4; + named_g_fuzz_type = isc_fuzz_tcpclient; + } else if (!strncmp(isc_commandline_argument, "resolver:", 9)) { + named_g_fuzz_addr = isc_commandline_argument + 9; + named_g_fuzz_type = isc_fuzz_resolver; + } else if (!strncmp(isc_commandline_argument, "http:", 5)) { + named_g_fuzz_addr = isc_commandline_argument + 5; + named_g_fuzz_type = isc_fuzz_http; + } else if (!strncmp(isc_commandline_argument, "rndc:", 5)) { + named_g_fuzz_addr = isc_commandline_argument + 5; + named_g_fuzz_type = isc_fuzz_rndc; + } else { + named_main_earlyfatal("unknown fuzzing type '%s'", + isc_commandline_argument); + } +} + +static void +parse_T_opt(char *option) { + const char *p; + char *last = NULL; + /* + * force the server to behave (or misbehave) in + * specified ways for testing purposes. + */ + if (!strcmp(option, "cookiealwaysvalid")) { + cookiealwaysvalid = true; + } else if (!strcmp(option, "dropedns")) { + dropedns = true; + } else if (!strcmp(option, "ednsformerr")) { + ednsformerr = true; + } else if (!strcmp(option, "ednsnotimp")) { + ednsnotimp = true; + } else if (!strcmp(option, "ednsrefused")) { + ednsrefused = true; + } else if (!strcmp(option, "fixedlocal")) { + fixedlocal = true; + } else if (!strcmp(option, "keepstderr")) { + named_g_keepstderr = true; + } else if (!strcmp(option, "noaa")) { + noaa = true; + } else if (!strcmp(option, "noedns")) { + noedns = true; + } else if (!strcmp(option, "nonearest")) { + nonearest = true; + } else if (!strcmp(option, "nosoa")) { + nosoa = true; + } else if (!strcmp(option, "nosyslog")) { + named_g_nosyslog = true; + } else if (!strcmp(option, "notcp")) { + notcp = true; + } else if (!strncmp(option, "maxcachesize=", 13)) { + named_g_maxcachesize = atoi(option + 13); + } else if (!strcmp(option, "maxudp512")) { + maxudp = 512; + } else if (!strcmp(option, "maxudp1460")) { + maxudp = 1460; + } else if (!strncmp(option, "maxudp=", 7)) { + maxudp = atoi(option + 7); + if (maxudp <= 0) { + named_main_earlyfatal("bad maxudp"); + } + } else if (!strncmp(option, "mkeytimers=", 11)) { + p = strtok_r(option + 11, "/", &last); + if (p == NULL) { + named_main_earlyfatal("bad mkeytimer"); + } + + dns_zone_mkey_hour = atoi(p); + if (dns_zone_mkey_hour == 0) { + named_main_earlyfatal("bad mkeytimer"); + } + + p = strtok_r(NULL, "/", &last); + if (p == NULL) { + dns_zone_mkey_day = (24 * dns_zone_mkey_hour); + dns_zone_mkey_month = (30 * dns_zone_mkey_day); + return; + } + + dns_zone_mkey_day = atoi(p); + if (dns_zone_mkey_day < dns_zone_mkey_hour) { + named_main_earlyfatal("bad mkeytimer"); + } + + p = strtok_r(NULL, "/", &last); + if (p == NULL) { + dns_zone_mkey_month = (30 * dns_zone_mkey_day); + return; + } + + dns_zone_mkey_month = atoi(p); + if (dns_zone_mkey_month < dns_zone_mkey_day) { + named_main_earlyfatal("bad mkeytimer"); + } + } else if (!strcmp(option, "sigvalinsecs")) { + sigvalinsecs = true; + } else if (!strcmp(option, "transferinsecs")) { + transferinsecs = true; + } else if (!strcmp(option, "transferslowly")) { + transferslowly = true; + } else if (!strcmp(option, "transferstuck")) { + transferstuck = true; + } else if (!strncmp(option, "tat=", 4)) { + named_g_tat_interval = atoi(option + 4); + } else { + fprintf(stderr, "unknown -T flag '%s'\n", option); + } +} + +static void +parse_port(char *arg) { + enum { DNSPORT, TLSPORT, HTTPSPORT, HTTPPORT } ptype = DNSPORT; + char *value = arg; + int port; + + if (strncmp(arg, "dns=", 4) == 0) { + value = arg + 4; + } else if (strncmp(arg, "tls=", 4) == 0) { + value = arg + 4; + ptype = TLSPORT; + } else if (strncmp(arg, "https=", 6) == 0) { + value = arg + 6; + ptype = HTTPSPORT; + } else if (strncmp(arg, "http=", 5) == 0) { + value = arg + 6; + ptype = HTTPPORT; + } + + port = parse_int(value, "port"); + if (port < 1 || port > 65535) { + named_main_earlyfatal("port '%s' out of range", value); + } + + switch (ptype) { + case DNSPORT: + named_g_port = port; + break; + case TLSPORT: + named_g_tlsport = port; + break; + case HTTPSPORT: + named_g_httpsport = port; + break; + case HTTPPORT: + named_g_httpport = port; + break; + default: + UNREACHABLE(); + } +} + +static void +parse_command_line(int argc, char *argv[]) { + int ch; + const char *p; + + save_command_line(argc, argv); + + /* + * NAMED_MAIN_ARGS is defined in main.h, so that it can be used + * both by named and by ntservice hooks. + */ + isc_commandline_errprint = false; + while ((ch = isc_commandline_parse(argc, argv, NAMED_MAIN_ARGS)) != -1) + { + switch (ch) { + case '4': + if (disable4) { + named_main_earlyfatal("cannot specify " + "-4 and -6"); + } + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + named_main_earlyfatal("IPv4 not supported " + "by OS"); + } + isc_net_disableipv6(); + disable6 = true; + break; + case '6': + if (disable6) { + named_main_earlyfatal("cannot specify " + "-4 and -6"); + } + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + named_main_earlyfatal("IPv6 not supported " + "by OS"); + } + isc_net_disableipv4(); + disable4 = true; + break; + case 'A': + parse_fuzz_arg(); + break; + case 'c': + named_g_conffile = isc_commandline_argument; + named_g_conffileset = true; + break; + case 'C': + printf("# Built-in default values. " + "This is NOT the run-time configuration!\n"); + printf("%s", named_config_getdefault()); + exit(EXIT_SUCCESS); + case 'd': + named_g_debuglevel = parse_int(isc_commandline_argument, + "debug " + "level"); + break; + case 'D': + /* Descriptive comment for 'ps'. */ + break; + case 'E': + named_g_engine = isc_commandline_argument; + break; + case 'f': + named_g_foreground = true; + break; + case 'g': + named_g_foreground = true; + named_g_logstderr = true; + break; + case 'L': + named_g_logfile = isc_commandline_argument; + break; + case 'M': + set_flags(isc_commandline_argument, mem_context_flags, + &isc_mem_defaultflags); + break; + case 'm': + set_flags(isc_commandline_argument, mem_debug_flags, + &isc_mem_debugging); + break; + case 'N': /* Deprecated. */ + case 'n': + named_g_cpus = parse_int(isc_commandline_argument, + "number of cpus"); + if (named_g_cpus == 0) { + named_g_cpus = 1; + } + break; + case 'p': + parse_port(isc_commandline_argument); + break; + case 's': + /* XXXRTH temporary syntax */ + want_stats = true; + break; + case 'S': + /* Formerly maxsocks */ + break; + case 't': + /* XXXJAB should we make a copy? */ + named_g_chrootdir = isc_commandline_argument; + break; + case 'T': /* NOT DOCUMENTED */ + parse_T_opt(isc_commandline_argument); + break; + case 'U': + /* Obsolete. No longer in use. Ignore. */ + named_main_earlywarning("option '-U' has been removed"); + break; + case 'u': + named_g_username = isc_commandline_argument; + break; + case 'v': + printversion(false); + exit(EXIT_SUCCESS); + case 'V': + printversion(true); + exit(EXIT_SUCCESS); + case 'x': + /* Obsolete. No longer in use. Ignore. */ + break; + case 'X': + /* Obsolete. No longer in use. Abort. */ + named_main_earlyfatal("option '-X' has been removed"); + break; + case 'F': +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips == NULL) { + ERR_clear_error(); + named_main_earlyfatal( + "Failed to load FIPS provider"); + } + base = OSSL_PROVIDER_load(NULL, "base"); + if (base == NULL) { + OSSL_PROVIDER_unload(fips); + ERR_clear_error(); + named_main_earlyfatal( + "Failed to load base provider"); + } +#endif + if (isc_fips_mode()) { /* Already in FIPS mode. */ + break; + } + if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + named_main_earlyfatal( + "setting FIPS mode failed"); + } + break; + case '?': + usage(); + if (isc_commandline_option == '?') { + exit(EXIT_SUCCESS); + } + p = strchr(NAMED_MAIN_ARGS, isc_commandline_option); + if (p == NULL || *++p != ':') { + named_main_earlyfatal("unknown option '-%c'", + isc_commandline_option); + } else { + named_main_earlyfatal("option '-%c' requires " + "an argument", + isc_commandline_option); + } + FALLTHROUGH; + default: + named_main_earlyfatal("parsing options returned %d", + ch); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + POST(argv); + + if (argc > 0) { + usage(); + named_main_earlyfatal("extra command line arguments"); + } +} + +static isc_result_t +create_managers(void) { + /* + * Set the default named_g_cpus if it was not set from the command line + */ + INSIST(named_g_cpus_detected > 0); + if (named_g_cpus == 0) { + named_g_cpus = named_g_cpus_detected; + } + + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, + ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s", + named_g_cpus_detected, named_g_cpus_detected == 1 ? "" : "s", + named_g_cpus, named_g_cpus == 1 ? "" : "s"); + + isc_managers_create(&named_g_mctx, named_g_cpus, &named_g_loopmgr, + &named_g_netmgr); + + isc_nm_maxudp(named_g_netmgr, maxudp); + + return ISC_R_SUCCESS; +} + +static void +setup(void) { + isc_result_t result; + ns_server_t *sctx; +#ifdef HAVE_LIBSCF + char *instance = NULL; +#endif /* ifdef HAVE_LIBSCF */ + + /* + * Get the user and group information before changing the root + * directory, so the administrator does not need to keep a copy + * of the user and group databases in the chroot'ed environment. + */ + named_os_inituserinfo(named_g_username); + + /* + * Initialize time conversion information + */ + named_os_tzset(); + + named_os_opendevnull(); + +#ifdef HAVE_LIBSCF + /* Check if named is under smf control, before chroot. */ + result = named_smf_get_instance(&instance, 0, named_g_mctx); + /* We don't care about instance, just check if we got one. */ + if (result == ISC_R_SUCCESS) { + named_smf_got_instance = 1; + } else { + named_smf_got_instance = 0; + } + if (instance != NULL) { + isc_mem_free(named_g_mctx, instance); + } +#endif /* HAVE_LIBSCF */ + + /* + * Check for the number of cpu's before named_os_chroot(). + */ + named_g_cpus_detected = isc_os_ncpus(); + + named_os_chroot(named_g_chrootdir); + + /* + * For operating systems which have a capability mechanism, now + * is the time to switch to minimal privs and change our user id. + * On traditional UNIX systems, this call will be a no-op, and we + * will change the user ID after reading the config file the first + * time. (We need to read the config file to know which possibly + * privileged ports to bind() to.) + */ + named_os_minprivs(); + + result = named_log_init(named_g_username != NULL); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("named_log_init() failed: %s", + isc_result_totext(result)); + } + + /* + * Now is the time to daemonize (if we're not running in the + * foreground). We waited until now because we wanted to get + * a valid logging context setup. We cannot daemonize any later, + * because calling create_managers() will create threads, which + * would be lost after fork(). + */ + if (!named_g_foreground) { + named_os_daemonize(); + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "starting %s%s ", PACKAGE_STRING, + PACKAGE_DESCRIPTION, PACKAGE_SRCID); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "running on %s", + named_os_uname()); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", + PACKAGE_CONFIGARGS); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "running as: %s%s%s", program_name, saved_command_line, + ellipsis); +#ifdef __clang__ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled by CLANG %s", __VERSION__); +#else /* ifdef __clang__ */ +#if defined(__ICC) || defined(__INTEL_COMPILER) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled by ICC %s", __VERSION__); +#else /* if defined(__ICC) || defined(__INTEL_COMPILER) */ +#ifdef __GNUC__ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled by GCC %s", __VERSION__); +#endif /* ifdef __GNUC__ */ +#endif /* if defined(__ICC) || defined(__INTEL_COMPILER) */ +#endif /* ifdef __clang__ */ +#ifdef __SUNPRO_C + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled by Solaris Studio %x", __SUNPRO_C); +#endif /* ifdef __SUNPRO_C */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with OpenSSL version: %s", + OPENSSL_VERSION_TEXT); +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to OpenSSL version: %s", + OpenSSL_version(OPENSSL_VERSION)); +#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ + * 0x10100000L */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to OpenSSL version: %s", + SSLeay_version(SSLEAY_VERSION)); +#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with libuv version: %d.%d.%d", UV_VERSION_MAJOR, + UV_VERSION_MINOR, UV_VERSION_PATCH); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to libuv version: %s", uv_version_string()); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with %s version: %s", RCU_FLAVOR, RCU_VERSION); +#if defined(JEMALLOC_VERSION) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with jemalloc version: %u.%u.%u", + JEMALLOC_VERSION_MAJOR, JEMALLOC_VERSION_MINOR, + JEMALLOC_VERSION_BUGFIX); +#elif defined(M_VERSION) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with system jemalloc version: %u", M_VERSION); +#endif +#if HAVE_LIBNGHTTP2 + nghttp2_info *nginfo = NULL; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with libnghttp2 version: %s", NGHTTP2_VERSION); + nginfo = nghttp2_version(1); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to libnghttp2 version: %s", nginfo->version_str); +#endif +#ifdef HAVE_LIBXML2 + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with libxml2 version: %s", + LIBXML_DOTTED_VERSION); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to libxml2 version: %s", xmlParserVersion); +#endif /* ifdef HAVE_LIBXML2 */ +#if defined(HAVE_JSON_C) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with json-c version: %s", JSON_C_VERSION); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to json-c version: %s", json_c_version()); +#endif /* if defined(HAVE_JSON_C) */ +#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with zlib version: %s", ZLIB_VERSION); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to zlib version: %s", zlibVersion()); +#endif /* if defined(HAVE_ZLIB) && defined(ZLIB_VERSION) */ +#if defined(HAVE_GEOIP2) + /* Unfortunately, no version define on link time */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to maxminddb version: %s", MMDB_lib_version()); +#endif /* if defined(HAVE_GEOIP2) */ +#if defined(HAVE_DNSTAP) + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "compiled with protobuf-c version: %s", + PROTOBUF_C_VERSION); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "linked to protobuf-c version: %s", protobuf_c_version()); +#endif /* if defined(HAVE_DNSTAP) */ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "----------------------------------------------------"); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "BIND 9 is maintained by Internet Systems Consortium,"); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "Inc. (ISC), a non-profit 501(c)(3) public-benefit "); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "corporation. Support and training for BIND 9 are "); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "available at https://www.isc.org/support"); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "----------------------------------------------------"); + + /* + * System resources cannot effectively be tuned on some systems. + * Raise the limit in such cases for safety. + */ + named_os_adjustnofile(); + + /* + * If the named configuration filename is relative, prepend the current + * directory's name before possibly changing to another directory. + */ + if (!isc_file_isabsolute(named_g_conffile)) { + result = isc_file_absolutepath(named_g_conffile, + absolute_conffile, + sizeof(absolute_conffile)); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("could not construct " + "absolute path " + "of configuration file: %s", + isc_result_totext(result)); + } + named_g_conffile = absolute_conffile; + } + + /* + * Record the server's startup time. + */ + named_g_boottime = isc_time_now(); + + result = create_managers(); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("create_managers() failed: %s", + isc_result_totext(result)); + } + + named_builtin_init(); + + /* + * Add calls to register sdb drivers here. + */ + /* xxdb_init(); */ + + /* + * Register the DLZ "dlopen" driver. + */ + result = dlz_dlopen_init(named_g_mctx); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("dlz_dlopen_init() failed: %s", + isc_result_totext(result)); + } + + named_server_create(named_g_mctx, &named_g_server); + ENSURE(named_g_server != NULL); + sctx = named_g_server->sctx; + + /* + * Report supported algorithms now that dst_lib_init() has + * been called via named_server_create(). + */ + format_supported_algorithms(logit); + + /* + * Modify server context according to command line options + */ + if (cookiealwaysvalid) { + ns_server_setoption(sctx, NS_SERVER_COOKIEALWAYSVALID, true); + } + if (disable4) { + ns_server_setoption(sctx, NS_SERVER_DISABLE4, true); + } + if (disable6) { + ns_server_setoption(sctx, NS_SERVER_DISABLE6, true); + } + if (dropedns) { + ns_server_setoption(sctx, NS_SERVER_DROPEDNS, true); + } + if (ednsformerr) { /* STD13 server */ + ns_server_setoption(sctx, NS_SERVER_EDNSFORMERR, true); + } + if (ednsnotimp) { + ns_server_setoption(sctx, NS_SERVER_EDNSNOTIMP, true); + } + if (ednsrefused) { + ns_server_setoption(sctx, NS_SERVER_EDNSREFUSED, true); + } + if (fixedlocal) { + ns_server_setoption(sctx, NS_SERVER_FIXEDLOCAL, true); + } + if (noaa) { + ns_server_setoption(sctx, NS_SERVER_NOAA, true); + } + if (noedns) { + ns_server_setoption(sctx, NS_SERVER_NOEDNS, true); + } + if (nonearest) { + ns_server_setoption(sctx, NS_SERVER_NONEAREST, true); + } + if (nosoa) { + ns_server_setoption(sctx, NS_SERVER_NOSOA, true); + } + if (notcp) { + ns_server_setoption(sctx, NS_SERVER_NOTCP, true); + } + if (sigvalinsecs) { + ns_server_setoption(sctx, NS_SERVER_SIGVALINSECS, true); + } + if (transferinsecs) { + ns_server_setoption(sctx, NS_SERVER_TRANSFERINSECS, true); + } + if (transferslowly) { + ns_server_setoption(sctx, NS_SERVER_TRANSFERSLOWLY, true); + } + if (transferstuck) { + ns_server_setoption(sctx, NS_SERVER_TRANSFERSTUCK, true); + } +} + +static void +cleanup(void) { + if (named_g_mapped != NULL) { + dns_acl_detach(&named_g_mapped); + } + + named_server_destroy(&named_g_server); + + named_builtin_deinit(); + + /* + * Add calls to unregister sdb drivers here. + */ + /* xxdb_clear(); */ + + /* + * Unregister "dlopen" DLZ driver. + */ + dlz_dlopen_clear(); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "exiting"); + named_log_shutdown(); +} + +static char *memstats = NULL; + +void +named_main_setmemstats(const char *filename) { + /* + * Caller has to ensure locking. + */ + + if (memstats != NULL) { + free(memstats); + memstats = NULL; + } + + if (filename == NULL) { + return; + } + + memstats = strdup(filename); +} + +#ifdef HAVE_LIBSCF +/* + * Get FMRI for the named process. + */ +isc_result_t +named_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) { + scf_handle_t *h = NULL; + int namelen; + char *instance; + + REQUIRE(ins_name != NULL && *ins_name == NULL); + + if ((h = scf_handle_create(SCF_VERSION)) == NULL) { + if (debug) { + UNEXPECTED_ERROR("scf_handle_create() failed: %s", + scf_strerror(scf_error())); + } + return ISC_R_FAILURE; + } + + if (scf_handle_bind(h) == -1) { + if (debug) { + UNEXPECTED_ERROR("scf_handle_bind() failed: %s", + scf_strerror(scf_error())); + } + scf_handle_destroy(h); + return ISC_R_FAILURE; + } + + if ((namelen = scf_myname(h, NULL, 0)) == -1) { + if (debug) { + UNEXPECTED_ERROR("scf_myname() failed: %s", + scf_strerror(scf_error())); + } + scf_handle_destroy(h); + return ISC_R_FAILURE; + } + + if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) { + UNEXPECTED_ERROR("named_smf_get_instance memory " + "allocation failed: %s", + isc_result_totext(ISC_R_NOMEMORY)); + scf_handle_destroy(h); + return ISC_R_FAILURE; + } + + if (scf_myname(h, instance, namelen + 1) == -1) { + if (debug) { + UNEXPECTED_ERROR("scf_myname() failed: %s", + scf_strerror(scf_error())); + } + scf_handle_destroy(h); + isc_mem_free(mctx, instance); + return ISC_R_FAILURE; + } + + scf_handle_destroy(h); + *ins_name = instance; + return ISC_R_SUCCESS; +} +#endif /* HAVE_LIBSCF */ + +/* main entry point, possibly hooked */ + +int +main(int argc, char *argv[]) { + isc_result_t result; +#ifdef HAVE_LIBSCF + char *instance = NULL; +#endif /* ifdef HAVE_LIBSCF */ + +#ifdef HAVE_GPERFTOOLS_PROFILER + (void)ProfilerStart(NULL); +#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ + + /* + * Technically, this call is superfluous because on startup of the main + * program, the portable "C" locale is selected by default. This + * explicit call here is for a reference that the BIND 9 code base is + * not locale aware and the locale MUST be set to "C" (or "POSIX") when + * calling any BIND 9 library code. If you are calling external + * libraries that use locale, such calls must be wrapped into + * setlocale(LC_ALL, ""); before the call and setlocale(LC_ALL, "C"); + * after the call, and no BIND 9 library calls must be made in between. + */ + setlocale(LC_ALL, "C"); + + /* + * Record version in core image. + * strings named.core | grep "named version:" + */ + strlcat(version, +#if defined(NO_VERSION_DATE) || !defined(__DATE__) + "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID ">", +#else + "named version: BIND " PACKAGE_VERSION " <" PACKAGE_SRCID + "> (" __DATE__ ")", +#endif + sizeof(version)); + result = isc_file_progname(*argv, program_name, sizeof(program_name)); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("program name too long"); + } + + isc_assertion_setcallback(assertion_failed); + isc_error_setfatal(library_fatal_error); + isc_error_setunexpected(library_unexpected_error); + + named_os_init(program_name); + + parse_command_line(argc, argv); + +#ifdef ENABLE_AFL + if (named_g_fuzz_type != isc_fuzz_none) { + named_fuzz_setup(); + } + + if (named_g_fuzz_type == isc_fuzz_resolver) { + dns_resolver_setfuzzing(); + } else if (named_g_fuzz_type == isc_fuzz_http) { + isc_httpd_setfinishhook(named_fuzz_notify); + } +#endif /* ifdef ENABLE_AFL */ + /* + * Warn about common configuration error. + */ + if (named_g_chrootdir != NULL) { + int len = strlen(named_g_chrootdir); + if (strncmp(named_g_chrootdir, named_g_conffile, len) == 0 && + (named_g_conffile[len] == '/' || + named_g_conffile[len] == '\\')) + { + named_main_earlywarning("config filename (-c %s) " + "contains chroot path (-t %s)", + named_g_conffile, + named_g_chrootdir); + } + } + + setup(); + isc_mem_setname(named_g_mctx, "main"); + INSIST(named_g_server != NULL); + + /* + * Start things running + */ + isc_signal_start(named_g_server->sighup); + + /* + * Pause the loop manager in fatal. + */ + named_g_loopmgr_running = true; + isc_loopmgr_run(named_g_loopmgr); + +#ifdef HAVE_LIBSCF + if (named_smf_want_disable == 1) { + result = named_smf_get_instance(&instance, 1, named_g_mctx); + if (result == ISC_R_SUCCESS && instance != NULL) { + if (smf_disable_instance(instance, 0) != 0) { + UNEXPECTED_ERROR("smf_disable_instance() " + "failed for %s : %s", + instance, + scf_strerror(scf_error())); + } + } + if (instance != NULL) { + isc_mem_free(named_g_mctx, instance); + } + } +#endif /* HAVE_LIBSCF */ + + cleanup(); + + if (want_stats) { + isc_mem_stats(named_g_mctx, stdout); + } + + if (named_g_memstatistics && memstats != NULL) { + FILE *fp = NULL; + result = isc_stdio_open(memstats, "w", &fp); + if (result == ISC_R_SUCCESS) { + isc_mem_stats(named_g_mctx, fp); + (void)isc_stdio_close(fp); + } + } + + isc_managers_destroy(&named_g_mctx, &named_g_loopmgr, &named_g_netmgr); + +#if ENABLE_LEAK_DETECTION + isc__tls_setdestroycheck(true); + isc__uv_setdestroycheck(true); + isc__xml_setdestroycheck(true); +#endif + + isc_mem_checkdestroyed(stderr); + + named_main_setmemstats(NULL); + + named_os_closedevnull(); + + named_os_shutdown(); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + if (base != NULL) { + OSSL_PROVIDER_unload(base); + } + if (fips != NULL) { + OSSL_PROVIDER_unload(fips); + } +#endif + +#ifdef HAVE_GPERFTOOLS_PROFILER + ProfilerStop(); +#endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ + + return 0; +} diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst new file mode 100644 index 0000000..89e76bd --- /dev/null +++ b/bin/named/named.conf.rst @@ -0,0 +1,66 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: named.conf + +named.conf - configuration file for **named** +--------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`named.conf` + +Description +~~~~~~~~~~~ + +:file:`named.conf` is the configuration file for :iscman:`named`. + +For complete documentation about the configuration statements, please refer to +the Configuration Reference section in the BIND 9 Administrator Reference +Manual. + +Statements are enclosed in braces and terminated with a semi-colon. +Clauses in the statements are also semi-colon terminated. The usual +comment styles are supported: + +C style: /\* \*/ + +C++ style: // to end of line + +Unix style: # to end of line + +.. literalinclude:: ../../doc/misc/options + +Any of these zone statements can also be set inside the view statement. + +.. literalinclude:: ../../doc/misc/primary.zoneopt +.. literalinclude:: ../../doc/misc/secondary.zoneopt +.. literalinclude:: ../../doc/misc/mirror.zoneopt +.. literalinclude:: ../../doc/misc/forward.zoneopt +.. literalinclude:: ../../doc/misc/hint.zoneopt +.. literalinclude:: ../../doc/misc/redirect.zoneopt +.. literalinclude:: ../../doc/misc/static-stub.zoneopt +.. literalinclude:: ../../doc/misc/stub.zoneopt +.. literalinclude:: ../../doc/misc/in-view.zoneopt + +Files +~~~~~ + +|named_conf| + +See Also +~~~~~~~~ + +:iscman:`named(8) `, :iscman:`named-checkconf(8) `, :iscman:`rndc(8) `, :iscman:`rndc-confgen(8) `, :iscman:`tsig-keygen(8) `, BIND 9 Administrator Reference Manual. + diff --git a/bin/named/named.rst b/bin/named/named.rst new file mode 100644 index 0000000..4f6a40b --- /dev/null +++ b/bin/named/named.rst @@ -0,0 +1,234 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: named +.. program:: named +.. _man_named: + +named - Internet domain name server +----------------------------------- + +Synopsis +~~~~~~~~ + +:program:`named` [ [**-4**] | [**-6**] ] [**-c** config-file] [**-C**] [**-d** debug-level] [**-D** string] [**-E** engine-name] [**-f**] [**-g**] [**-L** logfile] [**-M** option] [**-m** flag] [**-n** #cpus] [**-p** port] [**-s**] [**-t** directory] [**-u** user] [**-v**] [**-V**] ] + +Description +~~~~~~~~~~~ + +:program:`named` is a Domain Name System (DNS) server, part of the BIND 9 +distribution from ISC. For more information on the DNS, see :rfc:`1033`, +:rfc:`1034`, and :rfc:`1035`. + +When invoked without arguments, :program:`named` reads the default +configuration file |named_conf|, reads any initial data, and +listens for queries. + +Options +~~~~~~~ + +.. option:: -4 + + This option tells :program:`named` to use only IPv4, even if the host machine is capable of IPv6. :option:`-4` and + :option:`-6` are mutually exclusive. + +.. option:: -6 + + This option tells :program:`named` to use only IPv6, even if the host machine is capable of IPv4. :option:`-4` and + :option:`-6` are mutually exclusive. + +.. option:: -c config-file + + This option tells :program:`named` to use ``config-file`` as its configuration file instead of the default, + |named_conf|. To ensure that the configuration file + can be reloaded after the server has changed its working directory + due to to a possible ``directory`` option in the configuration file, + ``config-file`` should be an absolute pathname. + +.. option:: -C + + This option prints out the default built-in configuration and exits. + + NOTE: This is for debugging purposes only and is not an + accurate representation of the actual configuration used by :iscman:`named` + at runtime. + +.. option:: -d debug-level + + This option sets the daemon's debug level to ``debug-level``. Debugging traces from + :program:`named` become more verbose as the debug level increases. + +.. option:: -D string + + This option specifies a string that is used to identify a instance of :program:`named` + in a process listing. The contents of ``string`` are not examined. + +.. option:: -E engine-name + + When applicable, this option specifies the hardware to use for cryptographic + operations, such as a secure key store used for signing. + + When BIND 9 is built with OpenSSL, this needs to be set to the OpenSSL + engine identifier that drives the cryptographic accelerator or + hardware service module (usually ``pkcs11``). + +.. option:: -f + + This option runs the server in the foreground (i.e., do not daemonize). + +.. option:: -F + + This options turns on FIPS (US Federal Information Processing Standards) + mode if the underlying crytographic library supports running in FIPS + mode. + +.. option:: -g + + This option runs the server in the foreground and forces all logging to ``stderr``. + +.. option:: -L logfile + + This option sets the log to the file ``logfile`` by default, instead of the system log. + +.. option:: -M option + + This option sets the default (comma-separated) memory context + options. The possible flags are: + + - ``fill``: fill blocks of memory with tag values when they are + allocated or freed, to assist debugging of memory problems; this is + the implicit default if :program:`named` has been compiled with + ``--enable-developer``. + + - ``nofill``: disable the behavior enabled by ``fill``; this is the + implicit default unless :program:`named` has been compiled with + ``--enable-developer``. + +.. option:: -m flag + + This option turns on memory usage debugging flags. Possible flags are ``usage``, + ``trace`` and ``record``. These correspond to the + ``ISC_MEM_DEBUGXXXX`` flags described in ````. + +.. option:: -n #cpus + + This option creates ``#cpus`` worker threads to take advantage of multiple CPUs. If + not specified, :program:`named` tries to determine the number of CPUs + present and creates one thread per CPU. If it is unable to determine + the number of CPUs, a single worker thread is created. + +.. option:: -p value + + This option specifies the port(s) on which the server will listen + for queries. If ``value`` is of the form ```` or + ``dns=``, the server will listen for DNS queries on + ``portnum``; if not not specified, the default is port 53. If + ``value`` is of the form ``tls=``, the server will + listen for TLS queries on ``portnum``; the default is 853. + If ``value`` is of the form ``https=``, the server will + listen for HTTPS queries on ``portnum``; the default is 443. + If ``value`` is of the form ``http=``, the server will + listen for HTTP queries on ``portnum``; the default is 80. + +.. option:: -s + + This option writes memory usage statistics to ``stdout`` on exit. + +.. note:: + + This option is mainly of interest to BIND 9 developers and may be + removed or changed in a future release. + +.. option:: -t directory + + This option tells :program:`named` to chroot to ``directory`` after processing the command-line arguments, but + before reading the configuration file. + +.. warning:: + + This option should be used in conjunction with the :option:`-u` option, + as chrooting a process running as root doesn't enhance security on + most systems; the way ``chroot`` is defined allows a process + with root privileges to escape a chroot jail. + +.. option:: -U #listeners + + This option has been removed. Attempts to use it now result in a warning. + +.. option:: -u user + + This option sets the setuid to ``user`` after completing privileged operations, such as + creating sockets that listen on privileged ports. + +.. note:: + + On Linux, :program:`named` uses the kernel's capability mechanism to drop + all root privileges except the ability to ``bind`` to a + privileged port and set process resource limits. Unfortunately, + this means that the :option:`-u` option only works when :program:`named` is run + on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or later, since + previous kernels did not allow privileges to be retained after + ``setuid``. + +.. option:: -v + + This option reports the version number and exits. + +.. option:: -V + + This option reports the version number, build options, supported + cryptographics algorithms, and exits. + +.. option:: -X lock-file + + This option has been removed and using it will cause a fatal error. + +Signals +~~~~~~~ + +In routine operation, signals should not be used to control the +nameserver; :iscman:`rndc` should be used instead. + +SIGHUP + This signal forces a reload of the server. + +SIGINT, SIGTERM + These signals shut down the server. + +The result of sending any other signals to the server is undefined. + +Configuration +~~~~~~~~~~~~~ + +The :program:`named` configuration file is too complex to describe in detail +here. A complete description is provided in the BIND 9 Administrator +Reference Manual. + +:program:`named` inherits the ``umask`` (file creation mode mask) from the +parent process. If files created by :program:`named`, such as journal files, +need to have custom permissions, the ``umask`` should be set explicitly +in the script used to start the :program:`named` process. + +Files +~~~~~ + +|named_conf| + The default configuration file. + +|named_pid| + The default process-id file. + +See Also +~~~~~~~~ + +:rfc:`1033`, :rfc:`1034`, :rfc:`1035`, :iscman:`named-checkconf(8) `, :iscman:`named-checkzone(8) `, :iscman:`rndc(8) `, :iscman:`named.conf(5) `, BIND 9 Administrator Reference Manual. diff --git a/bin/named/os.c b/bin/named/os.c new file mode 100644 index 0000000..fe66a4d --- /dev/null +++ b/bin/named/os.c @@ -0,0 +1,867 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ +#include +#include +#include +#include +#include /* dev_t FreeBSD 2.1 */ +#ifdef HAVE_UNAME +#include +#endif /* ifdef HAVE_UNAME */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_TZSET +#include +#endif /* ifdef HAVE_TZSET */ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifdef HAVE_LIBSCF +#include +#endif /* ifdef HAVE_LIBSCF */ + +static char *pidfile = NULL; +static int devnullfd = -1; + +#ifndef ISC_FACILITY +#define ISC_FACILITY LOG_DAEMON +#endif /* ifndef ISC_FACILITY */ + +static struct passwd *runas_pw = NULL; +static bool done_setuid = false; +static int dfd[2] = { -1, -1 }; + +static uid_t saved_uid = (uid_t)-1; +static gid_t saved_gid = (gid_t)-1; + +#if HAVE_LIBCAP + +static bool non_root = false; +static bool non_root_caps = false; + +#include +#include + +static void +linux_setcaps(cap_t caps) { + char strbuf[ISC_STRERRORSIZE]; + + if ((getuid() != 0 && !non_root_caps) || non_root) { + return; + } + if (cap_set_proc(caps) < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("cap_set_proc() failed: %s:" + " please ensure that the capset kernel" + " module is loaded. see insmod(8)", + strbuf); + } +} + +#define SET_CAP(flag) \ + do { \ + cap_flag_value_t curval; \ + capval = (flag); \ + err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \ + if (err != -1 && curval) { \ + err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, \ + CAP_SET); \ + if (err == -1) { \ + strerror_r(errno, strbuf, sizeof(strbuf)); \ + named_main_earlyfatal("cap_set_proc failed: " \ + "%s", \ + strbuf); \ + } \ + \ + err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, \ + CAP_SET); \ + if (err == -1) { \ + strerror_r(errno, strbuf, sizeof(strbuf)); \ + named_main_earlyfatal("cap_set_proc failed: " \ + "%s", \ + strbuf); \ + } \ + } \ + } while (0) +#define INIT_CAP \ + do { \ + caps = cap_init(); \ + if (caps == NULL) { \ + strerror_r(errno, strbuf, sizeof(strbuf)); \ + named_main_earlyfatal("cap_init failed: %s", strbuf); \ + } \ + curcaps = cap_get_proc(); \ + if (curcaps == NULL) { \ + strerror_r(errno, strbuf, sizeof(strbuf)); \ + named_main_earlyfatal("cap_get_proc failed: %s", \ + strbuf); \ + } \ + } while (0) +#define FREE_CAP \ + { \ + cap_free(caps); \ + cap_free(curcaps); \ + } \ + while (0) + +static void +linux_initialprivs(void) { + cap_t caps; + cap_t curcaps; + cap_value_t capval; + char strbuf[ISC_STRERRORSIZE]; + int err; + + /*% + * We don't need most privileges, so we drop them right away. + * Later on linux_minprivs() will be called, which will drop our + * capabilities to the minimum needed to run the server. + */ + INIT_CAP; + + /* + * We need to be able to bind() to privileged ports, notably port 53! + */ + SET_CAP(CAP_NET_BIND_SERVICE); + + /* + * We need chroot() initially too. + */ + SET_CAP(CAP_SYS_CHROOT); + + /* + * We need setuid() as the kernel supports keeping capabilities after + * setuid(). + */ + SET_CAP(CAP_SETUID); + + /* + * Since we call initgroups, we need this. + */ + SET_CAP(CAP_SETGID); + + /* + * Without this, we run into problems reading a configuration file + * owned by a non-root user and non-world-readable on startup. + */ + SET_CAP(CAP_DAC_READ_SEARCH); + + /* + * XXX We might want to add CAP_SYS_RESOURCE, though it's not + * clear it would work right given the way linuxthreads work. + * XXXDCL But since we need to be able to set the maximum number + * of files, the stack size, data size, and core dump size to + * support named.conf options, this is now being added to test. + */ + SET_CAP(CAP_SYS_RESOURCE); + + /* + * We need to be able to set the ownership of the containing + * directory of the pid file when we create it. + */ + SET_CAP(CAP_CHOWN); + + linux_setcaps(caps); + + FREE_CAP; +} + +static void +linux_minprivs(void) { + cap_t caps; + cap_t curcaps; + cap_value_t capval; + char strbuf[ISC_STRERRORSIZE]; + int err; + + INIT_CAP; + /*% + * Drop all privileges except the ability to bind() to privileged + * ports. + * + * It's important that we drop CAP_SYS_CHROOT. If we didn't, it + * chroot() could be used to escape from the chrooted area. + */ + + SET_CAP(CAP_NET_BIND_SERVICE); + + /* + * XXX We might want to add CAP_SYS_RESOURCE, though it's not + * clear it would work right given the way linuxthreads work. + * XXXDCL But since we need to be able to set the maximum number + * of files, the stack size, data size, and core dump size to + * support named.conf options, this is now being added to test. + */ + SET_CAP(CAP_SYS_RESOURCE); + + linux_setcaps(caps); + + FREE_CAP; +} + +static void +linux_keepcaps(void) { + char strbuf[ISC_STRERRORSIZE]; + /*% + * Ask the kernel to allow us to keep our capabilities after we + * setuid(). + */ + + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) { + if (errno != EINVAL) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("prctl() failed: %s", strbuf); + } + } else { + non_root_caps = true; + if (getuid() != 0) { + non_root = true; + } + } +} + +#endif /* HAVE_LIBCAP */ + +static void +setperms(uid_t uid, gid_t gid) { + char strbuf[ISC_STRERRORSIZE]; + + /* + * Drop the gid privilege first, because in some cases the gid privilege + * cannot be dropped after the uid privilege has been dropped. + */ + if (setegid(gid) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("unable to set effective gid to %d: %s", + gid, strbuf); + } + + if (seteuid(uid) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("unable to set effective uid to %d: %s", + uid, strbuf); + } +} + +static void +setup_syslog(const char *progname) { + int options; + + options = LOG_PID; +#ifdef LOG_NDELAY + options |= LOG_NDELAY; +#endif /* ifdef LOG_NDELAY */ + openlog(isc_file_basename(progname), options, ISC_FACILITY); +} + +void +named_os_init(const char *progname) { + setup_syslog(progname); +#if HAVE_LIBCAP + linux_initialprivs(); +#endif /* HAVE_LIBCAP */ +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_IGN); +#endif /* ifdef SIGXFSZ */ +} + +void +named_os_daemonize(void) { + pid_t pid; + char strbuf[ISC_STRERRORSIZE]; + + if (pipe(dfd) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("pipe(): %s", strbuf); + } + + pid = fork(); + if (pid == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("fork(): %s", strbuf); + } + if (pid != 0) { + int n; + /* + * Wait for the child to finish loading for the first time. + * This would be so much simpler if fork() worked once we + * were multi-threaded. + */ + (void)close(dfd[1]); + do { + char buf; + n = read(dfd[0], &buf, 1); + if (n == 1) { + _exit(EXIT_SUCCESS); + } + } while (n == -1 && errno == EINTR); + _exit(EXIT_FAILURE); + } + (void)close(dfd[0]); + + /* + * We're the child. + */ + + if (setsid() == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("setsid(): %s", strbuf); + } + + /* + * Try to set stdin, stdout, and stderr to /dev/null, but press + * on even if it fails. + * + * XXXMLG The close() calls here are unneeded on all but NetBSD, but + * are harmless to include everywhere. dup2() is supposed to close + * the FD if it is in use, but unproven-pthreads-0.16 is broken + * and will end up closing the wrong FD. This will be fixed eventually, + * and these calls will be removed. + */ + if (devnullfd != -1) { + if (devnullfd != STDIN_FILENO) { + (void)close(STDIN_FILENO); + (void)dup2(devnullfd, STDIN_FILENO); + } + if (devnullfd != STDOUT_FILENO) { + (void)close(STDOUT_FILENO); + (void)dup2(devnullfd, STDOUT_FILENO); + } + if (devnullfd != STDERR_FILENO && !named_g_keepstderr) { + (void)close(STDERR_FILENO); + (void)dup2(devnullfd, STDERR_FILENO); + } + } +} + +void +named_os_started(void) { + char buf = 0; + + /* + * Signal to the parent that we started successfully. + */ + if (dfd[0] != -1 && dfd[1] != -1) { + if (write(dfd[1], &buf, 1) != 1) { + named_main_earlyfatal("unable to signal parent that we " + "otherwise started " + "successfully."); + } + close(dfd[1]); + dfd[0] = dfd[1] = -1; + } +} + +void +named_os_opendevnull(void) { + devnullfd = open("/dev/null", O_RDWR, 0); +} + +void +named_os_closedevnull(void) { + if (devnullfd != STDIN_FILENO && devnullfd != STDOUT_FILENO && + devnullfd != STDERR_FILENO) + { + close(devnullfd); + devnullfd = -1; + } +} + +static bool +all_digits(const char *s) { + if (*s == '\0') { + return false; + } + while (*s != '\0') { + if (!isdigit((unsigned char)(*s))) { + return false; + } + s++; + } + return true; +} + +void +named_os_chroot(const char *root) { + char strbuf[ISC_STRERRORSIZE]; +#ifdef HAVE_LIBSCF + named_smf_chroot = 0; +#endif /* ifdef HAVE_LIBSCF */ + if (root != NULL) { +#ifdef HAVE_CHROOT + if (chroot(root) < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("chroot(): %s", strbuf); + } +#else /* ifdef HAVE_CHROOT */ + named_main_earlyfatal("chroot(): disabled"); +#endif /* ifdef HAVE_CHROOT */ + if (chdir("/") < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("chdir(/): %s", strbuf); + } +#ifdef HAVE_LIBSCF + /* Set named_smf_chroot flag on successful chroot. */ + named_smf_chroot = 1; +#endif /* ifdef HAVE_LIBSCF */ + } +} + +void +named_os_inituserinfo(const char *username) { + if (username == NULL) { + return; + } + + if (all_digits(username)) { + runas_pw = getpwuid((uid_t)atoi(username)); + } else { + runas_pw = getpwnam(username); + } + endpwent(); + + if (runas_pw == NULL) { + named_main_earlyfatal("user '%s' unknown", username); + } + + if (getuid() == 0) { + char strbuf[ISC_STRERRORSIZE]; + if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("initgroups(): %s", strbuf); + } + } +} + +void +named_os_restoreuser(void) { + if (runas_pw == NULL || done_setuid) { + return; + } + + REQUIRE(saved_uid != (uid_t)-1); + REQUIRE(saved_gid != (gid_t)-1); + + setperms(saved_uid, saved_gid); +} + +void +named_os_changeuser(bool permanent) { + char strbuf[ISC_STRERRORSIZE]; + if (runas_pw == NULL || done_setuid) { + return; + } + + if (!permanent) { + saved_uid = getuid(); + saved_gid = getgid(); + + setperms(runas_pw->pw_uid, runas_pw->pw_gid); + + return; + } + + done_setuid = true; + + if (setgid(runas_pw->pw_gid) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("setgid(): %s", strbuf); + } + + if (setuid(runas_pw->pw_uid) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlyfatal("setuid(): %s", strbuf); + } + +#if HAVE_LIBCAP + /* + * Restore the ability of named to drop core after the setuid() + * call has disabled it. + */ + if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s", + strbuf); + } + + linux_minprivs(); +#endif /* HAVE_LIBCAP */ +} + +uid_t +named_os_uid(void) { + if (runas_pw == NULL) { + return 0; + } + return runas_pw->pw_uid; +} + +void +named_os_adjustnofile(void) { + int r; + struct rlimit rl; + rlim_t rlim_old; + char strbuf[ISC_STRERRORSIZE]; + + r = getrlimit(RLIMIT_NOFILE, &rl); + if (r != 0) { + goto fail; + } + + rlim_old = rl.rlim_cur; + + if (rl.rlim_cur == rl.rlim_max) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "the limit on open files is already at the " + "maximum allowed value: " + "%" PRIu64, + (uint64_t)rl.rlim_max); + return; + } + + rl.rlim_cur = rl.rlim_max; + r = setrlimit(RLIMIT_NOFILE, &rl); + if (r != 0) { + goto fail; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, + "adjusted limit on open files from " + "%" PRIu64 " to " + "%" PRIu64, + (uint64_t)rlim_old, (uint64_t)rl.rlim_cur); + return; + +fail: + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("adjusting limit on open files failed: %s", + strbuf); + return; +} + +void +named_os_minprivs(void) { +#if HAVE_LIBCAP + linux_keepcaps(); + named_os_changeuser(true); + linux_minprivs(); +#endif /* HAVE_LIBCAP */ +} + +static int +safe_open(const char *filename, mode_t mode, bool append) { + int fd; + struct stat sb; + + if (stat(filename, &sb) == -1) { + if (errno != ENOENT) { + return -1; + } + } else if ((sb.st_mode & S_IFREG) == 0) { + errno = EOPNOTSUPP; + return -1; + } + + if (append) { + fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, mode); + } else { + if (unlink(filename) < 0 && errno != ENOENT) { + return -1; + } + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, mode); + } + return fd; +} + +static void +cleanup_pidfile(void) { + int n; + if (pidfile != NULL) { + n = unlink(pidfile); + if (n == -1 && errno != ENOENT) { + named_main_earlywarning("unlink '%s': failed", pidfile); + } + free(pidfile); + } + pidfile = NULL; +} + +/* + * Ensure that a directory exists. + * NOTE: This function overwrites the '/' characters in 'filename' with + * nulls. The caller should copy the filename to a fresh buffer first. + */ +static int +mkdirpath(char *filename, void (*report)(const char *, ...)) { + char *slash = strrchr(filename, '/'); + char strbuf[ISC_STRERRORSIZE]; + unsigned int mode; + + if (slash != NULL && slash != filename) { + struct stat sb; + *slash = '\0'; + + if (stat(filename, &sb) == -1) { + if (errno != ENOENT) { + strerror_r(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't stat '%s': %s", filename, + strbuf); + goto error; + } + if (mkdirpath(filename, report) == -1) { + goto error; + } + /* + * Handle "//", "/./" and "/../" in path. + */ + if (!strcmp(slash + 1, "") || !strcmp(slash + 1, ".") || + !strcmp(slash + 1, "..")) + { + *slash = '/'; + return 0; + } + mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */ + mode |= S_IRGRP | S_IXGRP; /* g=rx */ + mode |= S_IROTH | S_IXOTH; /* o=rx */ + if (mkdir(filename, mode) == -1) { + strerror_r(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't mkdir '%s': %s", filename, + strbuf); + goto error; + } + if (runas_pw != NULL && + chown(filename, runas_pw->pw_uid, + runas_pw->pw_gid) == -1) + { + strerror_r(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't chown '%s': %s", filename, + strbuf); + } + } + *slash = '/'; + } + return 0; + +error: + *slash = '/'; + return -1; +} + +FILE * +named_os_openfile(const char *filename, mode_t mode, bool switch_user) { + char strbuf[ISC_STRERRORSIZE], *f; + FILE *fp; + int fd; + + /* + * Make the containing directory if it doesn't exist. + */ + f = strdup(filename); + if (f == NULL) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("couldn't strdup() '%s': %s", filename, + strbuf); + return NULL; + } + if (mkdirpath(f, named_main_earlywarning) == -1) { + free(f); + return NULL; + } + free(f); + + if (switch_user && runas_pw != NULL) { + /* + * Temporarily set UID/GID to the one we'll be running with + * eventually. + */ + named_os_changeuser(false); + + fd = safe_open(filename, mode, false); + + /* Restore UID/GID to previous uid/gid */ + named_os_restoreuser(); + + if (fd == -1) { + fd = safe_open(filename, mode, false); + if (fd != -1) { + named_main_earlywarning("Required root " + "permissions to open " + "'%s'.", + filename); + } else { + named_main_earlywarning("Could not open " + "'%s'.", + filename); + } + named_main_earlywarning("Please check file and " + "directory permissions " + "or reconfigure the filename."); + } + } else { + fd = safe_open(filename, mode, false); + } + + if (fd < 0) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("could not open file '%s': %s", + filename, strbuf); + return NULL; + } + + fp = fdopen(fd, "w"); + if (fp == NULL) { + strerror_r(errno, strbuf, sizeof(strbuf)); + named_main_earlywarning("could not fdopen() file '%s': %s", + filename, strbuf); + } + + return fp; +} + +void +named_os_writepidfile(const char *filename, bool first_time) { + FILE *fh; + pid_t pid; + char strbuf[ISC_STRERRORSIZE]; + void (*report)(const char *, ...); + + /* + * The caller must ensure any required synchronization. + */ + + report = first_time ? named_main_earlyfatal : named_main_earlywarning; + + cleanup_pidfile(); + + if (filename == NULL) { + return; + } + + pidfile = strdup(filename); + if (pidfile == NULL) { + strerror_r(errno, strbuf, sizeof(strbuf)); + (*report)("couldn't strdup() '%s': %s", filename, strbuf); + return; + } + + fh = named_os_openfile(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, + first_time); + if (fh == NULL) { + cleanup_pidfile(); + return; + } + pid = getpid(); + if (fprintf(fh, "%ld\n", (long)pid) < 0) { + (*report)("fprintf() to pid file '%s' failed", filename); + (void)fclose(fh); + cleanup_pidfile(); + return; + } + if (fflush(fh) == EOF) { + (*report)("fflush() to pid file '%s' failed", filename); + (void)fclose(fh); + cleanup_pidfile(); + return; + } + (void)fclose(fh); +} + +void +named_os_shutdown(void) { + closelog(); + cleanup_pidfile(); +} + +void +named_os_shutdownmsg(char *command, isc_buffer_t *text) { + char *last, *ptr; + pid_t pid; + + /* Skip the command name. */ + if (strtok_r(command, " \t", &last) == NULL) { + return; + } + + if ((ptr = strtok_r(NULL, " \t", &last)) == NULL) { + return; + } + + if (strcmp(ptr, "-p") != 0) { + return; + } + + pid = getpid(); + + (void)isc_buffer_printf(text, "pid: %ld", (long)pid); +} + +void +named_os_tzset(void) { +#ifdef HAVE_TZSET + tzset(); +#endif /* ifdef HAVE_TZSET */ +} + +#ifdef HAVE_UNAME +static char unamebuf[sizeof(struct utsname)]; +#else +static const char unamebuf[] = { "unknown architecture" }; +#endif +static const char *unamep = NULL; + +static void +getuname(void) { +#ifdef HAVE_UNAME + struct utsname uts; + + memset(&uts, 0, sizeof(uts)); + if (uname(&uts) < 0) { + snprintf(unamebuf, sizeof(unamebuf), "unknown architecture"); + return; + } + + snprintf(unamebuf, sizeof(unamebuf), "%s %s %s %s", uts.sysname, + uts.machine, uts.release, uts.version); +#endif /* ifdef HAVE_UNAME */ + unamep = unamebuf; +} + +const char * +named_os_uname(void) { + if (unamep == NULL) { + getuname(); + } + return unamep; +} diff --git a/bin/named/server.c b/bin/named/server.c new file mode 100644 index 0000000..f5f449d --- /dev/null +++ b/bin/named/server.c @@ -0,0 +1,17068 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DNSTAP +#include +#endif + +#ifdef HAVE_LIBSYSTEMD +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#if defined(HAVE_GEOIP2) +#include +#endif /* HAVE_GEOIP2 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LIBSCF +#include + +#include +#endif /* ifdef HAVE_LIBSCF */ + +/* On DragonFly BSD the header does not provide jemalloc API */ +#if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) +#include +#define JEMALLOC_API_SUPPORTED 1 +#elif defined(HAVE_JEMALLOC) +#include +#define JEMALLOC_API_SUPPORTED 1 +#endif + +#ifdef HAVE_LMDB +#include +#define configure_newzones configure_newzones_db +#define dumpzone dumpzone_db +#else /* HAVE_LMDB */ +#define configure_newzones configure_newzones_file +#define dumpzone dumpzone_file +#endif /* HAVE_LMDB */ + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif /* ifndef SIZE_MAX */ + +#ifndef SIZE_AS_PERCENT +#define SIZE_AS_PERCENT ((size_t)-2) +#endif /* ifndef SIZE_AS_PERCENT */ + +/* RFC7828 defines timeout as 16-bit value specified in units of 100 + * milliseconds, so the maximum and minimum advertised and keepalive + * timeouts are capped by the data type (it's ~109 minutes) + */ +#define MIN_INITIAL_TIMEOUT UINT32_C(2500) /* 2.5 seconds */ +#define MAX_INITIAL_TIMEOUT UINT32_C(120000) /* 2 minutes */ +#define MIN_IDLE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ +#define MAX_IDLE_TIMEOUT UINT32_C(120000) /* 2 minutes */ +#define MIN_KEEPALIVE_TIMEOUT UINT32_C(100) /* 0.1 seconds */ +#define MAX_KEEPALIVE_TIMEOUT UINT32_C(UINT16_MAX * 100) +#define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */ +#define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100) + +/*% + * Check an operation for failure. Assumes that the function + * using it has a 'result' variable and a 'cleanup' label. + */ +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +#define TCHECK(op) \ + do { \ + tresult = (op); \ + if (tresult != ISC_R_SUCCESS) { \ + isc_buffer_clear(*text); \ + goto cleanup; \ + } \ + } while (0) + +#define CHECKM(op, msg) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ + "%s: %s", msg, \ + isc_result_totext(result)); \ + goto cleanup; \ + } \ + } while (0) + +#define CHECKMF(op, msg, file) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, \ + "%s '%s': %s", msg, file, \ + isc_result_totext(result)); \ + goto cleanup; \ + } \ + } while (0) + +#define CHECKFATAL(op, msg) \ + { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + fatal(msg, result); \ + } \ + } + +/*% + * Maximum ADB size for views that share a cache. Use this limit to suppress + * the total of memory footprint, which should be the main reason for sharing + * a cache. Only effective when a finite max-cache-size is specified. + * This is currently defined to be 8MB. + */ +#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U + +struct named_dispatch { + isc_sockaddr_t addr; + unsigned int dispatchgen; + dns_dispatch_t *dispatch; + ISC_LINK(struct named_dispatch) link; +}; + +struct named_cache { + dns_cache_t *cache; + dns_view_t *primaryview; + bool needflush; + bool adbsizeadjusted; + dns_rdataclass_t rdclass; + ISC_LINK(named_cache_t) link; +}; + +struct dumpcontext { + isc_mem_t *mctx; + bool dumpcache; + bool dumpzones; + bool dumpadb; + bool dumpexpired; + bool dumpfail; + FILE *fp; + ISC_LIST(struct viewlistentry) viewlist; + struct viewlistentry *view; + struct zonelistentry *zone; + dns_dumpctx_t *mdctx; + dns_db_t *db; + dns_db_t *cache; + isc_loop_t *loop; + dns_dbversion_t *version; +}; + +struct viewlistentry { + dns_view_t *view; + ISC_LINK(struct viewlistentry) link; + ISC_LIST(struct zonelistentry) zonelist; +}; + +struct zonelistentry { + dns_zone_t *zone; + ISC_LINK(struct zonelistentry) link; +}; + +/*% + * Message-to-view matching context to run message signature validation + * asynchronously. + */ +typedef struct matching_view_ctx { + isc_netaddr_t *srcaddr; + isc_netaddr_t *destaddr; + dns_message_t *message; + dns_aclenv_t *env; + ns_server_t *sctx; + isc_loop_t *loop; + isc_job_cb cb; + void *cbarg; + isc_result_t *sigresult; + isc_result_t *viewmatchresult; + isc_result_t quota_result; + dns_view_t **viewp; + dns_view_t *view; +} matching_view_ctx_t; + +/*% + * Configuration context to retain for each view that allows + * new zones to be added at runtime. + */ +typedef struct ns_cfgctx { + isc_mem_t *mctx; + cfg_parser_t *conf_parser; + cfg_parser_t *add_parser; + cfg_obj_t *config; + cfg_obj_t *vconfig; + cfg_obj_t *nzf_config; + cfg_aclconfctx_t *actx; +} ns_cfgctx_t; + +/*% + * A function to write out added-zone configuration to the new_zone_file + * specified in 'view'. Maybe called by delete_zoneconf(). + */ +typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); + +/*% + * Holds state information for the initial zone loading process. + * Uses the isc_refcount structure to count the number of views + * with pending zone loads, dereferencing as each view finishes. + */ +typedef struct { + named_server_t *server; + bool reconfig; + isc_refcount_t refs; +} ns_zoneload_t; + +typedef struct { + named_server_t *server; +} catz_cb_data_t; + +typedef struct catz_chgzone { + isc_mem_t *mctx; + dns_catz_entry_t *entry; + dns_catz_zone_t *origin; + dns_view_t *view; + catz_cb_data_t *cbd; + bool mod; +} catz_chgzone_t; + +typedef struct catz_reconfig_data { + dns_catz_zone_t *catz; + const cfg_obj_t *config; + catz_cb_data_t *cbd; +} catz_reconfig_data_t; + +typedef enum { + CATZ_ADDZONE, + CATZ_MODZONE, + CATZ_DELZONE, +} catz_type_t; + +typedef struct { + unsigned int magic; +#define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r') + isc_buffer_t **text; + isc_result_t result; +} ns_dzarg_t; + +typedef enum { + MEMPROF_UNSUPPORTED = 0x00, + MEMPROF_INACTIVE = 0x01, + MEMPROF_FAILING = 0x02, + MEMPROF_OFF = 0x03, + MEMPROF_ON = 0x04, +} memprof_status; + +static const char *memprof_status_text[] = { + [MEMPROF_UNSUPPORTED] = "UNSUPPORTED", + [MEMPROF_INACTIVE] = "INACTIVE", + [MEMPROF_FAILING] = "FAILING", + [MEMPROF_OFF] = "OFF", + [MEMPROF_ON] = "ON", +}; + +/* + * These zones should not leak onto the Internet. + */ +const char *empty_zones[] = { + /* RFC 1918 */ + "10.IN-ADDR.ARPA", "16.172.IN-ADDR.ARPA", "17.172.IN-ADDR.ARPA", + "18.172.IN-ADDR.ARPA", "19.172.IN-ADDR.ARPA", "20.172.IN-ADDR.ARPA", + "21.172.IN-ADDR.ARPA", "22.172.IN-ADDR.ARPA", "23.172.IN-ADDR.ARPA", + "24.172.IN-ADDR.ARPA", "25.172.IN-ADDR.ARPA", "26.172.IN-ADDR.ARPA", + "27.172.IN-ADDR.ARPA", "28.172.IN-ADDR.ARPA", "29.172.IN-ADDR.ARPA", + "30.172.IN-ADDR.ARPA", "31.172.IN-ADDR.ARPA", "168.192.IN-ADDR.ARPA", + + /* RFC 6598 */ + "64.100.IN-ADDR.ARPA", "65.100.IN-ADDR.ARPA", "66.100.IN-ADDR.ARPA", + "67.100.IN-ADDR.ARPA", "68.100.IN-ADDR.ARPA", "69.100.IN-ADDR.ARPA", + "70.100.IN-ADDR.ARPA", "71.100.IN-ADDR.ARPA", "72.100.IN-ADDR.ARPA", + "73.100.IN-ADDR.ARPA", "74.100.IN-ADDR.ARPA", "75.100.IN-ADDR.ARPA", + "76.100.IN-ADDR.ARPA", "77.100.IN-ADDR.ARPA", "78.100.IN-ADDR.ARPA", + "79.100.IN-ADDR.ARPA", "80.100.IN-ADDR.ARPA", "81.100.IN-ADDR.ARPA", + "82.100.IN-ADDR.ARPA", "83.100.IN-ADDR.ARPA", "84.100.IN-ADDR.ARPA", + "85.100.IN-ADDR.ARPA", "86.100.IN-ADDR.ARPA", "87.100.IN-ADDR.ARPA", + "88.100.IN-ADDR.ARPA", "89.100.IN-ADDR.ARPA", "90.100.IN-ADDR.ARPA", + "91.100.IN-ADDR.ARPA", "92.100.IN-ADDR.ARPA", "93.100.IN-ADDR.ARPA", + "94.100.IN-ADDR.ARPA", "95.100.IN-ADDR.ARPA", "96.100.IN-ADDR.ARPA", + "97.100.IN-ADDR.ARPA", "98.100.IN-ADDR.ARPA", "99.100.IN-ADDR.ARPA", + "100.100.IN-ADDR.ARPA", "101.100.IN-ADDR.ARPA", "102.100.IN-ADDR.ARPA", + "103.100.IN-ADDR.ARPA", "104.100.IN-ADDR.ARPA", "105.100.IN-ADDR.ARPA", + "106.100.IN-ADDR.ARPA", "107.100.IN-ADDR.ARPA", "108.100.IN-ADDR.ARPA", + "109.100.IN-ADDR.ARPA", "110.100.IN-ADDR.ARPA", "111.100.IN-ADDR.ARPA", + "112.100.IN-ADDR.ARPA", "113.100.IN-ADDR.ARPA", "114.100.IN-ADDR.ARPA", + "115.100.IN-ADDR.ARPA", "116.100.IN-ADDR.ARPA", "117.100.IN-ADDR.ARPA", + "118.100.IN-ADDR.ARPA", "119.100.IN-ADDR.ARPA", "120.100.IN-ADDR.ARPA", + "121.100.IN-ADDR.ARPA", "122.100.IN-ADDR.ARPA", "123.100.IN-ADDR.ARPA", + "124.100.IN-ADDR.ARPA", "125.100.IN-ADDR.ARPA", "126.100.IN-ADDR.ARPA", + "127.100.IN-ADDR.ARPA", + + /* RFC 5735 and RFC 5737 */ + "0.IN-ADDR.ARPA", /* THIS NETWORK */ + "127.IN-ADDR.ARPA", /* LOOPBACK */ + "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ + "2.0.192.IN-ADDR.ARPA", /* TEST NET */ + "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ + "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ + "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ + + /* Local IPv6 Unicast Addresses */ + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6." + "ARPA", + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6." + "ARPA", + /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ + "D.F.IP6.ARPA", "8.E.F.IP6.ARPA", /* LINK LOCAL */ + "9.E.F.IP6.ARPA", /* LINK LOCAL */ + "A.E.F.IP6.ARPA", /* LINK LOCAL */ + "B.E.F.IP6.ARPA", /* LINK LOCAL */ + + /* Example Prefix, RFC 3849. */ + "8.B.D.0.1.0.0.2.IP6.ARPA", + + /* RFC 7534 */ + "EMPTY.AS112.ARPA", + + /* RFC 8375 */ + "HOME.ARPA", + + /* RFC 9462 */ + "RESOLVER.ARPA", + + NULL +}; + +noreturn static void +fatal(const char *msg, isc_result_t result); + +static void +named_server_reload(void *arg); + +#ifdef HAVE_LIBNGHTTP2 +static isc_result_t +listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, + const ns_listen_tls_params_t *tls_params, + isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, + isc_mem_t *mctx, isc_nm_proxy_type_t proxy, + ns_listenelt_t **target); +#endif + +static isc_result_t +listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, + isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target); + +static isc_result_t +listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, + isc_tlsctx_cache_t *tlsctx_cache, + ns_listenlist_t **target); + +static isc_result_t +configure_forward(const cfg_obj_t *config, dns_view_t *view, + const dns_name_t *origin, const cfg_obj_t *forwarders, + const cfg_obj_t *forwardtype); + +static isc_result_t +configure_alternates(const cfg_obj_t *config, dns_view_t *view, + const cfg_obj_t *alternates); + +static isc_result_t +configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, + const cfg_obj_t *vconfig, dns_view_t *view, + dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, + dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, + bool added, bool old_rpz_ok, bool is_catz_member, bool modify); + +static void +configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, + dns_view_t *view); + +static isc_result_t +configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + cfg_aclconfctx_t *actx); + +static const cfg_obj_t * +find_maplist(const cfg_obj_t *config, const char *listname, const char *name); + +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); + +static void +newzone_cfgctx_destroy(void **cfgp); + +static isc_result_t +putstr(isc_buffer_t **b, const char *str); + +static isc_result_t +putmem(isc_buffer_t **b, const char *str, size_t len); + +static isc_result_t +putuint8(isc_buffer_t **b, uint8_t val); + +static isc_result_t +putnull(isc_buffer_t **b); + +#ifdef HAVE_LMDB +static isc_result_t +nzd_writable(dns_view_t *view); + +static isc_result_t +nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi); + +static isc_result_t +nzd_env_reopen(dns_view_t *view); + +static void +nzd_env_close(dns_view_t *view); + +static isc_result_t +nzd_close(MDB_txn **txnp, bool commit); +#else /* ifdef HAVE_LMDB */ +static isc_result_t +nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); +#endif /* ifdef HAVE_LMDB */ + +static isc_result_t +load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg); + +/*% + * Configure a single view ACL at '*aclp'. Get its configuration from + * 'vconfig' (for per-view configuration) and maybe from 'config' + */ +static isc_result_t +configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, + const cfg_obj_t *gconfig, const char *aclname, + const char *acltuplename, cfg_aclconfctx_t *actx, + isc_mem_t *mctx, dns_acl_t **aclp) { + isc_result_t result; + const cfg_obj_t *maps[4]; + const cfg_obj_t *aclobj = NULL; + int i = 0; + + if (*aclp != NULL) { + dns_acl_detach(aclp); + } + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + if (gconfig != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(gconfig, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + maps[i] = NULL; + + (void)named_config_get(maps, aclname, &aclobj); + if (aclobj == NULL) { + /* + * No value available. *aclp == NULL. + */ + return ISC_R_SUCCESS; + } + + if (acltuplename != NULL) { + /* + * If the ACL is given in an optional tuple, retrieve it. + * The parser should have ensured that a valid object be + * returned. + */ + aclobj = cfg_tuple_get(aclobj, acltuplename); + } + + result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 0, + aclp); + + return result; +} + +/*% + * Configure a sortlist at '*aclp'. Essentially the same as + * configure_view_acl() except it calls cfg_acl_fromconfig with a + * nest_level value of 2. + */ +static isc_result_t +configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, + dns_acl_t **aclp) { + isc_result_t result; + const cfg_obj_t *maps[3]; + const cfg_obj_t *aclobj = NULL; + int i = 0; + + if (*aclp != NULL) { + dns_acl_detach(aclp); + } + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + maps[i] = NULL; + + (void)named_config_get(maps, "sortlist", &aclobj); + if (aclobj == NULL) { + return ISC_R_SUCCESS; + } + + /* + * Use a nest level of 3 for the "top level" of the sortlist; + * this means each entry in the top three levels will be stored + * as lists of separate, nested ACLs, rather than merged together + * into IP tables as is usually done with ACLs. + */ + result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, mctx, 3, + aclp); + + return result; +} + +static isc_result_t +configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, + const char *confname, const char *conftuplename, + isc_mem_t *mctx, dns_nametree_t **ntp) { + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *maps[3]; + const cfg_obj_t *obj = NULL; + const cfg_listelt_t *element = NULL; + int i = 0; + dns_fixedname_t fixed; + dns_name_t *name = NULL; + isc_buffer_t b; + const char *str = NULL; + const cfg_obj_t *nameobj = NULL; + + if (*ntp != NULL) { + dns_nametree_detach(ntp); + } + dns_nametree_create(mctx, DNS_NAMETREE_BOOL, confname, ntp); + + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + maps[i] = NULL; + + (void)named_config_get(maps, confname, &obj); + if (obj == NULL) { + /* + * No value available. *ntp == NULL. + */ + return ISC_R_SUCCESS; + } + + if (conftuplename != NULL) { + obj = cfg_tuple_get(obj, conftuplename); + if (cfg_obj_isvoid(obj)) { + return ISC_R_SUCCESS; + } + } + + name = dns_fixedname_initname(&fixed); + for (element = cfg_list_first(obj); element != NULL; + element = cfg_list_next(element)) + { + nameobj = cfg_listelt_value(element); + str = cfg_obj_asstring(nameobj); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + result = dns_nametree_add(*ntp, name, true); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(nameobj, named_g_lctx, ISC_LOG_ERROR, + "failed to add %s for %s: %s", str, + confname, isc_result_totext(result)); + goto cleanup; + } + } + + return ISC_R_SUCCESS; + +cleanup: + dns_nametree_detach(ntp); + return result; +} + +static isc_result_t +ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, + unsigned char *digest, dns_rdata_ds_t *ds) { + isc_result_t result; + dns_rdata_dnskey_t keystruct; + dns_rdata_t rdata = DNS_RDATA_INIT; + uint32_t rdata1, rdata2, rdata3; + const char *datastr = NULL, *namestr = NULL; + unsigned char data[4096]; + isc_buffer_t databuf; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + dns_fixedname_t fname; + dns_name_t *name = NULL; + isc_buffer_t namebuf; + const char *atstr = NULL; + enum { + INIT_DNSKEY, + STATIC_DNSKEY, + INIT_DS, + STATIC_DS, + TRUSTED + } anchortype; + + REQUIRE(namestrp != NULL && *namestrp == NULL); + REQUIRE(ds != NULL); + + /* if DNSKEY, flags; if DS, key tag */ + rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); + + /* if DNSKEY, protocol; if DS, algorithm */ + rdata2 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata2")); + + /* if DNSKEY, algorithm; if DS, digest type */ + rdata3 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata3")); + + namestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); + *namestrp = namestr; + + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&namebuf, namestr, strlen(namestr)); + isc_buffer_add(&namebuf, strlen(namestr)); + CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL)); + + if (*initialp) { + atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype")); + + if (strcasecmp(atstr, "static-key") == 0) { + *initialp = false; + anchortype = STATIC_DNSKEY; + } else if (strcasecmp(atstr, "static-ds") == 0) { + *initialp = false; + anchortype = STATIC_DS; + } else if (strcasecmp(atstr, "initial-key") == 0) { + anchortype = INIT_DNSKEY; + } else if (strcasecmp(atstr, "initial-ds") == 0) { + anchortype = INIT_DS; + } else { + cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, + "key '%s': " + "invalid initialization method '%s'", + namestr, atstr); + result = ISC_R_FAILURE; + goto cleanup; + } + } else { + anchortype = TRUSTED; + } + + isc_buffer_init(&databuf, data, sizeof(data)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + *ds = (dns_rdata_ds_t){ .common.rdclass = dns_rdataclass_in, + .common.rdtype = dns_rdatatype_ds }; + + ISC_LINK_INIT(&ds->common, link); + + switch (anchortype) { + case INIT_DNSKEY: + case STATIC_DNSKEY: + case TRUSTED: + /* + * This function should never be reached for view + * class other than IN + */ + keystruct.common.rdclass = dns_rdataclass_in; + keystruct.common.rdtype = dns_rdatatype_dnskey; + + /* + * The key data in keystruct is not dynamically allocated. + */ + keystruct.mctx = NULL; + + ISC_LINK_INIT(&keystruct.common, link); + + if (rdata1 > 0xffff) { + CHECKM(ISC_R_RANGE, "key flags"); + } + if (rdata1 & DNS_KEYFLAG_REVOKE) { + CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set"); + } + if (rdata2 > 0xff) { + CHECKM(ISC_R_RANGE, "key protocol"); + } + if (rdata3 > 0xff) { + CHECKM(ISC_R_RANGE, "key algorithm"); + } + + keystruct.flags = (uint16_t)rdata1; + keystruct.protocol = (uint8_t)rdata2; + keystruct.algorithm = (uint8_t)rdata3; + + if (!dst_algorithm_supported(keystruct.algorithm)) { + CHECK(DST_R_UNSUPPORTEDALG); + } + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_base64_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, + keystruct.common.rdtype, &keystruct, + &rrdatabuf)); + CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, + digest, ds)); + break; + + case INIT_DS: + case STATIC_DS: + if (rdata1 > 0xffff) { + CHECKM(ISC_R_RANGE, "key tag"); + } + if (rdata2 > 0xff) { + CHECKM(ISC_R_RANGE, "key algorithm"); + } + if (rdata3 > 0xff) { + CHECKM(ISC_R_RANGE, "digest type"); + } + + ds->key_tag = (uint16_t)rdata1; + ds->algorithm = (uint8_t)rdata2; + ds->digest_type = (uint8_t)rdata3; + + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); + CHECK(isc_hex_decodestring(datastr, &databuf)); + isc_buffer_usedregion(&databuf, &r); + + switch (ds->digest_type) { + case DNS_DSDIGEST_SHA1: + if (r.length != ISC_SHA1_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA256: + if (r.length != ISC_SHA256_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + case DNS_DSDIGEST_SHA384: + if (r.length != ISC_SHA384_DIGESTLENGTH) { + CHECK(ISC_R_UNEXPECTEDEND); + } + break; + default: + cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, + "key '%s': " + "unknown ds digest type %u", + namestr, ds->digest_type); + result = ISC_R_FAILURE; + goto cleanup; + break; + } + + ds->length = r.length; + ds->digest = digest; + memmove(ds->digest, r.base, r.length); + + break; + + default: + UNREACHABLE(); + } + + return ISC_R_SUCCESS; + +cleanup: + return result; +} + +static void +sfd_add(const dns_name_t *name, void *arg) { + if (arg != NULL) { + dns_view_sfd_add(arg, name); + } +} + +/*% + * Parse 'key' in the context of view configuration 'vconfig'. If successful, + * add the key to 'secroots' if both of the following conditions are true: + * + * - 'keyname_match' is NULL or it matches the owner name of 'key', + * - support for the algorithm used by 'key' is not disabled by 'resolver' + * for the owner name of 'key'. + * + * 'managed' is true for managed keys and false for trusted keys. 'mctx' is + * the memory context to use for allocating memory. + */ +static isc_result_t +process_key(const cfg_obj_t *key, dns_keytable_t *secroots, + const dns_name_t *keyname_match, dns_view_t *view, bool managed) { + dns_fixedname_t fkeyname; + dns_name_t *keyname = NULL; + const char *namestr = NULL; + dns_rdata_ds_t ds; + isc_result_t result; + bool initializing = managed; + unsigned char digest[ISC_MAX_MD_SIZE]; + isc_buffer_t b; + + result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); + + switch (result) { + case ISC_R_SUCCESS: + /* + * Trust anchor was parsed correctly. + */ + isc_buffer_constinit(&b, namestr, strlen(namestr)); + isc_buffer_add(&b, strlen(namestr)); + keyname = dns_fixedname_initname(&fkeyname); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + break; + case DST_R_UNSUPPORTEDALG: + case DST_R_BADKEYTYPE: + /* + * Key was parsed correctly, but it cannot be used; this is not + * a fatal error - log a warning about this key being ignored, + * but do not prevent any further ones from being processed. + */ + cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, + "ignoring %s for '%s': %s", + initializing ? "initial-key" : "static-key", + namestr, isc_result_totext(result)); + return ISC_R_SUCCESS; + case DST_R_NOCRYPTO: + /* + * Crypto support is not available. + */ + cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, + "ignoring %s for '%s': no crypto support", + initializing ? "initial-key" : "static-key", + namestr); + return result; + default: + /* + * Something unexpected happened; we have no choice but to + * indicate an error so that the configuration loading process + * is interrupted. + */ + cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, + "configuring %s for '%s': %s", + initializing ? "initial-key" : "static-key", + namestr, isc_result_totext(result)); + return ISC_R_FAILURE; + } + + /* + * If the caller requested to only load keys for a specific name and + * the owner name of this key does not match the requested name, do not + * load it. + */ + if (keyname_match != NULL && !dns_name_equal(keyname_match, keyname)) { + goto done; + } + + /* + * Ensure that 'resolver' allows using the algorithm of this key for + * its owner name. If it does not, do not load the key and log a + * warning, but do not prevent further keys from being processed. + */ + if (!dns_resolver_algorithm_supported(view->resolver, keyname, + ds.algorithm)) + { + cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, + "ignoring %s for '%s': algorithm is disabled", + initializing ? "initial-key" : "static-key", + namestr); + goto done; + } + + /* + * Add the key to 'secroots'. Keys from a "trust-anchors" or + * "managed-keys" statement may be either static or initializing + * keys. If it's not initializing, we don't want to treat it as + * managed, so we use 'initializing' twice here, for both the + * 'managed' and 'initializing' arguments to dns_keytable_add(). + */ + result = dns_keytable_add(secroots, initializing, initializing, keyname, + &ds, sfd_add, view); + +done: + return result; +} + +/* + * Load keys from configuration into key table. If 'keyname' is specified, + * only load keys matching that name. If 'managed' is true, load the key as + * an initializing key. + */ +static isc_result_t +load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, + const dns_name_t *keyname) { + const cfg_listelt_t *elt, *elt2; + const cfg_obj_t *keylist; + isc_result_t result; + dns_keytable_t *secroots = NULL; + + CHECK(dns_view_getsecroots(view, &secroots)); + + for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) + { + keylist = cfg_listelt_value(elt); + + for (elt2 = cfg_list_first(keylist); elt2 != NULL; + elt2 = cfg_list_next(elt2)) + { + CHECK(process_key(cfg_listelt_value(elt2), secroots, + keyname, view, managed)); + } + } + +cleanup: + if (secroots != NULL) { + dns_keytable_detach(&secroots); + } + if (result == DST_R_NOCRYPTO) { + result = ISC_R_SUCCESS; + } + return result; +} + +/*% + * Check whether a key has been successfully loaded. + */ +static bool +keyloaded(dns_view_t *view, const dns_name_t *name) { + isc_result_t result; + dns_keytable_t *secroots = NULL; + dns_keynode_t *keynode = NULL; + + result = dns_view_getsecroots(view, &secroots); + if (result != ISC_R_SUCCESS) { + return false; + } + + result = dns_keytable_find(secroots, name, &keynode); + + if (keynode != NULL) { + dns_keynode_detach(&keynode); + } + if (secroots != NULL) { + dns_keytable_detach(&secroots); + } + + return result == ISC_R_SUCCESS; +} + +/*% + * Configure DNSSEC keys for a view. + * + * The per-view configuration values and the server-global defaults are read + * from 'vconfig' and 'config'. + */ +static isc_result_t +configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, + const cfg_obj_t *config, const cfg_obj_t *bindkeys, + bool auto_root) { + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *view_keys = NULL; + const cfg_obj_t *global_keys = NULL; + const cfg_obj_t *view_managed_keys = NULL; + const cfg_obj_t *view_trust_anchors = NULL; + const cfg_obj_t *global_managed_keys = NULL; + const cfg_obj_t *global_trust_anchors = NULL; + const cfg_obj_t *maps[4]; + const cfg_obj_t *voptions = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *obj = NULL; + const char *directory; + int i = 0; + + /* We don't need trust anchors for the _bind view */ + if (strcmp(view->name, "_bind") == 0 && + view->rdclass == dns_rdataclass_chaos) + { + return ISC_R_SUCCESS; + } + + if (vconfig != NULL) { + voptions = cfg_tuple_get(vconfig, "options"); + if (voptions != NULL) { + (void)cfg_map_get(voptions, "trusted-keys", &view_keys); + + /* managed-keys and trust-anchors are synonyms. */ + (void)cfg_map_get(voptions, "managed-keys", + &view_managed_keys); + (void)cfg_map_get(voptions, "trust-anchors", + &view_trust_anchors); + + maps[i++] = voptions; + } + } + + if (config != NULL) { + (void)cfg_map_get(config, "trusted-keys", &global_keys); + + /* managed-keys and trust-anchors are synonyms. */ + (void)cfg_map_get(config, "managed-keys", &global_managed_keys); + (void)cfg_map_get(config, "trust-anchors", + &global_trust_anchors); + + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + + maps[i++] = named_g_defaults; + maps[i] = NULL; + + dns_view_initsecroots(view); + dns_view_initntatable(view, named_g_loopmgr); + + if (auto_root && view->rdclass == dns_rdataclass_in) { + const cfg_obj_t *builtin_keys = NULL; + + /* + * If bind.keys exists and is populated, it overrides + * the trust-anchors clause hard-coded in named_g_config. + */ + if (bindkeys != NULL) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "obtaining root key for view %s " + "from '%s'", + view->name, named_g_server->bindkeysfile); + + (void)cfg_map_get(bindkeys, "trust-anchors", + &builtin_keys); + + if (builtin_keys == NULL) { + isc_log_write( + named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "dnssec-validation auto: " + "WARNING: root zone key " + "not found"); + } + } + + if (builtin_keys == NULL) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "using built-in root key for view %s", + view->name); + + (void)cfg_map_get(named_g_config, "trust-anchors", + &builtin_keys); + } + + if (builtin_keys != NULL) { + CHECK(load_view_keys(builtin_keys, view, true, + dns_rootname)); + } + + if (!keyloaded(view, dns_rootname)) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "root key not loaded"); + result = ISC_R_FAILURE; + goto cleanup; + } + } + + if (view->rdclass == dns_rdataclass_in) { + CHECK(load_view_keys(view_keys, view, false, NULL)); + CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); + CHECK(load_view_keys(view_managed_keys, view, true, NULL)); + + CHECK(load_view_keys(global_keys, view, false, NULL)); + CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); + CHECK(load_view_keys(global_managed_keys, view, true, NULL)); + } + + /* + * Add key zone for managed keys. + */ + obj = NULL; + (void)named_config_get(maps, "managed-keys-directory", &obj); + directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); + if (directory != NULL) { + result = isc_file_isdirectory(directory); + } + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "invalid managed-keys-directory %s: %s", + directory, isc_result_totext(result)); + goto cleanup; + } else if (directory != NULL) { + if (!isc_file_isdirwritable(directory)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "managed-keys-directory '%s' " + "is not writable", + directory); + result = ISC_R_NOPERM; + goto cleanup; + } + } + + if (auto_root) { + CHECK(add_keydata_zone(view, directory, named_g_mctx)); + } + +cleanup: + return result; +} + +static isc_result_t +mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { + const cfg_listelt_t *element; + const cfg_obj_t *obj; + const char *str; + dns_fixedname_t fixed; + dns_name_t *name; + bool value; + isc_result_t result; + isc_buffer_t b; + + name = dns_fixedname_initname(&fixed); + for (element = cfg_list_first(mbs); element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); + CHECK(dns_resolver_setmustbesecure(resolver, name, value)); + } + + result = ISC_R_SUCCESS; + +cleanup: + return result; +} + +/*% + * Get a dispatch appropriate for the resolver of a given view. + */ +static isc_result_t +get_view_querysource_dispatch(const cfg_obj_t **maps, int af, + dns_dispatch_t **dispatchp, bool is_firstview) { + isc_result_t result = ISC_R_FAILURE; + dns_dispatch_t *disp = NULL; + isc_sockaddr_t sa; + const cfg_obj_t *obj = NULL; + + switch (af) { + case AF_INET: + result = named_config_get(maps, "query-source", &obj); + INSIST(result == ISC_R_SUCCESS); + break; + case AF_INET6: + result = named_config_get(maps, "query-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS); + break; + default: + UNREACHABLE(); + } + + if (cfg_obj_isvoid(obj)) { + /* + * We don't want to use this address family, let's + * bail now. The dispatch object for this family will + * be null then not used to run queries. + */ + return ISC_R_SUCCESS; + } else { + /* + * obj _has_ to be sockaddr here, cfg_obj_assockaddr() + * asserts this internally. + */ + sa = *(cfg_obj_assockaddr(obj)); + INSIST(isc_sockaddr_pf(&sa) == af); + } + + /* + * If we don't support this address family, we're done! + */ + switch (af) { + case AF_INET: + result = isc_net_probeipv4(); + break; + case AF_INET6: + result = isc_net_probeipv6(); + break; + default: + UNREACHABLE(); + } + if (result != ISC_R_SUCCESS) { + return ISC_R_SUCCESS; + } + + /* + * Try to find a dispatcher that we can share. + */ + if (isc_sockaddr_getport(&sa) != 0) { + INSIST(obj != NULL); + if (is_firstview) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, + "using specific query-source port " + "suppresses port randomization and can be " + "insecure."); + } + } + + result = dns_dispatch_createudp(named_g_dispatchmgr, &sa, &disp); + if (result != ISC_R_SUCCESS) { + isc_sockaddr_t any; + char buf[ISC_SOCKADDR_FORMATSIZE]; + + switch (af) { + case AF_INET: + isc_sockaddr_any(&any); + break; + case AF_INET6: + isc_sockaddr_any6(&any); + break; + } + if (isc_sockaddr_equal(&sa, &any)) { + return ISC_R_SUCCESS; + } + isc_sockaddr_format(&sa, buf, sizeof(buf)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "could not get query source dispatcher (%s): %s", + buf, isc_result_totext(result)); + return result; + } + + *dispatchp = disp; + + return ISC_R_SUCCESS; +} + +static isc_result_t +configure_order(dns_order_t *order, const cfg_obj_t *ent) { + dns_rdataclass_t rdclass; + dns_rdatatype_t rdtype; + const cfg_obj_t *obj; + dns_fixedname_t fixed; + unsigned int mode = 0; + const char *str; + isc_buffer_t b; + isc_result_t result; + bool addroot; + + result = named_config_getclass(cfg_tuple_get(ent, "class"), + dns_rdataclass_any, &rdclass); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = named_config_gettype(cfg_tuple_get(ent, "type"), + dns_rdatatype_any, &rdtype); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = cfg_tuple_get(ent, "name"); + if (cfg_obj_isstring(obj)) { + str = cfg_obj_asstring(obj); + } else { + str = "*"; + } + addroot = (strcmp(str, "*") == 0); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + dns_fixedname_init(&fixed); + result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, dns_rootname, + 0, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = cfg_tuple_get(ent, "ordering"); + INSIST(cfg_obj_isstring(obj)); + str = cfg_obj_asstring(obj); + if (!strcasecmp(str, "fixed")) { +#if DNS_RDATASET_FIXED + mode = DNS_RDATASETATTR_FIXEDORDER; +#else /* if DNS_RDATASET_FIXED */ + mode = DNS_RDATASETATTR_CYCLIC; +#endif /* DNS_RDATASET_FIXED */ + } else if (!strcasecmp(str, "random")) { + mode = DNS_RDATASETATTR_RANDOMIZE; + } else if (!strcasecmp(str, "cyclic")) { + mode = DNS_RDATASETATTR_CYCLIC; + } else if (!strcasecmp(str, "none")) { + mode = DNS_RDATASETATTR_NONE; + } else { + UNREACHABLE(); + } + + /* + * "*" should match everything including the root (BIND 8 compat). + * As dns_name_matcheswildcard(".", "*.") returns FALSE add a + * explicit entry for "." when the name is "*". + */ + if (addroot) { + result = dns_order_add(order, dns_rootname, rdtype, rdclass, + mode); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + return dns_order_add(order, dns_fixedname_name(&fixed), rdtype, rdclass, + mode); +} + +static isc_result_t +configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { + isc_netaddr_t na; + dns_peer_t *peer; + const cfg_obj_t *obj; + const char *str; + isc_result_t result; + unsigned int prefixlen; + + cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); + + peer = NULL; + result = dns_peer_newprefix(mctx, &na, prefixlen, &peer); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = NULL; + (void)cfg_map_get(cpeer, "bogus", &obj); + if (obj != NULL) { + CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "provide-ixfr", &obj); + if (obj != NULL) { + CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "request-expire", &obj); + if (obj != NULL) { + CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "request-ixfr", &obj); + if (obj != NULL) { + CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "request-nsid", &obj); + if (obj != NULL) { + CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "send-cookie", &obj); + if (obj != NULL) { + CHECK(dns_peer_setsendcookie(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "require-cookie", &obj); + if (obj != NULL) { + CHECK(dns_peer_setrequirecookie(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "edns", &obj); + if (obj != NULL) { + CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "edns-udp-size", &obj); + if (obj != NULL) { + uint32_t udpsize = cfg_obj_asuint32(obj); + if (udpsize < 512U) { + udpsize = 512U; + } + if (udpsize > 4096U) { + udpsize = 4096U; + } + CHECK(dns_peer_setudpsize(peer, (uint16_t)udpsize)); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "edns-version", &obj); + if (obj != NULL) { + uint32_t ednsversion = cfg_obj_asuint32(obj); + if (ednsversion > 255U) { + ednsversion = 255U; + } + CHECK(dns_peer_setednsversion(peer, (uint8_t)ednsversion)); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "max-udp-size", &obj); + if (obj != NULL) { + uint32_t udpsize = cfg_obj_asuint32(obj); + if (udpsize < 512U) { + udpsize = 512U; + } + if (udpsize > 4096U) { + udpsize = 4096U; + } + CHECK(dns_peer_setmaxudp(peer, (uint16_t)udpsize)); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "padding", &obj); + if (obj != NULL) { + uint32_t padding = cfg_obj_asuint32(obj); + if (padding > 512U) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "server padding value cannot " + "exceed 512: lowering"); + padding = 512U; + } + CHECK(dns_peer_setpadding(peer, (uint16_t)padding)); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "tcp-only", &obj); + if (obj != NULL) { + CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "tcp-keepalive", &obj); + if (obj != NULL) { + CHECK(dns_peer_settcpkeepalive(peer, cfg_obj_asboolean(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "transfers", &obj); + if (obj != NULL) { + CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); + } + + obj = NULL; + (void)cfg_map_get(cpeer, "transfer-format", &obj); + if (obj != NULL) { + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "many-answers") == 0) { + CHECK(dns_peer_settransferformat(peer, + dns_many_answers)); + } else if (strcasecmp(str, "one-answer") == 0) { + CHECK(dns_peer_settransferformat(peer, dns_one_answer)); + } else { + UNREACHABLE(); + } + } + + obj = NULL; + (void)cfg_map_get(cpeer, "keys", &obj); + if (obj != NULL) { + result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + obj = NULL; + if (na.family == AF_INET) { + (void)cfg_map_get(cpeer, "transfer-source", &obj); + } else { + (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); + } + if (obj != NULL) { + result = dns_peer_settransfersource(peer, + cfg_obj_assockaddr(obj)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + obj = NULL; + if (na.family == AF_INET) { + (void)cfg_map_get(cpeer, "notify-source", &obj); + } else { + (void)cfg_map_get(cpeer, "notify-source-v6", &obj); + } + if (obj != NULL) { + result = dns_peer_setnotifysource(peer, + cfg_obj_assockaddr(obj)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + obj = NULL; + if (na.family == AF_INET) { + (void)cfg_map_get(cpeer, "query-source", &obj); + } else { + (void)cfg_map_get(cpeer, "query-source-v6", &obj); + } + if (obj != NULL) { + INSIST(cfg_obj_issockaddr(obj)); + result = dns_peer_setquerysource(peer, cfg_obj_assockaddr(obj)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + *peerp = peer; + return ISC_R_SUCCESS; + +cleanup: + dns_peer_detach(&peer); + return result; +} + +static isc_result_t +configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, + const dns_dyndbctx_t *dctx) { + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *obj; + const char *name, *library; + + /* Get the name of the dyndb instance and the library path . */ + name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); + library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); + + obj = cfg_tuple_get(dyndb, "parameters"); + if (obj != NULL) { + result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), + cfg_obj_file(obj), cfg_obj_line(obj), + mctx, dctx); + } + + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dynamic database '%s' configuration failed: %s", + name, isc_result_totext(result)); + } + return result; +} + +static isc_result_t +disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { + isc_result_t result; + const cfg_obj_t *algorithms; + const cfg_listelt_t *element; + const char *str; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t b; + + name = dns_fixedname_initname(&fixed); + str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + + algorithms = cfg_tuple_get(disabled, "algorithms"); + for (element = cfg_list_first(algorithms); element != NULL; + element = cfg_list_next(element)) + { + isc_textregion_t r; + dns_secalg_t alg; + + r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); + r.length = strlen(r.base); + + result = dns_secalg_fromtext(&alg, &r); + if (result != ISC_R_SUCCESS) { + uint8_t ui; + result = isc_parse_uint8(&ui, r.base, 10); + alg = ui; + } + if (result != ISC_R_SUCCESS) { + cfg_obj_log(cfg_listelt_value(element), named_g_lctx, + ISC_LOG_ERROR, "invalid algorithm"); + CHECK(result); + } + CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); + } +cleanup: + return result; +} + +static isc_result_t +disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) { + isc_result_t result; + const cfg_obj_t *digests; + const cfg_listelt_t *element; + const char *str; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t b; + + name = dns_fixedname_initname(&fixed); + str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + + digests = cfg_tuple_get(disabled, "digests"); + for (element = cfg_list_first(digests); element != NULL; + element = cfg_list_next(element)) + { + isc_textregion_t r; + dns_dsdigest_t digest; + + r.base = UNCONST(cfg_obj_asstring(cfg_listelt_value(element))); + r.length = strlen(r.base); + + /* disable_ds_digests handles numeric values. */ + result = dns_dsdigest_fromtext(&digest, &r); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(cfg_listelt_value(element), named_g_lctx, + ISC_LOG_ERROR, "invalid algorithm"); + CHECK(result); + } + CHECK(dns_resolver_disable_ds_digest(resolver, name, digest)); + } +cleanup: + return result; +} + +static bool +on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { + const cfg_listelt_t *element; + dns_fixedname_t fixed; + dns_name_t *name; + isc_result_t result; + const cfg_obj_t *value; + const char *str; + isc_buffer_t b; + + name = dns_fixedname_initname(&fixed); + + for (element = cfg_list_first(disablelist); element != NULL; + element = cfg_list_next(element)) + { + value = cfg_listelt_value(element); + str = cfg_obj_asstring(value); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (dns_name_equal(name, zonename)) { + return true; + } + } + return false; +} + +static isc_result_t +check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv, + isc_mem_t *mctx) { + char **argv = NULL; + unsigned int i; + isc_result_t result = ISC_R_SUCCESS; + + CHECK(dns_zone_getdbtype(zone, &argv, mctx)); + + /* + * Check that all the arguments match. + */ + for (i = 0; i < dbtypec; i++) { + if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { + CHECK(ISC_R_FAILURE); + } + } + + /* + * Check that there are not extra arguments. + */ + if (i == dbtypec && argv[i] != NULL) { + result = ISC_R_FAILURE; + } + +cleanup: + isc_mem_free(mctx, argv); + return result; +} + +static void +setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { + isc_stats_t *zoneqrystats; + + dns_zone_setstatlevel(zone, level); + + zoneqrystats = NULL; + if (level == dns_zonestat_full) { + isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max); + } + dns_zone_setrequeststats(zone, zoneqrystats); + if (zoneqrystats != NULL) { + isc_stats_detach(&zoneqrystats); + } +} + +static named_cache_t * +cachelist_find(named_cachelist_t *cachelist, const char *cachename, + dns_rdataclass_t rdclass) { + for (named_cache_t *nsc = ISC_LIST_HEAD(*cachelist); nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) + { + if (nsc->rdclass == rdclass && + strcmp(dns_cache_getname(nsc->cache), cachename) == 0) + { + return nsc; + } + } + + return NULL; +} + +static bool +cache_reusable(dns_view_t *originview, dns_view_t *view, + bool new_zero_no_soattl) { + if (originview->rdclass != view->rdclass || + originview->checknames != view->checknames || + originview->acceptexpired != view->acceptexpired || + originview->enablevalidation != view->enablevalidation || + originview->maxcachettl != view->maxcachettl || + originview->maxncachettl != view->maxncachettl || + originview->resolver == NULL || + dns_resolver_getzeronosoattl(originview->resolver) != + new_zero_no_soattl) + { + return false; + } + + return true; +} + +static bool +cache_sharable(dns_view_t *originview, dns_view_t *view, + bool new_zero_no_soattl, uint64_t new_max_cache_size, + uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) { + /* + * If the cache cannot even reused for the same view, it cannot be + * shared with other views. + */ + if (!cache_reusable(originview, view, new_zero_no_soattl)) { + return false; + } + + /* + * Check other cache related parameters that must be consistent among + * the sharing views. + */ + if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl || + dns_cache_getservestalerefresh(originview->cache) != + new_stale_refresh_time || + dns_cache_getcachesize(originview->cache) != new_max_cache_size) + { + return false; + } + + return true; +} + +/* + * Callback from DLZ configure when the driver sets up a writeable zone + */ +static isc_result_t +dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) { + dns_name_t *origin = dns_zone_getorigin(zone); + dns_rdataclass_t zclass = view->rdclass; + isc_result_t result; + + result = dns_zonemgr_managezone(named_g_server->zonemgr, zone); + if (result != ISC_R_SUCCESS) { + return result; + } + dns_zone_setstats(zone, named_g_server->zonestats); + + return named_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin); +} + +static isc_result_t +dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, + unsigned int prefixlen, const char *server, const char *contact) { + char reverse[48 + sizeof("ip6.arpa.")] = { 0 }; + char buf[sizeof("x.x.")]; + const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." }; + const char *sep = ": view "; + const char *viewname = view->name; + const unsigned char *s6; + dns_fixedname_t fixed; + dns_name_t *name; + dns_zone_t *zone = NULL; + int dns64_dbtypec = 4; + isc_buffer_t b; + isc_result_t result; + + REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || + prefixlen == 56 || prefixlen == 64 || prefixlen == 96); + + if (!strcmp(viewname, "_default")) { + sep = ""; + viewname = ""; + } + + /* + * Construct the reverse name of the zone. + */ + s6 = na->type.in6.s6_addr; + while (prefixlen > 0) { + prefixlen -= 8; + snprintf(buf, sizeof(buf), "%x.%x.", s6[prefixlen / 8] & 0xf, + (s6[prefixlen / 8] >> 4) & 0xf); + strlcat(reverse, buf, sizeof(reverse)); + } + strlcat(reverse, "ip6.arpa.", sizeof(reverse)); + + /* + * Create the actual zone. + */ + if (server != NULL) { + dns64_dbtype[2] = server; + } + if (contact != NULL) { + dns64_dbtype[3] = contact; + } + name = dns_fixedname_initname(&fixed); + isc_buffer_constinit(&b, reverse, strlen(reverse)); + isc_buffer_add(&b, strlen(reverse)); + CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + dns_zone_create(&zone, mctx, 0); + CHECK(dns_zone_setorigin(zone, name)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_primary); + dns_zone_setstats(zone, named_g_server->zonestats); + dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype); + if (view->queryacl != NULL) { + dns_zone_setqueryacl(zone, view->queryacl); + } + if (view->queryonacl != NULL) { + dns_zone_setqueryonacl(zone, view->queryonacl); + } + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); + setquerystats(zone, mctx, dns_zonestat_none); + CHECK(dns_view_addzone(view, zone)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dns64 reverse zone%s%s: %s", sep, viewname, reverse); + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + return result; +} + +#ifdef USE_DNSRPS +typedef struct conf_dnsrps_ctx conf_dnsrps_ctx_t; +struct conf_dnsrps_ctx { + isc_result_t result; + char *cstr; + size_t cstr_size; + isc_mem_t *mctx; +}; + +/* + * Add to the DNSRPS configuration string. + */ +static bool +conf_dnsrps_sadd(conf_dnsrps_ctx_t *ctx, const char *p, ...) { + size_t new_len, cur_len, new_cstr_size; + char *new_cstr; + va_list args; + + if (ctx->cstr == NULL) { + ctx->cstr = isc_mem_get(ctx->mctx, 256); + ctx->cstr[0] = '\0'; + ctx->cstr_size = 256; + } + + cur_len = strlen(ctx->cstr); + va_start(args, p); + new_len = vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, + args) + + 1; + va_end(args); + + if (cur_len + new_len <= ctx->cstr_size) { + return true; + } + + new_cstr_size = ((cur_len + new_len) / 256 + 1) * 256; + new_cstr = isc_mem_get(ctx->mctx, new_cstr_size); + + memmove(new_cstr, ctx->cstr, cur_len); + isc_mem_put(ctx->mctx, ctx->cstr, ctx->cstr_size); + ctx->cstr_size = new_cstr_size; + ctx->cstr = new_cstr; + + /* cannot use args twice after a single va_start()on some systems */ + va_start(args, p); + vsnprintf(ctx->cstr + cur_len, ctx->cstr_size - cur_len, p, args); + va_end(args); + return true; +} + +/* + * Get a DNSRPS configuration value using the global and view options + * for the default. Return false upon failure. + */ +static bool +conf_dnsrps_get(const cfg_obj_t **sub_obj, const cfg_obj_t **maps, + const cfg_obj_t *obj, const char *name, + conf_dnsrps_ctx_t *ctx) { + if (ctx != NULL && ctx->result != ISC_R_SUCCESS) { + *sub_obj = NULL; + return false; + } + + *sub_obj = cfg_tuple_get(obj, name); + if (cfg_obj_isvoid(*sub_obj)) { + *sub_obj = NULL; + if (maps != NULL && + ISC_R_SUCCESS != named_config_get(maps, name, sub_obj)) + { + *sub_obj = NULL; + } + } + return true; +} + +/* + * Handle a DNSRPS boolean configuration value with the global and view + * options providing the default. + */ +static void +conf_dnsrps_yes_no(const cfg_obj_t *obj, const char *name, + conf_dnsrps_ctx_t *ctx) { + const cfg_obj_t *sub_obj; + + if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { + return; + } + if (sub_obj == NULL) { + return; + } + if (ctx == NULL) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "\"%s\" without \"dnsrps-enable yes\"", name); + return; + } + + conf_dnsrps_sadd(ctx, " %s %s", name, + cfg_obj_asboolean(sub_obj) ? "yes" : "no"); +} + +static void +conf_dnsrps_num(const cfg_obj_t *obj, const char *name, + conf_dnsrps_ctx_t *ctx) { + const cfg_obj_t *sub_obj; + + if (!conf_dnsrps_get(&sub_obj, NULL, obj, name, ctx)) { + return; + } + if (sub_obj == NULL) { + return; + } + if (ctx == NULL) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "\"%s\" without \"dnsrps-enable yes\"", name); + return; + } + + if (cfg_obj_isduration(sub_obj)) { + conf_dnsrps_sadd(ctx, " %s %d", name, + cfg_obj_asduration(sub_obj)); + } else { + conf_dnsrps_sadd(ctx, " %s %d", name, + cfg_obj_asuint32(sub_obj)); + } +} + +/* + * Convert the parsed RPZ configuration statement to a string for + * dns_rpz_new_zones(). + */ +static isc_result_t +conf_dnsrps(dns_view_t *view, const cfg_obj_t **maps, bool nsip_enabled, + bool nsdname_enabled, dns_rpz_zbits_t *nsip_on, + dns_rpz_zbits_t *nsdname_on, char **rps_cstr, size_t *rps_cstr_size, + const cfg_obj_t *rpz_obj, const cfg_listelt_t *zone_element) { + conf_dnsrps_ctx_t ctx; + const cfg_obj_t *zone_obj, *obj; + dns_rpz_num_t rpz_num; + bool on; + const char *s; + + memset(&ctx, 0, sizeof(ctx)); + ctx.result = ISC_R_SUCCESS; + ctx.mctx = view->mctx; + + for (rpz_num = 0; zone_element != NULL && ctx.result == ISC_R_SUCCESS; + ++rpz_num) + { + zone_obj = cfg_listelt_value(zone_element); + + s = cfg_obj_asstring(cfg_tuple_get(zone_obj, "zone name")); + conf_dnsrps_sadd(&ctx, "zone \"%s\"", s); + + obj = cfg_tuple_get(zone_obj, "policy"); + if (!cfg_obj_isvoid(obj)) { + s = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); + conf_dnsrps_sadd(&ctx, " policy %s", s); + if (strcasecmp(s, "cname") == 0) { + s = cfg_obj_asstring( + cfg_tuple_get(obj, "cname")); + conf_dnsrps_sadd(&ctx, " %s", s); + } + } + + conf_dnsrps_yes_no(zone_obj, "recursive-only", &ctx); + conf_dnsrps_yes_no(zone_obj, "log", &ctx); + conf_dnsrps_num(zone_obj, "max-policy-ttl", &ctx); + obj = cfg_tuple_get(rpz_obj, "nsip-enable"); + if (!cfg_obj_isvoid(obj)) { + if (cfg_obj_asboolean(obj)) { + *nsip_on |= DNS_RPZ_ZBIT(rpz_num); + } else { + *nsip_on &= ~DNS_RPZ_ZBIT(rpz_num); + } + } + on = ((*nsip_on & DNS_RPZ_ZBIT(rpz_num)) != 0); + if (nsip_enabled != on) { + conf_dnsrps_sadd(&ctx, on ? " nsip-enable yes " + : " nsip-enable no "); + } + obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); + if (!cfg_obj_isvoid(obj)) { + if (cfg_obj_asboolean(obj)) { + *nsdname_on |= DNS_RPZ_ZBIT(rpz_num); + } else { + *nsdname_on &= ~DNS_RPZ_ZBIT(rpz_num); + } + } + on = ((*nsdname_on & DNS_RPZ_ZBIT(rpz_num)) != 0); + if (nsdname_enabled != on) { + conf_dnsrps_sadd(&ctx, on ? " nsdname-enable yes " + : " nsdname-enable no "); + } + conf_dnsrps_sadd(&ctx, ";\n"); + zone_element = cfg_list_next(zone_element); + } + + conf_dnsrps_yes_no(rpz_obj, "recursive-only", &ctx); + conf_dnsrps_num(rpz_obj, "max-policy-ttl", &ctx); + conf_dnsrps_num(rpz_obj, "min-ns-dots", &ctx); + conf_dnsrps_yes_no(rpz_obj, "qname-wait-recurse", &ctx); + conf_dnsrps_yes_no(rpz_obj, "break-dnssec", &ctx); + if (!nsip_enabled) { + conf_dnsrps_sadd(&ctx, " nsip-enable no "); + } + if (!nsdname_enabled) { + conf_dnsrps_sadd(&ctx, " nsdname-enable no "); + } + + /* + * Get the general dnsrpzd parameters from the response-policy + * statement in the view and the general options. + */ + if (conf_dnsrps_get(&obj, maps, rpz_obj, "dnsrps-options", &ctx) && + obj != NULL) + { + conf_dnsrps_sadd(&ctx, " %s\n", cfg_obj_asstring(obj)); + } + + if (ctx.result == ISC_R_SUCCESS) { + *rps_cstr = ctx.cstr; + *rps_cstr_size = ctx.cstr_size; + } else { + if (ctx.cstr != NULL) { + isc_mem_put(ctx.mctx, ctx.cstr, ctx.cstr_size); + } + *rps_cstr = NULL; + *rps_cstr_size = 0; + } + return ctx.result; +} +#endif /* ifdef USE_DNSRPS */ + +static isc_result_t +configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, + const char *str, const char *msg) { + isc_result_t result; + + result = dns_name_fromstring(name, str, dns_rootname, DNS_NAME_DOWNCASE, + view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid %s '%s'", msg, str); + } + return result; +} + +static isc_result_t +configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, + const char *str, const dns_name_t *origin) { + isc_result_t result; + + result = dns_name_fromstring(name, str, origin, DNS_NAME_DOWNCASE, + view->mctx); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + } + return result; +} + +static isc_result_t +configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, + bool recursive_only_default, bool add_soa_default, + dns_ttl_t ttl_default, uint32_t minupdateinterval_default, + const dns_rpz_zone_t *old, bool *old_rpz_okp) { + const cfg_obj_t *rpz_obj, *obj; + const char *str; + dns_rpz_zone_t *zone = NULL; + isc_result_t result; + dns_rpz_num_t rpz_num; + + REQUIRE(old != NULL || !*old_rpz_okp); + + rpz_obj = cfg_listelt_value(element); + + if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) { + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "limit of %d response policy zones exceeded", + DNS_RPZ_MAX_ZONES); + return ISC_R_FAILURE; + } + + result = dns_rpz_new_zone(view->rpzs, &zone); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "Error creating new RPZ zone : %s", + isc_result_totext(result)); + return result; + } + + obj = cfg_tuple_get(rpz_obj, "recursive-only"); + if (cfg_obj_isvoid(obj) ? recursive_only_default + : cfg_obj_asboolean(obj)) + { + view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(zone->num); + } else { + view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(zone->num); + } + + obj = cfg_tuple_get(rpz_obj, "log"); + if (!cfg_obj_isvoid(obj) && !cfg_obj_asboolean(obj)) { + view->rpzs->p.no_log |= DNS_RPZ_ZBIT(zone->num); + } else { + view->rpzs->p.no_log &= ~DNS_RPZ_ZBIT(zone->num); + } + + obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); + if (cfg_obj_isduration(obj)) { + zone->max_policy_ttl = cfg_obj_asduration(obj); + } else { + zone->max_policy_ttl = ttl_default; + } + if (*old_rpz_okp && zone->max_policy_ttl != old->max_policy_ttl) { + *old_rpz_okp = false; + } + + obj = cfg_tuple_get(rpz_obj, "min-update-interval"); + if (cfg_obj_isduration(obj)) { + zone->min_update_interval = cfg_obj_asduration(obj); + } else { + zone->min_update_interval = minupdateinterval_default; + } + if (*old_rpz_okp && + zone->min_update_interval != old->min_update_interval) + { + *old_rpz_okp = false; + } + + str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); + result = configure_rpz_name(view, rpz_obj, &zone->origin, str, "zone"); + if (result != ISC_R_SUCCESS) { + return result; + } + if (dns_name_equal(&zone->origin, dns_rootname)) { + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone name '%s'", str); + return DNS_R_EMPTYLABEL; + } + if (!view->rpzs->p.dnsrps_enabled) { + for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones - 1; + ++rpz_num) + { + if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, + &zone->origin)) + { + cfg_obj_log(rpz_obj, named_g_lctx, + DNS_RPZ_ERROR_LEVEL, + "duplicate '%s'", str); + result = DNS_R_DUPLICATE; + return result; + } + } + } + if (*old_rpz_okp && !dns_name_equal(&old->origin, &zone->origin)) { + *old_rpz_okp = false; + } + + result = configure_rpz_name2(view, rpz_obj, &zone->client_ip, + DNS_RPZ_CLIENT_IP_ZONE, &zone->origin); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name2(view, rpz_obj, &zone->ip, DNS_RPZ_IP_ZONE, + &zone->origin); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name2(view, rpz_obj, &zone->nsdname, + DNS_RPZ_NSDNAME_ZONE, &zone->origin); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name2(view, rpz_obj, &zone->nsip, + DNS_RPZ_NSIP_ZONE, &zone->origin); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name(view, rpz_obj, &zone->passthru, + DNS_RPZ_PASSTHRU_NAME, "name"); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name(view, rpz_obj, &zone->drop, + DNS_RPZ_DROP_NAME, "name"); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = configure_rpz_name(view, rpz_obj, &zone->tcp_only, + DNS_RPZ_TCP_ONLY_NAME, "name"); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = cfg_tuple_get(rpz_obj, "policy"); + if (cfg_obj_isvoid(obj)) { + zone->policy = DNS_RPZ_POLICY_GIVEN; + } else { + str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); + zone->policy = dns_rpz_str2policy(str); + INSIST(zone->policy != DNS_RPZ_POLICY_ERROR); + if (zone->policy == DNS_RPZ_POLICY_CNAME) { + str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); + result = configure_rpz_name(view, rpz_obj, &zone->cname, + str, "cname"); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } + if (*old_rpz_okp && (zone->policy != old->policy || + !dns_name_equal(&old->cname, &zone->cname))) + { + *old_rpz_okp = false; + } + + obj = cfg_tuple_get(rpz_obj, "ede"); + if (!cfg_obj_isstring(obj)) { + zone->ede = 0; + } else { + str = cfg_obj_asstring(obj); + zone->ede = dns_rpz_str2ede(str); + INSIST(zone->ede != UINT16_MAX); + } + if (*old_rpz_okp && zone->ede != old->ede) { + *old_rpz_okp = false; + } + + obj = cfg_tuple_get(rpz_obj, "add-soa"); + if (cfg_obj_isvoid(obj)) { + zone->addsoa = add_soa_default; + } else { + zone->addsoa = cfg_obj_asboolean(obj); + } + if (*old_rpz_okp && zone->addsoa != old->addsoa) { + *old_rpz_okp = false; + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +configure_rpz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t **maps, + const cfg_obj_t *rpz_obj, bool *old_rpz_okp) { + bool dnsrps_enabled; + const cfg_listelt_t *zone_element; + char *rps_cstr; + size_t rps_cstr_size; + const cfg_obj_t *sub_obj; + bool recursive_only_default, add_soa_default; + bool nsip_enabled, nsdname_enabled; + dns_rpz_zbits_t nsip_on, nsdname_on; + dns_ttl_t ttl_default; + uint32_t minupdateinterval_default; + dns_rpz_zones_t *zones; + const dns_rpz_zones_t *old; + bool pview_must_detach = false; + const dns_rpz_zone_t *old_zone; + isc_result_t result; + int i; + + *old_rpz_okp = false; + + zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); + if (zone_element == NULL) { + return ISC_R_SUCCESS; + } + + nsip_enabled = true; + sub_obj = cfg_tuple_get(rpz_obj, "nsip-enable"); + if (!cfg_obj_isvoid(sub_obj)) { + nsip_enabled = cfg_obj_asboolean(sub_obj); + } + nsip_on = nsip_enabled ? DNS_RPZ_ALL_ZBITS : 0; + + nsdname_enabled = true; + sub_obj = cfg_tuple_get(rpz_obj, "nsdname-enable"); + if (!cfg_obj_isvoid(sub_obj)) { + nsdname_enabled = cfg_obj_asboolean(sub_obj); + } + nsdname_on = nsdname_enabled ? DNS_RPZ_ALL_ZBITS : 0; + + /* + * "dnsrps-enable yes|no" can be either a global or response-policy + * clause. + */ + dnsrps_enabled = false; + rps_cstr = NULL; + rps_cstr_size = 0; + sub_obj = NULL; + (void)named_config_get(maps, "dnsrps-enable", &sub_obj); + if (sub_obj != NULL) { + dnsrps_enabled = cfg_obj_asboolean(sub_obj); + } + sub_obj = cfg_tuple_get(rpz_obj, "dnsrps-enable"); + if (!cfg_obj_isvoid(sub_obj)) { + dnsrps_enabled = cfg_obj_asboolean(sub_obj); + } +#ifndef USE_DNSRPS + if (dnsrps_enabled) { + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "\"dnsrps-enable yes\" but" + " without `./configure --enable-dnsrps`"); + return ISC_R_FAILURE; + } +#else /* ifndef USE_DNSRPS */ + if (dnsrps_enabled) { + if (librpz == NULL) { + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, + "\"dnsrps-enable yes\" but %s", + librpz_lib_open_emsg.c); + return ISC_R_FAILURE; + } + + /* + * Generate the DNS Response Policy Service + * configuration string. + */ + result = conf_dnsrps(view, maps, nsip_enabled, nsdname_enabled, + &nsip_on, &nsdname_on, &rps_cstr, + &rps_cstr_size, rpz_obj, zone_element); + if (result != ISC_R_SUCCESS) { + return result; + } + } +#endif /* ifndef USE_DNSRPS */ + + result = dns_rpz_new_zones(view, named_g_loopmgr, rps_cstr, + rps_cstr_size, &view->rpzs); + if (result != ISC_R_SUCCESS) { + return result; + } + + zones = view->rpzs; + + zones->p.nsip_on = nsip_on; + zones->p.nsdname_on = nsdname_on; + + sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); + if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { + recursive_only_default = false; + } else { + recursive_only_default = true; + } + + sub_obj = cfg_tuple_get(rpz_obj, "add-soa"); + if (!cfg_obj_isvoid(sub_obj) && !cfg_obj_asboolean(sub_obj)) { + add_soa_default = false; + } else { + add_soa_default = true; + } + + sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); + if (!cfg_obj_isvoid(sub_obj) && cfg_obj_asboolean(sub_obj)) { + zones->p.break_dnssec = true; + } else { + zones->p.break_dnssec = false; + } + + sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); + if (cfg_obj_isduration(sub_obj)) { + ttl_default = cfg_obj_asduration(sub_obj); + } else { + ttl_default = DNS_RPZ_MAX_TTL_DEFAULT; + } + + sub_obj = cfg_tuple_get(rpz_obj, "min-update-interval"); + if (cfg_obj_isduration(sub_obj)) { + minupdateinterval_default = cfg_obj_asduration(sub_obj); + } else { + minupdateinterval_default = DNS_RPZ_MINUPDATEINTERVAL_DEFAULT; + } + + sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); + if (cfg_obj_isuint32(sub_obj)) { + zones->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; + } else { + zones->p.min_ns_labels = 2; + } + + sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); + if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { + zones->p.qname_wait_recurse = true; + } else { + zones->p.qname_wait_recurse = false; + } + + sub_obj = cfg_tuple_get(rpz_obj, "nsdname-wait-recurse"); + if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { + zones->p.nsdname_wait_recurse = true; + } else { + zones->p.nsdname_wait_recurse = false; + } + + sub_obj = cfg_tuple_get(rpz_obj, "nsip-wait-recurse"); + if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) { + zones->p.nsip_wait_recurse = true; + } else { + zones->p.nsip_wait_recurse = false; + } + + if (pview != NULL) { + old = pview->rpzs; + } else { + result = dns_viewlist_find(&named_g_server->viewlist, + view->name, view->rdclass, &pview); + if (result == ISC_R_SUCCESS) { + pview_must_detach = true; + old = pview->rpzs; + } else { + old = NULL; + } + } + + if (old == NULL) { + *old_rpz_okp = false; + } else { + *old_rpz_okp = true; + } + + for (i = 0; zone_element != NULL; + ++i, zone_element = cfg_list_next(zone_element)) + { + INSIST(!*old_rpz_okp || old != NULL); + if (*old_rpz_okp && i < old->p.num_zones) { + old_zone = old->zones[i]; + } else { + *old_rpz_okp = false; + old_zone = NULL; + } + result = configure_rpz_zone( + view, zone_element, recursive_only_default, + add_soa_default, ttl_default, minupdateinterval_default, + old_zone, old_rpz_okp); + if (result != ISC_R_SUCCESS) { + if (pview_must_detach) { + dns_view_detach(&pview); + } + return result; + } + } + + /* + * If this is a reloading and the parameters and list of policy + * zones are unchanged, then use the same policy data. + * Data for individual zones that must be reloaded will be merged. + */ + if (*old_rpz_okp) { + if (old != NULL && + memcmp(&old->p, &zones->p, sizeof(zones->p)) != 0) + { + *old_rpz_okp = false; + } else if ((old == NULL || old->rps_cstr == NULL) != + (zones->rps_cstr == NULL)) + { + *old_rpz_okp = false; + } else if (old != NULL && zones->rps_cstr != NULL && + strcmp(old->rps_cstr, zones->rps_cstr) != 0) + { + *old_rpz_okp = false; + } + } + + if (*old_rpz_okp) { + dns_rpz_zones_shutdown(view->rpzs); + dns_rpz_zones_detach(&view->rpzs); + dns_rpz_zones_attach(pview->rpzs, &view->rpzs); + dns_rpz_zones_detach(&pview->rpzs); + } else if (old != NULL && pview != NULL) { + ++pview->rpzs->rpz_ver; + view->rpzs->rpz_ver = pview->rpzs->rpz_ver; + cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_DEBUG_LEVEL1, + "updated RPZ policy: version %d", + view->rpzs->rpz_ver); + } + + if (pview_must_detach) { + dns_view_detach(&pview); + } + + return ISC_R_SUCCESS; +} + +static void +catz_addmodzone_cb(void *arg) { + catz_chgzone_t *cz = (catz_chgzone_t *)arg; + isc_result_t result; + dns_forwarders_t *dnsforwarders = NULL; + dns_name_t *name = NULL; + isc_buffer_t namebuf; + isc_buffer_t *confbuf = NULL; + char nameb[DNS_NAME_FORMATSIZE]; + const cfg_obj_t *zlist = NULL; + cfg_obj_t *zoneconf = NULL; + cfg_obj_t *zoneobj = NULL; + ns_cfgctx_t *cfg = NULL; + dns_zone_t *zone = NULL; + + if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { + goto cleanup; + } + + /* + * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' + * is true, so this is expected to be non-NULL. + */ + cfg = (ns_cfgctx_t *)cz->view->new_zone_config; + if (cfg == NULL) { + CHECK(ISC_R_FAILURE); + } + + name = dns_catz_entry_getname(cz->entry); + + isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); + dns_name_totext(name, DNS_NAME_OMITFINALDOT, &namebuf); + isc_buffer_putuint8(&namebuf, 0); + + result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); + if (result == ISC_R_SUCCESS && + dnsforwarders->fwdpolicy == dns_fwdpolicy_only) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_addmodzone_cb: " + "zone '%s' will not be processed because of the " + "explicitly configured forwarding for that zone", + nameb); + goto cleanup; + } + + result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone); + + if (cz->mod) { + dns_catz_zone_t *parentcatz; + + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: error \"%s\" while trying to " + "modify zone '%s'", + isc_result_totext(result), nameb); + goto cleanup; + } + + if (!dns_zone_getadded(zone)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_addmodzone_cb: " + "zone '%s' is not a dynamically " + "added zone", + nameb); + goto cleanup; + } + + parentcatz = dns_zone_get_parentcatz(zone); + + if (parentcatz == NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_addmodzone_cb: " + "zone '%s' exists and is not added by " + "a catalog zone, so won't be modified", + nameb); + goto cleanup; + } + if (parentcatz != cz->origin) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_addmodzone_cb: " + "zone '%s' exists in multiple " + "catalog zones", + nameb); + goto cleanup; + } + + dns_zone_detach(&zone); + } else { + /* Zone shouldn't already exist when adding */ + if (result == ISC_R_SUCCESS) { + if (dns_zone_get_parentcatz(zone) == NULL) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: " + "catz_addmodzone_cb: " + "zone '%s' will not be added " + "because it is an explicitly " + "configured zone", + nameb); + } else { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: " + "catz_addmodzone_cb: " + "zone '%s' will not be added " + "because another catalog zone " + "already contains an entry with " + "that zone", + nameb); + } + goto cleanup; + } else { + RUNTIME_CHECK(result == ISC_R_NOTFOUND); + } + } + RUNTIME_CHECK(zone == NULL); + /* Create a config for new zone */ + confbuf = NULL; + result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); + if (result == ISC_R_SUCCESS) { + cfg_parser_reset(cfg->add_parser); + result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, + &cfg_type_addzoneconf, 0, &zoneconf); + isc_buffer_free(&confbuf); + } + /* + * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() + * failed. + */ + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "catz: error \"%s\" while trying to generate " + "config for zone '%s'", + isc_result_totext(result), nameb); + goto cleanup; + } + CHECK(cfg_map_get(zoneconf, "zone", &zlist)); + if (!cfg_obj_islist(zlist)) { + CHECK(ISC_R_FAILURE); + } + + /* For now we only support adding one zone at a time */ + zoneobj = cfg_listelt_value(cfg_list_first(zlist)); + + /* Mark view unfrozen so that zone can be added */ + isc_loopmgr_pause(named_g_loopmgr); + dns_view_thaw(cz->view); + result = configure_zone(cfg->config, zoneobj, cfg->vconfig, cz->view, + &cz->cbd->server->viewlist, + &cz->cbd->server->kasplist, + &cz->cbd->server->keystorelist, cfg->actx, true, + false, true, cz->mod); + dns_view_freeze(cz->view); + isc_loopmgr_resume(named_g_loopmgr); + + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: failed to configure zone '%s' - %d", nameb, + result); + goto cleanup; + } + + /* Is it there yet? */ + CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone)); + + /* + * Load the zone from the master file. If this fails, we'll + * need to undo the configuration we've done already. + */ + result = dns_zone_load(zone, true); + if (result != ISC_R_SUCCESS) { + dns_db_t *dbp = NULL; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "catz: dns_zone_load() failed " + "with %s; reverting.", + isc_result_totext(result)); + + /* If the zone loaded partially, unload it */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Remove the zone from the zone table */ + dns_view_delzone(cz->view, zone); + goto cleanup; + } + + /* Flag the zone as having been added at runtime */ + dns_zone_setadded(zone, true); + dns_zone_set_parentcatz(zone, cz->origin); + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + if (zoneconf != NULL) { + cfg_obj_destroy(cfg->add_parser, &zoneconf); + } + if (dnsforwarders != NULL) { + dns_forwarders_detach(&dnsforwarders); + } + dns_catz_entry_detach(cz->origin, &cz->entry); + dns_catz_zone_detach(&cz->origin); + dns_view_weakdetach(&cz->view); + isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); +} + +static void +catz_delzone_cb(void *arg) { + catz_chgzone_t *cz = (catz_chgzone_t *)arg; + isc_result_t result; + dns_zone_t *zone = NULL; + dns_db_t *dbp = NULL; + char cname[DNS_NAME_FORMATSIZE]; + const char *file = NULL; + + if (isc_loop_shuttingdown(isc_loop_get(named_g_loopmgr, isc_tid()))) { + goto cleanup; + } + + isc_loopmgr_pause(named_g_loopmgr); + + dns_name_format(dns_catz_entry_getname(cz->entry), cname, + DNS_NAME_FORMATSIZE); + result = dns_view_findzone(cz->view, dns_catz_entry_getname(cz->entry), + DNS_ZTFIND_EXACT, &zone); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_delzone_cb: " + "zone '%s' not found", + cname); + goto resume; + } + + if (!dns_zone_getadded(zone)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_delzone_cb: " + "zone '%s' is not a dynamically added zone", + cname); + goto resume; + } + + if (dns_zone_get_parentcatz(zone) != cz->origin) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_delzone_cb: zone " + "'%s' exists in multiple catalog zones", + cname); + goto resume; + } + + /* Stop answering for this zone */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + if (dns_view_delzone(cz->view, zone) != ISC_R_SUCCESS) { + goto resume; + } + file = dns_zone_getfile(zone); + if (file != NULL) { + isc_file_remove(file); + file = dns_zone_getjournal(zone); + if (file != NULL) { + isc_file_remove(file); + } + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "catz: catz_delzone_cb: " + "zone '%s' deleted", + cname); +resume: + isc_loopmgr_resume(named_g_loopmgr); +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + dns_catz_entry_detach(cz->origin, &cz->entry); + dns_catz_zone_detach(&cz->origin); + dns_view_weakdetach(&cz->view); + isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); +} + +static isc_result_t +catz_run(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, + void *udata, catz_type_t type) { + catz_chgzone_t *cz = NULL; + isc_job_cb action = NULL; + + switch (type) { + case CATZ_ADDZONE: + case CATZ_MODZONE: + action = catz_addmodzone_cb; + break; + case CATZ_DELZONE: + action = catz_delzone_cb; + break; + default: + REQUIRE(0); + UNREACHABLE(); + } + + cz = isc_mem_get(view->mctx, sizeof(*cz)); + *cz = (catz_chgzone_t){ + .cbd = (catz_cb_data_t *)udata, + .mod = (type == CATZ_MODZONE), + }; + isc_mem_attach(view->mctx, &cz->mctx); + + dns_catz_entry_attach(entry, &cz->entry); + dns_catz_zone_attach(origin, &cz->origin); + dns_view_weakattach(view, &cz->view); + + isc_async_run(named_g_mainloop, action, cz); + + return ISC_R_SUCCESS; +} + +static isc_result_t +catz_addzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, + void *udata) { + return catz_run(entry, origin, view, udata, CATZ_ADDZONE); +} + +static isc_result_t +catz_delzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, + void *udata) { + return catz_run(entry, origin, view, udata, CATZ_DELZONE); +} + +static isc_result_t +catz_modzone(dns_catz_entry_t *entry, dns_catz_zone_t *origin, dns_view_t *view, + void *udata) { + return catz_run(entry, origin, view, udata, CATZ_MODZONE); +} + +static void +catz_changeview(dns_catz_entry_t *entry, void *arg1, void *arg2) { + dns_view_t *pview = arg1; + dns_view_t *view = arg2; + + dns_zone_t *zone = NULL; + isc_result_t result = dns_view_findzone( + pview, dns_catz_entry_getname(entry), DNS_ZTFIND_EXACT, &zone); + + if (result != ISC_R_SUCCESS) { + return; + } + + dns_zone_setview(zone, view); + dns_view_addzone(view, zone); + + dns_zone_detach(&zone); +} + +static void +catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { + dns_view_t *view = arg1; + catz_reconfig_data_t *data = arg2; + isc_buffer_t namebuf; + isc_buffer_t *confbuf = NULL; + const cfg_obj_t *zlist = NULL; + char nameb[DNS_NAME_FORMATSIZE]; + cfg_obj_t *zoneconf = NULL; + cfg_obj_t *zoneobj = NULL; + ns_cfgctx_t *cfg = NULL; + dns_zone_t *zone = NULL; + isc_result_t result; + + isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); + dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, + &namebuf); + isc_buffer_putuint8(&namebuf, 0); + + result = dns_view_findzone(view, dns_catz_entry_getname(entry), + DNS_ZTFIND_EXACT, &zone); + if (result != ISC_R_SUCCESS) { + return; + } + + /* + * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' + * is true, so this is expected to be non-NULL. + */ + cfg = (ns_cfgctx_t *)view->new_zone_config; + if (cfg == NULL) { + CHECK(ISC_R_FAILURE); + } + + result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); + if (result == ISC_R_SUCCESS) { + cfg_parser_reset(cfg->add_parser); + result = cfg_parse_buffer(cfg->add_parser, confbuf, "catz", 0, + &cfg_type_addzoneconf, 0, &zoneconf); + isc_buffer_free(&confbuf); + } + /* + * Fail if either dns_catz_generate_zonecfg() or cfg_parse_buffer() + * failed. + */ + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "catz_reconfigure: error \"%s\" while trying to " + "generate config for member zone '%s'", + isc_result_totext(result), nameb); + goto cleanup; + } + + CHECK(cfg_map_get(zoneconf, "zone", &zlist)); + if (!cfg_obj_islist(zlist)) { + CHECK(ISC_R_FAILURE); + } + zoneobj = cfg_listelt_value(cfg_list_first(zlist)); + + result = configure_zone(data->config, zoneobj, cfg->vconfig, view, + &data->cbd->server->viewlist, + &data->cbd->server->kasplist, + &data->cbd->server->keystorelist, cfg->actx, + true, false, true, true); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "catz_reconfigure : error \"%s\" while trying to " + "reconfigure member zone '%s'", + isc_result_totext(result), nameb); + goto cleanup; + } + +cleanup: + if (zoneconf != NULL) { + cfg_obj_destroy(cfg->add_parser, &zoneconf); + } + + dns_zone_detach(&zone); +} + +static isc_result_t +configure_catz_zone(dns_view_t *view, dns_view_t *pview, + const cfg_obj_t *config, const cfg_listelt_t *element) { + const cfg_obj_t *catz_obj, *obj; + dns_catz_zone_t *zone = NULL; + const char *str; + isc_result_t result; + dns_name_t origin; + dns_catz_options_t *opts; + + dns_name_init(&origin, NULL); + catz_obj = cfg_listelt_value(element); + + str = cfg_obj_asstring(cfg_tuple_get(catz_obj, "zone name")); + + result = dns_name_fromstring(&origin, str, dns_rootname, + DNS_NAME_DOWNCASE, view->mctx); + if (result == ISC_R_SUCCESS && dns_name_equal(&origin, dns_rootname)) { + result = DNS_R_EMPTYLABEL; + } + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(catz_obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, + "catz: invalid zone name '%s'", str); + goto cleanup; + } + + result = dns_catz_zone_add(view->catzs, &origin, &zone); + if (result == ISC_R_EXISTS) { + catz_reconfig_data_t data = { + .catz = zone, + .config = config, + .cbd = (catz_cb_data_t *)dns_catz_zones_get_udata( + view->catzs), + }; + + /* + * We have to walk through all the member zones, re-attach + * them to the current view and reconfigure + */ + dns_catz_zone_for_each_entry2(zone, catz_changeview, pview, + view); + dns_catz_zone_for_each_entry2(zone, catz_reconfigure, view, + &data); + } + + dns_catz_zone_resetdefoptions(zone); + opts = dns_catz_zone_getdefoptions(zone); + + obj = cfg_tuple_get(catz_obj, "default-masters"); + if (obj == NULL || !cfg_obj_istuple(obj)) { + obj = cfg_tuple_get(catz_obj, "default-primaries"); + } + if (obj != NULL && cfg_obj_istuple(obj)) { + result = named_config_getipandkeylist(config, obj, view->mctx, + &opts->masters); + } + + obj = cfg_tuple_get(catz_obj, "in-memory"); + if (obj != NULL && cfg_obj_isboolean(obj)) { + opts->in_memory = cfg_obj_asboolean(obj); + } + + obj = cfg_tuple_get(catz_obj, "zone-directory"); + if (!opts->in_memory && obj != NULL && cfg_obj_isstring(obj)) { + opts->zonedir = isc_mem_strdup(view->mctx, + cfg_obj_asstring(obj)); + if (isc_file_isdirectory(opts->zonedir) != ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, DNS_CATZ_ERROR_LEVEL, + "catz: zone-directory '%s' " + "not found; zone files will not be " + "saved", + opts->zonedir); + opts->in_memory = true; + } + } + + obj = cfg_tuple_get(catz_obj, "min-update-interval"); + if (obj != NULL && cfg_obj_isduration(obj)) { + opts->min_update_interval = cfg_obj_asduration(obj); + } + +cleanup: + dns_name_free(&origin, view->mctx); + + return result; +} + +static catz_cb_data_t ns_catz_cbdata; +static dns_catz_zonemodmethods_t ns_catz_zonemodmethods = { + catz_addzone, catz_modzone, catz_delzone, &ns_catz_cbdata +}; + +static isc_result_t +configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, + const cfg_obj_t *catz_obj) { + const cfg_listelt_t *zone_element = NULL; + const dns_catz_zones_t *old = NULL; + bool pview_must_detach = false; + isc_result_t result; + + /* xxxwpk TODO do it cleaner, once, somewhere */ + ns_catz_cbdata.server = named_g_server; + + zone_element = cfg_list_first(cfg_tuple_get(catz_obj, "zone list")); + if (zone_element == NULL) { + return ISC_R_SUCCESS; + } + + if (pview != NULL) { + old = pview->catzs; + } else { + result = dns_viewlist_find(&named_g_server->viewlist, + view->name, view->rdclass, &pview); + if (result == ISC_R_SUCCESS) { + pview_must_detach = true; + old = pview->catzs; + } + } + + if (old != NULL) { + dns_catz_zones_attach(pview->catzs, &view->catzs); + dns_catz_zones_detach(&pview->catzs); + dns_catz_prereconfig(view->catzs); + } else { + view->catzs = dns_catz_zones_new(view->mctx, named_g_loopmgr, + &ns_catz_zonemodmethods); + } + + while (zone_element != NULL) { + CHECK(configure_catz_zone(view, pview, config, zone_element)); + zone_element = cfg_list_next(zone_element); + } + + if (old != NULL) { + dns_catz_postreconfig(view->catzs); + } + + result = ISC_R_SUCCESS; + +cleanup: + if (pview_must_detach) { + dns_view_detach(&pview); + } + + return result; +} + +#define CHECK_RRL(cond, pat, val1, val2) \ + do { \ + if (!(cond)) { \ + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, pat, \ + val1, val2); \ + result = ISC_R_RANGE; \ + goto cleanup; \ + } \ + } while (0) + +#define CHECK_RRL_RATE(rate, def, max_rate, name) \ + do { \ + obj = NULL; \ + rrl->rate.str = name; \ + result = cfg_map_get(map, name, &obj); \ + if (result == ISC_R_SUCCESS) { \ + rrl->rate.r = cfg_obj_asuint32(obj); \ + CHECK_RRL(rrl->rate.r <= max_rate, name " %d > %d", \ + rrl->rate.r, max_rate); \ + } else { \ + rrl->rate.r = def; \ + } \ + rrl->rate.scaled = rrl->rate.r; \ + } while (0) + +static isc_result_t +configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { + const cfg_obj_t *obj; + dns_rrl_t *rrl; + isc_result_t result; + int min_entries, i, j; + + /* + * Most DNS servers have few clients, but intentinally open + * recursive and authoritative servers often have many. + * So start with a small number of entries unless told otherwise + * to reduce cold-start costs. + */ + min_entries = 500; + obj = NULL; + result = cfg_map_get(map, "min-table-size", &obj); + if (result == ISC_R_SUCCESS) { + min_entries = cfg_obj_asuint32(obj); + if (min_entries < 1) { + min_entries = 1; + } + } + result = dns_rrl_init(&rrl, view, min_entries); + if (result != ISC_R_SUCCESS) { + return result; + } + + i = ISC_MAX(20000, min_entries); + obj = NULL; + result = cfg_map_get(map, "max-table-size", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= min_entries, + "max-table-size %d < min-table-size %d", i, + min_entries); + } + rrl->max_entries = i; + + CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, + "responses-per-second"); + CHECK_RRL_RATE(referrals_per_second, rrl->responses_per_second.r, + DNS_RRL_MAX_RATE, "referrals-per-second"); + CHECK_RRL_RATE(nodata_per_second, rrl->responses_per_second.r, + DNS_RRL_MAX_RATE, "nodata-per-second"); + CHECK_RRL_RATE(nxdomains_per_second, rrl->responses_per_second.r, + DNS_RRL_MAX_RATE, "nxdomains-per-second"); + CHECK_RRL_RATE(errors_per_second, rrl->responses_per_second.r, + DNS_RRL_MAX_RATE, "errors-per-second"); + + CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, "all-per-second"); + + CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, "slip"); + + i = 15; + obj = NULL; + result = cfg_map_get(map, "window", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, + "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); + } + rrl->window = i; + + i = 0; + obj = NULL; + result = cfg_map_get(map, "qps-scale", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); + } + rrl->qps_scale = i; + rrl->qps = 1.0; + + i = 24; + obj = NULL; + result = cfg_map_get(map, "ipv4-prefix-length", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 8 && i <= 32, + "invalid 'ipv4-prefix-length %d'%s", i, ""); + } + rrl->ipv4_prefixlen = i; + if (i == 32) { + rrl->ipv4_mask = 0xffffffff; + } else { + rrl->ipv4_mask = htonl(0xffffffff << (32 - i)); + } + + i = 56; + obj = NULL; + result = cfg_map_get(map, "ipv6-prefix-length", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, + "ipv6-prefix-length %d < 16 or > %d", i, + DNS_RRL_MAX_PREFIX); + } + rrl->ipv6_prefixlen = i; + for (j = 0; j < 4; ++j) { + if (i <= 0) { + rrl->ipv6_mask[j] = 0; + } else if (i < 32) { + rrl->ipv6_mask[j] = htonl(0xffffffff << (32 - i)); + } else { + rrl->ipv6_mask[j] = 0xffffffff; + } + i -= 32; + } + + obj = NULL; + result = cfg_map_get(map, "exempt-clients", &obj); + if (result == ISC_R_SUCCESS) { + result = cfg_acl_fromconfig(obj, config, named_g_lctx, + named_g_aclconfctx, named_g_mctx, 0, + &rrl->exempt); + CHECK_RRL(result == ISC_R_SUCCESS, "invalid %s%s", + "address match list", ""); + } + + obj = NULL; + result = cfg_map_get(map, "log-only", &obj); + if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) { + rrl->log_only = true; + } else { + rrl->log_only = false; + } + + return ISC_R_SUCCESS; + +cleanup: + dns_rrl_view_destroy(view); + return result; +} + +static isc_result_t +add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + const dns_name_t *origin, const dns_name_t *contact) { + dns_dbnode_t *node = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_result_t result; + unsigned char buf[DNS_SOA_BUFFERSIZE]; + + CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, + 7200, 604800, 86400, buf, &rdata)); + + dns_rdatalist_init(&rdatalist); + rdatalist.type = rdata.type; + rdatalist.rdclass = rdata.rdclass; + rdatalist.ttl = 86400; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + dns_rdataset_init(&rdataset); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + CHECK(dns_db_findnode(db, name, true, &node)); + CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); + +cleanup: + if (node != NULL) { + dns_db_detachnode(db, &node); + } + return result; +} + +static isc_result_t +add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + const dns_name_t *nsname) { + dns_dbnode_t *node = NULL; + dns_rdata_ns_t ns; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_result_t result; + isc_buffer_t b; + unsigned char buf[DNS_NAME_MAXWIRE]; + + isc_buffer_init(&b, buf, sizeof(buf)); + + ns.common.rdtype = dns_rdatatype_ns; + ns.common.rdclass = dns_db_class(db); + ns.mctx = NULL; + dns_name_init(&ns.name, NULL); + dns_name_clone(nsname, &ns.name); + CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, + &ns, &b)); + + dns_rdatalist_init(&rdatalist); + rdatalist.type = rdata.type; + rdatalist.rdclass = rdata.rdclass; + rdatalist.ttl = 86400; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + dns_rdataset_init(&rdataset); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + CHECK(dns_db_findnode(db, name, true, &node)); + CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); + +cleanup: + if (node != NULL) { + dns_db_detachnode(db, &node); + } + return result; +} + +static isc_result_t +create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, + const cfg_obj_t *zonelist, const char **empty_dbtype, + int empty_dbtypec, dns_zonestat_level_t statlevel) { + char namebuf[DNS_NAME_FORMATSIZE]; + const cfg_listelt_t *element; + const cfg_obj_t *obj; + const cfg_obj_t *zconfig; + const cfg_obj_t *zoptions; + const char *default_dbtype[4] = { ZONEDB_DEFAULT }; + const char *sep = ": view "; + const char *str; + const char *viewname = view->name; + dns_db_t *db = NULL; + dns_dbversion_t *version = NULL; + dns_fixedname_t cfixed; + dns_fixedname_t fixed; + dns_fixedname_t nsfixed; + dns_name_t *contact; + dns_name_t *ns; + dns_name_t *zname; + dns_zone_t *zone = NULL; + int default_dbtypec = 1; + isc_result_t result; + dns_namereln_t namereln; + int order; + unsigned int nlabels; + + zname = dns_fixedname_initname(&fixed); + ns = dns_fixedname_initname(&nsfixed); + contact = dns_fixedname_initname(&cfixed); + + /* + * Look for forward "zones" beneath this empty zone and if so + * create a custom db for the empty zone. + */ + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + zconfig = cfg_listelt_value(element); + str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + CHECK(dns_name_fromstring(zname, str, dns_rootname, 0, NULL)); + namereln = dns_name_fullcompare(zname, name, &order, &nlabels); + if (namereln != dns_namereln_subdomain) { + continue; + } + + zoptions = cfg_tuple_get(zconfig, "options"); + + obj = NULL; + (void)cfg_map_get(zoptions, "type", &obj); + if (obj != NULL && + strcasecmp(cfg_obj_asstring(obj), "forward") == 0) + { + obj = NULL; + (void)cfg_map_get(zoptions, "forward", &obj); + if (obj == NULL) { + continue; + } + if (strcasecmp(cfg_obj_asstring(obj), "only") != 0) { + continue; + } + } + if (db == NULL) { + CHECK(dns_db_create(view->mctx, ZONEDB_DEFAULT, name, + dns_dbtype_zone, view->rdclass, 0, + NULL, &db)); + CHECK(dns_db_newversion(db, &version)); + if (strcmp(empty_dbtype[2], "@") == 0) { + dns_name_clone(name, ns); + } else { + CHECK(dns_name_fromstring(ns, empty_dbtype[2], + dns_rootname, 0, + NULL)); + } + CHECK(dns_name_fromstring(contact, empty_dbtype[3], + dns_rootname, 0, NULL)); + CHECK(add_soa(db, version, name, ns, contact)); + CHECK(add_ns(db, version, name, ns)); + } + CHECK(add_ns(db, version, zname, dns_rootname)); + } + + /* + * Is the existing zone ok to use? + */ + if (pzone != NULL) { + unsigned int typec; + const char **dbargv = NULL; + + if (db != NULL) { + typec = default_dbtypec; + dbargv = default_dbtype; + } else { + typec = empty_dbtypec; + dbargv = empty_dbtype; + } + + result = check_dbtype(pzone, typec, dbargv, view->mctx); + if (result != ISC_R_SUCCESS) { + pzone = NULL; + } + + if (pzone != NULL && + dns_zone_gettype(pzone) != dns_zone_primary) + { + pzone = NULL; + } + if (pzone != NULL && dns_zone_getfile(pzone) != NULL) { + pzone = NULL; + } + if (pzone != NULL) { + dns_zone_getraw(pzone, &zone); + if (zone != NULL) { + dns_zone_detach(&zone); + pzone = NULL; + } + } + } + + if (pzone == NULL) { + CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); + CHECK(dns_zone_setorigin(zone, name)); + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); + if (db == NULL) { + dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype); + } + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_primary); + dns_zone_setstats(zone, named_g_server->zonestats); + } else { + dns_zone_attach(pzone, &zone); + } + + dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setautomatic(zone, true); + if (view->queryacl != NULL) { + dns_zone_setqueryacl(zone, view->queryacl); + } else { + dns_zone_clearqueryacl(zone); + } + if (view->queryonacl != NULL) { + dns_zone_setqueryonacl(zone, view->queryonacl); + } else { + dns_zone_clearqueryonacl(zone); + } + dns_zone_clearupdateacl(zone); + if (view->transferacl != NULL) { + dns_zone_setxfracl(zone, view->transferacl); + } else { + dns_zone_clearxfracl(zone); + } + + setquerystats(zone, view->mctx, statlevel); + if (db != NULL) { + dns_db_closeversion(db, &version, true); + CHECK(dns_zone_replacedb(zone, db, false)); + } + dns_zone_setoption(zone, DNS_ZONEOPT_AUTOEMPTY, true); + dns_zone_setview(zone, view); + CHECK(dns_view_addzone(view, zone)); + + if (!strcmp(viewname, "_default")) { + sep = ""; + viewname = ""; + } + dns_name_format(name, namebuf, sizeof(namebuf)); + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_ZONELOAD, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "automatic empty zone%s%s: %s", sep, viewname, namebuf); + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + if (version != NULL) { + dns_db_closeversion(db, &version, false); + } + if (db != NULL) { + dns_db_detach(&db); + } + + INSIST(version == NULL); + + return result; +} + +static isc_result_t +create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, + const dns_name_t *name, const char *type, isc_mem_t *mctx, + const char *server, const char *contact) { + char namebuf[DNS_NAME_FORMATSIZE]; + const char *dbtype[4] = { "_builtin", NULL, "@", "." }; + const char *sep = ": view "; + const char *viewname = view->name; + dns_zone_t *zone = NULL; + int dbtypec = 4; + isc_result_t result; + + REQUIRE(type != NULL); + + if (!strcmp(viewname, "_default")) { + sep = ""; + viewname = ""; + } + + dbtype[1] = type; + if (server != NULL) { + dbtype[2] = server; + } + if (contact != NULL) { + dbtype[3] = contact; + } + + if (pzone != NULL) { + result = check_dbtype(pzone, dbtypec, dbtype, view->mctx); + if (result != ISC_R_SUCCESS) { + pzone = NULL; + } + } + + if (pzone == NULL) { + /* + * Create the actual zone. + */ + dns_zone_create(&zone, mctx, 0); + CHECK(dns_zone_setorigin(zone, name)); + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); + dns_zone_setclass(zone, view->rdclass); + dns_zone_settype(zone, dns_zone_primary); + dns_zone_setstats(zone, named_g_server->zonestats); + dns_zone_setdbtype(zone, dbtypec, dbtype); + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setautomatic(zone, true); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); + } else { + dns_zone_attach(pzone, &zone); + } + if (view->queryacl != NULL) { + dns_zone_setqueryacl(zone, view->queryacl); + } else { + dns_zone_clearqueryacl(zone); + } + if (view->queryonacl != NULL) { + dns_zone_setqueryonacl(zone, view->queryonacl); + } else { + dns_zone_clearqueryonacl(zone); + } + dns_zone_setview(zone, view); + CHECK(dns_view_addzone(view, zone)); + + dns_name_format(name, namebuf, sizeof(namebuf)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "automatic ipv4only zone%s%s: %s", sep, viewname, + namebuf); + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + return result; +} + +#ifdef HAVE_DNSTAP +static isc_result_t +configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) { + isc_result_t result; + const cfg_obj_t *obj, *obj2; + const cfg_listelt_t *element; + const char *dpath; + const cfg_obj_t *dlist = NULL; + dns_dtmsgtype_t dttypes = 0; + unsigned int i; + struct fstrm_iothr_options *fopt = NULL; + + result = named_config_get(maps, "dnstap", &dlist); + if (result != ISC_R_SUCCESS) { + return ISC_R_SUCCESS; + } + + for (element = cfg_list_first(dlist); element != NULL; + element = cfg_list_next(element)) + { + const char *str; + dns_dtmsgtype_t dt = 0; + + obj = cfg_listelt_value(element); + obj2 = cfg_tuple_get(obj, "type"); + str = cfg_obj_asstring(obj2); + if (strcasecmp(str, "client") == 0) { + dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR; + } else if (strcasecmp(str, "auth") == 0) { + dt |= DNS_DTTYPE_AQ | DNS_DTTYPE_AR; + } else if (strcasecmp(str, "resolver") == 0) { + dt |= DNS_DTTYPE_RQ | DNS_DTTYPE_RR; + } else if (strcasecmp(str, "forwarder") == 0) { + dt |= DNS_DTTYPE_FQ | DNS_DTTYPE_FR; + } else if (strcasecmp(str, "update") == 0) { + dt |= DNS_DTTYPE_UQ | DNS_DTTYPE_UR; + } else if (strcasecmp(str, "all") == 0) { + dt |= DNS_DTTYPE_CQ | DNS_DTTYPE_CR | DNS_DTTYPE_AQ | + DNS_DTTYPE_AR | DNS_DTTYPE_RQ | DNS_DTTYPE_RR | + DNS_DTTYPE_FQ | DNS_DTTYPE_FR | DNS_DTTYPE_UQ | + DNS_DTTYPE_UR; + } + + obj2 = cfg_tuple_get(obj, "mode"); + if (obj2 == NULL || cfg_obj_isvoid(obj2)) { + dttypes |= dt; + continue; + } + + str = cfg_obj_asstring(obj2); + if (strcasecmp(str, "query") == 0) { + dt &= ~DNS_DTTYPE_RESPONSE; + } else if (strcasecmp(str, "response") == 0) { + dt &= ~DNS_DTTYPE_QUERY; + } + + dttypes |= dt; + } + + if (named_g_server->dtenv == NULL && dttypes != 0) { + dns_dtmode_t dmode; + uint64_t max_size = 0; + uint32_t rolls = 0; + isc_log_rollsuffix_t suffix = isc_log_rollsuffix_increment; + + obj = NULL; + CHECKM(named_config_get(maps, "dnstap-output", &obj), + "'dnstap-output' must be set if 'dnstap' is set"); + + obj2 = cfg_tuple_get(obj, "mode"); + if (obj2 == NULL) { + CHECKM(ISC_R_FAILURE, "dnstap-output mode not found"); + } + if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0) { + dmode = dns_dtmode_file; + } else { + dmode = dns_dtmode_unix; + } + + obj2 = cfg_tuple_get(obj, "path"); + if (obj2 == NULL) { + CHECKM(ISC_R_FAILURE, "dnstap-output path not found"); + } + + dpath = cfg_obj_asstring(obj2); + + obj2 = cfg_tuple_get(obj, "size"); + if (obj2 != NULL && cfg_obj_isuint64(obj2)) { + max_size = cfg_obj_asuint64(obj2); + if (max_size > SIZE_MAX) { + cfg_obj_log(obj2, named_g_lctx, ISC_LOG_WARNING, + "'dnstap-output size " + "%" PRIu64 "' " + "is too large for this " + "system; reducing to %lu", + max_size, (unsigned long)SIZE_MAX); + max_size = SIZE_MAX; + } + } + + obj2 = cfg_tuple_get(obj, "versions"); + if (obj2 != NULL && cfg_obj_isuint32(obj2)) { + rolls = cfg_obj_asuint32(obj2); + } else { + rolls = ISC_LOG_ROLLINFINITE; + } + + obj2 = cfg_tuple_get(obj, "suffix"); + if (obj2 != NULL && cfg_obj_isstring(obj2) && + strcasecmp(cfg_obj_asstring(obj2), "timestamp") == 0) + { + suffix = isc_log_rollsuffix_timestamp; + } + + fopt = fstrm_iothr_options_init(); + /* + * Both network threads and worker threads may log dnstap data. + */ + fstrm_iothr_options_set_num_input_queues(fopt, + 2 * named_g_cpus); + fstrm_iothr_options_set_queue_model( + fopt, FSTRM_IOTHR_QUEUE_MODEL_MPSC); + + obj = NULL; + result = named_config_get(maps, "fstrm-set-buffer-hint", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + fstrm_iothr_options_set_buffer_hint(fopt, i); + } + + obj = NULL; + result = named_config_get(maps, "fstrm-set-flush-timeout", + &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + fstrm_iothr_options_set_flush_timeout(fopt, i); + } + + obj = NULL; + result = named_config_get(maps, "fstrm-set-input-queue-size", + &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + fstrm_iothr_options_set_input_queue_size(fopt, i); + } + + obj = NULL; + result = named_config_get( + maps, "fstrm-set-output-notify-threshold", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + fstrm_iothr_options_set_queue_notify_threshold(fopt, i); + } + + obj = NULL; + result = named_config_get(maps, "fstrm-set-output-queue-model", + &obj); + if (result == ISC_R_SUCCESS) { + if (strcasecmp(cfg_obj_asstring(obj), "spsc") == 0) { + i = FSTRM_IOTHR_QUEUE_MODEL_SPSC; + } else { + i = FSTRM_IOTHR_QUEUE_MODEL_MPSC; + } + fstrm_iothr_options_set_queue_model(fopt, i); + } + + obj = NULL; + result = named_config_get(maps, "fstrm-set-output-queue-size", + &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + fstrm_iothr_options_set_output_queue_size(fopt, i); + } + + obj = NULL; + result = named_config_get(maps, "fstrm-set-reopen-interval", + &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asduration(obj); + fstrm_iothr_options_set_reopen_interval(fopt, i); + } + + CHECKM(dns_dt_create(named_g_mctx, dmode, dpath, &fopt, + named_g_mainloop, &named_g_server->dtenv), + "unable to create dnstap environment"); + + CHECKM(dns_dt_setupfile(named_g_server->dtenv, max_size, rolls, + suffix), + "unable to set up dnstap logfile"); + } + + if (named_g_server->dtenv == NULL) { + return ISC_R_SUCCESS; + } + + obj = NULL; + result = named_config_get(maps, "dnstap-version", &obj); + if (result != ISC_R_SUCCESS) { + /* not specified; use the product and version */ + dns_dt_setversion(named_g_server->dtenv, PACKAGE_STRING); + } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { + /* Quoted string */ + dns_dt_setversion(named_g_server->dtenv, cfg_obj_asstring(obj)); + } + + obj = NULL; + result = named_config_get(maps, "dnstap-identity", &obj); + if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { + /* "hostname" is interpreted as boolean true */ + char buf[256]; + if (gethostname(buf, sizeof(buf)) == 0) { + dns_dt_setidentity(named_g_server->dtenv, buf); + } + } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { + /* Quoted string */ + dns_dt_setidentity(named_g_server->dtenv, + cfg_obj_asstring(obj)); + } + + dns_dt_attach(named_g_server->dtenv, &view->dtenv); + view->dttypes = dttypes; + + result = ISC_R_SUCCESS; + +cleanup: + if (fopt != NULL) { + fstrm_iothr_options_destroy(&fopt); + } + + return result; +} +#endif /* HAVE_DNSTAP */ + +static isc_result_t +create_mapped_acl(void) { + isc_result_t result; + dns_acl_t *acl = NULL; + struct in6_addr in6 = IN6ADDR_V4MAPPED_INIT; + isc_netaddr_t addr; + + isc_netaddr_fromin6(&addr, &in6); + + dns_acl_create(named_g_mctx, 1, &acl); + + result = dns_iptable_addprefix(acl->iptable, &addr, 96, true); + if (result == ISC_R_SUCCESS) { + dns_acl_attach(acl, &named_g_mapped); + } + dns_acl_detach(&acl); + return result; +} + +/*% + * A callback for the cfg_pluginlist_foreach() call in configure_view() below. + * If registering any plugin fails, registering subsequent ones is not + * attempted. + */ +static isc_result_t +register_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj, + const char *plugin_path, const char *parameters, + void *callback_data) { + dns_view_t *view = callback_data; + char full_path[PATH_MAX]; + isc_result_t result; + + result = ns_plugin_expandpath(plugin_path, full_path, + sizeof(full_path)); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "%s: plugin configuration failed: " + "unable to get full plugin path: %s", + plugin_path, isc_result_totext(result)); + return result; + } + + result = ns_plugin_register(full_path, parameters, config, + cfg_obj_file(obj), cfg_obj_line(obj), + named_g_mctx, named_g_lctx, + named_g_aclconfctx, view); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "%s: plugin configuration failed: %s", full_path, + isc_result_totext(result)); + } + + return result; +} + +/* + * Determine if a minimal-sized cache can be used for a given view, according + * to 'maps' (implicit defaults, global options, view options) and 'optionmaps' + * (global options, view options). This is only allowed for views which have + * recursion disabled and do not have "max-cache-size" set explicitly. Using + * minimal-sized caches prevents a situation in which all explicitly configured + * and built-in views inherit the default "max-cache-size 90%;" setting, which + * could lead to memory exhaustion with multiple views configured. + */ +static bool +minimal_cache_allowed(const cfg_obj_t *maps[4], + const cfg_obj_t *optionmaps[3]) { + const cfg_obj_t *obj; + + /* + * Do not use a minimal-sized cache for a view with recursion enabled. + */ + obj = NULL; + (void)named_config_get(maps, "recursion", &obj); + INSIST(obj != NULL); + if (cfg_obj_asboolean(obj)) { + return false; + } + + /* + * Do not use a minimal-sized cache if a specific size was requested. + */ + obj = NULL; + (void)named_config_get(optionmaps, "max-cache-size", &obj); + if (obj != NULL) { + return false; + } + + return true; +} + +static const char *const response_synonyms[] = { "response", NULL }; + +/* + * Configure 'view' according to 'vconfig', taking defaults from + * 'config' where values are missing in 'vconfig'. + * + * When configuring the default view, 'vconfig' will be NULL and the + * global defaults in 'config' used exclusively. + */ +static isc_result_t +configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, + cfg_obj_t *vconfig, named_cachelist_t *cachelist, + named_cachelist_t *oldcachelist, dns_kasplist_t *kasplist, + dns_keystorelist_t *keystores, const cfg_obj_t *bindkeys, + isc_mem_t *mctx, cfg_aclconfctx_t *actx, bool need_hints) { + const cfg_obj_t *maps[4]; + const cfg_obj_t *cfgmaps[3]; + const cfg_obj_t *optionmaps[3]; + const cfg_obj_t *options = NULL; + const cfg_obj_t *voptions = NULL; + const cfg_obj_t *forwardtype; + const cfg_obj_t *forwarders; + const cfg_obj_t *alternates; + const cfg_obj_t *zonelist; + const cfg_obj_t *dlzlist; + const cfg_obj_t *dlz; + const cfg_obj_t *prefetch_trigger; + const cfg_obj_t *prefetch_eligible; + unsigned int dlzargc; + char **dlzargv; + const cfg_obj_t *dyndb_list, *plugin_list; + const cfg_obj_t *disabled; + const cfg_obj_t *obj, *obj2; + const cfg_listelt_t *element = NULL; + const cfg_listelt_t *zone_element_latest = NULL; + in_port_t port; + dns_cache_t *cache = NULL; + isc_result_t result; + size_t max_cache_size; + uint32_t max_cache_size_percent = 0; + size_t max_adb_size; + uint32_t lame_ttl, fail_ttl; + uint32_t max_stale_ttl = 0; + uint32_t stale_refresh_time = 0; + dns_tsigkeyring_t *ring = NULL; + dns_transport_list_t *transports = NULL; + dns_view_t *pview = NULL; /* Production view */ + dns_dispatch_t *dispatch4 = NULL; + dns_dispatch_t *dispatch6 = NULL; + bool rpz_configured = false; + bool catz_configured = false; + bool shared_cache = false; + int i = 0, j = 0, k = 0; + const char *str; + const char *cachename = NULL; + dns_order_t *order = NULL; + uint32_t udpsize; + uint32_t maxbits; + unsigned int resopts = 0; + dns_zone_t *zone = NULL; + uint32_t clients_per_query, max_clients_per_query; + bool empty_zones_enable; + const cfg_obj_t *disablelist = NULL; + isc_stats_t *resstats = NULL; + dns_stats_t *resquerystats = NULL; + bool auto_root = false; + named_cache_t *nsc = NULL; + bool zero_no_soattl; + dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; + unsigned int query_timeout; + bool old_rpz_ok = false; + dns_dyndbctx_t *dctx = NULL; + dns_ntatable_t *ntatable = NULL; + const char *qminmode = NULL; + dns_adb_t *adb = NULL; + bool oldcache = false; + + REQUIRE(DNS_VIEW_VALID(view)); + + if (config != NULL) { + (void)cfg_map_get(config, "options", &options); + } + + /* + * maps: view options, options, defaults + * cfgmaps: view options, config + * optionmaps: view options, options + */ + if (vconfig != NULL) { + voptions = cfg_tuple_get(vconfig, "options"); + maps[i++] = voptions; + optionmaps[j++] = voptions; + cfgmaps[k++] = voptions; + } + if (options != NULL) { + maps[i++] = options; + optionmaps[j++] = options; + } + + maps[i++] = named_g_defaults; + maps[i] = NULL; + optionmaps[j] = NULL; + if (config != NULL) { + cfgmaps[k++] = config; + } + cfgmaps[k] = NULL; + + /* + * Set the view's port number for outgoing queries. + */ + CHECKM(named_config_getport(config, "port", &port), "port"); + dns_view_setdstport(view, port); + + /* + * Make the list of response policy zone names for a view that + * is used for real lookups and so cares about hints. + */ + obj = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) + { + CHECK(configure_rpz(view, NULL, maps, obj, &old_rpz_ok)); + rpz_configured = true; + } + + obj = NULL; + if (view->rdclass != dns_rdataclass_in && need_hints && + named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) + { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "'catalog-zones' option is only supported " + "for views with class IN"); + } + + obj = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "catalog-zones", &obj) == ISC_R_SUCCESS) + { + CHECK(configure_catz(view, NULL, config, obj)); + catz_configured = true; + } + + /* + * Configure the zones. + */ + zonelist = NULL; + if (voptions != NULL) { + (void)cfg_map_get(voptions, "zone", &zonelist); + } else { + (void)cfg_map_get(config, "zone", &zonelist); + } + + /* + * Load zone configuration + */ + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, view, viewlist, + kasplist, keystores, actx, false, + old_rpz_ok, false, false)); + zone_element_latest = element; + } + + /* + * Check that a primary or secondary zone was found for each + * zone named in the response policy statement, unless we are + * using RPZ service interface. + */ + if (view->rpzs != NULL && !view->rpzs->p.dnsrps_enabled) { + dns_rpz_num_t n; + + for (n = 0; n < view->rpzs->p.num_zones; ++n) { + if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(&view->rpzs->zones[n]->origin, + namebuf, sizeof(namebuf)); + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + DNS_RPZ_ERROR_LEVEL, + "rpz '%s' is not a primary or a " + "secondary zone", + namebuf); + result = ISC_R_NOTFOUND; + goto cleanup; + } + } + } + + /* + * If we're allowing added zones, then load zone configuration + * from the newzone file for zones that were added during previous + * runs. + */ + CHECK(configure_newzones(view, config, vconfig, actx)); + + /* + * Create Dynamically Loadable Zone driver. + */ + dlzlist = NULL; + if (voptions != NULL) { + (void)cfg_map_get(voptions, "dlz", &dlzlist); + } else { + (void)cfg_map_get(config, "dlz", &dlzlist); + } + + for (element = cfg_list_first(dlzlist); element != NULL; + element = cfg_list_next(element)) + { + dlz = cfg_listelt_value(element); + + obj = NULL; + (void)cfg_map_get(dlz, "database", &obj); + if (obj != NULL) { + dns_dlzdb_t *dlzdb = NULL; + const cfg_obj_t *name, *search = NULL; + char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); + + if (s == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + result = isc_commandline_strtoargv(mctx, s, &dlzargc, + &dlzargv, 0); + if (result != ISC_R_SUCCESS) { + isc_mem_free(mctx, s); + goto cleanup; + } + + name = cfg_map_getname(dlz); + result = dns_dlzcreate(mctx, cfg_obj_asstring(name), + dlzargv[0], dlzargc, dlzargv, + &dlzdb); + isc_mem_free(mctx, s); + isc_mem_cput(mctx, dlzargv, dlzargc, sizeof(*dlzargv)); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* + * If the DLZ backend supports configuration, + * and is searchable, then call its configure + * method now. If not searchable, we'll take + * care of it when we process the zone statement. + */ + (void)cfg_map_get(dlz, "search", &search); + if (search == NULL || cfg_obj_asboolean(search)) { + dlzdb->search = true; + result = dns_dlzconfigure( + view, dlzdb, dlzconfigure_callback); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + ISC_LIST_APPEND(view->dlz_searched, dlzdb, + link); + } else { + dlzdb->search = false; + ISC_LIST_APPEND(view->dlz_unsearched, dlzdb, + link); + } + } + } + + /* + * Obtain configuration parameters that affect the decision of whether + * we can reuse/share an existing cache. + */ + obj = NULL; + result = named_config_get(maps, "max-cache-size", &obj); + INSIST(result == ISC_R_SUCCESS); + /* + * If "-T maxcachesize=..." is in effect, it overrides any other + * "max-cache-size" setting found in configuration, either implicit or + * explicit. For simplicity, the value passed to that command line + * option is always treated as the number of bytes to set + * "max-cache-size" to. + */ + if (named_g_maxcachesize != 0) { + max_cache_size = named_g_maxcachesize; + } else if (minimal_cache_allowed(maps, optionmaps)) { + /* + * dns_cache_setcachesize() will adjust this to the smallest + * allowed value. + */ + max_cache_size = 1; + } else if (cfg_obj_isstring(obj)) { + str = cfg_obj_asstring(obj); + INSIST(strcasecmp(str, "unlimited") == 0); + max_cache_size = 0; + } else if (cfg_obj_ispercentage(obj)) { + max_cache_size = SIZE_AS_PERCENT; + max_cache_size_percent = cfg_obj_aspercentage(obj); + } else { + uint64_t value = cfg_obj_asuint64(obj); + if (value > SIZE_MAX) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "'max-cache-size " + "%" PRIu64 "' " + "is too large for this " + "system; reducing to %lu", + value, (unsigned long)SIZE_MAX); + value = SIZE_MAX; + } + max_cache_size = (size_t)value; + } + + if (max_cache_size == SIZE_AS_PERCENT) { + uint64_t totalphys = isc_meminfo_totalphys(); + + max_cache_size = + (size_t)(totalphys * max_cache_size_percent / 100); + if (totalphys == 0) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "Unable to determine amount of physical " + "memory, setting 'max-cache-size' to " + "unlimited"); + } else { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, + "'max-cache-size %d%%' " + "- setting to %" PRIu64 "MB " + "(out of %" PRIu64 "MB)", + max_cache_size_percent, + (uint64_t)(max_cache_size / (1024 * 1024)), + totalphys / (1024 * 1024)); + } + } + + /* Check-names. */ + obj = NULL; + result = named_checknames_get(maps, response_synonyms, &obj); + INSIST(result == ISC_R_SUCCESS); + + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "fail") == 0) { + resopts |= DNS_RESOLVER_CHECKNAMES | + DNS_RESOLVER_CHECKNAMESFAIL; + view->checknames = true; + } else if (strcasecmp(str, "warn") == 0) { + resopts |= DNS_RESOLVER_CHECKNAMES; + view->checknames = false; + } else if (strcasecmp(str, "ignore") == 0) { + view->checknames = false; + } else { + UNREACHABLE(); + } + + obj = NULL; + result = named_config_get(maps, "zero-no-soa-ttl-cache", &obj); + INSIST(result == ISC_R_SUCCESS); + zero_no_soattl = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "resolver-use-dns64", &obj); + INSIST(result == ISC_R_SUCCESS); + view->usedns64 = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "dns64", &obj); + if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") && + strcmp(view->name, "_meta")) + { + isc_netaddr_t na, suffix, *sp; + unsigned int prefixlen; + const char *server, *contact; + const cfg_obj_t *myobj; + + myobj = NULL; + result = named_config_get(maps, "dns64-server", &myobj); + if (result == ISC_R_SUCCESS) { + server = cfg_obj_asstring(myobj); + } else { + server = NULL; + } + + myobj = NULL; + result = named_config_get(maps, "dns64-contact", &myobj); + if (result == ISC_R_SUCCESS) { + contact = cfg_obj_asstring(myobj); + } else { + contact = NULL; + } + + for (element = cfg_list_first(obj); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *map = cfg_listelt_value(element); + dns_dns64_t *dns64 = NULL; + unsigned int dns64options = 0; + + cfg_obj_asnetprefix(cfg_map_getname(map), &na, + &prefixlen); + + obj = NULL; + (void)cfg_map_get(map, "suffix", &obj); + if (obj != NULL) { + sp = &suffix; + isc_netaddr_fromsockaddr( + sp, cfg_obj_assockaddr(obj)); + } else { + sp = NULL; + } + + clients = mapped = excluded = NULL; + obj = NULL; + (void)cfg_map_get(map, "clients", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + named_g_lctx, actx, + mctx, 0, &clients); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + obj = NULL; + (void)cfg_map_get(map, "mapped", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + named_g_lctx, actx, + mctx, 0, &mapped); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + obj = NULL; + (void)cfg_map_get(map, "exclude", &obj); + if (obj != NULL) { + result = cfg_acl_fromconfig(obj, config, + named_g_lctx, actx, + mctx, 0, &excluded); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } else { + if (named_g_mapped == NULL) { + result = create_mapped_acl(); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + dns_acl_attach(named_g_mapped, &excluded); + } + + obj = NULL; + (void)cfg_map_get(map, "recursive-only", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) { + dns64options |= DNS_DNS64_RECURSIVE_ONLY; + } + + obj = NULL; + (void)cfg_map_get(map, "break-dnssec", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) { + dns64options |= DNS_DNS64_BREAK_DNSSEC; + } + + result = dns_dns64_create(mctx, &na, prefixlen, sp, + clients, mapped, excluded, + dns64options, &dns64); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + dns_dns64_append(&view->dns64, dns64); + view->dns64cnt++; + result = dns64_reverse(view, mctx, &na, prefixlen, + server, contact); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + if (clients != NULL) { + dns_acl_detach(&clients); + } + if (mapped != NULL) { + dns_acl_detach(&mapped); + } + if (excluded != NULL) { + dns_acl_detach(&excluded); + } + } + } + + obj = NULL; + result = named_config_get(maps, "dnssec-accept-expired", &obj); + INSIST(result == ISC_R_SUCCESS); + view->acceptexpired = cfg_obj_asboolean(obj); + + obj = NULL; + /* 'optionmaps', not 'maps': don't check named_g_defaults yet */ + (void)named_config_get(optionmaps, "dnssec-validation", &obj); + if (obj == NULL) { + /* + * Default to VALIDATION_DEFAULT as set in config.c. + */ + (void)cfg_map_get(named_g_defaults, "dnssec-validation", &obj); + INSIST(obj != NULL); + } + if (obj != NULL) { + if (cfg_obj_isboolean(obj)) { + view->enablevalidation = cfg_obj_asboolean(obj); + } else { + /* + * If dnssec-validation is set but not boolean, + * then it must be "auto" + */ + view->enablevalidation = true; + auto_root = true; + } + } + + obj = NULL; + result = named_config_get(maps, "max-cache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->maxcachettl = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "max-ncache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->maxncachettl = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "min-cache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->mincachettl = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "min-ncache-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->minncachettl = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "synth-from-dnssec", &obj); + INSIST(result == ISC_R_SUCCESS); + view->synthfromdnssec = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "stale-cache-enable", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_asboolean(obj)) { + obj = NULL; + result = named_config_get(maps, "max-stale-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + max_stale_ttl = ISC_MAX(cfg_obj_asduration(obj), 1); + } + /* + * If 'stale-cache-enable' is false, max_stale_ttl is set to 0, + * meaning keeping stale RRsets in cache is disabled. + */ + + obj = NULL; + result = named_config_get(maps, "stale-answer-enable", &obj); + INSIST(result == ISC_R_SUCCESS); + view->staleanswersenable = cfg_obj_asboolean(obj); + + result = dns_viewlist_find(&named_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result == ISC_R_SUCCESS) { + view->staleanswersok = pview->staleanswersok; + dns_view_detach(&pview); + } else { + view->staleanswersok = dns_stale_answer_conf; + } + + obj = NULL; + result = named_config_get(maps, "stale-answer-client-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isstring(obj)) { + /* + * The only string values available for this option + * are "disabled" and "off". + * We use (uint32_t) -1 to represent disabled since + * a value of zero means that stale data can be used + * to promptly answer the query, while an attempt to + * refresh the RRset will still be made in background. + */ + view->staleanswerclienttimeout = (uint32_t)-1; + } else { + view->staleanswerclienttimeout = cfg_obj_asuint32(obj); + + /* + * BIND 9 no longer supports non-zero values of + * stale-answer-client-timeout. + */ + if (view->staleanswerclienttimeout != 0) { + view->staleanswerclienttimeout = 0; + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "BIND 9 no longer supports non-zero values of " + "stale-answer-client-timeout, adjusted to 0"); + } + } + + obj = NULL; + result = named_config_get(maps, "stale-refresh-time", &obj); + INSIST(result == ISC_R_SUCCESS); + stale_refresh_time = cfg_obj_asduration(obj); + + /* + * Configure the view's cache. + * + * First, check to see if there are any attach-cache options. If yes, + * attempt to lookup an existing cache at attach it to the view. If + * there is not one, then try to reuse an existing cache if possible; + * otherwise create a new cache. + * + * Note that the ADB is not preserved or shared in either case. + * + * When a matching view is found, the associated statistics are also + * retrieved and reused. + * + * XXX Determining when it is safe to reuse or share a cache is tricky. + * When the view's configuration changes, the cached data may become + * invalid because it reflects our old view of the world. We check + * some of the configuration parameters that could invalidate the cache + * or otherwise make it unshareable, but there are other configuration + * options that should be checked. For example, if a view uses a + * forwarder, changes in the forwarder configuration may invalidate + * the cache. At the moment, it's the administrator's responsibility to + * ensure these configuration options don't invalidate reusing/sharing. + */ + obj = NULL; + result = named_config_get(maps, "attach-cache", &obj); + if (result == ISC_R_SUCCESS) { + cachename = cfg_obj_asstring(obj); + } else { + cachename = view->name; + } + + nsc = cachelist_find(cachelist, cachename, view->rdclass); + if (result == ISC_R_SUCCESS && nsc == NULL) { + /* + * If we're using 'attach-cache' but didn't find the + * specified cache in the cache list already, check + * the old list. + */ + nsc = cachelist_find(oldcachelist, cachename, view->rdclass); + oldcache = true; + } + if (nsc != NULL) { + if (!cache_sharable(nsc->primaryview, view, zero_no_soattl, + max_cache_size, max_stale_ttl, + stale_refresh_time)) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "view %s can't use existing cache %s due " + "to configuration parameter mismatch", + view->name, + dns_cache_getname(nsc->cache)); + nsc = NULL; + } else { + if (oldcache) { + ISC_LIST_UNLINK(*oldcachelist, nsc, link); + ISC_LIST_APPEND(*cachelist, nsc, link); + nsc->primaryview = view; + } + dns_cache_attach(nsc->cache, &cache); + shared_cache = true; + } + } else if (strcmp(cachename, view->name) == 0) { + result = dns_viewlist_find(&named_g_server->viewlist, cachename, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + goto cleanup; + } + if (pview != NULL) { + if (!cache_reusable(pview, view, zero_no_soattl)) { + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_DEBUG(1), + "cache cannot be reused " + "for view %s due to " + "configuration parameter " + "mismatch", + view->name); + } else { + INSIST(pview->cache != NULL); + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_DEBUG(3), + "reusing existing cache"); + dns_cache_attach(pview->cache, &cache); + } + dns_resolver_getstats(pview->resolver, &resstats); + dns_resolver_getquerystats(pview->resolver, + &resquerystats); + dns_view_detach(&pview); + } + } + + if (nsc == NULL) { + /* + * Create a cache with the desired name. This normally + * equals the view name, but may also be a forward + * reference to a view that share the cache with this + * view but is not yet configured. If it is not the + * view name but not a forward reference either, then it + * is simply a named cache that is not shared. + */ + if (cache == NULL) { + CHECK(dns_cache_create(named_g_loopmgr, view->rdclass, + cachename, mctx, &cache)); + } + + nsc = isc_mem_get(mctx, sizeof(*nsc)); + *nsc = (named_cache_t){ + .primaryview = view, + .rdclass = view->rdclass, + .link = ISC_LINK_INITIALIZER, + }; + + dns_cache_attach(cache, &nsc->cache); + ISC_LIST_APPEND(*cachelist, nsc, link); + } + + dns_view_setcache(view, cache, shared_cache); + + dns_cache_setcachesize(cache, max_cache_size); + dns_cache_setservestalettl(cache, max_stale_ttl); + dns_cache_setservestalerefresh(cache, stale_refresh_time); + + dns_cache_detach(&cache); + + obj = NULL; + result = named_config_get(maps, "stale-answer-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + view->staleanswerttl = ISC_MAX(cfg_obj_asduration(obj), 1); + + /* + * Resolver. + */ + CHECK(get_view_querysource_dispatch( + maps, AF_INET, &dispatch4, + (ISC_LIST_PREV(view, link) == NULL))); + CHECK(get_view_querysource_dispatch( + maps, AF_INET6, &dispatch6, + (ISC_LIST_PREV(view, link) == NULL))); + if (dispatch4 == NULL && dispatch6 == NULL) { + UNEXPECTED_ERROR("unable to obtain either an IPv4 or" + " an IPv6 dispatch"); + result = ISC_R_UNEXPECTED; + goto cleanup; + } + + CHECK(dns_view_createresolver(view, named_g_netmgr, resopts, + named_g_server->tlsctx_client_cache, + dispatch4, dispatch6)); + + if (resstats == NULL) { + isc_stats_create(mctx, &resstats, dns_resstatscounter_max); + } + dns_resolver_setstats(view->resolver, resstats); + if (resquerystats == NULL) { + dns_rdatatypestats_create(mctx, &resquerystats); + } + dns_resolver_setquerystats(view->resolver, resquerystats); + + /* + * Set the ADB cache size to 1/8th of the max-cache-size or + * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. + */ + max_adb_size = 0; + if (max_cache_size != 0U) { + max_adb_size = max_cache_size / 8; + if (max_adb_size == 0U) { + max_adb_size = 1; /* Force minimum. */ + } + if (view != nsc->primaryview && + max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) + { + max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE; + if (!nsc->adbsizeadjusted) { + dns_view_getadb(nsc->primaryview, &adb); + if (adb != NULL) { + dns_adb_setadbsize( + adb, + MAX_ADB_SIZE_FOR_CACHESHARE); + nsc->adbsizeadjusted = true; + dns_adb_detach(&adb); + } + } + } + } + dns_view_getadb(view, &adb); + if (adb != NULL) { + dns_adb_setadbsize(adb, max_adb_size); + dns_adb_detach(&adb); + } + + /* + * Set up ADB quotas + */ + { + uint32_t fps, freq; + double low, high, discount; + + obj = NULL; + result = named_config_get(maps, "fetches-per-server", &obj); + INSIST(result == ISC_R_SUCCESS); + obj2 = cfg_tuple_get(obj, "fetches"); + fps = cfg_obj_asuint32(obj2); + obj2 = cfg_tuple_get(obj, "response"); + if (!cfg_obj_isvoid(obj2)) { + const char *resp = cfg_obj_asstring(obj2); + isc_result_t r = DNS_R_SERVFAIL; + + if (strcasecmp(resp, "drop") == 0) { + r = DNS_R_DROP; + } else if (strcasecmp(resp, "fail") == 0) { + r = DNS_R_SERVFAIL; + } else { + UNREACHABLE(); + } + + dns_resolver_setquotaresponse(view->resolver, + dns_quotatype_server, r); + } + + obj = NULL; + result = named_config_get(maps, "fetch-quota-params", &obj); + INSIST(result == ISC_R_SUCCESS); + + obj2 = cfg_tuple_get(obj, "frequency"); + freq = cfg_obj_asuint32(obj2); + + obj2 = cfg_tuple_get(obj, "low"); + low = (double)cfg_obj_asfixedpoint(obj2) / 100.0; + + obj2 = cfg_tuple_get(obj, "high"); + high = (double)cfg_obj_asfixedpoint(obj2) / 100.0; + + obj2 = cfg_tuple_get(obj, "discount"); + discount = (double)cfg_obj_asfixedpoint(obj2) / 100.0; + + dns_view_getadb(view, &adb); + if (adb != NULL) { + dns_adb_setquota(adb, fps, freq, low, high, discount); + dns_adb_detach(&adb); + } + } + + /* + * Set resolver's lame-ttl. + */ + obj = NULL; + result = named_config_get(maps, "lame-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + lame_ttl = cfg_obj_asduration(obj); + if (lame_ttl > 0) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "disabling lame cache despite lame-ttl > 0 as it " + "may cause performance issues"); + } + + /* + * Set the resolver's query timeout. + */ + obj = NULL; + result = named_config_get(maps, "resolver-query-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + query_timeout = cfg_obj_asuint32(obj); + dns_resolver_settimeout(view->resolver, query_timeout); + + /* Specify whether to use 0-TTL for negative response for SOA query */ + dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl); + + /* + * Set the resolver's EDNS UDP size. + */ + obj = NULL; + result = named_config_get(maps, "edns-udp-size", &obj); + INSIST(result == ISC_R_SUCCESS); + udpsize = cfg_obj_asuint32(obj); + if (udpsize < 512) { + udpsize = 512; + } + if (udpsize > 4096) { + udpsize = 4096; + } + dns_view_setudpsize(view, (uint16_t)udpsize); + + /* + * Set the maximum UDP response size. + */ + obj = NULL; + result = named_config_get(maps, "max-udp-size", &obj); + INSIST(result == ISC_R_SUCCESS); + udpsize = cfg_obj_asuint32(obj); + if (udpsize < 512) { + udpsize = 512; + } + if (udpsize > 4096) { + udpsize = 4096; + } + view->maxudp = udpsize; + + /* + * Set the maximum UDP when a COOKIE is not provided. + */ + obj = NULL; + result = named_config_get(maps, "nocookie-udp-size", &obj); + INSIST(result == ISC_R_SUCCESS); + udpsize = cfg_obj_asuint32(obj); + if (udpsize < 128) { + udpsize = 128; + } + if (udpsize > view->maxudp) { + udpsize = view->maxudp; + } + view->nocookieudp = udpsize; + + /* + * Set the maximum rsa exponent bits. + */ + obj = NULL; + result = named_config_get(maps, "max-rsa-exponent-size", &obj); + INSIST(result == ISC_R_SUCCESS); + maxbits = cfg_obj_asuint32(obj); + if (maxbits != 0 && maxbits < 35) { + maxbits = 35; + } + if (maxbits > 4096) { + maxbits = 4096; + } + view->maxbits = maxbits; + + /* + * Set supported DNSSEC algorithms. + */ + disabled = NULL; + (void)named_config_get(maps, "disable-algorithms", &disabled); + if (disabled != NULL) { + for (element = cfg_list_first(disabled); element != NULL; + element = cfg_list_next(element)) + { + CHECK(disable_algorithms(cfg_listelt_value(element), + view->resolver)); + } + } + + /* + * Set supported DS digest types. + */ + disabled = NULL; + (void)named_config_get(maps, "disable-ds-digests", &disabled); + if (disabled != NULL) { + for (element = cfg_list_first(disabled); element != NULL; + element = cfg_list_next(element)) + { + CHECK(disable_ds_digests(cfg_listelt_value(element), + view->resolver)); + } + } + + /* + * A global or view "forwarders" option, if present, + * creates an entry for "." in the forwarding table. + */ + forwardtype = NULL; + forwarders = NULL; + (void)named_config_get(maps, "forward", &forwardtype); + (void)named_config_get(maps, "forwarders", &forwarders); + if (forwarders != NULL) { + CHECK(configure_forward(config, view, dns_rootname, forwarders, + forwardtype)); + } + + /* + * Dual Stack Servers. + */ + alternates = NULL; + (void)named_config_get(maps, "dual-stack-servers", &alternates); + if (alternates != NULL) { + CHECK(configure_alternates(config, view, alternates)); + } + + /* + * We have default hints for class IN if we need them. + */ + if (view->rdclass == dns_rdataclass_in && view->hints == NULL) { + dns_view_sethints(view, named_g_server->in_roothints); + } + + /* + * If we still have no hints, this is a non-IN view with no + * "hints zone" configured. Issue a warning, except if this + * is a root server. Root servers never need to consult + * their hints, so it's no point requiring users to configure + * them. + */ + if (view->hints == NULL) { + dns_zone_t *rootzone = NULL; + (void)dns_view_findzone(view, dns_rootname, DNS_ZTFIND_EXACT, + &rootzone); + if (rootzone != NULL) { + dns_zone_detach(&rootzone); + need_hints = false; + } + if (need_hints) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "no root hints for view '%s'", + view->name); + } + } + + /* + * Configure the view's transports (DoT/DoH) + */ + CHECK(named_transports_fromconfig(config, vconfig, view->mctx, + &transports)); + dns_view_settransports(view, transports); + dns_transport_list_detach(&transports); + + /* + * Configure SIG(0) check limits when matching a DNS message to a view. + */ + obj = NULL; + result = named_config_get(maps, "sig0key-checks-limit", &obj); + INSIST(result == ISC_R_SUCCESS); + view->sig0key_checks_limit = cfg_obj_asuint32(obj); + + obj = NULL; + result = named_config_get(maps, "sig0message-checks-limit", &obj); + INSIST(result == ISC_R_SUCCESS); + view->sig0message_checks_limit = cfg_obj_asuint32(obj); + + /* + * Configure the view's TSIG keys. + */ + CHECK(named_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); + if (named_g_server->sessionkey != NULL) { + dns_tsigkey_t *tsigkey = NULL; + result = dns_tsigkey_createfromkey( + named_g_server->session_keyname, + named_g_server->session_keyalg, + named_g_server->sessionkey, false, false, NULL, 0, 0, + mctx, &tsigkey); + if (result == ISC_R_SUCCESS) { + result = dns_tsigkeyring_add(ring, tsigkey); + dns_tsigkey_detach(&tsigkey); + } + CHECK(result); + } + dns_view_setkeyring(view, ring); + dns_tsigkeyring_detach(&ring); + + /* + * See if we can re-use a dynamic key ring. + */ + result = dns_viewlist_find(&named_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + goto cleanup; + } + if (pview != NULL) { + dns_view_getdynamickeyring(pview, &ring); + if (ring != NULL) { + dns_view_setdynamickeyring(view, ring); + } + dns_tsigkeyring_detach(&ring); + dns_view_detach(&pview); + } else { + dns_view_restorekeyring(view); + } + + /* + * Configure the view's peer list. + */ + { + const cfg_obj_t *peers = NULL; + dns_peerlist_t *newpeers = NULL; + + (void)named_config_get(cfgmaps, "server", &peers); + CHECK(dns_peerlist_new(mctx, &newpeers)); + for (element = cfg_list_first(peers); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *cpeer = cfg_listelt_value(element); + dns_peer_t *peer; + + CHECK(configure_peer(cpeer, mctx, &peer)); + dns_peerlist_addpeer(newpeers, peer); + dns_peer_detach(&peer); + } + dns_peerlist_detach(&view->peers); + view->peers = newpeers; /* Transfer ownership. */ + } + + /* + * Configure the views rrset-order. + */ + { + const cfg_obj_t *rrsetorder = NULL; + + (void)named_config_get(maps, "rrset-order", &rrsetorder); + CHECK(dns_order_create(mctx, &order)); + for (element = cfg_list_first(rrsetorder); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *ent = cfg_listelt_value(element); + + CHECK(configure_order(order, ent)); + } + if (view->order != NULL) { + dns_order_detach(&view->order); + } + dns_order_attach(order, &view->order); + dns_order_detach(&order); + } + /* + * Copy the aclenv object. + */ + dns_aclenv_copy(view->aclenv, ns_interfacemgr_getaclenv( + named_g_server->interfacemgr)); + + /* + * Configure the "match-clients" and "match-destinations" ACL. + * (These are only meaningful at the view level, but 'config' + * must be passed so that named ACLs defined at the global level + * can be retrieved.) + */ + CHECK(configure_view_acl(vconfig, config, NULL, "match-clients", NULL, + actx, named_g_mctx, &view->matchclients)); + CHECK(configure_view_acl(vconfig, config, NULL, "match-destinations", + NULL, actx, named_g_mctx, + &view->matchdestinations)); + + /* + * Configure the "match-recursive-only" option. + */ + obj = NULL; + (void)named_config_get(maps, "match-recursive-only", &obj); + if (obj != NULL && cfg_obj_asboolean(obj)) { + view->matchrecursiveonly = true; + } else { + view->matchrecursiveonly = false; + } + + /* + * Configure other configurable data. + */ + obj = NULL; + result = named_config_get(maps, "recursion", &obj); + INSIST(result == ISC_R_SUCCESS); + view->recursion = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "qname-minimization", &obj); + INSIST(result == ISC_R_SUCCESS); + qminmode = cfg_obj_asstring(obj); + INSIST(qminmode != NULL); + if (!strcmp(qminmode, "strict")) { + view->qminimization = true; + view->qmin_strict = true; + } else if (!strcmp(qminmode, "relaxed")) { + view->qminimization = true; + view->qmin_strict = false; + } else { /* "disabled" or "off" */ + view->qminimization = false; + view->qmin_strict = false; + } + + obj = NULL; + result = named_config_get(maps, "auth-nxdomain", &obj); + INSIST(result == ISC_R_SUCCESS); + view->auth_nxdomain = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "minimal-any", &obj); + INSIST(result == ISC_R_SUCCESS); + view->minimal_any = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "minimal-responses", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + view->minimalresponses = dns_minimal_yes; + } else { + view->minimalresponses = dns_minimal_no; + } + } else { + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "no-auth") == 0) { + view->minimalresponses = dns_minimal_noauth; + } else if (strcasecmp(str, "no-auth-recursive") == 0) { + view->minimalresponses = dns_minimal_noauthrec; + } else { + UNREACHABLE(); + } + } + + obj = NULL; + result = named_config_get(maps, "transfer-format", &obj); + INSIST(result == ISC_R_SUCCESS); + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "many-answers") == 0) { + view->transfer_format = dns_many_answers; + } else if (strcasecmp(str, "one-answer") == 0) { + view->transfer_format = dns_one_answer; + } else { + UNREACHABLE(); + } + + obj = NULL; + result = named_config_get(maps, "trust-anchor-telemetry", &obj); + INSIST(result == ISC_R_SUCCESS); + view->trust_anchor_telemetry = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "root-key-sentinel", &obj); + INSIST(result == ISC_R_SUCCESS); + view->root_key_sentinel = cfg_obj_asboolean(obj); + + /* + * Set the "allow-query", "allow-query-cache", "allow-recursion", + * "allow-recursion-on" and "allow-query-cache-on" ACLs if + * configured in named.conf, but NOT from the global defaults. + * This is done by leaving the third argument to configure_view_acl() + * NULL. + * + * We ignore the global defaults here because these ACLs + * can inherit from each other. If any are still unset after + * applying the inheritance rules, we'll look up the defaults at + * that time. + */ + + /* named.conf only */ + CHECK(configure_view_acl(vconfig, config, NULL, "allow-query", NULL, + actx, named_g_mctx, &view->queryacl)); + + /* named.conf only */ + CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache", + NULL, actx, named_g_mctx, &view->cacheacl)); + /* named.conf only */ + CHECK(configure_view_acl(vconfig, config, NULL, "allow-query-cache-on", + NULL, actx, named_g_mctx, &view->cacheonacl)); + + CHECK(configure_view_acl(vconfig, config, named_g_config, "allow-proxy", + NULL, actx, named_g_mctx, &view->proxyacl)); + + CHECK(configure_view_acl(vconfig, config, named_g_config, + "allow-proxy-on", NULL, actx, named_g_mctx, + &view->proxyonacl)); + + if (strcmp(view->name, "_bind") != 0 && + view->rdclass != dns_rdataclass_chaos) + { + /* named.conf only */ + CHECK(configure_view_acl(vconfig, config, NULL, + "allow-recursion", NULL, actx, + named_g_mctx, &view->recursionacl)); + /* named.conf only */ + CHECK(configure_view_acl(vconfig, config, NULL, + "allow-recursion-on", NULL, actx, + named_g_mctx, &view->recursiononacl)); + } + + if (view->recursion) { + /* + * "allow-query-cache" inherits from "allow-recursion" if set, + * otherwise from "allow-query" if set. + */ + if (view->cacheacl == NULL) { + if (view->recursionacl != NULL) { + dns_acl_attach(view->recursionacl, + &view->cacheacl); + } else if (view->queryacl != NULL) { + dns_acl_attach(view->queryacl, &view->cacheacl); + } + } + + /* + * "allow-recursion" inherits from "allow-query-cache" if set, + * otherwise from "allow-query" if set. + */ + if (view->recursionacl == NULL) { + if (view->cacheacl != NULL) { + dns_acl_attach(view->cacheacl, + &view->recursionacl); + } else if (view->queryacl != NULL) { + dns_acl_attach(view->queryacl, + &view->recursionacl); + } + } + + /* + * "allow-query-cache-on" inherits from "allow-recursion-on" + * if set. + */ + if (view->cacheonacl == NULL) { + if (view->recursiononacl != NULL) { + dns_acl_attach(view->recursiononacl, + &view->cacheonacl); + } + } + + /* + * "allow-recursion-on" inherits from "allow-query-cache-on" + * if set. + */ + if (view->recursiononacl == NULL) { + if (view->cacheonacl != NULL) { + dns_acl_attach(view->cacheonacl, + &view->recursiononacl); + } + } + + /* + * If any are still unset at this point, we now get default + * values for from the global config. + */ + + if (view->recursionacl == NULL) { + /* global default only */ + CHECK(configure_view_acl( + NULL, NULL, named_g_config, "allow-recursion", + NULL, actx, named_g_mctx, &view->recursionacl)); + } + if (view->recursiononacl == NULL) { + /* global default only */ + CHECK(configure_view_acl(NULL, NULL, named_g_config, + "allow-recursion-on", NULL, + actx, named_g_mctx, + &view->recursiononacl)); + } + if (view->cacheacl == NULL) { + /* global default only */ + CHECK(configure_view_acl( + NULL, NULL, named_g_config, "allow-query-cache", + NULL, actx, named_g_mctx, &view->cacheacl)); + } + if (view->cacheonacl == NULL) { + /* global default only */ + CHECK(configure_view_acl(NULL, NULL, named_g_config, + "allow-query-cache-on", NULL, + actx, named_g_mctx, + &view->cacheonacl)); + } + } else { + /* + * We're not recursive; if the query-cache ACLs haven't + * been set at the options/view level, set them to none. + */ + if (view->cacheacl == NULL) { + CHECK(dns_acl_none(mctx, &view->cacheacl)); + } + if (view->cacheonacl == NULL) { + CHECK(dns_acl_none(mctx, &view->cacheonacl)); + } + } + + /* + * Finished setting recursion and query-cache ACLs, so now we + * can get the allow-query default if it wasn't set in named.conf + */ + if (view->queryacl == NULL) { + /* global default only */ + CHECK(configure_view_acl(NULL, NULL, named_g_config, + "allow-query", NULL, actx, + named_g_mctx, &view->queryacl)); + } + + /* + * Ignore case when compressing responses to the specified + * clients. This causes case not always to be preserved, + * and is needed by some broken clients. + */ + CHECK(configure_view_acl(vconfig, config, named_g_config, + "no-case-compress", NULL, actx, named_g_mctx, + &view->nocasecompress)); + + /* + * Disable name compression completely, this is a tradeoff + * between CPU and network usage. + */ + obj = NULL; + result = named_config_get(maps, "message-compression", &obj); + INSIST(result == ISC_R_SUCCESS); + view->msgcompression = cfg_obj_asboolean(obj); + + /* + * Filter setting on addresses in the answer section. + */ + CHECK(configure_view_acl(vconfig, config, named_g_config, + "deny-answer-addresses", "acl", actx, + named_g_mctx, &view->denyansweracl)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses", + "except-from", named_g_mctx, + &view->answeracl_exclude)); + + /* + * Filter setting on names (CNAME/DNAME targets) in the answer section. + */ + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "name", named_g_mctx, + &view->denyanswernames)); + CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases", + "except-from", named_g_mctx, + &view->answernames_exclude)); + + /* + * Configure sortlist, if set + */ + CHECK(configure_view_sortlist(vconfig, config, actx, named_g_mctx, + &view->sortlist)); + + /* + * Configure default allow-update and allow-update-forwarding ACLs, + * so they can be inherited by zones. (XXX: These are not + * read from the options/view level here. However, they may be + * read from there in zoneconf.c:configure_zone_acl() later.) + */ + if (view->updateacl == NULL) { + CHECK(configure_view_acl(NULL, NULL, named_g_config, + "allow-update", NULL, actx, + named_g_mctx, &view->updateacl)); + } + if (view->upfwdacl == NULL) { + CHECK(configure_view_acl(NULL, NULL, named_g_config, + "allow-update-forwarding", NULL, actx, + named_g_mctx, &view->upfwdacl)); + } + + /* + * Configure default allow-transfer and allow-notify ACLs so they + * can be inherited by zones. + */ + if (view->transferacl == NULL) { + CHECK(configure_view_acl(vconfig, config, named_g_config, + "allow-transfer", NULL, actx, + named_g_mctx, &view->transferacl)); + } + if (view->notifyacl == NULL) { + CHECK(configure_view_acl(vconfig, config, named_g_config, + "allow-notify", NULL, actx, + named_g_mctx, &view->notifyacl)); + } + + obj = NULL; + result = named_config_get(maps, "provide-ixfr", &obj); + INSIST(result == ISC_R_SUCCESS); + view->provideixfr = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "request-nsid", &obj); + INSIST(result == ISC_R_SUCCESS); + view->requestnsid = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "send-cookie", &obj); + INSIST(result == ISC_R_SUCCESS); + view->sendcookie = cfg_obj_asboolean(obj); + + obj = NULL; + if (view->pad_acl != NULL) { + dns_acl_detach(&view->pad_acl); + } + result = named_config_get(optionmaps, "response-padding", &obj); + if (result == ISC_R_SUCCESS) { + const cfg_obj_t *padobj = cfg_tuple_get(obj, "block-size"); + const cfg_obj_t *aclobj = cfg_tuple_get(obj, "acl"); + uint32_t padding = cfg_obj_asuint32(padobj); + + if (padding > 512U) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "response-padding block-size cannot " + "exceed 512: lowering"); + padding = 512U; + } + view->padding = (uint16_t)padding; + CHECK(cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, + named_g_mctx, 0, &view->pad_acl)); + } + + obj = NULL; + result = named_config_get(maps, "require-server-cookie", &obj); + INSIST(result == ISC_R_SUCCESS); + view->requireservercookie = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "v6-bias", &obj); + INSIST(result == ISC_R_SUCCESS); + view->v6bias = cfg_obj_asuint32(obj) * 1000; + + obj = NULL; + result = named_config_get(maps, "clients-per-query", &obj); + INSIST(result == ISC_R_SUCCESS); + clients_per_query = cfg_obj_asuint32(obj); + + obj = NULL; + result = named_config_get(maps, "max-clients-per-query", &obj); + INSIST(result == ISC_R_SUCCESS); + max_clients_per_query = cfg_obj_asuint32(obj); + + if (max_clients_per_query < clients_per_query) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "configured clients-per-query (%u) exceeds " + "max-clients-per-query (%u); automatically " + "adjusting max-clients-per-query to (%u)", + clients_per_query, max_clients_per_query, + clients_per_query); + max_clients_per_query = clients_per_query; + } + dns_resolver_setclientsperquery(view->resolver, clients_per_query, + max_clients_per_query); + + /* + * This is used for the cache and also as a default value + * for zone databases. + */ + obj = NULL; + result = named_config_get(maps, "max-records-per-type", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj)); + + /* + * This is used for the cache and also as a default value + * for zone databases. + */ + obj = NULL; + result = named_config_get(maps, "max-types-per-name", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-recursion-depth", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-recursion-queries", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-query-restarts", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_view_setmaxrestarts(view, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-query-count", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_view_setmaxqueries(view, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-validations-per-fetch", &obj); + if (result == ISC_R_SUCCESS) { + dns_resolver_setmaxvalidations(view->resolver, + cfg_obj_asuint32(obj)); + } + + obj = NULL; + result = named_config_get(maps, "max-validation-failures-per-fetch", + &obj); + if (result == ISC_R_SUCCESS) { + dns_resolver_setmaxvalidationfails(view->resolver, + cfg_obj_asuint32(obj)); + } + + obj = NULL; + result = named_config_get(maps, "fetches-per-zone", &obj); + INSIST(result == ISC_R_SUCCESS); + obj2 = cfg_tuple_get(obj, "fetches"); + dns_resolver_setfetchesperzone(view->resolver, cfg_obj_asuint32(obj2)); + obj2 = cfg_tuple_get(obj, "response"); + if (!cfg_obj_isvoid(obj2)) { + const char *resp = cfg_obj_asstring(obj2); + isc_result_t r = DNS_R_SERVFAIL; + + if (strcasecmp(resp, "drop") == 0) { + r = DNS_R_DROP; + } else if (strcasecmp(resp, "fail") == 0) { + r = DNS_R_SERVFAIL; + } else { + UNREACHABLE(); + } + + dns_resolver_setquotaresponse(view->resolver, + dns_quotatype_zone, r); + } + + obj = NULL; + result = named_config_get(maps, "prefetch", &obj); + INSIST(result == ISC_R_SUCCESS); + prefetch_trigger = cfg_tuple_get(obj, "trigger"); + view->prefetch_trigger = cfg_obj_asuint32(prefetch_trigger); + if (view->prefetch_trigger > 10) { + view->prefetch_trigger = 10; + } + prefetch_eligible = cfg_tuple_get(obj, "eligible"); + if (cfg_obj_isvoid(prefetch_eligible)) { + int m; + for (m = 1; maps[m] != NULL; m++) { + obj = NULL; + result = named_config_get(&maps[m], "prefetch", &obj); + INSIST(result == ISC_R_SUCCESS); + prefetch_eligible = cfg_tuple_get(obj, "eligible"); + if (cfg_obj_isuint32(prefetch_eligible)) { + break; + } + } + INSIST(cfg_obj_isuint32(prefetch_eligible)); + } + view->prefetch_eligible = cfg_obj_asuint32(prefetch_eligible); + if (view->prefetch_eligible < view->prefetch_trigger + 6) { + view->prefetch_eligible = view->prefetch_trigger + 6; + } + + /* + * For now, there is only one kind of trusted keys, the + * "security roots". + */ + CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys, + auto_root)); + + obj = NULL; + result = named_config_get(maps, "dnssec-must-be-secure", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(mustbesecure(obj, view->resolver)); + } + + obj = NULL; + result = named_config_get(maps, "nta-recheck", &obj); + INSIST(result == ISC_R_SUCCESS); + view->nta_recheck = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "nta-lifetime", &obj); + INSIST(result == ISC_R_SUCCESS); + view->nta_lifetime = cfg_obj_asduration(obj); + + obj = NULL; + result = named_config_get(maps, "preferred-glue", &obj); + if (result == ISC_R_SUCCESS) { + str = cfg_obj_asstring(obj); + if (strcasecmp(str, "a") == 0) { + view->preferred_glue = dns_rdatatype_a; + } else if (strcasecmp(str, "aaaa") == 0) { + view->preferred_glue = dns_rdatatype_aaaa; + } else { + view->preferred_glue = 0; + } + } else { + view->preferred_glue = 0; + } + + /* + * Load DynDB modules. + */ + dyndb_list = NULL; + if (voptions != NULL) { + (void)cfg_map_get(voptions, "dyndb", &dyndb_list); + } else { + (void)cfg_map_get(config, "dyndb", &dyndb_list); + } + + for (element = cfg_list_first(dyndb_list); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *dyndb = cfg_listelt_value(element); + + if (dctx == NULL) { + const void *hashinit = isc_hash_get_initializer(); + CHECK(dns_dyndb_createctx(mctx, hashinit, named_g_lctx, + view, named_g_server->zonemgr, + named_g_loopmgr, &dctx)); + } + + CHECK(configure_dyndb(dyndb, mctx, dctx)); + } + + /* + * Load plugins. + */ + plugin_list = NULL; + if (voptions != NULL) { + (void)cfg_map_get(voptions, "plugin", &plugin_list); + } else { + (void)cfg_map_get(config, "plugin", &plugin_list); + } + + if (plugin_list != NULL) { + INSIST(view->hooktable == NULL); + CHECK(ns_hooktable_create(view->mctx, + (ns_hooktable_t **)&view->hooktable)); + view->hooktable_free = ns_hooktable_free; + + ns_plugins_create(view->mctx, (ns_plugins_t **)&view->plugins); + view->plugins_free = ns_plugins_free; + + CHECK(cfg_pluginlist_foreach(config, plugin_list, named_g_lctx, + register_one_plugin, view)); + } + + /* + * Setup automatic empty zones. If recursion is off then + * they are disabled by default. + */ + obj = NULL; + (void)named_config_get(maps, "empty-zones-enable", &obj); + (void)named_config_get(maps, "disable-empty-zone", &disablelist); + if (obj == NULL && disablelist == NULL && + view->rdclass == dns_rdataclass_in) + { + empty_zones_enable = view->recursion; + } else if (view->rdclass == dns_rdataclass_in) { + if (obj != NULL) { + empty_zones_enable = cfg_obj_asboolean(obj); + } else { + empty_zones_enable = view->recursion; + } + } else { + empty_zones_enable = false; + } + + if (empty_zones_enable) { + const char *empty; + int empty_zone = 0; + dns_fixedname_t fixed; + dns_name_t *name; + isc_buffer_t buffer; + char server[DNS_NAME_FORMATSIZE + 1]; + char contact[DNS_NAME_FORMATSIZE + 1]; + const char *empty_dbtype[4] = { "_builtin", "empty", NULL, + NULL }; + int empty_dbtypec = 4; + dns_zonestat_level_t statlevel = dns_zonestat_none; + + name = dns_fixedname_initname(&fixed); + + obj = NULL; + result = named_config_get(maps, "empty-server", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), + dns_rootname, 0, NULL)); + isc_buffer_init(&buffer, server, sizeof(server) - 1); + CHECK(dns_name_totext(name, 0, &buffer)); + server[isc_buffer_usedlength(&buffer)] = 0; + empty_dbtype[2] = server; + } else { + empty_dbtype[2] = "@"; + } + + obj = NULL; + result = named_config_get(maps, "empty-contact", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), + dns_rootname, 0, NULL)); + isc_buffer_init(&buffer, contact, sizeof(contact) - 1); + CHECK(dns_name_totext(name, 0, &buffer)); + contact[isc_buffer_usedlength(&buffer)] = 0; + empty_dbtype[3] = contact; + } else { + empty_dbtype[3] = "."; + } + + obj = NULL; + result = named_config_get(maps, "zone-statistics", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + statlevel = dns_zonestat_full; + } else { + statlevel = dns_zonestat_none; + } + } else { + const char *levelstr = cfg_obj_asstring(obj); + if (strcasecmp(levelstr, "full") == 0) { + statlevel = dns_zonestat_full; + } else if (strcasecmp(levelstr, "terse") == 0) { + statlevel = dns_zonestat_terse; + } else if (strcasecmp(levelstr, "none") == 0) { + statlevel = dns_zonestat_none; + } else { + UNREACHABLE(); + } + } + + for (empty = empty_zones[empty_zone]; empty != NULL; + empty = empty_zones[++empty_zone]) + { + dns_forwarders_t *dnsforwarders = NULL; + dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; + + /* + * Look for zone on drop list. + */ + CHECK(dns_name_fromstring(name, empty, dns_rootname, 0, + NULL)); + if (disablelist != NULL && + on_disable_list(disablelist, name)) + { + continue; + } + + /* + * This zone already exists. + */ + (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, + &zone); + if (zone != NULL) { + dns_zone_detach(&zone); + continue; + } + + /* + * If we would forward this name don't add a + * empty zone for it. + */ + result = dns_fwdtable_find(view->fwdtable, name, + &dnsforwarders); + if (result == ISC_R_SUCCESS || + result == DNS_R_PARTIALMATCH) + { + fwdpolicy = dnsforwarders->fwdpolicy; + dns_forwarders_detach(&dnsforwarders); + } + if (fwdpolicy == dns_fwdpolicy_only) { + continue; + } + + /* + * See if we can re-use a existing zone. + */ + result = dns_viewlist_find(&named_g_server->viewlist, + view->name, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + { + goto cleanup; + } + + if (pview != NULL) { + (void)dns_view_findzone( + pview, name, DNS_ZTFIND_EXACT, &zone); + dns_view_detach(&pview); + } + + CHECK(create_empty_zone(zone, name, view, zonelist, + empty_dbtype, empty_dbtypec, + statlevel)); + if (zone != NULL) { + dns_zone_detach(&zone); + } + } + } + + obj = NULL; + if (view->rdclass == dns_rdataclass_in) { + (void)named_config_get(maps, "ipv4only-enable", &obj); + } + if (view->rdclass == dns_rdataclass_in && (obj != NULL) + ? cfg_obj_asboolean(obj) + : !ISC_LIST_EMPTY(view->dns64)) + { + const char *server, *contact; + dns_fixedname_t fixed; + dns_name_t *name; + struct { + const char *name; + const char *type; + } zones[] = { + { "ipv4only.arpa", "ipv4only" }, + { "170.0.0.192.in-addr.arpa", "ipv4reverse" }, + { "171.0.0.192.in-addr.arpa", "ipv4reverse" }, + }; + size_t ipv4only_zone; + + obj = NULL; + result = named_config_get(maps, "ipv4only-server", &obj); + if (result == ISC_R_SUCCESS) { + server = cfg_obj_asstring(obj); + } else { + server = NULL; + } + + obj = NULL; + result = named_config_get(maps, "ipv4only-contact", &obj); + if (result == ISC_R_SUCCESS) { + contact = cfg_obj_asstring(obj); + } else { + contact = NULL; + } + + name = dns_fixedname_initname(&fixed); + for (ipv4only_zone = 0; ipv4only_zone < ARRAY_SIZE(zones); + ipv4only_zone++) + { + dns_forwarders_t *dnsforwarders = NULL; + dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; + + CHECK(dns_name_fromstring(name, + zones[ipv4only_zone].name, + dns_rootname, 0, NULL)); + + (void)dns_view_findzone(view, name, DNS_ZTFIND_EXACT, + &zone); + if (zone != NULL) { + dns_zone_detach(&zone); + continue; + } + + /* + * If we would forward this name don't add it. + */ + result = dns_fwdtable_find(view->fwdtable, name, + &dnsforwarders); + if (result == ISC_R_SUCCESS || + result == DNS_R_PARTIALMATCH) + { + fwdpolicy = dnsforwarders->fwdpolicy; + dns_forwarders_detach(&dnsforwarders); + } + if (fwdpolicy == dns_fwdpolicy_only) { + continue; + } + + /* + * See if we can re-use a existing zone. + */ + result = dns_viewlist_find(&named_g_server->viewlist, + view->name, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + { + goto cleanup; + } + + if (pview != NULL) { + (void)dns_view_findzone( + pview, name, DNS_ZTFIND_EXACT, &zone); + dns_view_detach(&pview); + } + + CHECK(create_ipv4only_zone(zone, view, name, + zones[ipv4only_zone].type, + mctx, server, contact)); + if (zone != NULL) { + dns_zone_detach(&zone); + } + } + } + + obj = NULL; + result = named_config_get(maps, "rate-limit", &obj); + if (result == ISC_R_SUCCESS) { + result = configure_rrl(view, config, obj); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + + /* + * Set the servfail-ttl. + */ + obj = NULL; + result = named_config_get(maps, "servfail-ttl", &obj); + INSIST(result == ISC_R_SUCCESS); + fail_ttl = cfg_obj_asduration(obj); + if (fail_ttl > 30) { + fail_ttl = 30; + } + dns_view_setfailttl(view, fail_ttl); + + /* + * Name space to look up redirect information in. + */ + obj = NULL; + result = named_config_get(maps, "nxdomain-redirect", &obj); + if (result == ISC_R_SUCCESS) { + dns_name_t *name = dns_fixedname_name(&view->redirectfixed); + CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), + dns_rootname, 0, NULL)); + view->redirectzone = name; + } else { + view->redirectzone = NULL; + } + + /* + * Exceptions to DNSSEC validation. + */ + obj = NULL; + result = named_config_get(maps, "validate-except", &obj); + if (result == ISC_R_SUCCESS) { + result = dns_view_getntatable(view, &ntatable); + } + if (result == ISC_R_SUCCESS) { + for (element = cfg_list_first(obj); element != NULL; + element = cfg_list_next(element)) + { + dns_fixedname_t fntaname; + dns_name_t *ntaname; + + ntaname = dns_fixedname_initname(&fntaname); + obj = cfg_listelt_value(element); + CHECK(dns_name_fromstring(ntaname, + cfg_obj_asstring(obj), + dns_rootname, 0, NULL)); + CHECK(dns_ntatable_add(ntatable, ntaname, true, 0, + 0xffffffffU)); + } + } + +#ifdef HAVE_DNSTAP + /* + * Set up the dnstap environment and configure message + * types to log. + */ + CHECK(configure_dnstap(maps, view)); +#endif /* HAVE_DNSTAP */ + + result = ISC_R_SUCCESS; + +cleanup: + /* + * Revert to the old view if there was an error. + */ + if (result != ISC_R_SUCCESS) { + isc_result_t result2; + + result2 = dns_viewlist_find(&named_g_server->viewlist, + view->name, view->rdclass, &pview); + if (result2 == ISC_R_SUCCESS) { + dns_view_thaw(pview); + + obj = NULL; + if (rpz_configured && + pview->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "response-policy", &obj) == + ISC_R_SUCCESS) + { + /* + * We are swapping the places of the `view` and + * `pview` in the function's parameters list + * because we are reverting the same operation + * done previously in the "correct" order. + */ + result2 = configure_rpz(pview, view, maps, obj, + &old_rpz_ok); + if (result2 != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_ERROR, + "rpz configuration " + "revert failed for view " + "'%s'", + pview->name); + } + } + + obj = NULL; + if (catz_configured && + pview->rdclass == dns_rdataclass_in && need_hints && + named_config_get(maps, "catalog-zones", &obj) == + ISC_R_SUCCESS) + { + /* + * We are swapping the places of the `view` and + * `pview` in the function's parameters list + * because we are reverting the same operation + * done previously in the "correct" order. + */ + result2 = configure_catz(pview, view, config, + obj); + if (result2 != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_ERROR, + "catz configuration " + "revert failed for view " + "'%s'", + pview->name); + } + } + + dns_view_freeze(pview); + } + + if (pview != NULL) { + dns_view_detach(&pview); + } + + if (zone_element_latest != NULL) { + for (element = cfg_list_first(zonelist); + element != NULL; element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = + cfg_listelt_value(element); + configure_zone_setviewcommit(result, zconfig, + view); + if (element == zone_element_latest) { + /* + * This was the latest element that was + * successfully configured earlier. + */ + break; + } + } + } + } + + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + if (clients != NULL) { + dns_acl_detach(&clients); + } + if (mapped != NULL) { + dns_acl_detach(&mapped); + } + if (excluded != NULL) { + dns_acl_detach(&excluded); + } + if (ring != NULL) { + dns_tsigkeyring_detach(&ring); + } + if (zone != NULL) { + dns_zone_detach(&zone); + } + if (dispatch4 != NULL) { + dns_dispatch_detach(&dispatch4); + } + if (dispatch6 != NULL) { + dns_dispatch_detach(&dispatch6); + } + if (resstats != NULL) { + isc_stats_detach(&resstats); + } + if (resquerystats != NULL) { + dns_stats_detach(&resquerystats); + } + if (order != NULL) { + dns_order_detach(&order); + } + if (cache != NULL) { + dns_cache_detach(&cache); + } + if (dctx != NULL) { + dns_dyndb_destroyctx(&dctx); + } + + return result; +} + +static isc_result_t +configure_hints(dns_view_t *view, const char *filename) { + isc_result_t result; + dns_db_t *db; + + db = NULL; + result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); + if (result == ISC_R_SUCCESS) { + dns_view_sethints(view, db); + dns_db_detach(&db); + } + + return result; +} + +static isc_result_t +configure_alternates(const cfg_obj_t *config, dns_view_t *view, + const cfg_obj_t *alternates) { + const cfg_obj_t *portobj; + const cfg_obj_t *addresses; + const cfg_listelt_t *element; + isc_result_t result = ISC_R_SUCCESS; + in_port_t port; + + /* + * Determine which port to send requests to. + */ + CHECKM(named_config_getport(config, "port", &port), "port"); + + if (alternates != NULL) { + portobj = cfg_tuple_get(alternates, "port"); + if (cfg_obj_isuint32(portobj)) { + uint32_t val = cfg_obj_asuint32(portobj); + if (val > UINT16_MAX) { + cfg_obj_log(portobj, named_g_lctx, + ISC_LOG_ERROR, + "port '%u' out of range", val); + return ISC_R_RANGE; + } + port = (in_port_t)val; + } + } + + addresses = NULL; + if (alternates != NULL) { + addresses = cfg_tuple_get(alternates, "addresses"); + } + + for (element = cfg_list_first(addresses); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *alternate = cfg_listelt_value(element); + isc_sockaddr_t sa; + + if (!cfg_obj_issockaddr(alternate)) { + dns_fixedname_t fixed; + dns_name_t *name; + const char *str = cfg_obj_asstring( + cfg_tuple_get(alternate, "name")); + isc_buffer_t buffer; + in_port_t myport = port; + + isc_buffer_constinit(&buffer, str, strlen(str)); + isc_buffer_add(&buffer, strlen(str)); + name = dns_fixedname_initname(&fixed); + CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, + NULL)); + + portobj = cfg_tuple_get(alternate, "port"); + if (cfg_obj_isuint32(portobj)) { + uint32_t val = cfg_obj_asuint32(portobj); + if (val > UINT16_MAX) { + cfg_obj_log(portobj, named_g_lctx, + ISC_LOG_ERROR, + "port '%u' out of range", + val); + return ISC_R_RANGE; + } + myport = (in_port_t)val; + } + dns_resolver_addalternate(view->resolver, NULL, name, + myport); + continue; + } + + sa = *cfg_obj_assockaddr(alternate); + if (isc_sockaddr_getport(&sa) == 0) { + isc_sockaddr_setport(&sa, port); + } + dns_resolver_addalternate(view->resolver, &sa, NULL, 0); + } + +cleanup: + return result; +} + +static isc_result_t +validate_tls(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *obj, + isc_log_t *logctx, const char *str, dns_name_t **name) { + dns_fixedname_t fname; + dns_name_t *nm = dns_fixedname_initname(&fname); + isc_result_t result = dns_name_fromstring(nm, str, dns_rootname, 0, + NULL); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + return result; + } + + if (strcasecmp(str, "ephemeral") != 0) { + const cfg_obj_t *tlsmap = find_maplist(config, "tls", str); + + if (tlsmap == NULL) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "tls '%s' is not defined", str); + return ISC_R_FAILURE; + } + } + + if (name != NULL && *name == NULL) { + *name = isc_mem_get(view->mctx, sizeof(dns_name_t)); + dns_name_init(*name, NULL); + dns_name_dup(nm, view->mctx, *name); + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +configure_forward(const cfg_obj_t *config, dns_view_t *view, + const dns_name_t *origin, const cfg_obj_t *forwarders, + const cfg_obj_t *forwardtype) { + const cfg_obj_t *portobj = NULL; + const cfg_obj_t *tlspobj = NULL; + const cfg_obj_t *faddresses = NULL; + const cfg_listelt_t *element = NULL; + dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; + dns_forwarderlist_t fwdlist; + dns_forwarder_t *fwd = NULL; + isc_result_t result; + in_port_t port; + in_port_t tls_port; + const char *tls = NULL; + + ISC_LIST_INIT(fwdlist); + + /* + * Determine which port to send forwarded requests to. + */ + CHECKM(named_config_getport(config, "port", &port), "port"); + CHECKM(named_config_getport(config, "tls-port", &tls_port), "tls-port"); + + if (forwarders != NULL) { + portobj = cfg_tuple_get(forwarders, "port"); + if (cfg_obj_isuint32(portobj)) { + uint32_t val = cfg_obj_asuint32(portobj); + if (val > UINT16_MAX) { + cfg_obj_log(portobj, named_g_lctx, + ISC_LOG_ERROR, + "port '%u' out of range", val); + return ISC_R_RANGE; + } + port = tls_port = (in_port_t)val; + } + } + + /* + * TLS value for forwarded requests. + */ + if (forwarders != NULL) { + tlspobj = cfg_tuple_get(forwarders, "tls"); + if (cfg_obj_isstring(tlspobj)) { + tls = cfg_obj_asstring(tlspobj); + if (tls != NULL) { + result = validate_tls(config, view, tlspobj, + named_g_lctx, tls, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } + } + + faddresses = NULL; + if (forwarders != NULL) { + faddresses = cfg_tuple_get(forwarders, "addresses"); + } + + for (element = cfg_list_first(faddresses); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *forwarder = cfg_listelt_value(element); + const char *cur_tls = NULL; + + fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); + fwd->tlsname = NULL; + cur_tls = cfg_obj_getsockaddrtls(forwarder); + if (cur_tls == NULL) { + cur_tls = tls; + } + if (cur_tls != NULL) { + result = validate_tls(config, view, faddresses, + named_g_lctx, cur_tls, + &fwd->tlsname); + if (result != ISC_R_SUCCESS) { + isc_mem_put(view->mctx, fwd, + sizeof(dns_forwarder_t)); + goto cleanup; + } + } + fwd->addr = *cfg_obj_assockaddr(forwarder); + if (isc_sockaddr_getport(&fwd->addr) == 0) { + isc_sockaddr_setport(&fwd->addr, + cur_tls != NULL ? tls_port : port); + } + ISC_LINK_INIT(fwd, link); + ISC_LIST_APPEND(fwdlist, fwd, link); + } + + if (ISC_LIST_EMPTY(fwdlist)) { + if (forwardtype != NULL) { + cfg_obj_log(forwardtype, named_g_lctx, ISC_LOG_WARNING, + "no forwarders seen; disabling " + "forwarding"); + } + fwdpolicy = dns_fwdpolicy_none; + } else { + if (forwardtype == NULL) { + fwdpolicy = dns_fwdpolicy_first; + } else { + const char *forwardstr = cfg_obj_asstring(forwardtype); + if (strcasecmp(forwardstr, "first") == 0) { + fwdpolicy = dns_fwdpolicy_first; + } else if (strcasecmp(forwardstr, "only") == 0) { + fwdpolicy = dns_fwdpolicy_only; + } else { + UNREACHABLE(); + } + } + } + + result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist, + fwdpolicy); + if (result != ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(origin, namebuf, sizeof(namebuf)); + cfg_obj_log(forwarders, named_g_lctx, ISC_LOG_WARNING, + "could not set up forwarding for domain '%s': %s", + namebuf, isc_result_totext(result)); + goto cleanup; + } + + if (fwdpolicy == dns_fwdpolicy_only) { + dns_view_sfd_add(view, origin); + } + + result = ISC_R_SUCCESS; + +cleanup: + + while (!ISC_LIST_EMPTY(fwdlist)) { + fwd = ISC_LIST_HEAD(fwdlist); + ISC_LIST_UNLINK(fwdlist, fwd, link); + if (fwd->tlsname != NULL) { + dns_name_free(fwd->tlsname, view->mctx); + isc_mem_put(view->mctx, fwd->tlsname, + sizeof(dns_name_t)); + } + isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); + } + + return result; +} + +static isc_result_t +get_viewinfo(const cfg_obj_t *vconfig, const char **namep, + dns_rdataclass_t *classp) { + isc_result_t result = ISC_R_SUCCESS; + const char *viewname; + dns_rdataclass_t viewclass; + + REQUIRE(namep != NULL && *namep == NULL); + REQUIRE(classp != NULL); + + if (vconfig != NULL) { + const cfg_obj_t *classobj = NULL; + + viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); + classobj = cfg_tuple_get(vconfig, "class"); + CHECK(named_config_getclass(classobj, dns_rdataclass_in, + &viewclass)); + if (dns_rdataclass_ismeta(viewclass)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "view '%s': class must not be meta", + viewname); + CHECK(ISC_R_FAILURE); + } + } else { + viewname = "_default"; + viewclass = dns_rdataclass_in; + } + + *namep = viewname; + *classp = viewclass; + +cleanup: + return result; +} + +/* + * Find a view based on its configuration info and attach to it. + * + * If 'vconfig' is NULL, attach to the default view. + */ +static isc_result_t +find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, + dns_view_t **viewp) { + isc_result_t result; + const char *viewname = NULL; + dns_rdataclass_t viewclass; + dns_view_t *view = NULL; + + result = get_viewinfo(vconfig, &viewname, &viewclass); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_viewlist_find(viewlist, viewname, viewclass, &view); + if (result != ISC_R_SUCCESS) { + return result; + } + + *viewp = view; + return ISC_R_SUCCESS; +} + +/* + * Create a new view and add it to the list. + * + * If 'vconfig' is NULL, create the default view. + * + * The view created is attached to '*viewp'. + */ +static isc_result_t +create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, + dns_view_t **viewp) { + isc_result_t result; + const char *viewname = NULL; + dns_rdataclass_t viewclass; + dns_view_t *view = NULL; + + result = get_viewinfo(vconfig, &viewname, &viewclass); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_viewlist_find(viewlist, viewname, viewclass, &view); + if (result == ISC_R_SUCCESS) { + return ISC_R_EXISTS; + } + if (result != ISC_R_NOTFOUND) { + return result; + } + INSIST(view == NULL); + + result = dns_view_create(named_g_mctx, named_g_loopmgr, + named_g_dispatchmgr, viewclass, viewname, + &view); + if (result != ISC_R_SUCCESS) { + return result; + } + + isc_nonce_buf(view->secret, sizeof(view->secret)); + + ISC_LIST_APPEND(*viewlist, view, link); + dns_view_attach(view, viewp); + return ISC_R_SUCCESS; +} + +/* + * Configure or reconfigure a zone. + */ +static isc_result_t +configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, + const cfg_obj_t *vconfig, dns_view_t *view, + dns_viewlist_t *viewlist, dns_kasplist_t *kasplist, + dns_keystorelist_t *keystores, cfg_aclconfctx_t *aclconf, + bool added, bool old_rpz_ok, bool is_catz_member, bool modify) { + dns_view_t *pview = NULL; /* Production view */ + dns_zone_t *zone = NULL; /* New or reused zone */ + dns_zone_t *raw = NULL; /* New or reused raw zone */ + dns_zone_t *dupzone = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *zoptions = NULL; + const cfg_obj_t *typeobj = NULL; + const cfg_obj_t *forwarders = NULL; + const cfg_obj_t *forwardtype = NULL; + const cfg_obj_t *ixfrfromdiffs = NULL; + const cfg_obj_t *viewobj = NULL; + isc_result_t result = ISC_R_SUCCESS; + isc_result_t tresult; + isc_buffer_t buffer; + dns_fixedname_t fixorigin; + dns_name_t *origin; + const char *zname; + dns_rdataclass_t zclass; + const char *ztypestr; + dns_rpz_num_t rpz_num; + bool zone_is_catz = false; + bool zone_maybe_inline = false; + bool inline_signing = false; + bool fullsign = false; + + options = NULL; + (void)cfg_map_get(config, "options", &options); + + zoptions = cfg_tuple_get(zconfig, "options"); + + /* + * Get the zone origin as a dns_name_t. + */ + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + isc_buffer_constinit(&buffer, zname, strlen(zname)); + isc_buffer_add(&buffer, strlen(zname)); + dns_fixedname_init(&fixorigin); + CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), &buffer, + dns_rootname, 0, NULL)); + origin = dns_fixedname_name(&fixorigin); + + CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), + view->rdclass, &zclass)); + if (zclass != view->rdclass) { + const char *vname = NULL; + if (vconfig != NULL) { + vname = cfg_obj_asstring( + cfg_tuple_get(vconfig, "name")); + } else { + vname = ""; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': wrong class for view '%s'", zname, + vname); + result = ISC_R_FAILURE; + goto cleanup; + } + + (void)cfg_map_get(zoptions, "in-view", &viewobj); + if (viewobj != NULL) { + const char *inview = cfg_obj_asstring(viewobj); + dns_view_t *otherview = NULL; + + if (viewlist == NULL) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "'in-view' option is not permitted in " + "dynamically added zones"); + result = ISC_R_FAILURE; + goto cleanup; + } + + result = dns_viewlist_find(viewlist, inview, view->rdclass, + &otherview); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "view '%s' is not yet defined.", inview); + result = ISC_R_FAILURE; + goto cleanup; + } + + result = dns_view_findzone(otherview, origin, DNS_ZTFIND_EXACT, + &zone); + dns_view_detach(&otherview); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "zone '%s' not defined in view '%s'", zname, + inview); + result = ISC_R_FAILURE; + goto cleanup; + } + + CHECK(dns_view_addzone(view, zone)); + dns_zone_detach(&zone); + + /* + * If the zone contains a 'forwarders' statement, configure + * selective forwarding. Note: this is not inherited from the + * other view. + */ + forwarders = NULL; + result = cfg_map_get(zoptions, "forwarders", &forwarders); + if (result == ISC_R_SUCCESS) { + forwardtype = NULL; + (void)cfg_map_get(zoptions, "forward", &forwardtype); + CHECK(configure_forward(config, view, origin, + forwarders, forwardtype)); + } + result = ISC_R_SUCCESS; + goto cleanup; + } + + (void)cfg_map_get(zoptions, "type", &typeobj); + if (typeobj == NULL) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "zone '%s' 'type' not specified", zname); + result = ISC_R_FAILURE; + goto cleanup; + } + ztypestr = cfg_obj_asstring(typeobj); + + /* + * "hints zones" aren't zones. If we've got one, + * configure it and return. + */ + if (strcasecmp(ztypestr, "hint") == 0) { + const cfg_obj_t *fileobj = NULL; + if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': 'file' not specified", zname); + result = ISC_R_FAILURE; + goto cleanup; + } + if (dns_name_equal(origin, dns_rootname)) { + const char *hintsfile = cfg_obj_asstring(fileobj); + + CHECK(configure_hints(view, hintsfile)); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "ignoring non-root hint zone '%s'", + zname); + result = ISC_R_SUCCESS; + } + /* Skip ordinary zone processing. */ + goto cleanup; + } + + /* + * "forward zones" aren't zones either. Translate this syntax into + * the appropriate selective forwarding configuration and return. + */ + if (strcasecmp(ztypestr, "forward") == 0) { + forwardtype = NULL; + forwarders = NULL; + + (void)cfg_map_get(zoptions, "forward", &forwardtype); + (void)cfg_map_get(zoptions, "forwarders", &forwarders); + CHECK(configure_forward(config, view, origin, forwarders, + forwardtype)); + goto cleanup; + } + + /* + * Redirect zones only require minimal configuration. + */ + if (strcasecmp(ztypestr, "redirect") == 0) { + if (view->redirect != NULL) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "redirect zone already exists"); + result = ISC_R_EXISTS; + goto cleanup; + } + result = dns_viewlist_find(viewlist, view->name, view->rdclass, + &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + goto cleanup; + } + if (pview != NULL && pview->redirect != NULL) { + dns_zone_attach(pview->redirect, &zone); + dns_zone_setview(zone, view); + } else { + CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, + &zone)); + CHECK(dns_zone_setorigin(zone, origin)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, + zone)); + dns_zone_setstats(zone, named_g_server->zonestats); + } + CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, + kasplist, keystores, zone, NULL)); + dns_zone_attach(zone, &view->redirect); + goto cleanup; + } + + if (!modify) { + /* + * Check for duplicates in the new zone table. + */ + result = dns_view_findzone(view, origin, DNS_ZTFIND_EXACT, + &dupzone); + if (result == ISC_R_SUCCESS) { + /* + * We already have this zone! + */ + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "zone '%s' already exists", zname); + dns_zone_detach(&dupzone); + result = ISC_R_EXISTS; + goto cleanup; + } + INSIST(dupzone == NULL); + } + + /* + * Note whether this is a response policy zone and which one if so, + * unless we are using RPZ service interface. In that case, the + * BIND zone database has nothing to do with rpz and so we don't care. + */ + for (rpz_num = 0;; ++rpz_num) { + if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones || + view->rpzs->p.dnsrps_enabled) + { + rpz_num = DNS_RPZ_INVALID_NUM; + break; + } + if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) + { + break; + } + } + + if (!is_catz_member && view->catzs != NULL && + dns_catz_zone_get(view->catzs, origin) != NULL) + { + zone_is_catz = true; + } + + /* + * See if we can reuse an existing zone. This is + * only possible if all of these are true: + * - The zone's view exists + * - A zone with the right name exists in the view + * - The zone is compatible with the config + * options (e.g., an existing primary zone cannot + * be reused if the options specify a secondary zone) + * - The zone was not and is still not a response policy zone + * or the zone is a policy zone with an unchanged number + * and we are using the old policy zone summary data. + */ + result = dns_viewlist_find(&named_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + goto cleanup; + } + if (pview != NULL) { + result = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, + &zone); + } + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + goto cleanup; + } + + if (zone != NULL && + !named_zone_reusable(zone, zconfig, vconfig, config, kasplist)) + { + dns_zone_detach(&zone); + fullsign = true; + } + + if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || + (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) + { + dns_zone_detach(&zone); + } + + if (zone != NULL) { + /* + * We found a reusable zone. Make it use the + * new view. + */ + dns_zone_setview(zone, view); + } else { + /* + * We cannot reuse an existing zone, we have + * to create a new one. + */ + CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); + CHECK(dns_zone_setorigin(zone, origin)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); + dns_zone_setstats(zone, named_g_server->zonestats); + } + if (rpz_num != DNS_RPZ_INVALID_NUM) { + result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': incompatible" + " masterfile-format or database" + " for a response policy zone", + zname); + goto cleanup; + } + } + + if (zone_is_catz) { + dns_zone_catz_enable(zone, view->catzs); + } else if (dns_zone_catz_is_enabled(zone)) { + dns_zone_catz_disable(zone); + } + + /* + * If the zone contains a 'forwarders' statement, configure + * selective forwarding. + */ + forwarders = NULL; + if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) { + forwardtype = NULL; + (void)cfg_map_get(zoptions, "forward", &forwardtype); + CHECK(configure_forward(config, view, origin, forwarders, + forwardtype)); + } + + /* + * Mark whether the zone was originally added at runtime or not + */ + dns_zone_setadded(zone, added); + + /* + * Determine if we need to set up inline signing. + */ + zone_maybe_inline = (strcasecmp(ztypestr, "primary") == 0 || + strcasecmp(ztypestr, "master") == 0 || + strcasecmp(ztypestr, "secondary") == 0 || + strcasecmp(ztypestr, "slave") == 0); + + if (zone_maybe_inline) { + inline_signing = named_zone_inlinesigning(zconfig, vconfig, + config, kasplist); + } + if (inline_signing) { + dns_zone_getraw(zone, &raw); + if (raw == NULL) { + dns_zone_create(&raw, dns_zone_getmem(zone), + dns_zone_gettid(zone)); + CHECK(dns_zone_setorigin(raw, origin)); + dns_zone_setview(raw, view); + dns_zone_setstats(raw, named_g_server->zonestats); + CHECK(dns_zone_link(zone, raw)); + } + if (cfg_map_get(zoptions, "ixfr-from-differences", + &ixfrfromdiffs) == ISC_R_SUCCESS) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone '%s': 'ixfr-from-differences' is " + "ignored for inline-signed zones", + zname); + } + } + + /* + * Configure the zone. + */ + CHECK(named_zone_configure(config, vconfig, zconfig, aclconf, kasplist, + keystores, zone, raw)); + + /* + * Add the zone to its view in the new view list. + */ + if (!modify) { + CHECK(dns_view_addzone(view, zone)); + } + + if (zone_is_catz) { + /* + * force catz reload if the zone is loaded; + * if it's not it'll get reloaded on zone load + */ + dns_db_t *db = NULL; + + tresult = dns_zone_getdb(zone, &db); + if (tresult == ISC_R_SUCCESS) { + dns_catz_dbupdate_callback(db, view->catzs); + dns_db_detach(&db); + } + } + + /* + * Ensure that zone keys are reloaded on reconfig + */ + if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0) { + dns_zone_rekey(zone, fullsign); + } + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + if (raw != NULL) { + dns_zone_detach(&raw); + } + if (pview != NULL) { + dns_view_detach(&pview); + } + + return result; +} + +/* + * Configure built-in zone for storing managed-key data. + */ +static isc_result_t +add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { + isc_result_t result; + dns_view_t *pview = NULL; + dns_zone_t *zone = NULL; + dns_acl_t *none = NULL; + char filename[PATH_MAX]; + bool defaultview; + + REQUIRE(view != NULL); + + /* See if we can re-use an existing keydata zone. */ + result = dns_viewlist_find(&named_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) { + return result; + } + + if (pview != NULL) { + if (pview->managed_keys != NULL) { + dns_zone_attach(pview->managed_keys, + &view->managed_keys); + dns_zone_setview(pview->managed_keys, view); + dns_zone_setviewcommit(pview->managed_keys); + dns_view_detach(&pview); + dns_zone_synckeyzone(view->managed_keys); + return ISC_R_SUCCESS; + } + + dns_view_detach(&pview); + } + + /* No existing keydata zone was found; create one */ + CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone)); + CHECK(dns_zone_setorigin(zone, dns_rootname)); + + defaultview = (strcmp(view->name, "_default") == 0); + CHECK(isc_file_sanitize( + directory, defaultview ? "managed-keys" : view->name, + defaultview ? "bind" : "mkeys", filename, sizeof(filename))); + CHECK(dns_zone_setfile(zone, filename, dns_masterformat_text, + &dns_master_style_default)); + + dns_zone_setview(zone, view); + dns_zone_settype(zone, dns_zone_key); + dns_zone_setclass(zone, view->rdclass); + + CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone)); + + CHECK(dns_acl_none(mctx, &none)); + dns_zone_setqueryacl(zone, none); + dns_zone_setqueryonacl(zone, none); + dns_acl_detach(&none); + + dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); + dns_zone_setnotifytype(zone, dns_notifytype_no); + dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); + dns_zone_setjournalsize(zone, 0); + + dns_zone_setstats(zone, named_g_server->zonestats); + setquerystats(zone, mctx, dns_zonestat_none); + + if (view->managed_keys != NULL) { + dns_zone_detach(&view->managed_keys); + } + dns_zone_attach(zone, &view->managed_keys); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "set up managed keys zone for view %s, file '%s'", + view->name, filename); + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + if (none != NULL) { + dns_acl_detach(&none); + } + + return result; +} + +/* + * Configure a single server quota. + */ +static void +configure_server_quota(const cfg_obj_t **maps, const char *name, + isc_quota_t *quota) { + const cfg_obj_t *obj = NULL; + isc_result_t result; + + result = named_config_get(maps, name, &obj); + INSIST(result == ISC_R_SUCCESS); + isc_quota_max(quota, cfg_obj_asuint32(obj)); +} + +/* + * This function is called as soon as the 'directory' statement has been + * parsed. This can be extended to support other options if necessary. + */ +static isc_result_t +directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { + isc_result_t result; + const char *directory; + + REQUIRE(strcasecmp("directory", clausename) == 0); + + UNUSED(arg); + UNUSED(clausename); + + /* + * Change directory. + */ + directory = cfg_obj_asstring(obj); + + if (!isc_file_ischdiridempotent(directory)) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "option 'directory' contains relative path '%s'", + directory); + } + + if (!isc_file_isdirwritable(directory)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "directory '%s' is not writable", directory); + return ISC_R_NOPERM; + } + + result = isc_dir_chdir(directory); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "change directory to '%s' failed: %s", directory, + isc_result_totext(result)); + return result; + } + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == cwd) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "the working directory is now '%s'", cwd); + } + + return ISC_R_SUCCESS; +} + +/* + * This event callback is invoked to do periodic network interface + * scanning. + */ + +static void +interface_timer_tick(void *arg) { + named_server_t *server = (named_server_t *)arg; + + (void)ns_interfacemgr_scan(server->interfacemgr, false, false); +} + +static void +heartbeat_timer_tick(void *arg) { + named_server_t *server = (named_server_t *)arg; + dns_view_t *view = NULL; + + view = ISC_LIST_HEAD(server->viewlist); + while (view != NULL) { + dns_view_dialup(view); + view = ISC_LIST_NEXT(view, link); + } +} + +typedef struct { + isc_mem_t *mctx; + isc_loop_t *loop; + dns_fetch_t *fetch; + dns_view_t *view; + dns_fixedname_t tatname; + dns_fixedname_t keyname; + dns_rdataset_t rdataset; + dns_rdataset_t sigrdataset; +} ns_tat_t; + +static int +cid(const void *a, const void *b) { + const uint16_t ida = *(const uint16_t *)a; + const uint16_t idb = *(const uint16_t *)b; + if (ida < idb) { + return -1; + } else if (ida > idb) { + return 1; + } else { + return 0; + } +} + +static void +tat_done(void *arg) { + dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg; + ns_tat_t *tat = NULL; + + INSIST(resp != NULL); + + tat = resp->arg; + + INSIST(tat != NULL); + + /* Free resources which are not of interest */ + if (resp->node != NULL) { + dns_db_detachnode(resp->db, &resp->node); + } + if (resp->db != NULL) { + dns_db_detach(&resp->db); + } + + dns_resolver_freefresp(&resp); + dns_resolver_destroyfetch(&tat->fetch); + if (dns_rdataset_isassociated(&tat->rdataset)) { + dns_rdataset_disassociate(&tat->rdataset); + } + if (dns_rdataset_isassociated(&tat->sigrdataset)) { + dns_rdataset_disassociate(&tat->sigrdataset); + } + dns_view_detach(&tat->view); + isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); +} + +struct dotat_arg { + dns_view_t *view; + isc_loop_t *loop; +}; + +/*% + * Prepare the QNAME for the TAT query to be sent by processing the trust + * anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and + * the domain name which 'keynode' is associated with in 'origin'. + * + * A maximum of 12 key IDs can be reported in a single TAT query due to the + * 63-octet length limit for any single label in a domain name. If there are + * more than 12 keys configured at 'keynode', only the first 12 will be + * reported in the TAT query. + */ +static isc_result_t +get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) { + dns_rdataset_t dsset; + unsigned int i, n = 0; + uint16_t ids[12]; + isc_textregion_t r; + char label[64]; + int m; + + dns_rdataset_init(&dsset); + if (dns_keynode_dsset(keynode, &dsset)) { + isc_result_t result; + + for (result = dns_rdataset_first(&dsset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&dsset)) + { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_ds_t ds; + + dns_rdata_reset(&rdata); + dns_rdataset_current(&dsset, &rdata); + result = dns_rdata_tostruct(&rdata, &ds, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (n < (sizeof(ids) / sizeof(ids[0]))) { + ids[n] = ds.key_tag; + n++; + } + } + dns_rdataset_disassociate(&dsset); + } + + if (n == 0) { + return DNS_R_EMPTYNAME; + } + + if (n > 1) { + qsort(ids, n, sizeof(ids[0]), cid); + } + + /* + * Encoded as "_ta-xxxx\(-xxxx\)*" where xxxx is the hex version of + * of the keyid. + */ + label[0] = 0; + r.base = label; + r.length = sizeof(label); + m = snprintf(r.base, r.length, "_ta"); + if (m < 0 || (unsigned int)m > r.length) { + return ISC_R_FAILURE; + } + isc_textregion_consume(&r, m); + for (i = 0; i < n; i++) { + m = snprintf(r.base, r.length, "-%04x", ids[i]); + if (m < 0 || (unsigned int)m > r.length) { + return ISC_R_FAILURE; + } + isc_textregion_consume(&r, m); + } + + return dns_name_fromstring(target, label, keyname, 0, NULL); +} + +static void +tat_send(void *arg) { + ns_tat_t *tat = (ns_tat_t *)arg; + char namebuf[DNS_NAME_FORMATSIZE]; + dns_fixedname_t fdomain; + dns_name_t *domain = NULL; + dns_rdataset_t nameservers; + isc_result_t result; + dns_name_t *keyname = NULL; + dns_name_t *tatname = NULL; + + keyname = dns_fixedname_name(&tat->keyname); + tatname = dns_fixedname_name(&tat->tatname); + + dns_name_format(tatname, namebuf, sizeof(namebuf)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s: sending trust-anchor-telemetry query '%s/NULL'", + tat->view->name, namebuf); + + /* + * TAT queries should be sent to the authoritative servers for a given + * zone. If this function is called for a keytable node corresponding + * to a locally served zone, calling dns_resolver_createfetch() with + * NULL 'domain' and 'nameservers' arguments will cause 'tatname' to be + * resolved locally, without sending any TAT queries upstream. + * + * Work around this issue by calling dns_view_findzonecut() first. If + * the zone is served locally, the NS RRset for the given domain name + * will be retrieved from local data; if it is not, the deepest zone + * cut we have for it will be retrieved from cache. In either case, + * passing the results to dns_resolver_createfetch() will prevent it + * from returning NXDOMAIN for 'tatname' while still allowing it to + * chase down any potential delegations returned by upstream servers in + * order to eventually find the destination host to send the TAT query + * to. + * + * After the dns_view_findzonecut() call, 'domain' will hold the + * deepest zone cut we can find for 'keyname' while 'nameservers' will + * hold the NS RRset at that zone cut. + */ + domain = dns_fixedname_initname(&fdomain); + dns_rdataset_init(&nameservers); + result = dns_view_findzonecut(tat->view, keyname, domain, NULL, 0, 0, + true, true, &nameservers, NULL); + if (result == ISC_R_SUCCESS) { + result = dns_resolver_createfetch( + tat->view->resolver, tatname, dns_rdatatype_null, + domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL, + tat->loop, tat_done, tat, NULL, &tat->rdataset, + &tat->sigrdataset, &tat->fetch); + } + + /* + * 'domain' holds the dns_name_t pointer inside a dst_key_t structure. + * dns_resolver_createfetch() creates its own copy of 'domain' if it + * succeeds. Thus, 'domain' is not freed here. + * + * Even if dns_view_findzonecut() returned something else than + * ISC_R_SUCCESS, it still could have associated 'nameservers'. + * dns_resolver_createfetch() creates its own copy of 'nameservers' if + * it succeeds. Thus, we need to check whether 'nameservers' is + * associated and release it if it is. + */ + if (dns_rdataset_isassociated(&nameservers)) { + dns_rdataset_disassociate(&nameservers); + } + + if (result != ISC_R_SUCCESS) { + dns_view_detach(&tat->view); + isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat)); + } +} + +static void +dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, dns_name_t *keyname, + void *arg) { + struct dotat_arg *dotat_arg = (struct dotat_arg *)arg; + isc_result_t result; + dns_view_t *view = NULL; + ns_tat_t *tat = NULL; + + REQUIRE(keytable != NULL); + REQUIRE(keynode != NULL); + REQUIRE(dotat_arg != NULL); + + view = dotat_arg->view; + + tat = isc_mem_get(view->mctx, sizeof(*tat)); + *tat = (ns_tat_t){ 0 }; + + dns_rdataset_init(&tat->rdataset); + dns_rdataset_init(&tat->sigrdataset); + dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname)); + result = get_tat_qname(dns_fixedname_initname(&tat->tatname), keyname, + keynode); + if (result != ISC_R_SUCCESS) { + isc_mem_put(view->mctx, tat, sizeof(*tat)); + return; + } + isc_mem_attach(view->mctx, &tat->mctx); + tat->loop = dotat_arg->loop; + dns_view_attach(view, &tat->view); + + /* + * We don't want to be holding the keytable lock when calling + * dns_view_findzonecut() as it creates a lock order loop so + * call dns_view_findzonecut() in a event handler. + * + * zone->lock (dns_zone_setviewcommit) while holding view->lock + * (dns_view_setviewcommit) + * + * keytable->lock (dns_keytable_find) while holding zone->lock + * (zone_asyncload) + * + * view->lock (dns_view_findzonecut) while holding keytable->lock + * (dns_keytable_forall) + */ + isc_async_run(named_g_mainloop, tat_send, tat); +} + +static void +tat_timer_tick(void *arg) { + isc_result_t result; + named_server_t *server = (named_server_t *)arg; + struct dotat_arg dotat_arg = { 0 }; + dns_view_t *view = NULL; + dns_keytable_t *secroots = NULL; + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (!view->trust_anchor_telemetry || !view->enablevalidation) { + continue; + } + + result = dns_view_getsecroots(view, &secroots); + if (result != ISC_R_SUCCESS) { + continue; + } + + dotat_arg.view = view; + dotat_arg.loop = named_g_mainloop; + dns_keytable_forall(secroots, dotat, &dotat_arg); + dns_keytable_detach(&secroots); + } +} + +static void +pps_timer_tick(void *arg) { + static unsigned int oldrequests = 0; + unsigned int requests = atomic_load_relaxed(&ns_client_requests); + + UNUSED(arg); + + /* + * Don't worry about wrapping as the overflow result will be right. + */ + dns_pps = (requests - oldrequests) / 1200; + oldrequests = requests; +} + +/* + * Replace the current value of '*field', a dynamically allocated + * string or NULL, with a dynamically allocated copy of the + * null-terminated string pointed to by 'value', or NULL. + */ +static void +setstring(named_server_t *server, char **field, const char *value) { + char *copy; + + if (value != NULL) { + copy = isc_mem_strdup(server->mctx, value); + } else { + copy = NULL; + } + + if (*field != NULL) { + isc_mem_free(server->mctx, *field); + } + + *field = copy; +} + +/* + * Replace the current value of '*field', a dynamically allocated + * string or NULL, with another dynamically allocated string + * or NULL if whether 'obj' is a string or void value, respectively. + */ +static void +setoptstring(named_server_t *server, char **field, const cfg_obj_t *obj) { + if (cfg_obj_isvoid(obj)) { + setstring(server, field, NULL); + } else { + setstring(server, field, cfg_obj_asstring(obj)); + } +} + +static void +portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports, + bool positive) { + const cfg_listelt_t *element; + + for (element = cfg_list_first(ports); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *obj = cfg_listelt_value(element); + + if (cfg_obj_isuint32(obj)) { + in_port_t port = (in_port_t)cfg_obj_asuint32(obj); + + if (positive) { + isc_portset_add(portset, port); + } else { + isc_portset_remove(portset, port); + } + } else { + const cfg_obj_t *obj_loport, *obj_hiport; + in_port_t loport, hiport; + + obj_loport = cfg_tuple_get(obj, "loport"); + loport = (in_port_t)cfg_obj_asuint32(obj_loport); + obj_hiport = cfg_tuple_get(obj, "hiport"); + hiport = (in_port_t)cfg_obj_asuint32(obj_hiport); + + if (positive) { + isc_portset_addrange(portset, loport, hiport); + } else { + isc_portset_removerange(portset, loport, + hiport); + } + } + } +} + +static isc_result_t +removed(dns_zone_t *zone, void *uap) { + if (dns_zone_getview(zone) != uap) { + return ISC_R_SUCCESS; + } + + dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", + dns_zonetype_name(dns_zone_gettype(zone))); + return ISC_R_SUCCESS; +} + +static void +cleanup_session_key(named_server_t *server, isc_mem_t *mctx) { + if (server->session_keyfile != NULL) { + isc_file_remove(server->session_keyfile); + isc_mem_free(mctx, server->session_keyfile); + server->session_keyfile = NULL; + } + + if (server->session_keyname != NULL) { + if (dns_name_dynamic(server->session_keyname)) { + dns_name_free(server->session_keyname, mctx); + } + isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t)); + server->session_keyname = NULL; + } + + if (server->sessionkey != NULL) { + dst_key_free(&server->sessionkey); + } + + server->session_keyalg = DST_ALG_UNKNOWN; + server->session_keybits = 0; +} + +static isc_result_t +generate_session_key(const char *filename, const char *keynamestr, + const dns_name_t *keyname, dst_algorithm_t alg, + uint16_t bits, isc_mem_t *mctx, bool first_time, + dst_key_t **keyp) { + isc_result_t result = ISC_R_SUCCESS; + dst_key_t *key = NULL; + isc_buffer_t key_txtbuffer; + isc_buffer_t key_rawbuffer; + char key_txtsecret[256]; + char key_rawsecret[64]; + isc_region_t key_rawregion; + FILE *fp = NULL; + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "generating session key for dynamic DNS"); + + /* generate key */ + result = dst_key_generate(keyname, alg, bits, 1, 0, DNS_KEYPROTO_ANY, + dns_rdataclass_in, NULL, mctx, &key, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + + /* + * Dump the key to the buffer for later use. + */ + isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret)); + CHECK(dst_key_tobuffer(key, &key_rawbuffer)); + + isc_buffer_usedregion(&key_rawbuffer, &key_rawregion); + isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret)); + CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer)); + + /* Dump the key to the key file. */ + fp = named_os_openfile(filename, S_IRUSR | S_IWUSR, first_time); + if (fp == NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "could not create %s", filename); + result = ISC_R_NOPERM; + goto cleanup; + } + + fprintf(fp, + "key \"%s\" {\n" + "\talgorithm %s;\n" + "\tsecret \"%.*s\";\n};\n", + keynamestr, dst_hmac_algorithm_totext(alg), + (int)isc_buffer_usedlength(&key_txtbuffer), + (char *)isc_buffer_base(&key_txtbuffer)); + + CHECK(isc_stdio_flush(fp)); + result = isc_stdio_close(fp); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + *keyp = key; + return ISC_R_SUCCESS; + +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to generate session key " + "for dynamic DNS: %s", + isc_result_totext(result)); + if (fp != NULL) { + (void)isc_stdio_close(fp); + (void)isc_file_remove(filename); + } + if (key != NULL) { + dst_key_free(&key); + } + + return result; +} + +static isc_result_t +configure_session_key(const cfg_obj_t **maps, named_server_t *server, + isc_mem_t *mctx, bool first_time) { + const char *keyfile = NULL, *keynamestr = NULL, *algstr = NULL; + unsigned int algtype; + dns_fixedname_t fname; + dns_name_t *keyname = NULL; + isc_buffer_t buffer; + uint16_t bits; + const cfg_obj_t *obj = NULL; + bool need_deleteold = false; + bool need_createnew = false; + isc_result_t result; + + obj = NULL; + result = named_config_get(maps, "session-keyfile", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isvoid(obj)) { + keyfile = NULL; /* disable it */ + } else { + keyfile = cfg_obj_asstring(obj); + } + } else { + keyfile = named_g_defaultsessionkeyfile; + } + + obj = NULL; + result = named_config_get(maps, "session-keyname", &obj); + INSIST(result == ISC_R_SUCCESS); + keynamestr = cfg_obj_asstring(obj); + isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); + isc_buffer_add(&buffer, strlen(keynamestr)); + keyname = dns_fixedname_initname(&fname); + result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = NULL; + result = named_config_get(maps, "session-keyalg", &obj); + INSIST(result == ISC_R_SUCCESS); + algstr = cfg_obj_asstring(obj); + result = named_config_getkeyalgorithm(algstr, &algtype, &bits); + if (result != ISC_R_SUCCESS) { + const char *s = " (keeping current key)"; + + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "session-keyalg: " + "unsupported or unknown algorithm '%s'%s", + algstr, server->session_keyfile != NULL ? s : ""); + return result; + } + + /* See if we need to (re)generate a new key. */ + if (keyfile == NULL) { + if (server->session_keyfile != NULL) { + need_deleteold = true; + } + } else if (server->session_keyfile == NULL) { + need_createnew = true; + } else if (strcmp(keyfile, server->session_keyfile) != 0 || + !dns_name_equal(server->session_keyname, keyname) || + server->session_keyalg != algtype || + server->session_keybits != bits) + { + need_deleteold = true; + need_createnew = true; + } + + if (need_deleteold) { + INSIST(server->session_keyfile != NULL); + INSIST(server->session_keyname != NULL); + INSIST(server->sessionkey != NULL); + + cleanup_session_key(server, mctx); + } + + if (need_createnew) { + INSIST(server->sessionkey == NULL); + INSIST(server->session_keyfile == NULL); + INSIST(server->session_keyname == NULL); + INSIST(server->session_keyalg == DST_ALG_UNKNOWN); + INSIST(server->session_keybits == 0); + + server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(server->session_keyname, NULL); + dns_name_dup(keyname, mctx, server->session_keyname); + + server->session_keyfile = isc_mem_strdup(mctx, keyfile); + + server->session_keyalg = algtype; + server->session_keybits = bits; + + CHECK(generate_session_key(keyfile, keynamestr, keyname, + algtype, bits, mctx, first_time, + &server->sessionkey)); + } + + return result; + +cleanup: + cleanup_session_key(server, mctx); + return result; +} + +static isc_result_t +setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx) { + isc_result_t result = ISC_R_SUCCESS; + bool allow = false; + ns_cfgctx_t *nzcfg = NULL; + const cfg_obj_t *maps[4]; + const cfg_obj_t *options = NULL, *voptions = NULL; + const cfg_obj_t *nz = NULL; + const cfg_obj_t *nzdir = NULL; + const char *dir = NULL; + const cfg_obj_t *obj = NULL; + int i = 0; + uint64_t mapsize = 0ULL; + + REQUIRE(config != NULL); + + if (vconfig != NULL) { + voptions = cfg_tuple_get(vconfig, "options"); + } + if (voptions != NULL) { + maps[i++] = voptions; + } + result = cfg_map_get(config, "options", &options); + if (result == ISC_R_SUCCESS) { + maps[i++] = options; + } + maps[i++] = named_g_defaults; + maps[i] = NULL; + + result = named_config_get(maps, "allow-new-zones", &nz); + if (result == ISC_R_SUCCESS) { + allow = cfg_obj_asboolean(nz); + } + result = named_config_get(maps, "new-zones-directory", &nzdir); + if (result == ISC_R_SUCCESS) { + dir = cfg_obj_asstring(nzdir); + result = isc_file_isdirectory(dir); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "invalid new-zones-directory %s: %s", dir, + isc_result_totext(result)); + return result; + } + if (!isc_file_isdirwritable(dir)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "new-zones-directory '%s' " + "is not writable", + dir); + return ISC_R_NOPERM; + } + + dns_view_setnewzonedir(view, dir); + } + +#ifdef HAVE_LMDB + result = named_config_get(maps, "lmdb-mapsize", &obj); + if (result == ISC_R_SUCCESS && obj != NULL) { + mapsize = cfg_obj_asuint64(obj); + if (mapsize < (1ULL << 20)) { /* 1 megabyte */ + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "'lmdb-mapsize " + "%" PRId64 "' " + "is too small", + mapsize); + return ISC_R_FAILURE; + } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "'lmdb-mapsize " + "%" PRId64 "' " + "is too large", + mapsize); + return ISC_R_FAILURE; + } + } +#else /* ifdef HAVE_LMDB */ + UNUSED(obj); +#endif /* HAVE_LMDB */ + + /* + * A non-empty catalog-zones statement implies allow-new-zones + */ + if (!allow) { + const cfg_obj_t *cz = NULL; + result = named_config_get(maps, "catalog-zones", &cz); + if (result == ISC_R_SUCCESS) { + const cfg_listelt_t *e = + cfg_list_first(cfg_tuple_get(cz, "zone list")); + if (e != NULL) { + allow = true; + } + } + } + + if (!allow) { + dns_view_setnewzones(view, false, NULL, NULL, 0ULL); + return ISC_R_SUCCESS; + } + + nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); + *nzcfg = (ns_cfgctx_t){ 0 }; + + /* + * We attach the parser that was used for config as well + * as the one that will be used for added zones, to avoid + * a shutdown race later. + */ + isc_mem_attach(view->mctx, &nzcfg->mctx); + cfg_parser_attach(conf_parser, &nzcfg->conf_parser); + cfg_parser_attach(named_g_addparser, &nzcfg->add_parser); + cfg_aclconfctx_attach(actx, &nzcfg->actx); + + result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, + mapsize); + if (result != ISC_R_SUCCESS) { + cfg_aclconfctx_detach(&nzcfg->actx); + cfg_parser_destroy(&nzcfg->add_parser); + cfg_parser_destroy(&nzcfg->conf_parser); + isc_mem_putanddetach(&nzcfg->mctx, nzcfg, sizeof(*nzcfg)); + dns_view_setnewzones(view, false, NULL, NULL, 0ULL); + return result; + } + + cfg_obj_attach(config, &nzcfg->config); + if (vconfig != NULL) { + cfg_obj_attach(vconfig, &nzcfg->vconfig); + } + + result = load_nzf(view, nzcfg); + return result; +} + +static void +configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, + dns_view_t *view) { + const char *zname; + dns_fixedname_t fixorigin; + dns_name_t *origin; + isc_result_t result2; + dns_view_t *pview = NULL; + dns_zone_t *zone = NULL; + + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + origin = dns_fixedname_initname(&fixorigin); + + result2 = dns_name_fromstring(origin, zname, dns_rootname, 0, NULL); + if (result2 != ISC_R_SUCCESS) { + return; + } + + result2 = dns_viewlist_find(&named_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result2 != ISC_R_SUCCESS) { + return; + } + + result2 = dns_view_findzone(pview, origin, DNS_ZTFIND_EXACT, &zone); + if (result2 != ISC_R_SUCCESS) { + dns_view_detach(&pview); + return; + } + + if (result == ISC_R_SUCCESS) { + dns_zone_setviewcommit(zone); + } else { + dns_zone_setviewrevert(zone); + } + + dns_zone_detach(&zone); + dns_view_detach(&pview); +} + +#ifndef HAVE_LMDB + +static isc_result_t +configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + cfg_aclconfctx_t *actx) { + isc_result_t result; + ns_cfgctx_t *nzctx; + const cfg_obj_t *zonelist; + const cfg_listelt_t *element; + + nzctx = view->new_zone_config; + if (nzctx == NULL || nzctx->nzf_config == NULL) { + return ISC_R_SUCCESS; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading additional zones for view '%s'", view->name); + + zonelist = NULL; + cfg_map_get(nzctx->nzf_config, "zone", &zonelist); + + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = cfg_listelt_value(element); + CHECK(configure_zone(config, zconfig, vconfig, view, + &named_g_server->viewlist, + &named_g_server->kasplist, + &named_g_server->keystorelist, actx, true, + false, false, false)); + } + + result = ISC_R_SUCCESS; + +cleanup: + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig = cfg_listelt_value(element); + configure_zone_setviewcommit(result, zconfig, view); + } + + return result; +} + +#else /* HAVE_LMDB */ + +static isc_result_t +data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, + cfg_obj_t **zoneconfig) { + isc_result_t result; + const char *zone_name; + size_t zone_name_len; + const char *zone_config; + size_t zone_config_len; + cfg_obj_t *zoneconf = NULL; + char bufname[DNS_NAME_FORMATSIZE]; + + REQUIRE(view != NULL); + REQUIRE(key != NULL); + REQUIRE(data != NULL); + REQUIRE(text != NULL); + REQUIRE(zoneconfig != NULL && *zoneconfig == NULL); + + if (*text == NULL) { + isc_buffer_allocate(view->mctx, text, 256); + } else { + isc_buffer_clear(*text); + } + + zone_name = (const char *)key->mv_data; + zone_name_len = key->mv_size; + INSIST(zone_name != NULL && zone_name_len > 0); + + zone_config = (const char *)data->mv_data; + zone_config_len = data->mv_size; + INSIST(zone_config != NULL && zone_config_len > 0); + + /* zone zonename { config; }; */ + result = isc_buffer_reserve(*text, 6 + zone_name_len + 2 + + zone_config_len + 2); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + CHECK(putstr(text, "zone \"")); + CHECK(putmem(text, (const void *)zone_name, zone_name_len)); + CHECK(putstr(text, "\" ")); + CHECK(putmem(text, (const void *)zone_config, zone_config_len)); + CHECK(putstr(text, ";\n")); + + snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, + zone_name); + + cfg_parser_reset(named_g_addparser); + result = cfg_parse_buffer(named_g_addparser, *text, bufname, 0, + &cfg_type_addzoneconf, 0, &zoneconf); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "parsing config for zone '%.*s' in " + "NZD database '%s' failed", + (int)zone_name_len, zone_name, view->new_zone_db); + goto cleanup; + } + + *zoneconfig = zoneconf; + zoneconf = NULL; + result = ISC_R_SUCCESS; + +cleanup: + if (zoneconf != NULL) { + cfg_obj_destroy(named_g_addparser, &zoneconf); + } + + return result; +} + +/*% + * Prototype for a callback which can be used with for_all_newzone_cfgs(). + */ +typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, + cfg_obj_t *config, cfg_obj_t *vconfig, + dns_view_t *view, + cfg_aclconfctx_t *actx); + +/*% + * For each zone found in a NZD opened by the caller, create an object + * representing its configuration and invoke "callback" with the created + * object, "config", "vconfig", "mctx", "view" and "actx" as arguments (all + * these are non-global variables required to invoke configure_zone()). + * Immediately interrupt processing if an error is encountered while + * transforming NZD data into a zone configuration object or if "callback" + * returns an error. + * + * Caller must hold 'view->new_zone_lock'. + */ +static isc_result_t +for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, + cfg_obj_t *vconfig, dns_view_t *view, + cfg_aclconfctx_t *actx, MDB_txn *txn, MDB_dbi dbi) { + const cfg_obj_t *zconfig, *zlist; + isc_result_t result = ISC_R_SUCCESS; + cfg_obj_t *zconfigobj = NULL; + isc_buffer_t *text = NULL; + MDB_cursor *cursor = NULL; + MDB_val data, key; + int status; + + status = mdb_cursor_open(txn, dbi, &cursor); + if (status != MDB_SUCCESS) { + return ISC_R_FAILURE; + } + + for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); + status == MDB_SUCCESS; + status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) + { + /* + * Create a configuration object from data fetched from NZD. + */ + result = data_to_cfg(view, &key, &data, &text, &zconfigobj); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Extract zone configuration from configuration object. + */ + zlist = NULL; + result = cfg_map_get(zconfigobj, "zone", &zlist); + if (result != ISC_R_SUCCESS) { + break; + } else if (!cfg_obj_islist(zlist)) { + result = ISC_R_FAILURE; + break; + } + zconfig = cfg_listelt_value(cfg_list_first(zlist)); + + /* + * Invoke callback. + */ + result = callback(zconfig, config, vconfig, view, actx); + if (result != ISC_R_SUCCESS) { + break; + } + + /* + * Destroy the configuration object created in this iteration. + */ + cfg_obj_destroy(named_g_addparser, &zconfigobj); + } + + if (text != NULL) { + isc_buffer_free(&text); + } + if (zconfigobj != NULL) { + cfg_obj_destroy(named_g_addparser, &zconfigobj); + } + mdb_cursor_close(cursor); + + return result; +} + +/*% + * Attempt to configure a zone found in NZD and return the result. + */ +static isc_result_t +configure_newzone(const cfg_obj_t *zconfig, cfg_obj_t *config, + cfg_obj_t *vconfig, dns_view_t *view, + cfg_aclconfctx_t *actx) { + return configure_zone( + config, zconfig, vconfig, view, &named_g_server->viewlist, + &named_g_server->kasplist, &named_g_server->keystorelist, actx, + true, false, false, false); +} + +/*% + * Revert new view assignment for a zone found in NZD. + */ +static isc_result_t +configure_newzone_revert(const cfg_obj_t *zconfig, cfg_obj_t *config, + cfg_obj_t *vconfig, dns_view_t *view, + cfg_aclconfctx_t *actx) { + UNUSED(config); + UNUSED(vconfig); + UNUSED(actx); + + configure_zone_setviewcommit(ISC_R_FAILURE, zconfig, view); + + return ISC_R_SUCCESS; +} + +static isc_result_t +configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, + cfg_aclconfctx_t *actx) { + isc_result_t result; + MDB_txn *txn = NULL; + MDB_dbi dbi; + + if (view->new_zone_config == NULL) { + return ISC_R_SUCCESS; + } + + LOCK(&view->new_zone_lock); + + result = nzd_open(view, MDB_RDONLY, &txn, &dbi); + if (result != ISC_R_SUCCESS) { + UNLOCK(&view->new_zone_lock); + return ISC_R_SUCCESS; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading NZD configs from '%s' " + "for view '%s'", + view->new_zone_db, view->name); + + result = for_all_newzone_cfgs(configure_newzone, config, vconfig, view, + actx, txn, dbi); + if (result != ISC_R_SUCCESS) { + /* + * An error was encountered while attempting to configure zones + * found in NZD. As this error may have been caused by a + * configure_zone() failure, try restoring a sane configuration + * by reattaching all zones found in NZD to the old view. If + * this also fails, too bad, there is nothing more we can do in + * terms of trying to make things right. + */ + (void)for_all_newzone_cfgs(configure_newzone_revert, config, + vconfig, view, actx, txn, dbi); + } + + (void)nzd_close(&txn, false); + + UNLOCK(&view->new_zone_lock); + + return result; +} + +static isc_result_t +get_newzone_config(dns_view_t *view, const char *zonename, + cfg_obj_t **zoneconfig) { + isc_result_t result; + int status; + cfg_obj_t *zoneconf = NULL; + isc_buffer_t *text = NULL; + MDB_txn *txn = NULL; + MDB_dbi dbi; + MDB_val key, data; + char zname[DNS_NAME_FORMATSIZE]; + dns_fixedname_t fname; + dns_name_t *name; + isc_buffer_t b; + + INSIST(zoneconfig != NULL && *zoneconfig == NULL); + + LOCK(&view->new_zone_lock); + + CHECK(nzd_open(view, MDB_RDONLY, &txn, &dbi)); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading NZD config from '%s' " + "for zone '%s'", + view->new_zone_db, zonename); + + /* Normalize zone name */ + isc_buffer_constinit(&b, zonename, strlen(zonename)); + isc_buffer_add(&b, strlen(zonename)); + name = dns_fixedname_initname(&fname); + CHECK(dns_name_fromtext(name, &b, dns_rootname, DNS_NAME_DOWNCASE, + NULL)); + dns_name_format(name, zname, sizeof(zname)); + + key.mv_data = zname; + key.mv_size = strlen(zname); + + status = mdb_get(txn, dbi, &key, &data); + if (status != MDB_SUCCESS) { + CHECK(ISC_R_FAILURE); + } + + CHECK(data_to_cfg(view, &key, &data, &text, &zoneconf)); + + *zoneconfig = zoneconf; + zoneconf = NULL; + result = ISC_R_SUCCESS; + +cleanup: + (void)nzd_close(&txn, false); + + UNLOCK(&view->new_zone_lock); + + if (zoneconf != NULL) { + cfg_obj_destroy(named_g_addparser, &zoneconf); + } + if (text != NULL) { + isc_buffer_free(&text); + } + + return result; +} + +#endif /* HAVE_LMDB */ + +static isc_result_t +load_configuration(const char *filename, named_server_t *server, + bool first_time) { + cfg_obj_t *config = NULL, *bindkeys = NULL; + cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL; + const cfg_listelt_t *element; + const cfg_obj_t *builtin_views; + const cfg_obj_t *maps[3]; + const cfg_obj_t *obj; + const cfg_obj_t *options; + const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; + const cfg_obj_t *kasps; + const cfg_obj_t *keystores; + dns_kasp_t *kasp = NULL; + dns_kasp_t *kasp_next = NULL; + dns_kasp_t *default_kasp = NULL; + dns_kasplist_t tmpkasplist, kasplist; + dns_keystore_t *keystore = NULL; + dns_keystore_t *keystore_next = NULL; + dns_keystorelist_t tmpkeystorelist, keystorelist; + const cfg_obj_t *views = NULL; + dns_view_t *view_next = NULL; + dns_viewlist_t tmpviewlist; + dns_viewlist_t viewlist, builtin_viewlist; + in_port_t listen_port, udpport_low, udpport_high; + int i, backlog; + isc_interval_t interval; + isc_logconfig_t *logc = NULL; + isc_portset_t *v4portset = NULL; + isc_portset_t *v6portset = NULL; + isc_result_t result; + uint32_t heartbeat_interval; + uint32_t interface_interval; + uint32_t udpsize; + uint32_t transfer_message_size; + uint32_t recv_tcp_buffer_size; + uint32_t send_tcp_buffer_size; + uint32_t recv_udp_buffer_size; + uint32_t send_udp_buffer_size; + named_cache_t *nsc = NULL; + named_cachelist_t cachelist, tmpcachelist; + ns_altsecret_t *altsecret; + ns_altsecretlist_t altsecrets, tmpaltsecrets; + uint32_t softquota = 0; + uint32_t max; + uint64_t initial, idle, keepalive, advertised; + bool loadbalancesockets; + bool exclusive = true; + dns_aclenv_t *env = + ns_interfacemgr_getaclenv(named_g_server->interfacemgr); + + /* + * Require the reconfiguration to happen always on the main loop + */ + REQUIRE(isc_loop() == named_g_mainloop); + + ISC_LIST_INIT(kasplist); + ISC_LIST_INIT(keystorelist); + ISC_LIST_INIT(viewlist); + ISC_LIST_INIT(builtin_viewlist); + ISC_LIST_INIT(cachelist); + ISC_LIST_INIT(altsecrets); + + /* Ensure exclusive access to configuration data. */ + isc_loopmgr_pause(named_g_loopmgr); + + /* Create the ACL configuration context */ + if (named_g_aclconfctx != NULL) { + cfg_aclconfctx_detach(&named_g_aclconfctx); + } + result = cfg_aclconfctx_create(named_g_mctx, &named_g_aclconfctx); + if (result != ISC_R_SUCCESS) { + goto cleanup_exclusive; + } + + /* + * Shut down all dyndb instances. + */ + dns_dyndb_cleanup(false); + + /* + * Parse the global default pseudo-config file. + */ + if (first_time) { + result = named_config_parsedefaults(named_g_parser, + &named_g_config); + if (result != ISC_R_SUCCESS) { + named_main_earlyfatal("unable to load " + "internal defaults: %s", + isc_result_totext(result)); + } + RUNTIME_CHECK(cfg_map_get(named_g_config, "options", + &named_g_defaults) == ISC_R_SUCCESS); + } + + /* + * Log the current working directory. + */ + if (first_time) { + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == cwd) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "the initial working directory is '%s'", + cwd); + } + } + + /* + * Parse the configuration file using the new config code. + */ + config = NULL; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "loading configuration from '%s'", filename); + result = cfg_parser_create(named_g_mctx, named_g_lctx, &conf_parser); + if (result != ISC_R_SUCCESS) { + goto cleanup_exclusive; + } + + cfg_parser_setcallback(conf_parser, directory_callback, NULL); + result = cfg_parse_file(conf_parser, filename, &cfg_type_namedconf, + &config); + if (result != ISC_R_SUCCESS) { + goto cleanup_conf_parser; + } + + /* + * Check the validity of the configuration. + * + * (Ignore plugin parameters for now; they will be + * checked later when the modules are actually loaded and + * registered.) + */ + result = isccfg_check_namedconf(config, BIND_CHECK_ALGORITHMS, + named_g_lctx, named_g_mctx); + if (result != ISC_R_SUCCESS) { + goto cleanup_config; + } + + /* Let's recreate the TLS context cache */ + if (server->tlsctx_server_cache != NULL) { + isc_tlsctx_cache_detach(&server->tlsctx_server_cache); + } + + isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_server_cache); + + if (server->tlsctx_client_cache != NULL) { + isc_tlsctx_cache_detach(&server->tlsctx_client_cache); + } + + isc_tlsctx_cache_create(named_g_mctx, &server->tlsctx_client_cache); + + dns_zonemgr_set_tlsctx_cache(server->zonemgr, + server->tlsctx_client_cache); + + /* + * Fill in the maps array, used for resolving defaults. + */ + i = 0; + options = NULL; + result = cfg_map_get(config, "options", &options); + if (result == ISC_R_SUCCESS) { + maps[i++] = options; + } + maps[i++] = named_g_defaults; + maps[i] = NULL; + +#if HAVE_LIBNGHTTP2 + obj = NULL; + result = named_config_get(maps, "http-port", &obj); + INSIST(result == ISC_R_SUCCESS); + named_g_httpport = (in_port_t)cfg_obj_asuint32(obj); + + obj = NULL; + result = named_config_get(maps, "https-port", &obj); + INSIST(result == ISC_R_SUCCESS); + named_g_httpsport = (in_port_t)cfg_obj_asuint32(obj); + + obj = NULL; + result = named_config_get(maps, "http-listener-clients", &obj); + INSIST(result == ISC_R_SUCCESS); + named_g_http_listener_clients = cfg_obj_asuint32(obj); + + obj = NULL; + result = named_config_get(maps, "http-streams-per-connection", &obj); + INSIST(result == ISC_R_SUCCESS); + named_g_http_streams_per_conn = cfg_obj_asuint32(obj); +#endif + + /* + * If "dnssec-validation auto" is turned on, the root key + * will be used as a default trust anchor. The root key + * is built in, but if bindkeys-file is set, then it will + * be overridden with the key in that file. + */ + obj = NULL; + (void)named_config_get(maps, "bindkeys-file", &obj); + if (obj != NULL) { + setstring(server, &server->bindkeysfile, cfg_obj_asstring(obj)); + INSIST(server->bindkeysfile != NULL); + if (access(server->bindkeysfile, R_OK) != 0) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "unable to open '%s'; using built-in " + "keys instead", + server->bindkeysfile); + } else { + result = cfg_parser_create(named_g_mctx, named_g_lctx, + &bindkeys_parser); + if (result != ISC_R_SUCCESS) { + goto cleanup_config; + } + + result = cfg_parse_file(bindkeys_parser, + server->bindkeysfile, + &cfg_type_bindkeys, &bindkeys); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "unable to parse '%s' " + "error '%s'; using " + "built-in keys instead", + server->bindkeysfile, + isc_result_totext(result)); + } + } + } else { + setstring(server, &server->bindkeysfile, NULL); + } + +#if defined(HAVE_GEOIP2) + /* + * Release any previously opened GeoIP2 databases. + */ + named_geoip_unload(); + + /* + * Initialize GeoIP databases from the configured location. + * This should happen before configuring any ACLs, so that we + * know what databases are available and can reject any GeoIP + * ACLs that can't work. + */ + obj = NULL; + result = named_config_get(maps, "geoip-directory", &obj); + INSIST(result == ISC_R_SUCCESS); + if (cfg_obj_isstring(obj)) { + char *dir = UNCONST(cfg_obj_asstring(obj)); + named_geoip_load(dir); + } + named_g_aclconfctx->geoip = named_g_geoip; +#endif /* HAVE_GEOIP2 */ + + /* + * Configure various server options. + */ + configure_server_quota(maps, "transfers-out", + &server->sctx->xfroutquota); + configure_server_quota(maps, "tcp-clients", &server->sctx->tcpquota); + configure_server_quota(maps, "recursive-clients", + &server->sctx->recursionquota); + configure_server_quota(maps, "update-quota", &server->sctx->updquota); + configure_server_quota(maps, "sig0checks-quota", + &server->sctx->sig0checksquota); + + max = isc_quota_getmax(&server->sctx->recursionquota); + if (max > 1000) { + unsigned int margin = ISC_MAX(100, named_g_cpus + 1); + if (margin + 100 > max) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "'recursive-clients %d' too low when " + "running with %d worker threads", + max, named_g_cpus); + result = ISC_R_RANGE; + + goto cleanup_bindkeys_parser; + } + softquota = max - margin; + } else { + softquota = (max * 90) / 100; + } + isc_quota_soft(&server->sctx->recursionquota, softquota); + + obj = NULL; + result = named_config_get(maps, "sig0checks-quota-exempt", &obj); + if (result == ISC_R_SUCCESS) { + result = cfg_acl_fromconfig( + obj, config, named_g_lctx, named_g_aclconfctx, + named_g_mctx, 0, &server->sctx->sig0checksquota_exempt); + INSIST(result == ISC_R_SUCCESS); + } + + /* + * Set "blackhole". Only legal at options level; there is + * no default. + */ + result = configure_view_acl(NULL, config, NULL, "blackhole", NULL, + named_g_aclconfctx, named_g_mctx, + &server->sctx->blackholeacl); + if (result != ISC_R_SUCCESS) { + goto cleanup_bindkeys_parser; + } + + if (server->sctx->blackholeacl != NULL) { + dns_dispatchmgr_setblackhole(named_g_dispatchmgr, + server->sctx->blackholeacl); + } + + obj = NULL; + result = named_config_get(maps, "match-mapped-addresses", &obj); + INSIST(result == ISC_R_SUCCESS); + env->match_mapped = cfg_obj_asboolean(obj); + + /* + * Configure the network manager + */ + obj = NULL; + result = named_config_get(maps, "tcp-initial-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + initial = cfg_obj_asuint32(obj) * 100; + if (initial > MAX_INITIAL_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-initial-timeout value is out of range: " + "lowering to %" PRIu32, + MAX_INITIAL_TIMEOUT / 100); + initial = MAX_INITIAL_TIMEOUT; + } else if (initial < MIN_INITIAL_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-initial-timeout value is out of range: " + "raising to %" PRIu32, + MIN_INITIAL_TIMEOUT / 100); + initial = MIN_INITIAL_TIMEOUT; + } + + obj = NULL; + result = named_config_get(maps, "tcp-idle-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + idle = cfg_obj_asuint32(obj) * 100; + if (idle > MAX_IDLE_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-idle-timeout value is out of range: " + "lowering to %" PRIu32, + MAX_IDLE_TIMEOUT / 100); + idle = MAX_IDLE_TIMEOUT; + } else if (idle < MIN_IDLE_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-idle-timeout value is out of range: " + "raising to %" PRIu32, + MIN_IDLE_TIMEOUT / 100); + idle = MIN_IDLE_TIMEOUT; + } + + obj = NULL; + result = named_config_get(maps, "tcp-keepalive-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + keepalive = cfg_obj_asuint32(obj) * 100; + if (keepalive > MAX_KEEPALIVE_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-keepalive-timeout value is out of range: " + "lowering to %" PRIu32, + MAX_KEEPALIVE_TIMEOUT / 100); + keepalive = MAX_KEEPALIVE_TIMEOUT; + } else if (keepalive < MIN_KEEPALIVE_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-keepalive-timeout value is out of range: " + "raising to %" PRIu32, + MIN_KEEPALIVE_TIMEOUT / 100); + keepalive = MIN_KEEPALIVE_TIMEOUT; + } + + obj = NULL; + result = named_config_get(maps, "tcp-advertised-timeout", &obj); + INSIST(result == ISC_R_SUCCESS); + advertised = cfg_obj_asuint32(obj) * 100; + if (advertised > MAX_ADVERTISED_TIMEOUT) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "tcp-advertized-timeout value is out of range: " + "lowering to %" PRIu32, + MAX_ADVERTISED_TIMEOUT / 100); + advertised = MAX_ADVERTISED_TIMEOUT; + } + + isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, + advertised); + +#define CAP_IF_NOT_ZERO(v, min, max) \ + if (v > 0 && v < min) { \ + v = min; \ + } else if (v > max) { \ + v = max; \ + } + + /* Set the kernel send and receive buffer sizes */ + obj = NULL; + result = named_config_get(maps, "tcp-receive-buffer", &obj); + INSIST(result == ISC_R_SUCCESS); + recv_tcp_buffer_size = cfg_obj_asuint32(obj); + CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX); + + obj = NULL; + result = named_config_get(maps, "tcp-send-buffer", &obj); + INSIST(result == ISC_R_SUCCESS); + send_tcp_buffer_size = cfg_obj_asuint32(obj); + CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX); + + obj = NULL; + result = named_config_get(maps, "udp-receive-buffer", &obj); + INSIST(result == ISC_R_SUCCESS); + recv_udp_buffer_size = cfg_obj_asuint32(obj); + CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX); + + obj = NULL; + result = named_config_get(maps, "udp-send-buffer", &obj); + INSIST(result == ISC_R_SUCCESS); + send_udp_buffer_size = cfg_obj_asuint32(obj); + CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX); + + isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size, + send_tcp_buffer_size, recv_udp_buffer_size, + send_udp_buffer_size); + +#undef CAP_IF_NOT_ZERO + + /* + * Configure sets of UDP query source ports. + */ + result = isc_portset_create(named_g_mctx, &v4portset); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "creating UDP/IPv4 port set: %s", + isc_result_totext(result)); + goto cleanup_bindkeys_parser; + } + result = isc_portset_create(named_g_mctx, &v6portset); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "creating UDP/IPv6 port set: %s", + isc_result_totext(result)); + goto cleanup_v4portset; + } + + usev4ports = NULL; + usev6ports = NULL; + avoidv4ports = NULL; + avoidv6ports = NULL; + + (void)named_config_get(maps, "use-v4-udp-ports", &usev4ports); + if (usev4ports != NULL) { + portset_fromconf(v4portset, usev4ports, true); + } else { + result = isc_net_getudpportrange(AF_INET, &udpport_low, + &udpport_high); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "get the default UDP/IPv4 port range: %s", + isc_result_totext(result)); + goto cleanup_v6portset; + } + + if (udpport_low == udpport_high) { + isc_portset_add(v4portset, udpport_low); + } else { + isc_portset_addrange(v4portset, udpport_low, + udpport_high); + } + if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE4)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "using default UDP/IPv4 port range: " + "[%d, %d]", + udpport_low, udpport_high); + } + } + (void)named_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports); + if (avoidv4ports != NULL) { + portset_fromconf(v4portset, avoidv4ports, false); + } + + (void)named_config_get(maps, "use-v6-udp-ports", &usev6ports); + if (usev6ports != NULL) { + portset_fromconf(v6portset, usev6ports, true); + } else { + result = isc_net_getudpportrange(AF_INET6, &udpport_low, + &udpport_high); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "get the default UDP/IPv6 port range: %s", + isc_result_totext(result)); + goto cleanup_v6portset; + } + if (udpport_low == udpport_high) { + isc_portset_add(v6portset, udpport_low); + } else { + isc_portset_addrange(v6portset, udpport_low, + udpport_high); + } + if (!ns_server_getoption(server->sctx, NS_SERVER_DISABLE6)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "using default UDP/IPv6 port range: " + "[%d, %d]", + udpport_low, udpport_high); + } + } + (void)named_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports); + if (avoidv6ports != NULL) { + portset_fromconf(v6portset, avoidv6ports, false); + } + + dns_dispatchmgr_setavailports(named_g_dispatchmgr, v4portset, + v6portset); + + /* + * Set the EDNS UDP size when we don't match a view. + */ + obj = NULL; + result = named_config_get(maps, "edns-udp-size", &obj); + INSIST(result == ISC_R_SUCCESS); + udpsize = cfg_obj_asuint32(obj); + if (udpsize < 512) { + udpsize = 512; + } + if (udpsize > 4096) { + udpsize = 4096; + } + server->sctx->udpsize = (uint16_t)udpsize; + + /* Set the transfer message size for TCP */ + obj = NULL; + result = named_config_get(maps, "transfer-message-size", &obj); + INSIST(result == ISC_R_SUCCESS); + transfer_message_size = cfg_obj_asuint32(obj); + if (transfer_message_size < 512) { + transfer_message_size = 512; + } else if (transfer_message_size > 65535) { + transfer_message_size = 65535; + } + server->sctx->transfer_tcp_message_size = + (uint16_t)transfer_message_size; + + /* + * Configure the zone manager. + */ + obj = NULL; + result = named_config_get(maps, "transfers-in", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "transfers-per-ns", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "notify-rate", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "startup-notify-rate", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_setstartupnotifyrate(server->zonemgr, + cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "serial-query-rate", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); + + /* + * Determine which port to use for listening for incoming connections. + */ + if (named_g_port != 0) { + listen_port = named_g_port; + } else { + result = named_config_getport(config, "port", &listen_port); + if (result != ISC_R_SUCCESS) { + goto cleanup_v6portset; + } + } + + /* + * Find the listen queue depth. + */ + obj = NULL; + result = named_config_get(maps, "tcp-listen-queue", &obj); + INSIST(result == ISC_R_SUCCESS); + backlog = cfg_obj_asuint32(obj); + if ((backlog > 0) && (backlog < 10)) { + backlog = 10; + } + ns_interfacemgr_setbacklog(server->interfacemgr, backlog); + + obj = NULL; + result = named_config_get(maps, "reuseport", &obj); + INSIST(result == ISC_R_SUCCESS); + loadbalancesockets = cfg_obj_asboolean(obj); +#if HAVE_SO_REUSEPORT_LB + if (first_time) { + isc_nm_setloadbalancesockets(named_g_netmgr, + cfg_obj_asboolean(obj)); + } else if (loadbalancesockets != + isc_nm_getloadbalancesockets(named_g_netmgr)) + { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "changing reuseport value requires server restart"); + } +#else + if (loadbalancesockets) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING, + "reuseport has no effect on this system"); + } +#endif + + /* + * Configure the interface manager according to the "listen-on" + * statement. + */ + { + const cfg_obj_t *clistenon = NULL; + ns_listenlist_t *listenon = NULL; + + /* + * Even though listen-on is present in the default + * configuration, this way is easier. + */ + if (options != NULL) { + (void)cfg_map_get(options, "listen-on", &clistenon); + } + if (clistenon != NULL) { + result = listenlist_fromconfig( + clistenon, config, named_g_aclconfctx, + named_g_mctx, AF_INET, + server->tlsctx_server_cache, &listenon); + } else { + /* + * Not specified, use default. + */ + result = ns_listenlist_default(named_g_mctx, + listen_port, true, + AF_INET, &listenon); + } + if (result != ISC_R_SUCCESS) { + goto cleanup_v6portset; + } + + if (listenon != NULL) { + ns_interfacemgr_setlistenon4(server->interfacemgr, + listenon); + ns_listenlist_detach(&listenon); + } + } + + /* + * Ditto for IPv6. + */ + { + const cfg_obj_t *clistenon = NULL; + ns_listenlist_t *listenon = NULL; + + if (options != NULL) { + (void)cfg_map_get(options, "listen-on-v6", &clistenon); + } + if (clistenon != NULL) { + result = listenlist_fromconfig( + clistenon, config, named_g_aclconfctx, + named_g_mctx, AF_INET6, + server->tlsctx_server_cache, &listenon); + } else { + /* + * Not specified, use default. + */ + result = ns_listenlist_default(named_g_mctx, + listen_port, true, + AF_INET6, &listenon); + } + if (result != ISC_R_SUCCESS) { + goto cleanup_v6portset; + } + if (listenon != NULL) { + ns_interfacemgr_setlistenon6(server->interfacemgr, + listenon); + ns_listenlist_detach(&listenon); + } + } + + if (first_time) { + /* + * Rescan the interface list to pick up changes in the + * listen-on option. This requires the loopmgr to be + * temporarily resumed. + */ + isc_loopmgr_resume(named_g_loopmgr); + result = ns_interfacemgr_scan(server->interfacemgr, true, true); + isc_loopmgr_pause(named_g_loopmgr); + + /* + * Check that named is able to TCP listen on at least one + * interface. Otherwise, another named process could be running + * and we should fail. + */ + if (result == ISC_R_ADDRINUSE) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "unable to listen on any configured " + "interfaces"); + result = ISC_R_FAILURE; + goto cleanup_v6portset; + } + } + + /* + * Arrange for further interface scanning to occur periodically + * as specified by the "interface-interval" option. + */ + obj = NULL; + result = named_config_get(maps, "interface-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + interface_interval = cfg_obj_asduration(obj); + server->interface_interval = interface_interval; + + /* + * Enable automatic interface scans. + */ + obj = NULL; + result = named_config_get(maps, "automatic-interface-scan", &obj); + INSIST(result == ISC_R_SUCCESS); + server->sctx->interface_auto = cfg_obj_asboolean(obj); + + if (server->sctx->interface_auto) { + if (ns_interfacemgr_dynamic_updates_are_reliable() && + server->interface_interval != 0) + { + /* + * In some cases the user might expect a certain + * behaviour from the rescan timer, let's try to deduce + * that from the configuration options. + */ + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "Disabling periodic interface re-scans timer"); + server->interface_interval = 0; + } + + ns_interfacemgr_routeconnect(server->interfacemgr); + } else { + ns_interfacemgr_routedisconnect(server->interfacemgr); + } + + if (server->interface_interval == 0) { + isc_timer_stop(server->interface_timer); + } else { + isc_interval_set(&interval, interface_interval, 0); + isc_timer_start(server->interface_timer, isc_timertype_ticker, + &interval); + } + + /* + * Configure the dialup heartbeat timer. + */ + obj = NULL; + result = named_config_get(maps, "heartbeat-interval", &obj); + INSIST(result == ISC_R_SUCCESS); + heartbeat_interval = cfg_obj_asuint32(obj) * 60; + if (heartbeat_interval == 0) { + isc_timer_stop(server->heartbeat_timer); + } else if (server->heartbeat_interval != heartbeat_interval) { + isc_interval_set(&interval, heartbeat_interval, 0); + isc_timer_start(server->heartbeat_timer, isc_timertype_ticker, + &interval); + } + server->heartbeat_interval = heartbeat_interval; + + isc_interval_set(&interval, 1200, 0); + isc_timer_start(server->pps_timer, isc_timertype_ticker, &interval); + + isc_interval_set(&interval, named_g_tat_interval, 0); + isc_timer_start(server->tat_timer, isc_timertype_ticker, &interval); + + /* + * Write the PID file. + */ + obj = NULL; + if (named_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) { + if (cfg_obj_isvoid(obj)) { + named_os_writepidfile(NULL, first_time); + } else { + named_os_writepidfile(cfg_obj_asstring(obj), + first_time); + } + } else { + named_os_writepidfile(named_g_defaultpidfile, first_time); + } + + /* + * Configure the server-wide session key. This must be done before + * configure views because zone configuration may need to know + * session-keyname. + * + * Failure of session key generation isn't fatal at this time; if it + * turns out that a session key is really needed but doesn't exist, + * we'll treat it as a fatal error then. + */ + (void)configure_session_key(maps, server, named_g_mctx, first_time); + + /* + * Create the built-in key store ("key-directory"). + */ + result = cfg_keystore_fromconfig(NULL, named_g_mctx, named_g_lctx, + named_g_engine, &keystorelist, NULL); + if (result != ISC_R_SUCCESS) { + goto cleanup_keystorelist; + } + + /* + * Create the DNSSEC key stores. + */ + keystores = NULL; + (void)cfg_map_get(config, "key-store", &keystores); + for (element = cfg_list_first(keystores); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *kconfig = cfg_listelt_value(element); + keystore = NULL; + result = cfg_keystore_fromconfig(kconfig, named_g_mctx, + named_g_lctx, named_g_engine, + &keystorelist, NULL); + if (result != ISC_R_SUCCESS) { + goto cleanup_keystorelist; + } + } + + /* + * Create the built-in kasp policies ("default", "insecure"). + */ + kasps = NULL; + (void)cfg_map_get(named_g_config, "dnssec-policy", &kasps); + for (element = cfg_list_first(kasps); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *kconfig = cfg_listelt_value(element); + + kasp = NULL; + result = cfg_kasp_fromconfig(kconfig, default_kasp, true, + named_g_mctx, named_g_lctx, + &keystorelist, &kasplist, &kasp); + if (result != ISC_R_SUCCESS) { + goto cleanup_kasplist; + } + INSIST(kasp != NULL); + dns_kasp_freeze(kasp); + + /* Insist that the first built-in policy is the default one. */ + if (default_kasp == NULL) { + INSIST(strcmp(dns_kasp_getname(kasp), "default") == 0); + dns_kasp_attach(kasp, &default_kasp); + } + + dns_kasp_detach(&kasp); + } + INSIST(default_kasp != NULL); + + /* + * Create the DNSSEC key and signing policies (KASP). + */ + kasps = NULL; + (void)cfg_map_get(config, "dnssec-policy", &kasps); + for (element = cfg_list_first(kasps); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *kconfig = cfg_listelt_value(element); + kasp = NULL; + result = cfg_kasp_fromconfig(kconfig, default_kasp, true, + named_g_mctx, named_g_lctx, + &keystorelist, &kasplist, &kasp); + if (result != ISC_R_SUCCESS) { + goto cleanup_kasplist; + } + INSIST(kasp != NULL); + dns_kasp_freeze(kasp); + dns_kasp_detach(&kasp); + } + dns_kasp_detach(&default_kasp); + + /* + * Save keystore list and kasp list. + */ + tmpkeystorelist = server->keystorelist; + server->keystorelist = keystorelist; + keystorelist = tmpkeystorelist; + + tmpkasplist = server->kasplist; + server->kasplist = kasplist; + kasplist = tmpkasplist; + +#ifdef USE_DNSRPS + /* + * Find the path to the DNSRPS implementation library. + */ + obj = NULL; + if (named_config_get(maps, "dnsrps-library", &obj) == ISC_R_SUCCESS) { + if (server->dnsrpslib != NULL) { + dns_dnsrps_server_destroy(); + isc_mem_free(server->mctx, server->dnsrpslib); + server->dnsrpslib = NULL; + } + setstring(server, &server->dnsrpslib, cfg_obj_asstring(obj)); + result = dns_dnsrps_server_create(server->dnsrpslib); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "initializing DNSRPS RPZ provider '%s': %s", + server->dnsrpslib, isc_result_totext(result)); + /* + * It's okay if librpz isn't available. We'll complain + * later if it turns out to be needed for a view with + * "dnsrps-enable yes". + */ + if (result == ISC_R_FILENOTFOUND) { + result = ISC_R_SUCCESS; + } + CHECKFATAL(result, "initializing RPZ service interface"); + } +#endif /* ifdef USE_DNSRPS */ + + /* + * Configure the views. + */ + views = NULL; + (void)cfg_map_get(config, "view", &views); + + /* + * Create the views. + */ + for (element = cfg_list_first(views); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *vconfig = cfg_listelt_value(element); + dns_view_t *view = NULL; + + result = create_view(vconfig, &viewlist, &view); + if (result != ISC_R_SUCCESS) { + goto cleanup_viewlist; + } + INSIST(view != NULL); + + result = setup_newzones(view, config, vconfig, conf_parser, + named_g_aclconfctx); + dns_view_detach(&view); + + if (result != ISC_R_SUCCESS) { + goto cleanup_viewlist; + } + } + + /* + * If there were no explicit views then we do the default + * view here. + */ + if (views == NULL) { + dns_view_t *view = NULL; + + result = create_view(NULL, &viewlist, &view); + if (result != ISC_R_SUCCESS) { + goto cleanup_viewlist; + } + INSIST(view != NULL); + + result = setup_newzones(view, config, NULL, conf_parser, + named_g_aclconfctx); + + dns_view_detach(&view); + if (result != ISC_R_SUCCESS) { + goto cleanup_viewlist; + } + } + + /* + * Configure and freeze all explicit views. Explicit + * views that have zones were already created at parsing + * time, but views with no zones must be created here. + */ + for (element = cfg_list_first(views); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *vconfig = cfg_listelt_value(element); + dns_view_t *view = NULL; + + view = NULL; + result = find_view(vconfig, &viewlist, &view); + if (result != ISC_R_SUCCESS) { + goto cleanup_cachelist; + } + + result = configure_view(view, &viewlist, config, vconfig, + &cachelist, &server->cachelist, + &server->kasplist, + &server->keystorelist, bindkeys, + named_g_mctx, named_g_aclconfctx, true); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + goto cleanup_cachelist; + } + dns_view_freeze(view); + dns_view_detach(&view); + } + + /* + * Make sure we have a default view if and only if there + * were no explicit views. + */ + if (views == NULL) { + dns_view_t *view = NULL; + result = find_view(NULL, &viewlist, &view); + if (result != ISC_R_SUCCESS) { + goto cleanup_cachelist; + } + result = configure_view(view, &viewlist, config, NULL, + &cachelist, &server->cachelist, + &server->kasplist, + &server->keystorelist, bindkeys, + named_g_mctx, named_g_aclconfctx, true); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + goto cleanup_cachelist; + } + dns_view_freeze(view); + dns_view_detach(&view); + } + + /* + * Create (or recreate) the built-in views. + */ + builtin_views = NULL; + RUNTIME_CHECK(cfg_map_get(named_g_config, "view", &builtin_views) == + ISC_R_SUCCESS); + for (element = cfg_list_first(builtin_views); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *vconfig = cfg_listelt_value(element); + dns_view_t *view = NULL; + + result = create_view(vconfig, &builtin_viewlist, &view); + if (result != ISC_R_SUCCESS) { + goto cleanup_cachelist; + } + + result = configure_view( + view, &viewlist, config, vconfig, &cachelist, + &server->cachelist, &server->kasplist, + &server->keystorelist, bindkeys, named_g_mctx, + named_g_aclconfctx, false); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + goto cleanup_cachelist; + } + dns_view_freeze(view); + dns_view_detach(&view); + } + + /* Now combine the two viewlists into one */ + ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); + + /* + * Commit any dns_zone_setview() calls on all zones in the new + * view. + */ + for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + dns_view_setviewcommit(view); + } + + /* Swap our new view list with the production one. */ + tmpviewlist = server->viewlist; + server->viewlist = viewlist; + viewlist = tmpviewlist; + + /* Make the view list available to each of the views */ + for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + view->viewlist = &server->viewlist; + } + + /* Swap our new cache list with the production one. */ + tmpcachelist = server->cachelist; + server->cachelist = cachelist; + cachelist = tmpcachelist; + + /* Load the TKEY information from the configuration. */ + if (options != NULL) { + dns_tkeyctx_t *tkeyctx = NULL; + + result = named_tkeyctx_fromconfig(options, named_g_mctx, + &tkeyctx); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "configuring TKEY: %s", + isc_result_totext(result)); + goto cleanup_cachelist; + } + if (server->sctx->tkeyctx != NULL) { + dns_tkeyctx_destroy(&server->sctx->tkeyctx); + } + server->sctx->tkeyctx = tkeyctx; + } + +#ifdef HAVE_LMDB + /* + * If we're using LMDB, we may have created newzones databases + * as root, making it impossible to reopen them later after + * switching to a new userid. We close them now, and reopen + * after relinquishing privileges them. + */ + if (first_time) { + for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); + view != NULL; view = ISC_LIST_NEXT(view, link)) + { + nzd_env_close(view); + } + } +#endif /* HAVE_LMDB */ + + /* + * Switch to the effective UID for setting up files. + * Later, after configuring all the listening ports, + * we'll relinquish root privileges permanently. + */ + if (first_time) { + named_os_changeuser(false); + } + + /* + * Check that the working directory is writable. + */ + if (!isc_file_isdirwritable(".")) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "the working directory is not writable"); + result = ISC_R_NOPERM; + goto cleanup_cachelist; + } + +#ifdef HAVE_LMDB + /* + * Reopen NZD databases. + */ + if (first_time) { + for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); + view != NULL; view = ISC_LIST_NEXT(view, link)) + { + nzd_env_reopen(view); + } + } +#endif /* HAVE_LMDB */ + + /* + * Configure the logging system. + * + * Do this after changing UID to make sure that any log + * files specified in named.conf get created by the + * unprivileged user, not root. + */ + if (named_g_logstderr) { + const cfg_obj_t *logobj = NULL; + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "not using config file logging " + "statement for logging due to " + "-g option"); + + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) { + result = named_logconfig(NULL, logobj); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "checking logging configuration " + "failed: %s", + isc_result_totext(result)); + goto cleanup_cachelist; + } + } + } else { + const cfg_obj_t *logobj = NULL; + + isc_logconfig_create(named_g_lctx, &logc); + + logobj = NULL; + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) { + result = named_logconfig(logc, logobj); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "configuring logging: %s", + isc_result_totext(result)); + goto cleanup_logc; + } + } else { + named_log_setdefaultchannels(logc); + named_log_setdefaultsslkeylogfile(logc); + result = named_log_setunmatchedcategory(logc); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "setting up default 'category " + "unmatched': %s", + isc_result_totext(result)); + goto cleanup_logc; + } + result = named_log_setdefaultcategory(logc); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "setting up default 'category " + "default': %s", + isc_result_totext(result)); + goto cleanup_logc; + } + } + + isc_logconfig_use(named_g_lctx, logc); + logc = NULL; + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "now using logging configuration from " + "config file"); + } + + /* + * Set the default value of the query logging flag depending + * whether a "queries" category has been defined. This is + * a disgusting hack, but we need to do this for BIND 8 + * compatibility. + */ + if (first_time) { + const cfg_obj_t *logobj = NULL; + const cfg_obj_t *categories = NULL; + + obj = NULL; + if (named_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { + ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, + cfg_obj_asboolean(obj)); + } else { + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) { + (void)cfg_map_get(logobj, "category", + &categories); + } + if (categories != NULL) { + for (element = cfg_list_first(categories); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *catobj; + const char *str; + + obj = cfg_listelt_value(element); + catobj = cfg_tuple_get(obj, "name"); + str = cfg_obj_asstring(catobj); + if (strcasecmp(str, "queries") == 0) { + ns_server_setoption( + server->sctx, + NS_SERVER_LOGQUERIES, + true); + } + } + } + } + obj = NULL; + result = named_config_get(maps, "responselog", &obj); + if (result == ISC_R_SUCCESS) { + ns_server_setoption(server->sctx, + NS_SERVER_LOGRESPONSES, + cfg_obj_asboolean(obj)); + } + } + + obj = NULL; + if (options != NULL && + cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS) + { + named_g_memstatistics = cfg_obj_asboolean(obj); + } else { + named_g_memstatistics = + ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0); + } + + obj = NULL; + if (named_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS) + { + named_main_setmemstats(cfg_obj_asstring(obj)); + } else if (named_g_memstatistics) { + named_main_setmemstats("named.memstats"); + } else { + named_main_setmemstats(NULL); + } + + obj = NULL; + result = named_config_get(maps, "statistics-file", &obj); + INSIST(result == ISC_R_SUCCESS); + setstring(server, &server->statsfile, cfg_obj_asstring(obj)); + + obj = NULL; + result = named_config_get(maps, "dump-file", &obj); + INSIST(result == ISC_R_SUCCESS); + setstring(server, &server->dumpfile, cfg_obj_asstring(obj)); + + obj = NULL; + result = named_config_get(maps, "secroots-file", &obj); + INSIST(result == ISC_R_SUCCESS); + setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)); + + obj = NULL; + result = named_config_get(maps, "recursing-file", &obj); + INSIST(result == ISC_R_SUCCESS); + setstring(server, &server->recfile, cfg_obj_asstring(obj)); + + obj = NULL; + result = named_config_get(maps, "version", &obj); + if (result == ISC_R_SUCCESS) { + setoptstring(server, &server->version, obj); + server->version_set = true; + } else { + server->version_set = false; + } + + obj = NULL; + result = named_config_get(maps, "hostname", &obj); + if (result == ISC_R_SUCCESS) { + setoptstring(server, &server->hostname, obj); + server->hostname_set = true; + } else { + server->hostname_set = false; + } + + obj = NULL; + result = named_config_get(maps, "server-id", &obj); + server->sctx->usehostname = false; + if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { + /* The parser translates "hostname" to true */ + server->sctx->usehostname = true; + result = ns_server_setserverid(server->sctx, NULL); + } else if (result == ISC_R_SUCCESS && !cfg_obj_isvoid(obj)) { + /* Found a quoted string */ + result = ns_server_setserverid(server->sctx, + cfg_obj_asstring(obj)); + } else { + result = ns_server_setserverid(server->sctx, NULL); + } + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + obj = NULL; + result = named_config_get(maps, "flush-zones-on-shutdown", &obj); + if (result == ISC_R_SUCCESS) { + server->flushonshutdown = cfg_obj_asboolean(obj); + } else { + server->flushonshutdown = false; + } + + obj = NULL; + result = named_config_get(maps, "answer-cookie", &obj); + INSIST(result == ISC_R_SUCCESS); + server->sctx->answercookie = cfg_obj_asboolean(obj); + + obj = NULL; + result = named_config_get(maps, "cookie-algorithm", &obj); + INSIST(result == ISC_R_SUCCESS); + if (strcasecmp(cfg_obj_asstring(obj), "siphash24") == 0) { + server->sctx->cookiealg = ns_cookiealg_siphash24; + } else { + UNREACHABLE(); + } + + obj = NULL; + result = named_config_get(maps, "cookie-secret", &obj); + if (result == ISC_R_SUCCESS) { + const char *str; + bool first = true; + isc_buffer_t b; + unsigned int usedlength; + unsigned int expectedlength; + + for (element = cfg_list_first(obj); element != NULL; + element = cfg_list_next(element)) + { + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + + if (first) { + memset(server->sctx->secret, 0, + sizeof(server->sctx->secret)); + isc_buffer_init(&b, server->sctx->secret, + sizeof(server->sctx->secret)); + result = isc_hex_decodestring(str, &b); + if (result != ISC_R_SUCCESS && + result != ISC_R_NOSPACE) + { + goto cleanup_altsecrets; + } + first = false; + } else { + altsecret = isc_mem_get(server->sctx->mctx, + sizeof(*altsecret)); + isc_buffer_init(&b, altsecret->secret, + sizeof(altsecret->secret)); + result = isc_hex_decodestring(str, &b); + if (result != ISC_R_SUCCESS && + result != ISC_R_NOSPACE) + { + isc_mem_put(server->sctx->mctx, + altsecret, + sizeof(*altsecret)); + goto cleanup_altsecrets; + } + ISC_LIST_INITANDAPPEND(altsecrets, altsecret, + link); + } + + usedlength = isc_buffer_usedlength(&b); + switch (server->sctx->cookiealg) { + case ns_cookiealg_siphash24: + expectedlength = ISC_SIPHASH24_KEY_LENGTH; + if (usedlength != expectedlength) { + result = ISC_R_RANGE; + isc_log_write( + named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_ERROR, + "SipHash-2-4 cookie-secret " + "must be 128 bits: %s", + isc_result_totext(result)); + goto cleanup_altsecrets; + } + break; + } + } + } else { + isc_nonce_buf(server->sctx->secret, + sizeof(server->sctx->secret)); + } + + /* + * Swap altsecrets lists. + */ + tmpaltsecrets = server->sctx->altsecrets; + server->sctx->altsecrets = altsecrets; + altsecrets = tmpaltsecrets; + + (void)named_server_loadnta(server); + +#ifdef USE_DNSRPS + /* + * Start and connect to the DNS Response Policy Service + * daemon, dnsrpzd, for each view that uses DNSRPS. + */ + for (dns_view_t *view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + result = dns_dnsrps_connect(view->rpzs); + if (result != ISC_R_SUCCESS) { + view = NULL; + goto cleanup_altsecrets; + } + } +#endif /* ifdef USE_DNSRPS */ + + /* + * Record the time of most recent configuration + */ + named_g_configtime = isc_time_now(); + + isc_loopmgr_resume(named_g_loopmgr); + exclusive = false; + + /* Take back root privileges temporarily */ + if (first_time) { + named_os_restoreuser(); + } + + /* Configure the statistics channel(s) */ + result = named_statschannels_configure(named_g_server, config, + named_g_aclconfctx); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "configuring statistics server(s): %s", + isc_result_totext(result)); + goto cleanup_altsecrets; + } + + /* + * Bind the control port(s). + */ + result = named_controls_configure(named_g_server->controls, config, + named_g_aclconfctx); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "binding control channel(s): %s", + isc_result_totext(result)); + goto cleanup_altsecrets; + } + + (void)ns_interfacemgr_scan(server->interfacemgr, true, true); + + /* + * Permanently drop root privileges now. + */ + if (first_time) { + named_os_changeuser(true); + } + + /* + * These cleans up either the old production view list + * or our temporary list depending on whether they + * were swapped above or not. + */ +cleanup_altsecrets: + while ((altsecret = ISC_LIST_HEAD(altsecrets)) != NULL) { + ISC_LIST_UNLINK(altsecrets, altsecret, link); + isc_mem_put(server->sctx->mctx, altsecret, sizeof(*altsecret)); + } + +cleanup_logc: + if (logc != NULL) { + isc_logconfig_destroy(&logc); + } + +cleanup_cachelist: + while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) { + ISC_LIST_UNLINK(cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + + ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link); + +cleanup_viewlist: + for (dns_view_t *view = ISC_LIST_HEAD(viewlist); view != NULL; + view = view_next) + { + view_next = ISC_LIST_NEXT(view, link); + ISC_LIST_UNLINK(viewlist, view, link); + if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) + { + dns_view_setviewrevert(view); + (void)dns_view_apply(view, false, NULL, removed, view); + } + dns_view_detach(&view); + } + +cleanup_kasplist: + for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) { + kasp_next = ISC_LIST_NEXT(kasp, link); + ISC_LIST_UNLINK(kasplist, kasp, link); + dns_kasp_detach(&kasp); + } + +cleanup_keystorelist: + for (keystore = ISC_LIST_HEAD(keystorelist); keystore != NULL; + keystore = keystore_next) + { + keystore_next = ISC_LIST_NEXT(keystore, link); + ISC_LIST_UNLINK(keystorelist, keystore, link); + dns_keystore_detach(&keystore); + } + +cleanup_v6portset: + isc_portset_destroy(named_g_mctx, &v6portset); + +cleanup_v4portset: + isc_portset_destroy(named_g_mctx, &v4portset); + +cleanup_bindkeys_parser: + + if (bindkeys_parser != NULL) { + if (bindkeys != NULL) { + cfg_obj_destroy(bindkeys_parser, &bindkeys); + } + cfg_parser_destroy(&bindkeys_parser); + } + +cleanup_config: + cfg_obj_destroy(conf_parser, &config); + +cleanup_conf_parser: + cfg_parser_destroy(&conf_parser); + +cleanup_exclusive: + if (exclusive) { + isc_loopmgr_resume(named_g_loopmgr); + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "load_configuration: %s", isc_result_totext(result)); + + return result; +} + +static isc_result_t +view_loaded(void *arg) { + isc_result_t result; + ns_zoneload_t *zl = (ns_zoneload_t *)arg; + + /* + * Force zone maintenance. Do this after loading + * so that we know when we need to force AXFR of + * secondary zones whose master files are missing. + * + * We use the zoneload reference counter to let us + * know when all views are finished. + */ + if (isc_refcount_decrement(&zl->refs) == 1) { + named_server_t *server = zl->server; + bool reconfig = zl->reconfig; + dns_view_t *view = NULL; + + isc_refcount_destroy(&zl->refs); + isc_mem_put(server->mctx, zl, sizeof(*zl)); + + /* + * To maintain compatibility with log parsing tools that might + * be looking for this string after "rndc reconfig", we keep it + * as it is + */ + if (reconfig) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "any newly configured zones are now " + "loaded"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "all zones loaded"); + } + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (view->managed_keys != NULL) { + result = dns_zone_synckeyzone( + view->managed_keys); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, + DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_DNSSEC, + ISC_LOG_ERROR, + "failed to initialize " + "managed-keys for view %s " + "(%s): DNSSEC validation is " + "at risk", + view->name, + isc_result_totext(result)); + } + } + } + + CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), + "forcing zone maintenance"); + + named_os_started(); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "FIPS mode is %s", + isc_fips_mode() ? "enabled" : "disabled"); + +#if HAVE_LIBSYSTEMD + sd_notifyf(0, + "READY=1\n" + "STATUS=running\n" + "MAINPID=%" PRId64 "\n", + (int64_t)getpid()); +#endif /* HAVE_LIBSYSTEMD */ + + atomic_store(&server->reload_status, NAMED_RELOAD_DONE); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "running"); + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +load_zones(named_server_t *server, bool reconfig) { + isc_result_t result = ISC_R_SUCCESS; + ns_zoneload_t *zl = NULL; + dns_view_t *view = NULL; + + zl = isc_mem_get(server->mctx, sizeof(*zl)); + zl->server = server; + zl->reconfig = reconfig; + + isc_loopmgr_pause(named_g_loopmgr); + + isc_refcount_init(&zl->refs, 1); + + /* + * Schedule zones to be loaded from disk. + */ + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (view->managed_keys != NULL) { + result = dns_zone_load(view->managed_keys, false); + if (result != ISC_R_SUCCESS && + result != DNS_R_UPTODATE && + result != DNS_R_CONTINUE) + { + goto cleanup; + } + } + if (view->redirect != NULL) { + result = dns_zone_load(view->redirect, false); + if (result != ISC_R_SUCCESS && + result != DNS_R_UPTODATE && + result != DNS_R_CONTINUE) + { + goto cleanup; + } + } + + /* + * 'dns_view_asyncload' calls view_loaded if there are no + * zones. + */ + isc_refcount_increment(&zl->refs); + result = dns_view_asyncload(view, reconfig, view_loaded, zl); + if (result != ISC_R_SUCCESS) { + isc_refcount_decrement1(&zl->refs); + goto cleanup; + } + } + +cleanup: + if (isc_refcount_decrement(&zl->refs) == 1) { + isc_refcount_destroy(&zl->refs); + isc_mem_put(server->mctx, zl, sizeof(*zl)); + } + + isc_loopmgr_resume(named_g_loopmgr); + + return result; +} + +static void +run_server(void *arg) { + isc_result_t result; + named_server_t *server = (named_server_t *)arg; + dns_geoip_databases_t *geoip = NULL; + + dns_zonemgr_create(named_g_mctx, named_g_netmgr, &server->zonemgr); + + CHECKFATAL(dns_dispatchmgr_create(named_g_mctx, named_g_loopmgr, + named_g_netmgr, &named_g_dispatchmgr), + "creating dispatch manager"); + + dns_dispatchmgr_setstats(named_g_dispatchmgr, server->resolverstats); + +#if defined(HAVE_GEOIP2) + geoip = named_g_geoip; +#else /* if defined(HAVE_GEOIP2) */ + geoip = NULL; +#endif /* if defined(HAVE_GEOIP2) */ + + CHECKFATAL(ns_interfacemgr_create(named_g_mctx, server->sctx, + named_g_loopmgr, named_g_netmgr, + named_g_dispatchmgr, geoip, + &server->interfacemgr), + "creating interface manager"); + + isc_timer_create(named_g_mainloop, interface_timer_tick, server, + &server->interface_timer); + + isc_timer_create(named_g_mainloop, heartbeat_timer_tick, server, + &server->heartbeat_timer); + + isc_timer_create(named_g_mainloop, tat_timer_tick, server, + &server->tat_timer); + + isc_timer_create(named_g_mainloop, pps_timer_tick, server, + &server->pps_timer); + + CHECKFATAL( + cfg_parser_create(named_g_mctx, named_g_lctx, &named_g_parser), + "creating default configuration parser"); + + CHECKFATAL(cfg_parser_create(named_g_mctx, named_g_lctx, + &named_g_addparser), + "creating additional configuration parser"); + + CHECKFATAL(load_configuration(named_g_conffile, server, true), + "loading configuration"); + + CHECKFATAL(load_zones(server, false), "loading zones"); +#ifdef ENABLE_AFL + named_g_run_done = true; +#endif /* ifdef ENABLE_AFL */ +} + +void +named_server_flushonshutdown(named_server_t *server, bool flush) { + REQUIRE(NAMED_SERVER_VALID(server)); + + server->flushonshutdown = flush; +} + +static void +shutdown_server(void *arg) { + named_server_t *server = (named_server_t *)arg; + dns_view_t *view = NULL, *view_next = NULL; + dns_kasp_t *kasp = NULL, *kasp_next = NULL; + dns_keystore_t *keystore = NULL, *keystore_next = NULL; + bool flush = server->flushonshutdown; + named_cache_t *nsc = NULL; + +#if HAVE_LIBSYSTEMD + sd_notify(0, "STOPPING=1\n"); +#endif /* HAVE_LIBSYSTEMD */ + + isc_signal_stop(server->sighup); + isc_signal_destroy(&server->sighup); + + /* + * We need to shutdown the interface before going + * exclusive (which would pause the netmgr). + */ + ns_interfacemgr_shutdown(server->interfacemgr); + + named_controls_shutdown(server->controls); + + named_statschannels_shutdown(server); + + isc_loopmgr_pause(named_g_loopmgr); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "shutting down%s", + flush ? ": flushing changes" : ""); + + cleanup_session_key(server, server->mctx); + + if (named_g_aclconfctx != NULL) { + cfg_aclconfctx_detach(&named_g_aclconfctx); + } + + cfg_obj_destroy(named_g_parser, &named_g_config); + cfg_parser_destroy(&named_g_parser); + cfg_parser_destroy(&named_g_addparser); + + (void)named_server_saventa(server); + + for (kasp = ISC_LIST_HEAD(server->kasplist); kasp != NULL; + kasp = kasp_next) + { + kasp_next = ISC_LIST_NEXT(kasp, link); + ISC_LIST_UNLINK(server->kasplist, kasp, link); + dns_kasp_detach(&kasp); + } + + for (keystore = ISC_LIST_HEAD(server->keystorelist); keystore != NULL; + keystore = keystore_next) + { + keystore_next = ISC_LIST_NEXT(keystore, link); + ISC_LIST_UNLINK(server->keystorelist, keystore, link); + dns_keystore_detach(&keystore); + } + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = view_next) + { + view_next = ISC_LIST_NEXT(view, link); + ISC_LIST_UNLINK(server->viewlist, view, link); + dns_view_flushonshutdown(view, flush); + dns_view_detach(&view); + } + + /* + * Shut down all dyndb instances. + */ + dns_dyndb_cleanup(true); + + while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { + ISC_LIST_UNLINK(server->cachelist, nsc, link); + dns_cache_detach(&nsc->cache); + isc_mem_put(server->mctx, nsc, sizeof(*nsc)); + } + + isc_timer_destroy(&server->interface_timer); + isc_timer_destroy(&server->heartbeat_timer); + isc_timer_destroy(&server->pps_timer); + isc_timer_destroy(&server->tat_timer); + + ns_interfacemgr_detach(&server->interfacemgr); + + dns_dispatchmgr_detach(&named_g_dispatchmgr); + + dns_zonemgr_shutdown(server->zonemgr); + +#if defined(HAVE_GEOIP2) + named_geoip_shutdown(); +#endif /* HAVE_GEOIP2 */ + + dns_db_detach(&server->in_roothints); + + isc_loopmgr_resume(named_g_loopmgr); +} + +static isc_result_t +get_matching_view_sync(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, + dns_message_t *message, dns_aclenv_t *env, + isc_result_t *sigresult, dns_view_t **viewp) { + dns_view_t *view; + + /* + * We should not be running synchronous view matching if signature + * checking involves SIG(0). TSIG has priority of SIG(0), so if TSIG + * is set then we proceed anyway. + */ + INSIST(message->tsigkey != NULL || message->tsig != NULL || + message->sig0 == NULL); + + for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (message->rdclass == view->rdclass || + message->rdclass == dns_rdataclass_any) + { + const dns_name_t *tsig = NULL; + + dns_message_resetsig(message); + *sigresult = dns_message_checksig(message, view); + if (*sigresult == ISC_R_SUCCESS) { + tsig = dns_tsigkey_identity(message->tsigkey); + } + + if (dns_acl_allowed(srcaddr, tsig, view->matchclients, + env) && + dns_acl_allowed(destaddr, tsig, + view->matchdestinations, env) && + !(view->matchrecursiveonly && + (message->flags & DNS_MESSAGEFLAG_RD) == 0)) + { + dns_view_attach(view, viewp); + return ISC_R_SUCCESS; + } + } + } + + return ISC_R_NOTFOUND; +} + +static void +get_matching_view_done(void *cbarg) { + matching_view_ctx_t *mvctx = cbarg; + dns_message_t *message = mvctx->message; + + if (*mvctx->viewmatchresult == ISC_R_SUCCESS) { + INSIST(mvctx->view != NULL); + dns_view_attach(mvctx->view, mvctx->viewp); + } + + mvctx->cb(mvctx->cbarg); + + if (mvctx->quota_result == ISC_R_SUCCESS) { + isc_quota_release(&mvctx->sctx->sig0checksquota); + } + if (mvctx->view != NULL) { + dns_view_detach(&mvctx->view); + } + isc_loop_detach(&mvctx->loop); + ns_server_detach(&mvctx->sctx); + isc_mem_put(message->mctx, mvctx, sizeof(*mvctx)); + dns_message_detach(&message); +} + +static dns_view_t * +get_matching_view_next(dns_view_t *view, dns_rdataclass_t rdclass) { + if (view == NULL) { + view = ISC_LIST_HEAD(named_g_server->viewlist); + } else { + view = ISC_LIST_NEXT(view, link); + } + while (true) { + if (view == NULL || rdclass == view->rdclass || + rdclass == dns_rdataclass_any) + { + return view; + } + view = ISC_LIST_NEXT(view, link); + }; +} + +static void +get_matching_view_continue(void *cbarg, isc_result_t result) { + matching_view_ctx_t *mvctx = cbarg; + dns_view_t *view = NULL; + const dns_name_t *tsig = NULL; + + *mvctx->sigresult = result; + + if (result == ISC_R_SUCCESS) { + tsig = dns_tsigkey_identity(mvctx->message->tsigkey); + } + + if (dns_acl_allowed(mvctx->srcaddr, tsig, mvctx->view->matchclients, + mvctx->env) && + dns_acl_allowed(mvctx->destaddr, tsig, + mvctx->view->matchdestinations, mvctx->env) && + !(mvctx->view->matchrecursiveonly && + (mvctx->message->flags & DNS_MESSAGEFLAG_RD) == 0)) + { + /* + * A matching view is found. + */ + *mvctx->viewmatchresult = ISC_R_SUCCESS; + get_matching_view_done(cbarg); + return; + } + + dns_message_resetsig(mvctx->message); + + view = get_matching_view_next(mvctx->view, mvctx->message->rdclass); + dns_view_detach(&mvctx->view); + if (view != NULL) { + /* + * Try the next view. + */ + dns_view_attach(view, &mvctx->view); + result = dns_message_checksig_async( + mvctx->message, view, mvctx->loop, + get_matching_view_continue, mvctx); + INSIST(result == DNS_R_WAIT); + return; + } + + /* + * No matching view is found. + */ + *mvctx->viewmatchresult = ISC_R_NOTFOUND; + get_matching_view_done(cbarg); +} + +/*% + * Find a view that matches the source and destination addresses of a query. + */ +static isc_result_t +get_matching_view(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr, + dns_message_t *message, dns_aclenv_t *env, ns_server_t *sctx, + isc_loop_t *loop, isc_job_cb cb, void *cbarg, + isc_result_t *sigresult, isc_result_t *viewmatchresult, + dns_view_t **viewp) { + dns_view_t *view = NULL; + isc_result_t result; + + REQUIRE(message != NULL); + REQUIRE(sctx != NULL); + REQUIRE(loop == NULL || cb != NULL); + REQUIRE(sigresult != NULL); + REQUIRE(viewmatchresult != NULL); + REQUIRE(viewp != NULL && *viewp == NULL); + + /* No offloading is requested if the loop is unset. */ + if (loop == NULL) { + *viewmatchresult = get_matching_view_sync( + srcaddr, destaddr, message, env, sigresult, viewp); + return *viewmatchresult; + } + + /* Also no offloading when there is no view at all to match against. */ + view = get_matching_view_next(NULL, message->rdclass); + if (view == NULL) { + *viewmatchresult = ISC_R_NOTFOUND; + return *viewmatchresult; + } + + dns_message_resetsig(message); + + matching_view_ctx_t *mvctx = isc_mem_get(message->mctx, sizeof(*mvctx)); + *mvctx = (matching_view_ctx_t){ + .srcaddr = srcaddr, + .destaddr = destaddr, + .env = env, + .cb = cb, + .cbarg = cbarg, + .sigresult = sigresult, + .viewmatchresult = viewmatchresult, + .quota_result = ISC_R_UNSET, + .viewp = viewp, + }; + ns_server_attach(sctx, &mvctx->sctx); + isc_loop_attach(loop, &mvctx->loop); + dns_message_attach(message, &mvctx->message); + + /* + * If the message has a SIG0 signature which we are going to + * check, and the client is not exempt from the SIG(0) quota, + * then acquire a quota. TSIG has priority over SIG(0), so if + * TSIG is set then we don't care. + */ + if (message->tsigkey == NULL && message->tsig == NULL && + message->sig0 != NULL) + { + if (sctx->sig0checksquota_exempt != NULL) { + int exempt_match; + + result = dns_acl_match(srcaddr, NULL, + sctx->sig0checksquota_exempt, + env, &exempt_match, NULL); + if (result == ISC_R_SUCCESS && exempt_match > 0) { + mvctx->quota_result = ISC_R_EXISTS; + } + } + if (mvctx->quota_result == ISC_R_UNSET) { + mvctx->quota_result = + isc_quota_acquire(&sctx->sig0checksquota); + } + if (mvctx->quota_result == ISC_R_SOFTQUOTA) { + isc_quota_release(&sctx->sig0checksquota); + } + if (mvctx->quota_result != ISC_R_SUCCESS && + mvctx->quota_result != ISC_R_EXISTS) + { + *mvctx->viewmatchresult = ISC_R_QUOTA; + isc_async_run(loop, get_matching_view_done, mvctx); + return DNS_R_WAIT; + } + } + + dns_view_attach(view, &mvctx->view); + result = dns_message_checksig_async(message, view, loop, + get_matching_view_continue, mvctx); + INSIST(result == DNS_R_WAIT); + + return DNS_R_WAIT; +} + +void +named_server_create(isc_mem_t *mctx, named_server_t **serverp) { + isc_result_t result; + named_server_t *server = isc_mem_get(mctx, sizeof(*server)); + + *server = (named_server_t){ + .mctx = mctx, + .statsfile = isc_mem_strdup(mctx, "named.stats"), + .dumpfile = isc_mem_strdup(mctx, "named_dump.db"), + .secrootsfile = isc_mem_strdup(mctx, "named.secroots"), + .recfile = isc_mem_strdup(mctx, "named.recursing"), + }; + + /* Initialize server data structures. */ + ISC_LIST_INIT(server->kasplist); + ISC_LIST_INIT(server->keystorelist); + ISC_LIST_INIT(server->viewlist); + + /* Must be first. */ + CHECKFATAL(dst_lib_init(named_g_mctx, named_g_engine), + "initializing DST"); + + CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, + &server->in_roothints), + "setting up root hints"); + + atomic_init(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); + + ns_server_create(mctx, get_matching_view, &server->sctx); + +#if defined(HAVE_GEOIP2) + /* + * GeoIP must be initialized before the interface + * manager (which includes the ACL environment) + * is created. + */ + named_geoip_init(); +#endif /* HAVE_GEOIP2 */ + +#ifdef ENABLE_AFL + server->sctx->fuzztype = named_g_fuzz_type; + server->sctx->fuzznotify = named_fuzz_notify; +#endif /* ifdef ENABLE_AFL */ + + named_g_mainloop = isc_loop_main(named_g_loopmgr); + + isc_loop_setup(named_g_mainloop, run_server, server); + isc_loop_teardown(named_g_mainloop, shutdown_server, server); + + /* Add SIGHUP reload handler */ + server->sighup = isc_signal_new( + named_g_loopmgr, named_server_reloadwanted, server, SIGHUP); + + isc_stats_create(server->mctx, &server->sockstats, + isc_sockstatscounter_max); + isc_nm_setstats(named_g_netmgr, server->sockstats); + + isc_stats_create(named_g_mctx, &server->zonestats, + dns_zonestatscounter_max); + + isc_stats_create(named_g_mctx, &server->resolverstats, + dns_resstatscounter_max); + + CHECKFATAL(named_controls_create(server, &server->controls), + "named_controls_create"); + + ISC_LIST_INIT(server->statschannels); + + ISC_LIST_INIT(server->cachelist); + + server->magic = NAMED_SERVER_MAGIC; + + *serverp = server; +} + +void +named_server_destroy(named_server_t **serverp) { + named_server_t *server = *serverp; + REQUIRE(NAMED_SERVER_VALID(server)); + +#ifdef HAVE_DNSTAP + if (server->dtenv != NULL) { + dns_dt_detach(&server->dtenv); + } +#endif /* HAVE_DNSTAP */ + +#ifdef USE_DNSRPS + dns_dnsrps_server_destroy(); + isc_mem_free(server->mctx, server->dnsrpslib); +#endif /* ifdef USE_DNSRPS */ + + named_controls_destroy(&server->controls); + + isc_stats_detach(&server->zonestats); + isc_stats_detach(&server->sockstats); + isc_stats_detach(&server->resolverstats); + + if (server->sctx != NULL) { + ns_server_detach(&server->sctx); + } + + isc_mem_free(server->mctx, server->statsfile); + isc_mem_free(server->mctx, server->dumpfile); + isc_mem_free(server->mctx, server->secrootsfile); + isc_mem_free(server->mctx, server->recfile); + + if (server->bindkeysfile != NULL) { + isc_mem_free(server->mctx, server->bindkeysfile); + } + + if (server->version != NULL) { + isc_mem_free(server->mctx, server->version); + } + if (server->hostname != NULL) { + isc_mem_free(server->mctx, server->hostname); + } + + if (server->zonemgr != NULL) { + dns_zonemgr_detach(&server->zonemgr); + } + + dst_lib_destroy(); + + INSIST(ISC_LIST_EMPTY(server->kasplist)); + INSIST(ISC_LIST_EMPTY(server->keystorelist)); + INSIST(ISC_LIST_EMPTY(server->viewlist)); + INSIST(ISC_LIST_EMPTY(server->cachelist)); + + if (server->tlsctx_server_cache != NULL) { + isc_tlsctx_cache_detach(&server->tlsctx_server_cache); + } + + if (server->tlsctx_client_cache != NULL) { + isc_tlsctx_cache_detach(&server->tlsctx_client_cache); + } + + server->magic = 0; + isc_mem_put(server->mctx, server, sizeof(*server)); + *serverp = NULL; +} + +static void +fatal(const char *msg, isc_result_t result) { + if (named_g_loopmgr_running) { + isc_loopmgr_pause(named_g_loopmgr); + } + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, "%s: %s", msg, + isc_result_totext(result)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_CRITICAL, + "exiting (due to fatal error)"); + named_os_shutdown(); + _exit(EXIT_FAILURE); +} + +static isc_result_t +loadconfig(named_server_t *server) { + isc_result_t result; + result = load_configuration(named_g_conffile, server, false); + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "reloading configuration succeeded"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "reloading configuration failed: %s", + isc_result_totext(result)); + atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); + } + + return result; +} + +static isc_result_t +reload(named_server_t *server) { + isc_result_t result; + + atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); +#if HAVE_LIBSYSTEMD + char buf[512]; + int n = snprintf(buf, sizeof(buf), + "RELOADING=1\n" + "MONOTONIC_USEC=%" PRIu64 "\n" + "STATUS=reload command received\n", + (uint64_t)isc_time_monotonic() / NS_PER_US); + if (n > 0 && (size_t)n < sizeof(buf)) { + sd_notify(0, buf); + } +#endif /* HAVE_LIBSYSTEMD */ + + CHECK(loadconfig(server)); + + result = load_zones(server, false); + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "reloading zones succeeded"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "reloading zones failed: %s", + isc_result_totext(result)); + atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); + } +cleanup: +#if HAVE_LIBSYSTEMD + sd_notifyf(0, + "READY=1\n" + "STATUS=reload command finished: %s\n", + isc_result_totext(result)); +#endif /* HAVE_LIBSYSTEMD */ + return result; +} + +/* + * Handle a reload event (from SIGHUP). + */ +static void +named_server_reload(void *arg) { + named_server_t *server = (named_server_t *)arg; + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "received SIGHUP signal to reload zones"); + (void)reload(server); +} + +void +named_server_reloadwanted(void *arg, int signum) { + named_server_t *server = (named_server_t *)arg; + + REQUIRE(signum == SIGHUP); + + isc_async_run(named_g_mainloop, named_server_reload, server); +} + +#ifdef JEMALLOC_API_SUPPORTED +static isc_result_t +memprof_toggle(bool active) { + if (mallctl("prof.active", NULL, NULL, &active, sizeof(active)) != 0) { + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +memprof_dump(void) { + if (mallctl("prof.dump", NULL, NULL, NULL, 0) != 0) { + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} +#else +static isc_result_t +memprof_toggle(bool active) { + UNUSED(active); + + return ISC_R_NOTIMPLEMENTED; +} + +static isc_result_t +memprof_dump(void) { + return ISC_R_NOTIMPLEMENTED; +} + +#endif /* JEMALLOC_API_SUPPORTED */ + +void +named_server_scan_interfaces(named_server_t *server) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), + "automatic interface rescan"); + + ns_interfacemgr_scan(server->interfacemgr, true, false); +} + +/* + * Get the next token from lexer 'lex'. + * + * NOTE: the token value for string tokens always uses the same pointer + * value. Multiple calls to this function on the same lexer will always + * return either that value (lex->data) or NULL. It is necessary to copy + * the token into local storage if it needs to be referenced after the next + * call to next_token(). + */ +static char * +next_token(isc_lex_t *lex, isc_buffer_t **text) { + isc_result_t result; + isc_token_t token; + + token.type = isc_tokentype_unknown; + result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF | ISC_LEXOPT_QSTRING, + &token); + + switch (result) { + case ISC_R_NOMORE: + (void)isc_lex_close(lex); + break; + case ISC_R_SUCCESS: + if (token.type == isc_tokentype_eof) { + (void)isc_lex_close(lex); + } + break; + case ISC_R_NOSPACE: + if (text != NULL) { + (void)putstr(text, "token too large"); + (void)putnull(text); + } + return NULL; + default: + if (text != NULL) { + (void)putstr(text, isc_result_totext(result)); + (void)putnull(text); + } + return NULL; + } + + if (token.type == isc_tokentype_string || + token.type == isc_tokentype_qstring) + { + return token.value.as_textregion.base; + } + + return NULL; +} + +/* + * Find the zone specified in the control channel command, if any. + * If a zone is specified, point '*zonep' at it, otherwise + * set '*zonep' to NULL, and f 'zonename' is not NULL, copy + * the zone name into it (N.B. 'zonename' must have space to hold + * a full DNS name). + * + * If 'zonetxt' is set, the caller has already pulled a token + * off the command line that is to be used as the zone name. (This + * is sometimes done when it's necessary to check for an optional + * argument before the zone name, as in "rndc sync [-clean] zone".) + */ +static isc_result_t +zone_from_args(named_server_t *server, isc_lex_t *lex, const char *zonetxt, + dns_zone_t **zonep, char *zonename, isc_buffer_t **text, + bool skip) { + char *ptr; + char *classtxt; + const char *viewtxt = NULL; + dns_fixedname_t fname; + dns_name_t *name; + isc_result_t result; + dns_view_t *view = NULL; + dns_rdataclass_t rdclass; + char problem[DNS_NAME_FORMATSIZE + 500] = ""; + char zonebuf[DNS_NAME_FORMATSIZE]; + bool redirect = false; + + REQUIRE(zonep != NULL && *zonep == NULL); + + if (skip) { + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + } + + /* Look for the zone name. */ + if (zonetxt == NULL) { + zonetxt = next_token(lex, text); + } + if (zonetxt == NULL) { + return ISC_R_SUCCESS; + } + + /* Copy zonetxt because it'll be overwritten by next_token() */ + /* To locate a zone named "-redirect" use "-redirect." */ + if (strcmp(zonetxt, "-redirect") == 0) { + redirect = true; + strlcpy(zonebuf, ".", DNS_NAME_FORMATSIZE); + } else { + strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); + } + if (zonename != NULL) { + strlcpy(zonename, redirect ? "." : zonetxt, + DNS_NAME_FORMATSIZE); + } + + name = dns_fixedname_initname(&fname); + CHECK(dns_name_fromstring(name, zonebuf, dns_rootname, 0, NULL)); + + /* Look for the optional class name. */ + classtxt = next_token(lex, text); + if (classtxt != NULL) { + isc_textregion_t r; + r.base = classtxt; + r.length = strlen(classtxt); + CHECK(dns_rdataclass_fromtext(&rdclass, &r)); + + /* Look for the optional view name. */ + viewtxt = next_token(lex, text); + } else { + rdclass = dns_rdataclass_in; + } + + if (viewtxt == NULL) { + if (redirect) { + result = dns_viewlist_find(&server->viewlist, + "_default", + dns_rdataclass_in, &view); + if (result != ISC_R_SUCCESS || view->redirect == NULL) { + result = ISC_R_NOTFOUND; + snprintf(problem, sizeof(problem), + "redirect zone not found in " + "_default view"); + } else { + dns_zone_attach(view->redirect, zonep); + result = ISC_R_SUCCESS; + } + } else { + result = dns_viewlist_findzone(&server->viewlist, name, + classtxt == NULL, + rdclass, zonep); + if (result == ISC_R_NOTFOUND) { + snprintf(problem, sizeof(problem), + "no matching zone '%s' in any view", + zonebuf); + } else if (result == ISC_R_MULTIPLE) { + snprintf(problem, sizeof(problem), + "zone '%s' was found in multiple " + "views", + zonebuf); + } + } + } else { + result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, + &view); + if (result != ISC_R_SUCCESS) { + snprintf(problem, sizeof(problem), + "no matching view '%s'", viewtxt); + goto report; + } + + if (redirect) { + if (view->redirect != NULL) { + dns_zone_attach(view->redirect, zonep); + result = ISC_R_SUCCESS; + } else { + result = ISC_R_NOTFOUND; + } + } else { + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, + zonep); + } + if (result != ISC_R_SUCCESS) { + snprintf(problem, sizeof(problem), + "no matching zone '%s' in view '%s'", zonebuf, + viewtxt); + } + } + + /* Partial match? */ + if (result != ISC_R_SUCCESS && *zonep != NULL) { + dns_zone_detach(zonep); + } + if (result == DNS_R_PARTIALMATCH) { + result = ISC_R_NOTFOUND; + } +report: + if (result != ISC_R_SUCCESS) { + isc_result_t tresult; + + tresult = putstr(text, problem); + if (tresult == ISC_R_SUCCESS) { + (void)putnull(text); + } + } + +cleanup: + if (view != NULL) { + dns_view_detach(&view); + } + + return result; +} + +/* + * Act on a "retransfer" command from the command channel. + */ +isc_result_t +named_server_retransfercommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + const char *arg = NULL; + dns_zone_t *zone = NULL; + dns_zone_t *raw = NULL; + dns_zonetype_t type; + bool force = false; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + (void)next_token(lex, text); + + arg = next_token(lex, text); + if (arg != NULL && (strcmp(arg, "-force") == 0)) { + force = true; + arg = next_token(lex, text); + } + + result = zone_from_args(server, lex, arg, &zone, NULL, text, false); + if (result != ISC_R_SUCCESS) { + return result; + } + if (zone == NULL) { + return ISC_R_UNEXPECTEDEND; + } + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + dns_zone_detach(&zone); + dns_zone_attach(raw, &zone); + dns_zone_detach(&raw); + } + type = dns_zone_gettype(zone); + if (type == dns_zone_secondary || type == dns_zone_mirror || + type == dns_zone_stub || + (type == dns_zone_redirect && + dns_zone_getredirecttype(zone) == dns_zone_secondary)) + { + if (force) { + dns_zone_stopxfr(zone); + } + dns_zone_forcexfr(zone); + } else { + (void)putstr(text, "retransfer: inappropriate zone type: "); + (void)putstr(text, dns_zonetype_name(type)); + if (type == dns_zone_redirect) { + type = dns_zone_getredirecttype(zone); + (void)putstr(text, "("); + (void)putstr(text, dns_zonetype_name(type)); + (void)putstr(text, ")"); + } + (void)putnull(text); + result = ISC_R_FAILURE; + } + dns_zone_detach(&zone); + return result; +} + +/* + * Act on a "reload" command from the command channel. + */ +isc_result_t +named_server_reloadcommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_zonetype_t type; + const char *msg = NULL; + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); + if (result != ISC_R_SUCCESS) { + return result; + } + if (zone == NULL) { + result = reload(server); + if (result == ISC_R_SUCCESS) { + msg = "server reload successful"; + } + } else { + type = dns_zone_gettype(zone); + if (type == dns_zone_secondary || type == dns_zone_mirror || + type == dns_zone_stub) + { + dns_zone_refresh(zone); + dns_zone_detach(&zone); + msg = "zone refresh queued"; + } else { + result = dns_zone_load(zone, false); + dns_zone_detach(&zone); + switch (result) { + case ISC_R_SUCCESS: + msg = "zone reload successful"; + break; + case DNS_R_CONTINUE: + msg = "zone reload queued"; + result = ISC_R_SUCCESS; + break; + case DNS_R_UPTODATE: + msg = "zone reload up-to-date"; + result = ISC_R_SUCCESS; + break; + default: + /* failure message will be generated by rndc */ + break; + } + } + } + if (msg != NULL) { + (void)putstr(text, msg); + (void)putnull(text); + } + return result; +} + +/* + * Act on a "reset-stats" command from the command channel. + */ +isc_result_t +named_server_resetstatscommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + const char *arg = NULL; + bool recursive_high_water = false; + bool tcp_high_water = false; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + (void)next_token(lex, text); + + arg = next_token(lex, text); + if (arg == NULL) { + (void)putstr(text, "reset-stats: argument expected"); + (void)putnull(text); + return ISC_R_UNEXPECTEDEND; + } + while (arg != NULL) { + if (strcmp(arg, "recursive-high-water") == 0) { + recursive_high_water = true; + } else if (strcmp(arg, "tcp-high-water") == 0) { + tcp_high_water = true; + } else { + (void)putstr(text, "reset-stats: " + "unrecognized argument: "); + (void)putstr(text, arg); + (void)putnull(text); + return ISC_R_FAILURE; + } + arg = next_token(lex, text); + } + + if (recursive_high_water) { + isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, + ns_statscounter_recurshighwater); + } + if (tcp_high_water) { + isc_stats_set(ns_stats_get(server->sctx->nsstats), 0, + ns_statscounter_tcphighwater); + } + + return ISC_R_SUCCESS; +} + +/* + * Act on a "reconfig" command from the command channel. + */ +isc_result_t +named_server_reconfigcommand(named_server_t *server) { + isc_result_t result; + atomic_store(&server->reload_status, NAMED_RELOAD_IN_PROGRESS); +#if HAVE_LIBSYSTEMD + char buf[512]; + int n = snprintf(buf, sizeof(buf), + "RELOADING=1\n" + "MONOTONIC_USEC=%" PRIu64 "\n" + "STATUS=reconfig command received\n", + (uint64_t)isc_time_monotonic() / NS_PER_US); + if (n > 0 && (size_t)n < sizeof(buf)) { + sd_notify(0, buf); + } +#endif /* HAVE_LIBSYSTEMD */ + + CHECK(loadconfig(server)); + + result = load_zones(server, true); + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "scheduled loading new zones"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "loading new zones failed: %s", + isc_result_totext(result)); + atomic_store(&server->reload_status, NAMED_RELOAD_FAILED); + } +cleanup: +#if HAVE_LIBSYSTEMD + sd_notifyf(0, + "READY=1\n" + "STATUS=reconfig command finished: %s\n", + isc_result_totext(result)); +#endif /* HAVE_LIBSYSTEMD */ + return result; +} + +/* + * Act on a "notify" command from the command channel. + */ +isc_result_t +named_server_notifycommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + dns_zone_t *zone = NULL; + const char msg[] = "zone notify queued"; + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); + if (result != ISC_R_SUCCESS) { + return result; + } + if (zone == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + dns_zone_notify(zone); + dns_zone_detach(&zone); + (void)putstr(text, msg); + (void)putnull(text); + + return ISC_R_SUCCESS; +} + +/* + * Act on a "refresh" command from the command channel. + */ +isc_result_t +named_server_refreshcommand(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + dns_zone_t *zone = NULL, *raw = NULL; + const char msg1[] = "zone refresh queued"; + const char msg2[] = "not a secondary, mirror, or stub zone"; + dns_zonetype_t type; + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, NULL, &zone, NULL, text, true); + if (result != ISC_R_SUCCESS) { + return result; + } + if (zone == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + dns_zone_detach(&zone); + dns_zone_attach(raw, &zone); + dns_zone_detach(&raw); + } + + type = dns_zone_gettype(zone); + if (type == dns_zone_secondary || type == dns_zone_mirror || + type == dns_zone_stub) + { + dns_zone_refresh(zone); + dns_zone_detach(&zone); + (void)putstr(text, msg1); + (void)putnull(text); + return ISC_R_SUCCESS; + } + + dns_zone_detach(&zone); + (void)putstr(text, msg2); + (void)putnull(text); + return ISC_R_FAILURE; +} + +isc_result_t +named_server_setortoggle(named_server_t *server, const char *optname, + unsigned int option, isc_lex_t *lex) { + bool prev, value; + char *ptr = NULL; + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + prev = ns_server_getoption(server->sctx, option); + + ptr = next_token(lex, NULL); + if (ptr == NULL) { + value = !prev; + } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || + !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) + { + value = true; + } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || + !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) + { + value = false; + } else { + return DNS_R_SYNTAX; + } + + if (value == prev) { + return ISC_R_SUCCESS; + } + + ns_server_setoption(server->sctx, option, value); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "%s is now %s", + optname, value ? "on" : "off"); + return ISC_R_SUCCESS; +} + +static isc_result_t +listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, + isc_tlsctx_cache_t *tlsctx_cache, + ns_listenlist_t **target) { + isc_result_t result; + const cfg_listelt_t *element; + ns_listenlist_t *dlist = NULL; + + REQUIRE(target != NULL && *target == NULL); + + result = ns_listenlist_create(mctx, &dlist); + if (result != ISC_R_SUCCESS) { + return result; + } + + for (element = cfg_list_first(listenlist); element != NULL; + element = cfg_list_next(element)) + { + ns_listenelt_t *delt = NULL; + const cfg_obj_t *listener = cfg_listelt_value(element); + result = listenelt_fromconfig(listener, config, actx, mctx, + family, tlsctx_cache, &delt); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + ISC_LIST_APPEND(dlist->elts, delt, link); + } + *target = dlist; + return ISC_R_SUCCESS; + +cleanup: + ns_listenlist_detach(&dlist); + return result; +} + +static const cfg_obj_t * +find_maplist(const cfg_obj_t *config, const char *listname, const char *name) { + isc_result_t result; + const cfg_obj_t *maplist = NULL; + const cfg_listelt_t *elt = NULL; + + REQUIRE(config != NULL); + REQUIRE(name != NULL); + + result = cfg_map_get(config, listname, &maplist); + if (result != ISC_R_SUCCESS) { + return NULL; + } + + for (elt = cfg_list_first(maplist); elt != NULL; + elt = cfg_list_next(elt)) + { + const cfg_obj_t *map = cfg_listelt_value(elt); + if (strcasecmp(cfg_obj_asstring(cfg_map_getname(map)), name) == + 0) + { + return map; + } + } + + return NULL; +} + +/* + * Create a listen list from the corresponding configuration + * data structure. + */ +static isc_result_t +listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, + cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, + isc_tlsctx_cache_t *tlsctx_cache, + ns_listenelt_t **target) { + isc_result_t result; + const cfg_obj_t *ltup = NULL; + const cfg_obj_t *tlsobj = NULL, *httpobj = NULL; + const cfg_obj_t *portobj = NULL; + const cfg_obj_t *http_server = NULL; + const cfg_obj_t *proxyobj = NULL; + in_port_t port = 0; + const char *key = NULL, *cert = NULL, *ca_file = NULL, + *dhparam_file = NULL, *ciphers = NULL, *cipher_suites = NULL; + bool tls_prefer_server_ciphers = false, + tls_prefer_server_ciphers_set = false; + bool tls_session_tickets = false, tls_session_tickets_set = false; + bool do_tls = false, no_tls = false, http = false; + ns_listenelt_t *delt = NULL; + uint32_t tls_protos = 0; + ns_listen_tls_params_t tls_params = { 0 }; + const char *tlsname = NULL; + isc_nm_proxy_type_t proxy = ISC_NM_PROXY_NONE; + + REQUIRE(target != NULL && *target == NULL); + + ltup = cfg_tuple_get(listener, "tuple"); + RUNTIME_CHECK(ltup != NULL); + + tlsobj = cfg_tuple_get(ltup, "tls"); + if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { + tlsname = cfg_obj_asstring(tlsobj); + + if (strcasecmp(tlsname, "none") == 0) { + no_tls = true; + } else if (strcasecmp(tlsname, "ephemeral") == 0) { + do_tls = true; + } else { + const cfg_obj_t *keyobj = NULL, *certobj = NULL, + *ca_obj = NULL, *dhparam_obj = NULL; + const cfg_obj_t *tlsmap = NULL; + const cfg_obj_t *tls_proto_list = NULL; + const cfg_obj_t *ciphers_obj = NULL; + const cfg_obj_t *cipher_suites_obj = NULL; + const cfg_obj_t *prefer_server_ciphers_obj = NULL; + const cfg_obj_t *session_tickets_obj = NULL; + + do_tls = true; + + tlsmap = find_maplist(config, "tls", tlsname); + if (tlsmap == NULL) { + cfg_obj_log(tlsobj, named_g_lctx, ISC_LOG_ERROR, + "tls '%s' is not defined", + cfg_obj_asstring(tlsobj)); + return ISC_R_FAILURE; + } + + CHECK(cfg_map_get(tlsmap, "key-file", &keyobj)); + key = cfg_obj_asstring(keyobj); + + CHECK(cfg_map_get(tlsmap, "cert-file", &certobj)); + cert = cfg_obj_asstring(certobj); + + if (cfg_map_get(tlsmap, "ca-file", &ca_obj) == + ISC_R_SUCCESS) + { + ca_file = cfg_obj_asstring(ca_obj); + } + + if (cfg_map_get(tlsmap, "protocols", &tls_proto_list) == + ISC_R_SUCCESS) + { + const cfg_listelt_t *proto = NULL; + INSIST(tls_proto_list != NULL); + for (proto = cfg_list_first(tls_proto_list); + proto != 0; proto = cfg_list_next(proto)) + { + const cfg_obj_t *tls_proto_obj = + cfg_listelt_value(proto); + const char *tls_sver = + cfg_obj_asstring(tls_proto_obj); + const isc_tls_protocol_version_t ver = + isc_tls_protocol_name_to_version( + tls_sver); + + INSIST(ver != + ISC_TLS_PROTO_VER_UNDEFINED); + INSIST(isc_tls_protocol_supported(ver)); + tls_protos |= ver; + } + } + + if (cfg_map_get(tlsmap, "dhparam-file", &dhparam_obj) == + ISC_R_SUCCESS) + { + dhparam_file = cfg_obj_asstring(dhparam_obj); + } + + if (cfg_map_get(tlsmap, "ciphers", &ciphers_obj) == + ISC_R_SUCCESS) + { + ciphers = cfg_obj_asstring(ciphers_obj); + } + + if (cfg_map_get(tlsmap, "cipher-suites", + &cipher_suites_obj) == ISC_R_SUCCESS) + { + cipher_suites = + cfg_obj_asstring(cipher_suites_obj); + } + + if (cfg_map_get(tlsmap, "prefer-server-ciphers", + &prefer_server_ciphers_obj) == + ISC_R_SUCCESS) + { + tls_prefer_server_ciphers = cfg_obj_asboolean( + prefer_server_ciphers_obj); + tls_prefer_server_ciphers_set = true; + } + + if (cfg_map_get(tlsmap, "session-tickets", + &session_tickets_obj) == ISC_R_SUCCESS) + { + tls_session_tickets = + cfg_obj_asboolean(session_tickets_obj); + tls_session_tickets_set = true; + } + } + } + + tls_params = (ns_listen_tls_params_t){ + .name = tlsname, + .key = key, + .cert = cert, + .ca_file = ca_file, + .protocols = tls_protos, + .dhparam_file = dhparam_file, + .ciphers = ciphers, + .cipher_suites = cipher_suites, + .prefer_server_ciphers = tls_prefer_server_ciphers, + .prefer_server_ciphers_set = tls_prefer_server_ciphers_set, + .session_tickets = tls_session_tickets, + .session_tickets_set = tls_session_tickets_set + }; + + httpobj = cfg_tuple_get(ltup, "http"); + if (httpobj != NULL && cfg_obj_isstring(httpobj)) { + const char *httpname = cfg_obj_asstring(httpobj); + + if (!do_tls && !no_tls) { + return ISC_R_FAILURE; + } + + http_server = find_maplist(config, "http", httpname); + if (http_server == NULL && strcasecmp(httpname, "default") != 0) + { + cfg_obj_log(httpobj, named_g_lctx, ISC_LOG_ERROR, + "http '%s' is not defined", + cfg_obj_asstring(httpobj)); + return ISC_R_FAILURE; + } + + http = true; + } + + portobj = cfg_tuple_get(ltup, "port"); + if (!cfg_obj_isuint32(portobj)) { + if (http && do_tls) { + if (named_g_httpsport != 0) { + port = named_g_httpsport; + } else { + result = named_config_getport( + config, "https-port", &port); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } else if (http && !do_tls) { + if (named_g_httpport != 0) { + port = named_g_httpport; + } else { + result = named_config_getport( + config, "http-port", &port); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } else if (do_tls) { + if (named_g_tlsport != 0) { + port = named_g_tlsport; + } else { + result = named_config_getport( + config, "tls-port", &port); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } else { + if (named_g_port != 0) { + port = named_g_port; + } else { + result = named_config_getport(config, "port", + &port); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } + } else { + if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { + return ISC_R_RANGE; + } + port = (in_port_t)cfg_obj_asuint32(portobj); + } + + proxyobj = cfg_tuple_get(ltup, "proxy"); + if (proxyobj != NULL && cfg_obj_isstring(proxyobj)) { + const char *proxyval = cfg_obj_asstring(proxyobj); + + if (strcasecmp(proxyval, "encrypted") == 0) { + INSIST(do_tls == true); + proxy = ISC_NM_PROXY_ENCRYPTED; + } else if (strcasecmp(proxyval, "plain") == 0) { + proxy = ISC_NM_PROXY_PLAIN; + } else { + UNREACHABLE(); + } + } + +#ifdef HAVE_LIBNGHTTP2 + if (http) { + CHECK(listenelt_http(http_server, family, do_tls, &tls_params, + tlsctx_cache, port, mctx, proxy, &delt)); + } +#endif /* HAVE_LIBNGHTTP2 */ + + if (!http) { + CHECK(ns_listenelt_create(mctx, port, NULL, family, do_tls, + &tls_params, tlsctx_cache, proxy, + &delt)); + } + + result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), config, + named_g_lctx, actx, mctx, family, + &delt->acl); + if (result != ISC_R_SUCCESS) { + ns_listenelt_destroy(delt); + return result; + } + *target = delt; + +cleanup: + return result; +} + +#ifdef HAVE_LIBNGHTTP2 +static isc_result_t +listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls, + const ns_listen_tls_params_t *tls_params, + isc_tlsctx_cache_t *tlsctx_cache, in_port_t port, + isc_mem_t *mctx, isc_nm_proxy_type_t proxy, + ns_listenelt_t **target) { + isc_result_t result = ISC_R_SUCCESS; + ns_listenelt_t *delt = NULL; + char **endpoints = NULL; + const cfg_obj_t *eplist = NULL; + const cfg_listelt_t *elt = NULL; + size_t len = 1, i = 0; + uint32_t max_clients = named_g_http_listener_clients; + uint32_t max_streams = named_g_http_streams_per_conn; + + REQUIRE(target != NULL && *target == NULL); + + if (tls) { + INSIST(tls_params != NULL); + INSIST((tls_params->key == NULL) == (tls_params->cert == NULL)); + } + + if (port == 0) { + port = tls ? named_g_httpsport : named_g_httpport; + } + + /* + * If "default" was used, we set up the default endpoint + * of "/dns-query". + */ + if (http != NULL) { + const cfg_obj_t *cfg_max_clients = NULL; + const cfg_obj_t *cfg_max_streams = NULL; + + if (cfg_map_get(http, "endpoints", &eplist) == ISC_R_SUCCESS) { + INSIST(eplist != NULL); + len = cfg_list_length(eplist, false); + } + + if (cfg_map_get(http, "listener-clients", &cfg_max_clients) == + ISC_R_SUCCESS) + { + INSIST(cfg_max_clients != NULL); + max_clients = cfg_obj_asuint32(cfg_max_clients); + } + + if (cfg_map_get(http, "streams-per-connection", + &cfg_max_streams) == ISC_R_SUCCESS) + { + INSIST(cfg_max_streams != NULL); + max_streams = cfg_obj_asuint32(cfg_max_streams); + } + } + + endpoints = isc_mem_allocate(mctx, sizeof(endpoints[0]) * len); + + if (http != NULL && eplist != NULL) { + for (elt = cfg_list_first(eplist); elt != NULL; + elt = cfg_list_next(elt)) + { + const cfg_obj_t *ep = cfg_listelt_value(elt); + const char *path = cfg_obj_asstring(ep); + endpoints[i++] = isc_mem_strdup(mctx, path); + } + } else { + endpoints[i++] = isc_mem_strdup(mctx, ISC_NM_HTTP_DEFAULT_PATH); + } + + INSIST(i == len); + + result = ns_listenelt_create_http( + mctx, port, NULL, family, tls, tls_params, tlsctx_cache, proxy, + endpoints, len, max_clients, max_streams, &delt); + if (result != ISC_R_SUCCESS) { + goto error; + } + + *target = delt; + + return result; +error: + if (delt != NULL) { + ns_listenelt_destroy(delt); + } + return result; +} +#endif /* HAVE_LIBNGHTTP2 */ + +isc_result_t +named_server_dumpstats(named_server_t *server) { + isc_result_t result; + FILE *fp = NULL; + + CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), + "could not open statistics dump file", server->statsfile); + + result = named_stats_dump(server, fp); + +cleanup: + if (fp != NULL) { + (void)isc_stdio_close(fp); + } + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpstats complete"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumpstats failed: %s", + isc_result_totext(result)); + } + return result; +} + +static isc_result_t +add_zone_tolist(dns_zone_t *zone, void *uap) { + struct dumpcontext *dctx = uap; + struct zonelistentry *zle; + + zle = isc_mem_get(dctx->mctx, sizeof *zle); + zle->zone = NULL; + dns_zone_attach(zone, &zle->zone); + ISC_LINK_INIT(zle, link); + ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); + return ISC_R_SUCCESS; +} + +static isc_result_t +add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { + struct viewlistentry *vle; + isc_result_t result = ISC_R_SUCCESS; + + /* + * Prevent duplicate views. + */ + for (vle = ISC_LIST_HEAD(dctx->viewlist); vle != NULL; + vle = ISC_LIST_NEXT(vle, link)) + { + if (vle->view == view) { + return ISC_R_SUCCESS; + } + } + + vle = isc_mem_get(dctx->mctx, sizeof *vle); + vle->view = NULL; + dns_view_attach(view, &vle->view); + ISC_LINK_INIT(vle, link); + ISC_LIST_INIT(vle->zonelist); + ISC_LIST_APPEND(dctx->viewlist, vle, link); + if (dctx->dumpzones) { + result = dns_view_apply(view, true, NULL, add_zone_tolist, + dctx); + } + return result; +} + +static void +dumpcontext_destroy(struct dumpcontext *dctx) { + struct viewlistentry *vle; + struct zonelistentry *zle; + + vle = ISC_LIST_HEAD(dctx->viewlist); + while (vle != NULL) { + ISC_LIST_UNLINK(dctx->viewlist, vle, link); + zle = ISC_LIST_HEAD(vle->zonelist); + while (zle != NULL) { + ISC_LIST_UNLINK(vle->zonelist, zle, link); + dns_zone_detach(&zle->zone); + isc_mem_put(dctx->mctx, zle, sizeof *zle); + zle = ISC_LIST_HEAD(vle->zonelist); + } + dns_view_detach(&vle->view); + isc_mem_put(dctx->mctx, vle, sizeof *vle); + vle = ISC_LIST_HEAD(dctx->viewlist); + } + if (dctx->version != NULL) { + dns_db_closeversion(dctx->db, &dctx->version, false); + } + if (dctx->db != NULL) { + dns_db_detach(&dctx->db); + } + if (dctx->cache != NULL) { + dns_db_detach(&dctx->cache); + } + if (dctx->fp != NULL) { + (void)isc_stdio_close(dctx->fp); + } + if (dctx->mdctx != NULL) { + dns_dumpctx_detach(&dctx->mdctx); + } + isc_mem_put(dctx->mctx, dctx, sizeof *dctx); +} + +static void +dumpdone(void *arg, isc_result_t result) { + struct dumpcontext *dctx = arg; + char buf[1024 + 32]; + const dns_master_style_t *style; + + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + if (dctx->mdctx != NULL) { + dns_dumpctx_detach(&dctx->mdctx); + } + if (dctx->view == NULL) { + dctx->view = ISC_LIST_HEAD(dctx->viewlist); + if (dctx->view == NULL) { + goto done; + } + INSIST(dctx->zone == NULL); + } else { + goto resume; + } +nextview: + fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); +resume: + if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) { + fprintf(dctx->fp, ";\n; Cache of view '%s' is shared as '%s'\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); + } else if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) + { + if (dctx->dumpexpired) { + style = &dns_master_style_cache_with_expired; + } else { + style = &dns_master_style_cache; + } + /* start cache dump */ + if (dctx->view->view->cachedb != NULL) { + dns_db_attach(dctx->view->view->cachedb, &dctx->cache); + } + if (dctx->cache != NULL) { + fprintf(dctx->fp, + ";\n; Cache dump of view '%s' (cache %s)\n;\n", + dctx->view->view->name, + dns_cache_getname(dctx->view->view->cache)); + result = dns_master_dumptostreamasync( + dctx->mctx, dctx->cache, NULL, style, dctx->fp, + named_g_mainloop, dumpdone, dctx, &dctx->mdctx); + if (result == ISC_R_SUCCESS) { + return; + } + if (result == ISC_R_NOTIMPLEMENTED) { + fprintf(dctx->fp, "; %s\n", + isc_result_totext(result)); + } else if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + } + + if ((dctx->dumpadb || dctx->dumpfail) && dctx->cache == NULL && + dctx->view->view->cachedb != NULL) + { + dns_db_attach(dctx->view->view->cachedb, &dctx->cache); + } + + if (dctx->cache != NULL) { + if (dctx->dumpadb) { + dns_adb_t *adb = NULL; + dns_view_getadb(dctx->view->view, &adb); + if (adb != NULL) { + dns_adb_dump(adb, dctx->fp); + dns_adb_detach(&adb); + } + } + if (dctx->dumpfail) { + dns_badcache_print(dctx->view->view->failcache, + "SERVFAIL cache", dctx->fp); + } + dns_db_detach(&dctx->cache); + } + if (dctx->dumpzones) { + style = &dns_master_style_full; + nextzone: + if (dctx->version != NULL) { + dns_db_closeversion(dctx->db, &dctx->version, false); + } + if (dctx->db != NULL) { + dns_db_detach(&dctx->db); + } + if (dctx->zone == NULL) { + dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); + } else { + dctx->zone = ISC_LIST_NEXT(dctx->zone, link); + } + if (dctx->zone != NULL) { + /* start zone dump */ + dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); + fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); + result = dns_zone_getdb(dctx->zone->zone, &dctx->db); + if (result != ISC_R_SUCCESS) { + fprintf(dctx->fp, "; %s\n", + isc_result_totext(result)); + goto nextzone; + } + dns_db_currentversion(dctx->db, &dctx->version); + result = dns_master_dumptostreamasync( + dctx->mctx, dctx->db, dctx->version, style, + dctx->fp, dns_zone_getloop(dctx->zone->zone), + dumpdone, dctx, &dctx->mdctx); + if (result == ISC_R_SUCCESS) { + return; + } + if (result == ISC_R_NOTIMPLEMENTED) { + fprintf(dctx->fp, "; %s\n", + isc_result_totext(result)); + result = ISC_R_SUCCESS; + POST(result); + goto nextzone; + } + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + } + } + if (dctx->view != NULL) { + dctx->view = ISC_LIST_NEXT(dctx->view, link); + if (dctx->view != NULL) { + goto nextview; + } + } +done: + fprintf(dctx->fp, "; Dump complete\n"); + result = isc_stdio_flush(dctx->fp); + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpdb complete"); + } +cleanup: + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumpdb failed: %s", isc_result_totext(result)); + } + dumpcontext_destroy(dctx); +} + +isc_result_t +named_server_dumpdb(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + struct dumpcontext *dctx = NULL; + dns_view_t *view; + isc_result_t result; + char *ptr; + const char *sep; + bool found; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + dctx = isc_mem_get(server->mctx, sizeof(*dctx)); + *dctx = (struct dumpcontext){ + .mctx = server->mctx, + .dumpcache = true, + .dumpadb = true, + .dumpfail = true, + .viewlist = ISC_LIST_INITIALIZER, + }; + + CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), + "could not open dump file", server->dumpfile); + + ptr = next_token(lex, NULL); + sep = (ptr == NULL) ? "" : ": "; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); + + if (ptr != NULL && strcmp(ptr, "-all") == 0) { + /* also dump zones */ + dctx->dumpzones = true; + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { + /* this is the default */ + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-expired") == 0) { + /* this is the same as -cache but includes expired data */ + dctx->dumpexpired = true; + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { + /* only dump zones, suppress caches */ + dctx->dumpadb = false; + dctx->dumpcache = false; + dctx->dumpfail = false; + dctx->dumpzones = true; + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { + /* only dump adb, suppress other caches */ + dctx->dumpcache = false; + dctx->dumpfail = false; + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { + /* only dump badcache, suppress other caches */ + dctx->dumpadb = false; + dctx->dumpcache = false; + dctx->dumpfail = false; + ptr = next_token(lex, NULL); + } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { + /* only dump servfail cache, suppress other caches */ + dctx->dumpadb = false; + dctx->dumpcache = false; + ptr = next_token(lex, NULL); + } + +nextview: + found = false; + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (ptr != NULL && strcmp(view->name, ptr) != 0) { + continue; + } + found = true; + CHECK(add_view_tolist(dctx, view)); + } + if (ptr != NULL) { + if (!found) { + CHECK(putstr(text, "view '")); + CHECK(putstr(text, ptr)); + CHECK(putstr(text, "' not found")); + CHECK(putnull(text)); + result = ISC_R_NOTFOUND; + dumpdone(dctx, result); + return result; + } + ptr = next_token(lex, NULL); + if (ptr != NULL) { + goto nextview; + } + } + dumpdone(dctx, ISC_R_SUCCESS); + return ISC_R_SUCCESS; + +cleanup: + dumpcontext_destroy(dctx); + return result; +} + +isc_result_t +named_server_dumpsecroots(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + dns_view_t *view; + dns_keytable_t *secroots = NULL; + dns_ntatable_t *ntatable = NULL; + isc_result_t result; + char *ptr; + FILE *fp = NULL; + isc_time_t now; + char tbuf[64]; + unsigned int used = isc_buffer_usedlength(*text); + bool first = true; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* "-" here means print the output instead of dumping to file */ + ptr = next_token(lex, text); + if (ptr != NULL && strcmp(ptr, "-") == 0) { + ptr = next_token(lex, text); + } else { + result = isc_stdio_open(server->secrootsfile, "w", &fp); + if (result != ISC_R_SUCCESS) { + (void)putstr(text, "could not open "); + (void)putstr(text, server->secrootsfile); + CHECKMF(result, "could not open secroots dump file", + server->secrootsfile); + } + } + + now = isc_time_now(); + isc_time_formattimestamp(&now, tbuf, sizeof(tbuf)); + CHECK(putstr(text, "secure roots as of ")); + CHECK(putstr(text, tbuf)); + CHECK(putstr(text, ":\n")); + used = isc_buffer_usedlength(*text); + + do { + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (ptr != NULL && strcmp(view->name, ptr) != 0) { + continue; + } + if (secroots != NULL) { + dns_keytable_detach(&secroots); + } + result = dns_view_getsecroots(view, &secroots); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + continue; + } + if (first || used != isc_buffer_usedlength(*text)) { + CHECK(putstr(text, "\n")); + first = false; + } + CHECK(putstr(text, " Start view ")); + CHECK(putstr(text, view->name)); + CHECK(putstr(text, "\n Secure roots:\n\n")); + used = isc_buffer_usedlength(*text); + CHECK(dns_keytable_totext(secroots, text)); + + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + result = dns_view_getntatable(view, &ntatable); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + continue; + } + if (used != isc_buffer_usedlength(*text)) { + CHECK(putstr(text, "\n")); + } + CHECK(putstr(text, " Negative trust anchors:\n\n")); + used = isc_buffer_usedlength(*text); + CHECK(dns_ntatable_totext(ntatable, NULL, text)); + } + + if (ptr != NULL) { + ptr = next_token(lex, text); + } + } while (ptr != NULL); + +cleanup: + if (secroots != NULL) { + dns_keytable_detach(&secroots); + } + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + + if (fp != NULL) { + if (used != isc_buffer_usedlength(*text)) { + (void)putstr(text, "\n"); + } + fprintf(fp, "%.*s", (int)isc_buffer_usedlength(*text), + (char *)isc_buffer_base(*text)); + isc_buffer_clear(*text); + (void)isc_stdio_close(fp); + } else if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumpsecroots complete"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumpsecroots failed: %s", + isc_result_totext(result)); + } + return result; +} + +isc_result_t +named_server_dumprecursing(named_server_t *server) { + FILE *fp = NULL; + dns_view_t *view; + isc_result_t result; + + CHECKMF(isc_stdio_open(server->recfile, "w", &fp), + "could not open dump file", server->recfile); + fprintf(fp, ";\n; Recursing Queries\n;\n"); + ns_interfacemgr_dumprecursing(fp, server->interfacemgr); + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + fprintf(fp, ";\n; Active fetch domains [view: %s]\n;\n", + view->name); + dns_resolver_dumpfetches(view->resolver, isc_statsformat_file, + fp); + } + + fprintf(fp, "; Dump complete\n"); + +cleanup: + if (fp != NULL) { + result = isc_stdio_close(fp); + } + if (result == ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumprecursing complete"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "dumprecursing failed: %s", + isc_result_totext(result)); + } + return result; +} + +isc_result_t +named_server_setdebuglevel(named_server_t *server, isc_lex_t *lex) { + char *ptr; + char *endp; + long newlevel; + + UNUSED(server); + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Look for the new level name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + if (named_g_debuglevel < 99) { + named_g_debuglevel++; + } + } else { + newlevel = strtol(ptr, &endp, 10); + if (*endp != '\0' || newlevel < 0 || newlevel > 99) { + return ISC_R_RANGE; + } + named_g_debuglevel = (unsigned int)newlevel; + } + isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "debug level is now %u", named_g_debuglevel); + return ISC_R_SUCCESS; +} + +isc_result_t +named_server_validation(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + char *ptr; + dns_view_t *view; + bool changed = false; + isc_result_t result; + bool enable = true, set = true, first = true; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find out what we are to do. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || + !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) + { + enable = true; + } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || + !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) + { + enable = false; + } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { + set = false; + } else { + return DNS_R_SYNTAX; + } + + /* Look for the view name. */ + ptr = next_token(lex, text); + + isc_loopmgr_pause(named_g_loopmgr); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if ((ptr != NULL && strcasecmp(ptr, view->name) != 0) || + strcasecmp("_bind", view->name) == 0) + { + continue; + } + + if (set) { + CHECK(dns_view_flushcache(view, false)); + view->enablevalidation = enable; + changed = true; + } else { + if (!first) { + CHECK(putstr(text, "\n")); + } + CHECK(putstr(text, "DNSSEC validation is ")); + CHECK(putstr(text, view->enablevalidation + ? "enabled" + : "disabled")); + CHECK(putstr(text, " (view ")); + CHECK(putstr(text, view->name)); + CHECK(putstr(text, ")")); + first = false; + } + } + CHECK(putnull(text)); + + if (!set) { + result = ISC_R_SUCCESS; + } else if (changed) { + result = ISC_R_SUCCESS; + } else { + result = ISC_R_FAILURE; + } +cleanup: + isc_loopmgr_resume(named_g_loopmgr); + return result; +} + +isc_result_t +named_server_flushcache(named_server_t *server, isc_lex_t *lex) { + char *ptr; + dns_view_t *view; + bool flushed; + bool found; + isc_result_t result; + named_cache_t *nsc; + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Look for the view name. */ + ptr = next_token(lex, NULL); + + isc_loopmgr_pause(named_g_loopmgr); + flushed = true; + found = false; + + /* + * Flushing a cache is tricky when caches are shared by multiple views. + * We first identify which caches should be flushed in the local cache + * list, flush these caches, and then update other views that refer to + * the flushed cache DB. + */ + if (ptr != NULL) { + /* + * Mark caches that need to be flushed. This is an O(#view^2) + * operation in the very worst case, but should be normally + * much more lightweight because only a few (most typically just + * one) views will match. + */ + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (strcasecmp(ptr, view->name) != 0) { + continue; + } + found = true; + for (nsc = ISC_LIST_HEAD(server->cachelist); + nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) + { + if (nsc->cache == view->cache) { + break; + } + } + INSIST(nsc != NULL); + nsc->needflush = true; + } + } else { + found = true; + } + + /* Perform flush */ + for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) + { + if (ptr != NULL && !nsc->needflush) { + continue; + } + nsc->needflush = true; + result = dns_view_flushcache(nsc->primaryview, false); + if (result != ISC_R_SUCCESS) { + flushed = false; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "flushing cache in view '%s' failed: %s", + nsc->primaryview->name, + isc_result_totext(result)); + } + } + + /* + * Fix up views that share a flushed cache: let the views update the + * cache DB they're referring to. This could also be an expensive + * operation, but should typically be marginal: the inner loop is only + * necessary for views that share a cache, and if there are many such + * views the number of shared cache should normally be small. + * A worst case is that we have n views and n/2 caches, each shared by + * two views. Then this will be a O(n^2/4) operation. + */ + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (!dns_view_iscacheshared(view)) { + continue; + } + for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) + { + if (!nsc->needflush || nsc->cache != view->cache) { + continue; + } + result = dns_view_flushcache(view, true); + if (result != ISC_R_SUCCESS) { + flushed = false; + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "fixing cache in view '%s' " + "failed: %s", + view->name, isc_result_totext(result)); + } + } + } + + /* Cleanup the cache list. */ + for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; + nsc = ISC_LIST_NEXT(nsc, link)) + { + nsc->needflush = false; + } + + if (flushed && found) { + if (ptr != NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "flushing cache in view '%s' succeeded", + ptr); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "flushing caches in all views succeeded"); + } + result = ISC_R_SUCCESS; + } else { + if (!found) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "flushing cache in view '%s' failed: " + "view not found", + ptr); + result = ISC_R_NOTFOUND; + } else { + result = ISC_R_FAILURE; + } + } + isc_loopmgr_resume(named_g_loopmgr); + return result; +} + +isc_result_t +named_server_flushnode(named_server_t *server, isc_lex_t *lex, bool tree) { + char *ptr, *viewname; + char target[DNS_NAME_FORMATSIZE]; + dns_view_t *view; + bool flushed; + bool found; + isc_result_t result; + isc_buffer_t b; + dns_fixedname_t fixed; + dns_name_t *name; + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find the domain name to flush. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + strlcpy(target, ptr, DNS_NAME_FORMATSIZE); + isc_buffer_constinit(&b, target, strlen(target)); + isc_buffer_add(&b, strlen(target)); + name = dns_fixedname_initname(&fixed); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + + /* Look for the view name. */ + viewname = next_token(lex, NULL); + + isc_loopmgr_pause(named_g_loopmgr); + flushed = true; + found = false; + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (viewname != NULL && strcasecmp(viewname, view->name) != 0) { + continue; + } + found = true; + /* + * It's a little inefficient to try flushing name for all views + * if some of the views share a single cache. But since the + * operation is lightweight we prefer simplicity here. + */ + result = dns_view_flushnode(view, name, tree); + if (result != ISC_R_SUCCESS) { + flushed = false; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "flushing %s '%s' in cache view '%s' " + "failed: %s", + tree ? "tree" : "name", target, + view->name, isc_result_totext(result)); + } + } + if (flushed && found) { + if (viewname != NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "flushing %s '%s' in cache view '%s' " + "succeeded", + tree ? "tree" : "name", target, viewname); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "flushing %s '%s' in all cache views " + "succeeded", + tree ? "tree" : "name", target); + } + result = ISC_R_SUCCESS; + } else { + if (!found) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "flushing %s '%s' in cache view '%s' " + "failed: view not found", + tree ? "tree" : "name", target, viewname); + } + result = ISC_R_FAILURE; + } + isc_loopmgr_resume(named_g_loopmgr); + return result; +} + +isc_result_t +named_server_status(named_server_t *server, isc_buffer_t **text) { + isc_result_t result; + unsigned int zonecount, xferrunning, xferdeferred, xferfirstrefresh; + unsigned int soaqueries, automatic; + const char *ob = "", *cb = "", *alt = ""; + char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char line[1024], hostname[256]; + named_reload_t reload_status; + + REQUIRE(text != NULL); + + if (named_g_server->version_set) { + ob = " ("; + cb = ")"; + if (named_g_server->version == NULL) { + alt = "version.bind/txt/ch disabled"; + } else { + alt = named_g_server->version; + } + } + zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); + xferrunning = dns_zonemgr_getcount(server->zonemgr, + DNS_ZONESTATE_XFERRUNNING); + xferdeferred = dns_zonemgr_getcount(server->zonemgr, + DNS_ZONESTATE_XFERDEFERRED); + xferfirstrefresh = dns_zonemgr_getcount(server->zonemgr, + DNS_ZONESTATE_XFERFIRSTREFRESH); + soaqueries = dns_zonemgr_getcount(server->zonemgr, + DNS_ZONESTATE_SOAQUERY); + automatic = dns_zonemgr_getcount(server->zonemgr, + DNS_ZONESTATE_AUTOMATIC); + + isc_time_formathttptimestamp(&named_g_boottime, boottime, + sizeof(boottime)); + isc_time_formathttptimestamp(&named_g_configtime, configtime, + sizeof(configtime)); + + snprintf(line, sizeof(line), "version: %s%s %s%s%s\n", + PACKAGE_STRING, PACKAGE_DESCRIPTION, PACKAGE_SRCID, ob, alt, + cb); + CHECK(putstr(text, line)); + + if (gethostname(hostname, sizeof(hostname)) == 0) { + strlcpy(hostname, "localhost", sizeof(hostname)); + } + snprintf(line, sizeof(line), "running on %s: %s\n", hostname, + named_os_uname()); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "boot time: %s\n", boottime); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "last configured: %s\n", configtime); + CHECK(putstr(text, line)); + + if (named_g_chrootdir != NULL) { + snprintf(line, sizeof(line), "configuration file: %s (%s%s)\n", + named_g_conffile, named_g_chrootdir, named_g_conffile); + } else { + snprintf(line, sizeof(line), "configuration file: %s\n", + named_g_conffile); + } + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "CPUs found: %u\n", named_g_cpus_detected); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "worker threads: %u\n", named_g_cpus); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n", + zonecount, automatic); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "debug level: %u\n", named_g_debuglevel); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "xfers first refresh: %u\n", + xferfirstrefresh); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "soa queries in progress: %u\n", + soaqueries); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "query logging is %s\n", + ns_server_getoption(server->sctx, NS_SERVER_LOGQUERIES) + ? "ON" + : "OFF"); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "response logging is %s\n", + ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES) + ? "ON" + : "OFF"); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "memory profiling is %s\n", + named_server_getmemprof()); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", + isc_quota_getused(&server->sctx->recursionquota), + isc_quota_getsoft(&server->sctx->recursionquota), + isc_quota_getmax(&server->sctx->recursionquota)); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "recursive high-water: %u\n", + (unsigned int)ns_stats_get_counter( + server->sctx->nsstats, + ns_statscounter_recurshighwater)); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "tcp clients: %u/%u\n", + isc_quota_getused(&server->sctx->tcpquota), + isc_quota_getmax(&server->sctx->tcpquota)); + CHECK(putstr(text, line)); + + snprintf(line, sizeof(line), "TCP high-water: %u\n", + (unsigned int)ns_stats_get_counter( + server->sctx->nsstats, ns_statscounter_tcphighwater)); + CHECK(putstr(text, line)); + + reload_status = atomic_load(&server->reload_status); + if (reload_status != NAMED_RELOAD_DONE) { + snprintf(line, sizeof(line), "reload/reconfig %s\n", + reload_status == NAMED_RELOAD_FAILED ? "failed" + : "in progress"); + CHECK(putstr(text, line)); + } + + CHECK(putstr(text, "server is up and running")); + CHECK(putnull(text)); + + return ISC_R_SUCCESS; +cleanup: + return result; +} + +isc_result_t +named_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { + isc_result_t result; + char *ptr; + unsigned long count; + unsigned long i; + const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + ptr = next_token(lex, text); + if (ptr == NULL) { + count = 26; + } else { + count = strtoul(ptr, NULL, 10); + } + + CHECK(isc_buffer_reserve(*text, count)); + for (i = 0; i < count; i++) { + CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)])); + } + + CHECK(putnull(text)); + +cleanup: + return result; +} + +/* + * Act on a "sign" or "loadkeys" command from the command channel. + */ +isc_result_t +named_server_rekey(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_zonetype_t type; + uint16_t keyopts; + bool fullsign = false; + char *ptr; + + REQUIRE(text != NULL); + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcasecmp(ptr, NAMED_COMMAND_SIGN) == 0) { + fullsign = true; + } + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, NULL, &zone, NULL, text, false); + if (result != ISC_R_SUCCESS) { + return result; + } + if (zone == NULL) { + return ISC_R_UNEXPECTEDEND; /* XXX: or do all zones? */ + } + + type = dns_zone_gettype(zone); + if (type != dns_zone_primary) { + dns_zone_detach(&zone); + return DNS_R_NOTPRIMARY; + } + + keyopts = dns_zone_getkeyopts(zone); + + /* + * "rndc loadkeys" requires a "dnssec-policy". + */ + if ((keyopts & DNS_ZONEKEY_ALLOW) == 0) { + result = ISC_R_NOPERM; + } else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign) { + result = ISC_R_NOPERM; + } else { + dns_zone_rekey(zone, fullsign); + } + + dns_zone_detach(&zone); + return result; +} + +/* + * Act on a "sync" command from the command channel. + */ +static isc_result_t +synczone(dns_zone_t *zone, void *uap) { + bool cleanup = *(bool *)uap; + isc_result_t result; + dns_zone_t *raw = NULL; + char *journal; + + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + synczone(raw, uap); + dns_zone_detach(&raw); + } + + result = dns_zone_flush(zone); + if (result != ISC_R_SUCCESS) { + cleanup = false; + } + if (cleanup) { + journal = dns_zone_getjournal(zone); + if (journal != NULL) { + (void)isc_file_remove(journal); + } + } + + return result; +} + +isc_result_t +named_server_sync(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { + isc_result_t result, tresult; + dns_view_t *view = NULL; + dns_zone_t *zone = NULL; + char classstr[DNS_RDATACLASS_FORMATSIZE]; + char zonename[DNS_NAME_FORMATSIZE]; + const char *vname = NULL, *sep = NULL, *arg = NULL; + bool cleanup = false; + + REQUIRE(text != NULL); + + (void)next_token(lex, text); + + arg = next_token(lex, text); + if (arg != NULL && + (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) + { + cleanup = true; + arg = next_token(lex, text); + } + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, arg, &zone, NULL, text, false); + if (result != ISC_R_SUCCESS) { + return result; + } + + if (zone == NULL) { + isc_loopmgr_pause(named_g_loopmgr); + tresult = ISC_R_SUCCESS; + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + result = dns_view_apply(view, false, NULL, synczone, + &cleanup); + if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) + { + tresult = result; + } + } + isc_loopmgr_resume(named_g_loopmgr); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumping all zones%s: %s", + cleanup ? ", removing journal files" : "", + isc_result_totext(result)); + return tresult; + } + + isc_loopmgr_pause(named_g_loopmgr); + result = synczone(zone, &cleanup); + isc_loopmgr_resume(named_g_loopmgr); + + view = dns_zone_getview(zone); + if (strcmp(view->name, "_default") == 0 || + strcmp(view->name, "_bind") == 0) + { + vname = ""; + sep = ""; + } else { + vname = view->name; + sep = " "; + } + dns_rdataclass_format(dns_zone_getclass(zone), classstr, + sizeof(classstr)); + dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, + ISC_LOG_INFO, "sync: dumping zone '%s/%s'%s%s%s: %s", zonename, + classstr, sep, vname, cleanup ? ", removing journal file" : "", + isc_result_totext(result)); + dns_zone_detach(&zone); + return result; +} + +/* + * Act on a "freeze" or "thaw" command from the command channel. + */ +isc_result_t +named_server_freeze(named_server_t *server, bool freeze, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result, tresult; + dns_zone_t *mayberaw = NULL, *raw = NULL; + dns_zonetype_t type; + char classstr[DNS_RDATACLASS_FORMATSIZE]; + char zonename[DNS_NAME_FORMATSIZE]; + dns_view_t *view; + const char *vname, *sep; + bool frozen; + const char *msg = NULL; + + REQUIRE(text != NULL); + + result = zone_from_args(server, lex, NULL, &mayberaw, NULL, text, true); + if (result != ISC_R_SUCCESS) { + return result; + } + if (mayberaw == NULL) { + isc_loopmgr_pause(named_g_loopmgr); + tresult = ISC_R_SUCCESS; + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + result = dns_view_freezezones(view, freeze); + if (result != ISC_R_SUCCESS && tresult == ISC_R_SUCCESS) + { + tresult = result; + } + } + isc_loopmgr_resume(named_g_loopmgr); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s all zones: %s", + freeze ? "freezing" : "thawing", + isc_result_totext(tresult)); + return tresult; + } + dns_zone_getraw(mayberaw, &raw); + if (raw != NULL) { + dns_zone_detach(&mayberaw); + dns_zone_attach(raw, &mayberaw); + dns_zone_detach(&raw); + } + type = dns_zone_gettype(mayberaw); + if (type != dns_zone_primary) { + dns_zone_detach(&mayberaw); + return DNS_R_NOTPRIMARY; + } + + if (freeze && !dns_zone_isdynamic(mayberaw, true)) { + dns_zone_detach(&mayberaw); + return DNS_R_NOTDYNAMIC; + } + + isc_loopmgr_pause(named_g_loopmgr); + frozen = dns_zone_getupdatedisabled(mayberaw); + if (freeze) { + if (frozen) { + msg = "WARNING: The zone was already frozen.\n" + "Someone else may be editing it or " + "it may still be re-loading."; + result = DNS_R_FROZEN; + } + if (result == ISC_R_SUCCESS) { + result = dns_zone_flush(mayberaw); + if (result != ISC_R_SUCCESS) { + msg = "Flushing the zone updates to " + "disk failed."; + } + } + if (result == ISC_R_SUCCESS) { + dns_zone_setupdatedisabled(mayberaw, freeze); + } + } else { + if (frozen) { + result = dns_zone_loadandthaw(mayberaw); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + msg = "The zone reload and thaw was " + "successful."; + result = ISC_R_SUCCESS; + break; + case DNS_R_CONTINUE: + msg = "A zone reload and thaw was started.\n" + "Check the logs to see the result."; + result = ISC_R_SUCCESS; + break; + default: + break; + } + } + } + isc_loopmgr_resume(named_g_loopmgr); + + if (msg != NULL) { + (void)putstr(text, msg); + (void)putnull(text); + } + + view = dns_zone_getview(mayberaw); + if (strcmp(view->name, "_default") == 0 || + strcmp(view->name, "_bind") == 0) + { + vname = ""; + sep = ""; + } else { + vname = view->name; + sep = " "; + } + dns_rdataclass_format(dns_zone_getclass(mayberaw), classstr, + sizeof(classstr)); + dns_name_format(dns_zone_getorigin(mayberaw), zonename, + sizeof(zonename)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s zone '%s/%s'%s%s: %s", + freeze ? "freezing" : "thawing", zonename, classstr, sep, + vname, isc_result_totext(result)); + dns_zone_detach(&mayberaw); + return result; +} + +#ifdef HAVE_LIBSCF +/* + * This function adds a message for rndc to echo if named + * is managed by smf and is also running chroot. + */ +isc_result_t +named_smf_add_message(isc_buffer_t **text) { + REQUIRE(text != NULL); + + return putstr(text, "use svcadm(1M) to manage named"); +} +#endif /* HAVE_LIBSCF */ + +#ifndef HAVE_LMDB + +/* + * Emit a comment at the top of the nzf file containing the viewname + * Expects the fp to already be open for writing + */ +#define HEADER1 "# New zone file for view: " +#define HEADER2 \ + "\n# This file contains configuration for zones added by\n" \ + "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" +static isc_result_t +add_comment(FILE *fp, const char *viewname) { + isc_result_t result; + CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); + CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); + CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); +cleanup: + return result; +} + +static void +dumpzone(void *arg, const char *buf, int len) { + FILE *fp = arg; + + (void)isc_stdio_write(buf, len, 1, fp, NULL); +} + +static isc_result_t +nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { + isc_result_t result; + off_t offset; + FILE *fp = NULL; + bool offsetok = false; + + LOCK(&view->new_zone_lock); + + CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); + CHECK(isc_stdio_seek(fp, 0, SEEK_END)); + + CHECK(isc_stdio_tell(fp, &offset)); + offsetok = true; + if (offset == 0) { + CHECK(add_comment(fp, view->name)); + } + + CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); + cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); + CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); + CHECK(isc_stdio_flush(fp)); + result = isc_stdio_close(fp); + fp = NULL; + +cleanup: + if (fp != NULL) { + (void)isc_stdio_close(fp); + if (offsetok) { + isc_result_t result2; + + result2 = isc_file_truncate(view->new_zone_file, + offset); + if (result2 != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error truncating NZF file '%s' " + "during rollback from append: " + "%s", + view->new_zone_file, + isc_result_totext(result2)); + } + } + } + UNLOCK(&view->new_zone_lock); + return result; +} + +static isc_result_t +nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { + const cfg_obj_t *zl = NULL; + cfg_list_t *list; + const cfg_listelt_t *elt; + + FILE *fp = NULL; + char tmp[1024]; + isc_result_t result; + + result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, + sizeof(tmp)); + if (result == ISC_R_SUCCESS) { + result = isc_file_openunique(tmp, &fp); + } + if (result != ISC_R_SUCCESS) { + return result; + } + + cfg_map_get(config, "zone", &zl); + if (!cfg_obj_islist(zl)) { + CHECK(ISC_R_FAILURE); + } + + list = UNCONST(&zl->value.list); + + CHECK(add_comment(fp, view->name)); /* force a comment */ + + for (elt = ISC_LIST_HEAD(*list); elt != NULL; + elt = ISC_LIST_NEXT(elt, link)) + { + const cfg_obj_t *zconfig = cfg_listelt_value(elt); + + CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); + cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); + CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); + } + + CHECK(isc_stdio_flush(fp)); + result = isc_stdio_close(fp); + fp = NULL; + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + CHECK(isc_file_rename(tmp, view->new_zone_file)); + return result; + +cleanup: + if (fp != NULL) { + (void)isc_stdio_close(fp); + } + (void)isc_file_remove(tmp); + return result; +} + +static isc_result_t +load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { + isc_result_t result; + + /* The new zone file may not exist. That is OK. */ + if (!isc_file_exists(view->new_zone_file)) { + return ISC_R_SUCCESS; + } + + /* + * Parse the configuration in the NZF file. This may be called in + * multiple views, so we reset the parser each time. + */ + cfg_parser_reset(named_g_addparser); + result = cfg_parse_file(named_g_addparser, view->new_zone_file, + &cfg_type_addzoneconf, &nzcfg->nzf_config); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error parsing NZF file '%s': %s", + view->new_zone_file, isc_result_totext(result)); + } + + return result; +} +#else /* HAVE_LMDB */ + +static void +nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { + dns_fixedname_t fixed; + + dns_fixedname_init(&fixed); + dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); + dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen); + + key->mv_data = namebuf; + key->mv_size = strlen(namebuf); +} + +static void +dumpzone(void *arg, const char *buf, int len) { + ns_dzarg_t *dzarg = arg; + isc_result_t result; + + REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); + + result = putmem(dzarg->text, buf, len); + if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { + dzarg->result = result; + } +} + +static isc_result_t +nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone, + const cfg_obj_t *zconfig) { + isc_result_t result; + int status; + dns_view_t *view; + bool commit = false; + isc_buffer_t *text = NULL; + char namebuf[1024]; + MDB_val key, data; + ns_dzarg_t dzarg; + + view = dns_zone_getview(zone); + + nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf)); + + if (zconfig == NULL) { + /* We're deleting the zone from the database */ + status = mdb_del(*txnp, dbi, &key, NULL); + if (status != MDB_SUCCESS && status != MDB_NOTFOUND) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error deleting zone %s " + "from NZD database: %s", + namebuf, mdb_strerror(status)); + result = ISC_R_FAILURE; + goto cleanup; + } else if (status != MDB_NOTFOUND) { + commit = true; + } + } else { + /* We're creating or overwriting the zone */ + const cfg_obj_t *zoptions; + + isc_buffer_allocate(view->mctx, &text, 256); + + zoptions = cfg_tuple_get(zconfig, "options"); + if (zoptions == NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Unable to get options from config in " + "nzd_save()"); + result = ISC_R_FAILURE; + goto cleanup; + } + + dzarg.magic = DZARG_MAGIC; + dzarg.text = &text; + dzarg.result = ISC_R_SUCCESS; + cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); + if (dzarg.result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error writing zone config to " + "buffer in nzd_save(): %s", + isc_result_totext(dzarg.result)); + result = dzarg.result; + goto cleanup; + } + + data.mv_data = isc_buffer_base(text); + data.mv_size = isc_buffer_usedlength(text); + + status = mdb_put(*txnp, dbi, &key, &data, 0); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error inserting zone in " + "NZD database: %s", + mdb_strerror(status)); + result = ISC_R_FAILURE; + goto cleanup; + } + + commit = true; + } + + result = ISC_R_SUCCESS; + +cleanup: + if (!commit || result != ISC_R_SUCCESS) { + (void)mdb_txn_abort(*txnp); + } else { + status = mdb_txn_commit(*txnp); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error committing " + "NZD database: %s", + mdb_strerror(status)); + result = ISC_R_FAILURE; + } + } + *txnp = NULL; + + if (text != NULL) { + isc_buffer_free(&text); + } + + return result; +} + +/* + * Check whether the new zone database for 'view' can be opened for writing. + * + * Caller must hold 'view->new_zone_lock'. + */ +static isc_result_t +nzd_writable(dns_view_t *view) { + isc_result_t result = ISC_R_SUCCESS; + int status; + MDB_dbi dbi; + MDB_txn *txn = NULL; + + REQUIRE(view != NULL); + + status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "mdb_txn_begin: %s", mdb_strerror(status)); + return ISC_R_FAILURE; + } + + status = mdb_dbi_open(txn, NULL, 0, &dbi); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "mdb_dbi_open: %s", mdb_strerror(status)); + result = ISC_R_FAILURE; + } + + mdb_txn_abort(txn); + return result; +} + +/* + * Open the new zone database for 'view' and start a transaction for it. + * + * Caller must hold 'view->new_zone_lock'. + */ +static isc_result_t +nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { + int status; + MDB_txn *txn = NULL; + + REQUIRE(view != NULL); + REQUIRE(txnp != NULL && *txnp == NULL); + REQUIRE(dbi != NULL); + + status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "mdb_txn_begin: %s", mdb_strerror(status)); + goto cleanup; + } + + status = mdb_dbi_open(txn, NULL, 0, dbi); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "mdb_dbi_open: %s", mdb_strerror(status)); + goto cleanup; + } + + *txnp = txn; + +cleanup: + if (status != MDB_SUCCESS) { + if (txn != NULL) { + mdb_txn_abort(txn); + } + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} + +/* + * nzd_env_close() and nzd_env_reopen are a kluge to address the + * problem of an NZD file possibly being created before we drop + * root privileges. + */ +static void +nzd_env_close(dns_view_t *view) { + const char *dbpath = NULL; + char dbpath_copy[PATH_MAX]; + char lockpath[PATH_MAX]; + int status, ret; + + if (view->new_zone_dbenv == NULL) { + return; + } + + status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); + INSIST(status == MDB_SUCCESS); + snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); + strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); + mdb_env_close((MDB_env *)view->new_zone_dbenv); + + /* + * Database files must be owned by the eventual user, not by root. + */ + ret = chown(dbpath_copy, named_os_uid(), -1); + UNUSED(ret); + + /* + * Some platforms need the lockfile not to exist when we reopen the + * environment. + */ + (void)isc_file_remove(lockpath); + + view->new_zone_dbenv = NULL; +} + +static isc_result_t +nzd_env_reopen(dns_view_t *view) { + isc_result_t result; + MDB_env *env = NULL; + int status; + + if (view->new_zone_db == NULL) { + return ISC_R_SUCCESS; + } + + nzd_env_close(view); + + status = mdb_env_create(&env); + if (status != MDB_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, + "mdb_env_create failed: %s", + mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + + if (view->new_zone_mapsize != 0ULL) { + status = mdb_env_set_mapsize(env, view->new_zone_mapsize); + if (status != MDB_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, + "mdb_env_set_mapsize failed: %s", + mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + } + + status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); + if (status != MDB_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, + "mdb_env_open of '%s' failed: %s", + view->new_zone_db, mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + + view->new_zone_dbenv = env; + env = NULL; + result = ISC_R_SUCCESS; + +cleanup: + if (env != NULL) { + mdb_env_close(env); + } + return result; +} + +/* + * If 'commit' is true, commit the new zone database transaction pointed to by + * 'txnp'; otherwise, abort that transaction. + * + * Caller must hold 'view->new_zone_lock' for the view that the transaction + * pointed to by 'txnp' was started for. + */ +static isc_result_t +nzd_close(MDB_txn **txnp, bool commit) { + isc_result_t result = ISC_R_SUCCESS; + int status; + + REQUIRE(txnp != NULL); + + if (*txnp != NULL) { + if (commit) { + status = mdb_txn_commit(*txnp); + if (status != MDB_SUCCESS) { + result = ISC_R_FAILURE; + } + } else { + mdb_txn_abort(*txnp); + } + *txnp = NULL; + } + + return result; +} + +/* + * If there's an existing NZF file, load it and migrate its data + * to the NZD. + * + * Caller must hold view->new_zone_lock. + */ +static isc_result_t +load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { + isc_result_t result; + cfg_obj_t *nzf_config = NULL; + int status; + isc_buffer_t *text = NULL; + bool commit = false; + const cfg_obj_t *zonelist; + const cfg_listelt_t *element; + char tempname[PATH_MAX]; + MDB_txn *txn = NULL; + MDB_dbi dbi; + MDB_val key, data; + ns_dzarg_t dzarg; + + UNUSED(nzcfg); + + /* + * If NZF file doesn't exist, or NZD DB exists and already + * has data, return without attempting migration. + */ + if (!isc_file_exists(view->new_zone_file)) { + result = ISC_R_SUCCESS; + goto cleanup; + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "Migrating zones from NZF file '%s' to " + "NZD database '%s'", + view->new_zone_file, view->new_zone_db); + /* + * Instead of blindly copying lines, we parse the NZF file using + * the configuration parser, because it validates it against the + * config type, giving us a guarantee that valid configuration + * will be written to DB. + */ + cfg_parser_reset(named_g_addparser); + result = cfg_parse_file(named_g_addparser, view->new_zone_file, + &cfg_type_addzoneconf, &nzf_config); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error parsing NZF file '%s': %s", + view->new_zone_file, isc_result_totext(result)); + goto cleanup; + } + + zonelist = NULL; + CHECK(cfg_map_get(nzf_config, "zone", &zonelist)); + if (!cfg_obj_islist(zonelist)) { + CHECK(ISC_R_FAILURE); + } + + CHECK(nzd_open(view, 0, &txn, &dbi)); + + isc_buffer_allocate(view->mctx, &text, 256); + + for (element = cfg_list_first(zonelist); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *zconfig; + const cfg_obj_t *zoptions; + char zname[DNS_NAME_FORMATSIZE]; + dns_fixedname_t fname; + dns_name_t *name; + const char *origin; + isc_buffer_t b; + + zconfig = cfg_listelt_value(element); + + origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + if (origin == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + /* Normalize zone name */ + isc_buffer_constinit(&b, origin, strlen(origin)); + isc_buffer_add(&b, strlen(origin)); + name = dns_fixedname_initname(&fname); + CHECK(dns_name_fromtext(name, &b, dns_rootname, + DNS_NAME_DOWNCASE, NULL)); + dns_name_format(name, zname, sizeof(zname)); + + key.mv_data = zname; + key.mv_size = strlen(zname); + + zoptions = cfg_tuple_get(zconfig, "options"); + if (zoptions == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + isc_buffer_clear(text); + dzarg.magic = DZARG_MAGIC; + dzarg.text = &text; + dzarg.result = ISC_R_SUCCESS; + cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg); + if (dzarg.result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error writing zone config to " + "buffer in load_nzf(): %s", + isc_result_totext(result)); + result = dzarg.result; + goto cleanup; + } + + data.mv_data = isc_buffer_base(text); + data.mv_size = isc_buffer_usedlength(text); + + status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); + if (status != MDB_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Error inserting zone in " + "NZD database: %s", + mdb_strerror(status)); + result = ISC_R_FAILURE; + goto cleanup; + } + + commit = true; + } + + result = ISC_R_SUCCESS; + + /* + * Leaving the NZF file in place is harmless as we won't use it + * if an NZD database is found for the view. But we rename NZF file + * to a backup name here. + */ + strlcpy(tempname, view->new_zone_file, sizeof(tempname)); + if (strlen(tempname) < sizeof(tempname) - 1) { + strlcat(tempname, "~", sizeof(tempname)); + isc_file_rename(view->new_zone_file, tempname); + } + +cleanup: + if (result != ISC_R_SUCCESS) { + (void)nzd_close(&txn, false); + } else { + result = nzd_close(&txn, commit); + } + + if (text != NULL) { + isc_buffer_free(&text); + } + + if (nzf_config != NULL) { + cfg_obj_destroy(named_g_addparser, &nzf_config); + } + + return result; +} +#endif /* HAVE_LMDB */ + +static isc_result_t +newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, + cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, + bool *redirectp, isc_buffer_t **text) { + isc_result_t result; + isc_buffer_t argbuf; + bool redirect = false; + cfg_obj_t *zoneconf = NULL; + const cfg_obj_t *zlist = NULL; + const cfg_obj_t *zoneobj = NULL; + const cfg_obj_t *zoptions = NULL; + const cfg_obj_t *obj = NULL; + const char *viewname = NULL; + dns_rdataclass_t rdclass; + dns_view_t *view = NULL; + const char *bn = NULL; + + REQUIRE(viewp != NULL && *viewp == NULL); + REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); + REQUIRE(zoneconfp != NULL && *zoneconfp == NULL); + REQUIRE(redirectp != NULL); + + /* Try to parse the argument string */ + isc_buffer_init(&argbuf, command, (unsigned int)strlen(command)); + isc_buffer_add(&argbuf, strlen(command)); + + if (strncasecmp(command, "add", 3) == 0) { + bn = "addzone"; + } else if (strncasecmp(command, "mod", 3) == 0) { + bn = "modzone"; + } else { + UNREACHABLE(); + } + + /* + * Convert the "addzone" or "modzone" to just "zone", for + * the benefit of the parser + */ + isc_buffer_forward(&argbuf, 3); + + cfg_parser_reset(named_g_addparser); + CHECK(cfg_parse_buffer(named_g_addparser, &argbuf, bn, 0, + &cfg_type_addzoneconf, 0, &zoneconf)); + CHECK(cfg_map_get(zoneconf, "zone", &zlist)); + if (!cfg_obj_islist(zlist)) { + CHECK(ISC_R_FAILURE); + } + + /* For now we only support adding one zone at a time */ + zoneobj = cfg_listelt_value(cfg_list_first(zlist)); + + /* Check the zone type for ones that are not supported by addzone. */ + zoptions = cfg_tuple_get(zoneobj, "options"); + + obj = NULL; + (void)cfg_map_get(zoptions, "type", &obj); + if (obj == NULL) { + (void)cfg_map_get(zoptions, "in-view", &obj); + if (obj != NULL) { + (void)putstr(text, "'in-view' zones not supported by "); + (void)putstr(text, bn); + } else { + (void)putstr(text, "zone type not specified"); + } + CHECK(ISC_R_FAILURE); + } + + if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 || + strcasecmp(cfg_obj_asstring(obj), "forward") == 0) + { + (void)putstr(text, "'"); + (void)putstr(text, cfg_obj_asstring(obj)); + (void)putstr(text, "' zones not supported by "); + (void)putstr(text, bn); + CHECK(ISC_R_FAILURE); + } + + if (strcasecmp(cfg_obj_asstring(obj), "redirect") == 0) { + redirect = true; + } + + /* Make sense of optional class argument */ + obj = cfg_tuple_get(zoneobj, "class"); + CHECK(named_config_getclass(obj, dns_rdataclass_in, &rdclass)); + + /* Make sense of optional view argument */ + obj = cfg_tuple_get(zoneobj, "view"); + if (obj && cfg_obj_isstring(obj)) { + viewname = cfg_obj_asstring(obj); + } + if (viewname == NULL || *viewname == '\0') { + viewname = "_default"; + } + result = dns_viewlist_find(&server->viewlist, viewname, rdclass, &view); + if (result == ISC_R_NOTFOUND) { + (void)putstr(text, "no matching view found for '"); + (void)putstr(text, viewname); + (void)putstr(text, "'"); + goto cleanup; + } else if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + *viewp = view; + *zoneobjp = zoneobj; + *zoneconfp = zoneconf; + *redirectp = redirect; + + return ISC_R_SUCCESS; + +cleanup: + if (zoneconf != NULL) { + cfg_obj_destroy(named_g_addparser, &zoneconf); + } + if (view != NULL) { + dns_view_detach(&view); + } + + return result; +} + +static isc_result_t +delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, + const dns_name_t *zname, nzfwriter_t nzfwriter) { + isc_result_t result = ISC_R_NOTFOUND; + const cfg_listelt_t *elt = NULL; + const cfg_obj_t *zl = NULL; + cfg_list_t *list; + dns_fixedname_t myfixed; + dns_name_t *myname; + + REQUIRE(view != NULL); + REQUIRE(pctx != NULL); + REQUIRE(config != NULL); + REQUIRE(zname != NULL); + + LOCK(&view->new_zone_lock); + + cfg_map_get(config, "zone", &zl); + + if (!cfg_obj_islist(zl)) { + CHECK(ISC_R_FAILURE); + } + + list = UNCONST(&zl->value.list); + + myname = dns_fixedname_initname(&myfixed); + + for (elt = ISC_LIST_HEAD(*list); elt != NULL; + elt = ISC_LIST_NEXT(elt, link)) + { + const cfg_obj_t *zconf = cfg_listelt_value(elt); + const char *zn; + cfg_listelt_t *e; + + zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name")); + result = dns_name_fromstring(myname, zn, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS || !dns_name_equal(zname, myname)) { + continue; + } + + e = UNCONST(elt); + ISC_LIST_UNLINK(*list, e, link); + cfg_obj_destroy(pctx, &e->obj); + isc_mem_put(pctx->mctx, e, sizeof(*e)); + result = ISC_R_SUCCESS; + break; + } + + /* + * Write config to NZF file if appropriate + */ + if (nzfwriter != NULL && view->new_zone_file != NULL) { + result = nzfwriter(config, view); + } + +cleanup: + UNLOCK(&view->new_zone_lock); + return result; +} + +static isc_result_t +do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, + dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, + bool redirect, isc_buffer_t **text) { + isc_result_t result, tresult; + dns_zone_t *zone = NULL; +#ifndef HAVE_LMDB + FILE *fp = NULL; + bool cleanup_config = false; +#else /* HAVE_LMDB */ + MDB_txn *txn = NULL; + MDB_dbi dbi; + bool locked = false; + + UNUSED(zoneconf); +#endif + + /* Zone shouldn't already exist */ + if (redirect) { + result = (view->redirect == NULL) ? ISC_R_NOTFOUND + : ISC_R_EXISTS; + } else { + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); + if (result == ISC_R_SUCCESS) { + result = ISC_R_EXISTS; + } + } + if (result != ISC_R_NOTFOUND) { + goto cleanup; + } + + isc_loopmgr_pause(named_g_loopmgr); + +#ifndef HAVE_LMDB + /* + * Make sure we can open the configuration save file + */ + result = isc_stdio_open(view->new_zone_file, "a", &fp); + if (result != ISC_R_SUCCESS) { + isc_loopmgr_resume(named_g_loopmgr); + TCHECK(putstr(text, "unable to create '")); + TCHECK(putstr(text, view->new_zone_file)); + TCHECK(putstr(text, "': ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } + + (void)isc_stdio_close(fp); + fp = NULL; +#else /* HAVE_LMDB */ + LOCK(&view->new_zone_lock); + locked = true; + /* Make sure we can open the NZD database */ + result = nzd_writable(view); + if (result != ISC_R_SUCCESS) { + isc_loopmgr_resume(named_g_loopmgr); + TCHECK(putstr(text, "unable to open NZD database for '")); + TCHECK(putstr(text, view->new_zone_db)); + TCHECK(putstr(text, "'")); + result = ISC_R_FAILURE; + goto cleanup; + } +#endif /* HAVE_LMDB */ + + /* Mark view unfrozen and configure zone */ + dns_view_thaw(view); + result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, + &server->viewlist, &server->kasplist, + &server->keystorelist, cfg->actx, true, false, + false, false); + dns_view_freeze(view); + + isc_loopmgr_resume(named_g_loopmgr); + + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "configure_zone failed: ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } + + /* Is it there yet? */ + if (redirect) { + if (view->redirect == NULL) { + CHECK(ISC_R_NOTFOUND); + } + dns_zone_attach(view->redirect, &zone); + } else { + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "added new zone was not found: %s", + isc_result_totext(result)); + goto cleanup; + } + } + +#ifndef HAVE_LMDB + /* + * If there wasn't a previous newzone config, just save the one + * we've created. If there was a previous one, merge the new + * zone into it. + */ + if (cfg->nzf_config == NULL) { + cfg_obj_attach(zoneconf, &cfg->nzf_config); + } else { + cfg_obj_t *z = UNCONST(zoneobj); + CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, + "zone")); + } + cleanup_config = true; +#endif /* HAVE_LMDB */ + + /* + * Load the zone from the master file. If this fails, we'll + * need to undo the configuration we've done already. + */ + result = dns_zone_load(zone, true); + if (result != ISC_R_SUCCESS) { + dns_db_t *dbp = NULL; + + TCHECK(putstr(text, "dns_zone_loadnew failed: ")); + TCHECK(putstr(text, isc_result_totext(result))); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "addzone failed; reverting."); + + /* If the zone loaded partially, unload it */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Remove the zone from the zone table */ + dns_view_delzone(view, zone); + goto cleanup; + } + + /* Flag the zone as having been added at runtime */ + dns_zone_setadded(zone, true); + +#ifdef HAVE_LMDB + /* Save the new zone configuration into the NZD */ + CHECK(nzd_open(view, 0, &txn, &dbi)); + CHECK(nzd_save(&txn, dbi, zone, zoneobj)); +#else /* ifdef HAVE_LMDB */ + /* Append the zone configuration to the NZF */ + result = nzf_append(view, zoneobj); +#endif /* HAVE_LMDB */ + +cleanup: + +#ifndef HAVE_LMDB + if (fp != NULL) { + (void)isc_stdio_close(fp); + } + if (result != ISC_R_SUCCESS && cleanup_config) { + tresult = delete_zoneconf(view, cfg->add_parser, + cfg->nzf_config, name, NULL); + RUNTIME_CHECK(tresult == ISC_R_SUCCESS); + } +#else /* HAVE_LMDB */ + if (txn != NULL) { + (void)nzd_close(&txn, false); + } + if (locked) { + UNLOCK(&view->new_zone_lock); + } +#endif /* HAVE_LMDB */ + + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +static isc_result_t +do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, + dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, + bool redirect, isc_buffer_t **text) { + isc_result_t result, tresult; + dns_zone_t *zone = NULL; + bool added; +#ifndef HAVE_LMDB + FILE *fp = NULL; + cfg_obj_t *z; +#else /* HAVE_LMDB */ + MDB_txn *txn = NULL; + MDB_dbi dbi; + bool locked = false; +#endif /* HAVE_LMDB */ + + /* Zone must already exist */ + if (redirect) { + if (view->redirect != NULL) { + dns_zone_attach(view->redirect, &zone); + result = ISC_R_SUCCESS; + } else { + result = ISC_R_NOTFOUND; + } + } else { + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); + } + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + added = dns_zone_getadded(zone); + dns_zone_detach(&zone); + +#ifndef HAVE_LMDB + cfg = (ns_cfgctx_t *)view->new_zone_config; + if (cfg == NULL) { + TCHECK(putstr(text, "new zone config is not set")); + CHECK(ISC_R_FAILURE); + } +#endif /* ifndef HAVE_LMDB */ + + isc_loopmgr_pause(named_g_loopmgr); + +#ifndef HAVE_LMDB + /* Make sure we can open the configuration save file */ + result = isc_stdio_open(view->new_zone_file, "a", &fp); + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "unable to open '")); + TCHECK(putstr(text, view->new_zone_file)); + TCHECK(putstr(text, "': ")); + TCHECK(putstr(text, isc_result_totext(result))); + isc_loopmgr_resume(named_g_loopmgr); + goto cleanup; + } + (void)isc_stdio_close(fp); + fp = NULL; +#else /* HAVE_LMDB */ + LOCK(&view->new_zone_lock); + locked = true; + /* Make sure we can open the NZD database */ + result = nzd_writable(view); + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "unable to open NZD database for '")); + TCHECK(putstr(text, view->new_zone_db)); + TCHECK(putstr(text, "'")); + result = ISC_R_FAILURE; + isc_loopmgr_resume(named_g_loopmgr); + goto cleanup; + } +#endif /* HAVE_LMDB */ + + /* Reconfigure the zone */ + dns_view_thaw(view); + result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, + &server->viewlist, &server->kasplist, + &server->keystorelist, cfg->actx, true, false, + false, true); + dns_view_freeze(view); + + isc_loopmgr_resume(named_g_loopmgr); + + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "configure_zone failed: ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } + + /* Is it there yet? */ + if (redirect) { + if (view->redirect == NULL) { + CHECK(ISC_R_NOTFOUND); + } + dns_zone_attach(view->redirect, &zone); + } else { + CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); + } + +#ifndef HAVE_LMDB + /* Remove old zone from configuration (and NZF file if applicable) */ + if (added) { + result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, + dns_zone_getorigin(zone), + nzf_writeconf); + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "former zone configuration " + "not deleted: ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } + } +#endif /* HAVE_LMDB */ + + if (!added) { + if (cfg->vconfig == NULL) { + result = delete_zoneconf( + view, cfg->conf_parser, cfg->config, + dns_zone_getorigin(zone), NULL); + } else { + const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, + "options"); + result = delete_zoneconf( + view, cfg->conf_parser, voptions, + dns_zone_getorigin(zone), NULL); + } + + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "former zone configuration " + "not deleted: ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } + } + + /* Load the zone from the master file if it needs reloading. */ + result = dns_zone_load(zone, true); + + /* + * Dynamic zones need no reloading, so we can pass this result. + */ + if (result == DNS_R_DYNAMIC) { + result = ISC_R_SUCCESS; + } + + if (result != ISC_R_SUCCESS) { + dns_db_t *dbp = NULL; + + TCHECK(putstr(text, "failed to load zone '")); + TCHECK(putstr(text, zname)); + TCHECK(putstr(text, "': ")); + TCHECK(putstr(text, isc_result_totext(result))); + TCHECK(putstr(text, "\nThe zone is no longer being served. ")); + TCHECK(putstr(text, "Use 'rndc addzone' to correct\n")); + TCHECK(putstr(text, "the problem and restore service.")); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "modzone failed; removing zone."); + + /* If the zone loaded partially, unload it */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Remove the zone from the zone table */ + dns_view_delzone(view, zone); + goto cleanup; + } + +#ifndef HAVE_LMDB + /* Store the new zone configuration; also in NZF if applicable */ + z = UNCONST(zoneobj); + CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); +#endif /* HAVE_LMDB */ + + if (added) { +#ifdef HAVE_LMDB + CHECK(nzd_open(view, 0, &txn, &dbi)); + CHECK(nzd_save(&txn, dbi, zone, zoneobj)); +#else /* ifdef HAVE_LMDB */ + result = nzf_append(view, zoneobj); + if (result != ISC_R_SUCCESS) { + TCHECK(putstr(text, "\nNew zone config not saved: ")); + TCHECK(putstr(text, isc_result_totext(result))); + goto cleanup; + } +#endif /* HAVE_LMDB */ + + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zname)); + TCHECK(putstr(text, "' reconfigured.")); + } else { + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zname)); + TCHECK(putstr(text, "' must also be reconfigured in\n")); + TCHECK(putstr(text, "named.conf to make changes permanent.")); + } + +cleanup: + +#ifndef HAVE_LMDB + if (fp != NULL) { + (void)isc_stdio_close(fp); + } +#else /* HAVE_LMDB */ + if (txn != NULL) { + (void)nzd_close(&txn, false); + } + if (locked) { + UNLOCK(&view->new_zone_lock); + } +#endif /* HAVE_LMDB */ + + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +/* + * Act on an "addzone" or "modzone" command from the command channel. + */ +isc_result_t +named_server_changezone(named_server_t *server, char *command, + isc_buffer_t **text) { + isc_result_t result; + bool addzone; + bool redirect = false; + ns_cfgctx_t *cfg = NULL; + cfg_obj_t *zoneconf = NULL; + const cfg_obj_t *zoneobj = NULL; + const char *zonename; + dns_view_t *view = NULL; + isc_buffer_t buf; + dns_fixedname_t fname; + dns_name_t *dnsname; + + REQUIRE(text != NULL); + + if (strncasecmp(command, "add", 3) == 0) { + addzone = true; + } else { + INSIST(strncasecmp(command, "mod", 3) == 0); + addzone = false; + } + + CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, + &redirect, text)); + + /* Are we accepting new zones in this view? */ +#ifdef HAVE_LMDB + if (view->new_zone_db == NULL) +#else /* ifdef HAVE_LMDB */ + if (view->new_zone_file == NULL) +#endif /* HAVE_LMDB */ + { + (void)putstr(text, "Not allowing new zones in view '"); + (void)putstr(text, view->name); + (void)putstr(text, "'"); + result = ISC_R_NOPERM; + goto cleanup; + } + + cfg = (ns_cfgctx_t *)view->new_zone_config; + if (cfg == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); + isc_buffer_constinit(&buf, zonename, strlen(zonename)); + isc_buffer_add(&buf, strlen(zonename)); + + dnsname = dns_fixedname_initname(&fname); + CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, 0, NULL)); + + if (redirect) { + if (!dns_name_equal(dnsname, dns_rootname)) { + (void)putstr(text, "redirect zones must be called " + "\".\""); + CHECK(ISC_R_FAILURE); + } + } + + if (addzone) { + CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, + redirect, text)); + } else { + CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, + redirect, text)); + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "%s zone %s in view %s via %s", + addzone ? "added" : "updated", zonename, view->name, + addzone ? NAMED_COMMAND_ADDZONE : NAMED_COMMAND_MODZONE); + + /* Changing a zone counts as reconfiguration */ + named_g_configtime = isc_time_now(); + +cleanup: + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + if (zoneconf != NULL) { + cfg_obj_destroy(named_g_addparser, &zoneconf); + } + if (view != NULL) { + dns_view_detach(&view); + } + + return result; +} + +static bool +inuse(const char *file, bool first, isc_buffer_t **text) { + if (file != NULL && isc_file_exists(file)) { + if (first) { + (void)putstr(text, "The following files were in use " + "and may now be removed:\n"); + } else { + (void)putstr(text, "\n"); + } + (void)putstr(text, file); + (void)putnull(text); + return false; + } + return first; +} + +typedef struct { + dns_zone_t *zone; + bool cleanup; +} ns_dzctx_t; + +/* + * Carry out a zone deletion scheduled by named_server_delzone(). + */ +static void +rmzone(void *arg) { + ns_dzctx_t *dz = (ns_dzctx_t *)arg; + dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; + dns_catz_zone_t *catz = NULL; + char zonename[DNS_NAME_FORMATSIZE]; + dns_view_t *view = NULL; + ns_cfgctx_t *cfg = NULL; + dns_db_t *dbp = NULL; + bool added; + isc_result_t result; +#ifdef HAVE_LMDB + MDB_txn *txn = NULL; + MDB_dbi dbi; +#endif /* ifdef HAVE_LMDB */ + + REQUIRE(dz != NULL); + + /* Dig out configuration for this zone */ + zone = dz->zone; + view = dns_zone_getview(zone); + cfg = (ns_cfgctx_t *)view->new_zone_config; + dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "deleting zone %s in view %s via delzone", zonename, + view->name); + + /* + * Remove the zone from configuration (and NZF file if applicable) + * (If this is a catalog zone member then nzf_config can be NULL) + */ + added = dns_zone_getadded(zone); + catz = dns_zone_get_parentcatz(zone); + + if (added && catz == NULL && cfg != NULL) { +#ifdef HAVE_LMDB + /* Make sure we can open the NZD database */ + LOCK(&view->new_zone_lock); + result = nzd_open(view, 0, &txn, &dbi); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "unable to open NZD database for '%s'", + view->new_zone_db); + } else { + result = nzd_save(&txn, dbi, zone, NULL); + } + + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "unable to delete zone configuration: %s", + isc_result_totext(result)); + } + + if (txn != NULL) { + (void)nzd_close(&txn, false); + } + UNLOCK(&view->new_zone_lock); +#else /* ifdef HAVE_LMDB */ + result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, + dns_zone_getorigin(zone), + nzf_writeconf); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "unable to delete zone configuration: %s", + isc_result_totext(result)); + } +#endif /* HAVE_LMDB */ + } + + if (!added && cfg != NULL) { + if (cfg->vconfig != NULL) { + const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, + "options"); + result = delete_zoneconf( + view, cfg->conf_parser, voptions, + dns_zone_getorigin(zone), NULL); + } else { + result = delete_zoneconf( + view, cfg->conf_parser, cfg->config, + dns_zone_getorigin(zone), NULL); + } + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "unable to delete zone configuration: %s", + isc_result_totext(result)); + } + } + + /* Unload zone database */ + if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(zone); + } + + /* Clean up stub/secondary zone files if requested to do so */ + dns_zone_getraw(zone, &raw); + mayberaw = (raw != NULL) ? raw : zone; + + if (added && dz->cleanup) { + const char *file; + + file = dns_zone_getfile(mayberaw); + result = isc_file_remove(file); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + + file = dns_zone_getjournal(mayberaw); + result = isc_file_remove(file); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + + if (zone != mayberaw) { + file = dns_zone_getfile(zone); + result = isc_file_remove(file); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + + file = dns_zone_getjournal(zone); + result = isc_file_remove(file); + if (result != ISC_R_SUCCESS) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + } + } + + if (raw != NULL) { + dns_zone_detach(&raw); + } + dns_zone_detach(&zone); + isc_mem_put(named_g_mctx, dz, sizeof(*dz)); +} + +/* + * Act on a "delzone" command from the command channel. + */ +isc_result_t +named_server_delzone(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result, tresult; + dns_zone_t *zone = NULL; + dns_zone_t *raw = NULL; + dns_zone_t *mayberaw; + dns_view_t *view = NULL; + char zonename[DNS_NAME_FORMATSIZE]; + bool cleanup = false; + const char *ptr; + bool added; + ns_dzctx_t *dz = NULL; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find out what we are to do. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { + cleanup = true; + ptr = next_token(lex, text); + } + + CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, false)); + if (zone == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } + + INSIST(zonename != NULL); + + /* Is this a policy zone? */ + if (dns_zone_get_rpz_num(zone) != DNS_RPZ_INVALID_NUM) { + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zonename)); + TCHECK(putstr(text, + "' cannot be deleted: response-policy zone.")); + result = ISC_R_FAILURE; + goto cleanup; + } + + view = dns_zone_getview(zone); + if (dns_zone_gettype(zone) == dns_zone_redirect) { + dns_zone_detach(&view->redirect); + } else { + CHECK(dns_view_delzone(view, zone)); + } + + /* Send cleanup event */ + dz = isc_mem_get(named_g_mctx, sizeof(*dz)); + *dz = (ns_dzctx_t){ + .cleanup = cleanup, + }; + dns_zone_attach(zone, &dz->zone); + isc_async_run(dns_zone_getloop(zone), rmzone, dz); + + /* Inform user about cleaning up stub/secondary zone files */ + dns_zone_getraw(zone, &raw); + mayberaw = (raw != NULL) ? raw : zone; + + added = dns_zone_getadded(zone); + if (!added) { + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zonename)); + TCHECK(putstr(text, "' is no longer active and will be " + "deleted.\n")); + TCHECK(putstr(text, "To keep it from returning ")); + TCHECK(putstr(text, "when the server is restarted, it\n")); + TCHECK(putstr(text, "must also be removed from named.conf.")); + } else if (cleanup) { + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zonename)); + TCHECK(putstr(text, "' and associated files will be deleted.")); + } else if (dns_zone_gettype(mayberaw) == dns_zone_secondary || + dns_zone_gettype(mayberaw) == dns_zone_mirror || + dns_zone_gettype(mayberaw) == dns_zone_stub) + { + bool first; + const char *file; + + TCHECK(putstr(text, "zone '")); + TCHECK(putstr(text, zonename)); + TCHECK(putstr(text, "' will be deleted.")); + + file = dns_zone_getfile(mayberaw); + first = inuse(file, true, text); + + file = dns_zone_getjournal(mayberaw); + first = inuse(file, first, text); + + if (zone != mayberaw) { + file = dns_zone_getfile(zone); + first = inuse(file, first, text); + + file = dns_zone_getjournal(zone); + (void)inuse(file, first, text); + } + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "zone %s scheduled for removal via delzone", zonename); + + /* Removing a zone counts as reconfiguration */ + named_g_configtime = isc_time_now(); + + result = ISC_R_SUCCESS; + +cleanup: + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + if (raw != NULL) { + dns_zone_detach(&raw); + } + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +static const cfg_obj_t * +find_name_in_list_from_map(const cfg_obj_t *config, + const char *map_key_for_list, const char *name, + bool redirect) { + const cfg_obj_t *list = NULL; + const cfg_listelt_t *element; + const cfg_obj_t *obj = NULL; + dns_fixedname_t fixed1, fixed2; + dns_name_t *name1 = NULL, *name2 = NULL; + isc_result_t result; + + if (strcmp(map_key_for_list, "zone") == 0) { + name1 = dns_fixedname_initname(&fixed1); + name2 = dns_fixedname_initname(&fixed2); + result = dns_name_fromstring(name1, name, dns_rootname, 0, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + } + + cfg_map_get(config, map_key_for_list, &list); + for (element = cfg_list_first(list); element != NULL; + element = cfg_list_next(element)) + { + const char *vname; + + obj = cfg_listelt_value(element); + INSIST(obj != NULL); + vname = cfg_obj_asstring(cfg_tuple_get(obj, "name")); + if (vname == NULL) { + obj = NULL; + continue; + } + + if (name1 != NULL) { + result = dns_name_fromstring(name2, vname, dns_rootname, + 0, NULL); + if (result == ISC_R_SUCCESS && + dns_name_equal(name1, name2)) + { + const cfg_obj_t *zoptions; + const cfg_obj_t *typeobj = NULL; + zoptions = cfg_tuple_get(obj, "options"); + + if (zoptions != NULL) { + cfg_map_get(zoptions, "type", &typeobj); + } + if (redirect && typeobj != NULL && + strcasecmp(cfg_obj_asstring(typeobj), + "redirect") == 0) + { + break; + } else if (!redirect) { + break; + } + } + } else if (strcasecmp(vname, name) == 0) { + break; + } + + obj = NULL; + } + + return obj; +} + +static void +emitzone(void *arg, const char *buf, int len) { + ns_dzarg_t *dzarg = arg; + isc_result_t result; + + REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC)); + result = putmem(dzarg->text, buf, len); + if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) { + dzarg->result = result; + } +} + +/* + * Act on a "showzone" command from the command channel. + */ +isc_result_t +named_server_showzone(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result; + const cfg_obj_t *vconfig = NULL, *zconfig = NULL; + char zonename[DNS_NAME_FORMATSIZE]; + const cfg_obj_t *map; + dns_view_t *view = NULL; + dns_zone_t *zone = NULL; + ns_cfgctx_t *cfg = NULL; +#ifdef HAVE_LMDB + cfg_obj_t *nzconfig = NULL; +#endif /* HAVE_LMDB */ + bool added, redirect; + ns_dzarg_t dzarg; + + REQUIRE(text != NULL); + + /* Parse parameters */ + CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); + if (zone == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } + + redirect = dns_zone_gettype(zone) == dns_zone_redirect; + added = dns_zone_getadded(zone); + view = dns_zone_getview(zone); + dns_zone_detach(&zone); + + cfg = (ns_cfgctx_t *)view->new_zone_config; + if (cfg == NULL) { + result = ISC_R_FAILURE; + goto cleanup; + } + + if (!added) { + /* Find the view statement */ + vconfig = find_name_in_list_from_map(cfg->config, "view", + view->name, false); + + /* Find the zone statement */ + if (vconfig != NULL) { + map = cfg_tuple_get(vconfig, "options"); + } else { + map = cfg->config; + } + + zconfig = find_name_in_list_from_map(map, "zone", zonename, + redirect); + } + +#ifndef HAVE_LMDB + if (zconfig == NULL && cfg->nzf_config != NULL) { + zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", + zonename, redirect); + } +#else /* HAVE_LMDB */ + if (zconfig == NULL) { + const cfg_obj_t *zlist = NULL; + CHECK(get_newzone_config(view, zonename, &nzconfig)); + CHECK(cfg_map_get(nzconfig, "zone", &zlist)); + if (!cfg_obj_islist(zlist)) { + CHECK(ISC_R_FAILURE); + } + + zconfig = cfg_listelt_value(cfg_list_first(zlist)); + } +#endif /* HAVE_LMDB */ + + if (zconfig == NULL) { + CHECK(ISC_R_NOTFOUND); + } + + CHECK(putstr(text, "zone ")); + dzarg.magic = DZARG_MAGIC; + dzarg.text = text; + dzarg.result = ISC_R_SUCCESS; + cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); + CHECK(dzarg.result); + + CHECK(putstr(text, ";")); + + result = ISC_R_SUCCESS; + +cleanup: +#ifdef HAVE_LMDB + if (nzconfig != NULL) { + cfg_obj_destroy(named_g_addparser, &nzconfig); + } +#endif /* HAVE_LMDB */ + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; +} + +static void +newzone_cfgctx_destroy(void **cfgp) { + ns_cfgctx_t *cfg; + + REQUIRE(cfgp != NULL && *cfgp != NULL); + + cfg = *cfgp; + + if (cfg->conf_parser != NULL) { + if (cfg->config != NULL) { + cfg_obj_destroy(cfg->conf_parser, &cfg->config); + } + if (cfg->vconfig != NULL) { + cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig); + } + cfg_parser_destroy(&cfg->conf_parser); + } + if (cfg->add_parser != NULL) { + if (cfg->nzf_config != NULL) { + cfg_obj_destroy(cfg->add_parser, &cfg->nzf_config); + } + cfg_parser_destroy(&cfg->add_parser); + } + + if (cfg->actx != NULL) { + cfg_aclconfctx_detach(&cfg->actx); + } + + isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); + *cfgp = NULL; +} + +isc_result_t +named_server_signing(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result = ISC_R_SUCCESS; + dns_zone_t *zone = NULL; + dns_name_t *origin; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *version = NULL; + dns_rdatatype_t privatetype; + dns_rdataset_t privset; + bool first = true; + bool list = false, clear = false; + bool chain = false; + bool setserial = false; + bool resalt = false; + uint32_t serial = 0; + char keystr[DNS_SECALG_FORMATSIZE + 7]; /* <5-digit keyid>/ */ + unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; + unsigned char salt[255]; + const char *ptr; + size_t n; + bool kasp = false; + + REQUIRE(text != NULL); + + dns_rdataset_init(&privset); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find out what we are to do. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcasecmp(ptr, "-list") == 0) { + list = true; + } else if ((strcasecmp(ptr, "-clear") == 0) || + (strcasecmp(ptr, "-clean") == 0)) + { + clear = true; + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + strlcpy(keystr, ptr, sizeof(keystr)); + } else if (strcasecmp(ptr, "-nsec3param") == 0) { + char hashbuf[64], flagbuf[64], iterbuf[64]; + char nbuf[256]; + + chain = true; + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcasecmp(ptr, "none") == 0) { + hash = 0; + } else { + strlcpy(hashbuf, ptr, sizeof(hashbuf)); + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + strlcpy(flagbuf, ptr, sizeof(flagbuf)); + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + strlcpy(iterbuf, ptr, sizeof(iterbuf)); + n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", hashbuf, + flagbuf, iterbuf); + if (n == sizeof(nbuf)) { + return ISC_R_NOSPACE; + } + n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); + if (n != 3U) { + return ISC_R_BADNUMBER; + } + + if (hash > 0xffU || flags > 0xffU || + iter > dns_nsec3_maxiterations()) + { + return ISC_R_RANGE; + } + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } else if (strcasecmp(ptr, "auto") == 0) { + /* Auto-generate a random salt. + * XXXMUKS: This currently uses the + * minimum recommended length by RFC + * 5155 (64 bits). It should be made + * configurable. + */ + saltlen = 8; + resalt = true; + } else if (strcmp(ptr, "-") != 0) { + isc_buffer_t buf; + + isc_buffer_init(&buf, salt, sizeof(salt)); + CHECK(isc_hex_decodestring(ptr, &buf)); + saltlen = isc_buffer_usedlength(&buf); + } + } + } else if (strcasecmp(ptr, "-serial") == 0) { + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + CHECK(isc_parse_uint32(&serial, ptr, 10)); + setserial = true; + } else { + CHECK(DNS_R_SYNTAX); + } + + CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); + if (zone == NULL) { + CHECK(ISC_R_UNEXPECTEDEND); + } + + if (dns_zone_getkasp(zone) != NULL) { + kasp = true; + } + + if (clear) { + CHECK(dns_zone_keydone(zone, keystr)); + (void)putstr(text, "request queued"); + (void)putnull(text); + } else if (chain && !kasp) { + CHECK(dns_zone_setnsec3param( + zone, (uint8_t)hash, (uint8_t)flags, iter, + (uint8_t)saltlen, salt, true, resalt)); + (void)putstr(text, "nsec3param request queued"); + (void)putnull(text); + } else if (setserial) { + CHECK(dns_zone_setserial(zone, serial)); + (void)putstr(text, "serial request queued"); + (void)putnull(text); + } else if (list) { + privatetype = dns_zone_getprivatetype(zone); + origin = dns_zone_getorigin(zone); + CHECK(dns_zone_getdb(zone, &db)); + CHECK(dns_db_findnode(db, origin, false, &node)); + dns_db_currentversion(db, &version); + + result = dns_db_findrdataset(db, node, version, privatetype, + dns_rdatatype_none, 0, &privset, + NULL); + if (result == ISC_R_NOTFOUND) { + (void)putstr(text, "No signing records found"); + (void)putnull(text); + result = ISC_R_SUCCESS; + goto cleanup; + } + + for (result = dns_rdataset_first(&privset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&privset)) + { + dns_rdata_t priv = DNS_RDATA_INIT; + /* + * In theory, the output buffer could hold a full RDATA + * record which is 16-bit and then some text around + * it + */ + char output[UINT16_MAX + BUFSIZ]; + isc_buffer_t buf; + + dns_rdataset_current(&privset, &priv); + + isc_buffer_init(&buf, output, sizeof(output)); + CHECK(dns_private_totext(&priv, &buf)); + if (!first) { + CHECK(putstr(text, "\n")); + } + CHECK(putstr(text, output)); + first = false; + } + if (!first) { + CHECK(putnull(text)); + } + + if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } + } else if (kasp) { + (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec " + "command instead"); + (void)putnull(text); + } + +cleanup: + if (dns_rdataset_isassociated(&privset)) { + dns_rdataset_disassociate(&privset); + } + if (node != NULL) { + dns_db_detachnode(db, &node); + } + if (version != NULL) { + dns_db_closeversion(db, &version, false); + } + if (db != NULL) { + dns_db_detach(&db); + } + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +static bool +argcheck(char *cmd, const char *full) { + size_t l; + + if (cmd == NULL || cmd[0] != '-') { + return false; + } + + cmd++; + l = strlen(cmd); + if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) { + return false; + } + + return true; +} + +isc_result_t +named_server_dnssec(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result = ISC_R_SUCCESS; + dns_zone_t *zone = NULL; + dns_kasp_t *kasp = NULL; + dns_dnsseckeylist_t keys; + dns_dnsseckey_t *key; + char *ptr, *zonetext = NULL; + const char *msg = NULL; + /* variables for -checkds */ + bool checkds = false, dspublish = false; + /* variables for -rollover */ + bool rollover = false; + /* variables for -key */ + bool use_keyid = false; + dns_keytag_t keyid = 0; + uint8_t algorithm = 0; + /* variables for -status */ + bool status = false; + char output[4096]; + isc_stdtime_t now, when; + isc_time_t timenow, timewhen; + dns_db_t *db = NULL; + dns_dbversion_t *version = NULL; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find out what we are to do. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Initialize current time and key list. */ + timenow = isc_time_now(); + now = isc_time_seconds(&timenow); + when = now; + + ISC_LIST_INIT(keys); + + if (strcasecmp(ptr, "-status") == 0) { + status = true; + } else if (strcasecmp(ptr, "-rollover") == 0) { + rollover = true; + } else if (strcasecmp(ptr, "-checkds") == 0) { + checkds = true; + } else { + CHECK(DNS_R_SYNTAX); + } + + if (rollover || checkds) { + /* Check for options */ + for (;;) { + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "Bad format"; + CHECK(ISC_R_UNEXPECTEDEND); + } else if (argcheck(ptr, "alg")) { + isc_consttextregion_t alg; + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "No key algorithm specified"; + CHECK(ISC_R_UNEXPECTEDEND); + } + alg.base = ptr; + alg.length = strlen(alg.base); + result = dns_secalg_fromtext( + &algorithm, (isc_textregion_t *)&alg); + if (result != ISC_R_SUCCESS) { + msg = "Bad algorithm"; + CHECK(DNS_R_SYNTAX); + } + continue; + } else if (argcheck(ptr, "key")) { + uint16_t id; + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "No key identifier specified"; + CHECK(ISC_R_UNEXPECTEDEND); + } + CHECK(isc_parse_uint16(&id, ptr, 10)); + keyid = (dns_keytag_t)id; + use_keyid = true; + continue; + } else if (argcheck(ptr, "when")) { + uint32_t tw; + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "No time specified"; + CHECK(ISC_R_UNEXPECTEDEND); + } + CHECK(dns_time32_fromtext(ptr, &tw)); + when = (isc_stdtime_t)tw; + continue; + } else if (ptr[0] == '-') { + msg = "Unknown option"; + CHECK(DNS_R_SYNTAX); + } else if (checkds) { + /* + * No arguments provided, so we must be + * parsing "published|withdrawn". + */ + if (strcasecmp(ptr, "published") == 0) { + dspublish = true; + } else if (strcasecmp(ptr, "withdrawn") != 0) { + CHECK(DNS_R_SYNTAX); + } + } else if (rollover) { + /* + * No arguments provided, so we must be + * parsing the zone. + */ + zonetext = ptr; + } + break; + } + + if (rollover && !use_keyid) { + msg = "Key id is required when scheduling rollover"; + CHECK(DNS_R_SYNTAX); + } + + if (algorithm > 0 && !use_keyid) { + msg = "Key id is required when setting algorithm"; + CHECK(DNS_R_SYNTAX); + } + } + + /* Get zone. */ + CHECK(zone_from_args(server, lex, zonetext, &zone, NULL, text, false)); + if (zone == NULL) { + msg = "Zone not found"; + CHECK(ISC_R_UNEXPECTEDEND); + } + + /* Trailing garbage? */ + ptr = next_token(lex, text); + if (ptr != NULL) { + msg = "Too many arguments"; + CHECK(DNS_R_SYNTAX); + } + + /* Get dnssec-policy. */ + kasp = dns_zone_getkasp(zone); + if (kasp == NULL) { + msg = "Zone does not have dnssec-policy"; + goto cleanup; + } + + /* Get DNSSEC keys. */ + CHECK(dns_zone_getdb(zone, &db)); + dns_db_currentversion(db, &version); + LOCK(&kasp->lock); + result = dns_zone_getdnsseckeys(zone, db, version, now, &keys); + UNLOCK(&kasp->lock); + if (result != ISC_R_SUCCESS) { + if (result != ISC_R_NOTFOUND) { + goto cleanup; + } + } + + if (status) { + /* + * Output the DNSSEC status of the key and signing policy. + */ + isc_result_t r; + LOCK(&kasp->lock); + r = dns_keymgr_status(kasp, &keys, now, &output[0], + sizeof(output)); + UNLOCK(&kasp->lock); + CHECK(putstr(text, output)); + if (r != ISC_R_SUCCESS) { + CHECK(putstr(text, + "\n\nStatus output is truncated...")); + } + } else if (checkds) { + /* + * Mark DS record has been seen, so it may move to the + * rumoured state. + */ + char whenbuf[80]; + isc_time_set(&timewhen, when, 0); + isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); + isc_result_t ret; + + LOCK(&kasp->lock); + if (use_keyid) { + result = dns_keymgr_checkds_id(kasp, &keys, now, when, + dspublish, keyid, + (unsigned int)algorithm); + } else { + result = dns_keymgr_checkds(kasp, &keys, now, when, + dspublish); + } + UNLOCK(&kasp->lock); + + switch (result) { + case ISC_R_SUCCESS: + /* + * Rekey after checkds command because the next key + * event may have changed. + */ + dns_zone_rekey(zone, false); + + if (use_keyid) { + char tagbuf[6]; + snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); + CHECK(putstr(text, "KSK ")); + CHECK(putstr(text, tagbuf)); + CHECK(putstr(text, ": ")); + } + CHECK(putstr(text, "Marked DS as ")); + if (dspublish) { + CHECK(putstr(text, "published ")); + } else { + CHECK(putstr(text, "withdrawn ")); + } + CHECK(putstr(text, "since ")); + CHECK(putstr(text, whenbuf)); + break; + case DNS_R_TOOMANYKEYS: + CHECK(putstr(text, + "Error: multiple possible keys found, " + "retry command with -key id")); + break; + default: + ret = result; + CHECK(putstr(text, + "Error executing checkds command: ")); + CHECK(putstr(text, isc_result_totext(ret))); + break; + } + } else if (rollover) { + /* + * Manually rollover a key. + */ + char whenbuf[80]; + isc_time_set(&timewhen, when, 0); + isc_time_formattimestamp(&timewhen, whenbuf, sizeof(whenbuf)); + isc_result_t ret; + + LOCK(&kasp->lock); + result = dns_keymgr_rollover(kasp, &keys, now, when, keyid, + (unsigned int)algorithm); + UNLOCK(&kasp->lock); + + switch (result) { + case ISC_R_SUCCESS: + /* + * Rekey after rollover command because the next key + * event may have changed. + */ + dns_zone_rekey(zone, false); + + if (use_keyid) { + char tagbuf[6]; + snprintf(tagbuf, sizeof(tagbuf), "%u", keyid); + CHECK(putstr(text, "Key ")); + CHECK(putstr(text, tagbuf)); + CHECK(putstr(text, ": ")); + } + CHECK(putstr(text, "Rollover scheduled on ")); + CHECK(putstr(text, whenbuf)); + break; + case DNS_R_TOOMANYKEYS: + CHECK(putstr(text, + "Error: multiple possible keys found, " + "retry command with -alg algorithm")); + break; + default: + ret = result; + CHECK(putstr(text, + "Error executing rollover command: ")); + CHECK(putstr(text, isc_result_totext(ret))); + break; + } + } + CHECK(putnull(text)); + +cleanup: + if (msg != NULL) { + (void)putstr(text, msg); + (void)putnull(text); + } + + if (version != NULL) { + dns_db_closeversion(db, &version, false); + } + if (db != NULL) { + dns_db_detach(&db); + } + + while (!ISC_LIST_EMPTY(keys)) { + key = ISC_LIST_HEAD(keys); + ISC_LIST_UNLINK(keys, key, link); + dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key); + } + + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +static isc_result_t +putmem(isc_buffer_t **b, const char *str, size_t len) { + isc_result_t result; + + result = isc_buffer_reserve(*b, (unsigned int)len); + if (result != ISC_R_SUCCESS) { + return ISC_R_NOSPACE; + } + + isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len); + return ISC_R_SUCCESS; +} + +static isc_result_t +putstr(isc_buffer_t **b, const char *str) { + return putmem(b, str, strlen(str)); +} + +static isc_result_t +putuint8(isc_buffer_t **b, uint8_t val) { + isc_result_t result; + + result = isc_buffer_reserve(*b, 1); + if (result != ISC_R_SUCCESS) { + return ISC_R_NOSPACE; + } + + isc_buffer_putuint8(*b, val); + return ISC_R_SUCCESS; +} + +static isc_result_t +putnull(isc_buffer_t **b) { + return putuint8(b, 0); +} + +isc_result_t +named_server_zonestatus(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result = ISC_R_SUCCESS; + dns_zone_t *zone = NULL, *raw = NULL, *mayberaw = NULL; + const char *type, *file; + char zonename[DNS_NAME_FORMATSIZE]; + uint32_t serial, signed_serial, nodes; + char serbuf[16], sserbuf[16], nodebuf[16]; + char resignbuf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + 2]; + char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + isc_time_t loadtime, expiretime, refreshtime; + isc_time_t refreshkeytime, resigntime; + dns_zonetype_t zonetype; + bool dynamic = false, frozen = false; + bool hasraw = false; + bool secure, maintain, allow; + dns_db_t *db = NULL, *rawdb = NULL; + char **incfiles = NULL; + int nfiles = 0; + + REQUIRE(text != NULL); + + isc_time_settoepoch(&loadtime); + isc_time_settoepoch(&refreshtime); + isc_time_settoepoch(&expiretime); + isc_time_settoepoch(&refreshkeytime); + isc_time_settoepoch(&resigntime); + + CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, true)); + if (zone == NULL) { + result = ISC_R_UNEXPECTEDEND; + goto cleanup; + } + + /* Inline signing? */ + CHECK(dns_zone_getdb(zone, &db)); + dns_zone_getraw(zone, &raw); + hasraw = (raw != NULL); + if (hasraw) { + mayberaw = raw; + zonetype = dns_zone_gettype(raw); + CHECK(dns_zone_getdb(raw, &rawdb)); + } else { + mayberaw = zone; + zonetype = dns_zone_gettype(zone); + } + + type = dns_zonetype_name(zonetype); + + /* Serial number */ + result = dns_zone_getserial(mayberaw, &serial); + + /* This is to mirror old behavior with dns_zone_getserial */ + if (result != ISC_R_SUCCESS) { + serial = 0; + } + + snprintf(serbuf, sizeof(serbuf), "%u", serial); + if (hasraw) { + result = dns_zone_getserial(zone, &signed_serial); + if (result != ISC_R_SUCCESS) { + serial = 0; + } + snprintf(sserbuf, sizeof(sserbuf), "%u", signed_serial); + } + + /* Database node count */ + nodes = dns_db_nodecount(hasraw ? rawdb : db, dns_dbtree_main); + snprintf(nodebuf, sizeof(nodebuf), "%u", nodes); + + /* Security */ + secure = dns_db_issecure(db); + allow = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0); + maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0); + + /* Master files */ + file = dns_zone_getfile(mayberaw); + nfiles = dns_zone_getincludes(mayberaw, &incfiles); + + /* Load time */ + dns_zone_getloadtime(zone, &loadtime); + isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf)); + + /* Refresh/expire times */ + if (zonetype == dns_zone_secondary || zonetype == dns_zone_mirror || + zonetype == dns_zone_stub || zonetype == dns_zone_redirect) + { + dns_zone_getexpiretime(mayberaw, &expiretime); + isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf)); + dns_zone_getrefreshtime(mayberaw, &refreshtime); + isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf)); + } + + /* Key refresh time */ + if (zonetype == dns_zone_primary || + (zonetype == dns_zone_secondary && hasraw)) + { + dns_zone_getrefreshkeytime(zone, &refreshkeytime); + isc_time_formathttptimestamp(&refreshkeytime, kbuf, + sizeof(kbuf)); + } + + /* Dynamic? */ + if (zonetype == dns_zone_primary) { + dynamic = dns_zone_isdynamic(mayberaw, true); + frozen = dynamic && !dns_zone_isdynamic(mayberaw, false); + } + + /* Next resign event */ + if (secure && (zonetype == dns_zone_primary || + (zonetype == dns_zone_secondary && hasraw))) + { + dns_name_t *name; + dns_fixedname_t fixed; + isc_stdtime_t resign; + dns_typepair_t typepair; + + name = dns_fixedname_initname(&fixed); + + result = dns_db_getsigningtime(db, &resign, name, &typepair); + if (result == ISC_R_SUCCESS) { + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + + resign -= dns_zone_getsigresigninginterval(zone); + + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(DNS_TYPEPAIR_COVERS(typepair), + typebuf, sizeof(typebuf)); + snprintf(resignbuf, sizeof(resignbuf), "%s/%s", namebuf, + typebuf); + isc_time_set(&resigntime, resign, 0); + isc_time_formathttptimestamp(&resigntime, rtbuf, + sizeof(rtbuf)); + } + } + + /* Create text */ + CHECK(putstr(text, "name: ")); + CHECK(putstr(text, zonename)); + + CHECK(putstr(text, "\ntype: ")); + CHECK(putstr(text, type)); + + if (file != NULL) { + int i; + CHECK(putstr(text, "\nfiles: ")); + CHECK(putstr(text, file)); + for (i = 0; i < nfiles; i++) { + CHECK(putstr(text, ", ")); + if (incfiles[i] != NULL) { + CHECK(putstr(text, incfiles[i])); + } + } + } + + CHECK(putstr(text, "\nserial: ")); + CHECK(putstr(text, serbuf)); + if (hasraw) { + CHECK(putstr(text, "\nsigned serial: ")); + CHECK(putstr(text, sserbuf)); + } + + CHECK(putstr(text, "\nnodes: ")); + CHECK(putstr(text, nodebuf)); + + if (!isc_time_isepoch(&loadtime)) { + CHECK(putstr(text, "\nlast loaded: ")); + CHECK(putstr(text, lbuf)); + } + + if (!isc_time_isepoch(&refreshtime)) { + CHECK(putstr(text, "\nnext refresh: ")); + CHECK(putstr(text, rbuf)); + } + + if (!isc_time_isepoch(&expiretime)) { + CHECK(putstr(text, "\nexpires: ")); + CHECK(putstr(text, xbuf)); + } + + if (secure) { + CHECK(putstr(text, "\nsecure: yes")); + if (hasraw) { + CHECK(putstr(text, "\ninline signing: yes")); + } else { + CHECK(putstr(text, "\ninline signing: no")); + } + } else { + CHECK(putstr(text, "\nsecure: no")); + } + + if (maintain) { + CHECK(putstr(text, "\nkey maintenance: automatic")); + if (!isc_time_isepoch(&refreshkeytime)) { + CHECK(putstr(text, "\nnext key event: ")); + CHECK(putstr(text, kbuf)); + } + } else if (allow) { + CHECK(putstr(text, "\nkey maintenance: on command")); + } else if (secure || hasraw) { + CHECK(putstr(text, "\nkey maintenance: none")); + } + + if (!isc_time_isepoch(&resigntime)) { + CHECK(putstr(text, "\nnext resign node: ")); + CHECK(putstr(text, resignbuf)); + CHECK(putstr(text, "\nnext resign time: ")); + CHECK(putstr(text, rtbuf)); + } + + if (dynamic) { + CHECK(putstr(text, "\ndynamic: yes")); + if (frozen) { + CHECK(putstr(text, "\nfrozen: yes")); + } else { + CHECK(putstr(text, "\nfrozen: no")); + } + } else { + CHECK(putstr(text, "\ndynamic: no")); + } + + CHECK(putstr(text, "\nreconfigurable via modzone: ")); + CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no")); + +cleanup: + /* Indicate truncated output if possible. */ + if (result == ISC_R_NOSPACE) { + (void)putstr(text, "\n..."); + } + if (result == ISC_R_SUCCESS || result == ISC_R_NOSPACE) { + (void)putnull(text); + } + + if (db != NULL) { + dns_db_detach(&db); + } + if (rawdb != NULL) { + dns_db_detach(&rawdb); + } + if (incfiles != NULL && mayberaw != NULL) { + int i; + isc_mem_t *mctx = dns_zone_getmctx(mayberaw); + + for (i = 0; i < nfiles; i++) { + if (incfiles[i] != NULL) { + isc_mem_free(mctx, incfiles[i]); + } + } + isc_mem_free(mctx, incfiles); + } + if (raw != NULL) { + dns_zone_detach(&raw); + } + if (zone != NULL) { + dns_zone_detach(&zone); + } + return result; +} + +isc_result_t +named_server_nta(named_server_t *server, isc_lex_t *lex, bool readonly, + isc_buffer_t **text) { + dns_view_t *view; + dns_ntatable_t *ntatable = NULL; + isc_result_t result = ISC_R_SUCCESS; + char *ptr, *nametext = NULL, *viewname; + char namebuf[DNS_NAME_FORMATSIZE]; + char viewbuf[DNS_NAME_FORMATSIZE]; + isc_stdtime_t now, when; + isc_time_t t; + char tbuf[64]; + const char *msg = NULL; + bool dump = false, force = false; + dns_fixedname_t fn; + const dns_name_t *ntaname; + dns_name_t *fname; + dns_ttl_t ntattl; + bool ttlset = false, viewfound = false; + dns_rdataclass_t rdclass = dns_rdataclass_in; + bool first = true; + + REQUIRE(text != NULL); + + UNUSED(force); + + fname = dns_fixedname_initname(&fn); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + for (;;) { + /* Check for options */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcmp(ptr, "--") == 0) { + break; + } else if (argcheck(ptr, "dump")) { + dump = true; + } else if (argcheck(ptr, "remove")) { + ntattl = 0; + ttlset = true; + } else if (argcheck(ptr, "force")) { + force = true; + continue; + } else if (argcheck(ptr, "lifetime")) { + isc_textregion_t tr; + + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "No lifetime specified"; + CHECK(ISC_R_UNEXPECTEDEND); + } + + tr.base = ptr; + tr.length = strlen(ptr); + result = dns_ttl_fromtext(&tr, &ntattl); + if (result != ISC_R_SUCCESS) { + msg = "could not parse NTA lifetime"; + CHECK(result); + } + + if (ntattl > 604800) { + msg = "NTA lifetime cannot exceed one week"; + CHECK(ISC_R_RANGE); + } + + ttlset = true; + continue; + } else if (argcheck(ptr, "class")) { + isc_textregion_t tr; + + ptr = next_token(lex, text); + if (ptr == NULL) { + msg = "No class specified"; + CHECK(ISC_R_UNEXPECTEDEND); + } + + tr.base = ptr; + tr.length = strlen(ptr); + CHECK(dns_rdataclass_fromtext(&rdclass, &tr)); + continue; + } else if (ptr[0] == '-') { + msg = "Unknown option"; + CHECK(DNS_R_SYNTAX); + } else { + nametext = ptr; + } + + break; + } + + /* + * If -dump was specified, list NTA's and return + */ + if (dump) { + size_t last = 0; + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + result = dns_view_getntatable(view, &ntatable); + if (result == ISC_R_NOTFOUND) { + continue; + } + + if (last != isc_buffer_usedlength(*text)) { + CHECK(putstr(text, "\n")); + } + + last = isc_buffer_usedlength(*text); + + CHECK(dns_ntatable_totext(ntatable, view->name, text)); + } + CHECK(putnull(text)); + + goto cleanup; + } + + if (readonly) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_CONTROL, ISC_LOG_INFO, + "rejecting restricted control channel " + "NTA command"); + CHECK(ISC_R_FAILURE); + } + + /* Get the NTA name if not found above. */ + if (nametext == NULL) { + nametext = next_token(lex, text); + } + if (nametext == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Copy nametext as it'll be overwritten by next_token() */ + strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); + + if (strcmp(namebuf, ".") == 0) { + ntaname = dns_rootname; + } else { + isc_buffer_t b; + isc_buffer_init(&b, namebuf, strlen(namebuf)); + isc_buffer_add(&b, strlen(namebuf)); + CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0, NULL)); + ntaname = fname; + } + + /* Look for the view name. */ + viewname = next_token(lex, text); + if (viewname != NULL) { + strlcpy(viewbuf, viewname, DNS_NAME_FORMATSIZE); + viewname = viewbuf; + } + + if (next_token(lex, text) != NULL) { + CHECK(DNS_R_SYNTAX); + } + + now = isc_stdtime_now(); + + isc_loopmgr_pause(named_g_loopmgr); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (viewname != NULL && strcmp(view->name, viewname) != 0) { + continue; + } + viewfound = true; + + if (view->rdclass != rdclass && rdclass != dns_rdataclass_any) { + continue; + } + + if (view->nta_lifetime == 0) { + continue; + } + + if (!ttlset) { + ntattl = view->nta_lifetime; + } + + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + + result = dns_view_getntatable(view, &ntatable); + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + continue; + } + + result = dns_view_flushnode(view, ntaname, true); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "flush tree '%s' in cache view '%s': %s", namebuf, + view->name, isc_result_totext(result)); + + if (ntattl != 0) { + CHECK(dns_ntatable_add(ntatable, ntaname, force, now, + ntattl)); + + when = now + ntattl; + isc_time_set(&t, when, 0); + isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); + + if (!first) { + CHECK(putstr(text, "\n")); + } + first = false; + + CHECK(putstr(text, "Negative trust anchor added: ")); + CHECK(putstr(text, namebuf)); + CHECK(putstr(text, "/")); + CHECK(putstr(text, view->name)); + CHECK(putstr(text, ", expires ")); + CHECK(putstr(text, tbuf)); + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "added NTA '%s' (%d sec) in view '%s'", + namebuf, ntattl, view->name); + } else { + bool wasremoved; + + result = dns_ntatable_delete(ntatable, ntaname); + if (result == ISC_R_SUCCESS) { + wasremoved = true; + } else if (result == ISC_R_NOTFOUND) { + wasremoved = false; + } else { + goto cleanup_exclusive; + } + + if (!first) { + CHECK(putstr(text, "\n")); + } + first = false; + + CHECK(putstr(text, "Negative trust anchor ")); + CHECK(putstr(text, + wasremoved ? "removed: " : "not found: ")); + CHECK(putstr(text, namebuf)); + CHECK(putstr(text, "/")); + CHECK(putstr(text, view->name)); + + if (wasremoved) { + isc_log_write( + named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "removed NTA '%s' in view %s", namebuf, + view->name); + } + } + + result = dns_view_saventa(view); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "error writing NTA file " + "for view '%s': %s", + view->name, isc_result_totext(result)); + } + } + + if (!viewfound) { + msg = "No such view"; + result = ISC_R_NOTFOUND; + } else { + (void)putnull(text); + } + +cleanup_exclusive: + isc_loopmgr_resume(named_g_loopmgr); + +cleanup: + + if (msg != NULL) { + (void)putstr(text, msg); + (void)putnull(text); + } + + if (ntatable != NULL) { + dns_ntatable_detach(&ntatable); + } + return result; +} + +isc_result_t +named_server_saventa(named_server_t *server) { + dns_view_t *view; + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + isc_result_t result = dns_view_saventa(view); + + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "error writing NTA file " + "for view '%s': %s", + view->name, isc_result_totext(result)); + } + } + + return ISC_R_SUCCESS; +} + +isc_result_t +named_server_loadnta(named_server_t *server) { + dns_view_t *view; + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + isc_result_t result = dns_view_loadnta(view); + + if ((result != ISC_R_SUCCESS) && + (result != ISC_R_FILENOTFOUND) && + (result != ISC_R_NOTFOUND)) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "error loading NTA file " + "for view '%s': %s", + view->name, isc_result_totext(result)); + } + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +mkey_refresh(dns_view_t *view, isc_buffer_t **text) { + isc_result_t result; + char msg[DNS_NAME_FORMATSIZE + 500] = ""; + + snprintf(msg, sizeof(msg), "refreshing managed keys for '%s'", + view->name); + CHECK(putstr(text, msg)); + CHECK(dns_zone_synckeyzone(view->managed_keys)); + +cleanup: + return result; +} + +static isc_result_t +mkey_destroy(dns_view_t *view, isc_buffer_t **text) { + isc_result_t result; + char msg[DNS_NAME_FORMATSIZE + 500] = ""; + const char *file = NULL; + dns_db_t *dbp = NULL; + dns_zone_t *mkzone = NULL; + bool removed_a_file = false; + + if (view->managed_keys == NULL) { + CHECK(ISC_R_NOTFOUND); + } + + snprintf(msg, sizeof(msg), "destroying managed-keys database for '%s'", + view->name); + CHECK(putstr(text, msg)); + + isc_loopmgr_pause(named_g_loopmgr); + + /* Remove and clean up managed keys zone from view */ + mkzone = view->managed_keys; + view->managed_keys = NULL; + (void)dns_zone_flush(mkzone); + + /* Unload zone database */ + if (dns_zone_getdb(mkzone, &dbp) == ISC_R_SUCCESS) { + dns_db_detach(&dbp); + dns_zone_unload(mkzone); + } + + /* Delete files */ + file = dns_zone_getfile(mkzone); + result = isc_file_remove(file); + if (result == ISC_R_SUCCESS) { + removed_a_file = true; + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + + file = dns_zone_getjournal(mkzone); + result = isc_file_remove(file); + if (result == ISC_R_SUCCESS) { + removed_a_file = true; + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "file %s not removed: %s", file, + isc_result_totext(result)); + } + + if (!removed_a_file) { + CHECK(putstr(text, "error: no files could be removed")); + CHECK(ISC_R_FAILURE); + } + + dns_zone_detach(&mkzone); + result = ISC_R_SUCCESS; + +cleanup: + isc_loopmgr_resume(named_g_loopmgr); + return result; +} + +static isc_result_t +mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) { + isc_result_t result; + dns_db_t *db = NULL; + dns_dbversion_t *ver = NULL; + dns_rriterator_t rrit; + isc_stdtime_t now = isc_stdtime_now(); + dns_name_t *prevname = NULL; + + CHECK(dns_zone_getdb(view->managed_keys, &db)); + dns_db_currentversion(db, &ver); + dns_rriterator_init(&rrit, db, ver, 0); + for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS; + result = dns_rriterator_nextrrset(&rrit)) + { + char buf[DNS_NAME_FORMATSIZE + 500]; + dns_name_t *name = NULL; + dns_rdataset_t *kdset = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_keydata_t kd; + uint32_t ttl; + + dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL); + if (kdset == NULL || kdset->type != dns_rdatatype_keydata || + !dns_rdataset_isassociated(kdset)) + { + continue; + } + + if (name != prevname) { + char nbuf[DNS_NAME_FORMATSIZE]; + dns_name_format(name, nbuf, sizeof(nbuf)); + snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf); + CHECK(putstr(text, buf)); + } + + for (result = dns_rdataset_first(kdset); + result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset)) + { + char alg[DNS_SECALG_FORMATSIZE]; + char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + dns_keytag_t keyid; + isc_region_t r; + isc_time_t t; + bool revoked; + + dns_rdata_reset(&rdata); + dns_rdataset_current(kdset, &rdata); + result = dns_rdata_tostruct(&rdata, &kd, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + dns_rdata_toregion(&rdata, &r); + isc_region_consume(&r, 12); + keyid = dst_region_computeid(&r); + + snprintf(buf, sizeof(buf), "\n keyid: %u", keyid); + CHECK(putstr(text, buf)); + + dns_secalg_format(kd.algorithm, alg, sizeof(alg)); + snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg); + CHECK(putstr(text, buf)); + + revoked = ((kd.flags & DNS_KEYFLAG_REVOKE) != 0); + snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s", + revoked ? " REVOKE" : "", + ((kd.flags & DNS_KEYFLAG_KSK) != 0) ? " SEP" + : "", + (kd.flags == 0) ? " (none)" : ""); + CHECK(putstr(text, buf)); + + isc_time_set(&t, kd.refresh, 0); + isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); + snprintf(buf, sizeof(buf), "\n\tnext refresh: %s", + tbuf); + CHECK(putstr(text, buf)); + + if (kd.removehd != 0) { + isc_time_set(&t, kd.removehd, 0); + isc_time_formathttptimestamp(&t, tbuf, + sizeof(tbuf)); + snprintf(buf, sizeof(buf), "\n\tremove at: %s", + tbuf); + CHECK(putstr(text, buf)); + } + + isc_time_set(&t, kd.addhd, 0); + isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf)); + if (kd.addhd == 0) { + snprintf(buf, sizeof(buf), "\n\tno trust"); + } else if (revoked) { + snprintf(buf, sizeof(buf), "\n\ttrust revoked"); + } else if (kd.addhd <= now) { + snprintf(buf, sizeof(buf), + "\n\ttrusted since: %s", tbuf); + } else if (kd.addhd > now) { + snprintf(buf, sizeof(buf), + "\n\ttrust pending: %s", tbuf); + } + CHECK(putstr(text, buf)); + } + } + + if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } + +cleanup: + if (ver != NULL) { + dns_rriterator_destroy(&rrit); + dns_db_closeversion(db, &ver, false); + } + if (db != NULL) { + dns_db_detach(&db); + } + + return result; +} + +static isc_result_t +mkey_status(dns_view_t *view, isc_buffer_t **text) { + isc_result_t result; + char msg[ISC_FORMATHTTPTIMESTAMP_SIZE]; + isc_time_t t; + + CHECK(putstr(text, "view: ")); + CHECK(putstr(text, view->name)); + + CHECK(putstr(text, "\nnext scheduled event: ")); + + dns_zone_getrefreshkeytime(view->managed_keys, &t); + if (isc_time_isepoch(&t)) { + CHECK(putstr(text, "never")); + } else { + isc_time_formathttptimestamp(&t, msg, sizeof(msg)); + CHECK(putstr(text, msg)); + } + + CHECK(mkey_dumpzone(view, text)); + +cleanup: + return result; +} + +isc_result_t +named_server_mkeys(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + char *cmd, *classtxt, *viewtxt = NULL; + isc_result_t result = ISC_R_SUCCESS; + dns_view_t *view = NULL; + dns_rdataclass_t rdclass; + char msg[DNS_NAME_FORMATSIZE + 500] = ""; + enum { NONE, STAT, REFRESH, SYNC, DESTROY } opt = NONE; + bool found = false; + bool first = true; + + REQUIRE(text != NULL); + + /* Skip rndc command name */ + cmd = next_token(lex, text); + if (cmd == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Get managed-keys subcommand */ + cmd = next_token(lex, text); + if (cmd == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcasecmp(cmd, "status") == 0) { + opt = STAT; + } else if (strcasecmp(cmd, "refresh") == 0) { + opt = REFRESH; + } else if (strcasecmp(cmd, "sync") == 0) { + opt = SYNC; + } else if (strcasecmp(cmd, "destroy") == 0) { + opt = DESTROY; + } else { + snprintf(msg, sizeof(msg), "unknown command '%s'", cmd); + (void)putstr(text, msg); + result = ISC_R_UNEXPECTED; + goto cleanup; + } + + /* Look for the optional class name. */ + classtxt = next_token(lex, text); + if (classtxt != NULL) { + isc_textregion_t r; + r.base = classtxt; + r.length = strlen(classtxt); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + snprintf(msg, sizeof(msg), "unknown class '%s'", + classtxt); + (void)putstr(text, msg); + goto cleanup; + } + viewtxt = next_token(lex, text); + } + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (viewtxt != NULL && (rdclass != view->rdclass || + strcmp(view->name, viewtxt) != 0)) + { + continue; + } + + if (view->managed_keys == NULL) { + if (viewtxt != NULL) { + snprintf(msg, sizeof(msg), + "view '%s': no managed keys", viewtxt); + CHECK(putstr(text, msg)); + goto cleanup; + } else { + continue; + } + } + + found = true; + + switch (opt) { + case REFRESH: + if (!first) { + CHECK(putstr(text, "\n")); + } + CHECK(mkey_refresh(view, text)); + break; + case STAT: + if (!first) { + CHECK(putstr(text, "\n\n")); + } + CHECK(mkey_status(view, text)); + break; + case SYNC: + CHECK(dns_zone_flush(view->managed_keys)); + break; + case DESTROY: + if (!first) { + CHECK(putstr(text, "\n")); + } + CHECK(mkey_destroy(view, text)); + break; + default: + UNREACHABLE(); + } + + if (viewtxt != NULL) { + break; + } + first = false; + } + + if (!found) { + CHECK(putstr(text, "no views with managed keys")); + } + +cleanup: + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; +} + +isc_result_t +named_server_dnstap(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { +#ifdef HAVE_DNSTAP + char *ptr; + isc_result_t result; + bool reopen = false; + int backups = 0; + + REQUIRE(text != NULL); + + if (server->dtenv == NULL) { + return ISC_R_NOTFOUND; + } + + /* Check the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* "dnstap-reopen" was used in 9.11.0b1 */ + if (strcasecmp(ptr, "dnstap-reopen") == 0) { + reopen = true; + } else { + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + } + + if (reopen || strcasecmp(ptr, "-reopen") == 0) { + backups = ISC_LOG_ROLLNEVER; + } else if (strcasecmp(ptr, "-roll") == 0) { + unsigned int n; + ptr = next_token(lex, text); + if (ptr != NULL) { + unsigned int u; + n = sscanf(ptr, "%u", &u); + if (n != 1U || u > INT_MAX) { + return ISC_R_BADNUMBER; + } + backups = u; + } else { + backups = ISC_LOG_ROLLINFINITE; + } + } else { + return DNS_R_SYNTAX; + } + + result = dns_dt_reopen(server->dtenv, backups); + return result; +#else /* ifdef HAVE_DNSTAP */ + UNUSED(server); + UNUSED(lex); + UNUSED(text); + return ISC_R_NOTIMPLEMENTED; +#endif /* ifdef HAVE_DNSTAP */ +} + +isc_result_t +named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) { + char *ptr; + isc_result_t result = ISC_R_SUCCESS; + uint32_t initial, idle, keepalive, advertised; + char msg[128]; + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive, + &advertised); + + /* Look for optional arguments. */ + ptr = next_token(lex, NULL); + if (ptr != NULL) { + CHECK(isc_parse_uint32(&initial, ptr, 10)); + initial *= 100; + if (initial > MAX_INITIAL_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + if (initial < MIN_INITIAL_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + CHECK(isc_parse_uint32(&idle, ptr, 10)); + idle *= 100; + if (idle > MAX_IDLE_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + if (idle < MIN_IDLE_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + CHECK(isc_parse_uint32(&keepalive, ptr, 10)); + keepalive *= 100; + if (keepalive > MAX_KEEPALIVE_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + if (keepalive < MIN_KEEPALIVE_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + CHECK(isc_parse_uint32(&advertised, ptr, 10)); + advertised *= 100; + if (advertised > MAX_ADVERTISED_TIMEOUT) { + CHECK(ISC_R_RANGE); + } + + isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, + advertised); + } + + snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100); + CHECK(putstr(text, msg)); + snprintf(msg, sizeof(msg), "tcp-idle-timeout=%u\n", idle / 100); + CHECK(putstr(text, msg)); + snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n", + keepalive / 100); + CHECK(putstr(text, msg)); + snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u", + advertised / 100); + CHECK(putstr(text, msg)); + +cleanup: + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; +} + +isc_result_t +named_server_servestale(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + char *ptr, *classtxt, *viewtxt = NULL; + char msg[128]; + dns_rdataclass_t rdclass = dns_rdataclass_in; + dns_view_t *view; + bool found = false; + dns_stale_answer_t staleanswersok = dns_stale_answer_conf; + bool wantstatus = false; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || + !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) + { + staleanswersok = dns_stale_answer_yes; + } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || + !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) + { + staleanswersok = dns_stale_answer_no; + } else if (strcasecmp(ptr, "reset") == 0) { + staleanswersok = dns_stale_answer_conf; + } else if (!strcasecmp(ptr, "check") || !strcasecmp(ptr, "status")) { + wantstatus = true; + } else { + return DNS_R_SYNTAX; + } + + /* Look for the optional class name. */ + classtxt = next_token(lex, text); + if (classtxt != NULL) { + isc_textregion_t r; + + /* Look for the optional view name. */ + viewtxt = next_token(lex, text); + + /* + * If 'classtext' is not a valid class then it us a view name. + */ + r.base = classtxt; + r.length = strlen(classtxt); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + if (viewtxt != NULL) { + snprintf(msg, sizeof(msg), "unknown class '%s'", + classtxt); + (void)putstr(text, msg); + goto cleanup; + } + + viewtxt = classtxt; + classtxt = NULL; + } + } + + isc_loopmgr_pause(named_g_loopmgr); + + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + dns_ttl_t stale_ttl = 0; + uint32_t stale_refresh = 0; + dns_db_t *db = NULL; + + if (classtxt != NULL && rdclass != view->rdclass) { + continue; + } + + if (viewtxt != NULL && strcmp(view->name, viewtxt) != 0) { + continue; + } + + if (!wantstatus) { + view->staleanswersok = staleanswersok; + found = true; + continue; + } + + db = NULL; + dns_db_attach(view->cachedb, &db); + (void)dns_db_getservestalettl(db, &stale_ttl); + (void)dns_db_getservestalerefresh(db, &stale_refresh); + dns_db_detach(&db); + if (found) { + CHECK(putstr(text, "\n")); + } + CHECK(putstr(text, view->name)); + CHECK(putstr(text, ": ")); + switch (view->staleanswersok) { + case dns_stale_answer_yes: + if (stale_ttl > 0) { + CHECK(putstr(text, "stale cache " + "enabled; stale " + "answers enabled")); + } else { + CHECK(putstr(text, "stale cache disabled; " + "stale " + "answers unavailable")); + } + break; + case dns_stale_answer_no: + if (stale_ttl > 0) { + CHECK(putstr(text, "stale cache " + "enabled; stale " + "answers disabled")); + } else { + CHECK(putstr(text, "stale cache disabled; " + "stale " + "answers unavailable")); + } + break; + case dns_stale_answer_conf: + if (view->staleanswersenable && stale_ttl > 0) { + CHECK(putstr(text, "stale cache " + "enabled; stale " + "answers enabled")); + } else if (stale_ttl > 0) { + CHECK(putstr(text, "stale cache " + "enabled; stale " + "answers disabled")); + } else { + CHECK(putstr(text, "stale cache disabled; " + "stale " + "answers unavailable")); + } + break; + } + if (stale_ttl > 0) { + snprintf(msg, sizeof(msg), + " (stale-answer-ttl=%u " + "max-stale-ttl=%u " + "stale-refresh-time=%u)", + view->staleanswerttl, stale_ttl, + stale_refresh); + CHECK(putstr(text, msg)); + } + found = true; + } + + if (!found) { + result = ISC_R_NOTFOUND; + } + +cleanup: + isc_loopmgr_resume(named_g_loopmgr); + + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; +} + +isc_result_t +named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result = ISC_R_SUCCESS; + dns_view_t *view = NULL; + char *ptr = NULL, *viewname = NULL; + bool first = true; + dns_adb_t *adb = NULL; + + REQUIRE(text != NULL); + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Look for the view name. */ + viewname = next_token(lex, text); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + char tbuf[100]; + unsigned int used; + uint32_t val; + int s; + + if (view->rdclass != dns_rdataclass_in) { + continue; + } + + if (viewname != NULL && strcasecmp(view->name, viewname) != 0) { + continue; + } + + dns_view_getadb(view, &adb); + if (adb == NULL) { + continue; + } + + if (!first) { + CHECK(putstr(text, "\n")); + } + CHECK(putstr(text, "Rate limited servers, view ")); + CHECK(putstr(text, view->name)); + + dns_adb_getquota(adb, &val, NULL, NULL, NULL, NULL); + s = snprintf(tbuf, sizeof(tbuf), + " (fetches-per-server %u):", val); + if (s < 0 || (unsigned int)s > sizeof(tbuf)) { + CHECK(ISC_R_NOSPACE); + } + first = false; + CHECK(putstr(text, tbuf)); + used = isc_buffer_usedlength(*text); + CHECK(dns_adb_dumpquota(adb, text)); + if (used == isc_buffer_usedlength(*text)) { + CHECK(putstr(text, "\n None.")); + } + + CHECK(putstr(text, "\nRate limited servers, view ")); + CHECK(putstr(text, view->name)); + val = dns_resolver_getfetchesperzone(view->resolver); + s = snprintf(tbuf, sizeof(tbuf), + " (fetches-per-zone %u):", val); + if (s < 0 || (unsigned int)s > sizeof(tbuf)) { + CHECK(ISC_R_NOSPACE); + } + CHECK(putstr(text, tbuf)); + used = isc_buffer_usedlength(*text); + CHECK(dns_resolver_dumpquota(view->resolver, text)); + if (used == isc_buffer_usedlength(*text)) { + CHECK(putstr(text, "\n None.")); + } + dns_adb_detach(&adb); + } +cleanup: + if (adb != NULL) { + dns_adb_detach(&adb); + } + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; +} + +isc_result_t +named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { + isc_result_t result = ISC_R_SUCCESS; + dns_zone_t *zone = NULL; + dns_kasp_t *kasp = NULL; + const char *ptr; + char skrfile[PATH_MAX]; + + /* Skip the command name. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + /* Find out what we are to do. */ + ptr = next_token(lex, text); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + if (strcasecmp(ptr, "-import") != 0) { + CHECK(DNS_R_SYNTAX); + } + + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + (void)snprintf(skrfile, sizeof(skrfile), "%s", ptr); + + CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, false)); + if (zone == NULL) { + CHECK(ISC_R_UNEXPECTEDEND); + } + kasp = dns_zone_getkasp(zone); + if (kasp == NULL) { + CHECK(putstr(text, "zone does not have a dnssec-policy")); + CHECK(putnull(text)); + goto cleanup; + } + + if (!dns_kasp_offlineksk(kasp)) { + CHECK(putstr(text, "zone does not have offline-ksk enabled")); + CHECK(putnull(text)); + goto cleanup; + } + + result = dns_zone_import_skr(zone, skrfile); + if (result != ISC_R_SUCCESS) { + CHECK(putstr(text, "import failed: ")); + CHECK(putstr(text, isc_result_totext(result))); + CHECK(putnull(text)); + } else { + /* Schedule a rekey */ + dns_zone_rekey(zone, false); + } + +cleanup: + if (zone != NULL) { + dns_zone_detach(&zone); + } + + return result; +} + +isc_result_t +named_server_togglememprof(isc_lex_t *lex) { + isc_result_t result = ISC_R_FAILURE; + bool active; + char *ptr; + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } else if (!strcasecmp(ptr, "dump")) { + result = memprof_dump(); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to dump memory profile"); + + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "memory profile dumped"); + } + + goto done; + } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || + !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) + { + active = true; + } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || + !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) + { + active = false; + } else { + return DNS_R_SYNTAX; + } + + result = memprof_toggle(active); + if (result != ISC_R_SUCCESS) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to toggle memory profiling"); + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "memory profiling %s", + active ? "enabled" : "disabled"); + } + +done: + return result; +} + +#ifdef JEMALLOC_API_SUPPORTED +const char * +named_server_getmemprof(void) { + memprof_status status = MEMPROF_ON; + bool is_enabled; + size_t len = sizeof(is_enabled); + + if (mallctl("config.prof", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_UNSUPPORTED; + goto done; + } + + if (mallctl("opt.prof", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_INACTIVE; + goto done; + } + + len = sizeof(is_enabled); + if (mallctl("prof.active", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_OFF; + } + +done: + return memprof_status_text[status]; +} + +#else /* JEMALLOC_API_SUPPORTED */ +const char * +named_server_getmemprof(void) { + return memprof_status_text[MEMPROF_UNSUPPORTED]; +} +#endif /* JEMALLOC_API_SUPPORTED */ diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c new file mode 100644 index 0000000..083a910 --- /dev/null +++ b/bin/named/statschannel.c @@ -0,0 +1,4179 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#if HAVE_JSON_C +#include +#include +#endif /* HAVE_JSON_C */ + +#if HAVE_LIBXML2 +#include +#define ISC_XMLCHAR (const xmlChar *) +#endif /* HAVE_LIBXML2 */ + +#include "xsl_p.h" + +#define STATS_XML_VERSION_MAJOR "3" +#define STATS_XML_VERSION_MINOR "14" +#define STATS_XML_VERSION STATS_XML_VERSION_MAJOR "." STATS_XML_VERSION_MINOR + +#define STATS_JSON_VERSION_MAJOR "1" +#define STATS_JSON_VERSION_MINOR "8" +#define STATS_JSON_VERSION STATS_JSON_VERSION_MAJOR "." STATS_JSON_VERSION_MINOR + +#define CHECK(m) \ + do { \ + result = (m); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) + +struct named_statschannel { + /* Unlocked */ + isc_httpdmgr_t *httpdmgr; + isc_sockaddr_t address; + isc_mem_t *mctx; + + /* + * Locked by channel lock + */ + isc_mutex_t lock; + dns_acl_t *acl; + + /* Locked by main loop. */ + ISC_LINK(struct named_statschannel) link; +}; + +typedef struct stats_dumparg { + isc_statsformat_t type; + void *arg; /* type dependent argument */ + int ncounters; /* for general statistics */ + int *counterindices; /* for general statistics */ + uint64_t *countervalues; /* for general statistics */ + isc_result_t result; +} stats_dumparg_t; + +static isc_once_t once = ISC_ONCE_INIT; + +#if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) +#define EXTENDED_STATS +#else /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */ +#undef EXTENDED_STATS +#endif /* if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) */ + +#ifdef EXTENDED_STATS +static const char * +user_zonetype(dns_zone_t *zone) { + dns_zonetype_t ztype; + dns_view_t *view; + static const struct zt { + const dns_zonetype_t type; + const char *const string; + } typemap[] = { { dns_zone_none, "none" }, + { dns_zone_primary, "primary" }, + { dns_zone_secondary, "secondary" }, + { dns_zone_mirror, "mirror" }, + { dns_zone_stub, "stub" }, + { dns_zone_staticstub, "static-stub" }, + { dns_zone_key, "key" }, + { dns_zone_dlz, "dlz" }, + { dns_zone_redirect, "redirect" }, + { 0, NULL } }; + const struct zt *tp; + + if ((dns_zone_getoptions(zone) & DNS_ZONEOPT_AUTOEMPTY) != 0) { + return "builtin"; + } + + view = dns_zone_getview(zone); + if (view != NULL && strcmp(view->name, "_bind") == 0) { + return "builtin"; + } + + ztype = dns_zone_gettype(zone); + for (tp = typemap; tp->string != NULL && tp->type != ztype; tp++) { + /* empty */ + } + return tp->string; +} +#endif /* ifdef EXTENDED_STATS */ + +/*% + * Statistics descriptions. These could be statistically initialized at + * compile time, but we configure them run time in the init_desc() function + * below so that they'll be less susceptible to counter name changes. + */ +static const char *nsstats_desc[ns_statscounter_max]; +static const char *resstats_desc[dns_resstatscounter_max]; +static const char *adbstats_desc[dns_adbstats_max]; +static const char *zonestats_desc[dns_zonestatscounter_max]; +static const char *sockstats_desc[isc_sockstatscounter_max]; +static const char *dnssecstats_desc[dns_dnssecstats_max]; +static const char *udpinsizestats_desc[dns_sizecounter_in_max]; +static const char *udpoutsizestats_desc[dns_sizecounter_out_max]; +static const char *tcpinsizestats_desc[dns_sizecounter_in_max]; +static const char *tcpoutsizestats_desc[dns_sizecounter_out_max]; +static const char *dnstapstats_desc[dns_dnstapcounter_max]; +static const char *gluecachestats_desc[dns_gluecachestatscounter_max]; +#if defined(EXTENDED_STATS) +static const char *nsstats_xmldesc[ns_statscounter_max]; +static const char *resstats_xmldesc[dns_resstatscounter_max]; +static const char *adbstats_xmldesc[dns_adbstats_max]; +static const char *zonestats_xmldesc[dns_zonestatscounter_max]; +static const char *sockstats_xmldesc[isc_sockstatscounter_max]; +static const char *dnssecstats_xmldesc[dns_dnssecstats_max]; +static const char *udpinsizestats_xmldesc[dns_sizecounter_in_max]; +static const char *udpoutsizestats_xmldesc[dns_sizecounter_out_max]; +static const char *tcpinsizestats_xmldesc[dns_sizecounter_in_max]; +static const char *tcpoutsizestats_xmldesc[dns_sizecounter_out_max]; +static const char *dnstapstats_xmldesc[dns_dnstapcounter_max]; +static const char *gluecachestats_xmldesc[dns_gluecachestatscounter_max]; +#else /* if defined(EXTENDED_STATS) */ +#define nsstats_xmldesc NULL +#define resstats_xmldesc NULL +#define adbstats_xmldesc NULL +#define zonestats_xmldesc NULL +#define sockstats_xmldesc NULL +#define dnssecstats_xmldesc NULL +#define udpinsizestats_xmldesc NULL +#define udpoutsizestats_xmldesc NULL +#define tcpinsizestats_xmldesc NULL +#define tcpoutsizestats_xmldesc NULL +#define dnstapstats_xmldesc NULL +#define gluecachestats_xmldesc NULL +#endif /* EXTENDED_STATS */ + +#define TRY0(a) \ + do { \ + xmlrc = (a); \ + if (xmlrc < 0) \ + goto cleanup; \ + } while (0) + +/*% + * Mapping arrays to represent statistics counters in the order of our + * preference, regardless of the order of counter indices. For example, + * nsstats_desc[nsstats_index[0]] will be the description that is shown first. + */ +static int nsstats_index[ns_statscounter_max]; +static int resstats_index[dns_resstatscounter_max]; +static int adbstats_index[dns_adbstats_max]; +static int zonestats_index[dns_zonestatscounter_max]; +static int sockstats_index[isc_sockstatscounter_max]; +static int dnssecstats_index[dns_dnssecstats_max]; +static int udpinsizestats_index[dns_sizecounter_in_max]; +static int udpoutsizestats_index[dns_sizecounter_out_max]; +static int tcpinsizestats_index[dns_sizecounter_in_max]; +static int tcpoutsizestats_index[dns_sizecounter_out_max]; +static int dnstapstats_index[dns_dnstapcounter_max]; +static int gluecachestats_index[dns_gluecachestatscounter_max]; + +static void +set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs, + const char *xdesc, const char **xdescs) { + REQUIRE(counter < maxcounter); + REQUIRE(fdescs != NULL && fdescs[counter] == NULL); +#if defined(EXTENDED_STATS) + REQUIRE(xdescs != NULL && xdescs[counter] == NULL); +#endif /* if defined(EXTENDED_STATS) */ + + fdescs[counter] = fdesc; +#if defined(EXTENDED_STATS) + xdescs[counter] = xdesc; +#else /* if defined(EXTENDED_STATS) */ + UNUSED(xdesc); + UNUSED(xdescs); +#endif /* if defined(EXTENDED_STATS) */ +} + +static const char * +get_histo_desc(const char *prefix, int i, int inf, bool ext) { + static char buf[(DNS_SIZEHISTO_MAXIN + DNS_SIZEHISTO_MAXOUT) * 80]; + static size_t used = 0; + char *desc = buf + used; + size_t space = sizeof(buf) - used; + int min = DNS_SIZEHISTO_QUANTUM * i; + int max = DNS_SIZEHISTO_QUANTUM * (i + 1) - 1; + int len = 0; + + if (!ext && i < inf) { + len = snprintf(desc, space, "%s %u-%u bytes", prefix, min, max); + } else if (!ext && i >= inf) { + len = snprintf(desc, space, "%s %u+ bytes", prefix, min); + } else if (ext && i < inf) { + len = snprintf(desc, space, "%u-%u", min, max); + } else if (ext && i >= inf) { + len = snprintf(desc, space, "%u+", min); + } + INSIST(0 < len && (size_t)len < space); + used += len + 1; + return desc; +} + +static void +init_desc(void) { + int i; + + /* Initialize name server statistics */ + for (i = 0; i < ns_statscounter_max; i++) { + nsstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < ns_statscounter_max; i++) { + nsstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_NSSTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(ns_statscounter_##counterid, ns_statscounter_max, \ + desc, nsstats_desc, xmldesc, nsstats_xmldesc); \ + nsstats_index[i++] = ns_statscounter_##counterid; \ + } while (0) + + i = 0; + SET_NSSTATDESC(requestv4, "IPv4 requests received", "Requestv4"); + SET_NSSTATDESC(requestv6, "IPv6 requests received", "Requestv6"); + SET_NSSTATDESC(edns0in, "requests with EDNS(0) received", "ReqEdns0"); + SET_NSSTATDESC(badednsver, + "requests with unsupported EDNS version received", + "ReqBadEDNSVer"); + SET_NSSTATDESC(tsigin, "requests with TSIG received", "ReqTSIG"); + SET_NSSTATDESC(sig0in, "requests with SIG(0) received", "ReqSIG0"); + SET_NSSTATDESC(invalidsig, "requests with invalid signature", + "ReqBadSIG"); + SET_NSSTATDESC(requesttcp, "TCP requests received", "ReqTCP"); + SET_NSSTATDESC(tcphighwater, "TCP connection high-water", + "TCPConnHighWater"); + SET_NSSTATDESC(authrej, "auth queries rejected", "AuthQryRej"); + SET_NSSTATDESC(recurserej, "recursive queries rejected", "RecQryRej"); + SET_NSSTATDESC(xfrrej, "transfer requests rejected", "XfrRej"); + SET_NSSTATDESC(updaterej, "update requests rejected", "UpdateRej"); + SET_NSSTATDESC(response, "responses sent", "Response"); + SET_NSSTATDESC(truncatedresp, "truncated responses sent", + "TruncatedResp"); + SET_NSSTATDESC(edns0out, "responses with EDNS(0) sent", "RespEDNS0"); + SET_NSSTATDESC(tsigout, "responses with TSIG sent", "RespTSIG"); + SET_NSSTATDESC(sig0out, "responses with SIG(0) sent", "RespSIG0"); + SET_NSSTATDESC(success, "queries resulted in successful answer", + "QrySuccess"); + SET_NSSTATDESC(authans, "queries resulted in authoritative answer", + "QryAuthAns"); + SET_NSSTATDESC(nonauthans, + "queries resulted in non authoritative answer", + "QryNoauthAns"); + SET_NSSTATDESC(referral, "queries resulted in referral answer", + "QryReferral"); + SET_NSSTATDESC(nxrrset, "queries resulted in nxrrset", "QryNxrrset"); + SET_NSSTATDESC(servfail, "queries resulted in SERVFAIL", "QrySERVFAIL"); + SET_NSSTATDESC(formerr, "queries resulted in FORMERR", "QryFORMERR"); + SET_NSSTATDESC(nxdomain, "queries resulted in NXDOMAIN", "QryNXDOMAIN"); + SET_NSSTATDESC(recursion, "queries caused recursion", "QryRecursion"); + SET_NSSTATDESC(duplicate, "duplicate queries received", "QryDuplicate"); + SET_NSSTATDESC(dropped, "queries dropped", "QryDropped"); + SET_NSSTATDESC(failure, "other query failures", "QryFailure"); + SET_NSSTATDESC(xfrdone, "requested transfers completed", "XfrReqDone"); + SET_NSSTATDESC(updatereqfwd, "update requests forwarded", + "UpdateReqFwd"); + SET_NSSTATDESC(updaterespfwd, "update responses forwarded", + "UpdateRespFwd"); + SET_NSSTATDESC(updatefwdfail, "update forward failed", "UpdateFwdFail"); + SET_NSSTATDESC(updatedone, "updates completed", "UpdateDone"); + SET_NSSTATDESC(updatefail, "updates failed", "UpdateFail"); + SET_NSSTATDESC(updatebadprereq, + "updates rejected due to prerequisite failure", + "UpdateBadPrereq"); + SET_NSSTATDESC(recurshighwater, "Recursive clients high-water", + "RecursHighwater"); + SET_NSSTATDESC(recursclients, "recursing clients", "RecursClients"); + SET_NSSTATDESC(dns64, "queries answered by DNS64", "DNS64"); + SET_NSSTATDESC(ratedropped, "responses dropped for rate limits", + "RateDropped"); + SET_NSSTATDESC(rateslipped, "responses truncated for rate limits", + "RateSlipped"); + SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites", + "RPZRewrites"); + SET_NSSTATDESC(udp, "UDP queries received", "QryUDP"); + SET_NSSTATDESC(tcp, "TCP queries received", "QryTCP"); + SET_NSSTATDESC(nsidopt, "NSID option received", "NSIDOpt"); + SET_NSSTATDESC(expireopt, "Expire option received", "ExpireOpt"); + SET_NSSTATDESC(keepaliveopt, "EDNS TCP keepalive option received", + "KeepAliveOpt"); + SET_NSSTATDESC(padopt, "EDNS padding option received", "PadOpt"); + SET_NSSTATDESC(otheropt, "Other EDNS option received", "OtherOpt"); + SET_NSSTATDESC(cookiein, "COOKIE option received", "CookieIn"); + SET_NSSTATDESC(cookienew, "COOKIE - client only", "CookieNew"); + SET_NSSTATDESC(cookiebadsize, "COOKIE - bad size", "CookieBadSize"); + SET_NSSTATDESC(cookiebadtime, "COOKIE - bad time", "CookieBadTime"); + SET_NSSTATDESC(cookienomatch, "COOKIE - no match", "CookieNoMatch"); + SET_NSSTATDESC(cookiematch, "COOKIE - match", "CookieMatch"); + SET_NSSTATDESC(ecsopt, "EDNS client subnet option received", "ECSOpt"); + SET_NSSTATDESC(nxdomainredirect, + "queries resulted in NXDOMAIN that were redirected", + "QryNXRedir"); + SET_NSSTATDESC(nxdomainredirect_rlookup, + "queries resulted in NXDOMAIN that were redirected and " + "resulted in a successful remote lookup", + "QryNXRedirRLookup"); + SET_NSSTATDESC(badcookie, "sent badcookie response", "QryBADCOOKIE"); + SET_NSSTATDESC(nxdomainsynth, "synthesized a NXDOMAIN response", + "SynthNXDOMAIN"); + SET_NSSTATDESC(nodatasynth, "synthesized a no-data response", + "SynthNODATA"); + SET_NSSTATDESC(wildcardsynth, "synthesized a wildcard response", + "SynthWILDCARD"); + SET_NSSTATDESC(trystale, + "attempts to use stale cache data after lookup failure", + "QryTryStale"); + SET_NSSTATDESC(usedstale, + "successful uses of stale cache data after lookup " + "failure", + "QryUsedStale"); + SET_NSSTATDESC(prefetch, "queries triggered prefetch", "Prefetch"); + SET_NSSTATDESC(keytagopt, "Keytag option received", "KeyTagOpt"); + SET_NSSTATDESC(reclimitdropped, + "queries dropped due to recursive client limit", + "RecLimitDropped"); + SET_NSSTATDESC(updatequota, "Update quota exceeded", "UpdateQuota"); + + INSIST(i == ns_statscounter_max); + + /* Initialize resolver statistics */ + for (i = 0; i < dns_resstatscounter_max; i++) { + resstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < dns_resstatscounter_max; i++) { + resstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_RESSTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(dns_resstatscounter_##counterid, \ + dns_resstatscounter_max, desc, resstats_desc, \ + xmldesc, resstats_xmldesc); \ + resstats_index[i++] = dns_resstatscounter_##counterid; \ + } while (0) + + i = 0; + SET_RESSTATDESC(queryv4, "IPv4 queries sent", "Queryv4"); + SET_RESSTATDESC(queryv6, "IPv6 queries sent", "Queryv6"); + SET_RESSTATDESC(responsev4, "IPv4 responses received", "Responsev4"); + SET_RESSTATDESC(responsev6, "IPv6 responses received", "Responsev6"); + SET_RESSTATDESC(nxdomain, "NXDOMAIN received", "NXDOMAIN"); + SET_RESSTATDESC(servfail, "SERVFAIL received", "SERVFAIL"); + SET_RESSTATDESC(formerr, "FORMERR received", "FORMERR"); + SET_RESSTATDESC(othererror, "other errors received", "OtherError"); + SET_RESSTATDESC(edns0fail, "EDNS(0) query failures", "EDNS0Fail"); + SET_RESSTATDESC(mismatch, "mismatch responses received", "Mismatch"); + SET_RESSTATDESC(truncated, "truncated responses received", "Truncated"); + SET_RESSTATDESC(lame, "lame delegations received", "Lame"); + SET_RESSTATDESC(retry, "query retries", "Retry"); + SET_RESSTATDESC(dispabort, "queries aborted due to quota", + "QueryAbort"); + SET_RESSTATDESC(dispsockfail, "failures in opening query sockets", + "QuerySockFail"); + SET_RESSTATDESC(disprequdp, "UDP queries in progress", "QueryCurUDP"); + SET_RESSTATDESC(dispreqtcp, "TCP queries in progress", "QueryCurTCP"); + SET_RESSTATDESC(querytimeout, "query timeouts", "QueryTimeout"); + SET_RESSTATDESC(gluefetchv4, "IPv4 NS address fetches", "GlueFetchv4"); + SET_RESSTATDESC(gluefetchv6, "IPv6 NS address fetches", "GlueFetchv6"); + SET_RESSTATDESC(gluefetchv4fail, "IPv4 NS address fetch failed", + "GlueFetchv4Fail"); + SET_RESSTATDESC(gluefetchv6fail, "IPv6 NS address fetch failed", + "GlueFetchv6Fail"); + SET_RESSTATDESC(val, "DNSSEC validation attempted", "ValAttempt"); + SET_RESSTATDESC(valsuccess, "DNSSEC validation succeeded", "ValOk"); + SET_RESSTATDESC(valnegsuccess, "DNSSEC NX validation succeeded", + "ValNegOk"); + SET_RESSTATDESC(valfail, "DNSSEC validation failed", "ValFail"); + SET_RESSTATDESC(queryrtt0, + "queries with RTT < " DNS_RESOLVER_QRYRTTCLASS0STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS0STR); + SET_RESSTATDESC(queryrtt1, + "queries with RTT " DNS_RESOLVER_QRYRTTCLASS0STR + "-" DNS_RESOLVER_QRYRTTCLASS1STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS1STR); + SET_RESSTATDESC(queryrtt2, + "queries with RTT " DNS_RESOLVER_QRYRTTCLASS1STR + "-" DNS_RESOLVER_QRYRTTCLASS2STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS2STR); + SET_RESSTATDESC(queryrtt3, + "queries with RTT " DNS_RESOLVER_QRYRTTCLASS2STR + "-" DNS_RESOLVER_QRYRTTCLASS3STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS3STR); + SET_RESSTATDESC(queryrtt4, + "queries with RTT " DNS_RESOLVER_QRYRTTCLASS3STR + "-" DNS_RESOLVER_QRYRTTCLASS4STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR); + SET_RESSTATDESC(queryrtt5, + "queries with RTT > " DNS_RESOLVER_QRYRTTCLASS4STR "ms", + "QryRTT" DNS_RESOLVER_QRYRTTCLASS4STR "+"); + SET_RESSTATDESC(nfetch, "active fetches", "NumFetch"); + SET_RESSTATDESC(buckets, "bucket size", "BucketSize"); + SET_RESSTATDESC(refused, "REFUSED received", "REFUSED"); + SET_RESSTATDESC(cookienew, "COOKIE send with client cookie only", + "ClientCookieOut"); + SET_RESSTATDESC(cookieout, "COOKIE sent with client and server cookie", + "ServerCookieOut"); + SET_RESSTATDESC(cookiein, "COOKIE replies received", "CookieIn"); + SET_RESSTATDESC(cookieok, "COOKIE client ok", "CookieClientOk"); + SET_RESSTATDESC(badvers, "bad EDNS version", "BadEDNSVersion"); + SET_RESSTATDESC(badcookie, "bad cookie rcode", "BadCookieRcode"); + SET_RESSTATDESC(zonequota, "spilled due to zone quota", "ZoneQuota"); + SET_RESSTATDESC(serverquota, "spilled due to server quota", + "ServerQuota"); + SET_RESSTATDESC(clientquota, "spilled due to clients per query quota", + "ClientQuota"); + SET_RESSTATDESC(nextitem, "waited for next item", "NextItem"); + SET_RESSTATDESC(priming, "priming queries", "Priming"); + + INSIST(i == dns_resstatscounter_max); + + /* Initialize adb statistics */ + for (i = 0; i < dns_adbstats_max; i++) { + adbstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < dns_adbstats_max; i++) { + adbstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_ADBSTATDESC(id, desc, xmldesc) \ + do { \ + set_desc(dns_adbstats_##id, dns_adbstats_max, desc, \ + adbstats_desc, xmldesc, adbstats_xmldesc); \ + adbstats_index[i++] = dns_adbstats_##id; \ + } while (0) + i = 0; + SET_ADBSTATDESC(nentries, "Address hash table size", "nentries"); + SET_ADBSTATDESC(entriescnt, "Addresses in hash table", "entriescnt"); + SET_ADBSTATDESC(nnames, "Name hash table size", "nnames"); + SET_ADBSTATDESC(namescnt, "Names in hash table", "namescnt"); + + INSIST(i == dns_adbstats_max); + + /* Initialize zone statistics */ + for (i = 0; i < dns_zonestatscounter_max; i++) { + zonestats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < dns_zonestatscounter_max; i++) { + zonestats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_ZONESTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(dns_zonestatscounter_##counterid, \ + dns_zonestatscounter_max, desc, zonestats_desc, \ + xmldesc, zonestats_xmldesc); \ + zonestats_index[i++] = dns_zonestatscounter_##counterid; \ + } while (0) + + i = 0; + SET_ZONESTATDESC(notifyoutv4, "IPv4 notifies sent", "NotifyOutv4"); + SET_ZONESTATDESC(notifyoutv6, "IPv6 notifies sent", "NotifyOutv6"); + SET_ZONESTATDESC(notifyinv4, "IPv4 notifies received", "NotifyInv4"); + SET_ZONESTATDESC(notifyinv6, "IPv6 notifies received", "NotifyInv6"); + SET_ZONESTATDESC(notifyrej, "notifies rejected", "NotifyRej"); + SET_ZONESTATDESC(soaoutv4, "IPv4 SOA queries sent", "SOAOutv4"); + SET_ZONESTATDESC(soaoutv6, "IPv6 SOA queries sent", "SOAOutv6"); + SET_ZONESTATDESC(axfrreqv4, "IPv4 AXFR requested", "AXFRReqv4"); + SET_ZONESTATDESC(axfrreqv6, "IPv6 AXFR requested", "AXFRReqv6"); + SET_ZONESTATDESC(ixfrreqv4, "IPv4 IXFR requested", "IXFRReqv4"); + SET_ZONESTATDESC(ixfrreqv6, "IPv6 IXFR requested", "IXFRReqv6"); + SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded", + "XfrSuccess"); + SET_ZONESTATDESC(xfrfail, "transfer requests failed", "XfrFail"); + INSIST(i == dns_zonestatscounter_max); + + /* Initialize socket statistics */ + for (i = 0; i < isc_sockstatscounter_max; i++) { + sockstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < isc_sockstatscounter_max; i++) { + sockstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_SOCKSTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(isc_sockstatscounter_##counterid, \ + isc_sockstatscounter_max, desc, sockstats_desc, \ + xmldesc, sockstats_xmldesc); \ + sockstats_index[i++] = isc_sockstatscounter_##counterid; \ + } while (0) + + i = 0; + SET_SOCKSTATDESC(udp4open, "UDP/IPv4 sockets opened", "UDP4Open"); + SET_SOCKSTATDESC(udp6open, "UDP/IPv6 sockets opened", "UDP6Open"); + SET_SOCKSTATDESC(tcp4open, "TCP/IPv4 sockets opened", "TCP4Open"); + SET_SOCKSTATDESC(tcp6open, "TCP/IPv6 sockets opened", "TCP6Open"); + SET_SOCKSTATDESC(udp4openfail, "UDP/IPv4 socket open failures", + "UDP4OpenFail"); + SET_SOCKSTATDESC(udp6openfail, "UDP/IPv6 socket open failures", + "UDP6OpenFail"); + SET_SOCKSTATDESC(tcp4openfail, "TCP/IPv4 socket open failures", + "TCP4OpenFail"); + SET_SOCKSTATDESC(tcp6openfail, "TCP/IPv6 socket open failures", + "TCP6OpenFail"); + SET_SOCKSTATDESC(udp4close, "UDP/IPv4 sockets closed", "UDP4Close"); + SET_SOCKSTATDESC(udp6close, "UDP/IPv6 sockets closed", "UDP6Close"); + SET_SOCKSTATDESC(tcp4close, "TCP/IPv4 sockets closed", "TCP4Close"); + SET_SOCKSTATDESC(tcp6close, "TCP/IPv6 sockets closed", "TCP6Close"); + SET_SOCKSTATDESC(udp4bindfail, "UDP/IPv4 socket bind failures", + "UDP4BindFail"); + SET_SOCKSTATDESC(udp6bindfail, "UDP/IPv6 socket bind failures", + "UDP6BindFail"); + SET_SOCKSTATDESC(tcp4bindfail, "TCP/IPv4 socket bind failures", + "TCP4BindFail"); + SET_SOCKSTATDESC(tcp6bindfail, "TCP/IPv6 socket bind failures", + "TCP6BindFail"); + SET_SOCKSTATDESC(udp4connectfail, "UDP/IPv4 socket connect failures", + "UDP4ConnFail"); + SET_SOCKSTATDESC(udp6connectfail, "UDP/IPv6 socket connect failures", + "UDP6ConnFail"); + SET_SOCKSTATDESC(tcp4connectfail, "TCP/IPv4 socket connect failures", + "TCP4ConnFail"); + SET_SOCKSTATDESC(tcp6connectfail, "TCP/IPv6 socket connect failures", + "TCP6ConnFail"); + SET_SOCKSTATDESC(udp4connect, "UDP/IPv4 connections established", + "UDP4Conn"); + SET_SOCKSTATDESC(udp6connect, "UDP/IPv6 connections established", + "UDP6Conn"); + SET_SOCKSTATDESC(tcp4connect, "TCP/IPv4 connections established", + "TCP4Conn"); + SET_SOCKSTATDESC(tcp6connect, "TCP/IPv6 connections established", + "TCP6Conn"); + SET_SOCKSTATDESC(tcp4acceptfail, "TCP/IPv4 connection accept failures", + "TCP4AcceptFail"); + SET_SOCKSTATDESC(tcp6acceptfail, "TCP/IPv6 connection accept failures", + "TCP6AcceptFail"); + SET_SOCKSTATDESC(tcp4accept, "TCP/IPv4 connections accepted", + "TCP4Accept"); + SET_SOCKSTATDESC(tcp6accept, "TCP/IPv6 connections accepted", + "TCP6Accept"); + SET_SOCKSTATDESC(udp4sendfail, "UDP/IPv4 send errors", "UDP4SendErr"); + SET_SOCKSTATDESC(udp6sendfail, "UDP/IPv6 send errors", "UDP6SendErr"); + SET_SOCKSTATDESC(tcp4sendfail, "TCP/IPv4 send errors", "TCP4SendErr"); + SET_SOCKSTATDESC(tcp6sendfail, "TCP/IPv6 send errors", "TCP6SendErr"); + SET_SOCKSTATDESC(udp4recvfail, "UDP/IPv4 recv errors", "UDP4RecvErr"); + SET_SOCKSTATDESC(udp6recvfail, "UDP/IPv6 recv errors", "UDP6RecvErr"); + SET_SOCKSTATDESC(tcp4recvfail, "TCP/IPv4 recv errors", "TCP4RecvErr"); + SET_SOCKSTATDESC(tcp6recvfail, "TCP/IPv6 recv errors", "TCP6RecvErr"); + SET_SOCKSTATDESC(udp4active, "UDP/IPv4 sockets active", "UDP4Active"); + SET_SOCKSTATDESC(udp6active, "UDP/IPv6 sockets active", "UDP6Active"); + SET_SOCKSTATDESC(tcp4active, "TCP/IPv4 sockets active", "TCP4Active"); + SET_SOCKSTATDESC(tcp6active, "TCP/IPv6 sockets active", "TCP6Active"); + SET_SOCKSTATDESC(tcp4clients, "TCP/IPv4 clients currently connected", + "TCP4Clients"); + SET_SOCKSTATDESC(tcp6clients, "TCP/IPv6 clients currently connected", + "TCP6Clients"); + INSIST(i == isc_sockstatscounter_max); + + /* Initialize DNSSEC statistics */ + for (i = 0; i < dns_dnssecstats_max; i++) { + dnssecstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < dns_dnssecstats_max; i++) { + dnssecstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_DNSSECSTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(dns_dnssecstats_##counterid, dns_dnssecstats_max, \ + desc, dnssecstats_desc, xmldesc, \ + dnssecstats_xmldesc); \ + dnssecstats_index[i++] = dns_dnssecstats_##counterid; \ + } while (0) + + i = 0; + SET_DNSSECSTATDESC(asis, + "dnssec validation success with signer " + "\"as is\"", + "DNSSECasis"); + SET_DNSSECSTATDESC(downcase, + "dnssec validation success with signer " + "lower cased", + "DNSSECdowncase"); + SET_DNSSECSTATDESC(wildcard, "dnssec validation of wildcard signature", + "DNSSECwild"); + SET_DNSSECSTATDESC(fail, "dnssec validation failures", "DNSSECfail"); + INSIST(i == dns_dnssecstats_max); + + /* Initialize dnstap statistics */ + for (i = 0; i < dns_dnstapcounter_max; i++) { + dnstapstats_desc[i] = NULL; + } +#if defined(EXTENDED_STATS) + for (i = 0; i < dns_dnstapcounter_max; i++) { + dnstapstats_xmldesc[i] = NULL; + } +#endif /* if defined(EXTENDED_STATS) */ + +#define SET_DNSTAPSTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(dns_dnstapcounter_##counterid, dns_dnstapcounter_max, \ + desc, dnstapstats_desc, xmldesc, \ + dnstapstats_xmldesc); \ + dnstapstats_index[i++] = dns_dnstapcounter_##counterid; \ + } while (0) + i = 0; + SET_DNSTAPSTATDESC(success, "dnstap messages written", "DNSTAPsuccess"); + SET_DNSTAPSTATDESC(drop, "dnstap messages dropped", "DNSTAPdropped"); + INSIST(i == dns_dnstapcounter_max); + +#define SET_GLUECACHESTATDESC(counterid, desc, xmldesc) \ + do { \ + set_desc(dns_gluecachestatscounter_##counterid, \ + dns_gluecachestatscounter_max, desc, \ + gluecachestats_desc, xmldesc, \ + gluecachestats_xmldesc); \ + gluecachestats_index[i++] = \ + dns_gluecachestatscounter_##counterid; \ + } while (0) + i = 0; + SET_GLUECACHESTATDESC(hits_present, "Hits for present glue (cached)", + "GLUECACHEhitspresent"); + SET_GLUECACHESTATDESC(hits_absent, + "Hits for non-existent glue (cached)", + "GLUECACHEhitsabsent"); + SET_GLUECACHESTATDESC(inserts_present, + "Miss-plus-cache-inserts for present glue", + "GLUECACHEinsertspresent"); + SET_GLUECACHESTATDESC(inserts_absent, + "Miss-plus-cache-inserts for non-existent glue", + "GLUECACHEinsertsabsent"); + INSIST(i == dns_gluecachestatscounter_max); + + /* Sanity check */ + for (i = 0; i < ns_statscounter_max; i++) { + INSIST(nsstats_desc[i] != NULL); + } + for (i = 0; i < dns_resstatscounter_max; i++) { + INSIST(resstats_desc[i] != NULL); + } + for (i = 0; i < dns_adbstats_max; i++) { + INSIST(adbstats_desc[i] != NULL); + } + for (i = 0; i < dns_zonestatscounter_max; i++) { + INSIST(zonestats_desc[i] != NULL); + } + for (i = 0; i < isc_sockstatscounter_max; i++) { + INSIST(sockstats_desc[i] != NULL); + } + for (i = 0; i < dns_dnssecstats_max; i++) { + INSIST(dnssecstats_desc[i] != NULL); + } + for (i = 0; i < dns_dnstapcounter_max; i++) { + INSIST(dnstapstats_desc[i] != NULL); + } + for (i = 0; i < dns_gluecachestatscounter_max; i++) { + INSIST(gluecachestats_desc[i] != NULL); + } +#if defined(EXTENDED_STATS) + for (i = 0; i < ns_statscounter_max; i++) { + INSIST(nsstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_resstatscounter_max; i++) { + INSIST(resstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_adbstats_max; i++) { + INSIST(adbstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_zonestatscounter_max; i++) { + INSIST(zonestats_xmldesc[i] != NULL); + } + for (i = 0; i < isc_sockstatscounter_max; i++) { + INSIST(sockstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_dnssecstats_max; i++) { + INSIST(dnssecstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_dnstapcounter_max; i++) { + INSIST(dnstapstats_xmldesc[i] != NULL); + } + for (i = 0; i < dns_gluecachestatscounter_max; i++) { + INSIST(gluecachestats_xmldesc[i] != NULL); + } +#endif /* if defined(EXTENDED_STATS) */ + + /* Initialize traffic size statistics */ + + for (i = 0; i < DNS_SIZEHISTO_MAXOUT; i++) { + udpoutsizestats_index[i] = i; + tcpoutsizestats_index[i] = i; + udpoutsizestats_desc[i] = get_histo_desc( + "responses sent", i, DNS_SIZEHISTO_MAXOUT, false); + tcpoutsizestats_desc[i] = udpoutsizestats_desc[i]; +#if defined(EXTENDED_STATS) + udpoutsizestats_xmldesc[i] = get_histo_desc( + "responses sent", i, DNS_SIZEHISTO_MAXOUT, true); + tcpoutsizestats_xmldesc[i] = udpoutsizestats_xmldesc[i]; +#endif /* if defined(EXTENDED_STATS) */ + } + + for (i = 0; i <= DNS_SIZEHISTO_MAXIN; i++) { + udpinsizestats_index[i] = i; + tcpinsizestats_index[i] = i; + udpinsizestats_desc[i] = get_histo_desc( + "requests received", i, DNS_SIZEHISTO_MAXIN, false); + tcpinsizestats_desc[i] = udpinsizestats_desc[i]; +#if defined(EXTENDED_STATS) + if (i < DNS_SIZEHISTO_MAXIN) { + udpinsizestats_xmldesc[i] = udpoutsizestats_xmldesc[i]; + tcpinsizestats_xmldesc[i] = tcpoutsizestats_xmldesc[i]; + } else { + udpinsizestats_xmldesc[i] = + get_histo_desc("requests received", i, + DNS_SIZEHISTO_MAXIN, true); + tcpinsizestats_xmldesc[i] = udpinsizestats_xmldesc[i]; + } +#endif /* if defined(EXTENDED_STATS) */ + } +} + +/*% + * Dump callback functions. + */ + +static isc_result_t +dump_counters(isc_statsformat_t type, void *arg, const char *category, + const char **desc, int ncounters, int *indices, uint64_t *values, + int options); + +static void +generalstat_dump(isc_statscounter_t counter, uint64_t val, void *arg) { + stats_dumparg_t *dumparg = arg; + + REQUIRE(counter < dumparg->ncounters); + dumparg->countervalues[counter] = val; +} + +static isc_result_t +dump_stats(isc_stats_t *stats, isc_statsformat_t type, void *arg, + const char *category, const char **desc, int ncounters, int *indices, + uint64_t *values, int options) { + stats_dumparg_t dumparg; + + dumparg.type = type; + dumparg.ncounters = ncounters; + dumparg.counterindices = indices; + dumparg.countervalues = values; + + memset(values, 0, sizeof(values[0]) * ncounters); + isc_stats_dump(stats, generalstat_dump, &dumparg, options); + + return dump_counters(type, arg, category, desc, ncounters, indices, + values, options); +} + +#if defined(EXTENDED_STATS) +static isc_result_t +dump_histo(isc_histomulti_t *hm, isc_statsformat_t type, void *arg, + const char *category, const char **desc, int ncounters, int *indices, + uint64_t *values, int options) { + isc_histo_t *hg = NULL; + + isc_histomulti_merge(&hg, hm); + for (int i = 0; i < ncounters; i++) { + isc_histo_get(hg, i, NULL, NULL, &values[i]); + } + isc_histo_destroy(&hg); + + return dump_counters(type, arg, category, desc, ncounters, indices, + values, options); +} +#endif /* defined(EXTENDED_STATS) */ + +static isc_result_t +dump_counters(isc_statsformat_t type, void *arg, const char *category, + const char **desc, int ncounters, int *indices, uint64_t *values, + int options) { + int i, idx; + uint64_t value; + FILE *fp; +#ifdef HAVE_LIBXML2 + void *writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *job, *cat, *counter; +#endif /* ifdef HAVE_JSON_C */ + +#if !defined(EXTENDED_STATS) + UNUSED(category); +#endif /* if !defined(EXTENDED_STATS) */ + +#ifdef HAVE_JSON_C + cat = job = (json_object *)arg; + if (ncounters > 0 && type == isc_statsformat_json) { + if (category != NULL) { + cat = json_object_new_object(); + if (cat == NULL) { + return ISC_R_NOMEMORY; + } + json_object_object_add(job, category, cat); + } + } +#endif /* ifdef HAVE_JSON_C */ + + for (i = 0; i < ncounters; i++) { + idx = indices[i]; + value = values[idx]; + + if (value == 0 && (options & ISC_STATSDUMP_VERBOSE) == 0) { + continue; + } + + switch (type) { + case isc_statsformat_file: + fp = arg; + fprintf(fp, "%20" PRIu64 " %s\n", value, desc[idx]); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = arg; + + if (category != NULL) { + /* */ + TRY0(xmlTextWriterStartElement( + writer, ISC_XMLCHAR category)); + + /* inside category */ + TRY0(xmlTextWriterStartElement( + writer, ISC_XMLCHAR "name")); + TRY0(xmlTextWriterWriteString( + writer, ISC_XMLCHAR desc[idx])); + TRY0(xmlTextWriterEndElement(writer)); + /* */ + + /* */ + TRY0(xmlTextWriterStartElement( + writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteFormatString( + writer, "%" PRIu64, value)); + + TRY0(xmlTextWriterEndElement(writer)); + /* */ + TRY0(xmlTextWriterEndElement(writer)); + /* */ + } else { + TRY0(xmlTextWriterStartElement( + writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute( + writer, ISC_XMLCHAR "name", + ISC_XMLCHAR desc[idx])); + TRY0(xmlTextWriterWriteFormatString( + writer, "%" PRIu64, value)); + TRY0(xmlTextWriterEndElement(writer)); + /* counter */ + } + +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + counter = json_object_new_int64(value); + if (counter == NULL) { + return ISC_R_NOMEMORY; + } + json_object_object_add(cat, desc[idx], counter); +#endif /* ifdef HAVE_JSON_C */ + break; + } + } + return ISC_R_SUCCESS; +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at dump_counters()"); + return ISC_R_FAILURE; +#endif /* ifdef HAVE_LIBXML2 */ +} + +static void +rdtypestat_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) { + char typebuf[64]; + const char *typestr; + stats_dumparg_t *dumparg = arg; + FILE *fp; +#ifdef HAVE_LIBXML2 + void *writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *zoneobj, *obj; +#endif /* ifdef HAVE_JSON_C */ + + if ((DNS_RDATASTATSTYPE_ATTR(type) & + DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) == 0) + { + dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf, + sizeof(typebuf)); + typestr = typebuf; + } else { + typestr = "Others"; + } + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s\n", val, typestr); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR typestr)); + + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val)); + + TRY0(xmlTextWriterEndElement(writer)); /* type */ +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + zoneobj = (json_object *)dumparg->arg; + obj = json_object_new_int64(val); + if (obj == NULL) { + return; + } + json_object_object_add(zoneobj, typestr, obj); +#endif /* ifdef HAVE_JSON_C */ + break; + } + return; +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rdtypestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif /* ifdef HAVE_LIBXML2 */ +} + +static bool +rdatastatstype_attr(dns_rdatastatstype_t type, unsigned int attr) { + return (DNS_RDATASTATSTYPE_ATTR(type) & attr) != 0; +} + +static void +rdatasetstats_dump(dns_rdatastatstype_t type, uint64_t val, void *arg) { + stats_dumparg_t *dumparg = arg; + FILE *fp; + char typebuf[64]; + const char *typestr; + bool nxrrset = false; + bool stale = false; + bool ancient = false; +#ifdef HAVE_LIBXML2 + void *writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *zoneobj, *obj; + char buf[1024]; +#endif /* ifdef HAVE_JSON_C */ + + if ((DNS_RDATASTATSTYPE_ATTR(type) & + DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) + { + typestr = "NXDOMAIN"; + } else if ((DNS_RDATASTATSTYPE_ATTR(type) & + DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) + { + typestr = "Others"; + } else { + dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf, + sizeof(typebuf)); + typestr = typebuf; + } + + nxrrset = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_NXRRSET); + stale = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_STALE); + ancient = rdatastatstype_attr(type, DNS_RDATASTATSTYPE_ATTR_ANCIENT); + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s%s%s%s\n", val, ancient ? "~" : "", + stale ? "#" : "", nxrrset ? "!" : "", typestr); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name")); + TRY0(xmlTextWriterWriteFormatString( + writer, "%s%s%s%s", ancient ? "~" : "", + stale ? "#" : "", nxrrset ? "!" : "", typestr)); + TRY0(xmlTextWriterEndElement(writer)); /* name */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ + + TRY0(xmlTextWriterEndElement(writer)); /* rrset */ +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + zoneobj = (json_object *)dumparg->arg; + snprintf(buf, sizeof(buf), "%s%s%s%s", ancient ? "~" : "", + stale ? "#" : "", nxrrset ? "!" : "", typestr); + obj = json_object_new_int64(val); + if (obj == NULL) { + return; + } + json_object_object_add(zoneobj, buf, obj); +#endif /* ifdef HAVE_JSON_C */ + break; + } + return; +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rdatasetstats_dump()"); + dumparg->result = ISC_R_FAILURE; +#endif /* ifdef HAVE_LIBXML2 */ +} + +static void +opcodestat_dump(dns_opcode_t code, uint64_t val, void *arg) { + FILE *fp; + isc_buffer_t b; + char codebuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + void *writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *zoneobj, *obj; +#endif /* ifdef HAVE_JSON_C */ + + isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); + dns_opcode_totext(code, &b); + codebuf[isc_buffer_usedlength(&b)] = '\0'; + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR codebuf)); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + zoneobj = (json_object *)dumparg->arg; + obj = json_object_new_int64(val); + if (obj == NULL) { + return; + } + json_object_object_add(zoneobj, codebuf, obj); +#endif /* ifdef HAVE_JSON_C */ + break; + } + return; + +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at opcodestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif /* ifdef HAVE_LIBXML2 */ +} + +static void +rcodestat_dump(dns_rcode_t code, uint64_t val, void *arg) { + FILE *fp; + isc_buffer_t b; + char codebuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + void *writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *zoneobj, *obj; +#endif /* ifdef HAVE_JSON_C */ + + isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); + dns_rcode_totext(code, &b); + codebuf[isc_buffer_usedlength(&b)] = '\0'; + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s\n", val, codebuf); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR codebuf)); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + zoneobj = (json_object *)dumparg->arg; + obj = json_object_new_int64(val); + if (obj == NULL) { + return; + } + json_object_object_add(zoneobj, codebuf, obj); +#endif /* ifdef HAVE_JSON_C */ + break; + } + return; + +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rcodestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif /* ifdef HAVE_LIBXML2 */ +} + +#if defined(EXTENDED_STATS) +static void +dnssecsignstat_dump(uint32_t kval, uint64_t val, void *arg) { + FILE *fp; + char tagbuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + xmlTextWriterPtr writer; + int xmlrc; +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + json_object *zoneobj, *obj; +#endif /* ifdef HAVE_JSON_C */ + + /* + * kval is '(algorithm << 16) | keyid'. + */ + snprintf(tagbuf, sizeof(tagbuf), "%u+%u", (kval >> 16) & 0xff, + kval & 0xffff); + + switch (dumparg->type) { + case isc_statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" PRIu64 " %s\n", val, tagbuf); + break; + case isc_statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR tagbuf)); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ +#endif /* ifdef HAVE_LIBXML2 */ + break; + case isc_statsformat_json: +#ifdef HAVE_JSON_C + zoneobj = (json_object *)dumparg->arg; + obj = json_object_new_int64(val); + if (obj == NULL) { + return; + } + json_object_object_add(zoneobj, tagbuf, obj); +#endif /* ifdef HAVE_JSON_C */ + break; + } + return; +#ifdef HAVE_LIBXML2 +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at dnssecsignstat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif /* ifdef HAVE_LIBXML2 */ +} +#endif /* defined(EXTENDED_STATS) */ + +#ifdef HAVE_LIBXML2 +/* + * Which statistics to include when rendering to XML + */ +#define STATS_XML_STATUS 0x00 /* display only common statistics */ +#define STATS_XML_SERVER 0x01 +#define STATS_XML_ZONES 0x02 +#define STATS_XML_XFRINS 0x04 +#define STATS_XML_NET 0x08 +#define STATS_XML_MEM 0x10 +#define STATS_XML_TRAFFIC 0x20 +#define STATS_XML_ALL 0xff + +static isc_result_t +zone_xmlrender(dns_zone_t *zone, void *arg) { + isc_result_t result; + char buf[1024 + 32]; /* sufficiently large for zone name and class */ + dns_rdataclass_t rdclass; + uint32_t serial; + xmlTextWriterPtr writer = arg; + dns_zonestat_level_t statlevel; + int xmlrc; + stats_dumparg_t dumparg; + const char *ztype; + isc_time_t timestamp; + + statlevel = dns_zone_getstatlevel(zone); + if (statlevel == dns_zonestat_none) { + return ISC_R_SUCCESS; + } + + dumparg.type = isc_statsformat_xml; + dumparg.arg = writer; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone")); + + dns_zone_nameonly(zone, buf, sizeof(buf)); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR buf)); + + rdclass = dns_zone_getclass(zone); + dns_rdataclass_format(rdclass, buf, sizeof(buf)); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass", + ISC_XMLCHAR buf)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type")); + ztype = user_zonetype(zone); + if (ztype != NULL) { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "unknown")); + } + TRY0(xmlTextWriterEndElement(writer)); /* type */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial")); + if (dns_zone_getserial(zone, &serial) == ISC_R_SUCCESS) { + TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); /* serial */ + + /* + * Export zone timers to the statistics channel in XML format. For + * primary zones, only include the loaded time. For secondary zones, + * also include the expire and refresh times. + */ + CHECK(dns_zone_getloadtime(zone, ×tamp)); + + isc_time_formatISO8601(×tamp, buf, 64); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "loaded")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf)); + TRY0(xmlTextWriterEndElement(writer)); + + if (dns_zone_gettype(zone) == dns_zone_secondary) { + CHECK(dns_zone_getexpiretime(zone, ×tamp)); + isc_time_formatISO8601(×tamp, buf, 64); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "expires")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf)); + TRY0(xmlTextWriterEndElement(writer)); + + CHECK(dns_zone_getrefreshtime(zone, ×tamp)); + isc_time_formatISO8601(×tamp, buf, 64); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refresh")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR buf)); + TRY0(xmlTextWriterEndElement(writer)); + } + + if (statlevel == dns_zonestat_full) { + isc_stats_t *zonestats; + isc_stats_t *gluecachestats; + dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; + uint64_t nsstat_values[ns_statscounter_max]; + uint64_t gluecachestats_values[dns_gluecachestatscounter_max]; + + zonestats = dns_zone_getrequeststats(zone); + if (zonestats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR "type", + ISC_XMLCHAR "rcode")); + + CHECK(dump_stats(zonestats, isc_statsformat_xml, writer, + NULL, nsstats_xmldesc, + ns_statscounter_max, nsstats_index, + nsstat_values, ISC_STATSDUMP_VERBOSE)); + /* counters type="rcode"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + + gluecachestats = dns_zone_getgluecachestats(zone); + if (gluecachestats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute( + writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "gluecache")); + + CHECK(dump_stats(gluecachestats, isc_statsformat_xml, + writer, NULL, gluecachestats_xmldesc, + dns_gluecachestatscounter_max, + gluecachestats_index, + gluecachestats_values, + ISC_STATSDUMP_VERBOSE)); + /* counters type="rcode"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + + rcvquerystats = dns_zone_getrcvquerystats(zone); + if (rcvquerystats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR "type", + ISC_XMLCHAR "qtype")); + + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, + &dumparg, 0); + CHECK(dumparg.result); + + /* counters type="qtype"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + + dnssecsignstats = dns_zone_getdnssecsignstats(zone); + if (dnssecsignstats != NULL) { + /* counters type="dnssec-sign"*/ + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute( + writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "dnssec-sign")); + + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump( + dnssecsignstats, dns_dnssecsignstats_sign, + dnssecsignstat_dump, &dumparg, 0); + CHECK(dumparg.result); + + /* counters type="dnssec-sign"*/ + TRY0(xmlTextWriterEndElement(writer)); + + /* counters type="dnssec-refresh"*/ + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute( + writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "dnssec-refresh")); + + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump( + dnssecsignstats, dns_dnssecsignstats_refresh, + dnssecsignstat_dump, &dumparg, 0); + CHECK(dumparg.result); + + /* counters type="dnssec-refresh"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + } + + TRY0(xmlTextWriterEndElement(writer)); /* zone */ + + return ISC_R_SUCCESS; +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Failed at zone_xmlrender()"); + return ISC_R_FAILURE; +} + +static isc_result_t +xfrin_xmlrender(dns_zone_t *zone, void *arg) { + char buf[1024 + 32]; /* sufficiently large for zone name and class */ + dns_rdataclass_t rdclass; + const char *ztype; + uint32_t serial; + isc_sockaddr_t addr; + const isc_sockaddr_t *addrp = NULL; + char addr_buf[ISC_SOCKADDR_FORMATSIZE]; + dns_transport_type_t transport_type; + xmlTextWriterPtr writer = arg; + dns_zonestat_level_t statlevel; + int xmlrc; + dns_xfrin_t *xfr = NULL; + bool is_firstrefresh, is_running, is_deferred, is_presoa, is_pending; + bool needs_refresh; + bool is_first_data_received, is_ixfr; + unsigned int nmsg = 0; + unsigned int nrecs = 0; + uint64_t nbytes = 0; + uint64_t rate = 0; + + statlevel = dns_zone_getstatlevel(zone); + if (statlevel == dns_zonestat_none) { + return ISC_R_SUCCESS; + } + + if (dns_zone_getxfr(zone, &xfr, &is_firstrefresh, &is_running, + &is_deferred, &is_presoa, &is_pending, + &needs_refresh) != ISC_R_SUCCESS) + { + /* + * Failed to get information about the zone's incoming transfer + * (if any), but we still want to continue generating the + * remaining parts of the output. + */ + return ISC_R_SUCCESS; + } + + if (!is_running && !is_deferred && !is_presoa && !is_pending && + !needs_refresh) + { + if (xfr != NULL) { + dns_xfrin_detach(&xfr); + } + /* No ongoing/queued transfer. */ + return ISC_R_SUCCESS; + } + + if (is_running && xfr == NULL) { + /* The transfer is finished, and it's shutting down. */ + return ISC_R_SUCCESS; + } + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "xfrin")); + + dns_zone_nameonly(zone, buf, sizeof(buf)); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR buf)); + + rdclass = dns_zone_getclass(zone); + dns_rdataclass_format(rdclass, buf, sizeof(buf)); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "class", + ISC_XMLCHAR buf)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type")); + ztype = user_zonetype(zone); + if (ztype != NULL) { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial")); + if (dns_zone_getserial(zone, &serial) == ISC_R_SUCCESS) { + TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "remoteserial")); + if (is_running) { + serial = dns_xfrin_getendserial(xfr); + if (serial != 0) { + TRY0(xmlTextWriterWriteFormatString(writer, "%u", + serial)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "firstrefresh")); + TRY0(xmlTextWriterWriteString( + writer, ISC_XMLCHAR(is_firstrefresh ? "Yes" : "No"))); + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "state")); + if (is_running) { + const char *xfr_state = NULL; + + dns_xfrin_getstate(xfr, &xfr_state, &is_first_data_received, + &is_ixfr); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR xfr_state)); + } else if (is_deferred) { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "Deferred")); + } else if (is_presoa) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "Refresh SOA")); + } else if (is_pending) { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "Pending")); + } else if (needs_refresh) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "Needs Refresh")); + } else { + UNREACHABLE(); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refreshqueued")); + TRY0(xmlTextWriterWriteString( + writer, + ISC_XMLCHAR(is_running && needs_refresh ? "Yes" : "No"))); + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "localaddr")); + if (is_running) { + addrp = dns_xfrin_getsourceaddr(xfr); + isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); + } else if (is_presoa) { + dns_zone_getsourceaddr(zone, &addr); + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "remoteaddr")); + if (is_running) { + addrp = dns_xfrin_getprimaryaddr(xfr); + isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); + } else if (is_presoa) { + if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR addr_buf)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "soatransport")); + if (is_running || is_presoa) { + if (is_running) { + transport_type = dns_xfrin_getsoatransporttype(xfr); + } else { + transport_type = dns_zone_getrequesttransporttype(zone); + } + if (transport_type == DNS_TRANSPORT_UDP) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "UDP")); + } else if (transport_type == DNS_TRANSPORT_TCP) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "TCP")); + } else if (transport_type == DNS_TRANSPORT_TLS) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "TLS")); + } else if (transport_type == DNS_TRANSPORT_NONE) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "None")); + } else { + /* We don't expect any other SOA transport type. */ + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "transport")); + if (is_running) { + transport_type = dns_xfrin_gettransporttype(xfr); + if (transport_type == DNS_TRANSPORT_TCP) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "TCP")); + } else if (transport_type == DNS_TRANSPORT_TLS) { + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR "TLS")); + } else { + /* We don't expect any other transport type. */ + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tsigkeyname")); + if (is_running) { + const dns_name_t *tsigkeyname = dns_xfrin_gettsigkeyname(xfr); + char tsigkeyname_buf[DNS_NAME_FORMATSIZE]; + + if (tsigkeyname != NULL) { + dns_name_format(tsigkeyname, tsigkeyname_buf, + sizeof(tsigkeyname_buf)); + TRY0(xmlTextWriterWriteString( + writer, ISC_XMLCHAR tsigkeyname_buf)); + } + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "duration")); + if (is_running || is_deferred || is_presoa || is_pending) { + isc_time_t start = is_running ? dns_xfrin_getstarttime(xfr) + : dns_zone_getxfrintime(zone); + isc_time_t now = isc_time_now(); + isc_time_t diff; + uint32_t sec; + + isc_time_subtract(&now, &start, &diff); + sec = isc_time_seconds(&diff); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu32, sec)); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "0")); + } + TRY0(xmlTextWriterEndElement(writer)); + + if (is_running) { + dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes, &rate); + } + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nmsg")); + TRY0(xmlTextWriterWriteFormatString(writer, "%u", nmsg)); + TRY0(xmlTextWriterEndElement(writer)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nrecs")); + TRY0(xmlTextWriterWriteFormatString(writer, "%u", nrecs)); + TRY0(xmlTextWriterEndElement(writer)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nbytes")); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, nbytes)); + TRY0(xmlTextWriterEndElement(writer)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "rate")); + TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, rate)); + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ixfr")); + if (is_running && is_first_data_received) { + TRY0(xmlTextWriterWriteString( + writer, ISC_XMLCHAR(is_ixfr ? "Yes" : "No"))); + } else { + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "")); + } + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterEndElement(writer)); /* xfrin */ + + if (xfr != NULL) { + dns_xfrin_detach(&xfr); + } + + return ISC_R_SUCCESS; + +cleanup: + if (xfr != NULL) { + dns_xfrin_detach(&xfr); + } + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "Failed at xfrin_xmlrender()"); + + return ISC_R_FAILURE; +} + +static isc_result_t +generatexml(named_server_t *server, uint32_t flags, int *buflen, + xmlChar **buf) { + char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + isc_time_t now = isc_time_now(); + xmlTextWriterPtr writer = NULL; + xmlDocPtr doc = NULL; + int xmlrc; + dns_view_t *view; + stats_dumparg_t dumparg; + dns_stats_t *cacherrstats; + uint64_t nsstat_values[ns_statscounter_max]; + uint64_t resstat_values[dns_resstatscounter_max]; + uint64_t adbstat_values[dns_adbstats_max]; + uint64_t zonestat_values[dns_zonestatscounter_max]; + uint64_t sockstat_values[isc_sockstatscounter_max]; + uint64_t udpinsizestat_values[DNS_SIZEHISTO_MAXIN + 1]; + uint64_t udpoutsizestat_values[DNS_SIZEHISTO_MAXOUT + 1]; + uint64_t tcpinsizestat_values[DNS_SIZEHISTO_MAXIN + 1]; + uint64_t tcpoutsizestat_values[DNS_SIZEHISTO_MAXOUT + 1]; +#ifdef HAVE_DNSTAP + uint64_t dnstapstat_values[dns_dnstapcounter_max]; +#endif /* ifdef HAVE_DNSTAP */ + isc_result_t result; + + isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof boottime); + isc_time_formatISO8601ms(&named_g_configtime, configtime, + sizeof configtime); + isc_time_formatISO8601ms(&now, nowstr, sizeof nowstr); + + writer = xmlNewTextWriterDoc(&doc, 0); + if (writer == NULL) { + goto cleanup; + } + TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL)); + TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet", + ISC_XMLCHAR "type=\"text/xsl\" " + "href=\"/bind9.xsl\"")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version", + ISC_XMLCHAR STATS_XML_VERSION)); + + /* Set common fields for statistics dump */ + dumparg.type = isc_statsformat_xml; + dumparg.arg = writer; + + /* Render server information */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime)); + TRY0(xmlTextWriterEndElement(writer)); /* boot-time */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "config-time")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR configtime)); + TRY0(xmlTextWriterEndElement(writer)); /* config-time */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr)); + TRY0(xmlTextWriterEndElement(writer)); /* current-time */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "version")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR PACKAGE_VERSION)); + TRY0(xmlTextWriterEndElement(writer)); /* version */ + + if ((flags & STATS_XML_SERVER) != 0) { + dumparg.result = ISC_R_SUCCESS; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "opcode")); + + dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + CHECK(dumparg.result); + + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "rcode")); + + dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + CHECK(dumparg.result); + + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "qtype")); + + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(server->sctx->rcvquerystats, + rdtypestat_dump, &dumparg, 0); + CHECK(dumparg.result); + + TRY0(xmlTextWriterEndElement(writer)); /* counters */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "nsstat")); + + CHECK(dump_stats(ns_stats_get(server->sctx->nsstats), + isc_statsformat_xml, writer, NULL, + nsstats_xmldesc, ns_statscounter_max, + nsstats_index, nsstat_values, + ISC_STATSDUMP_VERBOSE)); + + TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "zonestat")); + + CHECK(dump_stats(server->zonestats, isc_statsformat_xml, writer, + NULL, zonestats_xmldesc, + dns_zonestatscounter_max, zonestats_index, + zonestat_values, ISC_STATSDUMP_VERBOSE)); + + TRY0(xmlTextWriterEndElement(writer)); /* /zonestat */ + + /* + * Most of the common resolver statistics entries are 0, so + * we don't use the verbose dump here. + */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resstat")); + CHECK(dump_stats(server->resolverstats, isc_statsformat_xml, + writer, NULL, resstats_xmldesc, + dns_resstatscounter_max, resstats_index, + resstat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* resstat */ + +#ifdef HAVE_DNSTAP + if (server->dtenv != NULL) { + isc_stats_t *dnstapstats = NULL; + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR "type", + ISC_XMLCHAR "dnstap")); + dns_dt_getstats(named_g_server->dtenv, &dnstapstats); + result = dump_stats( + dnstapstats, isc_statsformat_xml, writer, NULL, + dnstapstats_xmldesc, dns_dnstapcounter_max, + dnstapstats_index, dnstapstat_values, 0); + isc_stats_detach(&dnstapstats); + CHECK(result); + + TRY0(xmlTextWriterEndElement(writer)); /* dnstap */ + } +#endif /* ifdef HAVE_DNSTAP */ + } + + if ((flags & STATS_XML_NET) != 0) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "sockstat")); + + CHECK(dump_stats(server->sockstats, isc_statsformat_xml, writer, + NULL, sockstats_xmldesc, + isc_sockstatscounter_max, sockstats_index, + sockstat_values, ISC_STATSDUMP_VERBOSE)); + + TRY0(xmlTextWriterEndElement(writer)); /* /sockstat */ + } + TRY0(xmlTextWriterEndElement(writer)); /* /server */ + + if ((flags & STATS_XML_TRAFFIC) != 0) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "traffic")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv4")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + CHECK(dump_histo(server->sctx->udpinstats4, isc_statsformat_xml, + writer, NULL, udpinsizestats_xmldesc, + dns_sizecounter_in_max, udpinsizestats_index, + udpinsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + CHECK(dump_histo( + server->sctx->udpoutstats4, isc_statsformat_xml, writer, + NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, + udpoutsizestats_index, udpoutsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + CHECK(dump_histo(server->sctx->tcpinstats4, isc_statsformat_xml, + writer, NULL, tcpinsizestats_xmldesc, + dns_sizecounter_in_max, tcpinsizestats_index, + tcpinsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + CHECK(dump_histo( + server->sctx->tcpoutstats4, isc_statsformat_xml, writer, + NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, + tcpoutsizestats_index, tcpoutsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ipv6")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "udp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + CHECK(dump_histo(server->sctx->udpinstats6, isc_statsformat_xml, + writer, NULL, udpinsizestats_xmldesc, + dns_sizecounter_in_max, udpinsizestats_index, + udpinsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + CHECK(dump_histo( + server->sctx->udpoutstats6, isc_statsformat_xml, writer, + NULL, udpoutsizestats_xmldesc, dns_sizecounter_out_max, + udpoutsizestats_index, udpoutsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tcp")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "request-size")); + + CHECK(dump_histo(server->sctx->tcpinstats6, isc_statsformat_xml, + writer, NULL, tcpinsizestats_xmldesc, + dns_sizecounter_in_max, tcpinsizestats_index, + tcpinsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "response-size")); + + CHECK(dump_histo( + server->sctx->tcpoutstats6, isc_statsformat_xml, writer, + NULL, tcpoutsizestats_xmldesc, dns_sizecounter_out_max, + tcpoutsizestats_index, tcpoutsizestat_values, 0)); + + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + TRY0(xmlTextWriterEndElement(writer)); /* */ + } + + /* + * Render views. For each view we know of, call its + * rendering function. + */ + view = ISC_LIST_HEAD(server->viewlist); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views")); + while (view != NULL && ((flags & (STATS_XML_SERVER | STATS_XML_ZONES | + STATS_XML_XFRINS)) != 0)) + { + isc_stats_t *istats = NULL; + dns_stats_t *dstats = NULL; + dns_adb_t *adb = NULL; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR view->name)); + + if ((flags & STATS_XML_ZONES) != 0) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "zones")); + CHECK(dns_view_apply(view, true, NULL, zone_xmlrender, + writer)); + TRY0(xmlTextWriterEndElement(writer)); /* /zones */ + } + + if ((flags & STATS_XML_XFRINS) != 0) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "xfrins")); + CHECK(dns_zt_apply(view->zonetable, true, NULL, + xfrin_xmlrender, writer)); + TRY0(xmlTextWriterEndElement(writer)); /* /xfrins */ + } + + if ((flags & STATS_XML_SERVER) == 0) { + TRY0(xmlTextWriterEndElement(writer)); /* /view */ + view = ISC_LIST_NEXT(view, link); + continue; + } + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resqtype")); + + dns_resolver_getquerystats(view->resolver, &dstats); + if (dstats != NULL) { + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(dstats, rdtypestat_dump, + &dumparg, 0); + CHECK(dumparg.result); + } + dns_stats_detach(&dstats); + TRY0(xmlTextWriterEndElement(writer)); + + /* */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resstats")); + dns_resolver_getstats(view->resolver, &istats); + if (istats != NULL) { + CHECK(dump_stats(istats, isc_statsformat_xml, writer, + NULL, resstats_xmldesc, + dns_resstatscounter_max, + resstats_index, resstat_values, + ISC_STATSDUMP_VERBOSE)); + } + isc_stats_detach(&istats); + TRY0(xmlTextWriterEndElement(writer)); /* */ + + cacherrstats = dns_db_getrrsetstats(view->cachedb); + if (cacherrstats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "cache")); + TRY0(xmlTextWriterWriteAttribute( + writer, ISC_XMLCHAR "name", + ISC_XMLCHAR dns_cache_getname(view->cache))); + dumparg.result = ISC_R_SUCCESS; + dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, + &dumparg, 0); + CHECK(dumparg.result); + TRY0(xmlTextWriterEndElement(writer)); /* cache */ + } + + /* */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "adbstat")); + dns_view_getadb(view, &adb); + if (adb != NULL) { + result = dump_stats(dns_adb_getstats(adb), + isc_statsformat_xml, writer, NULL, + adbstats_xmldesc, dns_adbstats_max, + adbstats_index, adbstat_values, + ISC_STATSDUMP_VERBOSE); + dns_adb_detach(&adb); + CHECK(result); + } + TRY0(xmlTextWriterEndElement(writer)); /* */ + + /* */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "cachestats")); + TRY0(dns_cache_renderxml(view->cache, writer)); + TRY0(xmlTextWriterEndElement(writer)); /* */ + + TRY0(xmlTextWriterEndElement(writer)); /* view */ + + view = ISC_LIST_NEXT(view, link); + } + TRY0(xmlTextWriterEndElement(writer)); /* /views */ + + if ((flags & STATS_XML_MEM) != 0) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory")); + TRY0(isc_mem_renderxml(writer)); + TRY0(xmlTextWriterEndElement(writer)); /* /memory */ + } + + TRY0(xmlTextWriterEndElement(writer)); /* /statistics */ + TRY0(xmlTextWriterEndDocument(writer)); + + xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0); + if (*buf == NULL) { + goto cleanup; + } + + xmlFreeTextWriter(writer); + xmlFreeDoc(doc); + return ISC_R_SUCCESS; + +cleanup: + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed generating XML response"); + if (writer != NULL) { + xmlFreeTextWriter(writer); + } + if (doc != NULL) { + xmlFreeDoc(doc); + } + return ISC_R_FAILURE; +} + +static void +wrap_xmlfree(isc_buffer_t *buffer, void *arg) { + UNUSED(arg); + + xmlFree(isc_buffer_base(buffer)); +} + +static isc_result_t +render_xml(uint32_t flags, void *arg, unsigned int *retcode, + const char **retmsg, const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + unsigned char *msg = NULL; + int msglen; + named_server_t *server = arg; + isc_result_t result; + + result = generatexml(server, flags, &msglen, &msg); + + if (result == ISC_R_SUCCESS) { + *retcode = 200; + *retmsg = "OK"; + *mimetype = "text/xml"; + isc_buffer_reinit(b, msg, msglen); + isc_buffer_add(b, msglen); + *freecb = wrap_xmlfree; + *freecb_args = NULL; + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rendering XML()"); + } + + return result; +} + +static isc_result_t +render_xml_all(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, + void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_ALL, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_status(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_STATUS, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_server(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_SERVER, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_ZONES, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_xfrins(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_XFRINS, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_net(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, + void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_NET, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_mem(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, isc_httpdfree_t **freecb, + void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_MEM, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_xml_traffic(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_xml(STATS_XML_TRAFFIC, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +#endif /* HAVE_LIBXML2 */ + +#ifdef HAVE_JSON_C +/* + * Which statistics to include when rendering to JSON + */ +#define STATS_JSON_STATUS 0x00 /* display only common statistics */ +#define STATS_JSON_SERVER 0x01 +#define STATS_JSON_ZONES 0x02 +#define STATS_JSON_XFRINS 0x04 +#define STATS_JSON_NET 0x08 +#define STATS_JSON_MEM 0x10 +#define STATS_JSON_TRAFFIC 0x20 +#define STATS_JSON_ALL 0xff + +#define CHECKMEM(m) \ + do { \ + if (m == NULL) { \ + result = ISC_R_NOMEMORY; \ + goto cleanup; \ + } \ + } while (0) + +static void +wrap_jsonfree(isc_buffer_t *buffer, void *arg) { + json_object_put(isc_buffer_base(buffer)); + if (arg != NULL) { + json_object_put((json_object *)arg); + } +} + +static json_object * +addzone(char *name, char *classname, const char *ztype, uint32_t serial, + bool add_serial) { + json_object *node = json_object_new_object(); + + if (node == NULL) { + return NULL; + } + + json_object_object_add(node, "name", json_object_new_string(name)); + json_object_object_add(node, "class", + json_object_new_string(classname)); + if (add_serial) { + json_object_object_add(node, "serial", + json_object_new_int64(serial)); + } + if (ztype != NULL) { + json_object_object_add(node, "type", + json_object_new_string(ztype)); + } + return node; +} + +static isc_result_t +zone_jsonrender(dns_zone_t *zone, void *arg) { + isc_result_t result = ISC_R_SUCCESS; + char buf[1024 + 32]; /* sufficiently large for zone name and class */ + char classbuf[64]; /* sufficiently large for class */ + char *zone_name_only = NULL; + char *class_only = NULL; + dns_rdataclass_t rdclass; + uint32_t serial; + json_object *zonearray = (json_object *)arg; + json_object *zoneobj = NULL; + dns_zonestat_level_t statlevel; + isc_time_t timestamp; + + statlevel = dns_zone_getstatlevel(zone); + if (statlevel == dns_zonestat_none) { + return ISC_R_SUCCESS; + } + + dns_zone_nameonly(zone, buf, sizeof(buf)); + zone_name_only = buf; + + rdclass = dns_zone_getclass(zone); + dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); + class_only = classbuf; + + if (dns_zone_getserial(zone, &serial) != ISC_R_SUCCESS) { + zoneobj = addzone(zone_name_only, class_only, + user_zonetype(zone), 0, false); + } else { + zoneobj = addzone(zone_name_only, class_only, + user_zonetype(zone), serial, true); + } + + if (zoneobj == NULL) { + return ISC_R_NOMEMORY; + } + + /* + * Export zone timers to the statistics channel in JSON format. + * For primary zones, only include the loaded time. For secondary + * zones, also include the expire and refresh times. + */ + + CHECK(dns_zone_getloadtime(zone, ×tamp)); + + isc_time_formatISO8601(×tamp, buf, 64); + json_object_object_add(zoneobj, "loaded", json_object_new_string(buf)); + + if (dns_zone_gettype(zone) == dns_zone_secondary) { + CHECK(dns_zone_getexpiretime(zone, ×tamp)); + isc_time_formatISO8601(×tamp, buf, 64); + json_object_object_add(zoneobj, "expires", + json_object_new_string(buf)); + + CHECK(dns_zone_getrefreshtime(zone, ×tamp)); + isc_time_formatISO8601(×tamp, buf, 64); + json_object_object_add(zoneobj, "refresh", + json_object_new_string(buf)); + } + + if (statlevel == dns_zonestat_full) { + isc_stats_t *zonestats; + isc_stats_t *gluecachestats; + dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; + uint64_t nsstat_values[ns_statscounter_max]; + uint64_t gluecachestats_values[dns_gluecachestatscounter_max]; + + zonestats = dns_zone_getrequeststats(zone); + if (zonestats != NULL) { + json_object *counters = json_object_new_object(); + if (counters == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + result = dump_stats(zonestats, isc_statsformat_json, + counters, NULL, nsstats_xmldesc, + ns_statscounter_max, nsstats_index, + nsstat_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(zoneobj, "rcodes", + counters); + } else { + json_object_put(counters); + } + } + + gluecachestats = dns_zone_getgluecachestats(zone); + if (gluecachestats != NULL) { + json_object *counters = json_object_new_object(); + if (counters == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + result = dump_stats( + gluecachestats, isc_statsformat_json, counters, + NULL, gluecachestats_xmldesc, + dns_gluecachestatscounter_max, + gluecachestats_index, gluecachestats_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(zoneobj, "gluecache", + counters); + } else { + json_object_put(counters); + } + } + + rcvquerystats = dns_zone_getrcvquerystats(zone); + if (rcvquerystats != NULL) { + stats_dumparg_t dumparg; + json_object *counters = json_object_new_object(); + CHECKMEM(counters); + + dumparg.type = isc_statsformat_json; + dumparg.arg = counters; + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(zoneobj, "qtypes", + counters); + } else { + json_object_put(counters); + } + } + + dnssecsignstats = dns_zone_getdnssecsignstats(zone); + if (dnssecsignstats != NULL) { + stats_dumparg_t dumparg; + json_object *sign_counters = json_object_new_object(); + CHECKMEM(sign_counters); + + dumparg.type = isc_statsformat_json; + dumparg.arg = sign_counters; + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump( + dnssecsignstats, dns_dnssecsignstats_sign, + dnssecsignstat_dump, &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(sign_counters); + goto cleanup; + } + + if (json_object_get_object(sign_counters)->count != 0) { + json_object_object_add(zoneobj, "dnssec-sign", + sign_counters); + } else { + json_object_put(sign_counters); + } + + json_object *refresh_counters = + json_object_new_object(); + CHECKMEM(refresh_counters); + + dumparg.type = isc_statsformat_json; + dumparg.arg = refresh_counters; + dumparg.result = ISC_R_SUCCESS; + dns_dnssecsignstats_dump( + dnssecsignstats, dns_dnssecsignstats_refresh, + dnssecsignstat_dump, &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(refresh_counters); + goto cleanup; + } + + if (json_object_get_object(refresh_counters)->count != + 0) + { + json_object_object_add(zoneobj, + "dnssec-refresh", + refresh_counters); + } else { + json_object_put(refresh_counters); + } + } + } + + json_object_array_add(zonearray, zoneobj); + zoneobj = NULL; + result = ISC_R_SUCCESS; + +cleanup: + if (zoneobj != NULL) { + json_object_put(zoneobj); + } + return result; +} + +static isc_result_t +xfrin_jsonrender(dns_zone_t *zone, void *arg) { + isc_result_t result; + char buf[1024 + 32]; /* sufficiently large for zone name and class */ + char classbuf[64]; /* sufficiently large for class */ + char *zone_name_only = NULL; + char *class_only = NULL; + dns_rdataclass_t rdclass; + uint32_t serial; + json_object *xfrinarray = (json_object *)arg; + json_object *xfrinobj = NULL; + isc_sockaddr_t addr; + const isc_sockaddr_t *addrp = NULL; + char addr_buf[ISC_SOCKADDR_FORMATSIZE]; + dns_transport_type_t transport_type; + dns_zonestat_level_t statlevel; + dns_xfrin_t *xfr = NULL; + bool is_firstrefresh, is_running, is_deferred, is_presoa, is_pending; + bool needs_refresh; + bool is_first_data_received, is_ixfr; + unsigned int nmsg = 0; + unsigned int nrecs = 0; + uint64_t nbytes = 0; + uint64_t rate = 0; + + statlevel = dns_zone_getstatlevel(zone); + if (statlevel == dns_zonestat_none) { + return ISC_R_SUCCESS; + } + + dns_zone_nameonly(zone, buf, sizeof(buf)); + zone_name_only = buf; + + rdclass = dns_zone_getclass(zone); + dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); + class_only = classbuf; + + if (dns_zone_getserial(zone, &serial) != ISC_R_SUCCESS) { + xfrinobj = addzone(zone_name_only, class_only, + user_zonetype(zone), 0, false); + } else { + xfrinobj = addzone(zone_name_only, class_only, + user_zonetype(zone), serial, true); + } + + if (xfrinobj == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + result = dns_zone_getxfr(zone, &xfr, &is_firstrefresh, &is_running, + &is_deferred, &is_presoa, &is_pending, + &needs_refresh); + if (result != ISC_R_SUCCESS) { + result = ISC_R_SUCCESS; + goto cleanup; + } + + if (!is_running && !is_deferred && !is_presoa && !is_pending && + !needs_refresh) + { + /* No ongoing/queued transfer. */ + goto cleanup; + } + + if (is_running && xfr == NULL) { + /* The transfer is finished, and it's shutting down. */ + goto cleanup; + } + + if (is_running) { + serial = dns_xfrin_getendserial(xfr); + if (serial != 0) { + json_object_object_add(xfrinobj, "remoteserial", + json_object_new_int64(serial)); + } + } + + json_object_object_add( + xfrinobj, "firstrefresh", + json_object_new_string(is_firstrefresh ? "Yes" : "No")); + + if (is_running) { + const char *xfr_state = NULL; + + dns_xfrin_getstate(xfr, &xfr_state, &is_first_data_received, + &is_ixfr); + json_object_object_add(xfrinobj, "state", + json_object_new_string(xfr_state)); + } else if (is_deferred) { + json_object_object_add(xfrinobj, "state", + json_object_new_string("Deferred")); + } else if (is_presoa) { + json_object_object_add(xfrinobj, "state", + json_object_new_string("Refresh SOA")); + } else if (is_pending) { + json_object_object_add(xfrinobj, "state", + json_object_new_string("Pending")); + } else if (needs_refresh) { + json_object_object_add(xfrinobj, "state", + json_object_new_string("Needs Refresh")); + } else { + UNREACHABLE(); + } + + json_object_object_add( + xfrinobj, "refreshqueued", + json_object_new_string(is_running && needs_refresh ? "Yes" + : "No")); + + if (is_running) { + addrp = dns_xfrin_getsourceaddr(xfr); + isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); + json_object_object_add(xfrinobj, "localaddr", + json_object_new_string(addr_buf)); + } else if (is_presoa) { + dns_zone_getsourceaddr(zone, &addr); + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + json_object_object_add(xfrinobj, "localaddr", + json_object_new_string(addr_buf)); + } else { + json_object_object_add(xfrinobj, "localaddr", + json_object_new_string("-")); + } + + if (is_running) { + addrp = dns_xfrin_getprimaryaddr(xfr); + isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); + json_object_object_add(xfrinobj, "remoteaddr", + json_object_new_string(addr_buf)); + } else if (is_presoa) { + if (dns_zone_getprimaryaddr(zone, &addr) == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); + json_object_object_add( + xfrinobj, "remoteaddr", + json_object_new_string(addr_buf)); + } else { + json_object_object_add(xfrinobj, "remoteaddr", + json_object_new_string("-")); + } + } else { + json_object_object_add(xfrinobj, "remoteaddr", + json_object_new_string("-")); + } + + if (is_running || is_presoa) { + if (is_running) { + transport_type = dns_xfrin_getsoatransporttype(xfr); + } else { + transport_type = dns_zone_getrequesttransporttype(zone); + } + + if (transport_type == DNS_TRANSPORT_UDP) { + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("UDP")); + } else if (transport_type == DNS_TRANSPORT_TCP) { + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("TCP")); + } else if (transport_type == DNS_TRANSPORT_TLS) { + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("TLS")); + } else if (transport_type == DNS_TRANSPORT_NONE) { + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("None")); + } else { + /* We don't expect any other SOA transport type. */ + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("-")); + } + } else { + json_object_object_add(xfrinobj, "soatransport", + json_object_new_string("-")); + } + + if (is_running) { + transport_type = dns_xfrin_gettransporttype(xfr); + if (transport_type == DNS_TRANSPORT_TCP) { + json_object_object_add(xfrinobj, "transport", + json_object_new_string("TCP")); + } else if (transport_type == DNS_TRANSPORT_TLS) { + json_object_object_add(xfrinobj, "transport", + json_object_new_string("TLS")); + } else { + /* We don't expect any other transport type. */ + json_object_object_add(xfrinobj, "transport", + json_object_new_string("-")); + } + } else { + json_object_object_add(xfrinobj, "transport", + json_object_new_string("-")); + } + + if (is_running) { + const dns_name_t *tsigkeyname = dns_xfrin_gettsigkeyname(xfr); + char tsigkeyname_buf[DNS_NAME_FORMATSIZE]; + + if (tsigkeyname != NULL) { + dns_name_format(tsigkeyname, tsigkeyname_buf, + sizeof(tsigkeyname_buf)); + json_object_object_add( + xfrinobj, "tsigkeyname", + json_object_new_string(tsigkeyname_buf)); + } else { + json_object_object_add(xfrinobj, "tsigkeyname", NULL); + } + } else { + json_object_object_add(xfrinobj, "tsigkeyname", NULL); + } + + if (is_running || is_deferred || is_presoa || is_pending) { + isc_time_t start = is_running ? dns_xfrin_getstarttime(xfr) + : dns_zone_getxfrintime(zone); + isc_time_t now = isc_time_now(); + isc_time_t diff; + uint32_t sec; + + isc_time_subtract(&now, &start, &diff); + sec = isc_time_seconds(&diff); + json_object_object_add(xfrinobj, "duration", + json_object_new_int64((int64_t)sec)); + } else { + json_object_object_add(xfrinobj, "duration", + json_object_new_int64(0)); + } + + if (is_running) { + dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes, &rate); + } + json_object_object_add(xfrinobj, "nmsg", + json_object_new_int64((int64_t)nmsg)); + json_object_object_add(xfrinobj, "nrecs", + json_object_new_int64((int64_t)nrecs)); + json_object_object_add( + xfrinobj, "nbytes", + json_object_new_int64(nbytes > INT64_MAX ? INT64_MAX + : (int64_t)nbytes)); + json_object_object_add(xfrinobj, "rate", + json_object_new_int64(rate > INT64_MAX + ? INT64_MAX + : (int64_t)rate)); + + if (is_running && is_first_data_received) { + json_object_object_add( + xfrinobj, "ixfr", + json_object_new_string(is_ixfr ? "Yes" : "No")); + } else { + json_object_object_add(xfrinobj, "ixfr", + json_object_new_string("")); + } + + json_object_array_add(xfrinarray, xfrinobj); + xfrinobj = NULL; + result = ISC_R_SUCCESS; + +cleanup: + if (xfr != NULL) { + dns_xfrin_detach(&xfr); + } + if (xfrinobj != NULL) { + json_object_put(xfrinobj); + } + return result; +} + +static isc_result_t +generatejson(named_server_t *server, size_t *msglen, const char **msg, + json_object **rootp, uint32_t flags) { + dns_view_t *view; + isc_result_t result = ISC_R_SUCCESS; + json_object *bindstats, *viewlist, *counters, *obj; + json_object *traffic = NULL; + json_object *udpreq4 = NULL, *udpresp4 = NULL; + json_object *tcpreq4 = NULL, *tcpresp4 = NULL; + json_object *udpreq6 = NULL, *udpresp6 = NULL; + json_object *tcpreq6 = NULL, *tcpresp6 = NULL; + uint64_t nsstat_values[ns_statscounter_max]; + uint64_t resstat_values[dns_resstatscounter_max]; + uint64_t adbstat_values[dns_adbstats_max]; + uint64_t zonestat_values[dns_zonestatscounter_max]; + uint64_t sockstat_values[isc_sockstatscounter_max]; + uint64_t udpinsizestat_values[dns_sizecounter_in_max]; + uint64_t udpoutsizestat_values[dns_sizecounter_out_max]; + uint64_t tcpinsizestat_values[dns_sizecounter_in_max]; + uint64_t tcpoutsizestat_values[dns_sizecounter_out_max]; +#ifdef HAVE_DNSTAP + uint64_t dnstapstat_values[dns_dnstapcounter_max]; +#endif /* ifdef HAVE_DNSTAP */ + stats_dumparg_t dumparg; + char boottime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + char configtime[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + char nowstr[sizeof "yyyy-mm-ddThh:mm:ss.sssZ"]; + isc_time_t now; + + REQUIRE(msglen != NULL); + REQUIRE(msg != NULL && *msg == NULL); + REQUIRE(rootp == NULL || *rootp == NULL); + + bindstats = json_object_new_object(); + if (bindstats == NULL) { + return ISC_R_NOMEMORY; + } + + /* + * These statistics are included no matter which URL we use. + */ + obj = json_object_new_string(STATS_JSON_VERSION); + CHECKMEM(obj); + json_object_object_add(bindstats, "json-stats-version", obj); + + now = isc_time_now(); + isc_time_formatISO8601ms(&named_g_boottime, boottime, sizeof(boottime)); + isc_time_formatISO8601ms(&named_g_configtime, configtime, + sizeof configtime); + isc_time_formatISO8601ms(&now, nowstr, sizeof(nowstr)); + + obj = json_object_new_string(boottime); + CHECKMEM(obj); + json_object_object_add(bindstats, "boot-time", obj); + + obj = json_object_new_string(configtime); + CHECKMEM(obj); + json_object_object_add(bindstats, "config-time", obj); + + obj = json_object_new_string(nowstr); + CHECKMEM(obj); + json_object_object_add(bindstats, "current-time", obj); + obj = json_object_new_string(PACKAGE_VERSION); + CHECKMEM(obj); + json_object_object_add(bindstats, "version", obj); + + if ((flags & STATS_JSON_SERVER) != 0) { + /* OPCODE counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.type = isc_statsformat_json; + dumparg.arg = counters; + + dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "opcodes", counters); + } else { + json_object_put(counters); + } + + /* OPCODE counters */ + counters = json_object_new_object(); + + dumparg.type = isc_statsformat_json; + dumparg.arg = counters; + + dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, + &dumparg, ISC_STATSDUMP_VERBOSE); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "rcodes", counters); + } else { + json_object_put(counters); + } + + /* QTYPE counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + + dns_rdatatypestats_dump(server->sctx->rcvquerystats, + rdtypestat_dump, &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "qtypes", counters); + } else { + json_object_put(counters); + } + + /* server stat counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + + result = dump_stats(ns_stats_get(server->sctx->nsstats), + isc_statsformat_json, counters, NULL, + nsstats_xmldesc, ns_statscounter_max, + nsstats_index, nsstat_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "nsstats", counters); + } else { + json_object_put(counters); + } + + /* zone stat counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + + result = dump_stats(server->zonestats, isc_statsformat_json, + counters, NULL, zonestats_xmldesc, + dns_zonestatscounter_max, zonestats_index, + zonestat_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "zonestats", + counters); + } else { + json_object_put(counters); + } + + /* resolver stat counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + + result = dump_stats(server->resolverstats, isc_statsformat_json, + counters, NULL, resstats_xmldesc, + dns_resstatscounter_max, resstats_index, + resstat_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "resstats", counters); + } else { + json_object_put(counters); + } + +#ifdef HAVE_DNSTAP + /* dnstap stat counters */ + if (named_g_server->dtenv != NULL) { + isc_stats_t *dnstapstats = NULL; + dns_dt_getstats(named_g_server->dtenv, &dnstapstats); + counters = json_object_new_object(); + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + result = dump_stats(dnstapstats, isc_statsformat_json, + counters, NULL, dnstapstats_xmldesc, + dns_dnstapcounter_max, + dnstapstats_index, + dnstapstat_values, 0); + isc_stats_detach(&dnstapstats); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "dnstapstats", + counters); + } else { + json_object_put(counters); + } + } +#endif /* ifdef HAVE_DNSTAP */ + } + + if ((flags & + (STATS_JSON_SERVER | STATS_JSON_ZONES | STATS_JSON_XFRINS)) != 0) + { + viewlist = json_object_new_object(); + CHECKMEM(viewlist); + + json_object_object_add(bindstats, "views", viewlist); + + view = ISC_LIST_HEAD(server->viewlist); + while (view != NULL) { + json_object *za, *xa, *v = json_object_new_object(); + dns_adb_t *adb = NULL; + + CHECKMEM(v); + json_object_object_add(viewlist, view->name, v); + + za = json_object_new_array(); + CHECKMEM(za); + + if ((flags & STATS_JSON_ZONES) != 0) { + CHECK(dns_view_apply(view, true, NULL, + zone_jsonrender, za)); + } + + if (json_object_array_length(za) != 0) { + json_object_object_add(v, "zones", za); + } else { + json_object_put(za); + } + + xa = json_object_new_array(); + CHECKMEM(xa); + + if ((flags & STATS_JSON_XFRINS) != 0) { + CHECK(dns_zt_apply(view->zonetable, true, NULL, + xfrin_jsonrender, xa)); + } + + if (json_object_array_length(xa) != 0) { + json_object_object_add(v, "xfrins", xa); + } else { + json_object_put(xa); + } + + if ((flags & STATS_JSON_SERVER) != 0) { + json_object *res = NULL; + dns_stats_t *dstats = NULL; + isc_stats_t *istats = NULL; + + res = json_object_new_object(); + CHECKMEM(res); + json_object_object_add(v, "resolver", res); + + dns_resolver_getstats(view->resolver, &istats); + if (istats != NULL) { + counters = json_object_new_object(); + CHECKMEM(counters); + + result = dump_stats( + istats, isc_statsformat_json, + counters, NULL, + resstats_xmldesc, + dns_resstatscounter_max, + resstats_index, resstat_values, + 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + result = dumparg.result; + goto cleanup; + } + + json_object_object_add(res, "stats", + counters); + isc_stats_detach(&istats); + } + + dns_resolver_getquerystats(view->resolver, + &dstats); + if (dstats != NULL) { + counters = json_object_new_object(); + CHECKMEM(counters); + + dumparg.arg = counters; + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(dstats, + rdtypestat_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + result = dumparg.result; + goto cleanup; + } + + json_object_object_add(res, "qtypes", + counters); + dns_stats_detach(&dstats); + } + + dstats = dns_db_getrrsetstats(view->cachedb); + if (dstats != NULL) { + counters = json_object_new_object(); + CHECKMEM(counters); + + dumparg.arg = counters; + dumparg.result = ISC_R_SUCCESS; + dns_rdatasetstats_dump( + dstats, rdatasetstats_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) { + json_object_put(counters); + result = dumparg.result; + goto cleanup; + } + + json_object_object_add(res, "cache", + counters); + } + + counters = json_object_new_object(); + CHECKMEM(counters); + + result = dns_cache_renderjson(view->cache, + counters); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + json_object_object_add(res, "cachestats", + counters); + + dns_view_getadb(view, &adb); + if (adb != NULL) { + istats = dns_adb_getstats(adb); + dns_adb_detach(&adb); + } + if (istats != NULL) { + counters = json_object_new_object(); + CHECKMEM(counters); + + result = dump_stats( + istats, isc_statsformat_json, + counters, NULL, + adbstats_xmldesc, + dns_adbstats_max, + adbstats_index, adbstat_values, + 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + result = dumparg.result; + goto cleanup; + } + + json_object_object_add(res, "adb", + counters); + } + } + + view = ISC_LIST_NEXT(view, link); + } + } + + if ((flags & STATS_JSON_NET) != 0) { + /* socket stat counters */ + counters = json_object_new_object(); + + dumparg.result = ISC_R_SUCCESS; + dumparg.arg = counters; + + result = dump_stats(server->sockstats, isc_statsformat_json, + counters, NULL, sockstats_xmldesc, + isc_sockstatscounter_max, sockstats_index, + sockstat_values, 0); + if (result != ISC_R_SUCCESS) { + json_object_put(counters); + goto cleanup; + } + + if (json_object_get_object(counters)->count != 0) { + json_object_object_add(bindstats, "sockstats", + counters); + } else { + json_object_put(counters); + } + } + + if ((flags & STATS_JSON_MEM) != 0) { + json_object *memory = json_object_new_object(); + CHECKMEM(memory); + + result = isc_mem_renderjson(memory); + if (result != ISC_R_SUCCESS) { + json_object_put(memory); + goto cleanup; + } + + json_object_object_add(bindstats, "memory", memory); + } + + if ((flags & STATS_JSON_TRAFFIC) != 0) { + traffic = json_object_new_object(); + CHECKMEM(traffic); + + udpreq4 = json_object_new_object(); + CHECKMEM(udpreq4); + + udpresp4 = json_object_new_object(); + CHECKMEM(udpresp4); + + tcpreq4 = json_object_new_object(); + CHECKMEM(tcpreq4); + + tcpresp4 = json_object_new_object(); + CHECKMEM(tcpresp4); + + udpreq6 = json_object_new_object(); + CHECKMEM(udpreq6); + + udpresp6 = json_object_new_object(); + CHECKMEM(udpresp6); + + tcpreq6 = json_object_new_object(); + CHECKMEM(tcpreq6); + + tcpresp6 = json_object_new_object(); + CHECKMEM(tcpresp6); + + CHECK(dump_histo(server->sctx->udpinstats4, + isc_statsformat_json, udpreq4, NULL, + udpinsizestats_xmldesc, dns_sizecounter_in_max, + udpinsizestats_index, udpinsizestat_values, + 0)); + + CHECK(dump_histo(server->sctx->udpoutstats4, + isc_statsformat_json, udpresp4, NULL, + udpoutsizestats_xmldesc, + dns_sizecounter_out_max, udpoutsizestats_index, + udpoutsizestat_values, 0)); + + CHECK(dump_histo(server->sctx->tcpinstats4, + isc_statsformat_json, tcpreq4, NULL, + tcpinsizestats_xmldesc, dns_sizecounter_in_max, + tcpinsizestats_index, tcpinsizestat_values, + 0)); + + CHECK(dump_histo(server->sctx->tcpoutstats4, + isc_statsformat_json, tcpresp4, NULL, + tcpoutsizestats_xmldesc, + dns_sizecounter_out_max, tcpoutsizestats_index, + tcpoutsizestat_values, 0)); + + CHECK(dump_histo(server->sctx->udpinstats6, + isc_statsformat_json, udpreq6, NULL, + udpinsizestats_xmldesc, dns_sizecounter_in_max, + udpinsizestats_index, udpinsizestat_values, + 0)); + + CHECK(dump_histo(server->sctx->udpoutstats6, + isc_statsformat_json, udpresp6, NULL, + udpoutsizestats_xmldesc, + dns_sizecounter_out_max, udpoutsizestats_index, + udpoutsizestat_values, 0)); + + CHECK(dump_histo(server->sctx->tcpinstats6, + isc_statsformat_json, tcpreq6, NULL, + tcpinsizestats_xmldesc, dns_sizecounter_in_max, + tcpinsizestats_index, tcpinsizestat_values, + 0)); + + CHECK(dump_histo(server->sctx->tcpoutstats6, + isc_statsformat_json, tcpresp6, NULL, + tcpoutsizestats_xmldesc, + dns_sizecounter_out_max, tcpoutsizestats_index, + tcpoutsizestat_values, 0)); + + json_object_object_add(traffic, + "dns-udp-requests-sizes-received-ipv4", + udpreq4); + json_object_object_add( + traffic, "dns-udp-responses-sizes-sent-ipv4", udpresp4); + json_object_object_add(traffic, + "dns-tcp-requests-sizes-received-ipv4", + tcpreq4); + json_object_object_add( + traffic, "dns-tcp-responses-sizes-sent-ipv4", tcpresp4); + json_object_object_add(traffic, + "dns-udp-requests-sizes-received-ipv6", + udpreq6); + json_object_object_add( + traffic, "dns-udp-responses-sizes-sent-ipv6", udpresp6); + json_object_object_add(traffic, + "dns-tcp-requests-sizes-received-ipv6", + tcpreq6); + json_object_object_add( + traffic, "dns-tcp-responses-sizes-sent-ipv6", tcpresp6); + json_object_object_add(bindstats, "traffic", traffic); + udpreq4 = NULL; + udpresp4 = NULL; + tcpreq4 = NULL; + tcpresp4 = NULL; + udpreq6 = NULL; + udpresp6 = NULL; + tcpreq6 = NULL; + tcpresp6 = NULL; + traffic = NULL; + } + + *msg = json_object_to_json_string_ext(bindstats, + JSON_C_TO_STRING_PRETTY); + *msglen = strlen(*msg); + + if (rootp != NULL) { + *rootp = bindstats; + bindstats = NULL; + } + + result = ISC_R_SUCCESS; + +cleanup: + if (udpreq4 != NULL) { + json_object_put(udpreq4); + } + if (udpresp4 != NULL) { + json_object_put(udpresp4); + } + if (tcpreq4 != NULL) { + json_object_put(tcpreq4); + } + if (tcpresp4 != NULL) { + json_object_put(tcpresp4); + } + if (udpreq6 != NULL) { + json_object_put(udpreq6); + } + if (udpresp6 != NULL) { + json_object_put(udpresp6); + } + if (tcpreq6 != NULL) { + json_object_put(tcpreq6); + } + if (tcpresp6 != NULL) { + json_object_put(tcpresp6); + } + if (traffic != NULL) { + json_object_put(traffic); + } + if (bindstats != NULL) { + json_object_put(bindstats); + } + + return result; +} + +static isc_result_t +render_json(uint32_t flags, void *arg, unsigned int *retcode, + const char **retmsg, const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + isc_result_t result; + json_object *bindstats = NULL; + named_server_t *server = arg; + const char *msg = NULL; + size_t msglen = 0; + char *p; + + result = generatejson(server, &msglen, &msg, &bindstats, flags); + if (result == ISC_R_SUCCESS) { + *retcode = 200; + *retmsg = "OK"; + *mimetype = "application/json"; + p = UNCONST(msg); + isc_buffer_reinit(b, p, msglen); + isc_buffer_add(b, msglen); + *freecb = wrap_jsonfree; + *freecb_args = bindstats; + } else { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rendering JSON()"); + } + + return result; +} + +static isc_result_t +render_json_all(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_ALL, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_status(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_STATUS, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_server(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_SERVER, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_ZONES, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_xfrins(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_XFRINS, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_mem(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_MEM, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_net(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_NET, arg, retcode, retmsg, mimetype, b, + freecb, freecb_args); +} + +static isc_result_t +render_json_traffic(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, + void *arg, unsigned int *retcode, const char **retmsg, + const char **mimetype, isc_buffer_t *b, + isc_httpdfree_t **freecb, void **freecb_args) { + UNUSED(httpd); + UNUSED(urlinfo); + return render_json(STATS_JSON_TRAFFIC, arg, retcode, retmsg, mimetype, + b, freecb, freecb_args); +} + +#endif /* HAVE_JSON_C */ + +#if HAVE_LIBXML2 +/* + * This is only needed if we have libxml2 and was confusingly returned if + * neither of libxml2 or json-c is configured. + */ +static isc_result_t +render_xsl(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo, void *args, + unsigned int *retcode, const char **retmsg, const char **mimetype, + isc_buffer_t *b, isc_httpdfree_t **freecb, void **freecb_args) { + isc_result_t result; + char *p = NULL; + + UNUSED(httpd); + UNUSED(args); + + *freecb = NULL; + *freecb_args = NULL; + *mimetype = "text/xslt+xml"; + + if (isc_httpdurl_isstatic(urlinfo)) { + time_t t1, t2; + const isc_time_t *when; + const isc_time_t *loadtime; + + when = isc_httpd_if_modified_since(httpd); + + if (isc_time_isepoch(when)) { + goto send; + } + + result = isc_time_secondsastimet(when, &t1); + if (result != ISC_R_SUCCESS) { + goto send; + } + + loadtime = isc_httpdurl_loadtime(urlinfo); + + result = isc_time_secondsastimet(loadtime, &t2); + if (result != ISC_R_SUCCESS) { + goto send; + } + + if (t1 < t2) { + goto send; + } + + *retcode = 304; + *retmsg = "Not modified"; + goto end; + } + +send: + *retcode = 200; + *retmsg = "OK"; + p = UNCONST(xslmsg); + isc_buffer_reinit(b, p, strlen(xslmsg)); + isc_buffer_add(b, strlen(xslmsg)); +end: + return ISC_R_SUCCESS; +} +#endif + +static void +shutdown_listener(named_statschannel_t *listener) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "stopping statistics channel on %s", socktext); + + isc_httpdmgr_shutdown(&listener->httpdmgr); +} + +#if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) +static bool +client_ok(const isc_sockaddr_t *fromaddr, void *arg) { + named_statschannel_t *listener = arg; + dns_aclenv_t *env = + ns_interfacemgr_getaclenv(named_g_server->interfacemgr); + isc_netaddr_t netaddr; + char socktext[ISC_SOCKADDR_FORMATSIZE]; + int match; + + REQUIRE(listener != NULL); + + isc_netaddr_fromsockaddr(&netaddr, fromaddr); + + LOCK(&listener->lock); + if ((dns_acl_match(&netaddr, NULL, listener->acl, env, &match, NULL) == + ISC_R_SUCCESS) && + match > 0) + { + UNLOCK(&listener->lock); + return true; + } + UNLOCK(&listener->lock); + + isc_sockaddr_format(fromaddr, socktext, sizeof(socktext)); + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "rejected statistics connection from %s", socktext); + + return false; +} +#endif + +#if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C) +static void +destroy_listener(void *arg) { + named_statschannel_t *listener = (named_statschannel_t *)arg; + + REQUIRE(listener != NULL); + REQUIRE(!ISC_LINK_LINKED(listener, link)); + + /* We don't have to acquire the lock here since it's already unlinked */ + dns_acl_detach(&listener->acl); + + isc_mutex_destroy(&listener->lock); + isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); +} +#endif + +static isc_result_t +add_listener(named_server_t *server, named_statschannel_t **listenerp, + const cfg_obj_t *listen_params, const cfg_obj_t *config, + isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, + const char *socktext) { +#if !defined(HAVE_LIBXML2) && !defined(HAVE_JSON_C) + UNUSED(server); + UNUSED(listenerp); + UNUSED(listen_params); + UNUSED(config); + UNUSED(addr); + UNUSED(aclconfctx); + UNUSED(socktext); + + return ISC_R_NOTIMPLEMENTED; +#else + isc_result_t result; + named_statschannel_t *listener = NULL; + const cfg_obj_t *allow = NULL; + dns_acl_t *new_acl = NULL; + int pf; + + listener = isc_mem_get(server->mctx, sizeof(*listener)); + *listener = (named_statschannel_t){ .address = *addr }; + ISC_LINK_INIT(listener, link); + isc_mutex_init(&listener->lock); + isc_mem_attach(server->mctx, &listener->mctx); + + allow = cfg_tuple_get(listen_params, "allow"); + if (allow != NULL && cfg_obj_islist(allow)) { + result = cfg_acl_fromconfig(allow, config, named_g_lctx, + aclconfctx, listener->mctx, 0, + &new_acl); + } else { + result = dns_acl_any(listener->mctx, &new_acl); + } + CHECK(result); + + dns_acl_attach(new_acl, &listener->acl); + dns_acl_detach(&new_acl); + + pf = isc_sockaddr_pf(&listener->address); + if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || + (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) + { + CHECK(ISC_R_FAMILYNOSUPPORT); + } + + CHECK(isc_httpdmgr_create(named_g_netmgr, server->mctx, addr, client_ok, + destroy_listener, listener, + &listener->httpdmgr)); + +#ifdef HAVE_LIBXML2 + isc_httpdmgr_addurl(listener->httpdmgr, "/", false, render_xml_all, + server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml", false, render_xml_all, + server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR, false, + render_xml_all, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/status", false, + render_xml_status, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/server", false, + render_xml_server, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/zones", false, + render_xml_zones, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/xfrins", false, + render_xml_xfrins, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/net", false, + render_xml_net, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/mem", false, + render_xml_mem, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/xml/v" STATS_XML_VERSION_MAJOR "/traffic", false, + render_xml_traffic, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", true, render_xsl, + server); +#endif /* ifdef HAVE_LIBXML2 */ +#ifdef HAVE_JSON_C + isc_httpdmgr_addurl(listener->httpdmgr, "/json", false, render_json_all, + server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR, false, + render_json_all, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/status", false, + render_json_status, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/server", false, + render_json_server, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/zones", false, + render_json_zones, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/xfrins", false, + render_json_xfrins, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/net", false, + render_json_net, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/mem", false, + render_json_mem, server); + isc_httpdmgr_addurl(listener->httpdmgr, + "/json/v" STATS_JSON_VERSION_MAJOR "/traffic", + false, render_json_traffic, server); +#endif /* ifdef HAVE_JSON_C */ + + *listenerp = listener; + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "statistics channel listening on %s", socktext); + + return ISC_R_SUCCESS; + +cleanup: + if (listener->acl != NULL) { + dns_acl_detach(&listener->acl); + } + isc_mutex_destroy(&listener->lock); + isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); + + return result; +#endif +} + +static void +update_listener(named_server_t *server, named_statschannel_t **listenerp, + const cfg_obj_t *listen_params, const cfg_obj_t *config, + isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, + const char *socktext) { + named_statschannel_t *listener; + const cfg_obj_t *allow = NULL; + dns_acl_t *new_acl = NULL; + isc_result_t result = ISC_R_SUCCESS; + + for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL; + listener = ISC_LIST_NEXT(listener, link)) + { + if (isc_sockaddr_equal(addr, &listener->address)) { + break; + } + } + + if (listener == NULL) { + *listenerp = NULL; + return; + } + + /* + * Now, keep the old access list unless a new one can be made. + */ + allow = cfg_tuple_get(listen_params, "allow"); + if (allow != NULL && cfg_obj_islist(allow)) { + result = cfg_acl_fromconfig(allow, config, named_g_lctx, + aclconfctx, listener->mctx, 0, + &new_acl); + } else { + result = dns_acl_any(listener->mctx, &new_acl); + } + + if (result == ISC_R_SUCCESS) { + LOCK(&listener->lock); + + dns_acl_detach(&listener->acl); + dns_acl_attach(new_acl, &listener->acl); + dns_acl_detach(&new_acl); + + UNLOCK(&listener->lock); + } else { + cfg_obj_log(listen_params, named_g_lctx, ISC_LOG_WARNING, + "couldn't install new acl for " + "statistics channel %s: %s", + socktext, isc_result_totext(result)); + } + + *listenerp = listener; +} + +isc_result_t +named_statschannels_configure(named_server_t *server, const cfg_obj_t *config, + cfg_aclconfctx_t *aclconfctx) { + named_statschannel_t *listener, *listener_next; + named_statschannellist_t new_listeners; + const cfg_obj_t *statschannellist = NULL; + const cfg_listelt_t *element, *element2; + char socktext[ISC_SOCKADDR_FORMATSIZE]; + + isc_once_do(&once, init_desc); + + ISC_LIST_INIT(new_listeners); + + /* + * Get the list of named.conf 'statistics-channels' statements. + */ + (void)cfg_map_get(config, "statistics-channels", &statschannellist); + + /* + * Run through the new address/port list, noting sockets that are + * already being listened on and moving them to the new list. + * + * Identifying duplicate addr/port combinations is left to either + * the underlying config code, or to the bind attempt getting an + * address-in-use error. + */ + if (statschannellist != NULL) { +#ifndef EXTENDED_STATS + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "statistics-channels specified but not effective " + "due to missing XML and/or JSON library"); +#else /* EXTENDED_STATS */ +#ifndef HAVE_LIBXML2 + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "statistics-channels: XML library missing, " + "only JSON stats will be available"); +#endif /* !HAVE_LIBXML2 */ +#ifndef HAVE_JSON_C + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "statistics-channels: JSON library missing, " + "only XML stats will be available"); +#endif /* !HAVE_JSON_C */ +#endif /* EXTENDED_STATS */ + + for (element = cfg_list_first(statschannellist); + element != NULL; element = cfg_list_next(element)) + { + const cfg_obj_t *statschannel; + const cfg_obj_t *listenercfg = NULL; + + statschannel = cfg_listelt_value(element); + (void)cfg_map_get(statschannel, "inet", &listenercfg); + if (listenercfg == NULL) { + continue; + } + + for (element2 = cfg_list_first(listenercfg); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + const cfg_obj_t *listen_params; + const cfg_obj_t *obj; + isc_sockaddr_t addr; + + listen_params = cfg_listelt_value(element2); + + obj = cfg_tuple_get(listen_params, "address"); + addr = *cfg_obj_assockaddr(obj); + if (isc_sockaddr_getport(&addr) == 0) { + isc_sockaddr_setport( + &addr, + NAMED_STATSCHANNEL_HTTPPORT); + } + + isc_sockaddr_format(&addr, socktext, + sizeof(socktext)); + + isc_log_write(named_g_lctx, + NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, + ISC_LOG_DEBUG(9), + "processing statistics " + "channel %s", + socktext); + + update_listener(server, &listener, + listen_params, config, &addr, + aclconfctx, socktext); + + if (listener != NULL) { + /* + * Remove the listener from the old + * list, so it won't be shut down. + */ + ISC_LIST_UNLINK(server->statschannels, + listener, link); + } else { + /* + * This is a new listener. + */ + isc_result_t r; + + r = add_listener(server, &listener, + listen_params, config, + &addr, aclconfctx, + socktext); + if (r != ISC_R_SUCCESS) { + cfg_obj_log( + listen_params, + named_g_lctx, + ISC_LOG_WARNING, + "couldn't allocate " + "statistics channel" + " %s: %s", + socktext, + isc_result_totext(r)); + } + } + + if (listener != NULL) { + ISC_LIST_APPEND(new_listeners, listener, + link); + } + } + } + } + + for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL; + listener = listener_next) + { + listener_next = ISC_LIST_NEXT(listener, link); + ISC_LIST_UNLINK(server->statschannels, listener, link); + shutdown_listener(listener); + } + + ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link); + return ISC_R_SUCCESS; +} + +void +named_statschannels_shutdown(named_server_t *server) { + named_statschannel_t *listener; + + while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) { + ISC_LIST_UNLINK(server->statschannels, listener, link); + shutdown_listener(listener); + } +} + +isc_result_t +named_stats_dump(named_server_t *server, FILE *fp) { + isc_result_t result; + dns_view_t *view; + dns_zone_t *zone, *next; + stats_dumparg_t dumparg; + uint64_t nsstat_values[ns_statscounter_max]; + uint64_t resstat_values[dns_resstatscounter_max]; + uint64_t adbstat_values[dns_adbstats_max]; + uint64_t zonestat_values[dns_zonestatscounter_max]; + uint64_t sockstat_values[isc_sockstatscounter_max]; + uint64_t gluecachestats_values[dns_gluecachestatscounter_max]; + isc_stdtime_t now = isc_stdtime_now(); + + isc_once_do(&once, init_desc); + + /* Set common fields */ + dumparg.type = isc_statsformat_file; + dumparg.arg = fp; + + fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now); + + fprintf(fp, "++ Incoming Requests ++\n"); + dns_opcodestats_dump(server->sctx->opcodestats, opcodestat_dump, + &dumparg, 0); + + fprintf(fp, "++ Incoming Queries ++\n"); + dns_rdatatypestats_dump(server->sctx->rcvquerystats, rdtypestat_dump, + &dumparg, 0); + + fprintf(fp, "++ Outgoing Rcodes ++\n"); + dns_rcodestats_dump(server->sctx->rcodestats, rcodestat_dump, &dumparg, + 0); + + fprintf(fp, "++ Outgoing Queries ++\n"); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + dns_stats_t *dstats = NULL; + dns_resolver_getquerystats(view->resolver, &dstats); + if (dstats == NULL) { + continue; + } + if (strcmp(view->name, "_default") == 0) { + fprintf(fp, "[View: default]\n"); + } else { + fprintf(fp, "[View: %s]\n", view->name); + } + dns_rdatatypestats_dump(dstats, rdtypestat_dump, &dumparg, 0); + dns_stats_detach(&dstats); + } + + fprintf(fp, "++ Name Server Statistics ++\n"); + (void)dump_stats(ns_stats_get(server->sctx->nsstats), + isc_statsformat_file, fp, NULL, nsstats_desc, + ns_statscounter_max, nsstats_index, nsstat_values, 0); + + fprintf(fp, "++ Zone Maintenance Statistics ++\n"); + (void)dump_stats(server->zonestats, isc_statsformat_file, fp, NULL, + zonestats_desc, dns_zonestatscounter_max, + zonestats_index, zonestat_values, 0); + + fprintf(fp, "++ Resolver Statistics ++\n"); + fprintf(fp, "[Common]\n"); + (void)dump_stats(server->resolverstats, isc_statsformat_file, fp, NULL, + resstats_desc, dns_resstatscounter_max, resstats_index, + resstat_values, 0); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + isc_stats_t *istats = NULL; + dns_resolver_getstats(view->resolver, &istats); + if (istats == NULL) { + continue; + } + if (strcmp(view->name, "_default") == 0) { + fprintf(fp, "[View: default]\n"); + } else { + fprintf(fp, "[View: %s]\n", view->name); + } + (void)dump_stats(istats, isc_statsformat_file, fp, NULL, + resstats_desc, dns_resstatscounter_max, + resstats_index, resstat_values, 0); + isc_stats_detach(&istats); + } + + fprintf(fp, "++ Cache Statistics ++\n"); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + if (strcmp(view->name, "_default") == 0) { + fprintf(fp, "[View: default]\n"); + } else { + fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, + dns_cache_getname(view->cache)); + } + /* + * Avoid dumping redundant statistics when the cache is shared. + */ + if (dns_view_iscacheshared(view)) { + continue; + } + dns_cache_dumpstats(view->cache, fp); + } + + fprintf(fp, "++ Cache DB RRsets ++\n"); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + dns_stats_t *cacherrstats; + + cacherrstats = dns_db_getrrsetstats(view->cachedb); + if (cacherrstats == NULL) { + continue; + } + if (strcmp(view->name, "_default") == 0) { + fprintf(fp, "[View: default]\n"); + } else { + fprintf(fp, "[View: %s (Cache: %s)]\n", view->name, + dns_cache_getname(view->cache)); + } + if (dns_view_iscacheshared(view)) { + /* + * Avoid dumping redundant statistics when the cache is + * shared. + */ + continue; + } + dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, + &dumparg, 0); + } + + fprintf(fp, "++ ADB stats ++\n"); + for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + dns_adb_t *adb = NULL; + isc_stats_t *adbstats = NULL; + + dns_view_getadb(view, &adb); + if (adb != NULL) { + adbstats = dns_adb_getstats(adb); + dns_adb_detach(&adb); + } + if (adbstats == NULL) { + continue; + } + if (strcmp(view->name, "_default") == 0) { + fprintf(fp, "[View: default]\n"); + } else { + fprintf(fp, "[View: %s]\n", view->name); + } + (void)dump_stats(adbstats, isc_statsformat_file, fp, NULL, + adbstats_desc, dns_adbstats_max, + adbstats_index, adbstat_values, 0); + } + + fprintf(fp, "++ Socket I/O Statistics ++\n"); + (void)dump_stats(server->sockstats, isc_statsformat_file, fp, NULL, + sockstats_desc, isc_sockstatscounter_max, + sockstats_index, sockstat_values, 0); + + fprintf(fp, "++ Per Zone Query Statistics ++\n"); + zone = NULL; + for (result = dns_zone_first(server->zonemgr, &zone); + result == ISC_R_SUCCESS; + next = NULL, result = dns_zone_next(zone, &next), zone = next) + { + isc_stats_t *zonestats = dns_zone_getrequeststats(zone); + if (zonestats != NULL) { + char zonename[DNS_NAME_FORMATSIZE]; + + view = dns_zone_getview(zone); + if (view == NULL) { + continue; + } + + dns_name_format(dns_zone_getorigin(zone), zonename, + sizeof(zonename)); + fprintf(fp, "[%s", zonename); + if (strcmp(view->name, "_default") != 0) { + fprintf(fp, " (view: %s)", view->name); + } + fprintf(fp, "]\n"); + + (void)dump_stats(zonestats, isc_statsformat_file, fp, + NULL, nsstats_desc, + ns_statscounter_max, nsstats_index, + nsstat_values, 0); + } + } + + fprintf(fp, "++ Per Zone Glue Cache Statistics ++\n"); + zone = NULL; + for (result = dns_zone_first(server->zonemgr, &zone); + result == ISC_R_SUCCESS; + next = NULL, result = dns_zone_next(zone, &next), zone = next) + { + isc_stats_t *gluecachestats = dns_zone_getgluecachestats(zone); + if (gluecachestats != NULL) { + char zonename[DNS_NAME_FORMATSIZE]; + + view = dns_zone_getview(zone); + if (view == NULL) { + continue; + } + + dns_name_format(dns_zone_getorigin(zone), zonename, + sizeof(zonename)); + fprintf(fp, "[%s", zonename); + if (strcmp(view->name, "_default") != 0) { + fprintf(fp, " (view: %s)", view->name); + } + fprintf(fp, "]\n"); + + (void)dump_stats(gluecachestats, isc_statsformat_file, + fp, NULL, gluecachestats_desc, + dns_gluecachestatscounter_max, + gluecachestats_index, + gluecachestats_values, 0); + } + } + + fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now); + + return ISC_R_SUCCESS; /* this function currently always succeeds */ +} diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c new file mode 100644 index 0000000..a072fa4 --- /dev/null +++ b/bin/named/tkeyconf.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#define RETERR(x) \ + do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto failure; \ + } while (0) + +#include +#define LOG(msg) \ + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, \ + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "%s", msg) + +isc_result_t +named_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, + dns_tkeyctx_t **tctxp) { + isc_result_t result; + dns_tkeyctx_t *tctx = NULL; + const char *s; + dns_fixedname_t fname; + dns_name_t *name; + isc_buffer_t b; + const cfg_obj_t *obj; + + result = dns_tkeyctx_create(mctx, &tctx); + if (result != ISC_R_SUCCESS) { + return result; + } + + obj = NULL; + result = cfg_map_get(options, "tkey-domain", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + isc_buffer_constinit(&b, s, strlen(s)); + isc_buffer_add(&b, strlen(s)); + name = dns_fixedname_initname(&fname); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); + dns_name_init(tctx->domain, NULL); + dns_name_dup(name, mctx, tctx->domain); + } + + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-credential", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + + isc_buffer_constinit(&b, s, strlen(s)); + isc_buffer_add(&b, strlen(s)); + name = dns_fixedname_initname(&fname); + RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); + RETERR(dst_gssapi_acquirecred(name, false, &tctx->gsscred)); + } + + obj = NULL; + result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); + if (result == ISC_R_SUCCESS) { + s = cfg_obj_asstring(obj); + tctx->gssapi_keytab = isc_mem_strdup(mctx, s); + } + + *tctxp = tctx; + return ISC_R_SUCCESS; + +failure: + dns_tkeyctx_destroy(&tctx); + return result; +} diff --git a/bin/named/transportconf.c b/bin/named/transportconf.c new file mode 100644 index 0000000..af5af9d --- /dev/null +++ b/bin/named/transportconf.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#define create_name(id, name) \ + isc_buffer_t namesrc, namebuf; \ + char namedata[DNS_NAME_FORMATSIZE + 1]; \ + dns_name_init(name, NULL); \ + isc_buffer_constinit(&namesrc, id, strlen(id)); \ + isc_buffer_add(&namesrc, strlen(id)); \ + isc_buffer_init(&namebuf, namedata, sizeof(namedata)); \ + result = (dns_name_fromtext(name, &namesrc, dns_rootname, \ + DNS_NAME_DOWNCASE, &namebuf)); \ + if (result != ISC_R_SUCCESS) { \ + goto failure; \ + } + +#define parse_transport_option(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + setter(transport, cfg_obj_asstring(obj)); \ + } \ + } + +#define parse_transport_tls_versions(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + { \ + uint32_t tls_protos = 0; \ + const cfg_listelt_t *proto = NULL; \ + INSIST(obj != NULL); \ + for (proto = cfg_list_first(obj); proto != 0; \ + proto = cfg_list_next(proto)) \ + { \ + const cfg_obj_t *tls_proto_obj = \ + cfg_listelt_value(proto); \ + const char *tls_sver = \ + cfg_obj_asstring( \ + tls_proto_obj); \ + const isc_tls_protocol_version_t ver = \ + isc_tls_protocol_name_to_version( \ + tls_sver); \ + INSIST(ver != \ + ISC_TLS_PROTO_VER_UNDEFINED); \ + INSIST(isc_tls_protocol_supported( \ + ver)); \ + tls_protos |= ver; \ + } \ + if (tls_protos != 0) { \ + setter(transport, tls_protos); \ + } \ + } \ + } \ + } + +#define parse_transport_bool_option(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + setter(transport, cfg_obj_asboolean(obj)); \ + } \ + } + +static isc_result_t +add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) { + const cfg_obj_t *doh = NULL; + const char *dohid = NULL; + isc_result_t result; + + for (const cfg_listelt_t *element = cfg_list_first(transportlist); + element != NULL; element = cfg_list_next(element)) + { + dns_name_t dohname; + dns_transport_t *transport; + + doh = cfg_listelt_value(element); + dohid = cfg_obj_asstring(cfg_map_getname(doh)); + + create_name(dohid, &dohname); + + transport = dns_transport_new(&dohname, DNS_TRANSPORT_HTTP, + list); + + dns_transport_set_tlsname(transport, dohid); + parse_transport_option(doh, transport, "key-file", + dns_transport_set_keyfile); + parse_transport_option(doh, transport, "cert-file", + dns_transport_set_certfile); + parse_transport_tls_versions(doh, transport, "protocols", + dns_transport_set_tls_versions); + parse_transport_option(doh, transport, "ciphers", + dns_transport_set_ciphers); + parse_transport_option(doh, transport, "cipher-suites", + dns_transport_set_cipher_suites); + parse_transport_bool_option( + doh, transport, "prefer-server-ciphers", + dns_transport_set_prefer_server_ciphers); + parse_transport_option(doh, transport, "ca-file", + dns_transport_set_cafile); + parse_transport_option(doh, transport, "remote-hostname", + dns_transport_set_remote_hostname); + } + + return ISC_R_SUCCESS; +failure: + cfg_obj_log(doh, named_g_lctx, ISC_LOG_ERROR, + "configuring DoH '%s': %s", dohid, + isc_result_totext(result)); + + return result; +} + +static isc_result_t +add_tls_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) { + const cfg_obj_t *tls = NULL; + const char *tlsid = NULL; + isc_result_t result; + + for (const cfg_listelt_t *element = cfg_list_first(transportlist); + element != NULL; element = cfg_list_next(element)) + { + dns_name_t tlsname; + dns_transport_t *transport; + + tls = cfg_listelt_value(element); + tlsid = cfg_obj_asstring(cfg_map_getname(tls)); + + if (!strcmp(tlsid, "ephemeral")) { + result = ISC_R_UNEXPECTEDTOKEN; + goto failure; + } + + create_name(tlsid, &tlsname); + + transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, + list); + + dns_transport_set_tlsname(transport, tlsid); + parse_transport_option(tls, transport, "key-file", + dns_transport_set_keyfile); + parse_transport_option(tls, transport, "cert-file", + dns_transport_set_certfile); + parse_transport_tls_versions(tls, transport, "protocols", + dns_transport_set_tls_versions); + parse_transport_option(tls, transport, "ciphers", + dns_transport_set_ciphers); + parse_transport_option(tls, transport, "cipher-suites", + dns_transport_set_cipher_suites); + parse_transport_bool_option( + tls, transport, "prefer-server-ciphers", + dns_transport_set_prefer_server_ciphers); + parse_transport_option(tls, transport, "ca-file", + dns_transport_set_cafile); + parse_transport_option(tls, transport, "remote-hostname", + dns_transport_set_remote_hostname); + } + + return ISC_R_SUCCESS; +failure: + cfg_obj_log(tls, named_g_lctx, ISC_LOG_ERROR, + "configuring tls '%s': %s", tlsid, + isc_result_totext(result)); + + return result; +} + +#define CHECK(f) \ + if ((result = f) != ISC_R_SUCCESS) { \ + goto failure; \ + } + +static isc_result_t +transport_list_fromconfig(const cfg_obj_t *config, dns_transport_list_t *list) { + const cfg_obj_t *obj = NULL; + isc_result_t result = ISC_R_SUCCESS; + + if (result == ISC_R_SUCCESS && + cfg_map_get(config, "tls", &obj) == ISC_R_SUCCESS) + { + result = add_tls_transports(obj, list); + obj = NULL; + } + + if (result == ISC_R_SUCCESS && + cfg_map_get(config, "doh", &obj) == ISC_R_SUCCESS) + { + result = add_doh_transports(obj, list); + obj = NULL; + } + + return result; +} + +static void +transport_list_add_ephemeral(dns_transport_list_t *list) { + isc_result_t result; + dns_name_t tlsname; + dns_transport_t *transport; + + create_name("ephemeral", &tlsname); + + transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, list); + dns_transport_set_tlsname(transport, "ephemeral"); + + return; +failure: + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +isc_result_t +named_transports_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_transport_list_t **listp) { + isc_result_t result; + dns_transport_list_t *list = dns_transport_list_new(mctx); + + REQUIRE(listp != NULL && *listp == NULL); + + transport_list_add_ephemeral(list); + + if (config != NULL) { + result = transport_list_fromconfig(config, list); + if (result != ISC_R_SUCCESS) { + goto failure; + } + } + + if (vconfig != NULL) { + config = cfg_tuple_get(vconfig, "options"); + transport_list_fromconfig(config, list); + } + + *listp = list; + return ISC_R_SUCCESS; +failure: + dns_transport_list_detach(&list); + return result; +} diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c new file mode 100644 index 0000000..0256e5a --- /dev/null +++ b/bin/named/tsigconf.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +static isc_result_t +add_initial_keys(const cfg_obj_t *list, dns_tsigkeyring_t *ring, + isc_mem_t *mctx) { + dns_tsigkey_t *tsigkey = NULL; + const cfg_listelt_t *element; + const cfg_obj_t *key = NULL; + const char *keyid = NULL; + unsigned char *secret = NULL; + int secretalloc = 0; + isc_result_t ret; + + for (element = cfg_list_first(list); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *algobj = NULL; + const cfg_obj_t *secretobj = NULL; + dns_name_t keyname; + dst_algorithm_t alg = DST_ALG_UNKNOWN; + const char *algstr = NULL; + char keynamedata[1024]; + isc_buffer_t keynamesrc, keynamebuf; + const char *secretstr = NULL; + isc_buffer_t secretbuf; + int secretlen = 0; + uint16_t bits; + + key = cfg_listelt_value(element); + keyid = cfg_obj_asstring(cfg_map_getname(key)); + + algobj = NULL; + secretobj = NULL; + (void)cfg_map_get(key, "algorithm", &algobj); + (void)cfg_map_get(key, "secret", &secretobj); + INSIST(algobj != NULL && secretobj != NULL); + + /* + * Create the key name. + */ + dns_name_init(&keyname, NULL); + isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid)); + isc_buffer_add(&keynamesrc, strlen(keyid)); + isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); + ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, + DNS_NAME_DOWNCASE, &keynamebuf); + if (ret != ISC_R_SUCCESS) { + goto failure; + } + + /* + * Create the algorithm. + */ + algstr = cfg_obj_asstring(algobj); + if (named_config_getkeyalgorithm(algstr, &alg, &bits) != + ISC_R_SUCCESS) + { + cfg_obj_log(algobj, named_g_lctx, ISC_LOG_ERROR, + "key '%s': has a " + "unsupported algorithm '%s'", + keyid, algstr); + ret = DNS_R_BADALG; + goto failure; + } + + secretstr = cfg_obj_asstring(secretobj); + secretalloc = secretlen = strlen(secretstr) * 3 / 4; + secret = isc_mem_get(mctx, secretlen); + isc_buffer_init(&secretbuf, secret, secretlen); + ret = isc_base64_decodestring(secretstr, &secretbuf); + if (ret != ISC_R_SUCCESS) { + goto failure; + } + secretlen = isc_buffer_usedlength(&secretbuf); + + ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, mctx, + &tsigkey); + isc_mem_put(mctx, secret, secretalloc); + secret = NULL; + if (ret == ISC_R_SUCCESS) { + ret = dns_tsigkeyring_add(ring, tsigkey); + } + if (ret != ISC_R_SUCCESS) { + if (tsigkey != NULL) { + dns_tsigkey_detach(&tsigkey); + } + goto failure; + } + /* + * Set digest bits. + */ + dst_key_setbits(tsigkey->key, bits); + dns_tsigkey_detach(&tsigkey); + } + + return ISC_R_SUCCESS; + +failure: + if (secret != NULL) { + isc_mem_put(mctx, secret, secretalloc); + } + cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, + "configuring key '%s': %s", keyid, isc_result_totext(ret)); + return ret; +} + +isc_result_t +named_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_tsigkeyring_t **ringp) { + const cfg_obj_t *maps[3]; + const cfg_obj_t *keylist; + dns_tsigkeyring_t *ring = NULL; + isc_result_t result; + int i; + + REQUIRE(ringp != NULL && *ringp == NULL); + + i = 0; + if (config != NULL) { + maps[i++] = config; + } + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + maps[i] = NULL; + + dns_tsigkeyring_create(mctx, &ring); + + for (i = 0;; i++) { + if (maps[i] == NULL) { + break; + } + keylist = NULL; + result = cfg_map_get(maps[i], "key", &keylist); + if (result != ISC_R_SUCCESS) { + continue; + } + result = add_initial_keys(keylist, ring, mctx); + if (result != ISC_R_SUCCESS) { + goto failure; + } + } + + *ringp = ring; + return ISC_R_SUCCESS; + +failure: + dns_tsigkeyring_detach(&ring); + return result; +} diff --git a/bin/named/xsl_p.h b/bin/named/xsl_p.h new file mode 100644 index 0000000..5623534 --- /dev/null +++ b/bin/named/xsl_p.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +extern const char xslmsg[]; diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c new file mode 100644 index 0000000..fc65069 --- /dev/null +++ b/bin/named/zoneconf.c @@ -0,0 +1,2085 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* ACLs associated with zone */ +typedef enum { + allow_notify, + allow_query, + allow_query_on, + allow_transfer, + allow_update, + allow_update_forwarding +} acl_type_t; + +#define CHECK(x) \ + do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +/*% + * Convenience function for configuring a single zone ACL. + */ +static isc_result_t +configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, + const cfg_obj_t *config, acl_type_t acltype, + cfg_aclconfctx_t *actx, dns_zone_t *zone, + void (*setzacl)(dns_zone_t *, dns_acl_t *), + void (*clearzacl)(dns_zone_t *)) { + isc_result_t result; + const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL }; + const cfg_obj_t *aclobj = NULL; + int i = 0; + dns_acl_t **aclp = NULL, *acl = NULL; + const char *aclname; + dns_view_t *view; + + view = dns_zone_getview(zone); + + switch (acltype) { + case allow_notify: + if (view != NULL) { + aclp = &view->notifyacl; + } + aclname = "allow-notify"; + break; + case allow_query: + if (view != NULL) { + aclp = &view->queryacl; + } + aclname = "allow-query"; + break; + case allow_query_on: + if (view != NULL) { + aclp = &view->queryonacl; + } + aclname = "allow-query-on"; + break; + case allow_transfer: + if (view != NULL) { + aclp = &view->transferacl; + } + aclname = "allow-transfer"; + break; + case allow_update: + if (view != NULL) { + aclp = &view->updateacl; + } + aclname = "allow-update"; + break; + case allow_update_forwarding: + if (view != NULL) { + aclp = &view->upfwdacl; + } + aclname = "allow-update-forwarding"; + break; + default: + UNREACHABLE(); + } + + /* First check to see if ACL is defined within the zone */ + if (zconfig != NULL) { + maps[0] = cfg_tuple_get(zconfig, "options"); + (void)named_config_get(maps, aclname, &aclobj); + if (aclobj != NULL) { + aclp = NULL; + goto parse_acl; + } + } + + /* Failing that, see if there's a default ACL already in the view */ + if (aclp != NULL && *aclp != NULL) { + (*setzacl)(zone, *aclp); + return ISC_R_SUCCESS; + } + + /* Check for default ACLs that haven't been parsed yet */ + if (vconfig != NULL) { + const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); + if (options != NULL) { + maps[i++] = options; + } + } + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + maps[i++] = named_g_defaults; + maps[i] = NULL; + + (void)named_config_get(maps, aclname, &aclobj); + if (aclobj == NULL) { + (*clearzacl)(zone); + return ISC_R_SUCCESS; + } + +parse_acl: + result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx, + named_g_mctx, 0, &acl); + if (result != ISC_R_SUCCESS) { + return result; + } + (*setzacl)(zone, acl); + + /* Set the view default now */ + if (aclp != NULL) { + dns_acl_attach(acl, aclp); + } + + dns_acl_detach(&acl); + return ISC_R_SUCCESS; +} + +/*% + * Parse the zone update-policy statement. + */ +static isc_result_t +configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname) { + const cfg_obj_t *updatepolicy = NULL; + const cfg_listelt_t *element, *element2; + dns_ssutable_t *table = NULL; + isc_mem_t *mctx = dns_zone_getmctx(zone); + bool autoddns = false; + isc_result_t result = ISC_R_SUCCESS; + + (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); + + if (updatepolicy == NULL) { + dns_zone_setssutable(zone, NULL); + return ISC_R_SUCCESS; + } + + if (cfg_obj_isstring(updatepolicy) && + strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) + { + autoddns = true; + updatepolicy = NULL; + } + + dns_ssutable_create(mctx, &table); + + for (element = cfg_list_first(updatepolicy); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *stmt = cfg_listelt_value(element); + const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); + const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); + const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); + const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); + const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); + const char *str; + bool grant = false; + bool usezone = false; + dns_ssumatchtype_t mtype = dns_ssumatchtype_name; + dns_fixedname_t fname, fident; + isc_buffer_t b; + dns_ssuruletype_t *types; + unsigned int i, n; + + str = cfg_obj_asstring(mode); + if (strcasecmp(str, "grant") == 0) { + grant = true; + } else if (strcasecmp(str, "deny") == 0) { + grant = false; + } else { + UNREACHABLE(); + } + + str = cfg_obj_asstring(matchtype); + CHECK(dns_ssu_mtypefromstring(str, &mtype)); + if (mtype == dns_ssumatchtype_subdomain && + strcasecmp(str, "zonesub") == 0) + { + usezone = true; + } + + dns_fixedname_init(&fident); + str = cfg_obj_asstring(identity); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fident), &b, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } + + dns_fixedname_init(&fname); + if (usezone) { + dns_name_copy(dns_zone_getorigin(zone), + dns_fixedname_name(&fname)); + } else { + str = cfg_obj_asstring(dname); + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(dns_fixedname_name(&fname), + &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, named_g_lctx, + ISC_LOG_ERROR, + "'%s' is not a valid name", str); + goto cleanup; + } + } + + n = named_config_listcount(typelist); + if (n == 0) { + types = NULL; + } else { + types = isc_mem_cget(mctx, n, sizeof(*types)); + } + + i = 0; + for (element2 = cfg_list_first(typelist); element2 != NULL; + element2 = cfg_list_next(element2)) + { + const cfg_obj_t *typeobj; + const char *bracket; + isc_textregion_t r; + unsigned long max = 0; + + INSIST(i < n); + + typeobj = cfg_listelt_value(element2); + str = cfg_obj_asstring(typeobj); + r.base = UNCONST(str); + + bracket = strchr(str, '(' /*)*/); + if (bracket != NULL) { + char *end = NULL; + r.length = bracket - str; + max = strtoul(bracket + 1, &end, 10); + if (max > 0xffff || end[0] != /*(*/ ')' || + end[1] != 0) + { + cfg_obj_log(identity, named_g_lctx, + ISC_LOG_ERROR, + "'%s' is not a valid count", + bracket); + isc_mem_cput(mctx, types, n, + sizeof(*types)); + goto cleanup; + } + } else { + r.length = strlen(str); + } + types[i].max = max; + + result = dns_rdatatype_fromtext(&types[i++].type, &r); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(identity, named_g_lctx, + ISC_LOG_ERROR, + "'%.*s' is not a valid type", + (int)r.length, str); + isc_mem_cput(mctx, types, n, sizeof(*types)); + goto cleanup; + } + } + INSIST(i == n); + + dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident), + mtype, dns_fixedname_name(&fname), n, + types); + if (types != NULL) { + isc_mem_cput(mctx, types, n, sizeof(*types)); + } + } + + /* + * If "update-policy local;" and a session key exists, + * then use the default policy, which is equivalent to: + * update-policy { grant zonesub any; }; + */ + if (autoddns) { + dns_ssuruletype_t any = { dns_rdatatype_any, 0 }; + + if (named_g_server->session_keyname == NULL) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to enable auto DDNS policy " + "for zone %s: session key not found", + zname); + result = ISC_R_NOTFOUND; + goto cleanup; + } + + dns_ssutable_addrule(table, true, + named_g_server->session_keyname, + dns_ssumatchtype_local, + dns_zone_getorigin(zone), 1, &any); + } + + dns_zone_setssutable(zone, table); + +cleanup: + dns_ssutable_detach(&table); + return result; +} + +/* + * This is the TTL used for internally generated RRsets for static-stub zones. + * The value doesn't matter because the mapping is static, but needs to be + * defined for the sake of implementation. + */ +#define STATICSTUB_SERVER_TTL 86400 + +/*% + * Configure an apex NS with glues for a static-stub zone. + * For example, for the zone named "example.com", the following RRs will be + * added to the zone DB: + * example.com. NS example.com. + * example.com. A 192.0.2.1 + * example.com. AAAA 2001:db8::1 + */ +static isc_result_t +configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist_ns, + dns_rdatalist_t *rdatalist_a, + dns_rdatalist_t *rdatalist_aaaa) { + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + isc_region_t region, sregion; + dns_rdata_t *rdata; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); element != NULL; + element = cfg_list_next(element)) + { + const isc_sockaddr_t *sa; + isc_netaddr_t na; + const cfg_obj_t *address = cfg_listelt_value(element); + dns_rdatalist_t *rdatalist; + + sa = cfg_obj_assockaddr(address); + if (isc_sockaddr_getport(sa) != 0) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "port is not configurable for " + "static stub server-addresses"); + return ISC_R_FAILURE; + } + isc_netaddr_fromsockaddr(&na, sa); + if (isc_netaddr_getzone(&na) != 0) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "scoped address is not allowed " + "for static stub " + "server-addresses"); + return ISC_R_FAILURE; + } + + switch (na.family) { + case AF_INET: + region.length = sizeof(na.type.in); + rdatalist = rdatalist_a; + break; + default: + INSIST(na.family == AF_INET6); + region.length = sizeof(na.type.in6); + rdatalist = rdatalist_aaaa; + break; + } + + rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length); + region.base = (unsigned char *)(rdata + 1); + memmove(region.base, &na.type, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + rdatalist->type, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + /* + * If no address is specified (unlikely in this context, but possible), + * there's nothing to do anymore. + */ + if (ISC_LIST_EMPTY(rdatalist_a->rdata) && + ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) + { + return ISC_R_SUCCESS; + } + + /* Add to the list an apex NS with the ns name being the origin name */ + dns_name_toregion(dns_zone_getorigin(zone), &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memmove(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns, + ®ion); + ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link); + + return result; +} + +/*% + * Configure an apex NS with an out-of-zone NS names for a static-stub zone. + * For example, for the zone named "example.com", something like the following + * RRs will be added to the zone DB: + * example.com. NS ns.example.net. + */ +static isc_result_t +configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, + dns_rdatalist_t *rdatalist, + const char *zname) { + const cfg_listelt_t *element; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_rdata_t *rdata; + isc_region_t sregion, region; + isc_result_t result = ISC_R_SUCCESS; + + for (element = cfg_list_first(zconfig); element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *obj; + const char *str; + dns_fixedname_t fixed_name; + dns_name_t *nsname; + isc_buffer_t b; + + obj = cfg_listelt_value(element); + str = cfg_obj_asstring(obj); + + nsname = dns_fixedname_initname(&fixed_name); + + isc_buffer_constinit(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "server-name '%s' is not a valid " + "name", + str); + return result; + } + if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) { + cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR, + "server-name '%s' must not be a " + "subdomain of zone name '%s'", + str, zname); + return ISC_R_FAILURE; + } + + dns_name_toregion(nsname, &sregion); + rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length); + region.length = sregion.length; + region.base = (unsigned char *)(rdata + 1); + memmove(region.base, sregion.base, region.length); + dns_rdata_init(rdata); + dns_rdata_fromregion(rdata, dns_zone_getclass(zone), + dns_rdatatype_ns, ®ion); + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + } + + return result; +} + +/*% + * Configure static-stub zone. + */ +static isc_result_t +configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, + const char *zname, const char *dbtype) { + int i = 0; + const cfg_obj_t *obj; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_db_t *db = NULL; + dns_dbversion_t *dbversion = NULL; + dns_dbnode_t *apexnode = NULL; + dns_name_t apexname; + isc_result_t result; + dns_rdataset_t rdataset; + dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; + dns_rdatalist_t *rdatalists[] = { &rdatalist_ns, &rdatalist_a, + &rdatalist_aaaa, NULL }; + dns_rdata_t *rdata; + isc_region_t region; + + /* Create the DB beforehand */ + result = dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), + dns_dbtype_stub, dns_zone_getclass(zone), 0, + NULL, &db); + if (result != ISC_R_SUCCESS) { + return result; + } + + dns_rdataset_init(&rdataset); + + dns_rdatalist_init(&rdatalist_ns); + rdatalist_ns.rdclass = dns_zone_getclass(zone); + rdatalist_ns.type = dns_rdatatype_ns; + rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_a); + rdatalist_a.rdclass = dns_zone_getclass(zone); + rdatalist_a.type = dns_rdatatype_a; + rdatalist_a.ttl = STATICSTUB_SERVER_TTL; + + dns_rdatalist_init(&rdatalist_aaaa); + rdatalist_aaaa.rdclass = dns_zone_getclass(zone); + rdatalist_aaaa.type = dns_rdatatype_aaaa; + rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; + + /* Prepare zone RRs from the configuration */ + obj = NULL; + result = cfg_map_get(zconfig, "server-addresses", &obj); + if (result == ISC_R_SUCCESS) { + INSIST(obj != NULL); + CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns, + &rdatalist_a, + &rdatalist_aaaa)); + } + + obj = NULL; + result = cfg_map_get(zconfig, "server-names", &obj); + if (result == ISC_R_SUCCESS) { + INSIST(obj != NULL); + CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns, + zname)); + } + + /* + * Sanity check: there should be at least one NS RR at the zone apex + * to trigger delegation. + */ + if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "No NS record is configured for a " + "static-stub zone '%s'", + zname); + result = ISC_R_FAILURE; + goto cleanup; + } + + /* + * Now add NS and glue A/AAAA RRsets to the zone DB. + * First open a new version for the add operation and get a pointer + * to the apex node (all RRs are of the apex name). + */ + CHECK(dns_db_newversion(db, &dbversion)); + + dns_name_init(&apexname, NULL); + dns_name_clone(dns_zone_getorigin(zone), &apexname); + CHECK(dns_db_findnode(db, &apexname, false, &apexnode)); + + /* Add NS RRset */ + dns_rdatalist_tordataset(&rdatalist_ns, &rdataset); + CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, + NULL)); + dns_rdataset_disassociate(&rdataset); + + /* Add glue A RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { + dns_rdatalist_tordataset(&rdatalist_a, &rdataset); + CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, + 0, NULL)); + dns_rdataset_disassociate(&rdataset); + } + + /* Add glue AAAA RRset, if any */ + if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { + dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset); + CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, + 0, NULL)); + dns_rdataset_disassociate(&rdataset); + } + + dns_db_closeversion(db, &dbversion, true); + dns_zone_setdb(zone, db); + + result = ISC_R_SUCCESS; + +cleanup: + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + if (apexnode != NULL) { + dns_db_detachnode(db, &apexnode); + } + if (dbversion != NULL) { + dns_db_closeversion(db, &dbversion, false); + } + if (db != NULL) { + dns_db_detach(&db); + } + for (i = 0; rdatalists[i] != NULL; i++) { + while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { + ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); + dns_rdata_toregion(rdata, ®ion); + isc_mem_put(mctx, rdata, + sizeof(*rdata) + region.length); + } + } + + INSIST(dbversion == NULL); + + return result; +} + +/*% + * Convert a config file zone type into a server zone type. + */ +static dns_zonetype_t +zonetype_fromconfig(const cfg_obj_t *map) { + const cfg_obj_t *obj = NULL; + isc_result_t result; + + result = cfg_map_get(map, "type", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + return named_config_getzonetype(obj); +} + +/*% + * Helper function for strtoargv(). Pardon the gratuitous recursion. + */ +static isc_result_t +strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp, + unsigned int n) { + isc_result_t result; + + /* Discard leading whitespace. */ + while (*s == ' ' || *s == '\t') { + s++; + } + + if (*s == '\0') { + /* We have reached the end of the string. */ + *argcp = n; + *argvp = isc_mem_cget(mctx, n, sizeof(char *)); + } else { + char *p = s; + while (*p != ' ' && *p != '\t' && *p != '\0') { + p++; + } + if (*p != '\0') { + *p++ = '\0'; + } + + result = strtoargvsub(mctx, p, argcp, argvp, n + 1); + if (result != ISC_R_SUCCESS) { + return result; + } + (*argvp)[n] = s; + } + return ISC_R_SUCCESS; +} + +/*% + * Tokenize the string "s" into whitespace-separated words, + * return the number of words in '*argcp' and an array + * of pointers to the words in '*argvp'. The caller + * must free the array using isc_mem_put(). The string + * is modified in-place. + */ +static isc_result_t +strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) { + return strtoargvsub(mctx, s, argcp, argvp, 0); +} + +static const char *const primary_synonyms[] = { "primary", "master", NULL }; + +static const char *const secondary_synonyms[] = { "secondary", "slave", NULL }; + +static void +checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, + const cfg_obj_t **objp) { + isc_result_t result; + + switch (ztype) { + case dns_zone_secondary: + case dns_zone_mirror: + result = named_checknames_get(maps, secondary_synonyms, objp); + break; + case dns_zone_primary: + result = named_checknames_get(maps, primary_synonyms, objp); + break; + default: + UNREACHABLE(); + } + + INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL); +} + +/* + * Callback to see if a non-recursive query coming from 'srcaddr' to + * 'destaddr', with optional key 'mykey' for class 'rdclass' would be + * delivered to 'myview'. + * + * We run this unlocked as both the view list and the interface list + * are updated when the appropriate task has exclusivity. + */ +static bool +isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr, + const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, + void *arg ISC_ATTR_UNUSED) { + dns_aclenv_t *env = NULL; + dns_view_t *view = NULL; + dns_tsigkey_t *key = NULL; + isc_netaddr_t netsrc; + isc_netaddr_t netdst; + + /* interfacemgr can be destroyed only in exclusive mode. */ + if (named_g_server->interfacemgr == NULL) { + return true; + } + + if (!ns_interfacemgr_listeningon(named_g_server->interfacemgr, dstaddr)) + { + return false; + } + + isc_netaddr_fromsockaddr(&netsrc, srcaddr); + isc_netaddr_fromsockaddr(&netdst, dstaddr); + env = ns_interfacemgr_getaclenv(named_g_server->interfacemgr); + + for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL; + view = ISC_LIST_NEXT(view, link)) + { + const dns_name_t *tsig = NULL; + + if (view->matchrecursiveonly) { + continue; + } + + if (rdclass != view->rdclass) { + continue; + } + + if (mykey != NULL) { + bool match; + isc_result_t result; + + result = dns_view_gettsig(view, mykey->name, &key); + if (result != ISC_R_SUCCESS) { + continue; + } + match = dst_key_compare(mykey->key, key->key); + dns_tsigkey_detach(&key); + if (!match) { + continue; + } + tsig = dns_tsigkey_identity(mykey); + } + + if (dns_acl_allowed(&netsrc, tsig, view->matchclients, env) && + dns_acl_allowed(&netdst, tsig, view->matchdestinations, + env)) + { + break; + } + } + return view == myview; +} + +/*% + * For mirror zones, change "notify yes;" to "notify explicit;", informing the + * user only if "notify" was explicitly configured rather than inherited from + * default configuration. + */ +static dns_notifytype_t +process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype, + const char *zname, const cfg_obj_t **maps) { + const cfg_obj_t *obj = NULL; + + /* + * Return the original setting if this is not a mirror zone or if the + * zone is configured with something else than "notify yes;". + */ + if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) { + return ntype; + } + + /* + * Only log a message if "notify" was set in the configuration + * hierarchy supplied in 'maps'. + */ + if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO, + "'notify explicit;' will be used for mirror zone " + "'%s'", + zname); + } + + return dns_notifytype_explicit; +} + +isc_result_t +named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, + const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, + dns_kasplist_t *kasplist, dns_keystorelist_t *keystorelist, + dns_zone_t *zone, dns_zone_t *raw) { + isc_result_t result; + const char *zname; + dns_rdataclass_t zclass; + dns_rdataclass_t vclass; + const cfg_obj_t *maps[5]; + const cfg_obj_t *nodefault[4]; + const cfg_obj_t *zoptions = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *obj; + const char *filename = NULL; + const char *kaspname = NULL; + const char *dupcheck; + dns_checkdstype_t checkdstype = dns_checkdstype_yes; + dns_notifytype_t notifytype = dns_notifytype_yes; + uint32_t count; + unsigned int dbargc; + char **dbargv; + static char default_dbtype[] = ZONEDB_DEFAULT; + static char dlz_dbtype[] = "dlz"; + char *cpval = default_dbtype; + isc_mem_t *mctx = dns_zone_getmctx(zone); + dns_dialuptype_t dialup = dns_dialuptype_no; + dns_zonetype_t ztype; + int i; + int32_t journal_size; + bool multi; + dns_kasp_t *kasp = NULL; + bool check = false, fail = false; + bool warn = false, ignore = false; + bool ixfrdiff; + bool use_kasp = false; + dns_masterformat_t masterformat; + const dns_master_style_t *masterstyle = &dns_master_style_default; + isc_stats_t *zoneqrystats; + dns_stats_t *rcvquerystats; + dns_stats_t *dnssecsignstats; + dns_zonestat_level_t statlevel = dns_zonestat_none; + dns_ttl_t maxttl = 0; /* unlimited */ + dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; + bool transferinsecs = ns_server_getoption(named_g_server->sctx, + NS_SERVER_TRANSFERINSECS); + + i = 0; + if (zconfig != NULL) { + zoptions = cfg_tuple_get(zconfig, "options"); + nodefault[i] = maps[i] = zoptions; + i++; + } + if (vconfig != NULL) { + nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options"); + i++; + } + if (config != NULL) { + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + nodefault[i] = maps[i] = options; + i++; + } + } + nodefault[i] = NULL; + maps[i++] = named_g_defaults; + maps[i] = NULL; + + if (vconfig != NULL) { + CHECK(named_config_getclass(cfg_tuple_get(vconfig, "class"), + dns_rdataclass_in, &vclass)); + } else { + vclass = dns_rdataclass_in; + } + + /* + * Configure values common to all zone types. + */ + + zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + + CHECK(named_config_getclass(cfg_tuple_get(zconfig, "class"), vclass, + &zclass)); + dns_zone_setclass(zone, zclass); + if (raw != NULL) { + dns_zone_setclass(raw, zclass); + } + + ztype = zonetype_fromconfig(zoptions); + if (raw != NULL) { + dns_zone_settype(raw, ztype); + dns_zone_settype(zone, dns_zone_primary); + } else { + dns_zone_settype(zone, ztype); + } + + obj = NULL; + result = cfg_map_get(zoptions, "database", &obj); + if (result == ISC_R_SUCCESS) { + cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); + } + if (cpval == NULL) { + CHECK(ISC_R_NOMEMORY); + } + + obj = NULL; + result = cfg_map_get(zoptions, "dlz", &obj); + if (result == ISC_R_SUCCESS) { + const char *dlzname = cfg_obj_asstring(obj); + size_t len; + + if (cpval != default_dbtype) { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': both 'database' and 'dlz' " + "specified", + zname); + CHECK(ISC_R_FAILURE); + } + + len = strlen(dlzname) + 5; + cpval = isc_mem_allocate(mctx, len); + snprintf(cpval, len, "dlz %s", dlzname); + } + + result = strtoargv(mctx, cpval, &dbargc, &dbargv); + if (result != ISC_R_SUCCESS && cpval != default_dbtype) { + isc_mem_free(mctx, cpval); + CHECK(result); + } + + /* + * ANSI C is strange here. There is no logical reason why (char **) + * cannot be promoted automatically to (const char * const *) by the + * compiler w/o generating a warning. + */ + dns_zone_setdbtype(zone, dbargc, (const char *const *)dbargv); + isc_mem_cput(mctx, dbargv, dbargc, sizeof(*dbargv)); + if (cpval != default_dbtype && cpval != dlz_dbtype) { + isc_mem_free(mctx, cpval); + } + + obj = NULL; + result = cfg_map_get(zoptions, "file", &obj); + if (result == ISC_R_SUCCESS) { + filename = cfg_obj_asstring(obj); + } + + /* + * Unless we're using some alternative database, a primary zone + * will be needing a master file. + */ + if (ztype == dns_zone_primary && cpval == default_dbtype && + filename == NULL) + { + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': 'file' not specified", zname); + CHECK(ISC_R_FAILURE); + } + + if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { + masterformat = dns_masterformat_raw; + } else { + masterformat = dns_masterformat_text; + } + obj = NULL; + result = named_config_get(maps, "masterfile-format", &obj); + if (result == ISC_R_SUCCESS) { + const char *masterformatstr = cfg_obj_asstring(obj); + + if (strcasecmp(masterformatstr, "text") == 0) { + masterformat = dns_masterformat_text; + } else if (strcasecmp(masterformatstr, "raw") == 0) { + masterformat = dns_masterformat_raw; + } else { + UNREACHABLE(); + } + } + + obj = NULL; + result = named_config_get(maps, "masterfile-style", &obj); + if (result == ISC_R_SUCCESS) { + const char *masterstylestr = cfg_obj_asstring(obj); + + if (masterformat != dns_masterformat_text) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "zone '%s': 'masterfile-style' " + "can only be used with " + "'masterfile-format text'", + zname); + CHECK(ISC_R_FAILURE); + } + + if (strcasecmp(masterstylestr, "full") == 0) { + masterstyle = &dns_master_style_full; + } else if (strcasecmp(masterstylestr, "relative") == 0) { + masterstyle = &dns_master_style_default; + } else { + UNREACHABLE(); + } + } + + obj = NULL; + result = named_config_get(maps, "max-records", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj)); + if (zone != mayberaw) { + dns_zone_setmaxrecords(zone, 0); + } + + obj = NULL; + result = named_config_get(maps, "max-records-per-type", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxrrperset(mayberaw, cfg_obj_asuint32(obj)); + if (zone != mayberaw) { + dns_zone_setmaxrrperset(zone, 0); + } + + obj = NULL; + result = named_config_get(maps, "max-types-per-name", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxtypepername(mayberaw, cfg_obj_asuint32(obj)); + if (zone != mayberaw) { + dns_zone_setmaxtypepername(zone, 0); + } + + if (raw != NULL && filename != NULL) { +#define SIGNED ".signed" + size_t signedlen = strlen(filename) + sizeof(SIGNED); + char *signedname; + + CHECK(dns_zone_setfile(raw, filename, masterformat, + masterstyle)); + signedname = isc_mem_get(mctx, signedlen); + + (void)snprintf(signedname, signedlen, "%s" SIGNED, filename); + result = dns_zone_setfile(zone, signedname, + dns_masterformat_raw, NULL); + isc_mem_put(mctx, signedname, signedlen); + CHECK(result); + } else { + CHECK(dns_zone_setfile(zone, filename, masterformat, + masterstyle)); + } + + obj = NULL; + result = cfg_map_get(zoptions, "journal", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); + } + + /* + * Notify messages are processed by the raw zone if it exists. + */ + if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { + CHECK(configure_zone_acl(zconfig, vconfig, config, allow_notify, + ac, mayberaw, dns_zone_setnotifyacl, + dns_zone_clearnotifyacl)); + } + + /* + * XXXAG This probably does not make sense for stubs. + */ + CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query, ac, + zone, dns_zone_setqueryacl, + dns_zone_clearqueryacl)); + + CHECK(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac, + zone, dns_zone_setqueryonacl, + dns_zone_clearqueryonacl)); + + obj = NULL; + result = named_config_get(maps, "dialup", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + dialup = dns_dialuptype_yes; + } else { + dialup = dns_dialuptype_no; + } + } else { + const char *dialupstr = cfg_obj_asstring(obj); + if (strcasecmp(dialupstr, "notify") == 0) { + dialup = dns_dialuptype_notify; + } else if (strcasecmp(dialupstr, "notify-passive") == 0) { + dialup = dns_dialuptype_notifypassive; + } else if (strcasecmp(dialupstr, "refresh") == 0) { + dialup = dns_dialuptype_refresh; + } else if (strcasecmp(dialupstr, "passive") == 0) { + dialup = dns_dialuptype_passive; + } else { + UNREACHABLE(); + } + } + if (raw != NULL) { + dns_zone_setdialup(raw, dialup); + } + dns_zone_setdialup(zone, dialup); + + obj = NULL; + result = named_config_get(maps, "zone-statistics", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + statlevel = dns_zonestat_full; + } else { + statlevel = dns_zonestat_none; + } + } else { + const char *levelstr = cfg_obj_asstring(obj); + if (strcasecmp(levelstr, "full") == 0) { + statlevel = dns_zonestat_full; + } else if (strcasecmp(levelstr, "terse") == 0) { + statlevel = dns_zonestat_terse; + } else if (strcasecmp(levelstr, "none") == 0) { + statlevel = dns_zonestat_none; + } else { + UNREACHABLE(); + } + } + dns_zone_setstatlevel(zone, statlevel); + + zoneqrystats = NULL; + rcvquerystats = NULL; + dnssecsignstats = NULL; + if (statlevel == dns_zonestat_full) { + isc_stats_create(mctx, &zoneqrystats, ns_statscounter_max); + dns_rdatatypestats_create(mctx, &rcvquerystats); + dns_dnssecsignstats_create(mctx, &dnssecsignstats); + } + dns_zone_setrequeststats(zone, zoneqrystats); + dns_zone_setrcvquerystats(zone, rcvquerystats); + dns_zone_setdnssecsignstats(zone, dnssecsignstats); + + if (zoneqrystats != NULL) { + isc_stats_detach(&zoneqrystats); + } + + if (rcvquerystats != NULL) { + dns_stats_detach(&rcvquerystats); + } + + if (dnssecsignstats != NULL) { + dns_stats_detach(&dnssecsignstats); + } + + /* + * Configure authoritative zone functionality. This applies + * to primary servers (type "primary") and secondaries + * acting as primaries (type "secondary"), but not to stubs. + */ + if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && + ztype != dns_zone_redirect) + { + /* Make a reference to the default policy. */ + result = dns_kasplist_find(kasplist, "default", &kasp); + INSIST(result == ISC_R_SUCCESS && kasp != NULL); + dns_zone_setdefaultkasp(zone, kasp); + dns_kasp_detach(&kasp); + + obj = NULL; + result = named_config_get(maps, "dnssec-policy", &obj); + if (result == ISC_R_SUCCESS) { + kaspname = cfg_obj_asstring(obj); + if (strcmp(kaspname, "none") != 0) { + result = dns_kasplist_find(kasplist, kaspname, + &kasp); + if (result != ISC_R_SUCCESS) { + cfg_obj_log( + obj, named_g_lctx, + ISC_LOG_ERROR, + "dnssec-policy '%s' not found ", + kaspname); + CHECK(result); + } + dns_zone_setkasp(zone, kasp); + use_kasp = true; + } + } + if (!use_kasp) { + dns_zone_setkasp(zone, NULL); + } + + obj = NULL; + result = named_config_get(maps, "notify", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + notifytype = dns_notifytype_yes; + } else { + notifytype = dns_notifytype_no; + } + } else { + const char *str = cfg_obj_asstring(obj); + if (strcasecmp(str, "explicit") == 0) { + notifytype = dns_notifytype_explicit; + } else if (strcasecmp(str, "master-only") == 0 || + strcasecmp(str, "primary-only") == 0) + { + notifytype = dns_notifytype_masteronly; + } else { + UNREACHABLE(); + } + } + notifytype = process_notifytype(notifytype, ztype, zname, + nodefault); + if (raw != NULL) { + dns_zone_setnotifytype(raw, dns_notifytype_no); + } + dns_zone_setnotifytype(zone, notifytype); + + obj = NULL; + result = named_config_get(maps, "also-notify", &obj); + if (result == ISC_R_SUCCESS && + (notifytype == dns_notifytype_yes || + notifytype == dns_notifytype_explicit || + (notifytype == dns_notifytype_masteronly && + ztype == dns_zone_primary))) + { + dns_ipkeylist_t ipkl; + dns_ipkeylist_init(&ipkl); + + CHECK(named_config_getipandkeylist(config, obj, mctx, + &ipkl)); + dns_zone_setalsonotify(zone, ipkl.addrs, ipkl.sources, + ipkl.keys, ipkl.tlss, + ipkl.count); + dns_ipkeylist_clear(mctx, &ipkl); + } else { + dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0); + } + + obj = NULL; + result = named_config_get(maps, "parental-source", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj)); + + obj = NULL; + result = named_config_get(maps, "parental-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj)); + + obj = NULL; + result = named_config_get(maps, "notify-source", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)); + + obj = NULL; + result = named_config_get(maps, "notify-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)); + + obj = NULL; + result = named_config_get(maps, "notify-to-soa", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, + cfg_obj_asboolean(obj)); + + dns_zone_setisself(zone, isself, NULL); + + CHECK(configure_zone_acl( + zconfig, vconfig, config, allow_transfer, ac, zone, + dns_zone_setxfracl, dns_zone_clearxfracl)); + + obj = NULL; + result = named_config_get(maps, "max-transfer-time-out", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxxfrout( + zone, transferinsecs ? cfg_obj_asuint32(obj) + : cfg_obj_asuint32(obj) * 60); + + obj = NULL; + result = named_config_get(maps, "max-transfer-idle-out", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setidleout(zone, transferinsecs + ? cfg_obj_asuint32(obj) + : cfg_obj_asuint32(obj) * 60); + + obj = NULL; + result = named_config_get(maps, "max-journal-size", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (raw != NULL) { + dns_zone_setjournalsize(raw, -1); + } + dns_zone_setjournalsize(zone, -1); + if (cfg_obj_isstring(obj)) { + const char *str = cfg_obj_asstring(obj); + if (strcasecmp(str, "unlimited") == 0) { + journal_size = DNS_JOURNAL_SIZE_MAX; + } else { + INSIST(strcasecmp(str, "default") == 0); + journal_size = -1; + } + } else { + uint64_t value = cfg_obj_asuint64(obj); + if (value > DNS_JOURNAL_SIZE_MAX) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "'max-journal-size " + "%" PRId64 "' " + "is too large", + value); + CHECK(ISC_R_RANGE); + } + journal_size = (uint32_t)value; + } + if (raw != NULL) { + dns_zone_setjournalsize(raw, journal_size); + } + dns_zone_setjournalsize(zone, journal_size); + + obj = NULL; + result = named_config_get(maps, "ixfr-from-differences", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isboolean(obj)) { + ixfrdiff = cfg_obj_asboolean(obj); + } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 || + strcasecmp(cfg_obj_asstring(obj), "master") == 0) && + ztype == dns_zone_primary) + { + ixfrdiff = true; + } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") == + 0 || + strcasecmp(cfg_obj_asstring(obj), "slave") == 0) && + ztype == dns_zone_secondary) + { + ixfrdiff = true; + } else { + ixfrdiff = false; + } + if (raw != NULL) { + dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, + true); + dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, + false); + } else { + dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, + ixfrdiff); + } + + obj = NULL; + result = named_config_get(maps, "max-ixfr-ratio", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (cfg_obj_isstring(obj)) { + dns_zone_setixfrratio(zone, 0); + } else { + dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj)); + } + + obj = NULL; + result = named_config_get(maps, "request-expire", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj)); + + obj = NULL; + result = named_config_get(maps, "request-ixfr", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); + + obj = NULL; + checknames(ztype, maps, &obj); + INSIST(obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + fail = false; + check = true; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + fail = check = true; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + fail = check = false; + } else { + UNREACHABLE(); + } + if (raw != NULL) { + dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check); + dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, + fail); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, + false); + } else { + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, + fail); + } + + obj = NULL; + result = named_config_get(maps, "notify-delay", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "check-sibling", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, + cfg_obj_asboolean(obj)); + + obj = NULL; + result = named_config_get(maps, "check-spf", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + check = true; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + check = false; + } else { + UNREACHABLE(); + } + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check); + + obj = NULL; + result = named_config_get(maps, "check-svcb", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSVCB, + cfg_obj_asboolean(obj)); + + obj = NULL; + result = named_config_get(maps, "zero-no-soa-ttl", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); + + obj = NULL; + result = named_config_get(maps, "nsec3-test-zone", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, + cfg_obj_asboolean(obj)); + } else if (ztype == dns_zone_redirect) { + dns_zone_setnotifytype(zone, dns_notifytype_no); + + obj = NULL; + result = named_config_get(maps, "max-journal-size", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setjournalsize(zone, -1); + if (cfg_obj_isstring(obj)) { + const char *str = cfg_obj_asstring(obj); + if (strcasecmp(str, "unlimited") == 0) { + journal_size = DNS_JOURNAL_SIZE_MAX; + } else { + INSIST(strcasecmp(str, "default") == 0); + journal_size = -1; + } + } else { + uint64_t value = cfg_obj_asuint64(obj); + if (value > DNS_JOURNAL_SIZE_MAX) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "'max-journal-size " + "%" PRId64 "' " + "is too large", + value); + CHECK(ISC_R_RANGE); + } + journal_size = (uint32_t)value; + } + dns_zone_setjournalsize(zone, journal_size); + } + + if (use_kasp) { + maxttl = dns_kasp_zonemaxttl(dns_zone_getkasp(zone), false); + } else { + obj = NULL; + result = named_config_get(maps, "max-zone-ttl", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isduration(obj)) { + maxttl = cfg_obj_asduration(obj); + } + } + } + dns_zone_setmaxttl(zone, maxttl); + if (raw != NULL) { + dns_zone_setmaxttl(raw, maxttl); + } + + /* + * Configure update-related options. These apply to + * primary servers only. + */ + if (ztype == dns_zone_primary) { + dns_acl_t *updateacl; + + CHECK(configure_zone_acl(zconfig, vconfig, config, allow_update, + ac, mayberaw, dns_zone_setupdateacl, + dns_zone_clearupdateacl)); + + updateacl = dns_zone_getupdateacl(mayberaw); + if (updateacl != NULL && dns_acl_isinsecure(updateacl)) { + isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, + NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, + "zone '%s' allows unsigned updates " + "from remote hosts, which is insecure", + zname); + } + + CHECK(configure_zone_ssutable(zoptions, mayberaw, zname)); + } + + /* + * Configure DNSSEC signing. These apply to primary zones or zones that + * use inline-signing (raw != NULL). + */ + if (ztype == dns_zone_primary || raw != NULL) { + if (use_kasp) { + int seconds; + + if (dns_kasp_nsec3(kasp)) { + result = dns_zone_setnsec3param( + zone, 1, dns_kasp_nsec3flags(kasp), + dns_kasp_nsec3iter(kasp), + dns_kasp_nsec3saltlen(kasp), NULL, true, + false); + } else { + result = dns_zone_setnsec3param( + zone, 0, 0, 0, 0, NULL, true, false); + } + INSIST(result == ISC_R_SUCCESS); + + seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp); + dns_zone_setkeyvalidityinterval(zone, seconds); + + seconds = (uint32_t)dns_kasp_sigvalidity(kasp); + dns_zone_setsigvalidityinterval(zone, seconds); + + seconds = (uint32_t)dns_kasp_sigrefresh(kasp); + dns_zone_setsigresigninginterval(zone, seconds); + } + + obj = NULL; + result = named_config_get(maps, "key-directory", &obj); + if (result == ISC_R_SUCCESS) { + filename = cfg_obj_asstring(obj); + CHECK(dns_zone_setkeydirectory(zone, filename)); + } + /* Also save a reference to the keystore list. */ + dns_zone_setkeystores(zone, keystorelist); + + obj = NULL; + result = named_config_get(maps, "sig-signing-signatures", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "sig-signing-nodes", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "sig-signing-type", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "dnssec-loadkeys-interval", + &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + CHECK(dns_zone_setrefreshkeyinterval(zone, + cfg_obj_asuint32(obj))); + + if (kasp != NULL) { + bool s2i = (strcmp(dns_kasp_getname(kasp), + "insecure") != 0); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, !s2i); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true); + } + } + + if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) { + CHECK(configure_zone_acl(zconfig, vconfig, config, + allow_update_forwarding, ac, mayberaw, + dns_zone_setforwardacl, + dns_zone_clearforwardacl)); + } + + /*% + * Configure parental agents, applies to primary and secondary zones. + */ + if (ztype == dns_zone_primary || ztype == dns_zone_secondary) { + const cfg_obj_t *parentals = NULL; + (void)cfg_map_get(zoptions, "parental-agents", &parentals); + if (parentals != NULL) { + dns_ipkeylist_t ipkl; + dns_ipkeylist_init(&ipkl); + CHECK(named_config_getipandkeylist(config, parentals, + mctx, &ipkl)); + dns_zone_setparentals(zone, ipkl.addrs, ipkl.sources, + ipkl.keys, ipkl.tlss, ipkl.count); + dns_ipkeylist_clear(mctx, &ipkl); + } else { + dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0); + } + + obj = NULL; + result = named_config_get(maps, "checkds", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + checkdstype = dns_checkdstype_yes; + } else { + checkdstype = dns_checkdstype_no; + } + } else { + const char *str = cfg_obj_asstring(obj); + if (strcasecmp(str, "explicit") == 0) { + checkdstype = dns_checkdstype_explicit; + } else { + UNREACHABLE(); + } + } + } else if (parentals != NULL) { + checkdstype = dns_checkdstype_explicit; + } else { + checkdstype = dns_checkdstype_yes; + } + if (raw != NULL) { + dns_zone_setcheckdstype(raw, dns_checkdstype_no); + } + dns_zone_setcheckdstype(zone, checkdstype); + } + + /*% + * Configure primary zone functionality. + */ + if (ztype == dns_zone_primary) { + obj = NULL; + result = named_config_get(maps, "check-wildcard", &obj); + if (result == ISC_R_SUCCESS) { + check = cfg_obj_asboolean(obj); + } else { + check = false; + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); + + obj = NULL; + result = named_config_get(maps, "check-dup-records", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dupcheck = cfg_obj_asstring(obj); + if (strcasecmp(dupcheck, "warn") == 0) { + fail = false; + check = true; + } else if (strcasecmp(dupcheck, "fail") == 0) { + fail = check = true; + } else if (strcasecmp(dupcheck, "ignore") == 0) { + fail = check = false; + } else { + UNREACHABLE(); + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); + + obj = NULL; + result = named_config_get(maps, "check-mx", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + fail = false; + check = true; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + fail = check = true; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + fail = check = false; + } else { + UNREACHABLE(); + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); + + obj = NULL; + result = named_config_get(maps, "check-integrity", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, + cfg_obj_asboolean(obj)); + + obj = NULL; + result = named_config_get(maps, "check-mx-cname", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + warn = true; + ignore = false; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + warn = ignore = false; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + warn = ignore = true; + } else { + UNREACHABLE(); + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); + + obj = NULL; + result = named_config_get(maps, "check-srv-cname", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + warn = true; + ignore = false; + } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { + warn = ignore = false; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + warn = ignore = true; + } else { + UNREACHABLE(); + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, + ignore); + + obj = NULL; + result = named_config_get(maps, "serial-update-method", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) { + dns_zone_setserialupdatemethod( + zone, dns_updatemethod_unixtime); + } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) { + dns_zone_setserialupdatemethod(zone, + dns_updatemethod_date); + } else { + dns_zone_setserialupdatemethod( + zone, dns_updatemethod_increment); + } + } + + /* + * Configure secondary zone functionality. + */ + switch (ztype) { + case dns_zone_mirror: + /* + * Disable outgoing zone transfers for mirror zones unless they + * are explicitly enabled by zone configuration. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "allow-transfer", &obj); + if (obj == NULL) { + dns_acl_t *none; + CHECK(dns_acl_none(mctx, &none)); + dns_zone_setxfracl(zone, none); + dns_acl_detach(&none); + } + FALLTHROUGH; + case dns_zone_secondary: + case dns_zone_stub: + case dns_zone_redirect: + count = 0; + obj = NULL; + (void)cfg_map_get(zoptions, "primaries", &obj); + if (obj == NULL) { + (void)cfg_map_get(zoptions, "masters", &obj); + } + + /* + * Use the built-in primary server list if one was not + * explicitly specified and this is a root zone mirror. + */ + if (obj == NULL && ztype == dns_zone_mirror && + dns_name_equal(dns_zone_getorigin(zone), dns_rootname)) + { + result = named_config_getremotesdef( + named_g_config, "remote-servers", + DEFAULT_IANA_ROOT_ZONE_PRIMARIES, &obj); + CHECK(result); + } + if (obj != NULL) { + dns_ipkeylist_t ipkl; + dns_ipkeylist_init(&ipkl); + + CHECK(named_config_getipandkeylist(config, obj, mctx, + &ipkl)); + dns_zone_setprimaries(mayberaw, ipkl.addrs, + ipkl.sources, ipkl.keys, + ipkl.tlss, ipkl.count); + count = ipkl.count; + dns_ipkeylist_clear(mctx, &ipkl); + } else { + dns_zone_setprimaries(mayberaw, NULL, NULL, NULL, NULL, + 0); + } + + multi = false; + if (count > 1) { + obj = NULL; + result = named_config_get(maps, "multi-master", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + multi = cfg_obj_asboolean(obj); + } + dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); + + obj = NULL; + result = named_config_get(maps, "min-transfer-rate-in", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + uint32_t traffic_bytes = + cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes")); + uint32_t time_minutes = + cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes")); + if (traffic_bytes == 0) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "zone '%s': 'min-transfer-rate-in' bytes" + "value can not be '0'", + zname); + CHECK(ISC_R_FAILURE); + } + /* Max. 28 days (in minutes). */ + const unsigned int time_minutes_max = 28 * 24 * 60; + if (time_minutes < 1 || time_minutes > time_minutes_max) { + cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR, + "zone '%s': 'min-transfer-rate-in' minutes" + "value is out of range (1..%u)", + zname, time_minutes_max); + CHECK(ISC_R_FAILURE); + } + dns_zone_setminxfrratein(mayberaw, traffic_bytes, + transferinsecs ? time_minutes + : time_minutes * 60); + + obj = NULL; + result = named_config_get(maps, "max-transfer-time-in", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxxfrin( + mayberaw, transferinsecs ? cfg_obj_asuint32(obj) + : cfg_obj_asuint32(obj) * 60); + + obj = NULL; + result = named_config_get(maps, "max-transfer-idle-in", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setidlein(mayberaw, + transferinsecs ? cfg_obj_asuint32(obj) + : cfg_obj_asuint32(obj) * 60); + + obj = NULL; + result = named_config_get(maps, "max-refresh-time", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "min-refresh-time", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "max-retry-time", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "min-retry-time", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); + + obj = NULL; + result = named_config_get(maps, "transfer-source", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setxfrsource4(mayberaw, cfg_obj_assockaddr(obj)); + + obj = NULL; + result = named_config_get(maps, "transfer-source-v6", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setxfrsource6(mayberaw, cfg_obj_assockaddr(obj)); + + obj = NULL; + (void)named_config_get(maps, "try-tcp-refresh", &obj); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, + cfg_obj_asboolean(obj)); + break; + + case dns_zone_staticstub: + CHECK(configure_staticstub(zoptions, zone, zname, + default_dbtype)); + break; + + default: + break; + } + + result = ISC_R_SUCCESS; + +cleanup: + if (kasp != NULL) { + dns_kasp_detach(&kasp); + } + return result; +} + +/* + * Set up a DLZ zone as writeable + */ +isc_result_t +named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, + dns_rdataclass_t rdclass, dns_name_t *name) { + dns_db_t *db = NULL; + isc_result_t result; + + dns_zone_settype(zone, dns_zone_dlz); + result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); + if (result != ISC_R_SUCCESS) { + return result; + } + result = dns_zone_dlzpostload(zone, db); + dns_db_detach(&db); + return result; +} + +bool +named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig, + const cfg_obj_t *vconfig, const cfg_obj_t *config, + dns_kasplist_t *kasplist) { + const cfg_obj_t *zoptions = NULL; + const cfg_obj_t *obj = NULL; + const char *cfilename; + const char *zfilename; + dns_zone_t *raw = NULL; + bool has_raw, inline_signing; + dns_zonetype_t ztype; + + zoptions = cfg_tuple_get(zconfig, "options"); + + /* + * We always reconfigure a static-stub zone for simplicity, assuming + * the amount of data to be loaded is small. + */ + if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: staticstub"); + return false; + } + + /* If there's a raw zone, use that for filename and type comparison */ + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + zfilename = dns_zone_getfile(raw); + ztype = dns_zone_gettype(raw); + dns_zone_detach(&raw); + has_raw = true; + } else { + zfilename = dns_zone_getfile(zone); + ztype = dns_zone_gettype(zone); + has_raw = false; + } + + inline_signing = named_zone_inlinesigning(zconfig, vconfig, config, + kasplist); + if (!inline_signing && has_raw) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: old zone was inline-signing"); + return false; + } else if (inline_signing && !has_raw) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: old zone was not inline-signing"); + return false; + } + + if (zonetype_fromconfig(zoptions) != ztype) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: type mismatch"); + return false; + } + + obj = NULL; + (void)cfg_map_get(zoptions, "file", &obj); + if (obj != NULL) { + cfilename = cfg_obj_asstring(obj); + } else { + cfilename = NULL; + } + if (!((cfilename == NULL && zfilename == NULL) || + (cfilename != NULL && zfilename != NULL && + strcmp(cfilename, zfilename) == 0))) + { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: filename mismatch"); + return false; + } + + return true; +} + +bool +named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, + const cfg_obj_t *config, dns_kasplist_t *kasplist) { + const cfg_obj_t *maps[4]; + const cfg_obj_t *signing = NULL; + const cfg_obj_t *policy = NULL; + dns_kasp_t *kasp = NULL; + isc_result_t res; + bool inline_signing = false; + int i = 0; + + maps[i++] = cfg_tuple_get(zconfig, "options"); + if (vconfig != NULL) { + maps[i++] = cfg_tuple_get(vconfig, "options"); + } + if (config != NULL) { + const cfg_obj_t *options = NULL; + (void)cfg_map_get(config, "options", &options); + if (options != NULL) { + maps[i++] = options; + } + } + maps[i] = NULL; + + /* Check the value in dnssec-policy. */ + policy = NULL; + res = named_config_get(maps, "dnssec-policy", &policy); + /* If no dnssec-policy found, then zone is not using inline-signing. */ + if (res != ISC_R_SUCCESS || + strcmp(cfg_obj_asstring(policy), "none") == 0) + { + return false; + } + + /* Lookup the policy. */ + res = dns_kasplist_find(kasplist, cfg_obj_asstring(policy), &kasp); + if (res != ISC_R_SUCCESS) { + return false; + } + + inline_signing = dns_kasp_inlinesigning(kasp); + dns_kasp_detach(&kasp); + + /* + * The zone option 'inline-signing' may override the value in + * dnssec-policy. This is a zone-only option, so look in maps[0] + * only. + */ + res = cfg_map_get(maps[0], "inline-signing", &signing); + if (res == ISC_R_SUCCESS && cfg_obj_isboolean(signing)) { + return cfg_obj_asboolean(signing); + } + + return inline_signing; +} diff --git a/bin/nsupdate/Makefile.am b/bin/nsupdate/Makefile.am new file mode 100644 index 0000000..4ef15ed --- /dev/null +++ b/bin/nsupdate/Makefile.am @@ -0,0 +1,30 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(GSSAPI_CFLAGS) \ + $(KRB5_CFLAGS) \ + $(READLINE_CFLAGS) + +AM_CPPFLAGS += \ + -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) \ + $(GSSAPI_LIBS) \ + $(KRB5_LIBS) + +if HAVE_READLINE +LDADD += \ + $(READLINE_LIBS) +endif + +bin_PROGRAMS = nsupdate + +nsupdate_SOURCES = \ + nsupdate.c \ + ../dig/readline.h diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in new file mode 100644 index 0000000..fc5a190 --- /dev/null +++ b/bin/nsupdate/Makefile.in @@ -0,0 +1,841 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +@HAVE_READLINE_TRUE@am__append_2 = \ +@HAVE_READLINE_TRUE@ $(READLINE_LIBS) + +bin_PROGRAMS = nsupdate$(EXEEXT) +subdir = bin/nsupdate +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_nsupdate_OBJECTS = nsupdate.$(OBJEXT) +nsupdate_OBJECTS = $(am_nsupdate_OBJECTS) +nsupdate_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_READLINE_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) +nsupdate_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) \ + $(LIBISCCFG_LIBS) $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_3) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/nsupdate.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(nsupdate_SOURCES) +DIST_SOURCES = $(nsupdate_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) $(GSSAPI_CFLAGS) $(KRB5_CFLAGS) \ + $(READLINE_CFLAGS) \ + -DSESSION_KEYFILE=\"${localstatedir}/run/named/session.key\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) $(LIBISCCFG_LIBS) $(GSSAPI_LIBS) \ + $(KRB5_LIBS) $(am__append_2) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +nsupdate_SOURCES = \ + nsupdate.c \ + ../dig/readline.h + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/nsupdate/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/nsupdate/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +nsupdate$(EXEEXT): $(nsupdate_OBJECTS) $(nsupdate_DEPENDENCIES) $(EXTRA_nsupdate_DEPENDENCIES) + @rm -f nsupdate$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(nsupdate_OBJECTS) $(nsupdate_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsupdate.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/nsupdate.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/nsupdate.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-binPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir doc-am doc-local dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-binPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c new file mode 100644 index 0000000..76013fe --- /dev/null +++ b/bin/nsupdate/nsupdate.c @@ -0,0 +1,3582 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#if HAVE_GSSAPI +#include + +#if HAVE_KRB5_KRB5_H +#include +#elif HAVE_KRB5_H +#include +#endif + +#if HAVE_GSSAPI_GSSAPI_H +#include +#elif HAVE_GSSAPI_H +#include +#endif + +#endif /* HAVE_GSSAPI */ + +#include "../dig/readline.h" + +#define MAXCMD (128 * 1024) +#define MAXWIRE (64 * 1024) +#define INITTEXT (2 * 1024) +#define MAXTEXT (128 * 1024) +#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */ + +#define DNSDEFAULTPORT 53 + +#define DEFAULT_EDNS_BUFSIZE 1232 + +/* Number of addresses to request from isc_getaddresses() */ +#define MAX_SERVERADDRS 4 + +static uint16_t dnsport = DNSDEFAULTPORT; + +#ifndef RESOLV_CONF +#define RESOLV_CONF "/etc/resolv.conf" +#endif /* ifndef RESOLV_CONF */ + +static bool debugging = false, ddebugging = false; +static bool memdebugging = false; +static bool have_ipv4 = false; +static bool have_ipv6 = false; +static bool is_dst_up = false; +static bool use_tls = false; +static bool usevc = false; +static bool usegsstsig = false; +static bool local_only = false; +static isc_nm_t *netmgr = NULL; +static isc_loopmgr_t *loopmgr = NULL; +static isc_log_t *glctx = NULL; +static isc_mem_t *gmctx = NULL; +static dns_dispatchmgr_t *dispatchmgr = NULL; +static dns_requestmgr_t *requestmgr = NULL; +static dns_dispatch_t *dispatchv4 = NULL; +static dns_dispatch_t *dispatchv6 = NULL; +static dns_message_t *updatemsg = NULL; +static dns_fixedname_t fuserzone; +static dns_fixedname_t fzname; +static dns_name_t *userzone = NULL; +static dns_name_t *zname = NULL; +static dns_name_t tmpzonename = DNS_NAME_INITEMPTY; +static dns_name_t restart_primary = DNS_NAME_INITEMPTY; +static dns_tsigkeyring_t *gssring = NULL; +static dns_tsigkey_t *tsigkey = NULL; +static dst_key_t *sig0key = NULL; +static isc_sockaddr_t *servers = NULL; +static isc_sockaddr_t *primary_servers = NULL; +static dns_transport_list_t *transport_list = NULL; +static dns_transport_t *transport = NULL; +static isc_tlsctx_cache_t *tls_ctx_cache = NULL; +static char *tls_hostname = NULL; +static char *tls_client_key_file = NULL; +static char *tls_client_cert_file = NULL; +static char *tls_ca_file = NULL; +static bool tls_always_verify_remote = true; +static bool default_servers = true; +static int ns_inuse = 0; +static int primary_inuse = 0; +static int ns_total = 0; +static int ns_alloc = 0; +static int primary_total = 0; +static int primary_alloc = 0; +static isc_sockaddr_t *localaddr4 = NULL; +static isc_sockaddr_t *localaddr6 = NULL; +static const char *keyfile = NULL; +static char *keystr = NULL; +static bool shuttingdown = false; +static FILE *input; +static bool interactive = true; +static bool seenerror = false; +static const dns_master_style_t *style; +static int requests = 0; +static unsigned int logdebuglevel = 0; +static unsigned int timeout = 300; +static unsigned int udp_timeout = 3; +static unsigned int udp_retries = 3; +static dns_rdataclass_t defaultclass = dns_rdataclass_in; +static dns_rdataclass_t zoneclass = dns_rdataclass_none; +static isc_mutex_t answer_lock; +static dns_message_t *answer = NULL; +static uint32_t default_ttl = 0; +static bool default_ttl_set = false; +static uint32_t lease = 0, keylease = 0; +static bool lease_set = false, keylease_set = false; +static bool checknames = true; +static bool checksvcb = true; +static const char *resolvconf = RESOLV_CONF; + +bool done = false; + +typedef struct nsu_requestinfo { + dns_message_t *msg; + isc_sockaddr_t *addr; +} nsu_requestinfo_t; + +static void +sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, + dns_request_t **request); +static void +send_update(dns_name_t *zonename, isc_sockaddr_t *primary); + +static void +getinput(void *arg); + +noreturn static void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +static void +ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +#if HAVE_GSSAPI +static dns_fixedname_t fkname; +static isc_sockaddr_t *kserver = NULL; +static char *realm = NULL; +static char servicename[DNS_NAME_FORMATSIZE]; +static dns_name_t *keyname; +typedef struct nsu_gssinfo { + dns_message_t *msg; + isc_sockaddr_t *addr; + gss_ctx_id_t context; +} nsu_gssinfo_t; + +static void +failed_gssrequest(void); +static void +start_gssrequest(dns_name_t *primary); +static void +send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, + dns_request_t **request, gss_ctx_id_t context); +static void +recvgss(void *arg); +#endif /* HAVE_GSSAPI */ + +static void +error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +#define STATUS_MORE (uint16_t)0 +#define STATUS_SEND (uint16_t)1 +#define STATUS_QUIT (uint16_t)2 +#define STATUS_SYNTAX (uint16_t)3 + +static void +primary_from_servers(void) { + if (primary_servers != NULL && primary_servers != servers) { + isc_mem_cput(gmctx, primary_servers, primary_alloc, + sizeof(isc_sockaddr_t)); + } + primary_servers = servers; + primary_total = ns_total; + primary_alloc = ns_alloc; + primary_inuse = ns_inuse; +} + +static dns_rdataclass_t +getzoneclass(void) { + if (zoneclass == dns_rdataclass_none) { + zoneclass = defaultclass; + } + return zoneclass; +} + +static bool +setzoneclass(dns_rdataclass_t rdclass) { + if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none) + { + zoneclass = rdclass; + } + if (zoneclass != rdclass) { + return false; + } + return true; +} + +static void +fatal(const char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + _exit(EXIT_FAILURE); +} + +static void +error(const char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +} + +static void +debug(const char *format, ...) { + va_list args; + + if (debugging) { + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + +static void +ddebug(const char *format, ...) { + va_list args; + + if (ddebugging) { + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + +ISC_NO_SANITIZE_ADDRESS static void +check_result(isc_result_t result, const char *msg) { + if (result != ISC_R_SUCCESS) { + fatal("%s: %s", msg, isc_result_totext(result)); + } +} + +static char * +nsu_strsep(char **stringp, const char *delim) { + char *string = *stringp; + *stringp = NULL; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) { + return NULL; + } + + for (; *string != '\0'; string++) { + sc = *string; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) { + break; + } + } + if (dc == 0) { + break; + } + } + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) { + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return string; + } + } + } + return string; +} + +static void +reset_system(void) { + ddebug("reset_system()"); + /* If the update message is still around, destroy it */ + if (updatemsg != NULL) { + dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); + } else { + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &updatemsg); + } + updatemsg->opcode = dns_opcode_update; + if (usegsstsig) { + if (tsigkey != NULL) { + dns_tsigkey_detach(&tsigkey); + } + if (gssring != NULL) { + dns_tsigkeyring_detach(&gssring); + } + } +} + +static bool +parse_hmac(const char *hmacstr, size_t len, dst_algorithm_t *hmac_alg, + uint16_t *digestbitsp) { + uint16_t digestbits = 0; + isc_result_t result; + char buf[20]; + + REQUIRE(hmac_alg != NULL); + REQUIRE(hmacstr != NULL); + + if (len >= sizeof(buf)) { + error("unknown key type '%.*s'", (int)(len), hmacstr); + return false; + } + + /* Copy len bytes and NUL terminate. */ + strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf))); + + if (strcasecmp(buf, "hmac-md5") == 0) { + *hmac_alg = DST_ALG_HMACMD5; + } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { + *hmac_alg = DST_ALG_HMACMD5; + result = isc_parse_uint16(&digestbits, &buf[9], 10); + if (result != ISC_R_SUCCESS || digestbits > 128) { + error("digest-bits out of range [0..128]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha1") == 0) { + *hmac_alg = DST_ALG_HMACSHA1; + } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) { + *hmac_alg = DST_ALG_HMACSHA1; + result = isc_parse_uint16(&digestbits, &buf[10], 10); + if (result != ISC_R_SUCCESS || digestbits > 160) { + error("digest-bits out of range [0..160]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha224") == 0) { + *hmac_alg = DST_ALG_HMACSHA224; + } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) { + *hmac_alg = DST_ALG_HMACSHA224; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 224) { + error("digest-bits out of range [0..224]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha256") == 0) { + *hmac_alg = DST_ALG_HMACSHA256; + } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) { + *hmac_alg = DST_ALG_HMACSHA256; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 256) { + error("digest-bits out of range [0..256]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha384") == 0) { + *hmac_alg = DST_ALG_HMACSHA384; + } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) { + *hmac_alg = DST_ALG_HMACSHA384; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 384) { + error("digest-bits out of range [0..384]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else if (strcasecmp(buf, "hmac-sha512") == 0) { + *hmac_alg = DST_ALG_HMACSHA512; + } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) { + *hmac_alg = DST_ALG_HMACSHA512; + result = isc_parse_uint16(&digestbits, &buf[12], 10); + if (result != ISC_R_SUCCESS || digestbits > 512) { + error("digest-bits out of range [0..512]"); + return false; + } + *digestbitsp = (digestbits + 7) & ~0x7U; + } else { + error("unknown key type '%s'", buf); + return false; + } + return true; +} + +static int +basenamelen(const char *file) { + int len = strlen(file); + + if (len > 1 && file[len - 1] == '.') { + len -= 1; + } else if (len > 8 && strcmp(file + len - 8, ".private") == 0) { + len -= 8; + } else if (len > 4 && strcmp(file + len - 4, ".key") == 0) { + len -= 4; + } + return len; +} + +static void +setup_keystr(void) { + unsigned char *secret = NULL; + int secretlen; + isc_buffer_t secretbuf; + isc_result_t result; + isc_buffer_t keynamesrc; + char *secretstr = NULL; + char *s = NULL, *n = NULL; + dns_fixedname_t fkeyname; + dns_name_t *mykeyname = NULL; + char *name = NULL; + dst_algorithm_t hmac_alg; + uint16_t digestbits = 0; + + mykeyname = dns_fixedname_initname(&fkeyname); + + debug("Creating key..."); + + s = strchr(keystr, ':'); + if (s == NULL || s == keystr || s[1] == 0) { + fatal("key option must specify [hmac:]keyname:secret"); + } + secretstr = s + 1; + n = strchr(secretstr, ':'); + if (n != NULL) { + if (n == secretstr || n[1] == 0) { + fatal("key option must specify [hmac:]keyname:secret"); + } + name = secretstr; + secretstr = n + 1; + if (!parse_hmac(keystr, s - keystr, &hmac_alg, &digestbits)) { + exit(EXIT_FAILURE); + } + } else { + hmac_alg = DST_ALG_HMACMD5; + name = keystr; + n = s; + } + + isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name)); + isc_buffer_add(&keynamesrc, (unsigned int)(n - name)); + + debug("namefromtext"); + result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0, + NULL); + check_result(result, "dns_name_fromtext"); + + secretlen = strlen(secretstr) * 3 / 4; + secret = isc_mem_allocate(gmctx, secretlen); + + isc_buffer_init(&secretbuf, secret, secretlen); + result = isc_base64_decodestring(secretstr, &secretbuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create key from %s: %s\n", keystr, + isc_result_totext(result)); + goto failure; + } + + secretlen = isc_buffer_usedlength(&secretbuf); + + debug("keycreate"); + result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen, + gmctx, &tsigkey); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create key from %s: %s\n", keystr, + isc_result_totext(result)); + } else { + dst_key_setbits(tsigkey->key, digestbits); + } +failure: + if (secret != NULL) { + isc_mem_free(gmctx, secret); + } +} + +/* + * Get a key from a named.conf format keyfile + */ +static isc_result_t +read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) { + cfg_parser_t *pctx = NULL; + cfg_obj_t *sessionkey = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + const char *mykeyname; + const char *secretstr; + const char *algorithm; + isc_result_t result; + int len; + + if (!isc_file_exists(keyfile)) { + return ISC_R_FILENOTFOUND; + } + + result = cfg_parser_create(mctx, lctx, &pctx); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + &sessionkey); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + result = cfg_map_get(sessionkey, "key", &key); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + (void)cfg_map_get(key, "secret", &secretobj); + (void)cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) { + fatal("key must have algorithm and secret"); + } + + mykeyname = cfg_obj_asstring(cfg_map_getname(key)); + secretstr = cfg_obj_asstring(secretobj); + algorithm = cfg_obj_asstring(algorithmobj); + + len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3; + keystr = isc_mem_allocate(mctx, len); + snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr); + setup_keystr(); + +cleanup: + if (pctx != NULL) { + if (sessionkey != NULL) { + cfg_obj_destroy(pctx, &sessionkey); + } + cfg_parser_destroy(&pctx); + } + + if (keystr != NULL) { + isc_mem_free(mctx, keystr); + } + + return result; +} + +static void +setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { + dst_key_t *dstkey = NULL; + isc_result_t result; + dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; + + debug("Creating key..."); + + if (sig0key != NULL) { + dst_key_free(&sig0key); + } + + /* Try reading the key from a K* pair */ + result = dst_key_fromnamedfile( + keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); + + /* If that didn't work, try reading it as a session.key keyfile */ + if (result != ISC_R_SUCCESS) { + result = read_sessionkey(mctx, lctx); + if (result == ISC_R_SUCCESS) { + return; + } + } + + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "could not read key from %.*s.{private,key}: " + "%s\n", + basenamelen(keyfile), keyfile, + isc_result_totext(result)); + return; + } + + switch (dst_key_alg(dstkey)) { + case DST_ALG_HMACMD5: + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: + case DST_ALG_HMACSHA256: + case DST_ALG_HMACSHA384: + case DST_ALG_HMACSHA512: + hmac_alg = dst_key_alg(dstkey); + break; + default: + dst_key_attach(dstkey, &sig0key); + dst_key_free(&dstkey); + return; + } + + result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmac_alg, + dstkey, false, false, NULL, 0, 0, + mctx, &tsigkey); + dst_key_free(&dstkey); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create key from %s: %s\n", keyfile, + isc_result_totext(result)); + } +} + +static void +doshutdown(void) { + /* + * The isc_mem_put of primary_servers must be before the + * isc_mem_put of servers as it sets the servers pointer + * to NULL. + */ + if (primary_servers != NULL && primary_servers != servers) { + isc_mem_cput(gmctx, primary_servers, primary_alloc, + sizeof(isc_sockaddr_t)); + } + + if (servers != NULL) { + isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); + } + + if (localaddr4 != NULL) { + isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t)); + } + + if (localaddr6 != NULL) { + isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t)); + } + + if (tsigkey != NULL) { + ddebug("Freeing TSIG key"); + dns_tsigkey_detach(&tsigkey); + } + + if (sig0key != NULL) { + ddebug("Freeing SIG(0) key"); + dst_key_free(&sig0key); + } + + if (updatemsg != NULL) { + dns_message_detach(&updatemsg); + } + + ddebug("Destroying request manager"); + dns_requestmgr_detach(&requestmgr); + + ddebug("Freeing the dispatchers"); + if (have_ipv4) { + dns_dispatch_detach(&dispatchv4); + } + if (have_ipv6) { + dns_dispatch_detach(&dispatchv6); + } + + ddebug("Shutting down dispatch manager"); + dns_dispatchmgr_detach(&dispatchmgr); +} + +static void +maybeshutdown(void) { + /* when called from getinput, doshutdown might be already finished */ + if (requestmgr == NULL) { + return; + } + + ddebug("Shutting down request manager"); + dns_requestmgr_shutdown(requestmgr); + + if (requests != 0) { + return; + } + + doshutdown(); +} + +static void +shutdown_program(void *arg) { + UNUSED(arg); + + ddebug("shutdown_program()"); + + shuttingdown = true; + maybeshutdown(); +} + +/* + * Try honoring the operating system's preferred ephemeral port range. + */ +static void +set_source_ports(dns_dispatchmgr_t *manager) { + isc_portset_t *v4portset = NULL, *v6portset = NULL; + in_port_t udpport_low, udpport_high; + isc_result_t result; + + result = isc_portset_create(gmctx, &v4portset); + check_result(result, "isc_portset_create (v4)"); + result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high); + check_result(result, "isc_net_getudpportrange (v4)"); + isc_portset_addrange(v4portset, udpport_low, udpport_high); + + result = isc_portset_create(gmctx, &v6portset); + check_result(result, "isc_portset_create (v6)"); + result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high); + check_result(result, "isc_net_getudpportrange (v6)"); + isc_portset_addrange(v6portset, udpport_low, udpport_high); + + result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset); + check_result(result, "dns_dispatchmgr_setavailports"); + + isc_portset_destroy(gmctx, &v4portset); + isc_portset_destroy(gmctx, &v6portset); +} + +static isc_result_t +create_name(const char *str, char *namedata, size_t len, dns_name_t *name) { + isc_buffer_t namesrc, namebuf; + + dns_name_init(name, NULL); + isc_buffer_constinit(&namesrc, str, strlen(str)); + isc_buffer_add(&namesrc, strlen(str)); + isc_buffer_init(&namebuf, namedata, len); + + return dns_name_fromtext(name, &namesrc, dns_rootname, + DNS_NAME_DOWNCASE, &namebuf); +} + +static void +setup_system(void *arg ISC_ATTR_UNUSED) { + isc_result_t result; + isc_sockaddr_t bind_any, bind_any6; + isc_sockaddrlist_t *nslist; + isc_logconfig_t *logconfig = NULL; + irs_resconf_t *resconf = NULL; + dns_name_t tlsname; + char namedata[DNS_NAME_FORMATSIZE + 1]; + + ddebug("setup_system()"); + + isc_log_create(gmctx, &glctx, &logconfig); + isc_log_setcontext(glctx); + dns_log_init(glctx); + dns_log_setcontext(glctx); + + result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL); + check_result(result, "isc_log_usechannel"); + + isc_log_setdebuglevel(glctx, logdebuglevel); + + result = irs_resconf_load(gmctx, resolvconf, &resconf); + if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { + fatal("parse of %s failed", resolvconf); + } + + nslist = irs_resconf_getnameservers(resconf); + + if (servers != NULL) { + if (primary_servers == servers) { + primary_servers = NULL; + } + isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); + } + + ns_inuse = 0; + if (local_only || ISC_LIST_EMPTY(*nslist)) { + struct in_addr in; + struct in6_addr in6; + + if (local_only && keyfile == NULL) { + keyfile = SESSION_KEYFILE; + } + + default_servers = !local_only; + + ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0); + servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); + + if (have_ipv6) { + memset(&in6, 0, sizeof(in6)); + in6.s6_addr[15] = 1; + isc_sockaddr_fromin6(&servers[0], &in6, dnsport); + } + if (have_ipv4) { + in.s_addr = htonl(INADDR_LOOPBACK); + isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)], &in, + dnsport); + } + } else { + isc_sockaddr_t *sa; + int i; + + /* + * Count the nameservers (skipping any that we can't use + * because of address family restrictions) and allocate + * the servers array. + */ + ns_total = 0; + for (sa = ISC_LIST_HEAD(*nslist); sa != NULL; + sa = ISC_LIST_NEXT(sa, link)) + { + switch (sa->type.sa.sa_family) { + case AF_INET: + if (have_ipv4) { + ns_total++; + } + break; + case AF_INET6: + if (have_ipv6) { + ns_total++; + } + break; + default: + fatal("bad family"); + } + } + + ns_alloc = ns_total; + servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); + + i = 0; + for (sa = ISC_LIST_HEAD(*nslist); sa != NULL; + sa = ISC_LIST_NEXT(sa, link)) + { + switch (sa->type.sa.sa_family) { + case AF_INET: + if (have_ipv4) { + sa->type.sin.sin_port = htons(dnsport); + } else { + continue; + } + break; + case AF_INET6: + if (have_ipv6) { + sa->type.sin6.sin6_port = + htons(dnsport); + } else { + continue; + } + break; + default: + fatal("bad family"); + } + INSIST(i < ns_alloc); + servers[i++] = *sa; + } + } + + irs_resconf_destroy(&resconf); + + result = dns_dispatchmgr_create(gmctx, loopmgr, netmgr, &dispatchmgr); + check_result(result, "dns_dispatchmgr_create"); + + result = dst_lib_init(gmctx, NULL); + check_result(result, "dst_lib_init"); + is_dst_up = true; + + set_source_ports(dispatchmgr); + + if (have_ipv6) { + isc_sockaddr_any6(&bind_any6); + result = dns_dispatch_createudp(dispatchmgr, &bind_any6, + &dispatchv6); + check_result(result, "dns_dispatch_createudp (v6)"); + } + + if (have_ipv4) { + isc_sockaddr_any(&bind_any); + result = dns_dispatch_createudp(dispatchmgr, &bind_any, + &dispatchv4); + check_result(result, "dns_dispatch_createudp (v4)"); + } + transport_list = dns_transport_list_new(gmctx); + + isc_tlsctx_cache_create(gmctx, &tls_ctx_cache); + + if (tls_client_key_file == NULL) { + result = create_name("tls-non-auth-client", namedata, + sizeof(namedata), &tlsname); + check_result(result, "create_name (tls-non-auth-client)"); + transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, + transport_list); + dns_transport_set_tlsname(transport, "tls-non-auth-client"); + } else { + result = create_name("tls-auth-client", namedata, + sizeof(namedata), &tlsname); + check_result(result, "create_name (tls-auth-client)"); + transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, + transport_list); + dns_transport_set_tlsname(transport, "tls-auth-client"); + dns_transport_set_keyfile(transport, tls_client_key_file); + dns_transport_set_certfile(transport, tls_client_cert_file); + } + dns_transport_set_cafile(transport, tls_ca_file); + dns_transport_set_remote_hostname(transport, tls_hostname); + dns_transport_set_always_verify_remote(transport, + tls_always_verify_remote); + + result = dns_requestmgr_create(gmctx, loopmgr, dispatchmgr, dispatchv4, + dispatchv6, &requestmgr); + check_result(result, "dns_requestmgr_create"); + + if (keystr != NULL) { + setup_keystr(); + } else if (local_only) { + result = read_sessionkey(gmctx, glctx); + if (result != ISC_R_SUCCESS) { + fatal("can't read key from %s: %s\n", keyfile, + isc_result_totext(result)); + } + } else if (keyfile != NULL) { + setup_keyfile(gmctx, glctx); + } + + isc_mutex_init(&answer_lock); +} + +static int +get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr, + int naddrs) { + int count = 0; + isc_result_t result; + + isc_loopmgr_blocking(loopmgr); + result = isc_getaddresses(host, port, sockaddr, naddrs, &count); + isc_loopmgr_nonblocking(loopmgr); + if (result != ISC_R_SUCCESS) { + error("couldn't get address for '%s': %s", host, + isc_result_totext(result)); + } + return count; +} + +#define PARSE_ARGS_FMT "46A:C:dDE:ghH:iK:lL:MoOk:p:Pr:R:St:Tu:vVy:" + +static void +pre_parse_args(int argc, char **argv) { + dns_rdatatype_t t; + int ch; + char buf[100]; + bool doexit = false; + bool ipv4only = false, ipv6only = false; + + while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { + switch (ch) { + case 'M': /* was -dm */ + debugging = true; + ddebugging = true; + memdebugging = true; + isc_mem_debugging = ISC_MEM_DEBUGTRACE | + ISC_MEM_DEBUGRECORD; + break; + + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + + case '?': + case 'h': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + argv[0], isc_commandline_option); + } + fprintf(stderr, "usage: nsupdate [-CdDi] [-L level] " + "[-l] [-g | -o | -y keyname:secret " + "| -k keyfile] [-p port] " + "[ -S [-K tlskeyfile] [-E tlscertfile] " + "[-A tlscafile] [-H tlshostname] " + "[-O] ] [-v] [-V] [-P] [-T] [-4 | -6] " + "[filename]\n"); + exit(EXIT_FAILURE); + + case 'P': + for (t = 0xff00; t <= 0xfffe; t++) { + if (dns_rdatatype_ismeta(t)) { + continue; + } + dns_rdatatype_format(t, buf, sizeof(buf)); + if (strncmp(buf, "TYPE", 4) != 0) { + fprintf(stdout, "%s\n", buf); + } + } + doexit = true; + break; + + case 'T': + for (t = 1; t <= 0xfeff; t++) { + if (dns_rdatatype_ismeta(t)) { + continue; + } + dns_rdatatype_format(t, buf, sizeof(buf)); + if (strncmp(buf, "TYPE", 4) != 0) { + fprintf(stdout, "%s\n", buf); + } + } + doexit = true; + break; + + case 'V': + printf("nsupdate %s\n", PACKAGE_VERSION); + doexit = true; + break; + + default: + break; + } + } + if (doexit) { + exit(EXIT_SUCCESS); + } + isc_commandline_reset = true; + isc_commandline_index = 1; +} + +static void +parse_args(int argc, char **argv) { + int ch; + uint32_t i; + isc_result_t result; + bool force_interactive = false; + + debug("parse_args"); + while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) { + switch (ch) { + case '4': + if (have_ipv4) { + isc_net_disableipv6(); + have_ipv6 = false; + } else { + fatal("can't find IPv4 networking"); + } + break; + case '6': + if (have_ipv6) { + isc_net_disableipv4(); + have_ipv4 = false; + } else { + fatal("can't find IPv6 networking"); + } + break; + case 'A': + use_tls = true; + tls_ca_file = isc_commandline_argument; + break; + case 'C': + resolvconf = isc_commandline_argument; + break; + case 'd': + debugging = true; + break; + case 'D': /* was -dd */ + debugging = true; + ddebugging = true; + break; + case 'E': + use_tls = true; + tls_client_cert_file = isc_commandline_argument; + break; + case 'H': + use_tls = true; + tls_hostname = isc_commandline_argument; + break; + case 'M': + break; + case 'i': + force_interactive = true; + interactive = true; + break; + case 'K': + use_tls = true; + tls_client_key_file = isc_commandline_argument; + break; + case 'l': + local_only = true; + break; + case 'L': + result = isc_parse_uint32(&i, isc_commandline_argument, + 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "bad library debug value " + "'%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + logdebuglevel = i; + break; + case 'y': + keystr = isc_commandline_argument; + break; + case 'v': + usevc = true; + break; + case 'k': + keyfile = isc_commandline_argument; + break; + case 'g': + usegsstsig = true; + break; + case 'o': + usegsstsig = true; + break; + case 'O': + use_tls = true; + tls_always_verify_remote = false; + break; + case 'p': + result = isc_parse_uint16(&dnsport, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "bad port number " + "'%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + case 'S': + use_tls = true; + break; + case 't': + result = isc_parse_uint32(&timeout, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad timeout '%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + if (timeout == 0) { + timeout = UINT_MAX; + } + break; + case 'u': + result = isc_parse_uint32(&udp_timeout, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad udp timeout '%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + case 'r': + result = isc_parse_uint32(&udp_retries, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad udp retries '%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + + case 'R': + fatal("The -R option has been deprecated."); + break; + + default: + fprintf(stderr, "%s: unhandled option: %c\n", argv[0], + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + if (keyfile != NULL && keystr != NULL) { + fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]); + exit(EXIT_FAILURE); + } + +#if HAVE_GSSAPI + if (usegsstsig && (keyfile != NULL || keystr != NULL)) { + fprintf(stderr, "%s: cannot specify -g with -k or -y\n", + argv[0]); + exit(EXIT_FAILURE); + } +#else /* HAVE_GSSAPI */ + if (usegsstsig) { + fprintf(stderr, + "%s: cannot specify -g or -o, " + "program not linked with GSS API Library\n", + argv[0]); + exit(EXIT_FAILURE); + } +#endif /* HAVE_GSSAPI */ + + if (use_tls) { + usevc = true; + if ((tls_client_key_file == NULL) != + (tls_client_cert_file == NULL)) + { + fprintf(stderr, + "%s: cannot specify the -K option without" + "the -E option, and vice versa.\n", + argv[0]); + exit(EXIT_FAILURE); + } + if (tls_ca_file != NULL && tls_always_verify_remote == false) { + fprintf(stderr, + "%s: cannot specify the -A option in " + "conjuction with the -O option.\n", + argv[0]); + exit(EXIT_FAILURE); + } + } + + if (argv[isc_commandline_index] != NULL) { + if (strcmp(argv[isc_commandline_index], "-") == 0) { + input = stdin; + } else { + result = isc_stdio_open(argv[isc_commandline_index], + "r", &input); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not open '%s': %s\n", + argv[isc_commandline_index], + isc_result_totext(result)); + exit(EXIT_FAILURE); + } + } + if (!force_interactive) { + interactive = false; + } + } +} + +static uint16_t +parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) { + isc_result_t result; + char *word; + isc_buffer_t source; + + word = nsu_strsep(cmdlinep, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read owner name\n"); + return STATUS_SYNTAX; + } + + dns_message_gettempname(msg, namep); + isc_buffer_init(&source, word, strlen(word)); + isc_buffer_add(&source, strlen(word)); + result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + error("invalid owner name: %s", isc_result_totext(result)); + isc_buffer_invalidate(&source); + dns_message_puttempname(msg, namep); + return STATUS_SYNTAX; + } + isc_buffer_invalidate(&source); + return STATUS_MORE; +} + +static uint16_t +parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, + dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) { + char *cmdline = *cmdlinep; + isc_buffer_t source, *buf = NULL, *newbuf = NULL; + isc_region_t r; + isc_lex_t *lex = NULL; + dns_rdatacallbacks_t callbacks; + isc_result_t result; + + if (cmdline == NULL) { + rdata->flags = DNS_RDATA_UPDATE; + return STATUS_MORE; + } + + while (*cmdline != 0 && isspace((unsigned char)*cmdline)) { + cmdline++; + } + + if (*cmdline != 0) { + dns_rdatacallbacks_init(&callbacks); + isc_lex_create(gmctx, strlen(cmdline), &lex); + isc_buffer_init(&source, cmdline, strlen(cmdline)); + isc_buffer_add(&source, strlen(cmdline)); + result = isc_lex_openbuffer(lex, &source); + check_result(result, "isc_lex_openbuffer"); + isc_buffer_allocate(gmctx, &buf, MAXWIRE); + result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex, + dns_rootname, 0, gmctx, buf, + &callbacks); + isc_lex_destroy(&lex); + if (result == ISC_R_SUCCESS) { + isc_buffer_usedregion(buf, &r); + isc_buffer_allocate(gmctx, &newbuf, r.length); + isc_buffer_putmem(newbuf, r.base, r.length); + isc_buffer_usedregion(newbuf, &r); + dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r); + isc_buffer_free(&buf); + dns_message_takebuffer(msg, &newbuf); + } else { + fprintf(stderr, "invalid rdata format: %s\n", + isc_result_totext(result)); + isc_buffer_free(&buf); + return STATUS_SYNTAX; + } + } else { + rdata->flags = DNS_RDATA_UPDATE; + } + *cmdlinep = cmdline; + return STATUS_MORE; +} + +static uint16_t +make_prereq(char *cmdline, bool ispositive, bool isrrset) { + isc_result_t result; + char *word; + dns_name_t *name = NULL; + isc_textregion_t region; + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + uint16_t retval; + + ddebug("make_prereq()"); + + /* + * Read the owner name + */ + retval = parse_name(&cmdline, updatemsg, &name); + if (retval != STATUS_MORE) { + return retval; + } + + /* + * If this is an rrset prereq, read the class or type. + */ + if (isrrset) { + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read class or type\n"); + goto failure; + } + region.base = word; + region.length = strlen(word); + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS) { + if (!setzoneclass(rdataclass)) { + fprintf(stderr, "class mismatch: %s\n", word); + goto failure; + } + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read type\n"); + goto failure; + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + goto failure; + } + } else { + rdataclass = getzoneclass(); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "invalid type: %s\n", word); + goto failure; + } + } + } else { + rdatatype = dns_rdatatype_any; + } + + dns_message_gettemprdata(updatemsg, &rdata); + + dns_rdata_init(rdata); + + if (isrrset && ispositive) { + retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, + rdata); + if (retval != STATUS_MORE) { + goto failure; + } + } else { + rdata->flags = DNS_RDATA_UPDATE; + } + + dns_message_gettemprdatalist(updatemsg, &rdatalist); + dns_message_gettemprdataset(updatemsg, &rdataset); + rdatalist->type = rdatatype; + if (ispositive) { + if (isrrset && rdata->data != NULL) { + rdatalist->rdclass = rdataclass; + } else { + rdatalist->rdclass = dns_rdataclass_any; + } + } else { + rdatalist->rdclass = dns_rdataclass_none; + } + rdata->rdclass = rdatalist->rdclass; + rdata->type = rdatatype; + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE); + return STATUS_MORE; + +failure: + if (name != NULL) { + dns_message_puttempname(updatemsg, &name); + } + return STATUS_SYNTAX; +} + +static uint16_t +evaluate_prereq(char *cmdline) { + char *word; + bool ispositive, isrrset; + + ddebug("evaluate_prereq()"); + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read operation code\n"); + return STATUS_SYNTAX; + } + if (strcasecmp(word, "nxdomain") == 0) { + ispositive = false; + isrrset = false; + } else if (strcasecmp(word, "yxdomain") == 0) { + ispositive = true; + isrrset = false; + } else if (strcasecmp(word, "nxrrset") == 0) { + ispositive = false; + isrrset = true; + } else if (strcasecmp(word, "yxrrset") == 0) { + ispositive = true; + isrrset = true; + } else { + fprintf(stderr, "incorrect operation code: %s\n", word); + return STATUS_SYNTAX; + } + return make_prereq(cmdline, ispositive, isrrset); +} + +static void +updateopt(void) { + isc_result_t result; + dns_ednsopt_t ednsopts[1]; + unsigned char ul[8]; + unsigned int count = 0; + + if (lease_set) { + isc_buffer_t b; + INSIST(count < ARRAY_SIZE(ednsopts)); + ednsopts[count++] = (dns_ednsopt_t){ .code = DNS_OPT_UL, + .length = keylease_set ? 8 + : 4, + .value = ul }; + + isc_buffer_init(&b, ul, sizeof(ul)); + isc_buffer_putuint32(&b, lease); + isc_buffer_putuint32(&b, keylease); + } + + if (count != 0) { + dns_rdataset_t *opt = NULL; + result = dns_message_buildopt(updatemsg, &opt, 0, + DEFAULT_EDNS_BUFSIZE, 0, ednsopts, + count); + check_result(result, "dns_message_buildopt"); + result = dns_message_setopt(updatemsg, opt); + check_result(result, "dns_message_setopt"); + } else { + result = dns_message_setopt(updatemsg, NULL); + check_result(result, "dns_message_setopt"); + } +} + +static uint16_t +evaluate_lease(char *cmdline) { + char *word; + isc_result_t result; + uint32_t value1, value2; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read ttl\n"); + return STATUS_SYNTAX; + } + + if (!strcasecmp(word, "none")) { + lease = 0; + lease_set = false; + keylease = 0; + keylease_set = false; + updateopt(); + return STATUS_MORE; + } + + result = isc_parse_uint32(&value1, word, 10); + if (result != ISC_R_SUCCESS) { + return STATUS_SYNTAX; + } + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + lease = value1; + lease_set = true; + keylease = 0; + keylease_set = false; + updateopt(); + return STATUS_MORE; + } + + result = isc_parse_uint32(&value2, word, 10); + if (result != ISC_R_SUCCESS) { + return STATUS_SYNTAX; + } + + lease = value1; + lease_set = true; + keylease = value2; + keylease_set = true; + updateopt(); + + return STATUS_MORE; +} + +static uint16_t +evaluate_server(char *cmdline) { + char *word, *server; + long port; + + if (local_only) { + fprintf(stderr, "cannot reset server in localhost-only mode\n"); + return STATUS_SYNTAX; + } + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read server name\n"); + return STATUS_SYNTAX; + } + server = word; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + port = dnsport; + } else { + char *endp; + port = strtol(word, &endp, 10); + if (*endp != 0) { + fprintf(stderr, "port '%s' is not numeric\n", word); + return STATUS_SYNTAX; + } else if (port < 1 || port > 65535) { + fprintf(stderr, + "port '%s' is out of range " + "(1 to 65535)\n", + word); + return STATUS_SYNTAX; + } + } + + if (servers != NULL) { + if (primary_servers == servers) { + primary_servers = NULL; + } + isc_mem_cput(gmctx, servers, ns_alloc, sizeof(isc_sockaddr_t)); + } + + default_servers = false; + + ns_alloc = MAX_SERVERADDRS; + ns_inuse = 0; + servers = isc_mem_cget(gmctx, ns_alloc, sizeof(isc_sockaddr_t)); + ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc); + if (ns_total == 0) { + return STATUS_SYNTAX; + } + + return STATUS_MORE; +} + +static uint16_t +evaluate_local(char *cmdline) { + char *word, *local; + long port; + struct in_addr in4; + struct in6_addr in6; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read server name\n"); + return STATUS_SYNTAX; + } + local = word; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + port = 0; + } else { + char *endp; + port = strtol(word, &endp, 10); + if (*endp != 0) { + fprintf(stderr, "port '%s' is not numeric\n", word); + return STATUS_SYNTAX; + } else if (port < 1 || port > 65535) { + fprintf(stderr, + "port '%s' is out of range " + "(1 to 65535)\n", + word); + return STATUS_SYNTAX; + } + } + + if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) { + if (localaddr6 == NULL) { + localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); + } + isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port); + } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) { + if (localaddr4 == NULL) { + localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); + } + isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port); + } else { + fprintf(stderr, "invalid address %s", local); + return STATUS_SYNTAX; + } + + return STATUS_MORE; +} + +static uint16_t +evaluate_key(char *cmdline) { + char *namestr; + char *secretstr; + isc_buffer_t b; + isc_result_t result; + dns_fixedname_t fkeyname; + dns_name_t *mykeyname; + int secretlen; + unsigned char *secret = NULL; + isc_buffer_t secretbuf; + dst_algorithm_t hmac_alg = DST_ALG_UNKNOWN; + uint16_t digestbits = 0; + char *n; + + namestr = nsu_strsep(&cmdline, " \t\r\n"); + if (namestr == NULL || *namestr == 0) { + fprintf(stderr, "could not read key name\n"); + return STATUS_SYNTAX; + } + + mykeyname = dns_fixedname_initname(&fkeyname); + + n = strchr(namestr, ':'); + if (n != NULL) { + if (!parse_hmac(namestr, n - namestr, &hmac_alg, &digestbits)) { + return STATUS_SYNTAX; + } + namestr = n + 1; + } else { + hmac_alg = DST_ALG_HMACMD5; + } + + isc_buffer_init(&b, namestr, strlen(namestr)); + isc_buffer_add(&b, strlen(namestr)); + result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not parse key name\n"); + return STATUS_SYNTAX; + } + + secretstr = nsu_strsep(&cmdline, "\r\n"); + if (secretstr == NULL || *secretstr == 0) { + fprintf(stderr, "could not read key secret\n"); + return STATUS_SYNTAX; + } + secretlen = strlen(secretstr) * 3 / 4; + secret = isc_mem_allocate(gmctx, secretlen); + + isc_buffer_init(&secretbuf, secret, secretlen); + result = isc_base64_decodestring(secretstr, &secretbuf); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create key from %s: %s\n", secretstr, + isc_result_totext(result)); + isc_mem_free(gmctx, secret); + return STATUS_SYNTAX; + } + secretlen = isc_buffer_usedlength(&secretbuf); + + if (tsigkey != NULL) { + dns_tsigkey_detach(&tsigkey); + } + result = dns_tsigkey_create(mykeyname, hmac_alg, secret, secretlen, + gmctx, &tsigkey); + isc_mem_free(gmctx, secret); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not create key from %s %s: %s\n", + namestr, secretstr, isc_result_totext(result)); + return STATUS_SYNTAX; + } + dst_key_setbits(tsigkey->key, digestbits); + return STATUS_MORE; +} + +static uint16_t +evaluate_zone(char *cmdline) { + char *word; + isc_buffer_t b; + isc_result_t result; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read zone name\n"); + return STATUS_SYNTAX; + } + + userzone = dns_fixedname_initname(&fuserzone); + isc_buffer_init(&b, word, strlen(word)); + isc_buffer_add(&b, strlen(word)); + result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + userzone = NULL; /* Lest it point to an invalid name */ + fprintf(stderr, "could not parse zone name\n"); + return STATUS_SYNTAX; + } + + return STATUS_MORE; +} + +static uint16_t +evaluate_realm(char *cmdline) { +#if HAVE_GSSAPI + char *word; + char buf[1024]; + int n; + + if (realm != NULL) { + isc_mem_free(gmctx, realm); + realm = NULL; + } + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + return STATUS_MORE; + } + + n = snprintf(buf, sizeof(buf), "@%s", word); + if (n < 0 || (size_t)n >= sizeof(buf)) { + error("realm is too long"); + return STATUS_SYNTAX; + } + realm = isc_mem_strdup(gmctx, buf); + return STATUS_MORE; +#else /* HAVE_GSSAPI */ + UNUSED(cmdline); + return STATUS_SYNTAX; +#endif /* HAVE_GSSAPI */ +} + +static uint16_t +evaluate_ttl(char *cmdline) { + char *word; + isc_result_t result; + uint32_t ttl; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read ttl\n"); + return STATUS_SYNTAX; + } + + if (!strcasecmp(word, "none")) { + default_ttl = 0; + default_ttl_set = false; + return STATUS_MORE; + } + + result = isc_parse_uint32(&ttl, word, 10); + if (result != ISC_R_SUCCESS) { + return STATUS_SYNTAX; + } + + if (ttl > TTL_MAX) { + fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, + TTL_MAX); + return STATUS_SYNTAX; + } + default_ttl = ttl; + default_ttl_set = true; + + return STATUS_MORE; +} + +static uint16_t +evaluate_class(char *cmdline) { + char *word; + isc_textregion_t r; + isc_result_t result; + dns_rdataclass_t rdclass; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read class name\n"); + return STATUS_SYNTAX; + } + + r.base = word; + r.length = strlen(word); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not parse class name: %s\n", word); + return STATUS_SYNTAX; + } + switch (rdclass) { + case dns_rdataclass_none: + case dns_rdataclass_any: + case dns_rdataclass_reserved0: + fprintf(stderr, "bad default class: %s\n", word); + return STATUS_SYNTAX; + default: + defaultclass = rdclass; + } + + return STATUS_MORE; +} + +static uint16_t +update_addordelete(char *cmdline, bool isdelete) { + isc_result_t result; + dns_name_t *name = NULL; + uint32_t ttl; + char *word; + dns_rdataclass_t rdataclass; + dns_rdatatype_t rdatatype; + dns_rdata_t *rdata = NULL; + dns_rdatalist_t *rdatalist = NULL; + dns_rdataset_t *rdataset = NULL; + isc_textregion_t region; + uint16_t retval; + + ddebug("update_addordelete()"); + + /* + * Read the owner name. + */ + retval = parse_name(&cmdline, updatemsg, &name); + if (retval != STATUS_MORE) { + return retval; + } + + dns_message_gettemprdata(updatemsg, &rdata); + + dns_rdata_init(rdata); + + /* + * If this is an add, read the TTL and verify that it's in range. + * If it's a delete, ignore a TTL if present (for compatibility). + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (!isdelete) { + fprintf(stderr, "could not read owner ttl\n"); + goto failure; + } else { + ttl = 0; + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } + } + result = isc_parse_uint32(&ttl, word, 10); + if (result != ISC_R_SUCCESS) { + if (isdelete) { + ttl = 0; + goto parseclass; + } else if (default_ttl_set) { + ttl = default_ttl; + goto parseclass; + } else { + fprintf(stderr, "ttl '%s': %s\n", word, + isc_result_totext(result)); + goto failure; + } + } + + if (isdelete) { + ttl = 0; + } else if (ttl > TTL_MAX) { + fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word, + TTL_MAX); + goto failure; + } + + /* + * Read the class or type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); +parseclass: + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read class or type\n"); + goto failure; + } + } + region.base = word; + region.length = strlen(word); + rdataclass = dns_rdataclass_any; + result = dns_rdataclass_fromtext(&rdataclass, ®ion); + if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) { + if (!setzoneclass(rdataclass)) { + fprintf(stderr, "class mismatch: %s\n", word); + goto failure; + } + /* + * Now read the type. + */ + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + if (isdelete) { + rdataclass = dns_rdataclass_any; + rdatatype = dns_rdatatype_any; + rdata->flags = DNS_RDATA_UPDATE; + goto doneparsing; + } else { + fprintf(stderr, "could not read type\n"); + goto failure; + } + } + region.base = word; + region.length = strlen(word); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "'%s' is not a valid type: %s\n", word, + isc_result_totext(result)); + goto failure; + } + } else { + rdataclass = getzoneclass(); + result = dns_rdatatype_fromtext(&rdatatype, ®ion); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "'%s' is not a valid class or type: " + "%s\n", + word, isc_result_totext(result)); + goto failure; + } + } + + retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata); + if (retval != STATUS_MORE) { + goto failure; + } + + if (isdelete) { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + rdataclass = dns_rdataclass_any; + } else { + rdataclass = dns_rdataclass_none; + } + } else { + if ((rdata->flags & DNS_RDATA_UPDATE) != 0) { + fprintf(stderr, "could not read rdata\n"); + goto failure; + } + } + + if (!isdelete && checknames) { + dns_fixedname_t fixed; + dns_name_t *bad; + + if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type, + true)) + { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(name, namebuf, sizeof(namebuf)); + fprintf(stderr, "check-names failed: bad owner '%s'\n", + namebuf); + goto failure; + } + + bad = dns_fixedname_initname(&fixed); + if (!dns_rdata_checknames(rdata, name, bad)) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(bad, namebuf, sizeof(namebuf)); + fprintf(stderr, "check-names failed: bad name '%s'\n", + namebuf); + goto failure; + } + } + + if (!isdelete && checksvcb && rdata->type == dns_rdatatype_svcb) { + result = dns_rdata_checksvcb(name, rdata); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "check-svcb failed: %s\n", + isc_result_totext(result)); + goto failure; + } + } + + if (!isdelete && rdata->type == dns_rdatatype_nsec3param) { + dns_rdata_nsec3param_t nsec3param; + + result = dns_rdata_tostruct(rdata, &nsec3param, NULL); + check_result(result, "dns_rdata_tostruct"); + if (nsec3param.iterations > dns_nsec3_maxiterations()) { + fprintf(stderr, + "NSEC3PARAM has excessive iterations (> %u)\n", + dns_nsec3_maxiterations()); + goto failure; + } + } + +doneparsing: + + dns_message_gettemprdatalist(updatemsg, &rdatalist); + dns_message_gettemprdataset(updatemsg, &rdataset); + rdatalist->type = rdatatype; + rdatalist->rdclass = rdataclass; + rdatalist->covers = rdatatype; + rdatalist->ttl = (dns_ttl_t)ttl; + ISC_LIST_APPEND(rdatalist->rdata, rdata, link); + dns_rdatalist_tordataset(rdatalist, rdataset); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE); + return STATUS_MORE; + +failure: + if (name != NULL) { + dns_message_puttempname(updatemsg, &name); + } + dns_message_puttemprdata(updatemsg, &rdata); + return STATUS_SYNTAX; +} + +static uint16_t +evaluate_update(char *cmdline) { + char *word; + bool isdelete; + + ddebug("evaluate_update()"); + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read operation code\n"); + return STATUS_SYNTAX; + } + if (strcasecmp(word, "delete") == 0) { + isdelete = true; + } else if (strcasecmp(word, "del") == 0) { + isdelete = true; + } else if (strcasecmp(word, "add") == 0) { + isdelete = false; + } else { + fprintf(stderr, "incorrect operation code: %s\n", word); + return STATUS_SYNTAX; + } + return update_addordelete(cmdline, isdelete); +} + +static uint16_t +evaluate_checknames(char *cmdline) { + char *word; + + ddebug("evaluate_checknames()"); + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read check-names directive\n"); + return STATUS_SYNTAX; + } + if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 || + strcasecmp(word, "on") == 0) + { + checknames = true; + } else if (strcasecmp(word, "no") == 0 || + strcasecmp(word, "false") == 0 || + strcasecmp(word, "off") == 0) + { + checknames = false; + } else { + fprintf(stderr, "incorrect check-names directive: %s\n", word); + return STATUS_SYNTAX; + } + return STATUS_MORE; +} + +static uint16_t +evaluate_checksvcb(char *cmdline) { + char *word; + + ddebug("evaluate_checksvcb()"); + word = nsu_strsep(&cmdline, " \t\r\n"); + if (word == NULL || *word == 0) { + fprintf(stderr, "could not read check-svcb directive\n"); + return STATUS_SYNTAX; + } + if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 || + strcasecmp(word, "on") == 0) + { + checksvcb = true; + } else if (strcasecmp(word, "no") == 0 || + strcasecmp(word, "false") == 0 || + strcasecmp(word, "off") == 0) + { + checksvcb = false; + } else { + fprintf(stderr, "incorrect check-svcb directive: %s\n", word); + return STATUS_SYNTAX; + } + return STATUS_MORE; +} + +static void +setzone(dns_name_t *zonename) { + isc_result_t result; + dns_name_t *name = NULL; + dns_rdataset_t *rdataset = NULL; + + result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE); + if (result == ISC_R_SUCCESS) { + dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name); + dns_message_removename(updatemsg, name, DNS_SECTION_ZONE); + for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; + rdataset = ISC_LIST_HEAD(name->list)) + { + ISC_LIST_UNLINK(name->list, rdataset, link); + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(updatemsg, &rdataset); + } + dns_message_puttempname(updatemsg, &name); + } + + if (zonename != NULL) { + dns_message_gettempname(updatemsg, &name); + dns_name_clone(zonename, name); + dns_message_gettemprdataset(updatemsg, &rdataset); + dns_rdataset_makequestion(rdataset, getzoneclass(), + dns_rdatatype_soa); + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); + } +} + +static void +show_message(FILE *stream, dns_message_t *msg, const char *description) { + isc_result_t result; + isc_buffer_t *buf = NULL; + int bufsz; + + ddebug("show_message()"); + + setzone(userzone); + + bufsz = INITTEXT; + do { + if (bufsz > MAXTEXT) { + fprintf(stderr, "could not allocate large enough " + "buffer to display message\n"); + exit(EXIT_FAILURE); + } + if (buf != NULL) { + isc_buffer_free(&buf); + } + isc_buffer_allocate(gmctx, &buf, bufsz); + result = dns_message_totext(msg, style, 0, buf); + bufsz *= 2; + } while (result == ISC_R_NOSPACE); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not convert message to text format.\n"); + isc_buffer_free(&buf); + return; + } + fprintf(stream, "%s\n%.*s", description, + (int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf)); + fflush(stream); + isc_buffer_free(&buf); +} + +static uint16_t +do_next_command(char *cmdline) { + char *word; + + ddebug("do_next_command()"); + word = nsu_strsep(&cmdline, " \t\r\n"); + + if (word == NULL || *word == 0) { + return STATUS_SEND; + } + if (word[0] == ';') { + return STATUS_MORE; + } + if (strcasecmp(word, "quit") == 0) { + return STATUS_QUIT; + } + if (strcasecmp(word, "prereq") == 0) { + return evaluate_prereq(cmdline); + } + if (strcasecmp(word, "nxdomain") == 0) { + return make_prereq(cmdline, false, false); + } + if (strcasecmp(word, "yxdomain") == 0) { + return make_prereq(cmdline, true, false); + } + if (strcasecmp(word, "nxrrset") == 0) { + return make_prereq(cmdline, false, true); + } + if (strcasecmp(word, "yxrrset") == 0) { + return make_prereq(cmdline, true, true); + } + if (strcasecmp(word, "update") == 0) { + return evaluate_update(cmdline); + } + if (strcasecmp(word, "delete") == 0) { + return update_addordelete(cmdline, true); + } + if (strcasecmp(word, "del") == 0) { + return update_addordelete(cmdline, true); + } + if (strcasecmp(word, "add") == 0) { + return update_addordelete(cmdline, false); + } + if (strcasecmp(word, "lease") == 0) { + return evaluate_lease(cmdline); + } + if (strcasecmp(word, "server") == 0) { + return evaluate_server(cmdline); + } + if (strcasecmp(word, "local") == 0) { + return evaluate_local(cmdline); + } + if (strcasecmp(word, "zone") == 0) { + return evaluate_zone(cmdline); + } + if (strcasecmp(word, "class") == 0) { + return evaluate_class(cmdline); + } + if (strcasecmp(word, "send") == 0) { + return STATUS_SEND; + } + if (strcasecmp(word, "debug") == 0) { + if (debugging) { + ddebugging = true; + } else { + debugging = true; + } + return STATUS_MORE; + } + if (strcasecmp(word, "ttl") == 0) { + return evaluate_ttl(cmdline); + } + if (strcasecmp(word, "show") == 0) { + show_message(stdout, updatemsg, "Outgoing update query:"); + return STATUS_MORE; + } + if (strcasecmp(word, "answer") == 0) { + LOCK(&answer_lock); + if (answer != NULL) { + show_message(stdout, answer, "Answer:"); + } + UNLOCK(&answer_lock); + return STATUS_MORE; + } + if (strcasecmp(word, "key") == 0) { + usegsstsig = false; + return evaluate_key(cmdline); + } + if (strcasecmp(word, "realm") == 0) { + return evaluate_realm(cmdline); + } + if (strcasecmp(word, "check-names") == 0 || + strcasecmp(word, "checknames") == 0) + { + return evaluate_checknames(cmdline); + } + if (strcasecmp(word, "check-svcb") == 0 || + strcasecmp(word, "checksvcb") == 0) + { + return evaluate_checksvcb(cmdline); + } + if (strcasecmp(word, "gsstsig") == 0) { +#if HAVE_GSSAPI + usegsstsig = true; +#else /* HAVE_GSSAPI */ + fprintf(stderr, "gsstsig not supported\n"); +#endif /* HAVE_GSSAPI */ + return STATUS_MORE; + } + if (strcasecmp(word, "oldgsstsig") == 0) { +#if HAVE_GSSAPI + usegsstsig = true; +#else /* HAVE_GSSAPI */ + fprintf(stderr, "gsstsig not supported\n"); +#endif /* HAVE_GSSAPI */ + return STATUS_MORE; + } + if (strcasecmp(word, "help") == 0) { + fprintf(stdout, "nsupdate " PACKAGE_VERSION ":\n" + "local address [port] (set local " + "resolver)\n" + "server address [port] (set primary server " + "for zone)\n" + "send (send the update " + "request)\n" + "show (show the update " + "request)\n" + "answer (show the answer to " + "the last request)\n" + "quit (quit, any pending " + "update is not sent)\n" + "help (display this " + "message)\n" + "key [hmac:]keyname secret (use TSIG to sign " + "the request)\n" + "gsstsig (use GSS_TSIG to " + "sign the request)\n" + "zone name (set the zone to be " + "updated)\n" + "class CLASS (set the zone's DNS " + "class, e.g. IN (default), CH)\n" + "check-names { on | off } (enable / disable " + "check-names)\n" + "[prereq] nxdomain name (require that this " + "name does not exist)\n" + "[prereq] yxdomain name (require that this " + "name exists)\n" + "[prereq] nxrrset .... (require that this " + "RRset does not exist)\n" + "[prereq] yxrrset .... (require that this " + "RRset exists)\n" + "[update] add .... (add the given " + "record to the zone)\n" + "[update] del[ete] .... (remove the given " + "record(s) from the zone)\n"); + return STATUS_MORE; + } + if (strcasecmp(word, "version") == 0) { + fprintf(stdout, "nsupdate " PACKAGE_VERSION "\n"); + return STATUS_MORE; + } + fprintf(stderr, "incorrect section name: %s\n", word); + return STATUS_SYNTAX; +} + +static uint16_t +get_next_command(void) { + uint16_t result = STATUS_QUIT; + char cmdlinebuf[MAXCMD]; + char *cmdline = NULL, *ptr = NULL; + + if (interactive) { + cmdline = ptr = readline("> "); + if (ptr != NULL && *ptr != 0) { + add_history(ptr); + } + } else { + cmdline = fgets(cmdlinebuf, MAXCMD, input); + } + + if (cmdline != NULL) { + char *tmp = cmdline; + + /* + * Normalize input by removing any eol as readline() + * removes eol but fgets doesn't. + */ + (void)nsu_strsep(&tmp, "\r\n"); + result = do_next_command(cmdline); + } + if (ptr != NULL) { + free(ptr); + } + + return result; +} + +static bool +user_interaction(void) { + uint16_t result = STATUS_MORE; + + ddebug("user_interaction()"); + while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) { + result = get_next_command(); + if (!interactive && result == STATUS_SYNTAX) { + fatal("syntax error"); + } + } + if (result == STATUS_SEND) { + return true; + } + return false; +} + +static void +done_update(void) { + ddebug("done_update()"); + + isc_async_current(getinput, NULL); +} + +static void +check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) { + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_any_tsig_t tsig; + + result = dns_rdataset_first(rdataset); + check_result(result, "dns_rdataset_first"); + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, &tsig, NULL); + check_result(result, "dns_rdata_tostruct"); + if (tsig.error != 0) { + if (isc_buffer_remaininglength(b) < 1) { + check_result(ISC_R_NOSPACE, "isc_buffer_" + "remaininglength"); + } + isc_buffer_putstr(b, "(" /*)*/); + result = dns_tsigrcode_totext(tsig.error, b); + check_result(result, "dns_tsigrcode_totext"); + if (isc_buffer_remaininglength(b) < 1) { + check_result(ISC_R_NOSPACE, "isc_buffer_" + "remaininglength"); + } + isc_buffer_putstr(b, /*(*/ ")"); + } +} + +static bool +next_primary(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); + fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, + isc_result_totext(eresult)); + if (++primary_inuse >= primary_total) { + return false; + } + ddebug("%s: trying next server", caller); + return true; +} + +static void +update_completed(void *arg) { + dns_request_t *request = (dns_request_t *)arg; + isc_result_t result; + + ddebug("update_completed()"); + + requests--; + + if (shuttingdown) { + dns_request_destroy(&request); + maybeshutdown(); + return; + } + + result = dns_request_getresult(request); + if (result != ISC_R_SUCCESS) { + if (!next_primary("update_completed", + &primary_servers[primary_inuse], result)) + { + seenerror = true; + goto done; + } + + ddebug("Destroying request [%p]", request); + dns_request_destroy(&request); + dns_message_renderreset(updatemsg); + dns_message_settsigkey(updatemsg, NULL); + send_update(zname, &primary_servers[primary_inuse]); + return; + } + + LOCK(&answer_lock); + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &answer); + result = dns_request_getresponse(request, answer, + DNS_MESSAGEPARSE_PRESERVEORDER); + switch (result) { + case ISC_R_SUCCESS: + if (answer->verify_attempted) { + ddebug("tsig verification successful"); + } + break; + case DNS_R_CLOCKSKEW: + case DNS_R_EXPECTEDTSIG: + case DNS_R_TSIGERRORSET: + case DNS_R_TSIGVERIFYFAILURE: + case DNS_R_UNEXPECTEDTSIG: + case ISC_R_FAILURE: +#if 0 + if (usegsstsig && answer->rcode == dns_rcode_noerror) { + /* + * For MS DNS that violates RFC 2845, section 4.2 + */ + break; + } +#endif /* if 0 */ + fprintf(stderr, "; TSIG error with server: %s\n", + isc_result_totext(result)); + seenerror = true; + break; + default: + check_result(result, "dns_request_getresponse"); + } + + if (answer->opcode != dns_opcode_update) { + fatal("invalid OPCODE in response to UPDATE request"); + } + + if (answer->rcode != dns_rcode_noerror) { + seenerror = true; + if (!debugging) { + char buf[64]; + isc_buffer_t b; + dns_rdataset_t *rds; + + isc_buffer_init(&b, buf, sizeof(buf) - 1); + result = dns_rcode_totext(answer->rcode, &b); + check_result(result, "dns_rcode_totext"); + rds = dns_message_gettsig(answer, NULL); + if (rds != NULL) { + check_tsig_error(rds, &b); + } + fprintf(stderr, "update failed: %.*s\n", + (int)isc_buffer_usedlength(&b), buf); + } + } + if (debugging) { + show_message(stderr, answer, "\nReply from update query:"); + } + UNLOCK(&answer_lock); + +done: + dns_request_destroy(&request); + if (usegsstsig) { + dns_name_free(&tmpzonename, gmctx); + dns_name_free(&restart_primary, gmctx); + dns_name_init(&tmpzonename, 0); + dns_name_init(&restart_primary, 0); + } + done_update(); +} + +static void +send_update(dns_name_t *zone, isc_sockaddr_t *primary) { + isc_result_t result; + dns_request_t *request = NULL; + isc_sockaddr_t *srcaddr; + unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_LARGE; + dns_transport_t *req_transport = NULL; + isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; + + ddebug("send_update()"); + + setzone(zone); + + if (usevc) { + options |= DNS_REQUESTOPT_TCP; + if (use_tls) { + req_transport = transport; + req_tls_ctx_cache = tls_ctx_cache; + } + } + + if (tsigkey == NULL && sig0key != NULL) { + result = dns_message_setsig0key(updatemsg, sig0key); + check_result(result, "dns_message_setsig0key"); + } + if (debugging) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(primary, addrbuf, sizeof(addrbuf)); + fprintf(stderr, "Sending update to %s\n", addrbuf); + } + + if (isc_sockaddr_pf(primary) == AF_INET6) { + srcaddr = localaddr6; + } else { + srcaddr = localaddr4; + } + + /* Windows doesn't like the tsig name to be compressed. */ + if (updatemsg->tsigname) { + updatemsg->tsigname->attributes.nocompress = true; + } + + result = dns_request_create(requestmgr, updatemsg, srcaddr, primary, + req_transport, req_tls_ctx_cache, options, + tsigkey, timeout, udp_timeout, udp_retries, + isc_loop_main(loopmgr), update_completed, + NULL, &request); + check_result(result, "dns_request_create"); + + if (debugging) { + show_message(stdout, updatemsg, "Outgoing update query:"); + } + + requests++; +} + +static void +next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) { + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); + fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf, + isc_result_totext(eresult)); + if (++ns_inuse >= ns_total) { + fatal("could not reach any name server"); + } else { + ddebug("%s: trying next server", caller); + } +} + +static void +recvsoa(void *arg) { + dns_request_t *request = (dns_request_t *)arg; + isc_result_t result, eresult = dns_request_getresult(request); + nsu_requestinfo_t *reqinfo = dns_request_getarg(request); + dns_message_t *soaquery = reqinfo->msg; + dns_message_t *rcvmsg = NULL; + dns_section_t section; + dns_name_t *name = NULL; + dns_rdataset_t *soaset = NULL; + dns_rdata_soa_t soa; + dns_rdata_t soarr = DNS_RDATA_INIT; + int pass = 0; + dns_name_t primary; + isc_sockaddr_t *addr = reqinfo->addr; + isc_sockaddr_t *srcaddr = NULL; + bool seencname = false; + dns_name_t tname; + unsigned int nlabels; + + ddebug("recvsoa()"); + + requests--; + + if (shuttingdown) { + dns_request_destroy(&request); + dns_message_detach(&soaquery); + isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); + maybeshutdown(); + return; + } + + if (eresult != ISC_R_SUCCESS) { + next_server("recvsoa", addr, eresult); + ddebug("Destroying request [%p]", request); + dns_request_destroy(&request); + dns_message_renderreset(soaquery); + dns_message_settsigkey(soaquery, NULL); + sendrequest(&servers[ns_inuse], soaquery, &request); + isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); + setzoneclass(dns_rdataclass_none); + return; + } + + isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); + reqinfo = NULL; + + ddebug("About to create rcvmsg"); + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg); + result = dns_request_getresponse(request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result == DNS_R_TSIGERRORSET && servers != NULL) { + unsigned int options = DNS_REQUESTOPT_CASE; + dns_transport_t *req_transport = NULL; + isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; + + dns_message_detach(&rcvmsg); + ddebug("Destroying request [%p]", request); + dns_request_destroy(&request); + reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); + reqinfo->msg = soaquery; + reqinfo->addr = addr; + dns_message_renderreset(soaquery); + ddebug("retrying soa request without TSIG"); + + if (!default_servers && usevc) { + options |= DNS_REQUESTOPT_TCP; + if (use_tls) { + req_transport = transport; + req_tls_ctx_cache = tls_ctx_cache; + } + } + + if (isc_sockaddr_pf(addr) == AF_INET6) { + srcaddr = localaddr6; + } else { + srcaddr = localaddr4; + } + + result = dns_request_create(requestmgr, soaquery, srcaddr, addr, + req_transport, req_tls_ctx_cache, + options, NULL, timeout, udp_timeout, + udp_retries, isc_loop_main(loopmgr), + recvsoa, reqinfo, &request); + check_result(result, "dns_request_create"); + requests++; + return; + } + check_result(result, "dns_request_getresponse"); + + if (rcvmsg->rcode == dns_rcode_refused) { + next_server("recvsoa", addr, DNS_R_REFUSED); + dns_message_detach(&rcvmsg); + dns_request_destroy(&request); + dns_message_renderreset(soaquery); + dns_message_settsigkey(soaquery, NULL); + sendrequest(&servers[ns_inuse], soaquery, &request); + return; + } + + section = DNS_SECTION_ANSWER; + POST(section); + if (debugging) { + show_message(stderr, rcvmsg, "Reply from SOA query:"); + } + + if (rcvmsg->opcode != dns_opcode_query) { + fatal("invalid OPCODE in response to SOA query"); + } + + if (rcvmsg->rcode != dns_rcode_noerror && + rcvmsg->rcode != dns_rcode_nxdomain) + { + fatal("response to SOA query was unsuccessful"); + } + + if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) { + char namebuf[DNS_NAME_FORMATSIZE]; + dns_name_format(userzone, namebuf, sizeof(namebuf)); + error("specified zone '%s' does not exist (NXDOMAIN)", namebuf); + dns_message_detach(&rcvmsg); + dns_request_destroy(&request); + dns_message_detach(&soaquery); + ddebug("Out of recvsoa"); + seenerror = true; + done_update(); + return; + } + +lookforsoa: + if (pass == 0) { + section = DNS_SECTION_ANSWER; + } else if (pass == 1) { + section = DNS_SECTION_AUTHORITY; + } else { + goto droplabel; + } + + result = dns_message_firstname(rcvmsg, section); + if (result != ISC_R_SUCCESS) { + pass++; + goto lookforsoa; + } + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(rcvmsg, section, &name); + soaset = NULL; + result = dns_message_findtype(name, dns_rdatatype_soa, 0, + &soaset); + if (result == ISC_R_SUCCESS) { + break; + } + if (section == DNS_SECTION_ANSWER) { + dns_rdataset_t *tset = NULL; + if (dns_message_findtype(name, dns_rdatatype_cname, 0, + &tset) == ISC_R_SUCCESS || + dns_message_findtype(name, dns_rdatatype_dname, 0, + &tset) == ISC_R_SUCCESS) + { + seencname = true; + break; + } + } + + result = dns_message_nextname(rcvmsg, section); + } + + if (soaset == NULL && !seencname) { + pass++; + goto lookforsoa; + } + + if (seencname) { + goto droplabel; + } + + if (debugging) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_name_format(name, namestr, sizeof(namestr)); + fprintf(stderr, "Found zone name: %s\n", namestr); + } + + result = dns_rdataset_first(soaset); + check_result(result, "dns_rdataset_first"); + + dns_rdata_init(&soarr); + dns_rdataset_current(soaset, &soarr); + result = dns_rdata_tostruct(&soarr, &soa, NULL); + check_result(result, "dns_rdata_tostruct"); + + dns_name_init(&primary, NULL); + dns_name_clone(&soa.origin, &primary); + + if (userzone != NULL) { + zname = userzone; + } else { + /* + * Save the zone name in case we need to try a second + * address. + */ + zname = dns_fixedname_initname(&fzname); + dns_name_copy(name, zname); + } + + if (debugging) { + char namestr[DNS_NAME_FORMATSIZE]; + dns_name_format(&primary, namestr, sizeof(namestr)); + fprintf(stderr, "The primary is: %s\n", namestr); + } + + if (default_servers) { + char serverstr[DNS_NAME_MAXTEXT + 1]; + isc_buffer_t buf; + + isc_buffer_init(&buf, serverstr, sizeof(serverstr)); + result = dns_name_totext(&primary, DNS_NAME_OMITFINALDOT, &buf); + check_result(result, "dns_name_totext"); + serverstr[isc_buffer_usedlength(&buf)] = 0; + + if (primary_servers != NULL && primary_servers != servers) { + isc_mem_cput(gmctx, primary_servers, primary_alloc, + sizeof(isc_sockaddr_t)); + } + primary_alloc = MAX_SERVERADDRS; + primary_servers = isc_mem_cget(gmctx, primary_alloc, + sizeof(isc_sockaddr_t)); + primary_total = get_addresses(serverstr, dnsport, + primary_servers, primary_alloc); + if (primary_total == 0) { + seenerror = true; + dns_rdata_freestruct(&soa); + dns_message_detach(&soaquery); + dns_request_destroy(&request); + dns_message_detach(&rcvmsg); + ddebug("Out of recvsoa"); + done_update(); + return; + } + primary_inuse = 0; + } else { + primary_from_servers(); + } + dns_rdata_freestruct(&soa); + +#if HAVE_GSSAPI + if (usegsstsig) { + dns_name_init(&tmpzonename, NULL); + dns_name_dup(zname, gmctx, &tmpzonename); + dns_name_init(&restart_primary, NULL); + dns_name_dup(&primary, gmctx, &restart_primary); + start_gssrequest(&primary); + } else { + send_update(zname, &primary_servers[primary_inuse]); + setzoneclass(dns_rdataclass_none); + } +#else /* HAVE_GSSAPI */ + send_update(zname, &primary_servers[primary_inuse]); + setzoneclass(dns_rdataclass_none); +#endif /* HAVE_GSSAPI */ + + dns_message_detach(&soaquery); + dns_request_destroy(&request); + +out: + dns_message_detach(&rcvmsg); + ddebug("Out of recvsoa"); + return; + +droplabel: + result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION); + INSIST(result == ISC_R_SUCCESS); + name = NULL; + dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name); + nlabels = dns_name_countlabels(name); + if (nlabels == 1) { + fatal("could not find enclosing zone"); + } + dns_name_init(&tname, NULL); + dns_name_getlabelsequence(name, 1, nlabels - 1, &tname); + dns_name_clone(&tname, name); + dns_request_destroy(&request); + dns_message_renderreset(soaquery); + dns_message_settsigkey(soaquery, NULL); + sendrequest(&servers[ns_inuse], soaquery, &request); + goto out; +} + +static void +sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, + dns_request_t **request) { + isc_result_t result; + nsu_requestinfo_t *reqinfo; + isc_sockaddr_t *srcaddr; + unsigned int options = DNS_REQUESTOPT_CASE; + dns_transport_t *req_transport = NULL; + isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; + + if (!default_servers && usevc) { + options |= DNS_REQUESTOPT_TCP; + if (use_tls) { + req_transport = transport; + req_tls_ctx_cache = tls_ctx_cache; + } + } + + reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); + reqinfo->msg = msg; + reqinfo->addr = destaddr; + + if (isc_sockaddr_pf(destaddr) == AF_INET6) { + srcaddr = localaddr6; + } else { + srcaddr = localaddr4; + } + + result = dns_request_create( + requestmgr, msg, srcaddr, destaddr, req_transport, + req_tls_ctx_cache, options, default_servers ? NULL : tsigkey, + timeout, udp_timeout, udp_retries, isc_loop_main(loopmgr), + recvsoa, reqinfo, request); + check_result(result, "dns_request_create"); + requests++; +} + +#if HAVE_GSSAPI + +/* + * Get the realm from the users kerberos ticket if possible + */ +static void +get_ticket_realm(isc_mem_t *mctx) { + krb5_context ctx; + krb5_error_code rc; + krb5_ccache ccache; + krb5_principal princ; + char *name; + const char *ticket_realm; + + rc = krb5_init_context(&ctx); + if (rc != 0) { + return; + } + + rc = krb5_cc_default(ctx, &ccache); + if (rc != 0) { + krb5_free_context(ctx); + return; + } + + rc = krb5_cc_get_principal(ctx, ccache, &princ); + if (rc != 0) { + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + rc = krb5_unparse_name(ctx, princ, &name); + if (rc != 0) { + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return; + } + + ticket_realm = strrchr(name, '@'); + if (ticket_realm != NULL) { + realm = isc_mem_strdup(mctx, ticket_realm); + } + + free(name); + krb5_free_principal(ctx, princ); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + if (realm != NULL && debugging) { + fprintf(stderr, "Found realm from ticket: %s\n", realm + 1); + } +} + +static void +failed_gssrequest(void) { + seenerror = true; + + dns_name_free(&tmpzonename, gmctx); + dns_name_free(&restart_primary, gmctx); + dns_name_init(&tmpzonename, NULL); + dns_name_init(&restart_primary, NULL); + + done_update(); +} + +static void +start_gssrequest(dns_name_t *primary) { + dns_gss_ctx_id_t context; + isc_buffer_t buf; + isc_result_t result; + uint32_t val = 0; + dns_message_t *rmsg = NULL; + dns_request_t *request = NULL; + dns_name_t *servname; + dns_fixedname_t fname; + char namestr[DNS_NAME_FORMATSIZE]; + char mykeystr[DNS_NAME_FORMATSIZE]; + char *err_message = NULL; + + debug("start_gssrequest"); + usevc = true; + + if (gssring != NULL) { + dns_tsigkeyring_detach(&gssring); + } + + dns_tsigkeyring_create(gmctx, &gssring); + + dns_name_format(primary, namestr, sizeof(namestr)); + if (kserver == NULL) { + kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t)); + } + + memmove(kserver, &primary_servers[primary_inuse], + sizeof(isc_sockaddr_t)); + + servname = dns_fixedname_initname(&fname); + + if (realm == NULL) { + get_ticket_realm(gmctx); + } + + result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr, + realm ? realm : ""); + RUNTIME_CHECK(result < sizeof(servicename)); + isc_buffer_init(&buf, servicename, strlen(servicename)); + isc_buffer_add(&buf, strlen(servicename)); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fatal("dns_name_fromtext(servname) failed: %s", + isc_result_totext(result)); + } + + keyname = dns_fixedname_initname(&fkname); + + isc_nonce_buf(&val, sizeof(val)); + + result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val, + namestr); + RUNTIME_CHECK(result <= sizeof(mykeystr)); + + isc_buffer_init(&buf, mykeystr, strlen(mykeystr)); + isc_buffer_add(&buf, strlen(mykeystr)); + + result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fatal("dns_name_fromtext(keyname) failed: %s", + isc_result_totext(result)); + } + + /* Windows doesn't recognize name compression in the key name. */ + keyname->attributes.nocompress = true; + + rmsg = NULL; + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, &rmsg); + + /* Build first request. */ + context = GSS_C_NO_CONTEXT; + result = dns_tkey_buildgssquery(rmsg, keyname, servname, 0, &context, + gmctx, &err_message); + if (result == ISC_R_FAILURE) { + fprintf(stderr, "tkey query failed: %s\n", + err_message != NULL ? err_message : "unknown error"); + goto failure; + } + if (result != ISC_R_SUCCESS) { + fatal("dns_tkey_buildgssquery failed: %s", + isc_result_totext(result)); + } + + send_gssrequest(kserver, rmsg, &request, context); + return; + +failure: + if (rmsg != NULL) { + dns_message_detach(&rmsg); + } + if (err_message != NULL) { + isc_mem_free(gmctx, err_message); + } + failed_gssrequest(); +} + +static void +send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg, + dns_request_t **request, gss_ctx_id_t context) { + isc_result_t result; + nsu_gssinfo_t *reqinfo = NULL; + isc_sockaddr_t *srcaddr = NULL; + unsigned int options = DNS_REQUESTOPT_CASE | DNS_REQUESTOPT_TCP; + dns_transport_t *req_transport = NULL; + isc_tlsctx_cache_t *req_tls_ctx_cache = NULL; + + if (!default_servers && use_tls) { + req_transport = transport; + req_tls_ctx_cache = tls_ctx_cache; + } + + debug("send_gssrequest"); + REQUIRE(destaddr != NULL); + + reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t)); + *reqinfo = (nsu_gssinfo_t){ + .msg = msg, + .addr = destaddr, + .context = context, + }; + + if (isc_sockaddr_pf(destaddr) == AF_INET6) { + srcaddr = localaddr6; + } else { + srcaddr = localaddr4; + } + + result = dns_request_create( + requestmgr, msg, srcaddr, destaddr, req_transport, + req_tls_ctx_cache, options, tsigkey, timeout, udp_timeout, + udp_retries, isc_loop_main(loopmgr), recvgss, reqinfo, request); + check_result(result, "dns_request_create"); + if (debugging) { + show_message(stdout, msg, "Outgoing update query:"); + } + requests++; +} + +static void +recvgss(void *arg) { + dns_request_t *request = (dns_request_t *)arg; + nsu_gssinfo_t *reqinfo = dns_request_getarg(request); + isc_result_t result, eresult = dns_request_getresult(request); + dns_message_t *rcvmsg = NULL; + dns_message_t *tsigquery = reqinfo->msg; + dns_gss_ctx_id_t context = reqinfo->context; + isc_sockaddr_t *addr = reqinfo->addr; + isc_buffer_t buf; + dns_name_t *servname = NULL; + dns_fixedname_t fname; + char *err_message = NULL; + + ddebug("recvgss()"); + + requests--; + + if (shuttingdown) { + dns_request_destroy(&request); + dns_message_detach(&tsigquery); + isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); + maybeshutdown(); + return; + } + + if (eresult != ISC_R_SUCCESS) { + ddebug("Destroying request [%p]", request); + dns_request_destroy(&request); + if (!next_primary("recvgss", addr, eresult)) { + dns_message_detach(&tsigquery); + failed_gssrequest(); + } else { + dns_message_renderreset(tsigquery); + memmove(kserver, &primary_servers[primary_inuse], + sizeof(isc_sockaddr_t)); + send_gssrequest(kserver, tsigquery, &request, context); + } + isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); + return; + } + isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); + + ddebug("recvgss creating rcvmsg"); + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, &rcvmsg); + + result = dns_request_getresponse(request, rcvmsg, + DNS_MESSAGEPARSE_PRESERVEORDER); + check_result(result, "dns_request_getresponse"); + + if (debugging) { + show_message(stderr, rcvmsg, + "recvmsg reply from GSS-TSIG query"); + } + + if (rcvmsg->opcode != dns_opcode_query) { + fatal("invalid OPCODE in response to GSS-TSIG query"); + } + + if (rcvmsg->rcode != dns_rcode_noerror && + rcvmsg->rcode != dns_rcode_nxdomain) + { + char rcode[64]; + isc_buffer_t b; + + isc_buffer_init(&b, rcode, sizeof(rcode) - 1); + result = dns_rcode_totext(rcvmsg->rcode, &b); + check_result(result, "dns_rcode_totext"); + rcode[isc_buffer_usedlength(&b)] = 0; + + fatal("response to GSS-TSIG query was unsuccessful (%s)", + rcode); + } + + servname = dns_fixedname_initname(&fname); + isc_buffer_init(&buf, servicename, strlen(servicename)); + isc_buffer_add(&buf, strlen(servicename)); + result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL); + check_result(result, "dns_name_fromtext"); + + result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context, + &tsigkey, gssring, &err_message); + switch (result) { + case DNS_R_CONTINUE: + dns_message_detach(&rcvmsg); + dns_request_destroy(&request); + send_gssrequest(kserver, tsigquery, &request, context); + ddebug("Out of recvgss"); + return; + + case ISC_R_SUCCESS: + /* + * XXXSRA Waaay too much fun here. There's no good + * reason why we need a TSIG here (the people who put + * it into the spec admitted at the time that it was + * not a security issue), and Windows clients don't + * seem to work if named complies with the spec and + * includes the gratuitous TSIG. So we're in the + * bizarre situation of having to choose between + * complying with a useless requirement in the spec + * and interoperating. This is nuts. If we can + * confirm this behavior, we should ask the WG to + * consider removing the requirement for the + * gratuitous TSIG here. For the moment, we ignore + * the TSIG -- this too is a spec violation, but it's + * the least insane thing to do. + */ + + send_update(&tmpzonename, &primary_servers[primary_inuse]); + setzoneclass(dns_rdataclass_none); + break; + + default: + fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result), + err_message != NULL ? err_message : ""); + } + + dns_request_destroy(&request); + dns_message_detach(&tsigquery); + + dns_message_detach(&rcvmsg); + ddebug("Out of recvgss"); +} +#endif /* HAVE_GSSAPI */ + +static void +start_update(void) { + isc_result_t result; + dns_rdataset_t *rdataset = NULL; + dns_name_t *name = NULL; + dns_request_t *request = NULL; + dns_message_t *soaquery = NULL; + dns_name_t *firstname; + dns_section_t section = DNS_SECTION_UPDATE; + + ddebug("start_update()"); + + LOCK(&answer_lock); + if (answer != NULL) { + dns_message_detach(&answer); + } + UNLOCK(&answer_lock); + + /* + * If we have both the zone and the servers we have enough information + * to send the update straight away otherwise we need to discover + * the zone and / or the primary server. + */ + if (userzone != NULL && !default_servers && !usegsstsig) { + primary_from_servers(); + send_update(userzone, &primary_servers[primary_inuse]); + setzoneclass(dns_rdataclass_none); + return; + } + + dns_message_create(gmctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &soaquery); + + if (default_servers) { + soaquery->flags |= DNS_MESSAGEFLAG_RD; + } + + dns_message_gettempname(soaquery, &name); + + dns_message_gettemprdataset(soaquery, &rdataset); + + dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); + + if (userzone != NULL) { + dns_name_clone(userzone, name); + } else { + dns_rdataset_t *tmprdataset; + result = dns_message_firstname(updatemsg, section); + if (result == ISC_R_NOMORE) { + section = DNS_SECTION_PREREQUISITE; + result = dns_message_firstname(updatemsg, section); + } + if (result != ISC_R_SUCCESS) { + dns_message_puttempname(soaquery, &name); + dns_rdataset_disassociate(rdataset); + dns_message_puttemprdataset(soaquery, &rdataset); + dns_message_detach(&soaquery); + done_update(); + return; + } + firstname = NULL; + dns_message_currentname(updatemsg, section, &firstname); + dns_name_clone(firstname, name); + /* + * Looks to see if the first name references a DS record + * and if that name is not the root remove a label as DS + * records live in the parent zone so we need to start our + * search one label up. + */ + tmprdataset = ISC_LIST_HEAD(firstname->list); + if (section == DNS_SECTION_UPDATE && + !dns_name_equal(firstname, dns_rootname) && + tmprdataset->type == dns_rdatatype_ds) + { + unsigned int labels = dns_name_countlabels(name); + dns_name_getlabelsequence(name, 1, labels - 1, name); + } + } + + ISC_LIST_INIT(name->list); + ISC_LIST_APPEND(name->list, rdataset, link); + dns_message_addname(soaquery, name, DNS_SECTION_QUESTION); + + ns_inuse = 0; + sendrequest(&servers[ns_inuse], soaquery, &request); +} + +static void +cleanup(void) { + ddebug("cleanup()"); + + if (tls_ctx_cache != NULL) { + isc_tlsctx_cache_detach(&tls_ctx_cache); + } + + if (transport_list != NULL) { + dns_transport_list_detach(&transport_list); + } + + LOCK(&answer_lock); + if (answer != NULL) { + dns_message_detach(&answer); + } + UNLOCK(&answer_lock); + +#if HAVE_GSSAPI + if (tsigkey != NULL) { + ddebug("detach tsigkey x%p", tsigkey); + dns_tsigkey_detach(&tsigkey); + } + if (gssring != NULL) { + ddebug("Detaching GSS-TSIG keyring"); + dns_tsigkeyring_detach(&gssring); + } +#endif /* ifdef HAVE_GSSAPI */ + + if (sig0key != NULL) { + dst_key_free(&sig0key); + } + +#ifdef HAVE_GSSAPI + if (kserver != NULL) { + isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t)); + kserver = NULL; + } + if (realm != NULL) { + isc_mem_free(gmctx, realm); + realm = NULL; + } + if (dns_name_dynamic(&tmpzonename)) { + dns_name_free(&tmpzonename, gmctx); + } + if (dns_name_dynamic(&restart_primary)) { + dns_name_free(&restart_primary, gmctx); + } +#endif /* ifdef HAVE_GSSAPI */ + + ddebug("Removing log context"); + isc_log_destroy(&glctx); + + ddebug("Destroying memory context"); + if (memdebugging) { + isc_mem_stats(gmctx, stderr); + } + + isc_mutex_destroy(&answer_lock); + + if (is_dst_up) { + ddebug("Destroy DST lib"); + dst_lib_destroy(); + is_dst_up = false; + } + + ddebug("Shutting down managers"); + isc_managers_destroy(&gmctx, &loopmgr, &netmgr); +} + +static void +getinput(void *arg) { + bool more; + + UNUSED(arg); + + if (shuttingdown) { + maybeshutdown(); + return; + } + + reset_system(); + isc_loopmgr_blocking(loopmgr); + more = user_interaction(); + isc_loopmgr_nonblocking(loopmgr); + if (!more) { + isc_loopmgr_shutdown(loopmgr); + return; + } + + done = false; + start_update(); +} + +int +main(int argc, char **argv) { + uint32_t timeoutms; + + style = &dns_master_style_debug; + + input = stdin; + + interactive = isatty(0); + + if (isc_net_probeipv4() == ISC_R_SUCCESS) { + have_ipv4 = true; + } + if (isc_net_probeipv6() == ISC_R_SUCCESS) { + have_ipv6 = true; + } + if (!have_ipv4 && !have_ipv6) { + fatal("could not find either IPv4 or IPv6"); + } + + pre_parse_args(argc, argv); + + isc_managers_create(&gmctx, 1, &loopmgr, &netmgr); + + parse_args(argc, argv); + + /* Set the network manager timeouts in milliseconds. */ + timeoutms = timeout * 1000; + isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms); + + isc_loopmgr_setup(loopmgr, setup_system, NULL); + isc_loopmgr_setup(loopmgr, getinput, NULL); + isc_loopmgr_teardown(loopmgr, shutdown_program, NULL); + isc_loopmgr_run(loopmgr); + + cleanup(); + + if (seenerror) { + return 2; + } + + return 0; +} diff --git a/bin/nsupdate/nsupdate.rst b/bin/nsupdate/nsupdate.rst new file mode 100644 index 0000000..b98d70b --- /dev/null +++ b/bin/nsupdate/nsupdate.rst @@ -0,0 +1,451 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. iscman:: nsupdate +.. program:: nsupdate +.. _man_nsupdate: + +nsupdate - dynamic DNS update utility +------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`nsupdate` [**-d**] [**-D**] [**-i**] [**-L** level] [ [**-g**] | [**-o**] | [**-l**] | [**-y** [hmac:]keyname:secret] | [**-k** keyfile] ] [ [**-S**] [**-K** tlskeyfile] [**-E** tlscertfile] [**-A** tlscafile] [**-H** tlshostname] [-O] ] [**-t** timeout] [**-u** udptimeout] [**-r** udpretries] [**-v**] [**-T**] [**-P**] [**-V**] [ [**-4**] | [**-6**] ] [filename] + +Description +~~~~~~~~~~~ + +:program:`nsupdate` is used to submit Dynamic DNS Update requests, as defined in +:rfc:`2136`, to a name server. This allows resource records to be added or +removed from a zone without manually editing the zone file. A single +update request can contain requests to add or remove more than one +resource record. + +Zones that are under dynamic control via :program:`nsupdate` or a DHCP server +should not be edited by hand. Manual edits could conflict with dynamic +updates and cause data to be lost. + +The resource records that are dynamically added or removed with +:program:`nsupdate` must be in the same zone. Requests are sent to the +zone's primary server, which is identified by the MNAME field of the +zone's SOA record. + +Transaction signatures can be used to authenticate the Dynamic DNS +updates. These use the TSIG resource record type described in :rfc:`2845`, +the SIG(0) record described in :rfc:`2535` and :rfc:`2931`, or GSS-TSIG as +described in :rfc:`3645`. + +TSIG relies on a shared secret that should only be known to :program:`nsupdate` +and the name server. For instance, suitable ``key`` and ``server`` +statements are added to |named_conf| so that the name server +can associate the appropriate secret key and algorithm with the IP +address of the client application that is using TSIG +authentication. :iscman:`ddns-confgen` can generate suitable +configuration fragments. :program:`nsupdate` uses the :option:`-y` or :option:`-k` options +to provide the TSIG shared secret; these options are mutually exclusive. + +SIG(0) uses public key cryptography. To use a SIG(0) key, the public key +must be stored in a KEY record in a zone served by the name server. + +GSS-TSIG uses Kerberos credentials. Standard GSS-TSIG mode is switched +on with the :option:`-g` flag. A non-standards-compliant variant of GSS-TSIG +used by Windows 2000 can be switched on with the :option:`-o` flag. + +Options +~~~~~~~ + +.. option:: -4 + + This option sets use of IPv4 only. + +.. option:: -6 + + This option sets use of IPv6 only. + +.. option:: -A tlscafile + + This option specifies the file of the certificate authorities (CA) certificates + (in PEM format) in order to verify the remote server TLS certificate when + using DNS-over-TLS (DoT), to achieve Strict or Mutual TLS. When used, it will + override the certificates from the global certificates store, which are + otherwise used by default when :option:`-S` is enabled. This option can not + be used in conjuction with :option:`-O`, and it implies :option:`-S`. + +.. option:: -C + + Overrides the default `resolv.conf` file. This is only intended for testing. + +.. option:: -d + + This option sets debug mode, which provides tracing information about the update + requests that are made and the replies received from the name server. + +.. option:: -D + + This option sets extra debug mode. + +.. option:: -E tlscertfile + + This option sets the certificate(s) file for authentication for the + DNS-over-TLS (DoT) transport to the remote server. The certificate + chain file is expected to be in PEM format. This option implies :option:`-S`, + and can only be used with :option:`-K`. + +.. option:: -g + + This option enables standard GSS-TSIG mode. + +.. option:: -H tlshostname + + This option makes :program:`nsupdate` use the provided hostname during remote + server TLS certificate verification. Otherwise, the DNS server name + is used. This option implies :option:`-S`. + +.. option:: -i + + This option forces interactive mode, even when standard input is not a terminal. + +.. option:: -k keyfile + + This option indicates the file containing the TSIG authentication key. Keyfiles may be in + two formats: a single file containing a :iscman:`named.conf`-format ``key`` + statement, which may be generated automatically by :iscman:`ddns-confgen`; + or a pair of files whose names are of the format + ``K{name}.+157.+{random}.key`` and + ``K{name}.+157.+{random}.private``, which can be generated by + :iscman:`dnssec-keygen`. The :option:`-k` option can also be used to specify a SIG(0) + key used to authenticate Dynamic DNS update requests. In this case, + the key specified is not an HMAC-MD5 key. + +.. option:: -K tlskeyfile + + This option sets the key file for authenticated encryption for the + DNS-over-TLS (DoT) transport with the remote server. The private key file is + expected to be in PEM format. This option implies :option:`-S`, and can only + be used with :option:`-E`. + +.. option:: -l + + This option sets local-host only mode, which sets the server address to localhost + (disabling the ``server`` so that the server address cannot be + overridden). Connections to the local server use a TSIG key + found in |session_key|, which is automatically + generated by :iscman:`named` if any local ``primary`` zone has set + ``update-policy`` to ``local``. The location of this key file can be + overridden with the :option:`-k` option. + +.. option:: -L level + + This option sets the logging debug level. If zero, logging is disabled. + +.. option:: -o + + This option is deprecated. Previously, it enabled a + non-standards-compliant variant of GSS-TSIG that was used by Windows + 2000. Since that OS is now long past its end of life, this option is + now treated as a synonym for :option:`-g`. + +.. option:: -O + + This option enables Opportunistic TLS. When used, the remote peer's TLS + certificate will not be verified. This option should be used for debugging + purposes only, and it is not recommended to use it in production. This + option can not be used in conjuction with :option:`-A`, and it implies + :option:`-S`. + +.. option:: -p port + + This option sets the port to use for connections to a name server. The default is + 53. + +.. option:: -P + + This option prints the list of private BIND-specific resource record types whose + format is understood by :program:`nsupdate`. See also the :option:`-T` option. + +.. option:: -r udpretries + + This option sets the number of UDP retries. The default is 3. If zero, only one update + request is made. + +.. option:: -S + + This option indicates whether to use DNS-over-TLS (DoT) when querying + name servers specified by ``server servername port`` syntax in the input + file, and the primary server discovered through a SOA request. When the + :option:`-K` and :option:`-E` options are used, then the specified TLS + client certificate and private key pair are used for authentication + (Mutual TLS). This option implies :option:`-v`. + +.. option:: -t timeout + + This option sets the maximum time an update request can take before it is aborted. The + default is 300 seconds. If zero, the timeout is disabled for TCP mode. For UDP mode, + the option :option:`-u` takes precedence over this option, unless the option :option:`-u` + is set to zero, in which case the interval is computed from the :option:`-t` timeout interval + and the number of UDP retries. For UDP mode, the timeout can not be disabled, and will + be rounded up to 1 second in case if both :option:`-t` and :option:`-u` are set to zero. + +.. option:: -T + + This option prints the list of IANA standard resource record types whose format is + understood by :program:`nsupdate`. :program:`nsupdate` exits after the lists + are printed. The :option:`-T` option can be combined with the :option:`-P` + option. + + Other types can be entered using ``TYPEXXXXX`` where ``XXXXX`` is the + decimal value of the type with no leading zeros. The rdata, if + present, is parsed using the UNKNOWN rdata format, ( + ). + +.. option:: -u udptimeout + + This option sets the UDP retry interval. The default is 3 seconds. If zero, the + interval is computed from the timeout interval and number of UDP + retries. + +.. option:: -v + + This option specifies that TCP should be used even for small update requests. By default, :program:`nsupdate` uses + UDP to send update requests to the name server unless they are too + large to fit in a UDP request, in which case TCP is used. TCP may + be preferable when a batch of update requests is made. + +.. option:: -V + + This option prints the version number and exits. + +.. option:: -y [hmac:]keyname:secret + + This option sets the literal TSIG authentication key. ``keyname`` is the name of the key, + and ``secret`` is the base64 encoded shared secret. ``hmac`` is the + name of the key algorithm; valid choices are ``hmac-md5``, + ``hmac-sha1``, ``hmac-sha224``, ``hmac-sha256``, ``hmac-sha384``, or + ``hmac-sha512``. If ``hmac`` is not specified, the default is + ``hmac-md5``, or if MD5 was disabled, ``hmac-sha256``. + + NOTE: Use of the :option:`-y` option is discouraged because the shared + secret is supplied as a command-line argument in clear text. This may + be visible in the output from ps1 or in a history file maintained by + the user's shell. + +Input Format +~~~~~~~~~~~~ + +:program:`nsupdate` reads input from ``filename`` or standard input. Each +command is supplied on exactly one line of input. Some commands are for +administrative purposes; others are either update instructions or +prerequisite checks on the contents of the zone. These checks set +conditions that some name or set of resource records (RRset) either +exists or is absent from the zone. These conditions must be met if the +entire update request is to succeed. Updates are rejected if the +tests for the prerequisite conditions fail. + +Every update request consists of zero or more prerequisites and zero or +more updates. This allows a suitably authenticated update request to +proceed if some specified resource records are either present or missing from +the zone. A blank input line (or the ``send`` command) causes the +accumulated commands to be sent as one Dynamic DNS update request to the +name server. + +The command formats and their meanings are as follows: + +``server servername port`` + This command sends all dynamic update requests to the name server ``servername``. + When no server statement is provided, :program:`nsupdate` sends updates + to the primary server of the correct zone. The MNAME field of that + zone's SOA record identify the primary server for that zone. + ``port`` is the port number on ``servername`` where the dynamic + update requests are sent. If no port number is specified, the default + DNS port number of 53 is used. + + .. note:: This command has no effect when GSS-TSIG is in use. + +``local address port`` + This command sends all dynamic update requests using the local ``address``. When + no local statement is provided, :program:`nsupdate` sends updates using + an address and port chosen by the system. ``port`` can also + be used to force requests to come from a specific port. If no port number + is specified, the system assigns one. + +``zone zonename`` + This command specifies that all updates are to be made to the zone ``zonename``. + If no ``zone`` statement is provided, :program:`nsupdate` attempts to + determine the correct zone to update based on the rest of the input. + +``class classname`` + This command specifies the default class. If no ``class`` is specified, the default + class is ``IN``. + +``ttl seconds`` + This command specifies the default time-to-live, in seconds, for records to be added. The value + ``none`` clears the default TTL. + +``key hmac:keyname secret`` + This command specifies that all updates are to be TSIG-signed using the + ``keyname``-``secret`` pair. If ``hmac`` is specified, it sets + the signing algorithm in use. The default is ``hmac-md5``; if MD5 + was disabled, the default is ``hmac-sha256``. The ``key`` command overrides any key + specified on the command line via :option:`-y` or :option:`-k`. + +``gsstsig`` + This command uses GSS-TSIG to sign the updates. This is equivalent to specifying + :option:`-g` on the command line. + +``oldgsstsig`` + This command is deprecated and will be removed in a future release. + Previously, it caused ``nsupdate`` to use the Windows 2000 version of + GSS-TSIG to sign updates. It is now treated as a synonym for ``gsstsig``. + +``realm [realm_name]`` + When using GSS-TSIG, this command specifies the use of ``realm_name`` rather than the default realm + in ``krb5.conf``. If no realm is specified, the saved realm is + cleared. + +``check-names [boolean]`` + This command turns on or off check-names processing on records to be added. + Check-names has no effect on prerequisites or records to be deleted. + By default check-names processing is on. If check-names processing + fails, the record is not added to the UPDATE message. + +``check-svbc [boolean]`` + This command turns on or off check-svcb processing on records to be added. + Check-svcb has no effect on prerequisites or records to be deleted. + By default check-svcb processing is on. If check-svcb processing + fails, the record is not added to the UPDATE message. + +``lease time [keytime]`` + Set the EDNS Update Lease (UL) option to value to ``time`` and + optionally also set the key lease time to ``keytime`` in seconds. + If ``time`` is ``none`` the lease times are cleared. + +``prereq nxdomain domain-name`` + This command requires that no resource record of any type exist with the name + ``domain-name``. + +``prereq yxdomain domain-name`` + This command requires that ``domain-name`` exist (as at least one resource + record, of any type). + +``prereq nxrrset domain-name class type`` + This command requires that no resource record exist of the specified ``type``, + ``class``, and ``domain-name``. If ``class`` is omitted, IN (Internet) + is assumed. + +``prereq yxrrset domain-name class type`` + This command requires that a resource record of the specified ``type``, + ``class`` and ``domain-name`` exist. If ``class`` is omitted, IN + (internet) is assumed. + +``prereq yxrrset domain-name class type data`` + With this command, the ``data`` from each set of prerequisites of this form sharing a + common ``type``, ``class``, and ``domain-name`` are combined to form + a set of RRs. This set of RRs must exactly match the set of RRs + existing in the zone at the given ``type``, ``class``, and + ``domain-name``. The ``data`` are written in the standard text + representation of the resource record's RDATA. + +``update delete domain-name ttl class type data`` + This command deletes any resource records named ``domain-name``. If ``type`` and + ``data`` are provided, only matching resource records are removed. + The Internet class is assumed if ``class`` is not supplied. The + ``ttl`` is ignored, and is only allowed for compatibility. + +``update add domain-name ttl class type data`` + This command adds a new resource record with the specified ``ttl``, ``class``, and + ``data``. + +``show`` + This command displays the current message, containing all of the prerequisites and + updates specified since the last send. + +``send`` + This command sends the current message. This is equivalent to entering a blank + line. + +``answer`` + This command displays the answer. + +``debug`` + This command turns on debugging. + +``version`` + This command prints the version number. + +``help`` + This command prints a list of commands. + +Lines beginning with a semicolon (;) are comments and are ignored. + +Examples +~~~~~~~~ + +The examples below show how :program:`nsupdate` can be used to insert and +delete resource records from the ``example.com`` zone. Notice that the +input in each example contains a trailing blank line, so that a group of +commands is sent as one dynamic update request to the primary name +server for ``example.com``. + +:: + + # nsupdate + > update delete oldhost.example.com A + > update add newhost.example.com 86400 A 172.16.1.1 + > send + +Any A records for ``oldhost.example.com`` are deleted, and an A record +for ``newhost.example.com`` with IP address 172.16.1.1 is added. The +newly added record has a TTL of 1 day (86400 seconds). + +:: + + # nsupdate + > prereq nxdomain nickname.example.com + > update add nickname.example.com 86400 CNAME somehost.example.com + > send + +The prerequisite condition tells the name server to verify that there are +no resource records of any type for ``nickname.example.com``. If there +are, the update request fails. If this name does not exist, a CNAME for +it is added. This ensures that when the CNAME is added, it cannot +conflict with the long-standing rule in :rfc:`1034` that a name must not +exist as any other record type if it exists as a CNAME. (The rule has +been updated for DNSSEC in :rfc:`2535` to allow CNAMEs to have RRSIG, +DNSKEY, and NSEC records.) + +Files +~~~~~ + +``/etc/resolv.conf`` + Used to identify the default name server + +|session_key| + Sets the default TSIG key for use in local-only mode + +``K{name}.+157.+{random}.key`` + Base-64 encoding of the HMAC-MD5 key created by :iscman:`dnssec-keygen`. + +``K{name}.+157.+{random}.private`` + Base-64 encoding of the HMAC-MD5 key created by :iscman:`dnssec-keygen`. + +See Also +~~~~~~~~ + +:rfc:`2136`, :rfc:`3007`, :rfc:`2104`, :rfc:`2845`, :rfc:`1034`, :rfc:`2535`, :rfc:`2931`, +:iscman:`named(8) `, :iscman:`dnssec-keygen(8) `, :iscman:`tsig-keygen(8) `. + +Bugs +~~~~ + +The TSIG key is redundantly stored in two separate files. This is a +consequence of :program:`nsupdate` using the DST library for its cryptographic +operations, and may change in future releases. diff --git a/bin/plugins/Makefile.am b/bin/plugins/Makefile.am new file mode 100644 index 0000000..611dd1b --- /dev/null +++ b/bin/plugins/Makefile.am @@ -0,0 +1,15 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) + +pkglib_LTLIBRARIES = filter-aaaa.la +pkglib_LTLIBRARIES += filter-a.la + +filter_aaaa_la_SOURCES = filter-aaaa.c +filter_a_la_SOURCES = filter-a.c +filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic diff --git a/bin/plugins/Makefile.in b/bin/plugins/Makefile.in new file mode 100644 index 0000000..db2a7bf --- /dev/null +++ b/bin/plugins/Makefile.in @@ -0,0 +1,857 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = bin/plugins +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +filter_a_la_LIBADD = +am_filter_a_la_OBJECTS = filter-a.lo +filter_a_la_OBJECTS = $(am_filter_a_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +filter_a_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(filter_a_la_LDFLAGS) $(LDFLAGS) -o $@ +filter_aaaa_la_LIBADD = +am_filter_aaaa_la_OBJECTS = filter-aaaa.lo +filter_aaaa_la_OBJECTS = $(am_filter_aaaa_la_OBJECTS) +filter_aaaa_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(filter_aaaa_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/filter-a.Plo \ + ./$(DEPDIR)/filter-aaaa.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(filter_a_la_SOURCES) $(filter_aaaa_la_SOURCES) +DIST_SOURCES = $(filter_a_la_SOURCES) $(filter_aaaa_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +pkglib_LTLIBRARIES = filter-aaaa.la filter-a.la +filter_aaaa_la_SOURCES = filter-aaaa.c +filter_a_la_SOURCES = filter-a.c +filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/plugins/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/plugins/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +filter-a.la: $(filter_a_la_OBJECTS) $(filter_a_la_DEPENDENCIES) $(EXTRA_filter_a_la_DEPENDENCIES) + $(AM_V_CCLD)$(filter_a_la_LINK) -rpath $(pkglibdir) $(filter_a_la_OBJECTS) $(filter_a_la_LIBADD) $(LIBS) + +filter-aaaa.la: $(filter_aaaa_la_OBJECTS) $(filter_aaaa_la_DEPENDENCIES) $(EXTRA_filter_aaaa_la_DEPENDENCIES) + $(AM_V_CCLD)$(filter_aaaa_la_LINK) -rpath $(pkglibdir) $(filter_aaaa_la_OBJECTS) $(filter_aaaa_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter-a.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter-aaaa.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/filter-a.Plo + -rm -f ./$(DEPDIR)/filter-aaaa.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/filter-a.Plo + -rm -f ./$(DEPDIR)/filter-aaaa.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-pkglibLTLIBRARIES + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am test-am test-local uninstall uninstall-am \ + uninstall-pkglibLTLIBRARIES unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/plugins/filter-a.c b/bin/plugins/filter-a.c new file mode 100644 index 0000000..b3b874f --- /dev/null +++ b/bin/plugins/filter-a.c @@ -0,0 +1,879 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/* aliases for the exported symbols */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) + +/* + * Possible values for the settings of filter-a-on-v6 and + * filter-a-on-v4: "no" is NONE, "yes" is FILTER, "break-dnssec" + * is BREAK_DNSSEC. + */ +typedef enum { NONE = 0, FILTER = 1, BREAK_DNSSEC = 2 } filter_a_t; + +/* + * Persistent data for use by this module. This will be associated + * with client object address in the hash table, and will remain + * accessible until the client object is detached. + */ +typedef struct filter_data { + filter_a_t mode; + uint32_t flags; +} filter_data_t; + +typedef struct filter_instance { + ns_plugin_t *module; + isc_mem_t *mctx; + + /* + * Hash table associating a client object with its persistent data. + */ + isc_ht_t *ht; + isc_mutex_t hlock; + + /* + * Values configured when the module is loaded. + */ + filter_a_t v4_a; + filter_a_t v6_a; + dns_acl_t *a_acl; +} filter_instance_t; + +/* + * Per-client flags set by this module + */ +#define FILTER_A_RECURSING 0x0001 /* Recursing for AAAA */ +#define FILTER_A_FILTERED 0x0002 /* A was removed from answer */ + +/* + * Client attribute tests. + */ +#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) +#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0) + +/* + * Forward declarations of functions referenced in install_hooks(). + */ +static ns_hookresult_t +filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp); + +/*% + * Register the functions to be called at each hook point in 'hooktable', using + * memory context 'mctx' for allocating copies of stack-allocated structures + * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata' + * argument to every callback. + */ +static void +install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx, + filter_instance_t *inst) { + const ns_hook_t filter_init = { + .action = filter_qctx_initialize, + .action_data = inst, + }; + + const ns_hook_t filter_respbegin = { + .action = filter_respond_begin, + .action_data = inst, + }; + + const ns_hook_t filter_respanyfound = { + .action = filter_respond_any_found, + .action_data = inst, + }; + + const ns_hook_t filter_prepresp = { + .action = filter_prep_response_begin, + .action_data = inst, + }; + + const ns_hook_t filter_donesend = { + .action = filter_query_done_send, + .action_data = inst, + }; + + const ns_hook_t filter_destroy = { + .action = filter_qctx_destroy, + .action_data = inst, + }; + + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &filter_init); + ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_BEGIN, &filter_respbegin); + ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_ANY_FOUND, + &filter_respanyfound); + ns_hook_add(hooktable, mctx, NS_QUERY_PREP_RESPONSE_BEGIN, + &filter_prepresp); + ns_hook_add(hooktable, mctx, NS_QUERY_DONE_SEND, &filter_donesend); + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &filter_destroy); +} + +/** +** Support for parsing of parameters and configuration of the module. +**/ + +/* + * Support for parsing of parameters. + */ +static const char *filter_a_enums[] = { "break-dnssec", NULL }; + +static isc_result_t +parse_filter_a(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret); +} + +static void +doc_filter_a(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean); +} + +static cfg_type_t cfg_type_filter_a = { + "filter_a", parse_filter_a, cfg_print_ustring, + doc_filter_a, &cfg_rep_string, filter_a_enums, +}; + +static cfg_clausedef_t param_clauses[] = { + { "filter-a", &cfg_type_bracketed_aml, 0 }, + { "filter-a-on-v6", &cfg_type_filter_a, 0 }, + { "filter-a-on-v4", &cfg_type_filter_a, 0 }, +}; + +static cfg_clausedef_t *param_clausesets[] = { param_clauses, NULL }; + +static cfg_type_t cfg_type_parameters = { "filter-a-params", cfg_parse_mapbody, + cfg_print_mapbody, cfg_doc_mapbody, + &cfg_rep_map, param_clausesets }; + +static isc_result_t +parse_filter_a_on(const cfg_obj_t *param_obj, const char *param_name, + filter_a_t *dstp) { + const cfg_obj_t *obj = NULL; + isc_result_t result; + + result = cfg_map_get(param_obj, param_name, &obj); + if (result != ISC_R_SUCCESS) { + return ISC_R_SUCCESS; + } + + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + *dstp = FILTER; + } else { + *dstp = NONE; + } + } else if (strcasecmp(cfg_obj_asstring(obj), "break-dnssec") == 0) { + *dstp = BREAK_DNSSEC; + } else { + result = ISC_R_UNEXPECTED; + } + + return result; +} + +static isc_result_t +check_syntax(cfg_obj_t *fmap, const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, + void *actx) { + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *aclobj = NULL; + dns_acl_t *acl = NULL; + filter_a_t f4 = NONE, f6 = NONE; + + cfg_map_get(fmap, "filter-a", &aclobj); + if (aclobj == NULL) { + return result; + } + + CHECK(cfg_acl_fromconfig(aclobj, (const cfg_obj_t *)cfg, lctx, + (cfg_aclconfctx_t *)actx, mctx, 0, &acl)); + + CHECK(parse_filter_a_on(fmap, "filter-a-on-v6", &f6)); + CHECK(parse_filter_a_on(fmap, "filter-a-on-v4", &f4)); + + if ((f4 != NONE || f6 != NONE) && dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING, + "\"filter-a\" is 'none;' but " + "either filter-a-on-v6 or filter-a-on-v4 " + "is enabled"); + result = ISC_R_FAILURE; + } else if (f4 == NONE && f6 == NONE && !dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING, + "\"filter-a\" is set but " + "neither filter-a-on-v6 or filter-a-on-v4 " + "is enabled"); + result = ISC_R_FAILURE; + } + +cleanup: + if (acl != NULL) { + dns_acl_detach(&acl); + } + + return result; +} + +static isc_result_t +parse_parameters(filter_instance_t *inst, const char *parameters, + const void *cfg, const char *cfg_file, unsigned long cfg_line, + isc_mem_t *mctx, isc_log_t *lctx, void *actx) { + isc_result_t result = ISC_R_SUCCESS; + cfg_parser_t *parser = NULL; + cfg_obj_t *param_obj = NULL; + const cfg_obj_t *obj = NULL; + isc_buffer_t b; + + CHECK(cfg_parser_create(mctx, lctx, &parser)); + + isc_buffer_constinit(&b, parameters, strlen(parameters)); + isc_buffer_add(&b, strlen(parameters)); + CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + &cfg_type_parameters, 0, ¶m_obj)); + + CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx)); + + CHECK(parse_filter_a_on(param_obj, "filter-a-on-v6", &inst->v6_a)); + CHECK(parse_filter_a_on(param_obj, "filter-a-on-v4", &inst->v4_a)); + + result = cfg_map_get(param_obj, "filter-a", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(cfg_acl_fromconfig(obj, (const cfg_obj_t *)cfg, lctx, + (cfg_aclconfctx_t *)actx, mctx, 0, + &inst->a_acl)); + } else { + CHECK(dns_acl_any(mctx, &inst->a_acl)); + } + +cleanup: + if (param_obj != NULL) { + cfg_obj_destroy(parser, ¶m_obj); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + return result; +} + +/** +** Mandatory plugin API functions: +** +** - plugin_destroy +** - plugin_register +** - plugin_version +** - plugin_check +**/ + +/* + * Called by ns_plugin_register() to initialize the plugin and + * register hook functions into the view hook table. + */ +isc_result_t +plugin_register(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx, ns_hooktable_t *hooktable, void **instp) { + filter_instance_t *inst = NULL; + isc_result_t result = ISC_R_SUCCESS; + + isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_INFO, + "registering 'filter-a' " + "module from %s:%lu, %s parameters", + cfg_file, cfg_line, parameters != NULL ? "with" : "no"); + + inst = isc_mem_get(mctx, sizeof(*inst)); + *inst = (filter_instance_t){ 0 }; + isc_mem_attach(mctx, &inst->mctx); + + if (parameters != NULL) { + CHECK(parse_parameters(inst, parameters, cfg, cfg_file, + cfg_line, mctx, lctx, actx)); + } + + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); + isc_mutex_init(&inst->hlock); + + /* + * Set hook points in the view's hooktable. + */ + install_hooks(hooktable, mctx, inst); + + *instp = inst; + +cleanup: + if (result != ISC_R_SUCCESS) { + plugin_destroy((void **)&inst); + } + + return result; +} + +isc_result_t +plugin_check(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx) { + isc_result_t result = ISC_R_SUCCESS; + cfg_parser_t *parser = NULL; + cfg_obj_t *param_obj = NULL; + isc_buffer_t b; + + CHECK(cfg_parser_create(mctx, lctx, &parser)); + + isc_buffer_constinit(&b, parameters, strlen(parameters)); + isc_buffer_add(&b, strlen(parameters)); + CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + &cfg_type_parameters, 0, ¶m_obj)); + + CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx)); + +cleanup: + if (param_obj != NULL) { + cfg_obj_destroy(parser, ¶m_obj); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + return result; +} + +/* + * Called by ns_plugins_free(); frees memory allocated by + * the module when it was registered. + */ +void +plugin_destroy(void **instp) { + filter_instance_t *inst = (filter_instance_t *)*instp; + + if (inst->ht != NULL) { + isc_ht_destroy(&inst->ht); + isc_mutex_destroy(&inst->hlock); + } + if (inst->a_acl != NULL) { + dns_acl_detach(&inst->a_acl); + } + + isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst)); + *instp = NULL; + + return; +} + +/* + * Returns plugin API version for compatibility checks. + */ +int +plugin_version(void) { + return NS_PLUGIN_VERSION; +} + +/** +** "filter-a" feature implementation begins here. +**/ + +/*% + * Structure describing the filtering to be applied by process_section(). + */ +typedef struct section_filter { + query_ctx_t *qctx; + filter_a_t mode; + dns_section_t section; + const dns_name_t *name; + dns_rdatatype_t type; + bool only_if_aaaa_exists; +} section_filter_t; + +/* + * Check whether this is an IPv4 client. + */ +static bool +is_v4_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) { + return true; + } + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + { + return true; + } + return false; +} + +/* + * Check whether this is an IPv6 client. + */ +static bool +is_v6_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + !IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + { + return true; + } + return false; +} + +static filter_data_t * +client_state_get(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state = NULL; + isc_result_t result; + + LOCK(&inst->hlock); + result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), (void **)&client_state); + UNLOCK(&inst->hlock); + + return result == ISC_R_SUCCESS ? client_state : NULL; +} + +static void +client_state_create(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state; + isc_result_t result; + + client_state = isc_mem_get(inst->mctx, sizeof(*client_state)); + + client_state->mode = NONE; + client_state->flags = 0; + + LOCK(&inst->hlock); + result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), client_state); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +static void +client_state_destroy(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result; + + if (client_state == NULL) { + return; + } + + LOCK(&inst->hlock); + result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client)); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + isc_mem_put(inst->mctx, client_state, sizeof(*client_state)); +} + +/*% + * Mark 'rdataset' and 'sigrdataset' as rendered, gracefully handling NULL + * pointers and non-associated rdatasets. + */ +static void +mark_as_rendered(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { + if (rdataset != NULL && dns_rdataset_isassociated(rdataset)) { + rdataset->attributes |= DNS_RDATASETATTR_RENDERED; + } + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { + sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED; + } +} + +/*% + * Check whether an RRset of given 'type' is present at given 'name'. If + * it is found and either it is not signed or the combination of query + * flags and configured processing 'mode' allows it, mark the RRset and its + * associated signatures as already rendered to prevent them from appearing + * in the response message stored in 'qctx'. If 'only_if_aaaa_exists' is + * true, an RRset of type AAAA must also exist at 'name' in order for the + * above processing to happen. + */ +static bool +process_name(query_ctx_t *qctx, filter_a_t mode, const dns_name_t *name, + dns_rdatatype_t type, bool only_if_aaaa_exists) { + dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; + isc_result_t result; + bool modified = false; + + if (only_if_aaaa_exists) { + CHECK(dns_message_findtype(name, dns_rdatatype_aaaa, 0, NULL)); + } + + (void)dns_message_findtype(name, type, 0, &rdataset); + (void)dns_message_findtype(name, dns_rdatatype_rrsig, type, + &sigrdataset); + + if (rdataset != NULL && + (sigrdataset == NULL || !WANTDNSSEC(qctx->client) || + mode == BREAK_DNSSEC)) + { + /* + * An RRset of given 'type' was found at 'name' and at least + * one of the following is true: + * + * - the RRset is not signed, + * - the client did not set the DO bit in its request, + * - configuration allows us to tamper with signed responses. + * + * This means it is okay to filter out this RRset and its + * signatures, if any, from the response. + */ + mark_as_rendered(rdataset, sigrdataset); + modified = true; + } + +cleanup: + return modified; +} + +/*% + * Apply the requested section filter, i.e. prevent (when possible, as + * determined by process_name()) RRsets of given 'type' from being rendered + * in the given 'section' of the response message stored in 'qctx'. Clear + * the AD bit if the answer and/or authority section was modified. If + * 'name' is NULL, all names in the given 'section' are processed; + * otherwise, only 'name' is. 'only_if_aaaa_exists' is passed through to + * process_name(). + */ +static void +process_section(const section_filter_t *filter) { + query_ctx_t *qctx = filter->qctx; + filter_a_t mode = filter->mode; + dns_section_t section = filter->section; + const dns_name_t *name = filter->name; + dns_rdatatype_t type = filter->type; + bool only_if_aaaa_exists = filter->only_if_aaaa_exists; + + dns_message_t *message = qctx->client->message; + isc_result_t result; + + for (result = dns_message_firstname(message, section); + result == ISC_R_SUCCESS; + result = dns_message_nextname(message, section)) + { + dns_name_t *cur = NULL; + dns_message_currentname(message, section, &cur); + if (name != NULL && !dns_name_equal(name, cur)) { + /* + * We only want to process 'name' and this is not it. + */ + continue; + } + + if (!process_name(qctx, mode, cur, type, only_if_aaaa_exists)) { + /* + * Response was not modified, do not touch the AD bit. + */ + continue; + } + + if (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY) + { + message->flags &= ~DNS_MESSAGEFLAG_AD; + } + } +} + +/* + * Initialize filter state, fetching it from a memory pool and storing it + * in a hash table keyed according to the client object; this enables us to + * retrieve persistent data related to a client query for as long as the + * object persists. + */ +static ns_hookresult_t +filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state; + + *resp = ISC_R_UNSET; + + client_state = client_state_get(qctx, inst); + if (client_state == NULL) { + client_state_create(qctx, inst); + } + + return NS_HOOK_CONTINUE; +} + +/* + * Determine whether this client should have A filtered or not, based on + * the client address family and the settings of filter-a-on-v6 and + * filter-a-on-v4. + */ +static ns_hookresult_t +filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result; + + *resp = ISC_R_UNSET; + + if (client_state == NULL) { + return NS_HOOK_CONTINUE; + } + + if (inst->v4_a != NONE || inst->v6_a != NONE) { + result = ns_client_checkaclsilent(qctx->client, NULL, + inst->a_acl, true); + if (result == ISC_R_SUCCESS && inst->v4_a != NONE && + is_v4_client(qctx->client)) + { + client_state->mode = inst->v4_a; + } else if (result == ISC_R_SUCCESS && inst->v6_a != NONE && + is_v6_client(qctx->client)) + { + client_state->mode = inst->v6_a; + } + } + + return NS_HOOK_CONTINUE; +} + +/* + * Hide A rrsets if there is a matching AAAA. Trigger recursion if + * necessary to find out whether an AAAA exists. + * + * (This version is for processing answers to explicit A queries; ANY + * queries are handled in filter_respond_any_found().) + */ +static ns_hookresult_t +filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result = ISC_R_UNSET; + + *resp = ISC_R_UNSET; + + if (client_state == NULL) { + return NS_HOOK_CONTINUE; + } + + if (client_state->mode != BREAK_DNSSEC && + (client_state->mode != FILTER || + (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL && + dns_rdataset_isassociated(qctx->sigrdataset)))) + { + return NS_HOOK_CONTINUE; + } + + if (qctx->qtype == dns_rdatatype_a) { + dns_rdataset_t *trdataset; + trdataset = ns_client_newrdataset(qctx->client); + result = dns_db_findrdataset( + qctx->db, qctx->node, qctx->version, dns_rdatatype_aaaa, + 0, qctx->client->now, trdataset, NULL); + if (dns_rdataset_isassociated(trdataset)) { + dns_rdataset_disassociate(trdataset); + } + ns_client_putrdataset(qctx->client, &trdataset); + + /* + * We found an A. If we also found an AAAA, then the A + * must not be rendered. + * + * If the AAAA is not in our cache, then any result other than + * DNS_R_DELEGATION or ISC_R_NOTFOUND means there is no AAAAA, + * and so AAAAs are okay. + * + * We assume there is no AAAA if we can't recurse for this + * client. That might be the wrong answer, but what else + * can we do? Besides, the fact that we have the A and + * are using this mechanism in the first place suggests + * that we care more about AAAAs than As, and would have + * cached an AAAA if it existed. + */ + if (result == ISC_R_SUCCESS) { + mark_as_rendered(qctx->rdataset, qctx->sigrdataset); + qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD; + client_state->flags |= FILTER_A_FILTERED; + } else if (!qctx->authoritative && RECURSIONOK(qctx->client) && + (result == DNS_R_DELEGATION || + result == ISC_R_NOTFOUND)) + { + /* + * This is an ugly kludge to recurse + * for the AAAA and discard the result.??? + * + * Continue to add the A now. + * We'll make a note to not render it + * if the recursion for the AAAA succeeds. + */ + result = ns_query_recurse(qctx->client, + dns_rdatatype_aaaa, + qctx->client->query.qname, + NULL, NULL, qctx->resuming); + if (result == ISC_R_SUCCESS) { + client_state->flags |= FILTER_A_RECURSING; + qctx->client->query.attributes |= + NS_QUERYATTR_RECURSING; + } + } + } else if (qctx->qtype == dns_rdatatype_aaaa && + (client_state->flags & FILTER_A_RECURSING) != 0) + { + const section_filter_t filter_answer = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ANSWER, + .name = qctx->fname, + .type = dns_rdatatype_a, + }; + process_section(&filter_answer); + + client_state->flags &= ~FILTER_A_RECURSING; + + result = ns_query_done(qctx); + + *resp = result; + + return NS_HOOK_RETURN; + } + + *resp = result; + return NS_HOOK_CONTINUE; +} + +/* + * When answering an ANY query, remove A if AAAA is present. + */ +static ns_hookresult_t +filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + + *resp = ISC_R_UNSET; + + if (client_state != NULL && client_state->mode != NONE) { + /* + * If we are authoritative, require an AAAA record to be + * present before filtering out A records; otherwise, + * just assume an AAAA record exists even if it was not in the + * cache (and therefore is not in the response message), + * thus proceeding with filtering out A records. + */ + const section_filter_t filter_answer = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ANSWER, + .name = qctx->tname, + .type = dns_rdatatype_a, + .only_if_aaaa_exists = qctx->authoritative, + }; + process_section(&filter_answer); + } + + return NS_HOOK_CONTINUE; +} + +/* + * Hide A rrsets in the additional section if there is a matching AAAA, and + * hide NS in the authority section if A was filtered in the answer + * section. + */ +static ns_hookresult_t +filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + + *resp = ISC_R_UNSET; + + if (client_state != NULL && client_state->mode != NONE) { + const section_filter_t filter_additional = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ADDITIONAL, + .type = dns_rdatatype_a, + .only_if_aaaa_exists = true, + }; + process_section(&filter_additional); + + if ((client_state->flags & FILTER_A_FILTERED) != 0) { + const section_filter_t filter_authority = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_AUTHORITY, + .type = dns_rdatatype_ns, + }; + process_section(&filter_authority); + } + } + + return NS_HOOK_CONTINUE; +} + +/* + * If the client is being detached, then we can delete our persistent data + * from hash table and return it to the memory pool. + */ +static ns_hookresult_t +filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + + *resp = ISC_R_UNSET; + + if (!qctx->detach_client) { + return NS_HOOK_CONTINUE; + } + + client_state_destroy(qctx, inst); + + return NS_HOOK_CONTINUE; +} diff --git a/bin/plugins/filter-a.rst b/bin/plugins/filter-a.rst new file mode 100644 index 0000000..16b3dee --- /dev/null +++ b/bin/plugins/filter-a.rst @@ -0,0 +1,86 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: filter-a +.. _man_filter-a: + +filter-a.so - filter A in DNS responses when AAAA is present +--------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`plugin query` "filter-a.so" [{ parameters }]; + +Description +~~~~~~~~~~~ + +:program:`filter-a.so` is a query plugin module for :iscman:`named`, enabling +:iscman:`named` to omit some IPv4 addresses when responding to clients. + +For example: + +:: + + plugin query "filter-a.so" { + filter-a-on-v6 yes; + filter-a-on-v4 yes; + filter-a { 192.0.2.1; 2001:db8:2::1; }; + }; + +This module is intended to aid transition from IPv4 to IPv6 by +withholding IPv4 addresses from DNS clients which are not connected to +the IPv4 Internet, when the name being looked up has an IPv6 address +available. Use of this module is not recommended unless absolutely +necessary. + +Note: This mechanism can erroneously cause other servers not to give +A records to their clients. If a recursing server with both IPv6 and +IPv4 network connections queries an authoritative server using this +mechanism via IPv6, it is denied A records even if its client is +using IPv4. + +Options +~~~~~~~ + +``filter-a`` + This option specifies a list of client addresses for which A filtering is to + be applied. The default is ``any``. + +``filter-a-on-v6`` + If set to ``yes``, this option indicates that the DNS client is at an IPv6 address, in + ``filter-a``. If the response does not include DNSSEC + signatures, then all A records are deleted from the response. This + filtering applies to all responses, not only authoritative + ones. + + If set to ``break-dnssec``, then A records are deleted even when + DNSSEC is enabled. As suggested by the name, this causes the response + to fail to verify, because the DNSSEC protocol is designed to detect + deletions. + + This mechanism can erroneously cause other servers not to give A + records to their clients. If a recursing server with both IPv6 and IPv4 + network connections queries an authoritative server using this + mechanism via IPv6, it is denied A records even if its client is + using IPv4. + +``filter-a-on-v4`` + This option is identical to ``filter-a-on-v6``, except that it filters A responses + to queries from IPv4 clients instead of IPv6 clients. To filter all + responses, set both options to ``yes``. + +See Also +~~~~~~~~ + +BIND 9 Administrator Reference Manual. diff --git a/bin/plugins/filter-aaaa.c b/bin/plugins/filter-aaaa.c new file mode 100644 index 0000000..32dfc63 --- /dev/null +++ b/bin/plugins/filter-aaaa.c @@ -0,0 +1,882 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/* aliases for the exported symbols */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) + +/* + * Possible values for the settings of filter-aaaa-on-v4 and + * filter-aaaa-on-v6: "no" is NONE, "yes" is FILTER, "break-dnssec" + * is BREAK_DNSSEC. + */ +typedef enum { NONE = 0, FILTER = 1, BREAK_DNSSEC = 2 } filter_aaaa_t; + +/* + * Persistent data for use by this module. This will be associated + * with client object address in the hash table, and will remain + * accessible until the client object is detached. + */ +typedef struct filter_data { + filter_aaaa_t mode; + uint32_t flags; +} filter_data_t; + +typedef struct filter_instance { + ns_plugin_t *module; + isc_mem_t *mctx; + + /* + * Hash table associating a client object with its persistent data. + */ + isc_ht_t *ht; + isc_mutex_t hlock; + + /* + * Values configured when the module is loaded. + */ + filter_aaaa_t v4_aaaa; + filter_aaaa_t v6_aaaa; + dns_acl_t *aaaa_acl; +} filter_instance_t; + +/* + * Per-client flags set by this module + */ +#define FILTER_AAAA_RECURSING 0x0001 /* Recursing for A */ +#define FILTER_AAAA_FILTERED 0x0002 /* AAAA was removed from answer */ + +/* + * Client attribute tests. + */ +#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) +#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0) + +/* + * Forward declarations of functions referenced in install_hooks(). + */ +static ns_hookresult_t +filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp); + +/*% + * Register the functions to be called at each hook point in 'hooktable', using + * memory context 'mctx' for allocating copies of stack-allocated structures + * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata' + * argument to every callback. + */ +static void +install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx, + filter_instance_t *inst) { + const ns_hook_t filter_init = { + .action = filter_qctx_initialize, + .action_data = inst, + }; + + const ns_hook_t filter_respbegin = { + .action = filter_respond_begin, + .action_data = inst, + }; + + const ns_hook_t filter_respanyfound = { + .action = filter_respond_any_found, + .action_data = inst, + }; + + const ns_hook_t filter_prepresp = { + .action = filter_prep_response_begin, + .action_data = inst, + }; + + const ns_hook_t filter_donesend = { + .action = filter_query_done_send, + .action_data = inst, + }; + + const ns_hook_t filter_destroy = { + .action = filter_qctx_destroy, + .action_data = inst, + }; + + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &filter_init); + ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_BEGIN, &filter_respbegin); + ns_hook_add(hooktable, mctx, NS_QUERY_RESPOND_ANY_FOUND, + &filter_respanyfound); + ns_hook_add(hooktable, mctx, NS_QUERY_PREP_RESPONSE_BEGIN, + &filter_prepresp); + ns_hook_add(hooktable, mctx, NS_QUERY_DONE_SEND, &filter_donesend); + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &filter_destroy); +} + +/** +** Support for parsing of parameters and configuration of the module. +**/ + +/* + * Support for parsing of parameters. + */ +static const char *filter_aaaa_enums[] = { "break-dnssec", NULL }; + +static isc_result_t +parse_filter_aaaa(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret); +} + +static void +doc_filter_aaaa(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean); +} + +static cfg_type_t cfg_type_filter_aaaa = { + "filter_aaaa", parse_filter_aaaa, cfg_print_ustring, + doc_filter_aaaa, &cfg_rep_string, filter_aaaa_enums, +}; + +static cfg_clausedef_t param_clauses[] = { + { "filter-aaaa", &cfg_type_bracketed_aml, 0 }, + { "filter-aaaa-on-v4", &cfg_type_filter_aaaa, 0 }, + { "filter-aaaa-on-v6", &cfg_type_filter_aaaa, 0 }, +}; + +static cfg_clausedef_t *param_clausesets[] = { param_clauses, NULL }; + +static cfg_type_t cfg_type_parameters = { + "filter-aaaa-params", cfg_parse_mapbody, cfg_print_mapbody, + cfg_doc_mapbody, &cfg_rep_map, param_clausesets +}; + +static isc_result_t +parse_filter_aaaa_on(const cfg_obj_t *param_obj, const char *param_name, + filter_aaaa_t *dstp) { + const cfg_obj_t *obj = NULL; + isc_result_t result; + + result = cfg_map_get(param_obj, param_name, &obj); + if (result != ISC_R_SUCCESS) { + return ISC_R_SUCCESS; + } + + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + *dstp = FILTER; + } else { + *dstp = NONE; + } + } else if (strcasecmp(cfg_obj_asstring(obj), "break-dnssec") == 0) { + *dstp = BREAK_DNSSEC; + } else { + result = ISC_R_UNEXPECTED; + } + + return result; +} + +static isc_result_t +check_syntax(cfg_obj_t *fmap, const void *cfg, isc_mem_t *mctx, isc_log_t *lctx, + void *actx) { + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *aclobj = NULL; + dns_acl_t *acl = NULL; + filter_aaaa_t f4 = NONE, f6 = NONE; + + cfg_map_get(fmap, "filter-aaaa", &aclobj); + if (aclobj == NULL) { + return result; + } + + CHECK(cfg_acl_fromconfig(aclobj, (const cfg_obj_t *)cfg, lctx, + (cfg_aclconfctx_t *)actx, mctx, 0, &acl)); + + CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v4", &f4)); + CHECK(parse_filter_aaaa_on(fmap, "filter-aaaa-on-v6", &f6)); + + if ((f4 != NONE || f6 != NONE) && dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING, + "\"filter-aaaa\" is 'none;' but " + "either filter-aaaa-on-v4 or filter-aaaa-on-v6 " + "is enabled"); + result = ISC_R_FAILURE; + } else if (f4 == NONE && f6 == NONE && !dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, lctx, ISC_LOG_WARNING, + "\"filter-aaaa\" is set but " + "neither filter-aaaa-on-v4 or filter-aaaa-on-v6 " + "is enabled"); + result = ISC_R_FAILURE; + } + +cleanup: + if (acl != NULL) { + dns_acl_detach(&acl); + } + + return result; +} + +static isc_result_t +parse_parameters(filter_instance_t *inst, const char *parameters, + const void *cfg, const char *cfg_file, unsigned long cfg_line, + isc_mem_t *mctx, isc_log_t *lctx, void *actx) { + isc_result_t result = ISC_R_SUCCESS; + cfg_parser_t *parser = NULL; + cfg_obj_t *param_obj = NULL; + const cfg_obj_t *obj = NULL; + isc_buffer_t b; + + CHECK(cfg_parser_create(mctx, lctx, &parser)); + + isc_buffer_constinit(&b, parameters, strlen(parameters)); + isc_buffer_add(&b, strlen(parameters)); + CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + &cfg_type_parameters, 0, ¶m_obj)); + + CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx)); + + CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4", + &inst->v4_aaaa)); + CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v6", + &inst->v6_aaaa)); + + result = cfg_map_get(param_obj, "filter-aaaa", &obj); + if (result == ISC_R_SUCCESS) { + CHECK(cfg_acl_fromconfig(obj, (const cfg_obj_t *)cfg, lctx, + (cfg_aclconfctx_t *)actx, mctx, 0, + &inst->aaaa_acl)); + } else { + CHECK(dns_acl_any(mctx, &inst->aaaa_acl)); + } + +cleanup: + if (param_obj != NULL) { + cfg_obj_destroy(parser, ¶m_obj); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + return result; +} + +/** +** Mandatory plugin API functions: +** +** - plugin_destroy +** - plugin_register +** - plugin_version +** - plugin_check +**/ + +/* + * Called by ns_plugin_register() to initialize the plugin and + * register hook functions into the view hook table. + */ +isc_result_t +plugin_register(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx, ns_hooktable_t *hooktable, void **instp) { + filter_instance_t *inst = NULL; + isc_result_t result = ISC_R_SUCCESS; + + isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_INFO, + "registering 'filter-aaaa' " + "module from %s:%lu, %s parameters", + cfg_file, cfg_line, parameters != NULL ? "with" : "no"); + + inst = isc_mem_get(mctx, sizeof(*inst)); + *inst = (filter_instance_t){ 0 }; + + isc_mem_attach(mctx, &inst->mctx); + + if (parameters != NULL) { + CHECK(parse_parameters(inst, parameters, cfg, cfg_file, + cfg_line, mctx, lctx, actx)); + } + + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); + isc_mutex_init(&inst->hlock); + + /* + * Set hook points in the view's hooktable. + */ + install_hooks(hooktable, mctx, inst); + + *instp = inst; + +cleanup: + if (result != ISC_R_SUCCESS) { + plugin_destroy((void **)&inst); + } + + return result; +} + +isc_result_t +plugin_check(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx) { + isc_result_t result = ISC_R_SUCCESS; + cfg_parser_t *parser = NULL; + cfg_obj_t *param_obj = NULL; + isc_buffer_t b; + + CHECK(cfg_parser_create(mctx, lctx, &parser)); + + isc_buffer_constinit(&b, parameters, strlen(parameters)); + isc_buffer_add(&b, strlen(parameters)); + CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + &cfg_type_parameters, 0, ¶m_obj)); + + CHECK(check_syntax(param_obj, cfg, mctx, lctx, actx)); + +cleanup: + if (param_obj != NULL) { + cfg_obj_destroy(parser, ¶m_obj); + } + if (parser != NULL) { + cfg_parser_destroy(&parser); + } + return result; +} + +/* + * Called by ns_plugins_free(); frees memory allocated by + * the module when it was registered. + */ +void +plugin_destroy(void **instp) { + filter_instance_t *inst = (filter_instance_t *)*instp; + + if (inst->ht != NULL) { + isc_ht_destroy(&inst->ht); + isc_mutex_destroy(&inst->hlock); + } + if (inst->aaaa_acl != NULL) { + dns_acl_detach(&inst->aaaa_acl); + } + + isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst)); + *instp = NULL; + + return; +} + +/* + * Returns plugin API version for compatibility checks. + */ +int +plugin_version(void) { + return NS_PLUGIN_VERSION; +} + +/** +** "filter-aaaa" feature implementation begins here. +**/ + +/*% + * Structure describing the filtering to be applied by process_section(). + */ +typedef struct section_filter { + query_ctx_t *qctx; + filter_aaaa_t mode; + dns_section_t section; + const dns_name_t *name; + dns_rdatatype_t type; + bool only_if_a_exists; +} section_filter_t; + +/* + * Check whether this is an IPv4 client. + */ +static bool +is_v4_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) { + return true; + } + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + { + return true; + } + return false; +} + +/* + * Check whether this is an IPv6 client. + */ +static bool +is_v6_client(ns_client_t *client) { + if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 && + !IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr)) + { + return true; + } + return false; +} + +static filter_data_t * +client_state_get(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state = NULL; + isc_result_t result; + + LOCK(&inst->hlock); + result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), (void **)&client_state); + UNLOCK(&inst->hlock); + + return result == ISC_R_SUCCESS ? client_state : NULL; +} + +static void +client_state_create(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state; + isc_result_t result; + + client_state = isc_mem_get(inst->mctx, sizeof(*client_state)); + + client_state->mode = NONE; + client_state->flags = 0; + + LOCK(&inst->hlock); + result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), client_state); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +static void +client_state_destroy(const query_ctx_t *qctx, filter_instance_t *inst) { + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result; + + if (client_state == NULL) { + return; + } + + LOCK(&inst->hlock); + result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client)); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + isc_mem_put(inst->mctx, client_state, sizeof(*client_state)); +} + +/*% + * Mark 'rdataset' and 'sigrdataset' as rendered, gracefully handling NULL + * pointers and non-associated rdatasets. + */ +static void +mark_as_rendered(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { + if (rdataset != NULL && dns_rdataset_isassociated(rdataset)) { + rdataset->attributes |= DNS_RDATASETATTR_RENDERED; + } + if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { + sigrdataset->attributes |= DNS_RDATASETATTR_RENDERED; + } +} + +/*% + * Check whether an RRset of given 'type' is present at given 'name'. If + * it is found and either it is not signed or the combination of query + * flags and configured processing 'mode' allows it, mark the RRset and its + * associated signatures as already rendered to prevent them from appearing + * in the response message stored in 'qctx'. If 'only_if_a_exists' is + * true, an RRset of type A must also exist at 'name' in order for the + * above processing to happen. + */ +static bool +process_name(query_ctx_t *qctx, filter_aaaa_t mode, const dns_name_t *name, + dns_rdatatype_t type, bool only_if_a_exists) { + dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; + isc_result_t result; + bool modified = false; + + if (only_if_a_exists) { + CHECK(dns_message_findtype(name, dns_rdatatype_a, 0, NULL)); + } + + (void)dns_message_findtype(name, type, 0, &rdataset); + (void)dns_message_findtype(name, dns_rdatatype_rrsig, type, + &sigrdataset); + + if (rdataset != NULL && + (sigrdataset == NULL || !WANTDNSSEC(qctx->client) || + mode == BREAK_DNSSEC)) + { + /* + * An RRset of given 'type' was found at 'name' and at least + * one of the following is true: + * + * - the RRset is not signed, + * - the client did not set the DO bit in its request, + * - configuration allows us to tamper with signed responses. + * + * This means it is okay to filter out this RRset and its + * signatures, if any, from the response. + */ + mark_as_rendered(rdataset, sigrdataset); + modified = true; + } + +cleanup: + return modified; +} + +/*% + * Apply the requested section filter, i.e. prevent (when possible, as + * determined by process_name()) RRsets of given 'type' from being rendered + * in the given 'section' of the response message stored in 'qctx'. Clear + * the AD bit if the answer and/or authority section was modified. If + * 'name' is NULL, all names in the given 'section' are processed; + * otherwise, only 'name' is. 'only_if_a_exists' is passed through to + * process_name(). + */ +static void +process_section(const section_filter_t *filter) { + query_ctx_t *qctx = filter->qctx; + filter_aaaa_t mode = filter->mode; + dns_section_t section = filter->section; + const dns_name_t *name = filter->name; + dns_rdatatype_t type = filter->type; + bool only_if_a_exists = filter->only_if_a_exists; + + dns_message_t *message = qctx->client->message; + isc_result_t result; + + for (result = dns_message_firstname(message, section); + result == ISC_R_SUCCESS; + result = dns_message_nextname(message, section)) + { + dns_name_t *cur = NULL; + dns_message_currentname(message, section, &cur); + if (name != NULL && !dns_name_equal(name, cur)) { + /* + * We only want to process 'name' and this is not it. + */ + continue; + } + + if (!process_name(qctx, mode, cur, type, only_if_a_exists)) { + /* + * Response was not modified, do not touch the AD bit. + */ + continue; + } + + if (section == DNS_SECTION_ANSWER || + section == DNS_SECTION_AUTHORITY) + { + message->flags &= ~DNS_MESSAGEFLAG_AD; + } + } +} + +/* + * Initialize filter state, fetching it from a memory pool and storing it + * in a hash table keyed according to the client object; this enables us to + * retrieve persistent data related to a client query for as long as the + * object persists. + */ +static ns_hookresult_t +filter_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state; + + *resp = ISC_R_UNSET; + + client_state = client_state_get(qctx, inst); + if (client_state == NULL) { + client_state_create(qctx, inst); + } + + return NS_HOOK_CONTINUE; +} + +/* + * Determine whether this client should have AAAA filtered or not, based on + * the client address family and the settings of filter-aaaa-on-v4 and + * filter-aaaa-on-v6. + */ +static ns_hookresult_t +filter_prep_response_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result; + + *resp = ISC_R_UNSET; + + if (client_state == NULL) { + return NS_HOOK_CONTINUE; + } + + if (inst->v4_aaaa != NONE || inst->v6_aaaa != NONE) { + result = ns_client_checkaclsilent(qctx->client, NULL, + inst->aaaa_acl, true); + if (result == ISC_R_SUCCESS && inst->v4_aaaa != NONE && + is_v4_client(qctx->client)) + { + client_state->mode = inst->v4_aaaa; + } else if (result == ISC_R_SUCCESS && inst->v6_aaaa != NONE && + is_v6_client(qctx->client)) + { + client_state->mode = inst->v6_aaaa; + } + } + + return NS_HOOK_CONTINUE; +} + +/* + * Hide AAAA rrsets if there is a matching A. Trigger recursion if + * necessary to find out whether an A exists. + * + * (This version is for processing answers to explicit AAAA queries; ANY + * queries are handled in filter_respond_any_found().) + */ +static ns_hookresult_t +filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + isc_result_t result = ISC_R_UNSET; + + *resp = ISC_R_UNSET; + + if (client_state == NULL) { + return NS_HOOK_CONTINUE; + } + + if (client_state->mode != BREAK_DNSSEC && + (client_state->mode != FILTER || + (WANTDNSSEC(qctx->client) && qctx->sigrdataset != NULL && + dns_rdataset_isassociated(qctx->sigrdataset)))) + { + return NS_HOOK_CONTINUE; + } + + if (qctx->qtype == dns_rdatatype_aaaa) { + dns_rdataset_t *trdataset; + trdataset = ns_client_newrdataset(qctx->client); + result = dns_db_findrdataset( + qctx->db, qctx->node, qctx->version, dns_rdatatype_a, 0, + qctx->client->now, trdataset, NULL); + if (dns_rdataset_isassociated(trdataset)) { + dns_rdataset_disassociate(trdataset); + } + ns_client_putrdataset(qctx->client, &trdataset); + + /* + * We found an AAAA. If we also found an A, then the AAAA + * must not be rendered. + * + * If the A is not in our cache, then any result other than + * DNS_R_DELEGATION or ISC_R_NOTFOUND means there is no A, + * and so AAAAs are okay. + * + * We assume there is no A if we can't recurse for this + * client. That might be the wrong answer, but what else + * can we do? Besides, the fact that we have the AAAA and + * are using this mechanism in the first place suggests + * that we care more about As than AAAAs, and would have + * cached an A if it existed. + */ + if (result == ISC_R_SUCCESS) { + mark_as_rendered(qctx->rdataset, qctx->sigrdataset); + qctx->client->message->flags &= ~DNS_MESSAGEFLAG_AD; + client_state->flags |= FILTER_AAAA_FILTERED; + } else if (!qctx->authoritative && RECURSIONOK(qctx->client) && + (result == DNS_R_DELEGATION || + result == ISC_R_NOTFOUND)) + { + /* + * This is an ugly kludge to recurse + * for the A and discard the result. + * + * Continue to add the AAAA now. + * We'll make a note to not render it + * if the recursion for the A succeeds. + */ + result = ns_query_recurse(qctx->client, dns_rdatatype_a, + qctx->client->query.qname, + NULL, NULL, qctx->resuming); + if (result == ISC_R_SUCCESS) { + client_state->flags |= FILTER_AAAA_RECURSING; + qctx->client->query.attributes |= + NS_QUERYATTR_RECURSING; + } + } + } else if (qctx->qtype == dns_rdatatype_a && + (client_state->flags & FILTER_AAAA_RECURSING) != 0) + { + const section_filter_t filter_answer = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ANSWER, + .name = qctx->fname, + .type = dns_rdatatype_aaaa, + }; + process_section(&filter_answer); + + client_state->flags &= ~FILTER_AAAA_RECURSING; + + result = ns_query_done(qctx); + + *resp = result; + + return NS_HOOK_RETURN; + } + + *resp = result; + return NS_HOOK_CONTINUE; +} + +/* + * When answering an ANY query, remove AAAA if A is present. + */ +static ns_hookresult_t +filter_respond_any_found(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + + *resp = ISC_R_UNSET; + + if (client_state != NULL && client_state->mode != NONE) { + /* + * If we are authoritative, require an A record to be + * present before filtering out AAAA records; otherwise, + * just assume an A record exists even if it was not in the + * cache (and therefore is not in the response message), + * thus proceeding with filtering out AAAA records. + */ + const section_filter_t filter_answer = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ANSWER, + .name = qctx->tname, + .type = dns_rdatatype_aaaa, + .only_if_a_exists = qctx->authoritative, + }; + process_section(&filter_answer); + } + + return NS_HOOK_CONTINUE; +} + +/* + * Hide AAAA rrsets in the additional section if there is a matching A, and + * hide NS in the authority section if AAAA was filtered in the answer + * section. + */ +static ns_hookresult_t +filter_query_done_send(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + filter_data_t *client_state = client_state_get(qctx, inst); + + *resp = ISC_R_UNSET; + + if (client_state != NULL && client_state->mode != NONE) { + const section_filter_t filter_additional = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_ADDITIONAL, + .type = dns_rdatatype_aaaa, + .only_if_a_exists = true, + }; + process_section(&filter_additional); + + if ((client_state->flags & FILTER_AAAA_FILTERED) != 0) { + const section_filter_t filter_authority = { + .qctx = qctx, + .mode = client_state->mode, + .section = DNS_SECTION_AUTHORITY, + .type = dns_rdatatype_ns, + }; + process_section(&filter_authority); + } + } + + return NS_HOOK_CONTINUE; +} + +/* + * If the client is being detached, then we can delete our persistent data + * from hash table and return it to the memory pool. + */ +static ns_hookresult_t +filter_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + filter_instance_t *inst = (filter_instance_t *)cbdata; + + *resp = ISC_R_UNSET; + + if (!qctx->detach_client) { + return NS_HOOK_CONTINUE; + } + + client_state_destroy(qctx, inst); + + return NS_HOOK_CONTINUE; +} diff --git a/bin/plugins/filter-aaaa.rst b/bin/plugins/filter-aaaa.rst new file mode 100644 index 0000000..89904da --- /dev/null +++ b/bin/plugins/filter-aaaa.rst @@ -0,0 +1,90 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: filter-aaaa +.. _man_filter-aaaa: + +filter-aaaa.so - filter AAAA in DNS responses when A is present +--------------------------------------------------------------- + +Synopsis +~~~~~~~~ + +:program:`plugin query` "filter-aaaa.so" [{ parameters }]; + +Description +~~~~~~~~~~~ + +:program:`filter-aaaa.so` is a query plugin module for :iscman:`named`, enabling +:iscman:`named` to omit some IPv6 addresses when responding to clients. + +Until BIND 9.12, this feature was implemented natively in :iscman:`named` and +enabled with the ``filter-aaaa`` ACL and the ``filter-aaaa-on-v4`` and +``filter-aaaa-on-v6`` options. These options are no longer available in +:iscman:`named.conf` but can be passed as parameters to the +``filter-aaaa.so`` plugin, for example: + +:: + + plugin query "filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa-on-v6 yes; + filter-aaaa { 192.0.2.1; 2001:db8:2::1; }; + }; + +This module is intended to aid transition from IPv4 to IPv6 by +withholding IPv6 addresses from DNS clients which are not connected to +the IPv6 Internet, when the name being looked up has an IPv4 address +available. Use of this module is not recommended unless absolutely +necessary. + +Note: This mechanism can erroneously cause other servers not to give +AAAA records to their clients. If a recursing server with both IPv6 and +IPv4 network connections queries an authoritative server using this +mechanism via IPv4, it is denied AAAA records even if its client is +using IPv6. + +Options +~~~~~~~ + +``filter-aaaa`` + This option specifies a list of client addresses for which AAAA filtering is to + be applied. The default is ``any``. + +``filter-aaaa-on-v4`` + If set to ``yes``, this option indicates that the DNS client is at an IPv4 address, in + ``filter-aaaa``. If the response does not include DNSSEC + signatures, then all AAAA records are deleted from the response. This + filtering applies to all responses, not only authoritative + ones. + + If set to ``break-dnssec``, then AAAA records are deleted even when + DNSSEC is enabled. As suggested by the name, this causes the response + to fail to verify, because the DNSSEC protocol is designed to detect + deletions. + + This mechanism can erroneously cause other servers not to give AAAA + records to their clients. If a recursing server with both IPv6 and IPv4 + network connections queries an authoritative server using this + mechanism via IPv4, it is denied AAAA records even if its client is + using IPv6. + +``filter-aaaa-on-v6`` + This option is identical to ``filter-aaaa-on-v4``, except that it filters AAAA responses + to queries from IPv6 clients instead of IPv4 clients. To filter all + responses, set both options to ``yes``. + +See Also +~~~~~~~~ + +BIND 9 Administrator Reference Manual. diff --git a/bin/rndc/Makefile.am b/bin/rndc/Makefile.am new file mode 100644 index 0000000..f8f0ac9 --- /dev/null +++ b/bin/rndc/Makefile.am @@ -0,0 +1,24 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) \ + $(LIBISCCC_CFLAGS) + +AM_CPPFLAGS += \ + -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" + +sbin_PROGRAMS = rndc + +rndc_SOURCES = \ + rndc.c \ + util.c \ + util.h + +rndc_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCC_LIBS) \ + $(LIBISCCFG_LIBS) diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in new file mode 100644 index 0000000..d492c18 --- /dev/null +++ b/bin/rndc/Makefile.in @@ -0,0 +1,845 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +sbin_PROGRAMS = rndc$(EXEEXT) +subdir = bin/rndc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" +PROGRAMS = $(sbin_PROGRAMS) +am_rndc_OBJECTS = rndc.$(OBJEXT) util.$(OBJEXT) +rndc_OBJECTS = $(am_rndc_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +rndc_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) \ + $(LIBISCCC_LIBS) $(LIBISCCFG_LIBS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/rndc.Po ./$(DEPDIR)/util.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(rndc_SOURCES) +DIST_SOURCES = $(rndc_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) $(LIBISCCC_CFLAGS) \ + -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +rndc_SOURCES = \ + rndc.c \ + util.c \ + util.h + +rndc_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) \ + $(LIBISCCC_LIBS) \ + $(LIBISCCFG_LIBS) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/rndc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/rndc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +rndc$(EXEEXT): $(rndc_OBJECTS) $(rndc_DEPENDENCIES) $(EXTRA_rndc_DEPENDENCIES) + @rm -f rndc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rndc_OBJECTS) $(rndc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndc.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/rndc.Po + -rm -f ./$(DEPDIR)/util.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/rndc.Po + -rm -f ./$(DEPDIR)/util.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: uninstall-sbinPROGRAMS + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir doc-am doc-local dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am uninstall-sbinPROGRAMS unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c new file mode 100644 index 0000000..376d6d2 --- /dev/null +++ b/bin/rndc/rndc.c @@ -0,0 +1,1040 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "util.h" + +#define SERVERADDRS 10 +#define RNDC_TIMEOUT 60 * 1000 + +const char *progname = NULL; +bool verbose; + +static isc_nm_t *netmgr = NULL; +static isc_loopmgr_t *loopmgr = NULL; + +static const char *admin_conffile = NULL; +static const char *admin_keyfile = NULL; +static const char *version = PACKAGE_VERSION; +static const char *servername = NULL; +static isc_sockaddr_t serveraddrs[SERVERADDRS]; +static isc_sockaddr_t local4, local6; +static bool local4set = false, local6set = false; +static int nserveraddrs; +static int currentaddr = 0; +static unsigned int remoteport = 0; +static isc_buffer_t *databuf = NULL; +static isccc_ccmsg_t rndc_ccmsg; +static uint32_t algorithm; +static isccc_region_t secret; +static bool failed = false; +static bool c_flag = false; +static isc_mem_t *rndc_mctx = NULL; +static char *command = NULL; +static char *args = NULL; +static char program[256]; +static uint32_t serial; +static bool quiet = false; +static bool showresult = false; +static int32_t timeout = RNDC_TIMEOUT; + +static void +rndc_startconnect(isc_sockaddr_t *addr); + +noreturn static void +usage(int status); + +static void +usage(int status) { + fprintf(stderr, "\ +Usage: %s [-b address] [-c config] [-s server] [-p port]\n\ + [-k key-file ] [-y key] [-r] [-V] [-4 | -6] command\n\ +\n\ +command is one of the following:\n\ +\n\ + addzone zone [class [view]] { zone-options }\n\ + Add zone to given view. Requires allow-new-zones option.\n\ + delzone [-clean] zone [class [view]]\n\ + Removes zone from given view.\n\ + dnssec -checkds [-key id [-alg algorithm]] [-when time] (published|withdrawn) zone [class [view]]\n\ + Mark the DS record for the KSK of the given zone as seen\n\ + in the parent. If the zone has multiple KSKs, select a\n\ + specific key by providing the keytag with -key id and\n\ + optionally the key's algorithm with -alg algorithm.\n\ + Requires the zone to have a dnssec-policy.\n\ + dnssec -rollover -key id [-alg algorithm] [-when time] zone [class [view]]\n\ + Rollover key with id of the given zone. Requires the zone\n\ + to have a dnssec-policy.\n\ + dnssec -status zone [class [view]]\n\ + Show the DNSSEC signing state for the specified zone.\n\ + Requires the zone to have a dnssec-policy.\n\ + dnstap -reopen\n\ + Close, truncate and re-open the DNSTAP output file.\n\ + dnstap -roll [count]\n\ + Close, rename and re-open the DNSTAP output file(s).\n\ + dumpdb [-all|-cache|-zones|-adb|-bad|-expired|-fail] [view ...]\n\ + Dump cache(s) to the dump file (named_dump.db).\n\ + fetchlimit [view]\n\ + Show servers and domains currently rate-limited to fetch limits.\n\ + flush Flushes all of the server's caches.\n\ + flush [view] Flushes the server's cache for a view.\n\ + flushname name [view]\n\ + Flush the given name from the server's cache(s)\n\ + flushtree name [view]\n\ + Flush all names under the given name from the server's cache(s)\n\ + freeze Suspend updates to all dynamic zones.\n\ + freeze zone [class [view]]\n\ + Suspend updates to a dynamic zone.\n\ + halt Stop the server without saving pending updates.\n\ + halt -p Stop the server without saving pending updates reporting\n\ + process id.\n\ + skr -import file zone [class [view]]\n\ + Import a SKR file for the specified zone, for offline KSK\n\ + signing.\n\ + loadkeys zone [class [view]]\n\ + Update keys without signing immediately.\n\ + managed-keys refresh [class [view]]\n\ + Check trust anchor for RFC 5011 key changes\n\ + managed-keys status [class [view]]\n\ + Display RFC 5011 managed keys information\n\ + managed-keys sync [class [view]]\n\ + Write RFC 5011 managed keys to disk\n\ + memprof [ on | off | dump ]\n\ + Enable / disable memory profiling or dump the profile.\n\ + Requires named to built with jemalloc and run with the relevant\n\ + MALLOC_CONF environment variables.\n\ + modzone zone [class [view]] { zone-options }\n\ + Modify a zone's configuration.\n\ + Requires allow-new-zones option.\n\ + notify zone [class [view]]\n\ + Resend NOTIFY messages for the zone.\n\ + notrace Set debugging level to 0.\n\ + nta -dump\n\ + List all negative trust anchors.\n\ + nta [-lifetime duration] [-force] domain [view]\n\ + Set a negative trust anchor, disabling DNSSEC validation\n\ + for the given domain.\n\ + Using -lifetime specifies the duration of the NTA, up\n\ + to one week.\n\ + Using -force prevents the NTA from expiring before its\n\ + full lifetime, even if the domain can validate sooner.\n\ + nta -remove domain [view]\n\ + Remove a negative trust anchor, re-enabling validation\n\ + for the given domain.\n\ + querylog [ on | off ]\n\ + Enable / disable query logging.\n\ + reconfig Reload configuration file and new zones only.\n\ + recursing Dump the queries that are currently recursing (named.recursing)\n\ + refresh zone [class [view]]\n\ + Schedule immediate maintenance for a zone.\n\ + reload Reload configuration file and zones.\n\ + reload zone [class [view]]\n\ + Reload a single zone.\n\ + reset-stats \n\ + Reset the requested statistics counter(s).\n\ + responselog [ on | off ]\n\ + Enable / disable response logging.\n\ + retransfer zone [class [view]]\n\ + Retransfer a single zone without checking serial number.\n\ + scan Scan available network interfaces for changes.\n\ + secroots [view ...]\n\ + Write security roots to the secroots file.\n\ + serve-stale [ on | off | reset | status ] [class [view]]\n\ + Control whether stale answers are returned\n\ + showzone zone [class [view]]\n\ + Print a zone's configuration.\n\ + sign zone [class [view]]\n\ + Update zone keys, and sign as needed.\n\ + signing -clear all zone [class [view]]\n\ + Remove the private records for all keys that have\n\ + finished signing the given zone.\n\ + signing -clear / zone [class [view]]\n\ + Remove the private record that indicating the given key\n\ + has finished signing the given zone.\n\ + signing -list zone [class [view]]\n\ + List the private records showing the state of DNSSEC\n\ + signing in the given zone.\n\ + signing -nsec3param hash flags iterations salt zone [class [view]]\n\ + Add NSEC3 chain to zone if already signed.\n\ + Prime zone with NSEC3 chain if not yet signed.\n\ + signing -nsec3param none zone [class [view]]\n\ + Remove NSEC3 chains from zone.\n\ + signing -serial zone [class [view]]\n\ + Set the zones's serial to .\n\ + stats Write server statistics to the statistics file.\n\ + status Display status of the server.\n\ + stop Save pending updates to master files and stop the server.\n\ + stop -p Save pending updates to master files and stop the server\n\ + reporting process id.\n\ + sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\ + remove their journal files.\n\ + sync [-clean] zone [class [view]]\n\ + Dump a single zone's changes to disk, and optionally\n\ + remove its journal file.\n\ + tcp-timeouts Display the tcp-*-timeout option values\n\ + tcp-timeouts initial idle keepalive advertised\n\ + Update the tcp-*-timeout option values\n\ + thaw Enable updates to all dynamic zones and reload them.\n\ + thaw zone [class [view]]\n\ + Enable updates to a frozen dynamic zone and reload it.\n\ + trace Increment debugging level by one.\n\ + trace level Change the debugging level.\n\ + validation [ on | off | status ] [view]\n\ + Enable / disable DNSSEC validation.\n\ + zonestatus zone [class [view]]\n\ + Display the current status of a zone.\n\ +\n\ +Version: %s\n", + progname, version); + + exit(status); +} + +#define CMDLINE_FLAGS "46b:c:hk:Mmp:qrs:t:Vy:" + +static void +preparse_args(int argc, char **argv) { + bool ipv4only = false, ipv6only = false; + int ch; + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + default: + break; + } + } + + isc_commandline_reset = true; + isc_commandline_index = 1; +} + +static void +get_addresses(const char *host, in_port_t port) { + isc_result_t result; + int found = 0, count; + + REQUIRE(host != NULL); + + count = SERVERADDRS - nserveraddrs; + result = isc_getaddresses(host, port, &serveraddrs[nserveraddrs], count, + &found); + nserveraddrs += found; + + if (result != ISC_R_SUCCESS) { + fatal("couldn't get address for '%s': %s", host, + isc_result_totext(result)); + } + INSIST(nserveraddrs > 0); +} + +static void +rndc_senddone(isc_nmhandle_t *handle ISC_ATTR_UNUSED, isc_result_t result, + void *arg ISC_ATTR_UNUSED) { + if (result != ISC_R_SUCCESS) { + fatal("send failed: %s", isc_result_totext(result)); + } +} + +static void +rndc_recvdone(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg; + isccc_sexpr_t *response = NULL; + isccc_sexpr_t *data = NULL; + isccc_region_t source; + char *errormsg = NULL; + char *textmsg = NULL; + + REQUIRE(handle != NULL); + REQUIRE(ccmsg != NULL); + + if (result == ISC_R_EOF) { + fatal("connection to remote host closed.\n" + "* This may indicate that the\n" + "* remote server is using an older\n" + "* version of the command protocol,\n" + "* this host is not authorized to connect,\n" + "* the clocks are not synchronized,\n" + "* the key signing algorithm is incorrect,\n" + "* or the key is invalid."); + } else if (result != ISC_R_SUCCESS) { + fatal("recv failed: %s", isc_result_totext(result)); + } + + isccc_ccmsg_toregion(ccmsg, &source); + + DO("parse message", + isccc_cc_fromwire(&source, &response, algorithm, &secret)); + + data = isccc_alist_lookup(response, "_data"); + if (!isccc_alist_alistp(data)) { + fatal("bad or missing data section in response"); + } + result = isccc_cc_lookupstring(data, "err", &errormsg); + if (result == ISC_R_SUCCESS) { + failed = true; + fprintf(stderr, "%s: '%s' failed: %s\n", progname, command, + errormsg); + } else if (result != ISC_R_NOTFOUND) { + fprintf(stderr, "%s: parsing response failed: %s\n", progname, + isc_result_totext(result)); + } + + result = isccc_cc_lookupstring(data, "text", &textmsg); + if (result == ISC_R_SUCCESS) { + if ((!quiet || failed) && strlen(textmsg) != 0U) { + fprintf(failed ? stderr : stdout, "%s\n", textmsg); + } + } else if (result != ISC_R_NOTFOUND) { + fprintf(stderr, "%s: parsing response failed: %s\n", progname, + isc_result_totext(result)); + } + + if (showresult) { + isc_result_t eresult; + + result = isccc_cc_lookupuint32(data, "result", &eresult); + if (result == ISC_R_SUCCESS) { + printf("%s %u\n", isc_result_toid(eresult), eresult); + } else { + printf("NONE -1\n"); + } + } + + isccc_sexpr_free(&response); + + isccc_ccmsg_disconnect(ccmsg); + isc_loopmgr_shutdown(loopmgr); +} + +static void +rndc_recvnonce(isc_nmhandle_t *handle ISC_ATTR_UNUSED, isc_result_t result, + void *arg) { + isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg; + isccc_sexpr_t *response = NULL; + isccc_sexpr_t *_ctrl = NULL; + isccc_region_t source; + uint32_t nonce; + isccc_sexpr_t *request = NULL; + isccc_time_t now = isc_stdtime_now(); + isc_region_t r; + isccc_sexpr_t *data = NULL; + isc_buffer_t b; + + REQUIRE(ccmsg != NULL); + + if (result == ISC_R_EOF) { + fatal("connection to remote host closed.\n" + "* This may indicate that the\n" + "* remote server is using an older\n" + "* version of the command protocol,\n" + "* this host is not authorized to connect,\n" + "* the clocks are not synchronized,\n" + "* the key signing algorithm is incorrect\n" + "* or the key is invalid."); + } else if (result != ISC_R_SUCCESS) { + fatal("recv failed: %s", isc_result_totext(result)); + } + + isccc_ccmsg_toregion(ccmsg, &source); + + DO("parse message", + isccc_cc_fromwire(&source, &response, algorithm, &secret)); + + _ctrl = isccc_alist_lookup(response, "_ctrl"); + if (!isccc_alist_alistp(_ctrl)) { + fatal("bad or missing ctrl section in response"); + } + nonce = 0; + if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS) { + nonce = 0; + } + + DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, + now, now + 60, &request)); + data = isccc_alist_lookup(request, "_data"); + if (data == NULL) { + fatal("_data section missing"); + } + if (isccc_cc_definestring(data, "type", args) == NULL) { + fatal("out of memory"); + } + if (nonce != 0) { + _ctrl = isccc_alist_lookup(request, "_ctrl"); + if (_ctrl == NULL) { + fatal("_ctrl section missing"); + } + if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL) { + fatal("out of memory"); + } + } + + isc_buffer_clear(databuf); + /* Skip the length field (4 bytes) */ + isc_buffer_add(databuf, 4); + + DO("render message", + isccc_cc_towire(request, &databuf, algorithm, &secret)); + + isc_buffer_init(&b, databuf->base, 4); + isc_buffer_putuint32(&b, databuf->used - 4); + + r.base = databuf->base; + r.length = databuf->used; + + isccc_ccmsg_readmessage(ccmsg, rndc_recvdone, ccmsg); + isccc_ccmsg_sendmessage(ccmsg, &r, rndc_senddone, NULL); + + isccc_sexpr_free(&response); + isccc_sexpr_free(&request); + return; +} + +static void +rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) { + isccc_ccmsg_t *ccmsg = (isccc_ccmsg_t *)arg; + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isccc_sexpr_t *request = NULL; + isccc_sexpr_t *data = NULL; + isccc_time_t now = isc_stdtime_now(); + isc_region_t r; + isc_buffer_t b; + + REQUIRE(ccmsg != NULL); + + if (result != ISC_R_SUCCESS) { + isc_sockaddr_format(&serveraddrs[currentaddr], socktext, + sizeof(socktext)); + if (++currentaddr < nserveraddrs) { + notify("connection failed: %s: %s", socktext, + isc_result_totext(result)); + rndc_startconnect(&serveraddrs[currentaddr]); + return; + } + + fatal("connect failed: %s: %s", socktext, + isc_result_totext(result)); + } + + DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, + now, now + 60, &request)); + data = isccc_alist_lookup(request, "_data"); + if (data == NULL) { + fatal("_data section missing"); + } + if (isccc_cc_definestring(data, "type", "null") == NULL) { + fatal("out of memory"); + } + + isc_buffer_clear(databuf); + /* Skip the length field (4 bytes) */ + isc_buffer_add(databuf, 4); + + DO("render message", + isccc_cc_towire(request, &databuf, algorithm, &secret)); + + isc_buffer_init(&b, databuf->base, 4); + isc_buffer_putuint32(&b, databuf->used - 4); + + r.base = databuf->base; + r.length = databuf->used; + + /* isccc_ccmsg_init() attaches to the handle */ + isccc_ccmsg_init(rndc_mctx, handle, ccmsg); + isccc_ccmsg_setmaxsize(ccmsg, 1024 * 1024); + + isccc_ccmsg_readmessage(ccmsg, rndc_recvnonce, ccmsg); + isccc_ccmsg_sendmessage(ccmsg, &r, rndc_senddone, NULL); + + isccc_sexpr_free(&request); +} + +static void +rndc_startconnect(isc_sockaddr_t *addr) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t *local = NULL; + + isc_sockaddr_format(addr, socktext, sizeof(socktext)); + + notify("using server %s (%s)", servername, socktext); + + switch (isc_sockaddr_pf(addr)) { + case AF_INET: + local = &local4; + break; + case AF_INET6: + local = &local6; + break; + default: + UNREACHABLE(); + } + + isc_nm_tcpconnect(netmgr, local, addr, rndc_connected, &rndc_ccmsg, + timeout); +} + +static void +rndc_start(void *arg) { + UNUSED(arg); + + currentaddr = 0; + rndc_startconnect(&serveraddrs[currentaddr]); +} + +static void +parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, + cfg_parser_t **pctxp, cfg_obj_t **configp) { + isc_result_t result; + const char *conffile = admin_conffile; + const cfg_obj_t *addresses = NULL; + const cfg_obj_t *defkey = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *servers = NULL; + const cfg_obj_t *server = NULL; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *defport = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *address = NULL; + const cfg_listelt_t *elt; + const char *secretstr; + const char *algorithmstr; + static char secretarray[1024]; + const cfg_type_t *conftype = &cfg_type_rndcconf; + bool key_only = false; + const cfg_listelt_t *element; + + if (!isc_file_exists(conffile)) { + conffile = admin_keyfile; + conftype = &cfg_type_rndckey; + + if (c_flag) { + fatal("%s does not exist", admin_conffile); + } + + if (!isc_file_exists(conffile)) { + fatal("neither %s nor %s was found", admin_conffile, + admin_keyfile); + } + key_only = true; + } else if (!c_flag && isc_file_exists(admin_keyfile)) { + fprintf(stderr, + "WARNING: key file (%s) exists, but using " + "default configuration file (%s)\n", + admin_keyfile, admin_conffile); + } + + DO("create parser", cfg_parser_create(mctx, log, pctxp)); + + /* + * The parser will output its own errors, so DO() is not used. + */ + result = cfg_parse_file(*pctxp, conffile, conftype, &config); + if (result != ISC_R_SUCCESS) { + fatal("could not load rndc configuration"); + } + + if (!key_only) { + (void)cfg_map_get(config, "options", &options); + } + + if (key_only && servername == NULL) { + servername = "127.0.0.1"; + } else if (servername == NULL && options != NULL) { + const cfg_obj_t *defserverobj = NULL; + (void)cfg_map_get(options, "default-server", &defserverobj); + if (defserverobj != NULL) { + servername = cfg_obj_asstring(defserverobj); + } + } + + if (servername == NULL) { + fatal("no server specified and no default"); + } + + if (!key_only) { + (void)cfg_map_get(config, "server", &servers); + if (servers != NULL) { + for (elt = cfg_list_first(servers); elt != NULL; + elt = cfg_list_next(elt)) + { + const char *name = NULL; + server = cfg_listelt_value(elt); + name = cfg_obj_asstring( + cfg_map_getname(server)); + if (strcasecmp(name, servername) == 0) { + break; + } + server = NULL; + } + } + } + + /* + * Look for the name of the key to use. + */ + if (keyname != NULL) { + /* Was set on command line, do nothing. */ + } else if (server != NULL) { + DO("get key for server", cfg_map_get(server, "key", &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (options != NULL) { + DO("get default key", + cfg_map_get(options, "default-key", &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (!key_only) { + fatal("no key for server and no default"); + } + + /* + * Get the key's definition. + */ + if (key_only) { + DO("get key", cfg_map_get(config, "key", &key)); + } else { + DO("get config key list", cfg_map_get(config, "key", &keys)); + for (elt = cfg_list_first(keys); elt != NULL; + elt = cfg_list_next(elt)) + { + const char *name = NULL; + + key = cfg_listelt_value(elt); + name = cfg_obj_asstring(cfg_map_getname(key)); + if (strcasecmp(name, keyname) == 0) { + break; + } + } + if (elt == NULL) { + fatal("no key definition for name %s", keyname); + } + } + (void)cfg_map_get(key, "secret", &secretobj); + (void)cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) { + fatal("key must have algorithm and secret"); + } + + secretstr = cfg_obj_asstring(secretobj); + algorithmstr = cfg_obj_asstring(algorithmobj); + + if (strcasecmp(algorithmstr, "hmac-md5") == 0) { + algorithm = ISCCC_ALG_HMACMD5; + } else if (strcasecmp(algorithmstr, "hmac-sha1") == 0) { + algorithm = ISCCC_ALG_HMACSHA1; + } else if (strcasecmp(algorithmstr, "hmac-sha224") == 0) { + algorithm = ISCCC_ALG_HMACSHA224; + } else if (strcasecmp(algorithmstr, "hmac-sha256") == 0) { + algorithm = ISCCC_ALG_HMACSHA256; + } else if (strcasecmp(algorithmstr, "hmac-sha384") == 0) { + algorithm = ISCCC_ALG_HMACSHA384; + } else if (strcasecmp(algorithmstr, "hmac-sha512") == 0) { + algorithm = ISCCC_ALG_HMACSHA512; + } else { + fatal("unsupported algorithm: %s", algorithmstr); + } + + secret.rstart = (unsigned char *)secretarray; + secret.rend = (unsigned char *)secretarray + sizeof(secretarray); + DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); + secret.rend = secret.rstart; + secret.rstart = (unsigned char *)secretarray; + + /* + * Find the port to connect to. + */ + if (remoteport != 0) { + /* Was set on command line, do nothing. */ + } else { + if (server != NULL) { + (void)cfg_map_get(server, "port", &defport); + } + if (defport == NULL && options != NULL) { + (void)cfg_map_get(options, "default-port", &defport); + } + } + if (defport != NULL) { + remoteport = cfg_obj_asuint32(defport); + if (remoteport > 65535 || remoteport == 0) { + fatal("port %u out of range", remoteport); + } + } else if (remoteport == 0) { + remoteport = NS_CONTROL_PORT; + } + + if (server != NULL) { + result = cfg_map_get(server, "addresses", &addresses); + } else { + result = ISC_R_NOTFOUND; + } + if (result == ISC_R_SUCCESS) { + for (element = cfg_list_first(addresses); element != NULL; + element = cfg_list_next(element)) + { + isc_sockaddr_t sa; + + address = cfg_listelt_value(element); + if (!cfg_obj_issockaddr(address)) { + unsigned int myport; + const char *name; + const cfg_obj_t *obj; + + obj = cfg_tuple_get(address, "name"); + name = cfg_obj_asstring(obj); + obj = cfg_tuple_get(address, "port"); + if (cfg_obj_isuint32(obj)) { + myport = cfg_obj_asuint32(obj); + if (myport > UINT16_MAX || myport == 0) + { + fatal("port %u out of range", + myport); + } + } else { + myport = remoteport; + } + if (nserveraddrs < SERVERADDRS) { + get_addresses(name, (in_port_t)myport); + } else { + fprintf(stderr, + "too many address: " + "%s: dropped\n", + name); + } + continue; + } + sa = *cfg_obj_assockaddr(address); + if (isc_sockaddr_getport(&sa) == 0) { + isc_sockaddr_setport(&sa, remoteport); + } + if (nserveraddrs < SERVERADDRS) { + serveraddrs[nserveraddrs++] = sa; + } else { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(&sa, socktext, + sizeof(socktext)); + fprintf(stderr, + "too many address: %s: dropped\n", + socktext); + } + } + } + + if (!local4set && server != NULL) { + address = NULL; + cfg_map_get(server, "source-address", &address); + if (address != NULL) { + local4 = *cfg_obj_assockaddr(address); + local4set = true; + } + } + if (!local4set && options != NULL) { + address = NULL; + cfg_map_get(options, "default-source-address", &address); + if (address != NULL) { + local4 = *cfg_obj_assockaddr(address); + local4set = true; + } + } + + if (!local6set && server != NULL) { + address = NULL; + cfg_map_get(server, "source-address-v6", &address); + if (address != NULL) { + local6 = *cfg_obj_assockaddr(address); + local6set = true; + } + } + if (!local6set && options != NULL) { + address = NULL; + cfg_map_get(options, "default-source-address-v6", &address); + if (address != NULL) { + local6 = *cfg_obj_assockaddr(address); + local6set = true; + } + } + + *configp = config; +} + +int +main(int argc, char **argv) { + isc_result_t result = ISC_R_SUCCESS; + bool show_final_mem = false; + isc_log_t *log = NULL; + isc_logconfig_t *logconfig = NULL; + isc_logdestination_t logdest; + cfg_parser_t *pctx = NULL; + cfg_obj_t *config = NULL; + const char *keyname = NULL; + struct in_addr in; + struct in6_addr in6; + char *p = NULL; + size_t argslen; + int ch; + int i; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) { + memmove(program, "rndc", 5); + } + progname = program; + + admin_conffile = RNDC_CONFFILE; + admin_keyfile = RNDC_KEYFILE; + + isc_sockaddr_any(&local4); + isc_sockaddr_any6(&local6); + + isc_commandline_errprint = false; + + preparse_args(argc, argv); + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '4': + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + fatal("can't find IPv4 networking"); + } + isc_net_disableipv6(); + break; + case '6': + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + fatal("can't find IPv6 networking"); + } + isc_net_disableipv4(); + break; + case 'b': + if (inet_pton(AF_INET, isc_commandline_argument, &in) == + 1) + { + isc_sockaddr_fromin(&local4, &in, 0); + local4set = true; + } else if (inet_pton(AF_INET6, isc_commandline_argument, + &in6) == 1) + { + isc_sockaddr_fromin6(&local6, &in6, 0); + local6set = true; + } + break; + + case 'c': + admin_conffile = isc_commandline_argument; + c_flag = true; + break; + + case 'k': + admin_keyfile = isc_commandline_argument; + break; + + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + + case 'm': + show_final_mem = true; + break; + + case 'p': + remoteport = atoi(isc_commandline_argument); + if (remoteport > 65535 || remoteport == 0) { + fatal("port '%s' out of range", + isc_commandline_argument); + } + break; + + case 'q': + quiet = true; + break; + + case 'r': + showresult = true; + break; + + case 's': + servername = isc_commandline_argument; + break; + + case 't': + timeout = strtol(isc_commandline_argument, &p, 10); + if (*p != '\0' || timeout < 0 || timeout > 86400) { + fatal("invalid timeout '%s'", + isc_commandline_argument); + } + timeout *= 1000; + break; + + case 'V': + verbose = true; + break; + + case 'y': + keyname = isc_commandline_argument; + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(1); + } + FALLTHROUGH; + case 'h': + usage(0); + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(EXIT_FAILURE); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argv[0] == NULL) { + usage(1); + } else { + command = argv[0]; + if (strcmp(command, "restart") == 0) { + fatal("'%s' is not implemented", command); + } + notify("%s", command); + } + + serial = isc_random32(); + + isc_managers_create(&rndc_mctx, 1, &loopmgr, &netmgr); + isc_loopmgr_setup(loopmgr, rndc_start, NULL); + + isc_nm_settimeouts(netmgr, timeout, timeout, timeout, 0); + + isc_log_create(rndc_mctx, &log, &logconfig); + isc_log_setcontext(log); + isc_log_settag(logconfig, progname); + logdest.file.stream = stderr; + logdest.file.name = NULL; + logdest.file.versions = ISC_LOG_ROLLNEVER; + logdest.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_INFO, &logdest, + ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL); + DO("enabling log channel", + isc_log_usechannel(logconfig, "stderr", NULL, NULL)); + + parse_config(rndc_mctx, log, keyname, &pctx, &config); + + isc_buffer_allocate(rndc_mctx, &databuf, 2048); + + /* + * Convert argc/argv into a space-delimited command string + * similar to what the user might enter in interactive mode + * (if that were implemented). + */ + argslen = 0; + for (i = 0; i < argc; i++) { + argslen += strlen(argv[i]) + 1; + } + + args = isc_mem_get(rndc_mctx, argslen); + + p = args; + for (i = 0; i < argc; i++) { + size_t len = strlen(argv[i]); + memmove(p, argv[i], len); + p += len; + *p++ = ' '; + } + + p--; + *p++ = '\0'; + INSIST(p == args + argslen); + + if (nserveraddrs == 0 && servername != NULL) { + get_addresses(servername, (in_port_t)remoteport); + } + + isc_loopmgr_run(loopmgr); + + isccc_ccmsg_invalidate(&rndc_ccmsg); + + isc_log_destroy(&log); + isc_log_setcontext(NULL); + + cfg_obj_destroy(pctx, &config); + cfg_parser_destroy(&pctx); + + isc_mem_put(rndc_mctx, args, argslen); + + isc_buffer_free(&databuf); + + if (show_final_mem) { + isc_mem_stats(rndc_mctx, stderr); + } + + isc_managers_destroy(&rndc_mctx, &loopmgr, &netmgr); + + if (failed) { + return 1; + } + + return 0; +} diff --git a/bin/rndc/rndc.conf.rst b/bin/rndc/rndc.conf.rst new file mode 100644 index 0000000..20e6bc9 --- /dev/null +++ b/bin/rndc/rndc.conf.rst @@ -0,0 +1,158 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: rndc.conf +.. program:: rndc.conf +.. _man_rndc.conf: + +rndc.conf - rndc configuration file +----------------------------------- + +Synopsis +~~~~~~~~ + +:program:`rndc.conf` + +Description +~~~~~~~~~~~ + +:program:`rndc.conf` is the configuration file for :iscman:`rndc`, the BIND 9 name +server control utility. This file has a similar structure and syntax to +:iscman:`named.conf`. Statements are enclosed in braces and terminated with a +semi-colon. Clauses in the statements are also semi-colon terminated. +The usual comment styles are supported: + +C style: /\* \*/ + +C++ style: // to end of line + +Unix style: # to end of line + +:program:`rndc.conf` is much simpler than :iscman:`named.conf`. The file uses three +statements: an options statement, a server statement, and a key +statement. + +The ``options`` statement contains five clauses. The ``default-server`` +clause is followed by the name or address of a name server. This host +is used when no name server is given as an argument to :iscman:`rndc`. +The ``default-key`` clause is followed by the name of a key, which is +identified by a ``key`` statement. If no ``keyid`` is provided on the +rndc command line, and no ``key`` clause is found in a matching +``server`` statement, this default key is used to authenticate the +server's commands and responses. The ``default-port`` clause is followed +by the port to connect to on the remote name server. If no ``port`` +option is provided on the rndc command line, and no ``port`` clause is +found in a matching ``server`` statement, this default port is used +to connect. The ``default-source-address`` and +``default-source-address-v6`` clauses can be used to set the IPv4 +and IPv6 source addresses respectively. + +After the ``server`` keyword, the server statement includes a string +which is the hostname or address for a name server. The statement has +three possible clauses: ``key``, ``port``, and ``addresses``. The key +name must match the name of a key statement in the file. The port number +specifies the port to connect to. If an ``addresses`` clause is supplied, +these addresses are used instead of the server name. Each address +can take an optional port. If an ``source-address`` or +``source-address-v6`` is supplied, it is used to specify the +IPv4 and IPv6 source address, respectively. + +The ``key`` statement begins with an identifying string, the name of the +key. The statement has two clauses. ``algorithm`` identifies the +authentication algorithm for :iscman:`rndc` to use; currently only HMAC-MD5 +(for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), +HMAC-SHA384, and HMAC-SHA512 are supported. This is followed by a secret +clause which contains the base-64 encoding of the algorithm's +authentication key. The base-64 string is enclosed in double quotes. + +There are two common ways to generate the base-64 string for the secret. +The BIND 9 program :iscman:`rndc-confgen` can be used to generate a random +key, or the ``mmencode`` program, also known as ``mimencode``, can be +used to generate a base-64 string from known input. ``mmencode`` does +not ship with BIND 9 but is available on many systems. See the Example +section for sample command lines for each. + +Example +~~~~~~~ + +:: + + options { + default-server localhost; + default-key samplekey; + }; + +:: + + server localhost { + key samplekey; + }; + +:: + + server testserver { + key testkey; + addresses { localhost port 5353; }; + }; + +:: + + key samplekey { + algorithm hmac-sha256; + secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz"; + }; + +:: + + key testkey { + algorithm hmac-sha256; + secret "R3HI8P6BKw9ZwXwN3VZKuQ=="; + }; + + +In the above example, :iscman:`rndc` by default uses the server at +localhost (127.0.0.1) and the key called "samplekey". Commands to the +localhost server use the "samplekey" key, which must also be defined +in the server's configuration file with the same name and secret. The +key statement indicates that "samplekey" uses the HMAC-SHA256 algorithm +and its secret clause contains the base-64 encoding of the HMAC-SHA256 +secret enclosed in double quotes. + +If :option:`rndc -s testserver ` is used, then :iscman:`rndc` connects to the server +on localhost port 5353 using the key "testkey". + +To generate a random secret with :iscman:`rndc-confgen`: + +:iscman:`rndc-confgen` + +A complete :program:`rndc.conf` file, including the randomly generated key, +is written to the standard output. Commented-out ``key`` and +``controls`` statements for :iscman:`named.conf` are also printed. + +To generate a base-64 secret with ``mmencode``: + +``echo "known plaintext for a secret" | mmencode`` + +Name Server Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The name server must be configured to accept rndc connections and to +recognize the key specified in the :program:`rndc.conf` file, using the +controls statement in :iscman:`named.conf`. See the sections on the +``controls`` statement in the BIND 9 Administrator Reference Manual for +details. + +See Also +~~~~~~~~ + +:iscman:`rndc(8) `, :iscman:`rndc-confgen(8) `, :manpage:`mmencode(1)`, BIND 9 Administrator Reference Manual. diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst new file mode 100644 index 0000000..0cb54dc --- /dev/null +++ b/bin/rndc/rndc.rst @@ -0,0 +1,706 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. 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 https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. iscman:: rndc +.. program:: rndc +.. _man_rndc: + +rndc - name server control utility +---------------------------------- + +Synopsis +~~~~~~~~ + +:program:`rndc` [**-b** source-address] [**-c** config-file] [**-k** key-file] [**-s** server] [**-p** port] [**-q**] [**-r**] [**-V**] [**-y** server_key] [[**-4**] | [**-6**]] {command} + +Description +~~~~~~~~~~~ + +:program:`rndc` controls the operation of a name server. If :program:`rndc` is +invoked with no command line options or arguments, it prints a short +summary of the supported commands and the available options and their +arguments. + +:program:`rndc` communicates with the name server over a TCP connection, +sending commands authenticated with digital signatures. In the current +versions of :program:`rndc` and :iscman:`named`, the only supported authentication +algorithms are HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, +HMAC-SHA256 (default), HMAC-SHA384, and HMAC-SHA512. They use a shared +secret on each end of the connection, which provides TSIG-style +authentication for the command request and the name server's response. +All commands sent over the channel must be signed by a server_key known to +the server. + +:program:`rndc` reads a configuration file to determine how to contact the name +server and decide what algorithm and key it should use. + +Options +~~~~~~~ + +.. option:: -4 + + This option indicates use of IPv4 only. + +.. option:: -6 + + This option indicates use of IPv6 only. + +.. option:: -b source-address + + This option indicates ``source-address`` as the source address for the connection to the + server. Multiple instances are permitted, to allow setting of both the + IPv4 and IPv6 source addresses. + +.. option:: -c config-file + + This option indicates ``config-file`` as the configuration file instead of the default, + |rndc_conf|. + +.. option:: -k key-file + + This option indicates ``key-file`` as the key file instead of the default, + |rndc_key|. The key in |rndc_key| is used to + authenticate commands sent to the server if the config-file does not + exist. + +.. option:: -s server + + ``server`` is the name or address of the server which matches a server + statement in the configuration file for :program:`rndc`. If no server is + supplied on the command line, the host named by the default-server + clause in the options statement of the :program:`rndc` configuration file + is used. + +.. option:: -p port + + This option instructs BIND 9 to send commands to TCP port ``port`` instead of its default control + channel port, 953. + +.. option:: -q + + This option sets quiet mode, where message text returned by the server is not printed + unless there is an error. + +.. option:: -r + + This option instructs :program:`rndc` to print the result code returned by :iscman:`named` + after executing the requested command (e.g., ISC_R_SUCCESS, + ISC_R_FAILURE, etc.). + +.. option:: -t timeout + + This option sets the idle timeout period for :program:`rndc` to + ``timeout`` seconds. The default is 60 seconds, and the maximum settable + value is 86400 seconds (1 day). If set to 0, there is no timeout. + +.. option:: -V + + This option enables verbose logging. + +.. option:: -y server_key + + This option indicates use of the key ``server_key`` from the configuration file. For control message validation to succeed, ``server_key`` must be known + by :iscman:`named` with the same algorithm and secret string. If no ``server_key`` is specified, + :program:`rndc` first looks for a key clause in the server statement of + the server being used, or if no server statement is present for that + host, then in the default-key clause of the options statement. Note that + the configuration file contains shared secrets which are used to send + authenticated control commands to name servers, and should therefore + not have general read or write access. + +Commands +~~~~~~~~ + +A list of commands supported by :program:`rndc` can be seen by running :program:`rndc` +without arguments. + +Currently supported commands are: + +.. option:: addzone zone [class [view]] configuration + + This command adds a zone while the server is running. This command requires the + ``allow-new-zones`` option to be set to ``yes``. The configuration + string specified on the command line is the zone configuration text + that would ordinarily be placed in :iscman:`named.conf`. + + The configuration is saved in a file called ``viewname.nzf`` (or, if + :iscman:`named` is compiled with liblmdb, an LMDB database file called + ``viewname.nzd``). ``viewname`` is the name of the view, unless the view + name contains characters that are incompatible with use as a file + name, in which case a cryptographic hash of the view name is used + instead. When :iscman:`named` is restarted, the file is loaded into + the view configuration so that zones that were added can persist + after a restart. + + This sample ``addzone`` command adds the zone ``example.com`` to + the default view: + + ``rndc addzone example.com '{ type primary; file "example.com.db"; };'`` + + (Note the brackets around and semi-colon after the zone configuration + text.) + + See also :option:`rndc delzone` and :option:`rndc modzone`. + +.. option:: delzone [-clean] zone [class [view]] + + This command deletes a zone while the server is running. + + If the ``-clean`` argument is specified, the zone's master file (and + journal file, if any) are deleted along with the zone. Without + the ``-clean`` option, zone files must be deleted manually. (If the + zone is of type ``secondary`` or ``stub``, the files needing to be removed + are reported in the output of the ``rndc delzone`` command.) + + If the zone was originally added via ``rndc addzone``, then it is + removed permanently. However, if it was originally configured in + :iscman:`named.conf`, then that original configuration remains in place; + when the server is restarted or reconfigured, the zone is + recreated. To remove it permanently, it must also be removed from + :iscman:`named.conf`. + + See also :option:`rndc addzone` and :option:`rndc modzone`. + +.. option:: dnssec (-status | -rollover -key id [-alg algorithm] [-when time] | -checkds [-key id [-alg algorithm]] [-when time] published | withdrawn)) zone [class [view]] + + This command allows you to interact with the "dnssec-policy" of a given + zone. + + ``rndc dnssec -status`` show the DNSSEC signing state for the specified + zone. + + ``rndc dnssec -rollover`` allows you to schedule key rollover for a + specific key (overriding the original key lifetime). + + ``rndc dnssec -checkds`` informs :iscman:`named` that the DS for + a specified zone's key-signing key has been confirmed to be published + in, or withdrawn from, the parent zone. This is required in order to + complete a KSK rollover. The ``-key id`` and ``-alg algorithm`` arguments + can be used to specify a particular KSK, if necessary; if there is only + one key acting as a KSK for the zone, these arguments can be omitted. + The time of publication or withdrawal for the DS is set to the current + time by default, but can be overridden to a specific time with the + argument ``-when time``, where ``time`` is expressed in YYYYMMDDHHMMSS + notation. + +.. option:: dnstap (-reopen | -roll [number]) + + This command closes and re-opens DNSTAP output files. + + ``rndc dnstap -reopen`` allows + the output file to be renamed externally, so that :iscman:`named` can + truncate and re-open it. + + ``rndc dnstap -roll`` causes the output file + to be rolled automatically, similar to log files. The most recent + output file has ".0" appended to its name; the previous most recent + output file is moved to ".1", and so on. If ``number`` is specified, then + the number of backup log files is limited to that number. + +.. option:: dumpdb [-all | -cache | -zones | -adb | -bad | -expired | -fail] [view ...] + + This command dumps the server's caches (default) and/or zones to the dump file for + the specified views. If no view is specified, all views are dumped. + (See the ``dump-file`` option in the BIND 9 Administrator Reference + Manual.) + +.. option:: fetchlimit [view] + + This command dumps a list of servers that are currently being + rate-limited as a result of ``fetches-per-server`` settings, and + a list of domain names that are currently being rate-limited as + a result of ``fetches-per-zone`` settings. + +.. option:: flush + + This command flushes the server's cache. + +.. option:: flushname name [view] + + This command flushes the given name from the view's DNS cache and, if applicable, + from the view's nameserver address database, bad server cache, and + SERVFAIL cache. + +.. option:: flushtree name [view] + + This command flushes the given name, and all of its subdomains, from the view's + DNS cache, address database, bad server cache, and SERVFAIL cache. + +.. option:: freeze [zone [class [view]]] + + This command suspends updates to a dynamic zone. If no zone is specified, then all + zones are suspended. This allows manual edits to be made to a zone + normally updated by dynamic update, and causes changes in the + journal file to be synced into the master file. All dynamic update + attempts are refused while the zone is frozen. + + See also :option:`rndc thaw`. + +.. option:: halt [-p] + + This command stops the server immediately. Recent changes made through dynamic + update or IXFR are not saved to the master files, but are rolled + forward from the journal files when the server is restarted. If + ``-p`` is specified, :iscman:`named`'s process ID is returned. This allows + an external process to determine when :iscman:`named` has completed + halting. + + See also :option:`rndc stop`. + +.. option:: skr -import file zone [class [view]] + + This command allows you to import a SKR file for the specified zone, to + support offline KSK signing. + +.. option:: loadkeys [zone [class [view]]] + + This command fetches all DNSSEC keys for the given zone from the key directory. If + they are within their publication period, they are merged into the + zone's DNSKEY RRset. Unlike :option:`rndc sign`, however, the zone is not + immediately re-signed by the new keys, but is allowed to + incrementally re-sign over time. + + This command requires that the zone be configured with a ``dnssec-policy``, and + also requires the zone to be configured to allow dynamic DNS. (See "Dynamic + Update Policies" in the Administrator Reference Manual for more details.) + +.. option:: managed-keys (status | refresh | sync | destroy) [class [view]] + + This command inspects and controls the "managed-keys" database which handles + :rfc:`5011` DNSSEC trust anchor maintenance. If a view is specified, these + commands are applied to that view; otherwise, they are applied to all + views. + + - When run with the ``status`` keyword, this prints the current status of + the managed-keys database. + + - When run with the ``refresh`` keyword, this forces an immediate refresh + query to be sent for all the managed keys, updating the + managed-keys database if any new keys are found, without waiting + the normal refresh interval. + + - When run with the ``sync`` keyword, this forces an immediate dump of + the managed-keys database to disk (in the file + ``managed-keys.bind`` or (``viewname.mkeys``). This synchronizes + the database with its journal file, so that the database's current + contents can be inspected visually. + + - When run with the ``destroy`` keyword, the managed-keys database + is shut down and deleted, and all key maintenance is terminated. + This command should be used only with extreme caution. + + Existing keys that are already trusted are not deleted from + memory; DNSSEC validation can continue after this command is used. + However, key maintenance operations cease until :iscman:`named` is + restarted or reconfigured, and all existing key maintenance states + are deleted. + + Running :option:`rndc reconfig` or restarting :iscman:`named` immediately + after this command causes key maintenance to be reinitialized + from scratch, just as if the server were being started for the + first time. This is primarily intended for testing, but it may + also be used, for example, to jumpstart the acquisition of new + keys in the event of a trust anchor rollover, or as a brute-force + repair for key maintenance problems. + +.. option:: memprof [(on | off | dump)] + + This command controls memory profiling. To have any effect, :iscman:`named` must be + built with jemalloc, the library have profiling support enabled and run with the + ``prof:true`` allocator configuration. (either via ``MALLOC_CONF`` or ``/etc/malloc.conf``) + + The ``prof_active:false`` option is recommended to ensure the profiling overhead does + not affect :iscman:`named` when not needed. + + The ``on`` and ``off`` options will start and stop the jemalloc memory profiling respectively. + When run with the `dump` option, :iscman:`named` will dump the profile to the working + directory. The name will be chosen automatically by jemalloc. + +.. option:: modzone zone [class [view]] configuration + + This command modifies the configuration of a zone while the server is running. This + command requires the ``allow-new-zones`` option to be set to ``yes``. + As with ``addzone``, the configuration string specified on the + command line is the zone configuration text that would ordinarily be + placed in :iscman:`named.conf`. + + If the zone was originally added via :option:`rndc addzone`, the + configuration changes are recorded permanently and are still + in effect after the server is restarted or reconfigured. However, if + it was originally configured in :iscman:`named.conf`, then that original + configuration remains in place; when the server is restarted or + reconfigured, the zone reverts to its original configuration. To + make the changes permanent, it must also be modified in + :iscman:`named.conf`. + + See also :option:`rndc addzone` and :option:`rndc delzone`. + +.. option:: notify zone [class [view]] + + This command resends NOTIFY messages for the zone. + +.. option:: notrace + + This command sets the server's debugging level to 0. + + See also :option:`rndc trace`. + +.. option:: nta [(-class class | -dump | -force | -remove | -lifetime duration)] domain [view] + + This command sets a DNSSEC negative trust anchor (NTA) for ``domain``, with a + lifetime of ``duration``. The default lifetime is configured in + :iscman:`named.conf` via the ``nta-lifetime`` option, and defaults to one + hour. The lifetime cannot exceed one week. + + A negative trust anchor selectively disables DNSSEC validation for + zones that are known to be failing because of misconfiguration rather + than an attack. When data to be validated is at or below an active + NTA (and above any other configured trust anchors), :iscman:`named` + aborts the DNSSEC validation process and treats the data as insecure + rather than bogus. This continues until the NTA's lifetime has + elapsed. + + NTAs persist across restarts of the :iscman:`named` server. The NTAs for a + view are saved in a file called ``name.nta``, where ``name`` is the name + of the view; if it contains characters that are incompatible with + use as a file name, a cryptographic hash is generated from the name of + the view. + + An existing NTA can be removed by using the ``-remove`` option. + + An NTA's lifetime can be specified with the ``-lifetime`` option. + TTL-style suffixes can be used to specify the lifetime in seconds, + minutes, or hours. If the specified NTA already exists, its lifetime + is updated to the new value. Setting ``lifetime`` to zero is + equivalent to ``-remove``. + + If ``-dump`` is used, any other arguments are ignored and a list + of existing NTAs is printed. Note that this may include NTAs that are + expired but have not yet been cleaned up. + + Normally, :iscman:`named` periodically tests to see whether data below + an NTA can now be validated (see the ``nta-recheck`` option in the + Administrator Reference Manual for details). If data can be + validated, then the NTA is regarded as no longer necessary and is + allowed to expire early. The ``-force`` parameter overrides this behavior + and forces an NTA to persist for its entire lifetime, regardless of + whether data could be validated if the NTA were not present. + + The view class can be specified with ``-class``. The default is class + ``IN``, which is the only class for which DNSSEC is currently + supported. + + All of these options can be shortened, i.e., to ``-l``, ``-r``, + ``-d``, ``-f``, and ``-c``. + + Unrecognized options are treated as errors. To refer to a domain or + view name that begins with a hyphen, use a double-hyphen (--) on the + command line to indicate the end of options. + +.. option:: querylog [(on | off)] + + This command enables or disables query logging. For backward compatibility, this + command can also be used without an argument to toggle query logging + on and off. + + Query logging can also be enabled by explicitly directing the + ``queries`` ``category`` to a ``channel`` in the ``logging`` section + of :iscman:`named.conf`, or by specifying ``querylog yes;`` in the + ``options`` section of :iscman:`named.conf`. + +.. option:: reconfig + + This command reloads the configuration file and loads new zones, but does not reload + existing zone files even if they have changed. This is faster than a + full :option:`rndc reload` when there is a large number of zones, because it + avoids the need to examine the modification times of the zone files. + +.. option:: recursing + + This command dumps the list of queries :iscman:`named` is currently + recursing on, and the list of domains to which iterative queries + are currently being sent. + + The first list includes all unique clients that are waiting for + recursion to complete, including the query that is awaiting a + response and the timestamp (seconds since the Unix epoch) of + when named started processing this client query. + + The second list comprises of domains for which there are active + (or recently active) fetches in progress. It reports the number + of active fetches for each domain and the number of queries that + have been passed (allowed) or dropped (spilled) as a result of + the ``fetches-per-zone`` limit. (Note: these counters are not + cumulative over time; whenever the number of active fetches for + a domain drops to zero, the counter for that domain is deleted, + and the next time a fetch is sent to that domain, it is recreated + with the counters set to zero). + +.. option:: refresh zone [class [view]] + + This command schedules zone maintenance for the given zone. + +.. option:: reload + + This command reloads the configuration file and zones. + + .. program:: rndc reload + .. option:: zone [class [view]] + + If a zone is specified, this command reloads only the given zone. + If no zone is specified, the reloading happens asynchronously. + +.. program:: rndc + +.. option:: reset-stats + + This command resets the requested statistics counters. + + At least one counter name must be provided. Currently the following counters + are supported: ``recursive-high-water``, ``tcp-high-water``. + +.. option:: responselog [on | off] + + This command enables or disables response logging. For backward compatibility, + this command can also be used without an argument to toggle response logging + on and off. + + Unlike query logging, response logging cannot be enabled by explicitly directing + the ``responses`` ``category`` to a ``channel`` in the ``logging`` section + of :iscman:`named.conf`, but it can still be enabled by specifying + ``responselog yes;`` in the ``options`` section of :iscman:`named.conf`. + +.. option:: retransfer [-force] zone [class [view]] + + This command retransfers the given secondary zone from the primary server. + + If the zone is configured to use ``inline-signing``, the signed + version of the zone is discarded; after the retransfer of the + unsigned version is complete, the signed version is regenerated + with new signatures. With the optional ``-force`` argument provided + if there is an ongoing zone transfer it will be aborted before a new zone + transfer is scheduled. + +.. option:: scan + + This command scans the list of available network interfaces for changes, without + performing a full :option:`rndc reconfig` or waiting for the + ``interface-interval`` timer. + +.. option:: secroots [-] [view ...] + + This command dumps the security roots (i.e., trust anchors configured via + ``trust-anchors``, or the ``managed-keys`` or ``trusted-keys`` statements + [both deprecated], or ``dnssec-validation auto``) and negative trust anchors + for the specified views. If no view is specified, all views are + dumped. Security roots indicate whether they are configured as trusted + keys, managed keys, or initializing managed keys (managed keys that have not + yet been updated by a successful key refresh query). + + If the first argument is ``-``, then the output is returned via the + :program:`rndc` response channel and printed to the standard output. + Otherwise, it is written to the secroots dump file, which defaults to + ``named.secroots``, but can be overridden via the ``secroots-file`` + option in :iscman:`named.conf`. + + See also :option:`rndc managed-keys`. + +.. option:: serve-stale (on | off | reset | status) [class [view]] + + This command enables, disables, resets, or reports the current status of + the serving of stale answers as configured in :iscman:`named.conf`. + + If serving of stale answers is disabled by ``rndc-serve-stale off``, then it + remains disabled even if :iscman:`named` is reloaded or reconfigured. ``rndc + serve-stale reset`` restores the setting as configured in :iscman:`named.conf`. + + ``rndc serve-stale status`` reports whether caching and serving of stale + answers is currently enabled or disabled. It also reports the values of + ``stale-answer-ttl`` and ``max-stale-ttl``. + +.. option:: showzone zone [class [view]] + + This command prints the configuration of a running zone. + + See also :option:`rndc zonestatus`. + +.. option:: sign zone [class [view]] + + This command fetches all DNSSEC keys for the given zone from the key directory (see + the ``key-directory`` option in the BIND 9 Administrator Reference + Manual). If they are within their publication period, they are merged into + the zone's DNSKEY RRset. If the DNSKEY RRset is changed, then the + zone is automatically re-signed with the new key set. + + This command requires that the zone be configured with a ``dnssec-policy``, and + also requires the zone to be configured to allow dynamic DNS. (See "Dynamic + Update Policies" in the Administrator Reference Manual for more details.) + + See also :option:`rndc loadkeys`. + +.. option:: signing [(-list | -clear keyid/algorithm | -clear all | -nsec3param (parameters | none) | -serial value) zone [class [view]] + + This command lists, edits, or removes the DNSSEC signing-state records for the + specified zone. The status of ongoing DNSSEC operations, such as + signing or generating NSEC3 chains, is stored in the zone in the form + of DNS resource records of type ``sig-signing-type``. + ``rndc signing -list`` converts these records into a human-readable + form, indicating which keys are currently signing or have finished + signing the zone, and which NSEC3 chains are being created or + removed. + + ``rndc signing -clear`` can remove a single key (specified in the + same format that ``rndc signing -list`` uses to display it), or all + keys. In either case, only completed keys are removed; any record + indicating that a key has not yet finished signing the zone is + retained. + + ``rndc signing -nsec3param`` sets the NSEC3 parameters for a zone. + This is the only supported mechanism for using NSEC3 with + ``inline-signing`` zones. Parameters are specified in the same format + as an NSEC3PARAM resource record: ``hash algorithm``, ``flags``, ``iterations``, + and ``salt``, in that order. + + Currently, the only defined value for ``hash algorithm`` is ``1``, + representing SHA-1. The ``flags`` may be set to ``0`` or ``1``, + depending on whether the opt-out bit in the NSEC3 + chain should be set. ``iterations`` defines the number of additional times to apply + the algorithm when generating an NSEC3 hash. The ``salt`` is a string + of data expressed in hexadecimal, a hyphen (``-``) if no salt is to be + used, or the keyword ``auto``, which causes :iscman:`named` to generate a + random 64-bit salt. + + The only recommended configuration is ``rndc signing -nsec3param 1 0 0 - zone``, + i.e. no salt, no additional iterations, no opt-out. + + .. warning:: + Do not use extra iterations, salt, or opt-out unless all their implications + are fully understood. A higher number of iterations causes interoperability + problems and opens servers to CPU-exhausting DoS attacks. + + ``rndc signing -nsec3param none`` removes an existing NSEC3 chain and + replaces it with NSEC. + + ``rndc signing -serial value`` sets the serial number of the zone to + ``value``. If the value would cause the serial number to go backwards, it + is rejected. The primary use of this parameter is to set the serial number on inline + signed zones. + +.. option:: stats + + This command writes server statistics to the statistics file. (See the + ``statistics-file`` option in the BIND 9 Administrator Reference + Manual.) + +.. option:: status + + This command displays the status of the server. Note that the number of zones includes + the internal ``bind/CH`` zone and the default ``./IN`` hint zone, if + there is no explicit root zone configured. + +.. option:: stop -p + + This command stops the server, making sure any recent changes made through dynamic + update or IXFR are first saved to the master files of the updated + zones. If ``-p`` is specified, :iscman:`named`'s process ID is returned. + This allows an external process to determine when :iscman:`named` has + completed stopping. + + See also :option:`rndc halt`. + +.. option:: sync -clean [zone [class [view]]] + + This command syncs changes in the journal file for a dynamic zone to the master + file. If the "-clean" option is specified, the journal file is also + removed. If no zone is specified, then all zones are synced. + +.. option:: tcp-timeouts [initial idle keepalive advertised] + + When called without arguments, this command displays the current values of the + ``tcp-initial-timeout``, ``tcp-idle-timeout``, + ``tcp-keepalive-timeout``, and ``tcp-advertised-timeout`` options. + When called with arguments, these values are updated. This allows an + administrator to make rapid adjustments when under a + denial-of-service (DoS) attack. See the descriptions of these options in the BIND 9 + Administrator Reference Manual for details of their use. + +.. option:: thaw [zone [class [view]]] + + This command enables updates to a frozen dynamic zone. If no zone is specified, + then all frozen zones are enabled. This causes the server to reload + the zone from disk, and re-enables dynamic updates after the load has + completed. After a zone is thawed, dynamic updates are no longer + refused. If the zone has changed and the ``ixfr-from-differences`` + option is in use, the journal file is updated to reflect + changes in the zone. Otherwise, if the zone has changed, any existing + journal file is removed. If no zone is specified, the reloading happens + asynchronously. + + See also :option:`rndc freeze`. + +.. option:: trace [level] + + If no level is specified, this command increments the server's debugging + level by one. + + .. program:: rndc trace + .. option:: level + + If specified, this command sets the server's debugging level to the + provided value. + + See also :option:`rndc notrace`. + +.. program:: rndc + +.. option:: validation (on | off | status) [view ...] + + This command enables, disables, or checks the current status of DNSSEC validation. By + default, validation is enabled. + + The cache is flushed when validation is turned on or off to avoid using data + that might differ between states. + +.. option:: zonestatus zone [class [view]] + + This command displays the current status of the given zone, including the master + file name and any include files from which it was loaded, when it was + most recently loaded, the current serial number, the number of nodes, + whether the zone supports dynamic updates, whether the zone is DNSSEC + signed, whether it uses automatic DNSSEC key management or inline + signing, and the scheduled refresh or expiry times for the zone. + + See also :option:`rndc showzone`. + +:program:`rndc` commands that specify zone names, such as :option:`reload` +:option:`retransfer`, or :option:`zonestatus`, can be ambiguous when applied to zones +of type ``redirect``. Redirect zones are always called ``.``, and can be +confused with zones of type ``hint`` or with secondary copies of the root +zone. To specify a redirect zone, use the special zone name +``-redirect``, without a trailing period. (With a trailing period, this +would specify a zone called "-redirect".) + +Limitations +~~~~~~~~~~~ + +There is currently no way to provide the shared secret for a ``server_key`` +without using the configuration file. + +Several error messages could be clearer. + +See Also +~~~~~~~~ + +:iscman:`rndc.conf(5) `, :iscman:`rndc-confgen(8) `, +:iscman:`named(8) `, :iscman:`named.conf(5) `, BIND 9 Administrator +Reference Manual. diff --git a/bin/rndc/util.c b/bin/rndc/util.c new file mode 100644 index 0000000..e0529aa --- /dev/null +++ b/bin/rndc/util.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include "util.h" +#include +#include +#include +#include +#include + +#include + +extern bool verbose; +extern const char *progname; + +void +notify(const char *fmt, ...) { + va_list ap; + + if (verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + } +} + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + _exit(EXIT_FAILURE); +} diff --git a/bin/rndc/util.h b/bin/rndc/util.h new file mode 100644 index 0000000..4ac83e5 --- /dev/null +++ b/bin/rndc/util.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +/*! \file */ + +#include +#include +#include + +#define NS_CONTROL_PORT 953 + +#undef DO +#define DO(name, function) \ + do { \ + result = function; \ + if (result != ISC_R_SUCCESS) \ + fatal("%s: %s", name, isc_result_totext(result)); \ + else \ + notify("%s", name); \ + } while (0) + +ISC_LANG_BEGINDECLS + +void +notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); + +noreturn void +fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_LANG_ENDDECLS diff --git a/bin/tests/Makefile.am b/bin/tests/Makefile.am new file mode 100644 index 0000000..56e81b1 --- /dev/null +++ b/bin/tests/Makefile.am @@ -0,0 +1,38 @@ +include $(top_srcdir)/Makefile.top + +EXTRA_DIST = convert-trs-to-junit.py + +SUBDIRS = system + +noinst_PROGRAMS = \ + test_client \ + test_server \ + wire_test + +AM_CFLAGS += \ + $(TEST_CFLAGS) + +test_client_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) + +test_client_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +test_server_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) + +test_server_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +wire_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +wire_test_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in new file mode 100644 index 0000000..2819210 --- /dev/null +++ b/bin/tests/Makefile.in @@ -0,0 +1,993 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +noinst_PROGRAMS = test_client$(EXEEXT) test_server$(EXEEXT) \ + wire_test$(EXEEXT) +subdir = bin/tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +test_client_SOURCES = test_client.c +test_client_OBJECTS = test_client-test_client.$(OBJEXT) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +test_client_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_server_SOURCES = test_server.c +test_server_OBJECTS = test_server-test_server.$(OBJEXT) +test_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) +wire_test_SOURCES = wire_test.c +wire_test_OBJECTS = wire_test-wire_test.$(OBJEXT) +wire_test_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/test_client-test_client.Po \ + ./$(DEPDIR)/test_server-test_server.Po \ + ./$(DEPDIR)/wire_test-wire_test.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = test_client.c test_server.c wire_test.c +DIST_SOURCES = test_client.c test_server.c wire_test.c +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir distdir-am +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) $(TEST_CFLAGS) +AM_CPPFLAGS = \ + $(STD_CPPFLAGS) \ + -include $(top_builddir)/config.h \ + -I$(srcdir)/include + +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +EXTRA_DIST = convert-trs-to-junit.py +SUBDIRS = system +test_client_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) + +test_client_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +test_server_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) + +test_server_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +wire_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +wire_test_LDADD = \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES) + @rm -f test_client$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS) + +test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES) + @rm -f test_server$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS) + +wire_test$(EXEEXT): $(wire_test_OBJECTS) $(wire_test_DEPENDENCIES) $(EXTRA_wire_test_DEPENDENCIES) + @rm -f wire_test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(wire_test_OBJECTS) $(wire_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_client-test_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server-test_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wire_test-wire_test.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_client-test_client.o: test_client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_client-test_client.o -MD -MP -MF $(DEPDIR)/test_client-test_client.Tpo -c -o test_client-test_client.o `test -f 'test_client.c' || echo '$(srcdir)/'`test_client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_client-test_client.Tpo $(DEPDIR)/test_client-test_client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_client.c' object='test_client-test_client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_client-test_client.o `test -f 'test_client.c' || echo '$(srcdir)/'`test_client.c + +test_client-test_client.obj: test_client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_client-test_client.obj -MD -MP -MF $(DEPDIR)/test_client-test_client.Tpo -c -o test_client-test_client.obj `if test -f 'test_client.c'; then $(CYGPATH_W) 'test_client.c'; else $(CYGPATH_W) '$(srcdir)/test_client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_client-test_client.Tpo $(DEPDIR)/test_client-test_client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_client.c' object='test_client-test_client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_client_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_client-test_client.obj `if test -f 'test_client.c'; then $(CYGPATH_W) 'test_client.c'; else $(CYGPATH_W) '$(srcdir)/test_client.c'; fi` + +test_server-test_server.o: test_server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_server-test_server.o -MD -MP -MF $(DEPDIR)/test_server-test_server.Tpo -c -o test_server-test_server.o `test -f 'test_server.c' || echo '$(srcdir)/'`test_server.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_server-test_server.Tpo $(DEPDIR)/test_server-test_server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_server.c' object='test_server-test_server.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_server-test_server.o `test -f 'test_server.c' || echo '$(srcdir)/'`test_server.c + +test_server-test_server.obj: test_server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_server-test_server.obj -MD -MP -MF $(DEPDIR)/test_server-test_server.Tpo -c -o test_server-test_server.obj `if test -f 'test_server.c'; then $(CYGPATH_W) 'test_server.c'; else $(CYGPATH_W) '$(srcdir)/test_server.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_server-test_server.Tpo $(DEPDIR)/test_server-test_server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_server.c' object='test_server-test_server.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_server-test_server.obj `if test -f 'test_server.c'; then $(CYGPATH_W) 'test_server.c'; else $(CYGPATH_W) '$(srcdir)/test_server.c'; fi` + +wire_test-wire_test.o: wire_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wire_test-wire_test.o -MD -MP -MF $(DEPDIR)/wire_test-wire_test.Tpo -c -o wire_test-wire_test.o `test -f 'wire_test.c' || echo '$(srcdir)/'`wire_test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wire_test-wire_test.Tpo $(DEPDIR)/wire_test-wire_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wire_test.c' object='wire_test-wire_test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wire_test-wire_test.o `test -f 'wire_test.c' || echo '$(srcdir)/'`wire_test.c + +wire_test-wire_test.obj: wire_test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT wire_test-wire_test.obj -MD -MP -MF $(DEPDIR)/wire_test-wire_test.Tpo -c -o wire_test-wire_test.obj `if test -f 'wire_test.c'; then $(CYGPATH_W) 'wire_test.c'; else $(CYGPATH_W) '$(srcdir)/wire_test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wire_test-wire_test.Tpo $(DEPDIR)/wire_test-wire_test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wire_test.c' object='wire_test-wire_test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(wire_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o wire_test-wire_test.obj `if test -f 'wire_test.c'; then $(CYGPATH_W) 'wire_test.c'; else $(CYGPATH_W) '$(srcdir)/wire_test.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/test_client-test_client.Po + -rm -f ./$(DEPDIR)/test_server-test_server.Po + -rm -f ./$(DEPDIR)/wire_test-wire_test.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-recursive + +doc-am: doc-local + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/test_client-test_client.Po + -rm -f ./$(DEPDIR)/test_server-test_server.Po + -rm -f ./$(DEPDIR)/wire_test-wire_test.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +test: test-recursive + +test-am: test-local + +uninstall-am: + +unit: unit-recursive + +unit-am: unit-local + +.MAKE: $(am__recursive_targets) all check install install-am \ + install-exec install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-am clean clean-generic clean-libtool \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir doc-am doc-local dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am test-am test-local uninstall uninstall-am unit-am \ + unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/convert-trs-to-junit.py b/bin/tests/convert-trs-to-junit.py new file mode 100755 index 0000000..6d7b4aa --- /dev/null +++ b/bin/tests/convert-trs-to-junit.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# Convert automake .trs files into JUnit format suitable for Gitlab + +import argparse +import os +import sys +from xml.etree import ElementTree +from xml.etree.ElementTree import Element +from xml.etree.ElementTree import SubElement + + +# getting explicit encoding specification right for Python 2/3 would be messy, +# so let's hope for the best +def read_whole_text(filename): + with open(filename) as inf: # pylint: disable-msg=unspecified-encoding + return inf.read().strip() + + +def read_trs_result(filename): + result = None + with open(filename, "r") as trs: # pylint: disable-msg=unspecified-encoding + for line in trs: + items = line.split() + if len(items) < 2: + raise ValueError("unsupported line in trs file", filename, line) + if items[0] != (":test-result:"): + continue + if result is not None: + raise NotImplementedError("double :test-result:", filename) + result = items[1].upper() + + if result is None: + raise ValueError(":test-result: not found", filename) + + return result + + +def find_test_relative_path(source_dir, in_path): + """Return {in_path}.c if it exists, with fallback to {in_path}""" + candidates_relative = [in_path + ".c", in_path] + for relative in candidates_relative: + absolute = os.path.join(source_dir, relative) + if os.path.exists(absolute): + return relative + raise KeyError + + +def err_out(exception): + raise exception + + +def walk_trss(source_dir): + for cur_dir, _dirs, files in os.walk(source_dir, onerror=err_out): + for filename in files: + if not filename.endswith(".trs"): + continue + + filename_prefix = filename[: -len(".trs")] + log_name = filename_prefix + ".log" + full_trs_path = os.path.join(cur_dir, filename) + full_log_path = os.path.join(cur_dir, log_name) + sub_dir = os.path.relpath(cur_dir, source_dir) + test_name = os.path.join(sub_dir, filename_prefix) + + t = { + "name": test_name, + "full_log_path": full_log_path, + "rel_log_path": os.path.relpath(full_log_path, source_dir), + } + t["result"] = read_trs_result(full_trs_path) + + # try to find dir/file path for a clickable link + try: + t["rel_file_path"] = find_test_relative_path(source_dir, test_name) + except KeyError: + pass # no existing path found + + yield t + + +def append_testcase(testsuite, t): + # attributes taken from + # https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/gitlab/ci/parsers/test/junit.rb + attrs = {"name": t["name"]} + if "rel_file_path" in t: + attrs["file"] = t["rel_file_path"] + + testcase = SubElement(testsuite, "testcase", attrs) + + # Gitlab accepts only [[ATTACHMENT| links for system-out, not raw text + s = SubElement(testcase, "system-out") + s.text = "[[ATTACHMENT|" + t["rel_log_path"] + "]]" + if t["result"].lower() == "pass": + return + + # Gitlab shows output only for failed or skipped tests + if t["result"].lower() == "skip": + err = SubElement(testcase, "skipped") + else: + err = SubElement(testcase, "failure") + err.text = read_whole_text(t["full_log_path"]) + + +def gen_junit(results): + testsuites = Element("testsuites") + testsuite = SubElement(testsuites, "testsuite") + for test in results: + append_testcase(testsuite, test) + return testsuites + + +def check_directory(path): + try: + os.listdir(path) + return path + except OSError as ex: + msg = "Path {} cannot be listed as a directory: {}".format(path, ex) + raise argparse.ArgumentTypeError(msg) + + +def main(): + parser = argparse.ArgumentParser( + description="Recursively search for .trs + .log files and compile " + "them into JUnit XML suitable for Gitlab. Paths in the " + "XML are relative to the specified top directory." + ) + parser.add_argument( + "top_directory", + type=check_directory, + help="root directory where to start scanning for .trs files", + ) + args = parser.parse_args() + junit = gen_junit(walk_trss(args.top_directory)) + + # encode results into file format, on Python 3 it produces bytes + xml = ElementTree.tostring(junit, "utf-8") + # use stdout as a binary file object, Python2/3 compatibility + output = getattr(sys.stdout, "buffer", sys.stdout) + output.write(xml) + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/Makefile.am b/bin/tests/system/Makefile.am new file mode 100644 index 0000000..7ef563b --- /dev/null +++ b/bin/tests/system/Makefile.am @@ -0,0 +1,221 @@ +include $(top_srcdir)/Makefile.top + +EXTRA_DIST = . + +# Source tarballs must not contain configure/build artifacts. +dist-hook: + git clean -n -x -d | \ + grep -v "Makefile.in$$" | \ + sed -n "s|^Would remove \(.*\)|$(distdir)/\1|p" | \ + xargs -I{} rm -rf "{}" + +SUBDIRS = dyndb/driver dlzexternal/driver hooks/driver + +if DNSRPS +SUBDIRS += rpz/testlib +endif + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +LDADD += \ + $(LIBISC_LIBS) \ + $(LIBDNS_LIBS) + +if HAVE_PERL +if HAVE_PYTHON +if HAVE_PYTEST + +noinst_PROGRAMS = \ + feature-test \ + makejournal \ + pipelined/pipequeries \ + rndc/gencheck \ + rpz/dnsrps + +feature_test_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(OPENSSL_CFLAGS) + +feature_test_LDADD = \ + $(LDADD) \ + $(LIBDNS_LIBS) \ + $(OPENSSL_LIBS) + +makejournal_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBDNS_CFLAGS) + +makejournal_LDADD = \ + $(LDADD) \ + $(LIBDNS_LIBS) + +pipelined_pipequeries_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBDNS_CFLAGS) + +pipelined_pipequeries_LDADD = \ + $(LDADD) \ + $(LIBDNS_LIBS) + +rpz_dnsrps_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(LIBDNS_CFLAGS) \ + -DLIBRPZ_LIB_OPEN=\"$(abs_builddir)/rpz/testlib/.libs/libdummyrpz.so\" + +rpz_dnsrps_LDADD = \ + $(LDADD) \ + $(LIBDNS_LIBS) \ + $(DLOPEN_LIBS) + +# Longer running tests are listed (and executed) first to take the most +# advantage of parallel execution. +TESTS = \ + rpz \ + rpzrecurse \ + serve-stale \ + timeouts \ + upforwd \ + acl \ + additional \ + addzone \ + allow-query \ + auth \ + autosign \ + builtin \ + cacheclean \ + camp \ + case \ + catz \ + cds \ + chain \ + checkconf \ + checkds \ + checknames \ + checkzone \ + cookie \ + cpu \ + database \ + dialup \ + digdelv \ + dispatch \ + dlzexternal \ + dns64 \ + dnssec \ + dnstap \ + doth \ + dsdigest \ + dyndb \ + ecdsa \ + eddsa \ + ednscompliance \ + emptyzones \ + enginepkcs11 \ + filter-aaaa \ + fetchlimit \ + formerr \ + forward \ + geoip2 \ + glue \ + idna \ + include-multiplecfg \ + inline \ + integrity \ + ixfr \ + hooks \ + host \ + journal \ + kasp \ + keepalive \ + keyfromlabel \ + ksr \ + legacy \ + limits \ + logfileconfig \ + masterfile \ + masterformat \ + metadata \ + mirror \ + mkeys \ + multisigner \ + names \ + notify \ + nsec3 \ + nslookup \ + nsupdate \ + nzd2nzf \ + padding \ + pending \ + proxy \ + pipelined \ + qmin \ + query-source \ + reclimit \ + redirect \ + resolver \ + rndc \ + rootkeysentinel \ + rpzextra \ + rrchecker \ + rrl \ + rrsetorder \ + rsabigexponent \ + runtime \ + sfcache \ + shutdown \ + smartsign \ + sortlist \ + spf \ + staticstub \ + statistics \ + statschannel \ + stress \ + stub \ + synthfromdnssec \ + tcp \ + tools \ + transport-acl \ + tsig \ + tsiggss \ + ttl \ + unknown \ + verify \ + views \ + wildcard \ + xfer \ + xferquota \ + zero \ + zonechecks + +else !HAVE_PYTEST +check: + echo pytest is not available, no tests were ran + exit 1 +endif !HAVE_PYTEST +else !HAVE_PYTHON +check: + echo Python is not available, no tests were ran + exit 1 +endif !HAVE_PYTHON +else !HAVE_PERL +check: + echo Perl is not available, no tests were ran + exit 1 +endif !HAVE_PERL + +LOG_DRIVER_V = $(LOG_DRIVER_V_@AM_V@) +LOG_DRIVER_V_ = $(LOG_DRIVER_V_@AM_DEFAULT_V@) +LOG_DRIVER_V_0 = --verbose no +LOG_DRIVER_V_1 = --verbose yes + +LOG_DRIVER = $(srcdir)/custom-test-driver +AM_LOG_DRIVER_FLAGS = $(LOG_DRIVER_V) + +LOG_COMPILER = $(srcdir)/run.sh + +test-local: check + +clean-local:: + -find -L . -mindepth 1 -maxdepth 1 -type d -name "*_*" -and -not -name "_common" -exec rm -rf {} \; diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in new file mode 100644 index 0000000..62f6a27 --- /dev/null +++ b/bin/tests/system/Makefile.in @@ -0,0 +1,2419 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +@DNSRPS_TRUE@am__append_2 = rpz/testlib +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@noinst_PROGRAMS = feature-test$(EXEEXT) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ makejournal$(EXEEXT) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ pipelined/pipequeries$(EXEEXT) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rndc/gencheck$(EXEEXT) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rpz/dnsrps$(EXEEXT) +subdir = bin/tests/system +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = ifconfig.sh start.sh stop.sh +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +feature_test_SOURCES = feature-test.c +feature_test_OBJECTS = feature_test-feature-test.$(OBJEXT) +am__DEPENDENCIES_1 = +@HAVE_JEMALLOC_FALSE@am__DEPENDENCIES_2 = \ +@HAVE_JEMALLOC_FALSE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@feature_test_DEPENDENCIES = $(am__DEPENDENCIES_3) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +makejournal_SOURCES = makejournal.c +makejournal_OBJECTS = makejournal-makejournal.$(OBJEXT) +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@makejournal_DEPENDENCIES = $(am__DEPENDENCIES_3) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) +pipelined_pipequeries_SOURCES = pipelined/pipequeries.c +am__dirstamp = $(am__leading_dot)dirstamp +pipelined_pipequeries_OBJECTS = \ + pipelined/pipequeries-pipequeries.$(OBJEXT) +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@pipelined_pipequeries_DEPENDENCIES = $(am__DEPENDENCIES_3) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) +rndc_gencheck_SOURCES = rndc/gencheck.c +rndc_gencheck_OBJECTS = rndc/gencheck.$(OBJEXT) +rndc_gencheck_LDADD = $(LDADD) +rndc_gencheck_DEPENDENCIES = $(am__DEPENDENCIES_2) $(LIBDNS_LIBS) +rpz_dnsrps_SOURCES = rpz/dnsrps.c +rpz_dnsrps_OBJECTS = rpz/dnsrps-dnsrps.$(OBJEXT) +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@rpz_dnsrps_DEPENDENCIES = $(am__DEPENDENCIES_3) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/feature_test-feature-test.Po \ + ./$(DEPDIR)/makejournal-makejournal.Po \ + pipelined/$(DEPDIR)/pipequeries-pipequeries.Po \ + rndc/$(DEPDIR)/gencheck.Po rpz/$(DEPDIR)/dnsrps-dnsrps.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = feature-test.c makejournal.c pipelined/pipequeries.c \ + rndc/gencheck.c rpz/dnsrps.c +DIST_SOURCES = feature-test.c makejournal.c pipelined/pipequeries.c \ + rndc/gencheck.c rpz/dnsrps.c +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + check recheck distdir distdir-am +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +DIST_SUBDIRS = dyndb/driver dlzexternal/driver hooks/driver \ + rpz/testlib +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/ifconfig.sh.in \ + $(srcdir)/start.sh.in $(srcdir)/stop.sh.in \ + $(top_srcdir)/Makefile.top $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver README.md +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = $(LIBISC_LIBS) $(LIBDNS_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +EXTRA_DIST = . +SUBDIRS = dyndb/driver dlzexternal/driver hooks/driver $(am__append_2) +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@feature_test_CPPFLAGS = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_CFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(OPENSSL_CFLAGS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@feature_test_LDADD = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LDADD) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(OPENSSL_LIBS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@makejournal_CPPFLAGS = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_CFLAGS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@makejournal_LDADD = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LDADD) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@pipelined_pipequeries_CPPFLAGS = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_CFLAGS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@pipelined_pipequeries_LDADD = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LDADD) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@rpz_dnsrps_CPPFLAGS = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(AM_CPPFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_CFLAGS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ -DLIBRPZ_LIB_OPEN=\"$(abs_builddir)/rpz/testlib/.libs/libdummyrpz.so\" + +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@rpz_dnsrps_LDADD = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LDADD) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(LIBDNS_LIBS) \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ $(DLOPEN_LIBS) + + +# Longer running tests are listed (and executed) first to take the most +# advantage of parallel execution. +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@TESTS = \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rpz \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rpzrecurse \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ serve-stale \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ timeouts \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ upforwd \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ acl \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ additional \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ addzone \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ allow-query \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ auth \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ autosign \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ builtin \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ cacheclean \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ camp \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ case \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ catz \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ cds \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ chain \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ checkconf \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ checkds \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ checknames \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ checkzone \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ cookie \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ cpu \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ database \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dialup \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ digdelv \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dispatch \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dlzexternal \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dns64 \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dnssec \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dnstap \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ doth \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dsdigest \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ dyndb \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ ecdsa \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ eddsa \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ ednscompliance \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ emptyzones \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ enginepkcs11 \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ filter-aaaa \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ fetchlimit \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ formerr \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ forward \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ geoip2 \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ glue \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ idna \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ include-multiplecfg \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ inline \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ integrity \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ ixfr \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ hooks \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ host \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ journal \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ kasp \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ keepalive \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ keyfromlabel \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ ksr \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ legacy \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ limits \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ logfileconfig \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ masterfile \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ masterformat \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ metadata \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ mirror \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ mkeys \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ multisigner \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ names \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ notify \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ nsec3 \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ nslookup \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ nsupdate \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ nzd2nzf \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ padding \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ pending \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ proxy \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ pipelined \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ qmin \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ query-source \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ reclimit \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ redirect \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ resolver \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rndc \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rootkeysentinel \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rpzextra \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rrchecker \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rrl \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rrsetorder \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ rsabigexponent \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ runtime \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ sfcache \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ shutdown \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ smartsign \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ sortlist \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ spf \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ staticstub \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ statistics \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ statschannel \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ stress \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ stub \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ synthfromdnssec \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ tcp \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ tools \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ transport-acl \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ tsig \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ tsiggss \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ ttl \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ unknown \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ verify \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ views \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ wildcard \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ xfer \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ xferquota \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ zero \ +@HAVE_PERL_TRUE@@HAVE_PYTEST_TRUE@@HAVE_PYTHON_TRUE@ zonechecks + +LOG_DRIVER_V = $(LOG_DRIVER_V_@AM_V@) +LOG_DRIVER_V_ = $(LOG_DRIVER_V_@AM_DEFAULT_V@) +LOG_DRIVER_V_0 = --verbose no +LOG_DRIVER_V_1 = --verbose yes +LOG_DRIVER = $(srcdir)/custom-test-driver +AM_LOG_DRIVER_FLAGS = $(LOG_DRIVER_V) +LOG_COMPILER = $(srcdir)/run.sh +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/system/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +ifconfig.sh: $(top_builddir)/config.status $(srcdir)/ifconfig.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +start.sh: $(top_builddir)/config.status $(srcdir)/start.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +stop.sh: $(top_builddir)/config.status $(srcdir)/stop.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +feature-test$(EXEEXT): $(feature_test_OBJECTS) $(feature_test_DEPENDENCIES) $(EXTRA_feature_test_DEPENDENCIES) + @rm -f feature-test$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(feature_test_OBJECTS) $(feature_test_LDADD) $(LIBS) + +makejournal$(EXEEXT): $(makejournal_OBJECTS) $(makejournal_DEPENDENCIES) $(EXTRA_makejournal_DEPENDENCIES) + @rm -f makejournal$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(makejournal_OBJECTS) $(makejournal_LDADD) $(LIBS) +pipelined/$(am__dirstamp): + @$(MKDIR_P) pipelined + @: > pipelined/$(am__dirstamp) +pipelined/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) pipelined/$(DEPDIR) + @: > pipelined/$(DEPDIR)/$(am__dirstamp) +pipelined/pipequeries-pipequeries.$(OBJEXT): \ + pipelined/$(am__dirstamp) pipelined/$(DEPDIR)/$(am__dirstamp) + +pipelined/pipequeries$(EXEEXT): $(pipelined_pipequeries_OBJECTS) $(pipelined_pipequeries_DEPENDENCIES) $(EXTRA_pipelined_pipequeries_DEPENDENCIES) pipelined/$(am__dirstamp) + @rm -f pipelined/pipequeries$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pipelined_pipequeries_OBJECTS) $(pipelined_pipequeries_LDADD) $(LIBS) +rndc/$(am__dirstamp): + @$(MKDIR_P) rndc + @: > rndc/$(am__dirstamp) +rndc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) rndc/$(DEPDIR) + @: > rndc/$(DEPDIR)/$(am__dirstamp) +rndc/gencheck.$(OBJEXT): rndc/$(am__dirstamp) \ + rndc/$(DEPDIR)/$(am__dirstamp) + +rndc/gencheck$(EXEEXT): $(rndc_gencheck_OBJECTS) $(rndc_gencheck_DEPENDENCIES) $(EXTRA_rndc_gencheck_DEPENDENCIES) rndc/$(am__dirstamp) + @rm -f rndc/gencheck$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rndc_gencheck_OBJECTS) $(rndc_gencheck_LDADD) $(LIBS) +rpz/$(am__dirstamp): + @$(MKDIR_P) rpz + @: > rpz/$(am__dirstamp) +rpz/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) rpz/$(DEPDIR) + @: > rpz/$(DEPDIR)/$(am__dirstamp) +rpz/dnsrps-dnsrps.$(OBJEXT): rpz/$(am__dirstamp) \ + rpz/$(DEPDIR)/$(am__dirstamp) + +rpz/dnsrps$(EXEEXT): $(rpz_dnsrps_OBJECTS) $(rpz_dnsrps_DEPENDENCIES) $(EXTRA_rpz_dnsrps_DEPENDENCIES) rpz/$(am__dirstamp) + @rm -f rpz/dnsrps$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(rpz_dnsrps_OBJECTS) $(rpz_dnsrps_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f pipelined/*.$(OBJEXT) + -rm -f rndc/*.$(OBJEXT) + -rm -f rpz/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/feature_test-feature-test.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/makejournal-makejournal.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@pipelined/$(DEPDIR)/pipequeries-pipequeries.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@rndc/$(DEPDIR)/gencheck.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@rpz/$(DEPDIR)/dnsrps-dnsrps.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +feature_test-feature-test.o: feature-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT feature_test-feature-test.o -MD -MP -MF $(DEPDIR)/feature_test-feature-test.Tpo -c -o feature_test-feature-test.o `test -f 'feature-test.c' || echo '$(srcdir)/'`feature-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/feature_test-feature-test.Tpo $(DEPDIR)/feature_test-feature-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='feature-test.c' object='feature_test-feature-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o feature_test-feature-test.o `test -f 'feature-test.c' || echo '$(srcdir)/'`feature-test.c + +feature_test-feature-test.obj: feature-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT feature_test-feature-test.obj -MD -MP -MF $(DEPDIR)/feature_test-feature-test.Tpo -c -o feature_test-feature-test.obj `if test -f 'feature-test.c'; then $(CYGPATH_W) 'feature-test.c'; else $(CYGPATH_W) '$(srcdir)/feature-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/feature_test-feature-test.Tpo $(DEPDIR)/feature_test-feature-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='feature-test.c' object='feature_test-feature-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(feature_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o feature_test-feature-test.obj `if test -f 'feature-test.c'; then $(CYGPATH_W) 'feature-test.c'; else $(CYGPATH_W) '$(srcdir)/feature-test.c'; fi` + +makejournal-makejournal.o: makejournal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT makejournal-makejournal.o -MD -MP -MF $(DEPDIR)/makejournal-makejournal.Tpo -c -o makejournal-makejournal.o `test -f 'makejournal.c' || echo '$(srcdir)/'`makejournal.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/makejournal-makejournal.Tpo $(DEPDIR)/makejournal-makejournal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='makejournal.c' object='makejournal-makejournal.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o makejournal-makejournal.o `test -f 'makejournal.c' || echo '$(srcdir)/'`makejournal.c + +makejournal-makejournal.obj: makejournal.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT makejournal-makejournal.obj -MD -MP -MF $(DEPDIR)/makejournal-makejournal.Tpo -c -o makejournal-makejournal.obj `if test -f 'makejournal.c'; then $(CYGPATH_W) 'makejournal.c'; else $(CYGPATH_W) '$(srcdir)/makejournal.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/makejournal-makejournal.Tpo $(DEPDIR)/makejournal-makejournal.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='makejournal.c' object='makejournal-makejournal.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(makejournal_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o makejournal-makejournal.obj `if test -f 'makejournal.c'; then $(CYGPATH_W) 'makejournal.c'; else $(CYGPATH_W) '$(srcdir)/makejournal.c'; fi` + +pipelined/pipequeries-pipequeries.o: pipelined/pipequeries.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pipelined/pipequeries-pipequeries.o -MD -MP -MF pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo -c -o pipelined/pipequeries-pipequeries.o `test -f 'pipelined/pipequeries.c' || echo '$(srcdir)/'`pipelined/pipequeries.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo pipelined/$(DEPDIR)/pipequeries-pipequeries.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipelined/pipequeries.c' object='pipelined/pipequeries-pipequeries.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pipelined/pipequeries-pipequeries.o `test -f 'pipelined/pipequeries.c' || echo '$(srcdir)/'`pipelined/pipequeries.c + +pipelined/pipequeries-pipequeries.obj: pipelined/pipequeries.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pipelined/pipequeries-pipequeries.obj -MD -MP -MF pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo -c -o pipelined/pipequeries-pipequeries.obj `if test -f 'pipelined/pipequeries.c'; then $(CYGPATH_W) 'pipelined/pipequeries.c'; else $(CYGPATH_W) '$(srcdir)/pipelined/pipequeries.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) pipelined/$(DEPDIR)/pipequeries-pipequeries.Tpo pipelined/$(DEPDIR)/pipequeries-pipequeries.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pipelined/pipequeries.c' object='pipelined/pipequeries-pipequeries.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pipelined_pipequeries_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pipelined/pipequeries-pipequeries.obj `if test -f 'pipelined/pipequeries.c'; then $(CYGPATH_W) 'pipelined/pipequeries.c'; else $(CYGPATH_W) '$(srcdir)/pipelined/pipequeries.c'; fi` + +rpz/dnsrps-dnsrps.o: rpz/dnsrps.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rpz/dnsrps-dnsrps.o -MD -MP -MF rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo -c -o rpz/dnsrps-dnsrps.o `test -f 'rpz/dnsrps.c' || echo '$(srcdir)/'`rpz/dnsrps.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo rpz/$(DEPDIR)/dnsrps-dnsrps.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpz/dnsrps.c' object='rpz/dnsrps-dnsrps.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rpz/dnsrps-dnsrps.o `test -f 'rpz/dnsrps.c' || echo '$(srcdir)/'`rpz/dnsrps.c + +rpz/dnsrps-dnsrps.obj: rpz/dnsrps.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rpz/dnsrps-dnsrps.obj -MD -MP -MF rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo -c -o rpz/dnsrps-dnsrps.obj `if test -f 'rpz/dnsrps.c'; then $(CYGPATH_W) 'rpz/dnsrps.c'; else $(CYGPATH_W) '$(srcdir)/rpz/dnsrps.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) rpz/$(DEPDIR)/dnsrps-dnsrps.Tpo rpz/$(DEPDIR)/dnsrps-dnsrps.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rpz/dnsrps.c' object='rpz/dnsrps-dnsrps.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rpz_dnsrps_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rpz/dnsrps-dnsrps.obj `if test -f 'rpz/dnsrps.c'; then $(CYGPATH_W) 'rpz/dnsrps.c'; else $(CYGPATH_W) '$(srcdir)/rpz/dnsrps.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + -rm -rf pipelined/.libs pipelined/_libs + -rm -rf rndc/.libs rndc/_libs + -rm -rf rpz/.libs rpz/_libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +rpz.log: rpz + @p='rpz'; \ + b='rpz'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rpzrecurse.log: rpzrecurse + @p='rpzrecurse'; \ + b='rpzrecurse'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +serve-stale.log: serve-stale + @p='serve-stale'; \ + b='serve-stale'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +timeouts.log: timeouts + @p='timeouts'; \ + b='timeouts'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +upforwd.log: upforwd + @p='upforwd'; \ + b='upforwd'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +acl.log: acl + @p='acl'; \ + b='acl'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +additional.log: additional + @p='additional'; \ + b='additional'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +addzone.log: addzone + @p='addzone'; \ + b='addzone'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +allow-query.log: allow-query + @p='allow-query'; \ + b='allow-query'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +auth.log: auth + @p='auth'; \ + b='auth'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +autosign.log: autosign + @p='autosign'; \ + b='autosign'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +builtin.log: builtin + @p='builtin'; \ + b='builtin'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cacheclean.log: cacheclean + @p='cacheclean'; \ + b='cacheclean'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +camp.log: camp + @p='camp'; \ + b='camp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +case.log: case + @p='case'; \ + b='case'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +catz.log: catz + @p='catz'; \ + b='catz'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cds.log: cds + @p='cds'; \ + b='cds'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +chain.log: chain + @p='chain'; \ + b='chain'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +checkconf.log: checkconf + @p='checkconf'; \ + b='checkconf'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +checkds.log: checkds + @p='checkds'; \ + b='checkds'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +checknames.log: checknames + @p='checknames'; \ + b='checknames'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +checkzone.log: checkzone + @p='checkzone'; \ + b='checkzone'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cookie.log: cookie + @p='cookie'; \ + b='cookie'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +cpu.log: cpu + @p='cpu'; \ + b='cpu'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +database.log: database + @p='database'; \ + b='database'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dialup.log: dialup + @p='dialup'; \ + b='dialup'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +digdelv.log: digdelv + @p='digdelv'; \ + b='digdelv'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dispatch.log: dispatch + @p='dispatch'; \ + b='dispatch'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dlzexternal.log: dlzexternal + @p='dlzexternal'; \ + b='dlzexternal'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dns64.log: dns64 + @p='dns64'; \ + b='dns64'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dnssec.log: dnssec + @p='dnssec'; \ + b='dnssec'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dnstap.log: dnstap + @p='dnstap'; \ + b='dnstap'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +doth.log: doth + @p='doth'; \ + b='doth'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dsdigest.log: dsdigest + @p='dsdigest'; \ + b='dsdigest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +dyndb.log: dyndb + @p='dyndb'; \ + b='dyndb'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ecdsa.log: ecdsa + @p='ecdsa'; \ + b='ecdsa'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +eddsa.log: eddsa + @p='eddsa'; \ + b='eddsa'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ednscompliance.log: ednscompliance + @p='ednscompliance'; \ + b='ednscompliance'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +emptyzones.log: emptyzones + @p='emptyzones'; \ + b='emptyzones'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +enginepkcs11.log: enginepkcs11 + @p='enginepkcs11'; \ + b='enginepkcs11'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +filter-aaaa.log: filter-aaaa + @p='filter-aaaa'; \ + b='filter-aaaa'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +fetchlimit.log: fetchlimit + @p='fetchlimit'; \ + b='fetchlimit'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +formerr.log: formerr + @p='formerr'; \ + b='formerr'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +forward.log: forward + @p='forward'; \ + b='forward'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +geoip2.log: geoip2 + @p='geoip2'; \ + b='geoip2'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +glue.log: glue + @p='glue'; \ + b='glue'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +idna.log: idna + @p='idna'; \ + b='idna'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +include-multiplecfg.log: include-multiplecfg + @p='include-multiplecfg'; \ + b='include-multiplecfg'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +inline.log: inline + @p='inline'; \ + b='inline'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +integrity.log: integrity + @p='integrity'; \ + b='integrity'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ixfr.log: ixfr + @p='ixfr'; \ + b='ixfr'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +hooks.log: hooks + @p='hooks'; \ + b='hooks'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +host.log: host + @p='host'; \ + b='host'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +journal.log: journal + @p='journal'; \ + b='journal'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +kasp.log: kasp + @p='kasp'; \ + b='kasp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +keepalive.log: keepalive + @p='keepalive'; \ + b='keepalive'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +keyfromlabel.log: keyfromlabel + @p='keyfromlabel'; \ + b='keyfromlabel'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ksr.log: ksr + @p='ksr'; \ + b='ksr'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +legacy.log: legacy + @p='legacy'; \ + b='legacy'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +limits.log: limits + @p='limits'; \ + b='limits'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +logfileconfig.log: logfileconfig + @p='logfileconfig'; \ + b='logfileconfig'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +masterfile.log: masterfile + @p='masterfile'; \ + b='masterfile'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +masterformat.log: masterformat + @p='masterformat'; \ + b='masterformat'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +metadata.log: metadata + @p='metadata'; \ + b='metadata'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +mirror.log: mirror + @p='mirror'; \ + b='mirror'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +mkeys.log: mkeys + @p='mkeys'; \ + b='mkeys'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +multisigner.log: multisigner + @p='multisigner'; \ + b='multisigner'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +names.log: names + @p='names'; \ + b='names'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +notify.log: notify + @p='notify'; \ + b='notify'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nsec3.log: nsec3 + @p='nsec3'; \ + b='nsec3'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nslookup.log: nslookup + @p='nslookup'; \ + b='nslookup'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nsupdate.log: nsupdate + @p='nsupdate'; \ + b='nsupdate'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +nzd2nzf.log: nzd2nzf + @p='nzd2nzf'; \ + b='nzd2nzf'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +padding.log: padding + @p='padding'; \ + b='padding'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pending.log: pending + @p='pending'; \ + b='pending'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +proxy.log: proxy + @p='proxy'; \ + b='proxy'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +pipelined.log: pipelined + @p='pipelined'; \ + b='pipelined'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +qmin.log: qmin + @p='qmin'; \ + b='qmin'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +query-source.log: query-source + @p='query-source'; \ + b='query-source'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +reclimit.log: reclimit + @p='reclimit'; \ + b='reclimit'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +redirect.log: redirect + @p='redirect'; \ + b='redirect'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +resolver.log: resolver + @p='resolver'; \ + b='resolver'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rndc.log: rndc + @p='rndc'; \ + b='rndc'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rootkeysentinel.log: rootkeysentinel + @p='rootkeysentinel'; \ + b='rootkeysentinel'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rpzextra.log: rpzextra + @p='rpzextra'; \ + b='rpzextra'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rrchecker.log: rrchecker + @p='rrchecker'; \ + b='rrchecker'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rrl.log: rrl + @p='rrl'; \ + b='rrl'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rrsetorder.log: rrsetorder + @p='rrsetorder'; \ + b='rrsetorder'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +rsabigexponent.log: rsabigexponent + @p='rsabigexponent'; \ + b='rsabigexponent'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +runtime.log: runtime + @p='runtime'; \ + b='runtime'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sfcache.log: sfcache + @p='sfcache'; \ + b='sfcache'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +shutdown.log: shutdown + @p='shutdown'; \ + b='shutdown'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +smartsign.log: smartsign + @p='smartsign'; \ + b='smartsign'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +sortlist.log: sortlist + @p='sortlist'; \ + b='sortlist'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +spf.log: spf + @p='spf'; \ + b='spf'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +staticstub.log: staticstub + @p='staticstub'; \ + b='staticstub'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +statistics.log: statistics + @p='statistics'; \ + b='statistics'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +statschannel.log: statschannel + @p='statschannel'; \ + b='statschannel'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stress.log: stress + @p='stress'; \ + b='stress'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +stub.log: stub + @p='stub'; \ + b='stub'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +synthfromdnssec.log: synthfromdnssec + @p='synthfromdnssec'; \ + b='synthfromdnssec'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tcp.log: tcp + @p='tcp'; \ + b='tcp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tools.log: tools + @p='tools'; \ + b='tools'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +transport-acl.log: transport-acl + @p='transport-acl'; \ + b='transport-acl'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tsig.log: tsig + @p='tsig'; \ + b='tsig'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tsiggss.log: tsiggss + @p='tsiggss'; \ + b='tsiggss'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +ttl.log: ttl + @p='ttl'; \ + b='ttl'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +unknown.log: unknown + @p='unknown'; \ + b='unknown'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +verify.log: verify + @p='verify'; \ + b='verify'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +views.log: views + @p='views'; \ + b='views'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +wildcard.log: wildcard + @p='wildcard'; \ + b='wildcard'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xfer.log: xfer + @p='xfer'; \ + b='xfer'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +xferquota.log: xferquota + @p='xferquota'; \ + b='xferquota'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +zero.log: zero + @p='zero'; \ + b='zero'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +zonechecks.log: zonechecks + @p='zonechecks'; \ + b='zonechecks'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f pipelined/$(DEPDIR)/$(am__dirstamp) + -rm -f pipelined/$(am__dirstamp) + -rm -f rndc/$(DEPDIR)/$(am__dirstamp) + -rm -f rndc/$(am__dirstamp) + -rm -f rpz/$(DEPDIR)/$(am__dirstamp) + -rm -f rpz/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f ./$(DEPDIR)/feature_test-feature-test.Po + -rm -f ./$(DEPDIR)/makejournal-makejournal.Po + -rm -f pipelined/$(DEPDIR)/pipequeries-pipequeries.Po + -rm -f rndc/$(DEPDIR)/gencheck.Po + -rm -f rpz/$(DEPDIR)/dnsrps-dnsrps.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-recursive + +doc-am: doc-local + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f ./$(DEPDIR)/feature_test-feature-test.Po + -rm -f ./$(DEPDIR)/makejournal-makejournal.Po + -rm -f pipelined/$(DEPDIR)/pipequeries-pipequeries.Po + -rm -f rndc/$(DEPDIR)/gencheck.Po + -rm -f rpz/$(DEPDIR)/dnsrps-dnsrps.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +test: test-recursive + +test-am: test-local + +uninstall-am: + +unit: unit-recursive + +unit-am: unit-local + +.MAKE: $(am__recursive_targets) all check check-am install install-am \ + install-exec install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--depfiles check check-TESTS check-am clean clean-generic \ + clean-libtool clean-local clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am dist-hook distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ + test-am test-local uninstall uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Source tarballs must not contain configure/build artifacts. +dist-hook: + git clean -n -x -d | \ + grep -v "Makefile.in$$" | \ + sed -n "s|^Would remove \(.*\)|$(distdir)/\1|p" | \ + xargs -I{} rm -rf "{}" + +@HAVE_PERL_TRUE@@HAVE_PYTEST_FALSE@@HAVE_PYTHON_TRUE@check: +@HAVE_PERL_TRUE@@HAVE_PYTEST_FALSE@@HAVE_PYTHON_TRUE@ echo pytest is not available, no tests were ran +@HAVE_PERL_TRUE@@HAVE_PYTEST_FALSE@@HAVE_PYTHON_TRUE@ exit 1 +@HAVE_PERL_TRUE@@HAVE_PYTHON_FALSE@check: +@HAVE_PERL_TRUE@@HAVE_PYTHON_FALSE@ echo Python is not available, no tests were ran +@HAVE_PERL_TRUE@@HAVE_PYTHON_FALSE@ exit 1 +@HAVE_PERL_FALSE@check: +@HAVE_PERL_FALSE@ echo Perl is not available, no tests were ran +@HAVE_PERL_FALSE@ exit 1 + +test-local: check + +clean-local:: + -find -L . -mindepth 1 -maxdepth 1 -type d -name "*_*" -and -not -name "_common" -exec rm -rf {} \; + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/system/README.md b/bin/tests/system/README.md new file mode 100644 index 0000000..ee5ce8e --- /dev/null +++ b/bin/tests/system/README.md @@ -0,0 +1,483 @@ + + +# BIND9 System Test Framework + +This directory holds test environments for running bind9 system tests involving +multiple name servers. + +Each system test directory holds a set of scripts and configuration files to +test different parts of BIND. The directories are named for the aspect of BIND +they test, for example: + + dnssec/ DNSSEC tests + forward/ Forwarding tests + glue/ Glue handling tests + +etc. + +A system test directory must start with an alphabetic character and may not +contain any special characters. Only hyphen may be used as a word separator. + +Typically each set of tests sets up 2-5 name servers and then performs one or +more tests against them. Within the test subdirectory, each name server has a +separate subdirectory containing its configuration data. These subdirectories +are named "nsN" or "ansN" (where N is a number between 1 and 8, e.g. ns1, ans2 +etc.) + +The tests are completely self-contained and do not require access to the real +DNS. Generally, one of the test servers (usually ns1) is set up as a root +nameserver and is listed in the hints file of the others. + + +## Running the Tests + +### Prerequisites + +To run system tests, make sure you have the following dependencies installed: + +- python3 +- pytest +- perl +- dnspython +- pytest-xdist (for parallel execution) +- python-jinja2 + +Individual system tests might also require additional dependencies. If those +are missing, the affected tests will be skipped and should produce a message +specifying what additional prerequisites they expect. + +### Network Setup + +To enable all servers to run on the same machine, they bind to separate virtual +IP addresses on the loopback interface. ns1 runs on 10.53.0.1, ns2 on +10.53.0.2, etc. Before running any tests, you must set up these addresses by +running the command + + sh ifconfig.sh up + +as root. The interfaces can be removed by executing the command: + + sh ifconfig.sh down + +... also as root. + +The servers use unprivileged ports (above 1024) instead of the usual port 53, +so they can be run without root privileges once the interfaces have been set +up. + +**Note for MacOS Users** + +If you wish to make the interfaces survive across reboots, copy +org.isc.bind.system and org.isc.bind.system.plist to /Library/LaunchDaemons +then run + + launchctl load /Library/LaunchDaemons/org.isc.bind.system.plist + +... as root. + +### Running a Single Test + +The recommended way is to use pytest and its test selection facilities: + + pytest -k + +Using `-k` to specify a pattern allows to run a single pytest test case within +a system test. E.g. you can use `-k test_sslyze_dot` to execute just the +`test_sslyze_dot()` function from `doth/tests_sslyze.py`. + +However, using the `-k` pattern might pick up more tests than intended. You can +use the `--collect-only` option to check the list of tests which match you `-k` +pattern. If you just want to execute all system tests within a single test +directory, you can also use the utility script: + + ./run.sh system_test_dir_name + +### Running All the System Tests + +Issuing plain `pytest` command without any argument will execute all tests +sequentially. To execute them in parallel, ensure you have pytest-xdist +installed and run: + + pytest [-n ] + +Alternately, using the make command is also supported: + + make [-j numproc] test + +### rr + +When running system tests, named can be run under the rr tool. rr records a +trace to the $system_test/nsX/named-Y/ directory, which can be later used to +replay named. To enable this, execute start.pl with the USE_RR environment +variable set. + +### Test Artifacts + +Each test module is executed inside a unique temporary directory which contains +all the artifacts from the test run. If the tests succeed, they are deleted by +default. To override this behaviour, pass `--noclean` to pytest. + +The directory name starts with the system test name, followed by `_tmp_XXXXXX`, +i.e. `dns64_tmp_r07vei9s` for `dns64` test run. Since this name changes each +run, a convenience symlink that has a stable name is also created. It points to +the latest test artifacts directory and has a form of `dns64_sh_dns64` +(depending on the particular test module). + +To clean up the temporary directories and symlinks, run `make clean-local` in +the system test directory. + +The following test artifacts are typically available: + +- pytest.log.txt: main log file with test output +- files generated by the test itself, e.g. output from "dig" and "rndc" +- files produced by named, other tools or helper scripts + + +## Writing System Tests + +### File Overview + +Tests are organized into system test directories which may hold one or more +test modules (python files). Each module may have multiple test cases. The +system test directories may contain the following standard files: + +- `tests_*.py`: These python files are picked up by pytest as modules. If they + contain any test functions, they're added to the test suite. + +- `*.j2`: These jinja2 templates can be used for configuration files or any + other files which require certain variables filled in, e.g. ports from the + environment variables. During test setup, the pytest runner will automatically + fill those in and strip the filename extension .j2, e.g. `ns1/named.conf.j2` + becomes `ns1/named.conf`. When using advanced templating to conditionally + include/omit entire sections or when filling in custom variables used for the + test, ensure the templates always include the defaults. If you don't need the + file to be auto-templated during test setup, use `.j2.manual` instead and then + no defaults are needed. + +- `setup.sh`: This sets up the preconditions for the tests. + +- `tests.sh`: Any shell-based tests are located within this file. Runs the + actual tests. + +- `tests_sh_*.py`: A glue file for the pytest runner for executing shell tests. + +- `ns`: These subdirectories contain test name servers that can be queried + or can interact with each other. The value of N indicates the address the + server listens on: for example, ns2 listens on 10.53.0.2, and ns4 on + 10.53.0.4. All test servers use an unprivileged port, so they don't need to + run as root. These servers log at the highest debug level and the log is + captured in the file "named.run". + +- `ans`: Like ns[X], but these are simple mock name servers implemented in + Perl or Python. They are generally programmed to misbehave in ways named + would not so as to exercise named's ability to interoperate with badly + behaved name servers. + +### Module Scope + +A module is a python file which contains test functions. Every system +test directory may contain multiple modules (i.e. tests_*.py files). + +The server setup/teardown is performed for each module. Bundling test cases +together inside a single module may save some resources. However, test cases +inside a single module can't be executed in parallel. + +It is possible to execute different modules defined within a single system test +directory in parallel. This is possible thanks to executing the tests inside a +temporary directory and proper port assignment to ensure there won't be any +conflicts. + +### Port Usage + +In order for the tests to run in parallel, each test requires a unique set of +ports. This is ensured by the pytest runner, which assigns a unique set of +ports to each test module. + +Inside the python tests, it is possible to use the `ports` fixture to get the +assigned port numbers. They're also set as environment variables. These include: + +- `PORT`: used as the basic dns port +- `TLSPORT`: used as the port for DNS-over-TLS +- `HTTPPORT`, `HTTPSPORT`: used as the ports for DNS-over-HTTP +- `CONTROLPORT`: used as the RNDC control port +- `EXTRAPORT1` through `EXTRAPORT8`: additional ports that can be used as needed + +### Logging + +Each module has a separate log which will be saved as pytest.log.txt in the +temporary directory in which the test is executed. This log includes messages +for this module setup/teardown as well as any logging from the tests. Logging +level DEBUG and above will be present in this log. + +In general, any log messages using INFO or above will also be printed out +during pytest execution. In CI, the pytest output is also saved to +pytest.out.txt in the bin/tests/system directory. + +### Adding a Test to the System Test Suite + +Once a test has been created it will be automatically picked up by the pytest +runner if it upholds the convention expected by pytest (especially when it comes +to naming files and test functions). + +However, if a new system test directory is created, it also needs to be added to +`TESTS` in `Makefile.am`, in order to work with `make check`. + + +## Test Files + +### setup.sh + +This script is responsible for setting up the configuration files used in the +test. It is used by both the python and shell tests. It is interpreted just +before the servers are started up for each test module. + +To cope with the varying port number, ports are not hard-coded into +configuration files (or, for that matter, scripts that emulate nameservers). +Instead, setup.sh is responsible for editing the configuration files to set the +port numbers. + +To do this, configuration files should be supplied in the form of templates +containing tokens identifying ports. The tokens have the same name as the +environment variables listed above, but are prefixed and suffixed by the "@" +symbol. For example, a fragment of a configuration file template might look +like: + + controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; + }; + + options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + allow-new-zones yes; + }; + +setup.sh should copy the template to the desired filename using the +"copy_setports" shell function defined in "conf.sh", i.e. + + copy_setports ns1/named.conf.in ns1/named.conf + +This replaces tokens like @PORT@ with the contents of the environment variables +listed above. setup.sh should do this for all configuration files required when +the test starts. + +("setup.sh" should also use this method for replacing the tokens in any Perl or +Python name servers used in the test.) + +### tests_*.py + +These are test modules containing tests written in python. Every test is a +function which begins with the name `test_` (according to pytest convention). It +is possible to pass fixtures to the test function by specifying their name as +function arguments. Fixtures are used to provide context to the tests, e.g.: + +- `ports` is a dictionary with assigned port numbers + +### tests_sh_*.py + +These are glue files that are required to execute shell based tests (see below). +These modules shouldn't contain any python tests (use a separate file instead). + +### tests.sh + +This is the test file for shell based tests. + + +## Nameservers + +As noted earlier, a system test will involve a number of nameservers. These +will be either instances of named, or special servers written in a language +such as Perl or Python. + +For the former, the version of "named" being run is that in the "bin/named" +directory in the tree holding the tests (i.e. if "make test" is being run +immediately after "make", the version of "named" used is that just built). The +configuration files, zone files etc. for these servers are located in +subdirectories of the test directory named "nsN", where N is a small integer. +The latter are special nameservers, mostly used for generating deliberately bad +responses, located in subdirectories named "ansN" (again, N is an integer). +In addition to configuration files, these directories should hold the +appropriate script files as well. + +Note that the "N" for a particular test forms a single number space, e.g. if +there is an "ns2" directory, there cannot be an "ans2" directory as well. +Ideally, the directory numbers should start at 1 and work upwards. + +When tests are executed, pytest takes care of the test setup and teardown. It +looks for any `nsN` and `ansN` directories in the system test directory and +starts those servers. + +### `named` Command-Line Options + +By default, `named` server is started with the following options: + + -c named.conf Specifies the configuration file to use (so by implication, + each "nsN" nameserver's configuration file must be called + named.conf). + + -d 99 Sets the maximum debugging level. + + -D The "-D" option sets a string used to identify the + nameserver in a process listing. In this case, the string + is the name of the subdirectory. + + -g Runs the server in the foreground and logs everything to + stderr. + + -m record + Turns on these memory usage debugging flags. + +All output is sent to a file called `named.run` in the nameserver directory. + +The options used to start named can be altered. There are a couple ways of +doing this. `start.pl` checks the methods in a specific order: if a check +succeeds, the options are set and any other specification is ignored. In order, +these are: + +1. Specifying options to `start.pl` or `start_server` shell utility function + after the name of the test directory, e.g. + + start_server --noclean --restart --port ${PORT} ns1 -- "-D xfer-ns1 -T transferinsecs -T transferslowly" + +2. Including a file called "named.args" in the "nsN" directory. If present, +the contents of the first non-commented, non-blank line of the file are used as +the named command-line arguments. The rest of the file is ignored. + +3. Tweaking the default command line arguments with "-T" options. This flag is +used to alter the behavior of BIND for testing and is not documented in the +ARM. The presence of certain files in the "nsN" directory adds flags to +the default command line (the content of the files is irrelevant - it +is only the presence that counts): + + named.noaa Appends "-T noaa" to the command line, which causes + "named" to never set the AA bit in an answer. + + named.dropedns Adds "-T dropedns" to the command line, which causes + "named" to recognise EDNS options in messages, but drop + messages containing them. + + named.maxudp1460 Adds "-T maxudp1460" to the command line, setting the + maximum UDP size handled by named to 1460. + + named.maxudp512 Adds "-T maxudp512" to the command line, setting the + maximum UDP size handled by named to 512. + + named.noedns Appends "-T noedns" to the command line, which disables + recognition of EDNS options in messages. + + named.notcp Adds "-T notcp", which disables TCP in "named". + + named.soa Appends "-T nosoa" to the command line, which disables + the addition of SOA records to negative responses (or to + the additional section if the response is triggered by RPZ + rewriting). + +### Running Nameservers Interactively + +In order to debug the nameservers, you can let pytest perform the nameserver +setup and interact with the servers before the test starts, or even at specific +points during the test, using the `--trace` option to drop you into pdb debugger +which pauses the execution of the tests, while keeping the server state intact: + + pytest -k dns64 --trace + + +## Developer Notes + +### Test discovery and collection + +There are two distinct types of system tests. The first is a shell script +tests.sh containing individual test cases executed sequentially and the +success/failure is determined by return code. The second type is a regular +pytest file which contains test functions. + +Dealing with the regular pytest files doesn't require any special consideration +as long as the naming conventions are met. Discovering the tests.sh tests is +more complicated. + +The chosen solution is to add a bit of glue for each system test. For every +tests.sh, there is an accompanying tests_sh_*.py file that contains a test +function which utilizes a custom run_tests_sh fixture to call the tests.sh +script. Other solutions were tried and eventually rejected. While this +introduces a bit of extra glue, it is the most portable, compatible and least +complex solution. + +### Compatibility with older pytest version + +Keep in mind that the pytest runner must work with ancient versions of pytest. +When implementing new features, it is advisable to check feature support in +pytest and pytest-xdist in older distributions first. + +As a general rule, any changes to the pytest runner need to keep working on all +platforms in CI that use the pytest runner. As of 2023-11-14, the oldest +supported version is whatever is available in EL8. + +We may need to add more compat code eventually to handle breaking upstream +changes. For example, using request.fspath attribute is already deprecated in +latest pytest. + +### Format of Shell Test Output + +Shell-based tests have the following format of output: + + :: [()] + +e.g. + + I:catz:checking that dom1.example is not served by primary (1) + +The meanings of the fields are as follows: + + +This indicates the type of message. This is one of: + + S Start of the test + A Start of test (retained for backwards compatibility) + T Start of test (retained for backwards compatibility) + E End of the test + I Information. A test will typically output many of these messages + during its run, indicating test progress. Note that such a message may + be of the form "I:testname:failed", indicating that a sub-test has + failed. + R Result. Each test will result in one such message, which is of the + form: + + R:: + + where is one of: + + PASS The test passed + FAIL The test failed + SKIPPED The test was not run, usually because some + prerequisites required to run the test are missing. + + +This is the name of the temporary test directory from which the message +emanated, which is also the name of the subdirectory holding the test files. + + +This is text output by the test during its execution. + +() +If present, this will correlate with a file created by the test. The tests +execute commands and route the output of each command to a file. The name of +this file depends on the command and the test, but will usually be of the form: + + .out. + +e.g. nsupdate.out.test28, dig.out.q3. This aids diagnosis of problems by +allowing the output that caused the problem message to be identified. + diff --git a/bin/tests/system/_common/controls.conf.in b/bin/tests/system/_common/controls.conf.in new file mode 100644 index 0000000..1db9286 --- /dev/null +++ b/bin/tests/system/_common/controls.conf.in @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + diff --git a/bin/tests/system/_common/rndc.conf b/bin/tests/system/_common/rndc.conf new file mode 100644 index 0000000..26420d5 --- /dev/null +++ b/bin/tests/system/_common/rndc.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + default-key "rndc_key"; +}; + +key rndc_key { + algorithm hmac-sha256; + secret "1234abcd8765"; +}; + +/* Regresssion test for [GL #4991] */ +server example.com { + key rndc-key; + addresses { localhost; 127.0.0.1; ::1; }; +}; diff --git a/bin/tests/system/_common/rndc.key b/bin/tests/system/_common/rndc.key new file mode 100644 index 0000000..3ef41c3 --- /dev/null +++ b/bin/tests/system/_common/rndc.key @@ -0,0 +1,15 @@ +/* + * Copyright (C) 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; diff --git a/bin/tests/system/_common/root.hint b/bin/tests/system/_common/root.hint new file mode 100644 index 0000000..e0f186c --- /dev/null +++ b/bin/tests/system/_common/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/_common/root.hint.blackhole b/bin/tests/system/_common/root.hint.blackhole new file mode 100644 index 0000000..d90ac89 --- /dev/null +++ b/bin/tests/system/_common/root.hint.blackhole @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS ns99.root-servers.nil. +ns99.root-servers.nil. IN A 10.53.0.99 diff --git a/bin/tests/system/acl/ns2/named1.conf.in b/bin/tests/system/acl/ns2/named1.conf.in new file mode 100644 index 0000000..59d3897 --- /dev/null +++ b/bin/tests/system/acl/ns2/named1.conf.in @@ -0,0 +1,62 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "tsigzone" { + type primary; + file "tsigzone.db"; + allow-transfer { !key one; any; }; +}; diff --git a/bin/tests/system/acl/ns2/named2.conf.in b/bin/tests/system/acl/ns2/named2.conf.in new file mode 100644 index 0000000..116a298 --- /dev/null +++ b/bin/tests/system/acl/ns2/named2.conf.in @@ -0,0 +1,66 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "tsigzone" { + type primary; + file "tsigzone.db"; + /* + * 0a00::/8 and 10/8 are the same bits, but different address + * families. This should *not* match IPv4 queries from 10.*. + */ + allow-transfer { 0a00::/8; !10/8; key one; }; +}; diff --git a/bin/tests/system/acl/ns2/named3.conf.in b/bin/tests/system/acl/ns2/named3.conf.in new file mode 100644 index 0000000..5688ab2 --- /dev/null +++ b/bin/tests/system/acl/ns2/named3.conf.in @@ -0,0 +1,75 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key three { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +acl reject { + !key one; !key two; any; +}; + +acl accept { + 10.53.0.1; 10.53.0.2; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "tsigzone" { + type primary; + file "tsigzone.db"; + allow-transfer { !reject; accept; }; +}; diff --git a/bin/tests/system/acl/ns2/named4.conf.in b/bin/tests/system/acl/ns2/named4.conf.in new file mode 100644 index 0000000..b0fdd62 --- /dev/null +++ b/bin/tests/system/acl/ns2/named4.conf.in @@ -0,0 +1,74 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +acl rejectkeys { + !key one; !key two; any; +}; + +acl rejectaddrs { + !10.53.0.1; !10.53.0.2; any; +}; + +acl check1 { !key one; 10.53.0.1; }; + +acl check2 { !key two; 10.53.0.2; }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "tsigzone" { + type primary; + file "tsigzone.db"; + allow-transfer { !rejectkeys; !rejectaddrs; !check1; !check2; any; }; +}; diff --git a/bin/tests/system/acl/ns2/named5.conf.in b/bin/tests/system/acl/ns2/named5.conf.in new file mode 100644 index 0000000..b4338da --- /dev/null +++ b/bin/tests/system/acl/ns2/named5.conf.in @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; + allow-query-on { 10.53.0.2; }; + blackhole { 10.53.0.8; }; +}; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "tsigzone" { + type primary; + file "tsigzone.db"; + allow-transfer { !key one; any; }; +}; diff --git a/bin/tests/system/acl/ns3/example.db b/bin/tests/system/acl/ns3/example.db new file mode 100644 index 0000000..34fe9e5 --- /dev/null +++ b/bin/tests/system/acl/ns3/example.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 diff --git a/bin/tests/system/acl/ns3/named.conf.in b/bin/tests/system/acl/ns3/named.conf.in new file mode 100644 index 0000000..31d3526 --- /dev/null +++ b/bin/tests/system/acl/ns3/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion no; + notify no; + allow-new-zones yes; + allow-transfer { none; }; + dnssec-validation no; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/acl/ns4/example.db b/bin/tests/system/acl/ns4/example.db new file mode 100644 index 0000000..91c8702 --- /dev/null +++ b/bin/tests/system/acl/ns4/example.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.4 diff --git a/bin/tests/system/acl/ns4/existing.db b/bin/tests/system/acl/ns4/existing.db new file mode 100644 index 0000000..91c8702 --- /dev/null +++ b/bin/tests/system/acl/ns4/existing.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.4 diff --git a/bin/tests/system/acl/ns4/named.conf.in b/bin/tests/system/acl/ns4/named.conf.in new file mode 100644 index 0000000..9b769d1 --- /dev/null +++ b/bin/tests/system/acl/ns4/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; + notify no; + allow-new-zones yes; + allow-transfer { none; }; + dnssec-validation no; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +zone "existing" { + type primary; + file "existing.db"; +}; diff --git a/bin/tests/system/acl/setup.sh b/bin/tests/system/acl/setup.sh new file mode 100644 index 0000000..f563d78 --- /dev/null +++ b/bin/tests/system/acl/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/example.db +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 3 >ns2/tsigzone.db +copy_setports ns2/named1.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf diff --git a/bin/tests/system/acl/tests.sh b/bin/tests/system/acl/tests.sh new file mode 100644 index 0000000..f98bc34 --- /dev/null +++ b/bin/tests/system/acl/tests.sh @@ -0,0 +1,283 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +status=0 +t=0 + +echo_i "testing basic ACL processing" +# key "one" should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +# any other key should be fine +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +copy_setports ns2/named2.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 +sleep 5 + +# prefix 10/8 should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +# any other address should work, as long as it sends key "one" +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 127.0.0.1 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 127.0.0.1 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +echo_i "testing nested ACL processing" +# all combinations of 10.53.0.{1|2} with key {one|two}, should succeed +copy_setports ns2/named3.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 +sleep 5 + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.2 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.2 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# but only one or the other should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 127.0.0.1 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.2 axfr >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $tt failed" + status=1 +} + +# and other values? right out +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 127.0.0.1 axfr -y "${DEFAULT_HMAC}:three:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +# now we only allow 10.53.0.1 *and* key one, or 10.53.0.2 *and* key two +copy_setports ns2/named4.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 +sleep 5 + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.2 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# should succeed +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 && { + echo_i "test $t failed" + status=1 +} + +# should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.2 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +# should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.1 axfr -y "${DEFAULT_HMAC}:two:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +# should fail +t=$((t + 1)) +$DIG $DIGOPTS tsigzone. \ + @10.53.0.2 -b 10.53.0.3 axfr -y "${DEFAULT_HMAC}:one:1234abcd8765" >dig.out.${t} +grep "^;" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +echo_i "testing allow-query-on ACL processing" +copy_setports ns2/named5.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 +sleep 5 +t=$((t + 1)) +$DIG -p ${PORT} +tcp soa example. \ + @10.53.0.2 -b 10.53.0.3 >dig.out.${t} +grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed" + status=1 +} + +echo_i "testing blackhole ACL processing" +t=$((t + 1)) +ret=0 +$DIG -p ${PORT} +tcp soa example. \ + @10.53.0.2 -b 10.53.0.3 >dig.out.1.${t} +grep "status: NOERROR" dig.out.1.${t} >/dev/null 2>&1 || ret=1 +$DIG -p ${PORT} +tcp soa example. \ + @10.53.0.2 -b 10.53.0.8 >dig.out.2.${t} && ret=1 +grep "status: NOERROR" dig.out.2.${t} >/dev/null 2>&1 && ret=1 +grep "communications error" dig.out.2.${t} >/dev/null 2>&1 || ret=1 +$DIG -p ${PORT} soa example. \ + @10.53.0.2 -b 10.53.0.3 >dig.out.3.${t} +grep "status: NOERROR" dig.out.3.${t} >/dev/null 2>&1 || ret=1 +$DIG -p ${PORT} soa example. \ + @10.53.0.2 -b 10.53.0.8 >dig.out.4.${t} && ret=1 +grep "status: NOERROR" dig.out.4.${t} >/dev/null 2>&1 && ret=1 +grep "timed out" dig.out.4.${t} >/dev/null 2>&1 || ret=1 +grep ";; no servers could be reached" dig.out.4.${t} >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# AXFR tests against ns3 + +echo_i "testing allow-transfer ACLs against ns3 (no existing zones)" + +echo_i "calling addzone example.com on ns3" +$RNDCCMD 10.53.0.3 addzone 'example.com {type primary; file "example.db"; }; ' +sleep 1 + +t=$((t + 1)) +ret=0 +echo_i "checking AXFR of example.com from ns3 with ACL allow-transfer { none; }; (${t})" +$DIG -p ${PORT} @10.53.0.3 example.com axfr >dig.out.${t} 2>&1 +grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "calling rndc reconfig" +rndc_reconfig ns3 10.53.0.3 + +sleep 1 + +t=$((t + 1)) +ret=0 +echo_i "re-checking AXFR of example.com from ns3 with ACL allow-transfer { none; }; (${t})" +$DIG -p ${PORT} @10.53.0.3 example.com axfr >dig.out.${t} 2>&1 +grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# AXFR tests against ns4 + +echo_i "testing allow-transfer ACLs against ns4 (1 pre-existing zone)" + +echo_i "calling addzone example.com on ns4" +$RNDCCMD 10.53.0.4 addzone 'example.com {type primary; file "example.db"; }; ' +sleep 1 + +t=$((t + 1)) +ret=0 +echo_i "checking AXFR of example.com from ns4 with ACL allow-transfer { none; }; (${t})" +$DIG -p ${PORT} @10.53.0.4 example.com axfr >dig.out.${t} 2>&1 +grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "calling rndc reconfig" +rndc_reconfig ns4 10.53.0.4 + +sleep 1 + +t=$((t + 1)) +ret=0 +echo_i "re-checking AXFR of example.com from ns4 with ACL allow-transfer { none; }; (${t})" +$DIG -p ${PORT} @10.53.0.4 example.com axfr >dig.out.${t} 2>&1 +grep "Transfer failed." dig.out.${t} >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/acl/tests_sh_acl.py b/bin/tests/system/acl/tests_sh_acl.py new file mode 100644 index 0000000..9a6bc91 --- /dev/null +++ b/bin/tests/system/acl/tests_sh_acl.py @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + "ns*/_default.nzd*", + "ns*/_default.nzf*", + "ns2/example.db", + "ns2/tsigzone.db", + ] +) + + +def test_acl(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/additional/ns1/mx.db b/bin/tests/system/additional/ns1/mx.db new file mode 100644 index 0000000..6305e8b --- /dev/null +++ b/bin/tests/system/additional/ns1/mx.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 + MX 0 mail +ns1 A 10.53.0.1 +mail A 1.2.3.4 +_25._tcp.mail TLSA 3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383 diff --git a/bin/tests/system/additional/ns1/named.args b/bin/tests/system/additional/ns1/named.args new file mode 100644 index 0000000..7545344 --- /dev/null +++ b/bin/tests/system/additional/ns1/named.args @@ -0,0 +1,2 @@ +# this server runs named with only one worker thread +-m record -c named.conf -d 99 -D additional-ns1 -g -n 1 -T maxcachesize=2097152 diff --git a/bin/tests/system/additional/ns1/named1.conf.in b/bin/tests/system/additional/ns1/named1.conf.in new file mode 100644 index 0000000..0d07e54 --- /dev/null +++ b/bin/tests/system/additional/ns1/named1.conf.in @@ -0,0 +1,62 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + recursion no; + dnssec-validation no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + minimal-responses yes; +}; + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "rt.example" { + type primary; + file "rt.db"; +}; + +zone "naptr.example" { + type primary; + file "naptr.db"; +}; + +zone "rt2.example" { + type primary; + file "rt2.db"; +}; + +zone "naptr2.example" { + type primary; + file "naptr2.db"; +}; + +zone "nid.example" { + type primary; + file "nid.db"; +}; diff --git a/bin/tests/system/additional/ns1/named2.conf.in b/bin/tests/system/additional/ns1/named2.conf.in new file mode 100644 index 0000000..efed639 --- /dev/null +++ b/bin/tests/system/additional/ns1/named2.conf.in @@ -0,0 +1,62 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + recursion no; + dnssec-validation no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + minimal-responses no; +}; + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "rt.example" { + type primary; + file "rt.db"; +}; + +zone "naptr.example" { + type primary; + file "naptr.db"; +}; + +zone "rt2.example" { + type primary; + file "rt2.db"; +}; + +zone "naptr2.example" { + type primary; + file "naptr2.db"; +}; + +zone "nid.example" { + type primary; + file "nid.db"; +}; diff --git a/bin/tests/system/additional/ns1/named3.conf.in b/bin/tests/system/additional/ns1/named3.conf.in new file mode 100644 index 0000000..0ff7125 --- /dev/null +++ b/bin/tests/system/additional/ns1/named3.conf.in @@ -0,0 +1,63 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + recursion no; + dnssec-validation no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + minimal-any yes; + minimal-responses no-auth; +}; + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "rt.example" { + type primary; + file "rt.db"; +}; + +zone "naptr.example" { + type primary; + file "naptr.db"; +}; + +zone "rt2.example" { + type primary; + file "rt2.db"; +}; + +zone "naptr2.example" { + type primary; + file "naptr2.db"; +}; + +zone "nid.example" { + type primary; + file "nid.db"; +}; diff --git a/bin/tests/system/additional/ns1/named4.conf.in b/bin/tests/system/additional/ns1/named4.conf.in new file mode 100644 index 0000000..8c53086 --- /dev/null +++ b/bin/tests/system/additional/ns1/named4.conf.in @@ -0,0 +1,72 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + recursion no; + dnssec-validation no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + minimal-responses no-auth-recursive; +}; + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "mx.example" { + type primary; + file "mx.db"; +}; + +zone "srv.example" { + type primary; + file "srv.db"; +}; + +zone "rt.example" { + type primary; + file "rt.db"; +}; + +zone "naptr.example" { + type primary; + file "naptr.db"; +}; + +zone "rt2.example" { + type primary; + file "rt2.db"; +}; + +zone "naptr2.example" { + type primary; + file "naptr2.db"; +}; + +zone "nid.example" { + type primary; + file "nid.db"; +}; diff --git a/bin/tests/system/additional/ns1/naptr.db b/bin/tests/system/additional/ns1/naptr.db new file mode 100644 index 0000000..51d3c85 --- /dev/null +++ b/bin/tests/system/additional/ns1/naptr.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 + +nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server +server SRV 0 0 5061 server +server A 192.168.2.9 +server AAAA 192::9 diff --git a/bin/tests/system/additional/ns1/naptr2.db b/bin/tests/system/additional/ns1/naptr2.db new file mode 100644 index 0000000..78ca4ad --- /dev/null +++ b/bin/tests/system/additional/ns1/naptr2.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 + +nap IN NAPTR 50 50 "S" "SIPS+D2T" "" server.hang3a.zone. +www AAAA 192::99 +www A 192.168.2.99 +www X25 100099 diff --git a/bin/tests/system/additional/ns1/nid.db b/bin/tests/system/additional/ns1/nid.db new file mode 100644 index 0000000..f76b52e --- /dev/null +++ b/bin/tests/system/additional/ns1/nid.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 + +ns1 NID 2 0:0:0:0 +ns1 L64 2 0:0:0:0 +ns1 L32 2 0.0.0.0 +nid2 NID 2 0:0:0:1 +nid2 LP 2 ns1 diff --git a/bin/tests/system/additional/ns1/root.db b/bin/tests/system/additional/ns1/root.db new file mode 100644 index 0000000..94cfdda --- /dev/null +++ b/bin/tests/system/additional/ns1/root.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. IN SOA ns2. hostmaster ( 2 8H 2H 4W 1D); +. NS ns1.rt.example. +. NS ns2.rt.example. +ns1.rt.example. A 10.53.0.1 +ns2.rt.example. A 10.53.0.2 +rt.example. NS ns1. +naptr.example. NS ns1. +rt2.example. NS ns1. +naptr2.example. NS ns1. +nid.example. NS ns1. diff --git a/bin/tests/system/additional/ns1/rt.db b/bin/tests/system/additional/ns1/rt.db new file mode 100644 index 0000000..c858f0d --- /dev/null +++ b/bin/tests/system/additional/ns1/rt.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 + NS ns1.rt2.example. +ns1 A 10.53.0.1 + +rt RT 2 www +www AAAA 192::99 +www A 192.168.2.99 +www X25 100099 diff --git a/bin/tests/system/additional/ns1/rt2.db b/bin/tests/system/additional/ns1/rt2.db new file mode 100644 index 0000000..b61a198 --- /dev/null +++ b/bin/tests/system/additional/ns1/rt2.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 + +rt RT 2 www.hang3b.zone. +server SRV 0 0 5061 server +server A 192.168.2.9 +server AAAA 192::9 diff --git a/bin/tests/system/additional/ns1/srv.db b/bin/tests/system/additional/ns1/srv.db new file mode 100644 index 0000000..0aee21a --- /dev/null +++ b/bin/tests/system/additional/ns1/srv.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 +_xmpp-client._tcp SRV 1 0 5222 server +server A 1.2.3.4 +_5222._tcp.server TLSA 3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383 diff --git a/bin/tests/system/additional/ns2/named.conf.in b/bin/tests/system/additional/ns2/named.conf.in new file mode 100644 index 0000000..ed43ca6 --- /dev/null +++ b/bin/tests/system/additional/ns2/named.conf.in @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + recursion no; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + notify no; + minimal-responses yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/additional/ns2/root.db b/bin/tests/system/additional/ns2/root.db new file mode 100644 index 0000000..728bdde --- /dev/null +++ b/bin/tests/system/additional/ns2/root.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. IN SOA ns2. hostmaster ( 2 8H 2H 4W 1D); +. NS ns2. +ns1. A 10.53.0.1 +ns2. A 10.53.0.2 +rt.example. NS ns1. +naptr.example. NS ns1. +rt2.example. NS ns1. +naptr2.example. NS ns1. +nid.example. NS ns1. + diff --git a/bin/tests/system/additional/ns3/ex.db b/bin/tests/system/additional/ns3/ex.db new file mode 100644 index 0000000..c893a84 --- /dev/null +++ b/bin/tests/system/additional/ns3/ex.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 + NS ns1.ex2. +ns1 A 10.53.0.1 diff --git a/bin/tests/system/additional/ns3/ex2.db b/bin/tests/system/additional/ns3/ex2.db new file mode 100644 index 0000000..f9039cf --- /dev/null +++ b/bin/tests/system/additional/ns3/ex2.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA ns1 hostmaster ( 2 8H 2H 4W 1D ); + NS ns1 +ns1 A 10.53.0.1 diff --git a/bin/tests/system/additional/ns3/named.conf.in b/bin/tests/system/additional/ns3/named.conf.in new file mode 100644 index 0000000..f47a380 --- /dev/null +++ b/bin/tests/system/additional/ns3/named.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + minimal-responses no; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "ex" { + type primary; + file "ex.db"; +}; + +zone "ex2" { + type primary; + file "ex2.db"; +}; diff --git a/bin/tests/system/additional/ns3/root.hint b/bin/tests/system/additional/ns3/root.hint new file mode 100644 index 0000000..ef6ee6f --- /dev/null +++ b/bin/tests/system/additional/ns3/root.hint @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. NS ns2. +ns2. A 10.53.0.2 diff --git a/bin/tests/system/additional/setup.sh b/bin/tests/system/additional/setup.sh new file mode 100644 index 0000000..d117b4c --- /dev/null +++ b/bin/tests/system/additional/setup.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf diff --git a/bin/tests/system/additional/tests.sh b/bin/tests/system/additional/tests.sh new file mode 100644 index 0000000..e1b0cfb --- /dev/null +++ b/bin/tests/system/additional/tests.sh @@ -0,0 +1,405 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +status=0 +n=0 + +dotests() { + n=$((n + 1)) + echo_i "test with RT, single zone (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t RT rt.rt.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with RT, two zones (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t RT rt.rt2.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NAPTR, single zone (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t NAPTR nap.naptr.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NAPTR, two zones (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t NAPTR nap.hang3b.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with LP (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t LP nid2.nid.example @10.53.0.1 >dig.out.$n || ret=1 + case $minimal in + no) + grep -w "NS" dig.out.$n >/dev/null || ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + yes) + grep -w "NS" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + ;; + no-auth) + grep -w "NS" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + no-auth-recursive) + grep -w "NS" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + esac + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NID (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t NID ns1.nid.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $minimal = no ]; then + # change && to || when we support NID additional processing + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + else + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + fi + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NID + LP (+rec) ($n)" + ret=0 + $DIG $DIGOPTS +rec -t NID nid2.nid.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $minimal = no ]; then + # change && to || when we support NID additional processing + grep -w "LP" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + else + grep -w "LP" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + fi + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with RT, single zone (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t RT rt.rt.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with RT, two zones (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t RT rt.rt2.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NAPTR, single zone (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t NAPTR nap.naptr.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NAPTR, two zones (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t NAPTR nap.hang3b.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with LP (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t LP nid2.nid.example @10.53.0.1 >dig.out.$n || ret=1 + case $minimal in + no) + grep -w "NS" dig.out.$n >/dev/null || ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + yes) + grep -w "NS" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + ;; + no-auth) + grep -w "NS" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + no-auth-recursive) + grep -w "NS" dig.out.$n >/dev/null || ret=1 + grep -w "L64" dig.out.$n >/dev/null || ret=1 + grep -w "L32" dig.out.$n >/dev/null || ret=1 + ;; + esac + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NID (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t NID ns1.nid.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $minimal = no ]; then + # change && to || when we support NID additional processing + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + else + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + fi + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NID + LP (+norec) ($n)" + ret=0 + $DIG $DIGOPTS +norec -t NID nid2.nid.example @10.53.0.1 >dig.out.$n || ret=1 + if [ $minimal = no ]; then + # change && to || when we support NID additional processing + grep -w "LP" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + else + grep -w "LP" dig.out.$n >/dev/null && ret=1 + grep -w "L64" dig.out.$n >/dev/null && ret=1 + grep -w "L32" dig.out.$n >/dev/null && ret=1 + fi + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NS, root zone ($n)" + ret=0 + $DIG $DIGOPTS -t NS . @10.53.0.1 >dig.out.$n || ret=1 + # Always expect glue for root priming queries, regardless $minimal + grep 'ADDITIONAL: 3' dig.out.$n >/dev/null || ret=1 + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi + + n=$((n + 1)) + echo_i "test with NS, non-root zone ($n)" + ret=0 + $DIG $DIGOPTS -t NS rt.example @10.53.0.1 >dig.out.$n || ret=1 + case $minimal in + yes) + grep 'ADDITIONAL: 2' dig.out.$n >/dev/null || ret=1 + ;; + no) + grep 'ADDITIONAL: 2' dig.out.$n >/dev/null || ret=1 + ;; + no-auth) + grep 'ADDITIONAL: 2' dig.out.$n >/dev/null || ret=1 + ;; + no-auth-recursive) + grep 'ADDITIONAL: 2' dig.out.$n >/dev/null || ret=1 + ;; + esac + if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) + fi +} + +echo_i "testing with 'minimal-responses yes;'" +minimal=yes +dotests + +echo_i "reconfiguring server: minimal-responses no" +copy_setports ns1/named2.conf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 + +echo_i "testing with 'minimal-responses no;'" +minimal=no +dotests + +n=$((n + 1)) +echo_i "testing with 'minimal-any no;' ($n)" +ret=0 +$DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "reconfiguring server: minimal-any yes" +copy_setports ns1/named3.conf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 + +n=$((n + 1)) +echo_i "testing with 'minimal-any yes;' over UDP ($n)" +ret=0 +$DIG $DIGOPTS -t ANY +notcp www.rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi +n=$((n + 1)) + +echo_i "testing with 'minimal-any yes;' over TCP ($n)" +ret=0 +$DIG $DIGOPTS -t ANY +tcp www.rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +n=$((n + 1)) +echo_i "testing with 'minimal-any yes;' over UDP ($n)" +ret=0 +$DIG $DIGOPTS -t ANY +notcp www.rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "testing with 'minimal-responses no-auth;'" +minimal=no-auth +dotests + +echo_i "reconfiguring server: minimal-responses no-auth-recursive" +copy_setports ns1/named4.conf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 + +echo_i "testing with 'minimal-responses no-auth-recursive;'" +minimal=no-auth-recursive +dotests + +n=$((n + 1)) +echo_i "testing returning TLSA records with MX query ($n)" +ret=0 +$DIG $DIGOPTS -t mx mx.example @10.53.0.1 >dig.out.$n || ret=1 +grep "mx\.example\..*MX.0 mail\.mx\.example" dig.out.$n >/dev/null || ret=1 +grep "mail\.mx\.example\..*A.1\.2\.3\.4" dig.out.$n >/dev/null || ret=1 +grep "_25\._tcp\.mail\.mx\.example\..*TLSA.3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +n=$((n + 1)) +echo_i "testing returning TLSA records with SRV query ($n)" +ret=0 +$DIG $DIGOPTS -t srv _xmpp-client._tcp.srv.example @10.53.0.1 >dig.out.$n || ret=1 +grep "_xmpp-client\._tcp\.srv\.example\..*SRV.1 0 5222 server\.srv\.example" dig.out.$n >/dev/null || ret=1 +grep "server\.srv\.example\..*A.1\.2\.3\.4" dig.out.$n >/dev/null || ret=1 +grep "_5222\._tcp\.server\.srv\.example\..*TLSA.3 0 1 5B30F9602297D558EB719162C225088184FAA32CA45E1ED15DE58A21 D9FCE383" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "reconfiguring server: minimal-responses no" +copy_setports ns1/named2.conf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 + +n=$((n + 1)) +echo_i "testing NS handling in ANY responses (authoritative) ($n)" +ret=0 +$DIG $DIGOPTS -t ANY rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 +grep "NS[ ]*ns" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +n=$((n + 1)) +echo_i "testing NS handling in ANY responses (recursive) ($n)" +ret=0 +$DIG $DIGOPTS -t ANY rt.example @10.53.0.3 >dig.out.$n || ret=1 +grep "AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 +grep "NS[ ]*ns" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +n=$((n + 1)) +echo_i "testing out-of-zone additional data from auth zones (authoritative) ($n)" +ret=0 +$DIG $DIGOPTS -t NS rt.example @10.53.0.1 >dig.out.$n || ret=1 +grep "ADDITIONAL: 2" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +n=$((n + 1)) +echo_i "testing out-of-zone additional data from auth zones (recursive) ($n)" +ret=0 +$DIG $DIGOPTS -t NS ex @10.53.0.3 >dig.out.$n || ret=1 +grep "ADDITIONAL: 3" dig.out.$n >/dev/null || ret=1 +if [ $ret -eq 1 ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/additional/tests_sh_additional.py b/bin/tests/system/additional/tests_sh_additional.py new file mode 100644 index 0000000..b467f80 --- /dev/null +++ b/bin/tests/system/additional/tests_sh_additional.py @@ -0,0 +1,22 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + ] +) + + +def test_additional(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/addzone/ns1/inlinesec.db b/bin/tests/system/addzone/ns1/inlinesec.db new file mode 100644 index 0000000..eb9d042 --- /dev/null +++ b/bin/tests/system/addzone/ns1/inlinesec.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN inlinesec.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns1/named.conf.in b/bin/tests/system/addzone/ns1/named.conf.in new file mode 100644 index 0000000..30731c4 --- /dev/null +++ b/bin/tests/system/addzone/ns1/named.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + allow-query { any; }; + allow-new-zones yes; + recursion no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "inlinesec.example" { + type primary; + file "inlinesec.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; +}; diff --git a/bin/tests/system/addzone/ns1/redirect.db.1 b/bin/tests/system/addzone/ns1/redirect.db.1 new file mode 100644 index 0000000..5dcdd1b --- /dev/null +++ b/bin/tests/system/addzone/ns1/redirect.db.1 @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/addzone/ns1/redirect.db.2 b/bin/tests/system/addzone/ns1/redirect.db.2 new file mode 100644 index 0000000..4dcbdbc --- /dev/null +++ b/bin/tests/system/addzone/ns1/redirect.db.2 @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 1 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/addzone/ns2/added.db b/bin/tests/system/addzone/ns2/added.db new file mode 100644 index 0000000..286e717 --- /dev/null +++ b/bin/tests/system/addzone/ns2/added.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +;$ORIGIN added.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/default.nzf.in b/bin/tests/system/addzone/ns2/default.nzf.in new file mode 100644 index 0000000..d9740f5 --- /dev/null +++ b/bin/tests/system/addzone/ns2/default.nzf.in @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone previous.example { type primary; file "previous.db"; }; diff --git a/bin/tests/system/addzone/ns2/hints.db b/bin/tests/system/addzone/ns2/hints.db new file mode 100644 index 0000000..e0f186c --- /dev/null +++ b/bin/tests/system/addzone/ns2/hints.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/addzone/ns2/inline.db b/bin/tests/system/addzone/ns2/inline.db new file mode 100644 index 0000000..c968104 --- /dev/null +++ b/bin/tests/system/addzone/ns2/inline.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN inline.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/named1.conf.in b/bin/tests/system/addzone/ns2/named1.conf.in new file mode 100644 index 0000000..bd94f6e --- /dev/null +++ b/bin/tests/system/addzone/ns2/named1.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-query { any; }; + recursion no; + allow-new-zones yes; + dnssec-validation no; +}; + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "normal.db"; +}; + +zone "finaldot.example." { + type primary; + file "normal.db"; +}; diff --git a/bin/tests/system/addzone/ns2/named2.conf.in b/bin/tests/system/addzone/ns2/named2.conf.in new file mode 100644 index 0000000..ef9adeb --- /dev/null +++ b/bin/tests/system/addzone/ns2/named2.conf.in @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +view internal { + match-clients { 10.53.0.2; }; + allow-new-zones no; + recursion yes; + + response-policy { zone "policy"; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "policy" { + type primary; + file "normal.db"; + }; +}; + +view external { + match-clients { any; }; + allow-new-zones yes; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; + +# This view is only here to test that configuration context is cleaned +# up correctly when using multiple named ACLs (regression test for RT #22739) +acl match { none; }; +acl nobody { none; }; +view extra { + match-clients { match; }; + allow-new-zones yes; + allow-transfer { nobody; }; + allow-query { nobody; }; + allow-recursion { nobody; }; +}; diff --git a/bin/tests/system/addzone/ns2/named3.conf.in b/bin/tests/system/addzone/ns2/named3.conf.in new file mode 100644 index 0000000..ca934c4 --- /dev/null +++ b/bin/tests/system/addzone/ns2/named3.conf.in @@ -0,0 +1,78 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; 10.53.0.4; 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + new-zones-directory "new-zones"; + dnssec-validation no; +}; + +view internal { + match-clients { 10.53.0.2; }; + allow-new-zones no; + recursion yes; + + response-policy { zone "policy"; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "policy" { + type primary; + file "normal.db"; + }; +}; + +view directory { + match-clients { 10.53.0.5; }; + allow-new-zones yes; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; + +view external { + match-clients { any; }; + allow-new-zones yes; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; + +# This view is only here to test that configuration context is cleaned +# up correctly when using multiple named ACLs (regression test for RT #22739) +acl match { none; }; +acl nobody { none; }; +view extra { + match-clients { match; }; + allow-new-zones yes; + allow-transfer { nobody; }; + allow-query { nobody; }; + allow-recursion { nobody; }; +}; diff --git a/bin/tests/system/addzone/ns2/normal.db b/bin/tests/system/addzone/ns2/normal.db new file mode 100644 index 0000000..fa05638 --- /dev/null +++ b/bin/tests/system/addzone/ns2/normal.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN normal.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/previous.db b/bin/tests/system/addzone/ns2/previous.db new file mode 100644 index 0000000..6d2e495 --- /dev/null +++ b/bin/tests/system/addzone/ns2/previous.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN previous.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/addzone/ns2/redirect.db.1 b/bin/tests/system/addzone/ns2/redirect.db.1 new file mode 100644 index 0000000..5dcdd1b --- /dev/null +++ b/bin/tests/system/addzone/ns2/redirect.db.1 @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/addzone/ns2/redirect.db.2 b/bin/tests/system/addzone/ns2/redirect.db.2 new file mode 100644 index 0000000..4dcbdbc --- /dev/null +++ b/bin/tests/system/addzone/ns2/redirect.db.2 @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 1 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/addzone/ns3/e.db b/bin/tests/system/addzone/ns3/e.db new file mode 100644 index 0000000..7f74f0a --- /dev/null +++ b/bin/tests/system/addzone/ns3/e.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns3 hostmaster 0 0 0 0 0 +@ NS ns3 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/addzone/ns3/example.db b/bin/tests/system/addzone/ns3/example.db new file mode 100644 index 0000000..2bf4f8d --- /dev/null +++ b/bin/tests/system/addzone/ns3/example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ IN SOA localhost. localhost.localhost. 1 10800 3600 605800 86400 +@ IN NS localhost. diff --git a/bin/tests/system/addzone/ns3/named1.conf.in b/bin/tests/system/addzone/ns3/named1.conf.in new file mode 100644 index 0000000..e05ce21 --- /dev/null +++ b/bin/tests/system/addzone/ns3/named1.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-query { any; }; + allow-transfer { any; }; + recursion no; + allow-new-zones yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "redirect.db"; +}; + +remote-servers "test" { + 10.53.0.99; +}; diff --git a/bin/tests/system/addzone/ns3/named2.conf.in b/bin/tests/system/addzone/ns3/named2.conf.in new file mode 100644 index 0000000..76e4b8a --- /dev/null +++ b/bin/tests/system/addzone/ns3/named2.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-query { any; }; + allow-transfer { any; }; + recursion no; + allow-new-zones yes; + dnssec-validation no; +}; diff --git a/bin/tests/system/addzone/ns3/redirect.db.1 b/bin/tests/system/addzone/ns3/redirect.db.1 new file mode 100644 index 0000000..60a2622 --- /dev/null +++ b/bin/tests/system/addzone/ns3/redirect.db.1 @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS . +@ 0 A 127.0.0.1 diff --git a/bin/tests/system/addzone/ns3/redirect.db.2 b/bin/tests/system/addzone/ns3/redirect.db.2 new file mode 100644 index 0000000..3804fef --- /dev/null +++ b/bin/tests/system/addzone/ns3/redirect.db.2 @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 1 0 0 0 0 +@ 0 NS . +@ 0 A 127.0.0.1 diff --git a/bin/tests/system/addzone/setup.sh b/bin/tests/system/addzone/setup.sh new file mode 100644 index 0000000..b2227c1 --- /dev/null +++ b/bin/tests/system/addzone/setup.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +cp -f ns1/redirect.db.1 ns1/redirect.db +cp -f ns2/redirect.db.1 ns2/redirect.db +cp -f ns3/redirect.db.1 ns3/redirect.db + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named1.conf.in ns2/named.conf +copy_setports ns3/named1.conf.in ns3/named.conf + +cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf +mkdir ns2/new-zones diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh new file mode 100755 index 0000000..6d5939c --- /dev/null +++ b/bin/tests/system/addzone/tests.sh @@ -0,0 +1,749 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +check_zonestatus() ( + $RNDCCMD "10.53.0.$1" zonestatus -redirect >"zonestatus.out.ns$1.$n" \ + && grep "type: redirect" "zonestatus.out.ns$1.$n" >/dev/null \ + && grep "serial: 1" "zonestatus.out.ns$1.$n" >/dev/null +) + +status=0 +n=0 + +echo_i "checking normally loaded zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# When LMDB support is compiled in, this tests that migration from +# NZF to NZD occurs during named startup +echo_i "checking previously added zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 a.previous.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.previous.example' dig.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if $FEATURETEST --with-lmdb; then + echo_i "checking that existing NZF file was renamed after migration ($n)" + [ -e ns2/3bf305731dd26307.nzf~ ] || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "adding new zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'added.example { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +_check_adding_new_zone() ( + $DIG $DIGOPTS @10.53.0.2 a.added.example a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.added.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_adding_new_zone || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null +echo_i "checking addzone errors are logged correctly" +ret=0 +$RNDCCMD 10.53.0.2 addzone bad.example '{ type mister; };' 2>&1 | grep 'unexpected token' >/dev/null 2>&1 || ret=1 +wait_for_log_peek 20 "addzone: 'mister' unexpected" ns2/named.run || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null +echo_i "checking modzone errors are logged correctly" +ret=0 +$RNDCCMD 10.53.0.2 modzone added.example '{ type mister; };' 2>&1 | grep 'unexpected token' >/dev/null 2>&1 || ret=1 +wait_for_log_peek 20 "modzone: 'mister' unexpected" ns2/named.run || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "adding a zone that requires quotes ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone '"32/1.0.0.127-in-addr.added.example" { +check-names ignore; type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +_check_zone_that_requires_quotes() ( + $DIG $DIGOPTS @10.53.0.2 "a.32/1.0.0.127-in-addr.added.example" a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.32/1.0.0.127-in-addr.added.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_zone_that_requires_quotes || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "adding a zone with a quote in the name ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone '"foo\"bar.example" { check-names ignore; type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +_check_zone_with_a_quote() ( + $DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.foo\\"bar.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_zone_with_a_quote || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "adding new zone with missing file ($n)" +ret=0 +$DIG $DIGOPTS +all @10.53.0.2 a.missing.example a >dig.out.ns2.pre.$n || ret=1 +grep "status: REFUSED" dig.out.ns2.pre.$n >/dev/null || ret=1 +$RNDCCMD 10.53.0.2 addzone 'missing.example { type primary; file "missing.db"; };' 2>rndc.out.ns2.$n && ret=1 +grep "file not found" rndc.out.ns2.$n >/dev/null || ret=1 +$DIG $DIGOPTS +all @10.53.0.2 a.missing.example a >dig.out.ns2.post.$n || ret=1 +grep "status: REFUSED" dig.out.ns2.post.$n >/dev/null || ret=1 +digcomp dig.out.ns2.pre.$n dig.out.ns2.post.$n || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if ! $FEATURETEST --with-lmdb; then + echo_i "verifying no comments in NZF file ($n)" + ret=0 + hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l) + [ $hcount -eq 0 ] || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "checking rndc showzone with previously added zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 showzone previous.example >rndc.out.ns2.$n +expected='zone "previous.example" { type primary; file "previous.db"; };' +[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if $FEATURETEST --with-lmdb; then + echo_i "checking zone is present in NZD ($n)" + ret=0 + $NZD2NZF ns2/_default.nzd | grep previous.example >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "deleting previously added zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone previous.example 2>&1 | sed 's/^/I:ns2 /' +_check_deleting_previously_added_zone() ( + $DIG $DIGOPTS @10.53.0.2 a.previous.example a >dig.out.ns2.$n \ + && grep 'status: REFUSED' dig.out.ns2.$n >/dev/null \ + && ! grep '^a.previous.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_previously_added_zone || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +check_nzd2nzf() ( + $NZD2NZF ns2/_default.nzd >nzd2nzf.out.$n \ + && ! grep previous.example nzd2nzf.out.$n >/dev/null +) + +if $FEATURETEST --with-lmdb; then + echo_i "checking zone was deleted from NZD ($n)" + retry_quiet 10 check_nzd2nzf || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +if ! $FEATURETEST --with-lmdb; then + echo_i "checking NZF file now has comment ($n)" + ret=0 + hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l) + [ $hcount -eq 1 ] || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "deleting newly added zone added.example ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone added.example 2>&1 | sed 's/^/I:ns2 /' +_check_deleting_newly_added_zone() ( + $DIG $DIGOPTS @10.53.0.2 a.added.example a >dig.out.ns2.$n \ + && grep 'status: REFUSED' dig.out.ns2.$n >/dev/null \ + && ! grep '^a.added.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_newly_added_zone || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "deleting newly added zone with escaped quote ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone "foo\\\"bar.example" 2>&1 | sed 's/^/I:ns2 /' +_check_deleting_newly_added_zone_quote() ( + $DIG $DIGOPTS @10.53.0.2 "a.foo\"bar.example" a >dig.out.ns2.$n \ + && grep 'status: REFUSED' dig.out.ns2.$n >/dev/null \ + && ! grep "^a.foo\"bar.example" dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_newly_added_zone_quote || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc showzone with a normally-loaded zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 showzone normal.example >rndc.out.ns2.$n +expected='zone "normal.example" { type primary; file "normal.db"; };' +[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc showzone with a normally-loaded zone with trailing dot ($n)" +ret=0 +$RNDCCMD 10.53.0.2 showzone finaldot.example >rndc.out.ns2.$n +expected='zone "finaldot.example." { type primary; file "normal.db"; };' +[ "$(cat rndc.out.ns2.$n)" = "$expected" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc showzone with a normally-loaded redirect zone ($n)" +ret=0 +$RNDCCMD 10.53.0.1 showzone -redirect >rndc.out.ns1.$n +expected='zone "." { type redirect; file "redirect.db"; };' +[ "$(cat rndc.out.ns1.$n)" = "$expected" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc zonestatus with a normally-loaded redirect zone ($n)" +ret=0 +$RNDCCMD 10.53.0.1 zonestatus -redirect >rndc.out.ns1.$n +grep "type: redirect" rndc.out.ns1.$n >/dev/null || ret=1 +grep "serial: 0" rndc.out.ns1.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc reload with a normally-loaded redirect zone ($n)" +ret=0 +sleep 1 +cp -f ns1/redirect.db.2 ns1/redirect.db +$RNDCCMD 10.53.0.1 reload -redirect >rndc.out.ns1.$n +retry_quiet 5 check_zonestatus 1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "delete a normally-loaded zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone normal.example >rndc.out.ns2.$n 2>&1 +grep "is no longer active and will be deleted" rndc.out.ns2.$n >/dev/null || ret=11 +grep "To keep it from returning when the server is restarted" rndc.out.ns2.$n >/dev/null || ret=1 +grep "must also be removed from named.conf." rndc.out.ns2.$n >/dev/null || ret=1 +_check_delete_normally_loaded_zone() ( + $DIG $DIGOPTS @10.53.0.2 a.normal.example a >dig.out.ns2.$n \ + && grep 'status: REFUSED' dig.out.ns2.$n >/dev/null +) +retry_quiet 5 _check_delete_normally_loaded_zone || ret=1 + +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to add primary zone with inline signing ($n)" +$RNDCCMD 10.53.0.2 addzone 'inline.example { type primary; file "inline.db"; dnssec-policy default; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /' +_check_add_primary_zone_with_inline() ( + $DIG $DIGOPTS @10.53.0.2 a.inline.example a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.inline.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 5 _check_add_primary_zone_with_inline || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to add primary zone with inline signing and missing file ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'inlinemissing.example { type primary; file "missing.db"; dnssec-policy default; inline-signing yes; };' 2>rndc.out.ns2.$n && ret=1 +grep "file not found" rndc.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to add secondary zone with inline signing ($n)" +$RNDCCMD 10.53.0.2 addzone 'inlinesec.example { type secondary; primaries { 10.53.0.1; }; file "inlinesec.bk"; dnssec-policy default; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /' +_check_add_secondary_with_inline() ( + $DIG $DIGOPTS @10.53.0.2 a.inlinesec.example a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.inlinesec.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 5 _check_add_secondary_with_inline || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to delete secondary zone with inline signing ($n)" +ret=0 +retry_quiet 10 test -f ns2/inlinesec.bk.signed -a -f ns2/inlinesec.bk || ret=1 +$RNDCCMD 10.53.0.2 delzone inlinesec.example >rndc.out2.test$n 2>&1 || ret=1 +test -f inlinesec.bk \ + || grep '^inlinesec.bk$' rndc.out2.test$n >/dev/null || { + echo_i "failed to report inlinesec.bk" + ret=1 +} +test ! -f inlinesec.bk.signed \ + || grep '^inlinesec.bk.signed$' rndc.out2.test$n >/dev/null || { + echo_i "failed to report inlinesec.bk.signed" + ret=1 +} +n=$((n + 1)) +status=$((status + ret)) + +echo_i "restoring secondary zone with inline signing ($n)" +$RNDCCMD 10.53.0.2 addzone 'inlinesec.example { type secondary; primaries { 10.53.0.1; }; file "inlinesec.bk"; dnssec-policy default; inline-signing yes; };' 2>&1 | sed 's/^/I:ns2 /' +_check_restoring_secondary_with_inline() ( + $DIG $DIGOPTS @10.53.0.2 a.inlinesec.example a >dig.out.ns2.$n \ + && grep 'status: NOERROR' dig.out.ns2.$n >/dev/null \ + && grep '^a.inlinesec.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 5 _check_restoring_secondary_with_inline || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "deleting secondary zone with automatic zone file removal ($n)" +ret=0 +retry_quiet 10 test -f ns2/inlinesec.bk.signed -a -f ns2/inlinesec.bk || ret=1 +$RNDCCMD 10.53.0.2 delzone -clean inlinesec.example >/dev/null 2>&1 +retry_quiet 10 test ! -f ns2/inlinesec.bk.signed -a ! -f ns2/inlinesec.bk +n=$((n + 1)) +status=$((status + ret)) + +echo_i "modifying zone configuration ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'mod.example { type primary; file "added.db"; };' 2>&1 | sed 's/^/ns2 /' | cat_i +$DIG +norec $DIGOPTS @10.53.0.2 mod.example ns >dig.out.ns2.1.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.1.$n >/dev/null || ret=1 +$RNDCCMD 10.53.0.2 modzone 'mod.example { type primary; file "added.db"; allow-query { none; }; };' 2>&1 | sed 's/^/ns2 /' | cat_i +$DIG +norec $DIGOPTS @10.53.0.2 mod.example ns >dig.out.ns2.2.$n || ret=1 +$RNDCCMD 10.53.0.2 showzone mod.example | grep 'allow-query { "none"; };' >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that adding a 'stub' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'stub.example { type stub; primaries { 1.2.3.4; }; file "stub.example.bk"; };' >rndc.out.ns2.$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that adding a 'static-stub' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'static-stub.example { type static-stub; server-addresses { 1.2.3.4; }; };' >rndc.out.ns2.$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that adding a 'primary redirect' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone '"." { type redirect; file "redirect.db"; };' >rndc.out.ns2.$n 2>&1 || ret=1 +_check_add_primary_redirect() ( + $RNDCCMD 10.53.0.2 showzone -redirect >showzone.out.ns2.$n 2>&1 \ + && grep "type redirect;" showzone.out.ns2.$n >/dev/null \ + && $RNDCCMD 10.53.0.2 zonestatus -redirect >zonestatus.out.ns2.$n 2>&1 \ + && grep "type: redirect" zonestatus.out.ns2.$n >/dev/null \ + && grep "serial: 0" zonestatus.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_add_primary_redirect || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that reloading a added 'primary redirect' zone works ($n)" +ret=0 +sleep 1 +cp -f ns2/redirect.db.2 ns2/redirect.db +$RNDCCMD 10.53.0.2 reload -redirect >rndc.out.ns2.$n +retry_quiet 10 check_zonestatus 2 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that retransfer of a added 'primary redirect' zone fails ($n)" +ret=0 +$RNDCCMD 10.53.0.2 retransfer -redirect >rndc.out.ns2.$n 2>&1 && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that deleting a 'primary redirect' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone -redirect >rndc.out.ns2.$n 2>&1 || ret=1 +_check_deleting_primary_redirect() ( + $RNDCCMD 10.53.0.2 showzone -redirect >showzone.out.ns2.$n 2>&1 || true + grep 'not found' showzone.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_primary_redirect || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that adding a 'secondary redirect' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone '"." { type redirect; primaries { 10.53.0.3;}; file "redirect.bk"; };' >rndc.out.ns2.$n 2>&1 || ret=1 +_check_adding_secondary_redirect() ( + $RNDCCMD 10.53.0.2 showzone -redirect >showzone.out.ns2.$n 2>&1 \ + && grep "type redirect;" showzone.out.ns2.$n >/dev/null \ + && $RNDCCMD 10.53.0.2 zonestatus -redirect >zonestatus.out.ns2.$n 2>&1 \ + && grep "type: redirect" zonestatus.out.ns2.$n >/dev/null \ + && grep "serial: 0" zonestatus.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_adding_secondary_redirect || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that retransfering a added 'secondary redirect' zone works ($n)" +ret=0 +cp -f ns3/redirect.db.2 ns3/redirect.db +$RNDCCMD 10.53.0.3 reload . >showzone.out.ns3.$n 2>&1 || ret=1 +_check_retransfering_secondary_redirect() ( + $RNDCCMD 10.53.0.2 retransfer -redirect >rndc.out.ns2.$n 2>&1 \ + && $RNDCCMD 10.53.0.2 zonestatus -redirect >zonestatus.out.ns2.$n 2>&1 \ + && grep "type: redirect" zonestatus.out.ns2.$n >/dev/null \ + && grep "serial: 1" zonestatus.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_retransfering_secondary_redirect || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that deleting a 'secondary redirect' zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone -redirect >rndc.out.ns2.$n 2>&1 || ret=1 +_check_deleting_secondary_redirect() ( + $RNDCCMD 10.53.0.2 showzone -redirect >showzone.out.ns2.$n 2>&1 || true + grep 'not found' showzone.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_secondary_redirect || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that zone type 'hint' is properly rejected ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone '"." { type hint; file "hints.db"; };' >rndc.out.ns2.$n 2>&1 && ret=1 +grep "zones not supported by addzone" rndc.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that zone type 'forward' is properly rejected ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'forward.example { type forward; forwarders { 1.2.3.4; }; forward only; };' >rndc.out.ns2.$n 2>&1 && ret=1 +grep "zones not supported by addzone" rndc.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'in-view' zones are properly rejected ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'in-view.example { in-view "_default"; };' >rndc.out.ns2.$n 2>&1 && ret=1 +grep "zones not supported by addzone" rndc.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "reconfiguring server with multiple views" +rm -f ns2/named.conf +copy_setports ns2/named2.conf.in ns2/named.conf +rndc_reconfig ns2 10.53.0.2 + +echo_i "adding new zone to external view ($n)" +# NOTE: The internal view has "recursion yes" set, and so queries for +# nonexistent zones should return NOERROR. The external view is +# "recursion no", so queries for nonexistent zones should return +# REFUSED. This behavior should be the same regardless of whether +# the zone does not exist because a) it has not yet been loaded, b) +# it failed to load, or c) it has been deleted. +ret=0 +$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.intpre.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.intpre.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.extpre.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.extpre.$n >/dev/null || ret=1 +$RNDCCMD 10.53.0.2 addzone 'added.example in external { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.int.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.ext.$n >/dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.ext.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if ! $FEATURETEST --with-lmdb; then + echo_i "checking new NZF file has comment ($n)" + ret=0 + hcount=$(grep "^# New zone file for view: external" ns2/external.nzf | wc -l) + [ $hcount -eq 1 ] || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +if $FEATURETEST --with-lmdb; then + echo_i "verifying added.example in external view created an external.nzd DB ($n)" + ret=0 + [ -e ns2/external.nzd ] || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "checking rndc reload causes named to reload the external view's new zone config ($n)" +ret=0 +$RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/ns2 /' | cat_i +_check_rndc_reload_external_view_config() ( + $DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.int.$n \ + && grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null \ + && $DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n \ + && grep 'status: NOERROR' dig.out.ns2.ext.$n >/dev/null \ + && grep '^a.added.example' dig.out.ns2.ext.$n >/dev/null +) +retry_quiet 10 _check_rndc_reload_external_view_config || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking rndc showzone with newly added zone ($n)" +_check_rndc_showzone_newly_added() ( + if ! $FEATURETEST --with-lmdb; then + expected='zone "added.example" in external { type primary; file "added.db"; };' + else + expected='zone "added.example" { type primary; file "added.db"; };' + fi + $RNDCCMD 10.53.0.2 showzone added.example in external >rndc.out.ns2.$n 2>/dev/null \ + && [ "$(cat rndc.out.ns2.$n)" = "$expected" ] +) +retry_quiet 10 _check_rndc_showzone_newly_added || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "deleting newly added zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /' +_check_deleting_newly_added_zone() ( + $DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.$n \ + && grep 'status: REFUSED' dig.out.ns2.$n >/dev/null \ + && ! grep '^a.added.example' dig.out.ns2.$n >/dev/null +) +retry_quiet 10 _check_deleting_newly_added_zone || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to add zone to internal view ($n)" +ret=0 +$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.pre.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.pre.$n >/dev/null || ret=1 +$RNDCCMD 10.53.0.2 addzone 'added.example in internal { type primary; file "added.db"; };' 2>rndc.out.ns2.$n && ret=1 +grep "permission denied" rndc.out.ns2.$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.int.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.ext.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "attempting to delete a policy zone ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone 'policy in internal' 2>rndc.out.ns2.$n >&1 && ret=1 +grep 'cannot be deleted' rndc.out.ns2.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "adding new zone again to external view ($n)" +ret=0 +$RNDCCMD 10.53.0.2 addzone 'added.example in external { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +_check_adding_new_zone_again_external() ( + $DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.int.$n \ + && grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null \ + && $DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n \ + && grep 'status: NOERROR' dig.out.ns2.ext.$n >/dev/null \ + && grep '^a.added.example' dig.out.ns2.ext.$n >/dev/null +) +retry_quiet 10 _check_adding_new_zone_again_external || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "reconfiguring server with multiple views and new-zones-directory" +rm -f ns2/named.conf +copy_setports ns2/named3.conf.in ns2/named.conf +rndc_reconfig ns2 10.53.0.2 + +echo_i "checking new zone is still loaded after dir change ($n)" +ret=0 +$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.ext.$n >/dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.ext.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "deleting newly added zone from external ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone 'added.example in external' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "adding new zone to directory view ($n)" +ret=0 +$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.intpre.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.intpre.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.extpre.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.extpre.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a >dig.out.ns2.dirpre.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.dirpre.$n >/dev/null || ret=1 +$RNDCCMD 10.53.0.2 addzone 'added.example in directory { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns2 /' +$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.added.example a >dig.out.ns2.int.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.4 -b 10.53.0.4 a.added.example a >dig.out.ns2.ext.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.ext.$n >/dev/null || ret=1 +$DIG +norec $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a >dig.out.ns2.dir.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.dir.$n >/dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.dir.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if $FEATURETEST --with-lmdb; then + echo_i "checking NZD file was created in new-zones-directory ($n)" + expect=ns2/new-zones/directory.nzd +else + echo_i "checking NZF file was created in new-zones-directory ($n)" + expect=ns2/new-zones/directory.nzf +fi +$RNDCCMD 10.53.0.2 sync 'added.example IN directory' 2>&1 | sed 's/^/I:ns2 /' +sleep 2 +[ -e "$expect" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "deleting newly added zone from directory ($n)" +ret=0 +$RNDCCMD 10.53.0.2 delzone 'added.example in directory' 2>&1 | sed 's/^/I:ns2 /' +$DIG $DIGOPTS @10.53.0.5 -b 10.53.0.5 a.added.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.added.example' dig.out.ns2.$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "ensure the configuration context is cleaned up correctly ($n)" +ret=0 +rndc_reconfig ns2 10.53.0.2 +$RNDCCMD 10.53.0.2 status >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check delzone after reconfig failure ($n)" +ret=0 +$RNDCCMD 10.53.0.3 addzone 'inlinesec.example. IN { type secondary; file "inlinesec.db"; masterfile-format text; primaries { test; }; };' >/dev/null 2>&1 || ret=1 +copy_setports ns3/named2.conf.in ns3/named.conf +rndc_reconfig ns3 10.53.0.3 +$RNDCCMD 10.53.0.3 delzone inlinesec.example >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if ! $FEATURETEST --with-lmdb; then + echo_i "check that addzone is fully reversed on failure (--with-lmdb=no) ($n)" + ret=0 + $RNDCCMD 10.53.0.3 addzone "test1.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 + $RNDCCMD 10.53.0.3 addzone "test2.baz" '{ type primary; file "dne.db"; };' >/dev/null 2>&1 && ret=1 + $RNDCCMD 10.53.0.3 addzone "test3.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 + $RNDCCMD 10.53.0.3 delzone "test3.baz" >/dev/null 2>&1 || ret=1 + grep test2.baz ns3/_default.nzf >/dev/null && ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +_check_version_bind() ( + $DIG $DIGOPTS @10.53.0.3 version.bind txt ch >dig.out.test$n \ + && grep "status: NOERROR" dig.out.test$n >/dev/null +) + +echo_i "check that named restarts with multiple added zones ($n)" +ret=0 +$RNDCCMD 10.53.0.3 addzone "test4.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone "test5.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone '"test/.baz"' '{ type primary; check-names ignore; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone '"test\".baz"' '{ type primary; check-names ignore; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone '"test\\.baz"' '{ type primary; check-names ignore; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone '"test\032.baz"' '{ type primary; check-names ignore; file "e.db"; };' >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 addzone '"test\010.baz"' '{ type primary; check-names ignore; file "e.db"; };' >/dev/null 2>&1 || ret=1 +stop_server ns3 +start_server --noclean --restart --port ${PORT} ns3 || ret=1 +retry_quiet 10 _check_version_bind || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA "test4.baz" >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA "test5.baz" >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.2.test$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA 'test/.baz' >dig.out.3.test$n || ret=1 +grep "status: NOERROR" dig.out.3.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.3.test$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA 'test\\.baz' >dig.out.4.test$n || ret=1 +grep "status: NOERROR" dig.out.4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.4.test$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA 'test\032.baz' >dig.out.5.test$n || ret=1 +grep "status: NOERROR" dig.out.5.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.5.test$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 SOA 'test\010.baz' >dig.out.6.test$n || ret=1 +grep "status: NOERROR" dig.out.6.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.6.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/addzone/tests_rndc_deadlock.py b/bin/tests/system/addzone/tests_rndc_deadlock.py new file mode 100755 index 0000000..3b987d3 --- /dev/null +++ b/bin/tests/system/addzone/tests_rndc_deadlock.py @@ -0,0 +1,90 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import concurrent.futures +import time + +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/*.nzf*", + "ns*/*.nzd*", + "ns1/redirect.db", + "ns2/new-zones", + "ns2/redirect.db", + "ns3/redirect.db", + ] +) + + +def rndc_loop(test_state, domain, ns3): + """ + Run "rndc addzone", "rndc modzone", and "rndc delzone" in a tight loop + until the test is considered finished, ignoring errors + """ + rndc_commands = [ + ["addzone", domain, '{ type primary; file "example.db"; };'], + [ + "modzone", + domain, + '{ type primary; file "example.db"; allow-transfer { any; }; };', + ], + ["delzone", domain], + ] + + while not test_state["finished"]: + for command in rndc_commands: + ns3.rndc(" ".join(command), ignore_errors=True, log=False) + + +def check_if_server_is_responsive(ns3): + """ + Check if server status can be successfully retrieved using "rndc status" + """ + try: + ns3.rndc("status", log=False) + return True + except isctest.rndc.RNDCException: + return False + + +def test_rndc_deadlock(servers): + """ + Test whether running "rndc addzone", "rndc modzone", and "rndc delzone" + commands concurrently does not trigger a deadlock + """ + test_state = {"finished": False} + ns3 = servers["ns3"] + + # Create 4 worker threads running "rndc" commands in a loop. + with concurrent.futures.ThreadPoolExecutor() as executor: + for i in range(1, 5): + domain = "example%d" % i + executor.submit(rndc_loop, test_state, domain, ns3) + + # Run "rndc status" 10 times, with 1-second pauses between attempts. + # Each "rndc status" invocation has a timeout of 10 seconds. If any of + # them fails, the loop will be interrupted. + server_is_responsive = True + attempts = 10 + while server_is_responsive and attempts > 0: + server_is_responsive = check_if_server_is_responsive(ns3) + attempts -= 1 + time.sleep(1) + + # Signal worker threads that the test is finished. + test_state["finished"] = True + + # Check whether all "rndc status" commands succeeded. + assert server_is_responsive diff --git a/bin/tests/system/addzone/tests_sh_addzone.py b/bin/tests/system/addzone/tests_sh_addzone.py new file mode 100644 index 0000000..4ca4440 --- /dev/null +++ b/bin/tests/system/addzone/tests_sh_addzone.py @@ -0,0 +1,43 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out*", + "showzone.out.*", + "zonestatus.out.*", + "ns*/*.nzd*", + "ns*/*.nzf*", + "ns1/redirect.db", + "nzd2nzf.out.*", + "ns2/*.nzf~", + "ns2/K*.key", + "ns2/K*.private", + "ns2/K*.state", + "ns2/external.nzd", + "ns2/extra.nzd", + "ns2/inline.db.jbk", + "ns2/inline.db.signed", + "ns2/inline.db.signed.jnl", + "ns2/inlinesec.bk.jbk", + "ns2/new-zones", + "ns2/redirect.bk", + "ns2/redirect.db", + "ns3/redirect.db", + ] +) + + +def test_addzone(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/allow-query/ns1/named.conf.in b/bin/tests/system/allow-query/ns1/named.conf.in new file mode 100644 index 0000000..dd786e2 --- /dev/null +++ b/bin/tests/system/allow-query/ns1/named.conf.in @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/allow-query/ns1/root.db b/bin/tests/system/allow-query/ns1/root.db new file mode 100644 index 0000000..456198e --- /dev/null +++ b/bin/tests/system/allow-query/ns1/root.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA a.root-servers.nil. hostmaster.localhost. 1 3600 1200 604800 3600 + NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +normal.example. NS ns2.normal.example. +ns2.normal.example. A 10.53.0.2 diff --git a/bin/tests/system/allow-query/ns2/generic.db b/bin/tests/system/allow-query/ns2/generic.db new file mode 100644 index 0000000..83e66f9 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/generic.db @@ -0,0 +1,33 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN @ +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.7.1 +mail A 10.0.7.2 +b A 10.0.7.3 +c A 10.0.7.4 +d A 10.0.7.5 +e A 10.0.7.6 +f A 10.0.7.7 +g A 10.0.7.8 +h A 10.0.7.9 diff --git a/bin/tests/system/allow-query/ns2/named01.conf.in b/bin/tests/system/allow-query/ns2/named01.conf.in new file mode 100644 index 0000000..fec3ddd --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named01.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named02.conf.in b/bin/tests/system/allow-query/ns2/named02.conf.in new file mode 100644 index 0000000..95a78b2 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named02.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { any; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named03.conf.in b/bin/tests/system/allow-query/ns2/named03.conf.in new file mode 100644 index 0000000..fd6add2 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named03.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { none; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named04.conf.in b/bin/tests/system/allow-query/ns2/named04.conf.in new file mode 100644 index 0000000..f6d231d --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named04.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { 10.53.0.2; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named05.conf.in b/bin/tests/system/allow-query/ns2/named05.conf.in new file mode 100644 index 0000000..fe6cc0c --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named05.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { 10.53.0.1; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named06.conf.in b/bin/tests/system/allow-query/ns2/named06.conf.in new file mode 100644 index 0000000..1f78f13 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named06.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query {! 10.53.0.2; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named07.conf.in b/bin/tests/system/allow-query/ns2/named07.conf.in new file mode 100644 index 0000000..15dca8f --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named07.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.2; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { accept; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named08.conf.in b/bin/tests/system/allow-query/ns2/named08.conf.in new file mode 100644 index 0000000..c2eed2d --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named08.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.1; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { accept; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named09.conf.in b/bin/tests/system/allow-query/ns2/named09.conf.in new file mode 100644 index 0000000..248da9e --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named09.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.2; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query {! accept; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named10.conf.in b/bin/tests/system/allow-query/ns2/named10.conf.in new file mode 100644 index 0000000..1dbafbd --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named10.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { key one; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named11.conf.in b/bin/tests/system/allow-query/ns2/named11.conf.in new file mode 100644 index 0000000..4d961a5 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named11.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234efgh8765"; +}; + + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { key one; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named12.conf.in b/bin/tests/system/allow-query/ns2/named12.conf.in new file mode 100644 index 0000000..75ab352 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named12.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query {! key one; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; diff --git a/bin/tests/system/allow-query/ns2/named21.conf.in b/bin/tests/system/allow-query/ns2/named21.conf.in new file mode 100644 index 0000000..b120f2a --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named21.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named22.conf.in b/bin/tests/system/allow-query/ns2/named22.conf.in new file mode 100644 index 0000000..37ccedc --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named22.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { any; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; + +}; diff --git a/bin/tests/system/allow-query/ns2/named23.conf.in b/bin/tests/system/allow-query/ns2/named23.conf.in new file mode 100644 index 0000000..c43e232 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named23.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { none; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named24.conf.in b/bin/tests/system/allow-query/ns2/named24.conf.in new file mode 100644 index 0000000..6cdbeec --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named24.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { 10.53.0.2; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named25.conf.in b/bin/tests/system/allow-query/ns2/named25.conf.in new file mode 100644 index 0000000..51e247c --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named25.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { 10.53.0.1; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named26.conf.in b/bin/tests/system/allow-query/ns2/named26.conf.in new file mode 100644 index 0000000..a72136c --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named26.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query {! 10.53.0.2; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named27.conf.in b/bin/tests/system/allow-query/ns2/named27.conf.in new file mode 100644 index 0000000..4c3f958 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named27.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.2; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { accept; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; + +}; diff --git a/bin/tests/system/allow-query/ns2/named28.conf.in b/bin/tests/system/allow-query/ns2/named28.conf.in new file mode 100644 index 0000000..8db4555 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named28.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.1; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { accept; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named29.conf.in b/bin/tests/system/allow-query/ns2/named29.conf.in new file mode 100644 index 0000000..2031a6e --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named29.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.2; }; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query {! accept; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named30.conf.in b/bin/tests/system/allow-query/ns2/named30.conf.in new file mode 100644 index 0000000..0a90219 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named30.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { key one; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named31.conf.in b/bin/tests/system/allow-query/ns2/named31.conf.in new file mode 100644 index 0000000..faec50e --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named31.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234efgh8765"; +}; + + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { key one; }; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { key one; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named32.conf.in b/bin/tests/system/allow-query/ns2/named32.conf.in new file mode 100644 index 0000000..dcd663b --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named32.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query {! key one; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named33.conf.in b/bin/tests/system/allow-query/ns2/named33.conf.in new file mode 100644 index 0000000..3721e62 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named33.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { none; }; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { any; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; + +}; diff --git a/bin/tests/system/allow-query/ns2/named34.conf.in b/bin/tests/system/allow-query/ns2/named34.conf.in new file mode 100644 index 0000000..09125ef --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named34.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { any; }; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { none; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named40.conf.in b/bin/tests/system/allow-query/ns2/named40.conf.in new file mode 100644 index 0000000..2349d92 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named40.conf.in @@ -0,0 +1,108 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl accept { 10.53.0.2; }; + +acl badaccept { 10.53.0.1; }; + +key one { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +key two { + algorithm @DEFAULT_HMAC@; + secret "1234efgh8765"; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; +}; + +zone "any.example" { + type primary; + file "generic.db"; + allow-query { any; }; +}; + +zone "none.example" { + type primary; + file "generic.db"; + allow-query { none; }; +}; + +zone "addrallow.example" { + type primary; + file "generic.db"; + allow-query { 10.53.0.2; }; +}; + +zone "addrnotallow.example" { + type primary; + file "generic.db"; + allow-query { 10.53.0.1; }; +}; + +zone "addrdisallow.example" { + type primary; + file "generic.db"; + allow-query { ! 10.53.0.2; }; +}; + +zone "aclallow.example" { + type primary; + file "generic.db"; + allow-query { accept; }; +}; + +zone "aclnotallow.example" { + type primary; + file "generic.db"; + allow-query { badaccept; }; +}; + +zone "acldisallow.example" { + type primary; + file "generic.db"; + allow-query { ! accept; }; +}; + +/* Also usable for testing key not allowed */ +zone "keyallow.example" { + type primary; + file "generic.db"; + allow-query { key one; }; +}; + +zone "keydisallow.example" { + type primary; + file "generic.db"; + allow-query { ! key one; }; +}; diff --git a/bin/tests/system/allow-query/ns2/named53.conf.in b/bin/tests/system/allow-query/ns2/named53.conf.in new file mode 100644 index 0000000..d3463b2 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named53.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { none; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; + allow-query { any; }; +}; diff --git a/bin/tests/system/allow-query/ns2/named54.conf.in b/bin/tests/system/allow-query/ns2/named54.conf.in new file mode 100644 index 0000000..5dddf89 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named54.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + allow-query { any; }; + dnssec-validation no; +}; + +include "controls.conf"; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "normal.example" { + type primary; + file "generic.db"; + allow-query { none; }; +}; diff --git a/bin/tests/system/allow-query/ns2/named55.conf.in b/bin/tests/system/allow-query/ns2/named55.conf.in new file mode 100644 index 0000000..4a0880f --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named55.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { none; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + allow-query { any; }; + }; + +}; diff --git a/bin/tests/system/allow-query/ns2/named56.conf.in b/bin/tests/system/allow-query/ns2/named56.conf.in new file mode 100644 index 0000000..564063b --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named56.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + + allow-query { any; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + allow-query { none; }; + }; +}; diff --git a/bin/tests/system/allow-query/ns2/named57.conf.in b/bin/tests/system/allow-query/ns2/named57.conf.in new file mode 100644 index 0000000..db5f3d0 --- /dev/null +++ b/bin/tests/system/allow-query/ns2/named57.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +include "controls.conf"; + +view "internal" { + allow-query-on { any; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone "normal.example" { + type primary; + file "generic.db"; + }; + + zone "aclnotallow.example" { + type primary; + file "generic.db"; + allow-query-on { none; }; + }; +}; diff --git a/bin/tests/system/allow-query/ns3/named.args b/bin/tests/system/allow-query/ns3/named.args new file mode 100644 index 0000000..b424c39 --- /dev/null +++ b/bin/tests/system/allow-query/ns3/named.args @@ -0,0 +1,2 @@ +# this server only has 127.0.0.1 in its localhost/localnets ACLs +-m record -c named.conf -d 99 -D allow-query-ns3 -g -T maxcachesize=2097152 -T fixedlocal diff --git a/bin/tests/system/allow-query/ns3/named1.conf.in b/bin/tests/system/allow-query/ns3/named1.conf.in new file mode 100644 index 0000000..bc42246 --- /dev/null +++ b/bin/tests/system/allow-query/ns3/named1.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/allow-query/ns3/named2.conf.in b/bin/tests/system/allow-query/ns3/named2.conf.in new file mode 100644 index 0000000..53e73ad --- /dev/null +++ b/bin/tests/system/allow-query/ns3/named2.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + allow-recursion { any; }; + allow-recursion-on { none; }; + allow-query-cache-on { 10.53.0.3; }; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/allow-query/ns3/named3.conf.in b/bin/tests/system/allow-query/ns3/named3.conf.in new file mode 100644 index 0000000..36b5f77 --- /dev/null +++ b/bin/tests/system/allow-query/ns3/named3.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; 10.53.1.2; }; + listen-on-v6 { none; }; + recursion yes; + allow-recursion { any; }; + allow-query-cache { any; }; + allow-query-cache-on { 10.53.0.3; }; # allow-recursion-on inherits + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/allow-query/ns3/named4.conf.in b/bin/tests/system/allow-query/ns3/named4.conf.in new file mode 100644 index 0000000..f9e88d4 --- /dev/null +++ b/bin/tests/system/allow-query/ns3/named4.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; 10.53.1.2; }; + listen-on-v6 { none; }; + recursion yes; + allow-recursion { any; }; + allow-query-cache { any; }; + allow-recursion-on { 10.53.0.3; }; # allow-query-cache-on inherits + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/allow-query/setup.sh b/bin/tests/system/allow-query/setup.sh new file mode 100644 index 0000000..886c8ac --- /dev/null +++ b/bin/tests/system/allow-query/setup.sh @@ -0,0 +1,19 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ../_common/controls.conf.in ns2/controls.conf +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named01.conf.in ns2/named.conf +copy_setports ns3/named1.conf.in ns3/named.conf diff --git a/bin/tests/system/allow-query/tests.sh b/bin/tests/system/allow-query/tests.sh new file mode 100644 index 0000000..bfacf76 --- /dev/null +++ b/bin/tests/system/allow-query/tests.sh @@ -0,0 +1,738 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Test of allow-query statement. +# allow-query takes an address match list and can be included in either the +# options statement or in the zone statement. This test assumes that the +# acl tests cover the details of the address match list and uses a limited +# number of address match test cases to ensure that allow-query finds the +# expected match. +# Test list: +# In options: +# default (any), any, none, [localhost, localnets], +# allowed address, not allowed address, denied address, +# allowed key, not allowed key, denied key +# allowed acl, not allowed acl, denied acl (acls pointing to addresses) +# +# Each of these tests requires changing to a new configuration +# file and using rndc to update the server +# +# In view, with nothing in options (default to any) +# default (any), any, none, [localhost, localnets], +# allowed address, not allowed address, denied address, +# allowed key, not allowed key, denied key +# allowed acl, not allowed acl, denied acl (acls pointing to addresses) +# +# In view, with options set to none, view set to any +# In view, with options set to any, view set to none +# +# In zone, with nothing in options (default to any) +# any, none, [localhost, localnets], +# allowed address, denied address, +# allowed key, not allowed key, denied key +# allowed acl, not allowed acl, denied acl (acls pointing to addresses), +# +# In zone, with options set to none, zone set to any +# In zone, with options set to any, zone set to none +# In zone, with view set to none, zone set to any +# In zone, with view set to any, zone set to none +# +# zone types of primary, secondary and stub can be tested in parallel by +# using multiple instances (ns2 as primary, ns3 as secondary, ns4 as stub) +# and querying as necessary. +# + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +dnssec -p ${PORT}" + +status=0 +n=0 + +nextpart ns2/named.run >/dev/null + +# Test 1 - default, query allowed +n=$((n + 1)) +echo_i "test $n: default - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 2 - explicit any, query allowed +n=$((n + 1)) +copy_setports ns2/named02.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: explicit any - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 3 - none, query refused +n=$((n + 1)) +copy_setports ns2/named03.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: none - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +nextpart ns2/named.run | grep 'recursion not enabled for view' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +DIGNOEDNS="+tcp +nosea +nostat +nocmd +norec +noques +noauth +noadd +nostats +noedns -p ${PORT}" + +echo_i "test $n: none - query refused (no edns)" +ret=0 +$DIG $DIGNOEDNS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null && ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 4 - address allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named04.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: address allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 5 - address not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named05.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: address not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 6 - address disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named06.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: address disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 7 - acl allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named07.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: acl allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 8 - acl not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named08.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: acl not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 9 - acl disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named09.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: acl disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 10 - key allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named10.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: key allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 11 - key not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named11.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: key not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:two:1234efgh8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 12 - key disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named12.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: key disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The next set of tests check if allow-query works in a view + +n=20 +# Test 21 - views default, query allowed +n=$((n + 1)) +copy_setports ns2/named21.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views default - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 22 - views explicit any, query allowed +n=$((n + 1)) +copy_setports ns2/named22.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views explicit any - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 23 - views none, query refused +n=$((n + 1)) +copy_setports ns2/named23.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views none - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 24 - views address allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named24.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views address allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 25 - views address not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named25.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views address not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 26 - views address disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named26.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views address disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 27 - views acl allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named27.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views acl allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 28 - views acl not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named28.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views acl not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 29 - views acl disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named29.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views acl disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 30 - views key allowed, query allowed +n=$((n + 1)) +copy_setports ns2/named30.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views key allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 31 - views key not allowed, query refused +n=$((n + 1)) +copy_setports ns2/named31.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views key not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:two:1234efgh8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 32 - views key disallowed, query refused +n=$((n + 1)) +copy_setports ns2/named32.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views key disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 33 - views over options, views allow, query allowed +n=$((n + 1)) +copy_setports ns2/named33.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views over options, views allow - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 34 - views over options, views disallow, query refused +n=$((n + 1)) +copy_setports ns2/named34.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views over options, views disallow - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Tests for allow-query in the zone statements + +n=40 + +# Test 41 - zone default, query allowed +n=$((n + 1)) +copy_setports ns2/named40.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: zone default - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 42 - zone explicit any, query allowed +n=$((n + 1)) +echo_i "test $n: zone explicit any - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.any.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.any.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 43 - zone none, query refused +n=$((n + 1)) +echo_i "test $n: zone none - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.none.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.none.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 44 - zone address allowed, query allowed +n=$((n + 1)) +echo_i "test $n: zone address allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.addrallow.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 45 - zone address not allowed, query refused +n=$((n + 1)) +echo_i "test $n: zone address not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrnotallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.addrnotallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 46 - zone address disallowed, query refused +n=$((n + 1)) +echo_i "test $n: zone address disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.addrdisallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.addrdisallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 47 - zone acl allowed, query allowed +n=$((n + 1)) +echo_i "test $n: zone acl allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.aclallow.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 48 - zone acl not allowed, query refused +n=$((n + 1)) +echo_i "test $n: zone acl not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclnotallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.aclnotallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 49 - zone acl disallowed, query refused +n=$((n + 1)) +echo_i "test $n: zone acl disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.acldisallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.acldisallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 50 - zone key allowed, query allowed +n=$((n + 1)) +echo_i "test $n: zone key allowed - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.keyallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.keyallow.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 51 - zone key not allowed, query refused +n=$((n + 1)) +echo_i "test $n: zone key not allowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:two:1234efgh8765" a.keyallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.keyallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 52 - zone key disallowed, query refused +n=$((n + 1)) +echo_i "test $n: zone key disallowed - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y "${DEFAULT_HMAC}:one:1234abcd8765" a.keydisallow.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.keydisallow.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 53 - zones over options, zones allow, query allowed +n=$((n + 1)) +copy_setports ns2/named53.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views over options, views allow - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 54 - zones over options, zones disallow, query refused +n=$((n + 1)) +copy_setports ns2/named54.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: views over options, views disallow - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 55 - zones over views, zones allow, query allowed +n=$((n + 1)) +copy_setports ns2/named55.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: zones over views, views allow - query allowed" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 56 - zones over views, zones disallow, query refused +n=$((n + 1)) +copy_setports ns2/named56.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: zones over views, views disallow - query refused" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 57 - zones over views, zones disallow, query refused (allow-query-on) +n=$((n + 1)) +copy_setports ns2/named57.conf.in ns2/named.conf +rndc_reload ns2 10.53.0.2 + +echo_i "test $n: zones over views, allow-query-on" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.normal.example a >dig.out.ns2.1.$n || ret=1 +grep 'status: NOERROR' dig.out.ns2.1.$n >/dev/null || ret=1 +grep '^a.normal.example' dig.out.ns2.1.$n >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.aclnotallow.example a >dig.out.ns2.2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns2.2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns2.2.$n >/dev/null || ret=1 +grep '^a.aclnotallow.example' dig.out.ns2.2.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 58 - allow-recursion default +n=$((n + 1)) +echo_i "test $n: default allow-recursion configuration" +ret=0 +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 -b 127.0.0.1 a.normal.example a >dig.out.ns3.1.$n || ret=1 +grep 'status: NOERROR' dig.out.ns3.1.$n >/dev/null || ret=1 +$DIG -p ${PORT} @10.53.0.3 -b 10.53.0.1 a.normal.example a >dig.out.ns3.2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n >/dev/null || ret=1 +nextpart ns3/named.run | grep 'allow-recursion did not match' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 59 - allow-query-cache default +n=$((n + 1)) +echo_i "test $n: default allow-query-cache configuration" +ret=0 +$DIG -p ${PORT} @10.53.0.3 -b 127.0.0.1 ns . >dig.out.ns3.1.$n || ret=1 +grep 'status: NOERROR' dig.out.ns3.1.$n >/dev/null || ret=1 +$DIG -p ${PORT} @10.53.0.3 -b 10.53.0.1 ns . >dig.out.ns3.2.$n || ret=1 +grep 'status: REFUSED' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n >/dev/null || ret=1 +nextpart ns3/named.run | grep 'allow-recursion did not match' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 60 - block recursion-on, allow query-cache-on +n=$((n + 1)) +copy_setports ns3/named2.conf.in ns3/named.conf +rndc_reload ns3 10.53.0.3 + +echo_i "test $n: block recursion-on, allow query-cache-on" +ret=0 +# this should query the cache, and an answer should already be there +$DIG -p ${PORT} @10.53.0.3 a.normal.example a >dig.out.ns3.1.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.1.$n >/dev/null || ret=1 +grep 'ANSWER: 1' dig.out.ns3.1.$n >/dev/null || ret=1 +# this should require recursion and therefore can't get an answer +$DIG -p ${PORT} @10.53.0.3 b.normal.example a >dig.out.ns3.2.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'ANSWER: 0' dig.out.ns3.2.$n >/dev/null || ret=1 +nextpart ns3/named.run | grep 'allow-recursion-on did not match' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 61 - inheritance of allow-query-cache-on from allow-recursion-on +n=$((n + 1)) +copy_setports ns3/named3.conf.in ns3/named.conf +rndc_reload ns3 10.53.0.3 + +echo_i "test $n: inheritance of allow-query-cache-on" +ret=0 +# this should query the cache, an answer should already be there +$DIG -p ${PORT} @10.53.0.3 a.normal.example a >dig.out.ns3.1.$n || ret=1 +grep 'ANSWER: 1' dig.out.ns3.1.$n >/dev/null || ret=1 +# this should be refused due to allow-recursion-on/allow-query-cache-on +$DIG -p ${PORT} @10.53.1.2 a.normal.example a >dig.out.ns3.2.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'status: REFUSED' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n >/dev/null || ret=1 +# this should require recursion and should be allowed +$DIG -p ${PORT} @10.53.0.3 c.normal.example a >dig.out.ns3.3.$n || ret=1 +grep 'ANSWER: 1' dig.out.ns3.3.$n >/dev/null || ret=1 +# this should require recursion and be refused +$DIG -p ${PORT} @10.53.1.2 d.normal.example a >dig.out.ns3.4.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.4.$n >/dev/null || ret=1 +grep 'status: REFUSED' dig.out.ns3.4.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.4.$n >/dev/null || ret=1 +nextpart ns3/named.run | grep 'allow-recursion-on did not match' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test 62 - inheritance of allow-recursion-on from allow-query-cache-on +n=$((n + 1)) +copy_setports ns3/named4.conf.in ns3/named.conf +rndc_reload ns3 10.53.0.3 + +echo_i "test $n: inheritance of allow-recursion-on" +ret=0 +# this should query the cache, an answer should already be there +$DIG -p ${PORT} @10.53.0.3 a.normal.example a >dig.out.ns3.1.$n || ret=1 +grep 'ANSWER: 1' dig.out.ns3.1.$n >/dev/null || ret=1 +# this should be refused due to allow-recursion-on/allow-query-cache-on +$DIG -p ${PORT} @10.53.1.2 a.normal.example a >dig.out.ns3.2.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'status: REFUSED' dig.out.ns3.2.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.2.$n >/dev/null || ret=1 +# this should require recursion and should be allowed +$DIG -p ${PORT} @10.53.0.3 e.normal.example a >dig.out.ns3.3.$n || ret=1 +grep 'ANSWER: 1' dig.out.ns3.3.$n >/dev/null || ret=1 +# this should require recursion and be refused +$DIG -p ${PORT} @10.53.1.2 f.normal.example a >dig.out.ns3.4.$n || ret=1 +grep 'recursion requested but not available' dig.out.ns3.4.$n >/dev/null || ret=1 +grep 'status: REFUSED' dig.out.ns3.4.$n >/dev/null || ret=1 +grep 'EDE: 18 (Prohibited)' dig.out.ns3.4.$n >/dev/null || ret=1 +nextpart ns3/named.run | grep 'allow-recursion-on did not match' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/allow-query/tests_sh_allow_query.py b/bin/tests/system/allow-query/tests_sh_allow_query.py new file mode 100644 index 0000000..0a17c7e --- /dev/null +++ b/bin/tests/system/allow-query/tests_sh_allow_query.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns2/controls.conf", + ] +) + + +def test_allow_query(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/ans.pl b/bin/tests/system/ans.pl new file mode 100644 index 0000000..bfd36bc --- /dev/null +++ b/bin/tests/system/ans.pl @@ -0,0 +1,596 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# This is the name server from hell. It provides canned +# responses based on pattern matching the queries, and +# can be reprogrammed on-the-fly over a TCP connection. +# +# The server listens for queries on port 5300 (or PORT). +# +# The server listens for control connections on port 5301 (or EXTRAPORT1). +# +# A control connection is a TCP stream of lines like +# +# /pattern/ +# name ttl type rdata +# name ttl type rdata +# ... +# /pattern/ +# name ttl type rdata +# name ttl type rdata +# ... +# +# There can be any number of patterns, each associated +# with any number of response RRs. Each pattern is a +# Perl regular expression. If an empty pattern ("//") is +# received, the server will ignore all incoming queries (TCP +# connections will still be accepted, but both UDP queries +# and TCP queries will not be responded to). If a non-empty +# pattern is then received over the same control connection, +# default behavior is restored. +# +# Each incoming query is converted into a string of the form +# "qname qtype" (the printable query domain name, space, +# printable query type) and matched against each pattern. +# +# The first pattern matching the query is selected, and +# the RR following the pattern line are sent in the +# answer section of the response. +# +# Each new control connection causes the current set of +# patterns and responses to be cleared before adding new +# ones. +# +# The server handles UDP and TCP queries. Zone transfer +# responses work, but must fit in a single 64 k message. +# +# Now you can add TSIG, just specify key/key data with: +# +# /pattern / +# name ttl type rdata +# name ttl type rdata +# +# Note that this data will still be sent with any request for +# pattern, only this data will be signed. Currently, this is only +# done for TCP. +# +# /pattern NOTIMP / +# /pattern NOTIMP/ +# +# Return a NOTIMP response +# +# /pattern EDNS=NOTIMP / +# /pattern EDNS=NOTIMP/ +# +# Return a NOTIMP response to an EDNS request +# +# /pattern EDNS=FORMERR / +# /pattern EDNS=FORMERR/ +# +# Return a FORMERR response to an EDNS request +# +# /pattern bad-id / +# /pattern bad-id/ +# +# will add 50 to the message id of the response. + + +use IO::File; +use IO::Socket; +use Data::Dumper; +use Net::DNS; +use Net::DNS::Packet; +use strict; + +# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early +local $SIG{PIPE} = 'IGNORE'; + +# Flush logged output after every line +local $| = 1; + +# We default to listening on 10.53.0.2 for historical reasons +# XXX: we should also be able to specify IPv6 +my $server_addr = "10.53.0.2"; +if (@ARGV > 0) { + $server_addr = @ARGV[0]; +} + +my $mainport = int($ENV{'PORT'}); +if (!$mainport) { $mainport = 5300; } +my $ctrlport = int($ENV{'EXTRAPORT1'}); +if (!$ctrlport) { $ctrlport = 5301; } +my $hmac_algorithm = $ENV{'DEFAULT_HMAC'}; +if (!defined($hmac_algorithm)) { $hmac_algorithm = "hmac-sha256"; } + +# XXX: we should also be able to set the port numbers to listen on. +my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $mainport, Proto => "udp", Reuse => 1) or die "$!"; + +my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $mainport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +print "listening on $server_addr:$mainport,$ctrlport.\n"; +print "Using Net::DNS $Net::DNS::VERSION\n"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!";; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +#my @answers = (); +my @rules; +my $udphandler; +my $tcphandler; + +sub handleUDP { + my ($buf) = @_; + my $request; + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + my $qclass = $questions[0]->qclass; + my $id = $request->header->id; + + my $packet = new Net::DNS::Packet($qname, $qtype, $qclass); + $packet->header->qr(1); + $packet->header->aa(1); + $packet->header->id($id); + + # get the existing signature if any, and clear the additional section + my $prev_tsig; + while (my $rr = $request->pop("additional")) { + $prev_tsig = $rr if ($rr->type eq "TSIG"); + } + + my $r; + foreach $r (@rules) { + my $pattern = $r->{pattern}; + my($dbtype, $key_name, $key_data) = split(/ /,$pattern); + print "[handleUDP] $dbtype, $key_name, $key_data\n"; + if ("$qname $qtype" =~ /$dbtype/) { + my $a; + foreach $a (@{$r->{answer}}) { + $packet->push("answer", $a); + } + if (defined($key_name) && defined($key_data)) { + my $tsig; + # Sign the packet + print " Signing the response with " . + "$key_name/$key_data\n"; + + if ($Net::DNS::VERSION < 0.69) { + $tsig = Net::DNS::RR->new( + "$key_name TSIG $key_data"); + } else { + $tsig = Net::DNS::RR->new( + name => $key_name, + algorithm => $hmac_algorithm, + type => 'TSIG', + key => $key_data); + } + + # These kluges are necessary because Net::DNS + # doesn't know how to sign responses. We + # clear compnames so that the TSIG key and + # algorithm name won't be compressed, and + # add one to arcount because the signing + # function will attempt to decrement it, + # which is incorrect in a response. Finally + # we set request_mac to the previous digest. + $packet->{"compnames"} = {} + if ($Net::DNS::VERSION < 0.70); + $packet->{"header"}{"arcount"} += 1 + if ($Net::DNS::VERSION < 0.70); + if (defined($prev_tsig)) { + if ($Net::DNS::VERSION < 0.73) { + my $rmac = pack('n H*', + length($prev_tsig->mac)/2, + $prev_tsig->mac); + $tsig->{"request_mac"} = + unpack("H*", $rmac); + } else { + $tsig->request_mac( + $prev_tsig->mac); + } + } + + $packet->sign_tsig($tsig); + } + last; + } + } + #$packet->print; + + return $packet->data; +} + +# namelen: +# given a stream of data, reads a DNS-formatted name and returns its +# total length, thus making it possible to skip past it. +sub namelen { + my ($data) = @_; + my $len = 0; + my $label_len = 0; + do { + $label_len = unpack("c", $data); + $data = substr($data, $label_len + 1); + $len += $label_len + 1; + } while ($label_len != 0); + return ($len); +} + +# packetlen: +# given a stream of data, reads a DNS wire-format packet and returns +# its total length, making it possible to skip past it. +sub packetlen { + my ($data) = @_; + my $q; + my $rr; + my $header; + my $offset; + + # + # decode/encode were introduced in Net::DNS 0.68 + # parse is no longer a method and calling it here makes perl croak. + # + my $decode = 0; + $decode = 1 if ($Net::DNS::VERSION >= 0.68); + + if ($decode) { + ($header, $offset) = Net::DNS::Header->decode(\$data); + } else { + ($header, $offset) = Net::DNS::Header->parse(\$data); + } + + for (1 .. $header->qdcount) { + if ($decode) { + ($q, $offset) = + Net::DNS::Question->decode(\$data, $offset); + } else { + ($q, $offset) = + Net::DNS::Question->parse(\$data, $offset); + } + } + for (1 .. $header->ancount) { + if ($decode) { + ($q, $offset) = Net::DNS::RR->decode(\$data, $offset); + } else { + ($q, $offset) = Net::DNS::RR->parse(\$data, $offset); + } + } + for (1 .. $header->nscount) { + if ($decode) { + ($q, $offset) = Net::DNS::RR->decode(\$data, $offset); + } else { + ($q, $offset) = Net::DNS::RR->parse(\$data, $offset); + } + } + for (1 .. $header->arcount) { + if ($decode) { + ($q, $offset) = Net::DNS::RR->decode(\$data, $offset); + } else { + ($q, $offset) = Net::DNS::RR->parse(\$data, $offset); + } + } + return $offset; +} + +# sign_tcp_continuation: +# This is a hack to correct the problem that Net::DNS has no idea how +# to sign multiple-message TCP responses. Several data that are included +# in the digest when signing a query or the first message of a response are +# omitted when signing subsequent messages in a TCP stream. +# +# Net::DNS::Packet->sign_tsig() has the ability to use a custom signing +# function (specified by calling Packet->sign_func()). We use this +# function as the signing function for TCP continuations, and it removes +# the unwanted data from the digest before calling the default sign_hmac +# function. +sub sign_tcp_continuation { + my ($key, $data) = @_; + + # copy out first two bytes: size of the previous MAC + my $rmacsize = unpack("n", $data); + $data = substr($data, 2); + + # copy out previous MAC + my $rmac = substr($data, 0, $rmacsize); + $data = substr($data, $rmacsize); + + # try parsing out the packet information + my $plen = packetlen($data); + my $pdata = substr($data, 0, $plen); + $data = substr($data, $plen); + + # remove the keyname, ttl, class, and algorithm name + $data = substr($data, namelen($data)); + $data = substr($data, 6); + $data = substr($data, namelen($data)); + + # preserve the TSIG data + my $tdata = substr($data, 0, 8); + + # prepare a new digest and sign with it + $data = pack("n", $rmacsize) . $rmac . $pdata . $tdata; + return Net::DNS::RR::TSIG::sign_hmac($key, $data); +} + +sub handleTCP { + my ($buf) = @_; + my $request; + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + my $qclass = $questions[0]->qclass; + my $id = $request->header->id; + my @additional = $request->additional; + my $has_opt = 0; + foreach (@additional) { + $has_opt = 1 if (ref($_) eq 'Net::DNS::RR::OPT'); + } + + my $opaque; + + my $packet = new Net::DNS::Packet($qname, $qtype, $qclass); + $packet->header->qr(1); + $packet->header->aa(1); + $packet->header->id($id); + + # get the existing signature if any, and clear the additional section + my $prev_tsig; + my $signer; + my $continuation = 0; + if ($Net::DNS::VERSION < 0.81) { + while (my $rr = $request->pop("additional")) { + if ($rr->type eq "TSIG") { + $prev_tsig = $rr; + } + } + } + + my @results = (); + my $count_these = 0; + + my $r; + foreach $r (@rules) { + my $pattern = $r->{pattern}; + my($dbtype, $key_name, $key_data, $tname) = split(/ /,$pattern); + print "[handleTCP] $dbtype, $key_name, $key_data, $tname \n"; + if ("$qname $qtype" =~ /$dbtype/) { + $count_these++; + my $a; + my $done = 0; + + while (defined($key_name) && + ($key_name eq "NOTIMP" || $key_name eq "EDNS=NOTIMP" || + $key_name eq "EDNS=FORMERR" || $key_name eq "bad-id")) { + + if (defined($key_name) && $key_name eq "NOTIMP") { + $packet->header->rcode('NOTIMP') if (!$done); + $key_name = $key_data; + ($key_data, $tname) = split(/ /,$tname); + $done = 1; + } + + if (defined($key_name) && $key_name eq "EDNS=NOTIMP") { + if ($has_opt) { + $packet->header->rcode('NOTIMP') if (!$done); + $done = 1; + } + $key_name = $key_data; + ($key_data, $tname) = split(/ /,$tname); + } + + if (defined($key_name) && $key_name eq "EDNS=FORMERR") { + if ($has_opt) { + $packet->header->rcode('FORMERR') if (!$done); + $done = 1; + } + $key_name = $key_data; + ($key_data, $tname) = split(/ /,$tname); + } + + if (defined($key_name) && $key_name eq "bad-id") { + $packet->header->id(($id+50)%0xffff); + $key_name = $key_data; + ($key_data, $tname) = split(/ /,$tname); + } + } + + if (!$done) { + foreach $a (@{$r->{answer}}) { + $packet->push("answer", $a); + } + } + + if (defined($key_name) && defined($key_data)) { + my $tsig; + # sign the packet + print " Signing the data with " . + "$key_name/$key_data\n"; + + if ($Net::DNS::VERSION < 0.69) { + $tsig = Net::DNS::RR->new( + "$key_name TSIG $key_data"); + $tsig->algorithm = $hmac_algorithm; + } elsif ($Net::DNS::VERSION >= 0.81 && + $continuation) { + } elsif ($Net::DNS::VERSION >= 0.75 && + $continuation) { + $tsig = $prev_tsig; + } else { + $tsig = Net::DNS::RR->new( + name => $key_name, + algorithm => $hmac_algorithm, + type => 'TSIG', + key => $key_data); + } + + # These kluges are necessary because Net::DNS + # doesn't know how to sign responses. We + # clear compnames so that the TSIG key and + # algorithm name won't be compressed, and + # add one to arcount because the signing + # function will attempt to decrement it, + # which is incorrect in a response. Finally + # we set request_mac to the previous digest. + $packet->{"compnames"} = {} + if ($Net::DNS::VERSION < 0.70); + $packet->{"header"}{"arcount"} += 1 + if ($Net::DNS::VERSION < 0.70); + if (defined($prev_tsig)) { + if ($Net::DNS::VERSION < 0.73) { + my $rmac = pack('n H*', + length($prev_tsig->mac)/2, + $prev_tsig->mac); + $tsig->{"request_mac"} = + unpack("H*", $rmac); + } elsif ($Net::DNS::VERSION < 0.81) { + $tsig->request_mac( + $prev_tsig->mac); + } + } + + $tsig->sign_func($signer) if defined($signer); + $tsig->continuation($continuation) if + ($Net::DNS::VERSION >= 0.71 && + $Net::DNS::VERSION <= 0.74 ); + if ($Net::DNS::VERSION < 0.81) { + $packet->sign_tsig($tsig); + } elsif ($continuation) { + $opaque = $packet->sign_tsig($opaque); + } else { + $opaque = $packet->sign_tsig($request); + } + $signer = \&sign_tcp_continuation + if ($Net::DNS::VERSION < 0.70); + $continuation = 1; + + my $copy = + Net::DNS::Packet->new(\($packet->data)); + $prev_tsig = $copy->pop("additional"); + } + #$packet->print; + push(@results,$packet->data); + last if ($done); + if ($tname eq "") { + $tname = $qname; + } + $packet = new Net::DNS::Packet($tname, $qtype, $qclass); + $packet->header->qr(1); + $packet->header->aa(1); + $packet->header->id($id); + } + } + print " A total of $count_these patterns matched\n"; + return \@results; +} + +# Main +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($ctlsock), 1) = 1; + vec($rin, fileno($tcpsock), 1) = 1; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($ctlsock), 1)) { + warn "ctl conn"; + my $conn = $ctlsock->accept; + my $rule = (); + @rules = (); + while (my $line = $conn->getline) { + chomp $line; + if ($line =~ m!^/(.*)/$!) { + if (length($1) == 0) { + $udphandler = sub { return; }; + $tcphandler = sub { return; }; + } else { + $udphandler = \&handleUDP; + $tcphandler = \&handleTCP; + $rule = { pattern => $1, answer => [] }; + push(@rules, $rule); + } + } else { + push(@{$rule->{answer}}, + new Net::DNS::RR($line)); + } + } + $conn->close; + #print Dumper(@rules); + #print "+=+=+ $rules[0]->{'pattern'}\n"; + #print "+=+=+ $rules[0]->{'answer'}->[0]->{'rname'}\n"; + #print "+=+=+ $rules[0]->{'answer'}->[0]\n"; + } elsif (vec($rout, fileno($udpsock), 1)) { + printf "UDP request\n"; + my $buf; + $udpsock->recv($buf, 512); + my $result = &$udphandler($buf); + if (defined($result)) { + my $num_chars = $udpsock->send($result); + print " Sent $num_chars bytes via UDP\n"; + } + } elsif (vec($rout, fileno($tcpsock), 1)) { + my $conn = $tcpsock->accept; + my $buf; + for (;;) { + my $lenbuf; + my $n = $conn->sysread($lenbuf, 2); + last unless $n == 2; + my $len = unpack("n", $lenbuf); + $n = $conn->sysread($buf, $len); + last unless $n == $len; + print "TCP request\n"; + my $result = &$tcphandler($buf); + if (defined($result)) { + foreach my $response (@$result) { + $len = length($response); + $n = $conn->syswrite(pack("n", $len), 2); + $n = $conn->syswrite($response, $len); + print " Sent: $n chars via TCP\n"; + } + } + } + $conn->close; + } +} diff --git a/bin/tests/system/auth/ns1/chaos.db b/bin/tests/system/auth/ns1/chaos.db new file mode 100644 index 0000000..bbd489a --- /dev/null +++ b/bin/tests/system/auth/ns1/chaos.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ CH SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A ch-addr.example. 1001 +test A ch-addr.example. 1002 + A ch-addr.example. 1003 diff --git a/bin/tests/system/auth/ns1/example.com.db b/bin/tests/system/auth/ns1/example.com.db new file mode 100644 index 0000000..6768895 --- /dev/null +++ b/bin/tests/system/auth/ns1/example.com.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 +www CNAME server.example.net. +inzone CNAME a.example.com. +a A 10.53.0.1 +dname DNAME @ diff --git a/bin/tests/system/auth/ns1/example.net.db b/bin/tests/system/auth/ns1/example.net.db new file mode 100644 index 0000000..29885ca --- /dev/null +++ b/bin/tests/system/auth/ns1/example.net.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2018010100 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 +server A 10.53.0.100 diff --git a/bin/tests/system/auth/ns1/named.conf.j2 b/bin/tests/system/auth/ns1/named.conf.j2 new file mode 100644 index 0000000..7fdc1a1 --- /dev/null +++ b/bin/tests/system/auth/ns1/named.conf.j2 @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +view main in { + allow-transfer { any; }; + + zone example.net { + type primary; + file "example.net.db"; + }; + + zone example.com { + type primary; + file "example.com.db"; + }; +}; + +view alt chaos { + zone example.chaos chaos { + type primary; + file "chaos.db"; + }; +}; diff --git a/bin/tests/system/auth/ns2/named.conf.j2 b/bin/tests/system/auth/ns2/named.conf.j2 new file mode 100644 index 0000000..9b82c50 --- /dev/null +++ b/bin/tests/system/auth/ns2/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation no; +}; + +zone example.net { + type secondary; + primaries { 10.53.0.1; }; + file "example.net.bk"; +}; + +zone example.com { + type secondary; + primaries { 10.53.0.1; }; + file "example.com.bk"; +}; diff --git a/bin/tests/system/auth/tests.sh b/bin/tests/system/auth/tests.sh new file mode 100644 index 0000000..2499b46 --- /dev/null +++ b/bin/tests/system/auth/tests.sh @@ -0,0 +1,190 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp -p ${PORT}" + +status=0 +n=0 + +n=$((n + 1)) +echo_i "wait for zones to finish transferring to ns2 ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + for zone in example.com example.net; do + $DIG $DIGOPTS @10.53.0.2 soa $zone >dig.out.test$n || ret=1 + grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# +# If recursion is unrequested or unavailable, then cross-zone CNAME records +# should not be followed. If both requested and available, they should be. +# +n=$((n + 1)) +echo_i "check that cross-zone CNAME record does not return target data (rd=0/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.1 www.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa;" dig.out.test$n >/dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n >/dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that cross-zone CNAME record does not return target data (rd=1/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +rec @10.53.0.1 www.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa rd;" dig.out.test$n >/dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n >/dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that cross-zone CNAME record does not return target data (rd=0/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.2 www.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa ra;" dig.out.test$n >/dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n >/dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that cross-zone CNAME records return target data (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 www.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa rd ra;" dig.out.test$n >/dev/null || ret=1 +grep "www.example.com.*CNAME.*server.example.net" dig.out.test$n >/dev/null || ret=1 +grep "server.example.net.*A.*10.53.0.100" dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# +# In-zone CNAME records should always be followed regardless of RD and RA. +# +n=$((n + 1)) +echo_i "check that in-zone CNAME records return target data (rd=0/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.1 inzone.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa;" dig.out.test$n >/dev/null || ret=1 +grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n >/dev/null || ret=1 +grep "a.example.com.*A.*10.53.0.1" dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone CNAME records returns target data (rd=1/ra=0) ($n)" +ret=0 +$DIG $DIGOPTS +rec @10.53.0.1 inzone.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa rd;" dig.out.test$n >/dev/null || ret=1 +grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n >/dev/null || ret=1 +grep "a.example.com.*A.*10.53.0.1" dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone CNAME records return target data (rd=0/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS +norec @10.53.0.2 inzone.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa ra;" dig.out.test$n >/dev/null || ret=1 +grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n >/dev/null || ret=1 +grep "a.example.com.*A.*10.53.0.1" dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone CNAME records return target data (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 inzone.example.com >dig.out.test$n || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "flags: qr aa rd ra;" dig.out.test$n >/dev/null || ret=1 +grep "inzone.example.com.*CNAME.*a.example.com" dig.out.test$n >/dev/null || ret=1 +grep "a.example.com.*A.*10.53.0.1" dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone CNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t cname inzone.example.com >dig.out.test$n || ret=1 +grep 'ANSWER: 1,' dig.out.test$n >/dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone CNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t any inzone.example.com >dig.out.test$n || ret=1 +grep 'ANSWER: 1,' dig.out.test$n >/dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone DNAME records does not return target data when QTYPE is CNAME (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t cname inzone.dname.example.com >dig.out.test$n || ret=1 +grep 'ANSWER: 2,' dig.out.test$n >/dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n >/dev/null || ret=1 +grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.example\.com\..*CNAME.a\.example\.com\.' dig.out.test$n >/dev/null && ret=1 +grep 'a\.example\.com\..*A.10\.53\.0\.1' dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that in-zone DNAME records does not return target data when QTYPE is ANY (rd=1/ra=1) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 -t any inzone.dname.example.com >dig.out.test$n || ret=1 +grep 'ANSWER: 2,' dig.out.test$n >/dev/null || ret=1 +grep 'flags: qr aa rd ra;' dig.out.test$n >/dev/null || ret=1 +grep 'dname\.example\.com\..*DNAME.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.dname\.example\.com\..*CNAME.inzone\.example\.com\.' dig.out.test$n >/dev/null || ret=1 +grep 'inzone\.example\.com.*CNAME.a\.example\.com\.' dig.out.test$n >/dev/null && ret=1 +grep 'a\.example\.com.*A.10\.53\.0\.1' dig.out.test$n >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that CHAOS addresses are compared correctly ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 +noall +answer ch test.example.chaos >dig.out.test$n || ret=1 +lines=$(wc -l $zonefile + +zskact=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone) +zskvanish=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone) +zskdel=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -D now $zone) +zskinact=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -I now $zone) +zskunpub=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -G $zone) +zsksby=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -A none $zone) +zskactnowpub1d=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -A now -P +1d $zone) +zsknopriv=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q $zone) +rm $zsknopriv.private + +ksksby=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -P now -A now -fk $zone) +kskrev=$($KEYGEN -3 -a ${DEFAULT_ALGORITHM} -q -R now -fk $zone) + +keyfile_to_static_ds $ksksby >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns4/trusted.conf + +keyfile_to_static_ds $kskrev >trusted.conf +cp trusted.conf ../ns5/trusted.conf + +echo $zskact >../active.key +echo $zskvanish >../vanishing.key +echo $zskdel >../del.key +echo $zskinact >../inact.key +echo $zskunpub >../unpub.key +echo $zsknopriv >../nopriv.key +echo $zsksby >../standby.key +echo $zskactnowpub1d >../activate-now-publish-1day.key +$REVOKE -R $kskrev >../rev.key + +$SIGNER -S -o . -O full root.db >signing.out 2>&1 diff --git a/bin/tests/system/autosign/ns1/named.conf.in b/bin/tests/system/autosign/ns1/named.conf.in new file mode 100644 index 0000000..fb76b65 --- /dev/null +++ b/bin/tests/system/autosign/ns1/named.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db.signed"; + allow-transfer { any; }; + allow-update { any; }; + allow-query { any; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/autosign/ns1/root.db.in b/bin/tests/system/autosign/ns1/root.db.in new file mode 100644 index 0000000..6715a02 --- /dev/null +++ b/bin/tests/system/autosign/ns1/root.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +. IN SOA a.root.servers.nil. each.isc.org. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +. TXT "root zone" +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +bar. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+59973.key b/bin/tests/system/autosign/ns2/Xbar.+013+59973.key new file mode 100644 index 0000000..1f4d1f4 --- /dev/null +++ b/bin/tests/system/autosign/ns2/Xbar.+013+59973.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 59973, for bar. +; Created: 20220623022335 (Thu Jun 23 12:23:35 2022) +; Publish: 20220623022335 (Thu Jun 23 12:23:35 2022) +; Activate: 20220623022335 (Thu Jun 23 12:23:35 2022) +bar. IN DNSKEY 257 3 13 QT6CpMaV4BT072+NaKLY5H01Mj2r1MOgsxgoiTAq1Fbf6rrkEWpnbktu Dh9Ol9kuzcUrefxDuxNwsXJu3iDPxw== diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+59973.private b/bin/tests/system/autosign/ns2/Xbar.+013+59973.private new file mode 100644 index 0000000..708d242 --- /dev/null +++ b/bin/tests/system/autosign/ns2/Xbar.+013+59973.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: joFZ8vCdyqkgMb6rZ0zanrdrzOSCg1GyEJV6tp5F+Bw= +Created: 20220623022335 +Publish: 20220623022335 +Activate: 20220623022335 diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+60101.key b/bin/tests/system/autosign/ns2/Xbar.+013+60101.key new file mode 100644 index 0000000..0c47840 --- /dev/null +++ b/bin/tests/system/autosign/ns2/Xbar.+013+60101.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 60101, for bar. +; Created: 20220623022331 (Thu Jun 23 12:23:31 2022) +; Publish: 20220623022331 (Thu Jun 23 12:23:31 2022) +; Activate: 20220623022331 (Thu Jun 23 12:23:31 2022) +bar. IN DNSKEY 257 3 13 dLGGOAE5uJd53Gci9MdymaRTMwsXVn13j05IfGJoVt9ucpeXpoIKVViX JNVE/uO4eJvkHycdEAvdVUWcslEmMQ== diff --git a/bin/tests/system/autosign/ns2/Xbar.+013+60101.private b/bin/tests/system/autosign/ns2/Xbar.+013+60101.private new file mode 100644 index 0000000..6ca8370 --- /dev/null +++ b/bin/tests/system/autosign/ns2/Xbar.+013+60101.private @@ -0,0 +1,6 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: pTTXxZUTzeVBXHMUJxTMxjh9yU4oxDtEhEvpkj+olf0= +Created: 20220623022331 +Publish: 20220623022331 +Activate: 20220623022331 diff --git a/bin/tests/system/autosign/ns2/bar.db.in b/bin/tests/system/autosign/ns2/bar.db.in new file mode 100644 index 0000000..8a9fa98 --- /dev/null +++ b/bin/tests/system/autosign/ns2/bar.db.in @@ -0,0 +1,80 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns.secure +ns.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +z A 10.0.0.26 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 diff --git a/bin/tests/system/autosign/ns2/child.nsec3.example.db.in b/bin/tests/system/autosign/ns2/child.nsec3.example.db.in new file mode 100644 index 0000000..8fc3bc8 --- /dev/null +++ b/bin/tests/system/autosign/ns2/child.nsec3.example.db.in @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2006081400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ IN NS ns2.example. diff --git a/bin/tests/system/autosign/ns2/child.optout.example.db.in b/bin/tests/system/autosign/ns2/child.optout.example.db.in new file mode 100644 index 0000000..8fc3bc8 --- /dev/null +++ b/bin/tests/system/autosign/ns2/child.optout.example.db.in @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2006081400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ IN NS ns2.example. diff --git a/bin/tests/system/autosign/ns2/dst.example.db.in b/bin/tests/system/autosign/ns2/dst.example.db.in new file mode 100644 index 0000000..0039484 --- /dev/null +++ b/bin/tests/system/autosign/ns2/dst.example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2.example. +a A 10.0.0.1 diff --git a/bin/tests/system/autosign/ns2/example.db.in b/bin/tests/system/autosign/ns2/example.db.in new file mode 100644 index 0000000..a970074 --- /dev/null +++ b/bin/tests/system/autosign/ns2/example.db.in @@ -0,0 +1,88 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns.secure +ns.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +z A 10.0.0.26 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 + +nsec3-to-nsec NS ns.nsec3-to-nsec +ns.nsec3-to-nsec A 10.53.0.3 + +oldsigs NS ns.oldsigs +ns.oldsigs A 10.53.0.3 + +dname-at-apex-nsec3 NS ns3 diff --git a/bin/tests/system/autosign/ns2/insecure.secure.example.db.in b/bin/tests/system/autosign/ns2/insecure.secure.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/autosign/ns2/insecure.secure.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/autosign/ns2/keygen.sh b/bin/tests/system/autosign/ns2/keygen.sh new file mode 100644 index 0000000..7421968 --- /dev/null +++ b/bin/tests/system/autosign/ns2/keygen.sh @@ -0,0 +1,68 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +# Have the child generate subdomain keys and pass DS sets to us. +(cd ../ns3 && $SHELL keygen.sh) + +for subdomain in secure nsec3 optout rsasha256 rsasha512 \ + nsec3-to-nsec oldsigs dname-at-apex-nsec3; do + cp ../ns3/dsset-$subdomain.example. . +done + +# Create keys and pass the DS to the parent. +zone=example +zonefile="${zone}.db" +infile="${zonefile}.in" +cat $infile dsset-*.example. >$zonefile + +kskname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone) +$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone >/dev/null +$DSFROMKEY $kskname.key >dsset-${zone}. + +# Create keys for a private secure zone. +zone=private.secure.example +zonefile="${zone}.db" +infile="${zonefile}.in" +ksk=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone) +$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone >/dev/null +keyfile_to_static_ds $ksk >private.conf +cp private.conf ../ns4/private.conf +$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >signing.privsec.out 2>&1 + +# Extract saved keys for the revoke-to-duplicate-key test +zone=bar +zonefile="${zone}.db" +infile="${zonefile}.in" +cat $infile >$zonefile +for i in Xbar.+013+59973.key Xbar.+013+59973.private \ + Xbar.+013+60101.key Xbar.+013+60101.private; do + cp $i $(echo $i | sed s/X/K/) +done +$KEYGEN -a ECDSAP256SHA256 -q $zone >/dev/null +$DSFROMKEY Kbar.+013+60101.key >dsset-bar. +$SIGNER -S -o bar. -O full $zonefile >signing.bar.out 2>&1 + +# a zone with empty non-terminals. +zone=nsec3-with-ent +zonefile=nsec3-with-ent.db +infile=nsec3-with-ent.db.in +cat $infile >$zonefile +kskname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q -fk $zone) +$KEYGEN -a ${DEFAULT_ALGORITHM} -3 -q $zone >/dev/null + +# Copy zone input files +cp child.nsec3.example.db.in child.nsec3.example.db +cp child.optout.example.db.in child.optout.example.db +cp insecure.secure.example.db.in insecure.secure.example.db diff --git a/bin/tests/system/autosign/ns2/named.conf.in b/bin/tests/system/autosign/ns2/named.conf.in new file mode 100644 index 0000000..f4c555b --- /dev/null +++ b/bin/tests/system/autosign/ns2/named.conf.in @@ -0,0 +1,148 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; + dnssec-loadkeys-interval 30; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "autosign" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "private" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 2; +}; + +dnssec-policy "nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 0; +}; + +dnssec-policy "optout" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout yes salt-length 0; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; + sig-signing-type 65280; +}; + +zone "bar" { + type primary; + file "bar.db.signed"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; +}; + +zone "private.secure.example" { + type primary; + file "private.secure.example.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy private; +}; + +zone "insecure.secure.example" { + type primary; + file "insecure.secure.example.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "child.nsec3.example" { + type primary; + file "child.nsec3.example.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "child.optout.example" { + type primary; + file "child.optout.example.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy optout; +}; + +zone "nsec3-with-ent" { + type primary; + file "nsec3-with-ent.db"; + allow-query { any; }; + allow-transfer { any; }; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/autosign/ns2/nsec3-with-ent.db.in b/bin/tests/system/autosign/ns2/nsec3-with-ent.db.in new file mode 100644 index 0000000..5a3e207 --- /dev/null +++ b/bin/tests/system/autosign/ns2/nsec3-with-ent.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns2.example. . ( + 2010042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2.example. +sub1.ent NS . +sub2.ent NS . diff --git a/bin/tests/system/autosign/ns2/private.secure.example.db.in b/bin/tests/system/autosign/ns2/private.secure.example.db.in new file mode 100644 index 0000000..29fcddf --- /dev/null +++ b/bin/tests/system/autosign/ns2/private.secure.example.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +private2secure-nxdomain CNAME r.example. diff --git a/bin/tests/system/autosign/ns3/autonsec3.example.db.in b/bin/tests/system/autosign/ns3/autonsec3.example.db.in new file mode 100644 index 0000000..17964e8 --- /dev/null +++ b/bin/tests/system/autosign/ns3/autonsec3.example.db.in @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/autosign/ns3/delay.example.db.in b/bin/tests/system/autosign/ns3/delay.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/delay.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/delzsk.example.db.in b/bin/tests/system/autosign/ns3/delzsk.example.db.in new file mode 100644 index 0000000..14fef54 --- /dev/null +++ b/bin/tests/system/autosign/ns3/delzsk.example.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000010101 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +sub NS ns.sub + DS 12345 8 1 0000000000000000000000000000000000000000 +ns.sub A 10.53.0.3 diff --git a/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in b/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in new file mode 100644 index 0000000..080d111 --- /dev/null +++ b/bin/tests/system/autosign/ns3/dname-at-apex-nsec3.example.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns3.example. . 1 1200 1200 1814400 3600 +@ NS ns3.example. +@ DNAME example. +@ NSEC3PARAM 1 0 0 - diff --git a/bin/tests/system/autosign/ns3/inaczsk.example.db.in b/bin/tests/system/autosign/ns3/inaczsk.example.db.in new file mode 100644 index 0000000..1376922 --- /dev/null +++ b/bin/tests/system/autosign/ns3/inaczsk.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/inaczsk2.example.db.in b/bin/tests/system/autosign/ns3/inaczsk2.example.db.in new file mode 100644 index 0000000..1376922 --- /dev/null +++ b/bin/tests/system/autosign/ns3/inaczsk2.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/insecure.example.db b/bin/tests/system/autosign/ns3/insecure.example.db new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/autosign/ns3/insecure.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in b/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in new file mode 100644 index 0000000..8a96023 --- /dev/null +++ b/bin/tests/system/autosign/ns3/jitter.nsec3.example.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh new file mode 100644 index 0000000..54f53a4 --- /dev/null +++ b/bin/tests/system/autosign/ns3/keygen.sh @@ -0,0 +1,343 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +SYSTESTDIR=autosign + +dumpit() { + echo_d "${debug}: dumping ${1}" + cat "${1}" | cat_d +} + +setup() { + echo_i "setting up zone: $1" + debug="$1" + zone="$1" + zonefile="${zone}.db" + infile="${zonefile}.in" + n=$((${n:-0} + 1)) +} + +mkdir inactive + +setup secure.example +cp $infile $zonefile +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# NSEC3/NSEC test zone +# +setup secure.nsec3.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# NSEC3/NSEC3 test zone +# +setup nsec3.nsec3.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# Jitter/NSEC3 test zone +# +setup jitter.nsec3.example +cp $infile $zonefile +count=1 +while [ $count -le 1000 ]; do + echo "label${count} IN TXT label${count}" >>$zonefile + count=$((count + 1)) +done +# Don't create keys just yet, because the scenario we want to test +# is an unsigned zone that has a NSEC3PARAM record added with +# dynamic update before the keys are generated. + +# +# OPTOUT/NSEC3 test zone +# +setup optout.nsec3.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A nsec3 zone (non-optout). +# +setup nsec3.example +cat $infile dsset-*.${zone}. >$zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# An NSEC3 zone, with NSEC3 parameters set prior to signing +# +setup autonsec3.example +cat $infile >$zonefile +ksk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +echo $ksk >../autoksk.key +zsk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +echo $zsk >../autozsk.key +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# OPTOUT/NSEC test zone +# +setup secure.optout.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# OPTOUT/NSEC3 test zone +# +setup nsec3.optout.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# OPTOUT/OPTOUT test zone +# +setup optout.optout.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A optout nsec3 zone. +# +setup optout.example +cat $infile dsset-*.${zone}. >$zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A RSASHA256 zone. +# +setup rsasha256.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a RSASHA256 -b 2048 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a RSASHA256 -b 2048 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A RSASHA512 zone. +# +setup rsasha512.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a RSASHA512 -b 2048 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a RSASHA512 -b 2048 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# NSEC-only zone. A zone using NSEC-only DNSSEC algorithms. +# None of these algorithms are supported for signing in FIPS mode +# as they are MD5 and SHA1 based. +# +if [ $RSASHA1_SUPPORTED = 1 ]; then + setup nsec-only.example + cp $infile $zonefile + ksk=$($KEYGEN -q -a RSASHA1 -fk $zone 2>kg.out) || dumpit kg.out + $KEYGEN -q -a RSASHA1 $zone >kg.out 2>&1 || dumpit kg.out + $DSFROMKEY $ksk.key >dsset-${zone}. +else + echo_i "skip: nsec-only.example - signing with RSASHA1 not supported" +fi + +# +# Signature refresh test zone. Signatures are set to expire long +# in the past; they should be updated by autosign. +# +setup oldsigs.example +cp $infile $zonefile +count=1 +while [ $count -le 1000 ]; do + echo "label${count} IN TXT label${count}" >>$zonefile + count=$((count + 1)) +done +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$SIGNER -PS -x -s now-1y -e now-6mo -o $zone -f $zonefile.signed $zonefile >s.out || dumpit s.out +cp $zonefile.signed $zonefile.bak +mv $zonefile.signed $zonefile + +# +# NSEC3->NSEC transition test zone. +# +setup nsec3-to-nsec.example +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out + +# +# NSEC3->NSEC3 transition test zone. +# +setup nsec3-to-nsec3.example +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out + +# +# Introducing a pre-published key test. +# +setup prepub.example +infile="prepub.example.db.in" +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone >kg.out 2>&1 || dumpit kg.out +zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone 2>kg.out) || dumpit kg.out +echo $zsk >../prepub.key +$SIGNER -S -3 beef -o $zone -f $zonefile $infile >s.out || dumpit s.out + +# +# Key TTL tests. +# + +# no default key TTL; DNSKEY should get SOA TTL +setup ttl1.example +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +cp $infile $zonefile + +# default key TTL should be used +setup ttl2.example +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 60 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone >kg.out 2>&1 || dumpit kg.out +cp $infile $zonefile + +# mismatched key TTLs, should use shortest +setup ttl3.example +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 30 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone >kg.out 2>&1 || dumpit kg.out +cp $infile $zonefile + +# existing DNSKEY RRset, should retain TTL +setup ttl4.example +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 -fk $zone >kg.out 2>&1 || dumpit kg.out +cat ${infile} K${zone}.+*.key >$zonefile +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 180 $zone >kg.out 2>&1 || dumpit kg.out + +# +# A zone with a DNSKEY RRset that is published before it's activated +# +setup delay.example +ksk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +echo $ksk >../delayksk.key +zsk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +echo $zsk >../delayzsk.key +cp delay.example.db.in delay.example.db + +# +# A zone with signatures that are already expired, and the private KSK +# is missing. +# +setup noksk.example +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out +echo $ksk >../noksk-ksk.key +rm -f ${ksk}.private + +# +# A zone with signatures that are already expired, and the private ZSK +# is missing. +# +setup nozsk.example +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out +echo $ksk >../nozsk-ksk.key +echo $zsk >../nozsk-zsk.key +rm -f ${zsk}.private + +# +# A zone with signatures that are already expired, and the private ZSK +# is inactive. +# +setup inaczsk.example +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +$SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out +echo $ksk >../inaczsk-ksk.key +echo $zsk >../inaczsk-zsk.key +$SETTIME -I now $zsk >st.out 2>&1 || dumpit st.out + +# +# A zone that is set to 'dnssec-policy' during a reconfig +# +setup reconf.example +cp secure.example.db.in $zonefile +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out + +# +# A zone which generates CDS and CDNSEY RRsets automatically (with an additional CSK) +# +setup sync.example +cp $infile $zonefile +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. +echo ns3/$ksk >../sync.key + +# +# A zone that generates CDS and CDNSKEY automatically +# +setup kskonly.example +cp $infile $zonefile +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A zone that has a published inactive key that is autosigned. +# +setup inaczsk2.example +cp $infile $zonefile +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. + +# +# A zone that starts with an active KSK + ZSK and an inactive ZSK, with the +# latter getting deleted during the test. +# +setup delzsk.example +cp $infile $zonefile +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -I now-1w $zone 2>kg.out) || dumpit kg.out +cat $zsk.key >>$zonefile +mv $zsk.key inactive/ +mv $zsk.private inactive/ +echo $zsk >../delzsk.key + +# +# Check that NSEC3 are correctly signed and returned from below a DNAME +# +setup dname-at-apex-nsec3.example +cp $infile $zonefile +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$DSFROMKEY $ksk.key >dsset-${zone}. diff --git a/bin/tests/system/autosign/ns3/kskonly.example.db.in b/bin/tests/system/autosign/ns3/kskonly.example.db.in new file mode 100644 index 0000000..c6c7f88 --- /dev/null +++ b/bin/tests/system/autosign/ns3/kskonly.example.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in new file mode 100644 index 0000000..3707a2c --- /dev/null +++ b/bin/tests/system/autosign/ns3/named.conf.in @@ -0,0 +1,397 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; + dnssec-loadkeys-interval 10; + allow-new-zones yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +# The default +dnssec-policy "autosign" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +# Additional CSK +dnssec-policy "sync" { + keys { + csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +# NSEC3 +dnssec-policy "nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 0; +}; + +# NSEC3 opt-out +dnssec-policy "optout" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout yes salt-length 0; +}; + +# Jitter +dnssec-policy "jitter" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + signatures-validity P10D; + signatures-validity-dnskey P10D; + signatures-refresh P2D; + signatures-jitter P8D; +}; + +# Jitter, NSEC3 +dnssec-policy "jitter-nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 0; + + signatures-validity P10D; + signatures-validity-dnskey P10D; + signatures-refresh P2D; + +}; + +# RSASHA256 +dnssec-policy "rsasha256" { + keys { + ksk key-directory lifetime unlimited algorithm RSASHA256 2048; + zsk key-directory lifetime unlimited algorithm RSASHA256 2048; + }; +}; + +# RSASHA512 +dnssec-policy "rsasha512" { + keys { + ksk key-directory lifetime unlimited algorithm RSASHA512 2048; + zsk key-directory lifetime unlimited algorithm RSASHA512 2048; + }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.2; }; + file "example.bk"; +}; + +zone "bar" { + type secondary; + primaries { 10.53.0.2; }; + file "bar.bk"; +}; + +zone "secure.example" { + type primary; + file "secure.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "insecure.example" { + type primary; + file "insecure.example.db"; + dnssec-policy none; +}; + +zone "nsec3.example" { + type primary; + file "nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "autonsec3.example" { + type primary; + file "autonsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "optout.nsec3.example" { + type primary; + file "optout.nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy optout; +}; + +zone "nsec3.nsec3.example" { + type primary; + file "nsec3.nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "jitter.nsec3.example" { + type primary; + file "jitter.nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy jitter-nsec3; + sig-signing-nodes 1000; + sig-signing-signatures 100; +}; + +zone "secure.nsec3.example" { + type primary; + file "secure.nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "optout.example" { + type primary; + file "optout.example.db"; + allow-update { any; }; + dnssec-policy optout; +}; + +zone "secure.optout.example" { + type primary; + file "secure.optout.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy optout; +}; + +zone "nsec3.optout.example" { + type primary; + file "nsec3.optout.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy optout; +}; + +zone "optout.optout.example" { + type primary; + file "optout.optout.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy optout; +}; + +zone "rsasha256.example" { + type primary; + file "rsasha256.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy rsasha256; +}; + +zone "rsasha512.example" { + type primary; + file "rsasha512.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy rsasha512; +}; + +zone "nsec-only.example" { + type primary; + file "nsec-only.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "nsec3-to-nsec.example" { + type primary; + file "nsec3-to-nsec.example.db"; + allow-update { any; }; + inline-signing no; + max-journal-size 10M; + dnssec-policy autosign; +}; + +zone "nsec3-to-nsec3.example" { + type primary; + file "nsec3-to-nsec3.example.db"; + allow-update { any; }; + inline-signing no; + max-journal-size 10M; + dnssec-policy nsec3; +}; + +zone "oldsigs.example" { + type primary; + file "oldsigs.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy jitter; + sig-signing-nodes 1000; + sig-signing-signatures 100; +}; + +zone "prepub.example" { + type primary; + file "prepub.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "ttl1.example" { + type primary; + file "ttl1.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "ttl2.example" { + type primary; + file "ttl2.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "ttl3.example" { + type primary; + file "ttl3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "ttl4.example" { + type primary; + file "ttl4.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "delay.example" { + type primary; + file "delay.example.db"; +}; + +zone "nozsk.example" { + type primary; + file "nozsk.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "inaczsk.example" { + type primary; + file "inaczsk.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "noksk.example" { + type primary; + file "noksk.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "sync.example" { + type primary; + file "sync.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy sync; +}; + +zone "kskonly.example" { + type primary; + file "kskonly.example.db"; + allow-update { any; }; + dnssec-policy autosign; +}; + +zone "inaczsk2.example" { + type primary; + file "inaczsk2.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy autosign; +}; + +zone "delzsk.example." { + type primary; + file "delzsk.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +zone "dname-at-apex-nsec3.example" { + type primary; + file "dname-at-apex-nsec3.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec3; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/autosign/ns3/noksk.example.db.in b/bin/tests/system/autosign/ns3/noksk.example.db.in new file mode 100644 index 0000000..1376922 --- /dev/null +++ b/bin/tests/system/autosign/ns3/noksk.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/nozsk.example.db.in b/bin/tests/system/autosign/ns3/nozsk.example.db.in new file mode 100644 index 0000000..5d244c3 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nozsk.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 ; 1 hour +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/nsec-only.example.db.in b/bin/tests/system/autosign/ns3/nsec-only.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec-only.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in b/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec3-to-nsec.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/nsec3-to-nsec3.example.db.in b/bin/tests/system/autosign/ns3/nsec3-to-nsec3.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec3-to-nsec3.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/nsec3.example.db.in b/bin/tests/system/autosign/ns3/nsec3.example.db.in new file mode 100644 index 0000000..17964e8 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec3.example.db.in @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in b/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec3.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in b/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec3.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/oldsigs.example.db.in b/bin/tests/system/autosign/ns3/oldsigs.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/oldsigs.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/optout.example.db.in b/bin/tests/system/autosign/ns3/optout.example.db.in new file mode 100644 index 0000000..fbb05af --- /dev/null +++ b/bin/tests/system/autosign/ns3/optout.example.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +child NS ns2.example. +insecure.empty NS ns.insecure.empty +ns.insecure.empty A 10.53.0.3 diff --git a/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in b/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/optout.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/optout.optout.example.db.in b/bin/tests/system/autosign/ns3/optout.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/optout.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/prepub.example.db.in b/bin/tests/system/autosign/ns3/prepub.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/autosign/ns3/prepub.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/autosign/ns3/rsasha256.example.db.in b/bin/tests/system/autosign/ns3/rsasha256.example.db.in new file mode 100644 index 0000000..f6c4fab --- /dev/null +++ b/bin/tests/system/autosign/ns3/rsasha256.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/rsasha512.example.db.in b/bin/tests/system/autosign/ns3/rsasha512.example.db.in new file mode 100644 index 0000000..f6c4fab --- /dev/null +++ b/bin/tests/system/autosign/ns3/rsasha512.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in b/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/autosign/ns3/secure-to-insecure.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/autosign/ns3/secure.example.db.in b/bin/tests/system/autosign/ns3/secure.example.db.in new file mode 100644 index 0000000..9855ec0 --- /dev/null +++ b/bin/tests/system/autosign/ns3/secure.example.db.in @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + +dname-and-txt DNAME @ + TXT "DNAME and TXT" diff --git a/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/secure.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/secure.optout.example.db.in b/bin/tests/system/autosign/ns3/secure.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/autosign/ns3/secure.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/autosign/ns3/sync.example.db.in b/bin/tests/system/autosign/ns3/sync.example.db.in new file mode 100644 index 0000000..c6c7f88 --- /dev/null +++ b/bin/tests/system/autosign/ns3/sync.example.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 diff --git a/bin/tests/system/autosign/ns3/ttl1.example.db.in b/bin/tests/system/autosign/ns3/ttl1.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/ttl1.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/ttl2.example.db.in b/bin/tests/system/autosign/ns3/ttl2.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/ttl2.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/ttl3.example.db.in b/bin/tests/system/autosign/ns3/ttl3.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/ttl3.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns3/ttl4.example.db.in b/bin/tests/system/autosign/ns3/ttl4.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/autosign/ns3/ttl4.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/autosign/ns4/named.conf.in b/bin/tests/system/autosign/ns4/named.conf.in new file mode 100644 index 0000000..13a8e89 --- /dev/null +++ b/bin/tests/system/autosign/ns4/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + dnssec-must-be-secure mustbesecure.example yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; +include "private.conf"; diff --git a/bin/tests/system/autosign/ns5/named.conf.in b/bin/tests/system/autosign/ns5/named.conf.in new file mode 100644 index 0000000..e0927da --- /dev/null +++ b/bin/tests/system/autosign/ns5/named.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/autosign/setup.sh b/bin/tests/system/autosign/setup.sh new file mode 100644 index 0000000..e029fdf --- /dev/null +++ b/bin/tests/system/autosign/setup.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +echo_i "generating keys and preparing zones" +cd ns1 && $SHELL keygen.sh diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh new file mode 100755 index 0000000..14064af --- /dev/null +++ b/bin/tests/system/autosign/tests.sh @@ -0,0 +1,1369 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +# convert private-type records to readable form +# $1 is the zone +# $2 is the server +# $3 is ignored +# $4 is the alternate type +showprivate() { + echo "-- $@ --" + $DIG $DIGOPTS +nodnssec +short @$2 -t ${4:-type65534} $1 | cut -f3 -d' ' \ + | while read record; do + $PERL -e 'my $rdata = pack("H*", @ARGV[0]); + die "invalid record" unless length($rdata) == 5; + my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata); + my $action = "signing"; + $action = "removing" if $remove; + my $state = " (incomplete)"; + $state = " (complete)" if $complete; + print ("$action: alg: $alg, key: $key$state\n");' $record + done +} + +# check that signing records are marked as complete +# if $3 is 1 then we are expecting "(incomplete)" +# if $3 is 2 then we are not expecting either "(complete)" or "(incomplete)" +# if $4 is present then that specifies any alternate type to check +checkprivate() { + _ret=0 + expected="${3:-0}" + x=$(showprivate "$@") + echo $x | grep "(complete)" >/dev/null || _ret=2 + echo $x | grep "(incomplete)" >/dev/null && _ret=1 + + if [ $_ret = $expected ]; then + return 0 + fi + + echo "$x" + echo_i "failed" + return 1 +} + +# wait until notifies for zone $1 are sent by server $2. This is an indication +# that the zone is signed with the active keys, and the changes have been +# committed. +wait_for_notifies() { + wait_for_log 10 "zone ${1}/IN: sending notifies" "${2}/named.run" || return 1 +} + +freq() { + _file=$1 + # remove first and last line that has incomplete set and skews the distribution + awk '$4 == "RRSIG" {print substr($9,1,8)}' <"$_file" | sort | uniq -c | sed '1d;$d' +} +# Check the signatures expiration times. First check how many signatures +# there are in total ($rrsigs). Then see what the distribution of signature +# expiration times is ($expiretimes). Ignore the time part for a better +# modelled distribution. +checkjitter() { + _file=$1 + _ret=0 + + if ! command -v bc >/dev/null 2>&1; then + echo_i "skip: bc not available" + return 0 + fi + + freq "$_file" | cat_i + _expiretimes=$(freq "$_file" | awk '{print $1}') + + _count=0 + # Check if we have at least 4 days + # This number has been tuned for `signatures-validity 10d; signatures-jitter 8d`, as + # 1. signature expiration dates should be spread out across at most 8 days + # 2. we remove first and last day to remove frequency outlier, we are left with 6 days + # 3. we subtract two more days to allow test pass on day boundaries, etc. leaving us with 4 days + for _num in $_expiretimes; do + _count=$((_count + 1)) + done + if [ "$_count" -lt 4 ]; then + echo_i "error: not enough categories" + return 1 + fi + + # Calculate mean + _total=0 + for _num in $_expiretimes; do + _total=$((_total + _num)) + done + _mean=$(($_total / $_count)) + + # Calculate stddev + _stddev=0 + for _num in $_expiretimes; do + _stddev=$(echo "$_stddev + (($_num - $_mean) * ($_num - $_mean))" | bc) + done + _stddev=$(echo "sqrt($_stddev/$_count)" | bc) + + # We expect the number of signatures not to exceed the mean +- 3 * stddev. + _limit=$((_stddev * 3)) + _low=$((_mean - _limit)) + _high=$((_mean + _limit)) + # Find outliers. + echo_i "checking whether all frequencies fall into <$_low;$_high> range" + for _num in $_expiretimes; do + if [ $_num -gt $_high ]; then + echo_i "error: too many RRSIG records ($_num) in expiration bucket" + _ret=1 + fi + if [ $_num -lt $_low ]; then + echo_i "error: too few RRSIG records ($_num) in expiration bucket" + _ret=1 + fi + done + + return $_ret +} + +# +# The NSEC record at the apex of the zone and its RRSIG records are +# added as part of the last step in signing a zone. We wait for the +# NSEC records to appear before proceeding with a counter to prevent +# infinite loops if there is a error. +# +echo_i "waiting for autosign changes to take effect" +i=0 +while [ $i -lt 30 ]; do + ret=0 + # + # Wait for the root DNSKEY RRset to be fully signed. + # + $DIG $DIGOPTS . @10.53.0.1 dnskey >dig.out.ns1.test$n.dnskey || ret=1 + grep "ANSWER: 11," dig.out.ns1.test$n.dnskey >/dev/null || ret=1 + for z in .; do + $DIG $DIGOPTS $z @10.53.0.1 nsec >dig.out.ns1.test$n.nsec || ret=1 + grep "NS SOA" dig.out.ns1.test$n.nsec >/dev/null || ret=1 + done + for z in bar. example.; do # skip NSEC3 signed zones + $DIG $DIGOPTS $z @10.53.0.2 nsec >dig.out.ns2.test$n.$z || ret=1 + grep "NS SOA" dig.out.ns2.test$n.$z >/dev/null || ret=1 + done + for z in bar. example. inaczsk2.example. noksk.example nozsk.example; do + $DIG $DIGOPTS $z @10.53.0.3 nsec >dig.out.ns3.test$n.$z || ret=1 + grep "NS SOA" dig.out.ns3.test$n.$z >/dev/null || ret=1 + done + i=$((i + 1)) + if [ $ret = 0 ]; then break; fi + echo_i "waiting ... ($i)" + sleep 2 +done +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Initial counts of RRSIG expiry fields values for auto signed zones" +for z in .; do + echo_i zone $z + $DIG $DIGOPTS $z @10.53.0.1 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i +done +for z in bar. example. private.secure.example.; do + echo_i zone $z + $DIG $DIGOPTS $z @10.53.0.2 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i +done +for z in inaczsk2.example.; do + echo_i zone $z + $DIG $DIGOPTS $z @10.53.0.3 axfr | awk '$4 == "RRSIG" {print $9}' | sort | uniq -c | cat_i +done + +# Set logfile offset for wait_for_log usage. +nextpartreset ns3/named.run + +echo_i "signing preset nsec3 zone" +zsk=$(cat autozsk.key) +ksk=$(cat autoksk.key) +$SETTIME -K ns3 -P now -A now $zsk >settime.out.test$n.zsk || ret=1 +$SETTIME -K ns3 -P now -A now $ksk >settime.out.test$n.ksk || ret=1 +($RNDCCMD 10.53.0.3 loadkeys autonsec3.example. 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 + +echo_i "waiting for changes to take effect" +sleep 3 + +missing=$(keyfile_to_key_id "$(cat noksk-ksk.key)") +echo_i "checking that expired RRSIGs from missing KSK $missing are not deleted ($n)" +ret=0 +$JOURNALPRINT ns3/noksk.example.db.jnl \ + | awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {error=1}} END {exit error}' id=$missing || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +missing=$(keyfile_to_key_id "$(cat nozsk-zsk.key)") +ksk=$(keyfile_to_key_id "$(cat nozsk-ksk.key)") +echo_i "checking that expired RRSIGs from missing ZSK $missing are replaced ($n)" +ret=0 +$JOURNALPRINT ns3/nozsk.example.db.jnl \ + | awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$missing || ret=1 +$JOURNALPRINT ns3/nozsk.example.db.jnl \ + | awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +inactive=$(keyfile_to_key_id "$(cat inaczsk-zsk.key)") +ksk=$(keyfile_to_key_id "$(cat inaczsk-ksk.key)") +echo_i "checking that expired RRSIGs from inactive ZSK $inactive are replaced ($n)" +ret=0 +$JOURNALPRINT ns3/inaczsk.example.db.jnl \ + | awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$inactive || ret=1 +$JOURNALPRINT ns3/inaczsk.example.db.jnl \ + | awk '{if ($1 == "add" && $5 == "RRSIG" && $12 == id) {ok=1}} END {exit ok?0:1}' id=$ksk || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that replaced RRSIGs are not logged (missing ZSK private key) ($n)" +ret=0 +loglines=$(grep "Key nozsk.example/$DEFAULT_ALGORITHM/$missing .* retaining signatures" ns3/named.run | wc -l) +[ "$loglines" -eq 0 ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that replaced RRSIGs are not logged (inactive ZSK private key) ($n)" +ret=0 +loglines=$(grep "Key inaczsk.example/$DEFAULT_ALGORITHM/$inactive .* retaining signatures" ns3/named.run | wc -l) +[ "$loglines" -eq 0 ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Send rndc sync command to ns1, ns2 and ns3, to force the dynamically +# signed zones to be dumped to their zone files +echo_i "dumping zone files" +($RNDCCMD 10.53.0.1 sync 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +($RNDCCMD 10.53.0.2 sync 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 +($RNDCCMD 10.53.0.3 sync 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 + +now="$(TZ=UTC date +%Y%m%d%H%M%S)" +check_expiry() ( + $DIG $DIGOPTS AXFR oldsigs.example @10.53.0.3 >dig.out.test$n || return 1 + nearest_expiration="$(awk '$4 == "RRSIG" { print $9 }' dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check jitter distribution. +echo_i "checking expired signatures were jittered correctly ($n)" +ret=0 +$DIG $DIGOPTS axfr oldsigs.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 +checkjitter dig.out.ns3.test$n || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NSEC->NSEC3 conversion succeeded ($n)" +ret=0 +$DIG $DIGOPTS nsec3.example. nsec3param @10.53.0.3 >dig.out.ns3.ok.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.ok.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking direct NSEC3 autosigning succeeded ($n)" +ret=0 +$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 >dig.out.ns3.ok.test$n || ret=1 +[ -s dig.out.ns3.ok.test$n ] || ret=1 +grep "NSEC3PARAM" dig.out.ns3.ok.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTLs of imported DNSKEYs (no default) ($n)" +ret=0 +$DIG $DIGOPTS +tcp +noall +answer dnskey ttl1.example. @10.53.0.3 >dig.out.ns3.test$n || ret=1 +[ -s dig.out.ns3.test$n ] || ret=1 +(awk 'BEGIN {r=0} $2 != 300 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTLs of imported DNSKEYs (with default) ($n)" +ret=0 +$DIG $DIGOPTS +tcp +noall +answer dnskey ttl2.example. @10.53.0.3 >dig.out.ns3.test$n || ret=1 +[ -s dig.out.ns3.test$n ] || ret=1 +(awk 'BEGIN {r=0} $2 != 60 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTLs of imported DNSKEYs (mismatched) ($n)" +ret=0 +$DIG $DIGOPTS +tcp +noall +answer dnskey ttl3.example. @10.53.0.3 >dig.out.ns3.test$n || ret=1 +[ -s dig.out.ns3.test$n ] || ret=1 +(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTLs of imported DNSKEYs (existing RRset) ($n)" +ret=0 +$DIG $DIGOPTS +tcp +noall +answer dnskey ttl4.example. @10.53.0.3 >dig.out.ns3.test$n || ret=1 +[ -s dig.out.ns3.test$n ] || ret=1 +(awk 'BEGIN {r=0} $2 != 30 {r=1; print "found TTL " $2} END {exit r}' dig.out.ns3.test$n | cat_i) || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking positive validation NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking positive validation NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking positive validation OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NXDOMAIN NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth q.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth q.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NXDOMAIN OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth q.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth q.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NODATA NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NODATA NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking negative validation NODATA OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the insecure.example domain + +echo_i "checking 1-server insecurity proof NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking 1-server negative insecurity proof NSEC ($n)" +ret=0 +$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the secure.example domain + +echo_i "checking multi-stage positive validation NSEC/NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.secure.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.secure.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.secure.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.secure.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.optout.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.optout.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.secure.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.secure.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.nsec3.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.nsec3.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.optout.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.optout.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking empty NODATA OPTOUT ($n)" +ret=0 +$DIG $DIGOPTS +noauth empty.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth empty.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the insecure.secure.example domain (insecurity proof) + +echo_i "checking 2-server insecurity proof ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \ + >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check a negative response in insecure.secure.example + +echo_i "checking 2-server insecurity proof with a negative answer ($n)" +ret=0 +$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a >dig.out.ns2.test$n \ + || ret=1 +$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a >dig.out.ns4.test$n \ + || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking security root query ($n)" +ret=0 +$DIG $DIGOPTS . @10.53.0.4 key >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking positive validation RSASHA256 NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking positive validation RSASHA512 NSEC ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that positive validation in a privately secure zone works ($n)" +ret=0 +$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that negative validation in a privately secure zone works ($n)" +ret=0 +$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking privately secure to nxdomain works ($n)" +ret=0 +$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Try validating with a revoked trusted key. +# This should fail. + +echo_i "checking that validation returns insecure due to revoked trusted key ($n)" +ret=0 +$DIG $DIGOPTS example. soa @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "flags:.*; QUERY" dig.out.ns5.test$n >/dev/null || ret=1 +grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that revoked key is present ($n)" +ret=0 +id=$(cat rev.key) +$DIG $DIGOPTS +multi dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '; key id = '"$id"'$' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that revoked key self-signs ($n)" +ret=0 +id=$(cat rev.key) +$DIG $DIGOPTS dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for unpublished key ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat unpub.key)") +$DIG $DIGOPTS +multi dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '; key id = '"$id"'$' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for activated but unpublished key ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat activate-now-publish-1day.key)") +$DIG $DIGOPTS +multi dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '; key id = '"$id"'$' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that standby key does not sign records ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat standby.key)") +$DIG $DIGOPTS dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that deactivated key does not sign records ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat inact.key)") +$DIG $DIGOPTS dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking insertion of public-only key ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat nopriv.key)") +file="ns1/$(cat nopriv.key).key" +keydata=$(grep DNSKEY $file) +$NSUPDATE >/dev/null 2>&1 <dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking key deletion ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat del.key)") +$DIG $DIGOPTS +multi dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '; key id = '"$id"'$' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that serial number and RRSIGs are both updated (rt21045) ($n)" +ret=0 +$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 +oldserial=$(cat dig.out.ns3.test$n | awk '$0 !~ /SOA/ {print $3}') +oldinception=$(cat dig.out.ns3.test$n | awk '/SOA/ {print $6}' | sort -u) +id=$(keyfile_to_key_id "$(cat prepub.key)") +echo_i "prepublish key for ZSK $id" +($RNDCCMD 10.53.0.3 dnssec -rollover -key $id prepub.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 +newserial=$oldserial +try=0 +while [ $oldserial -eq $newserial -a $try -lt 42 ]; do + $DIG $DIGOPTS +short soa prepub.example @10.53.0.3 >dig.out.ns3.test$n.2 || true + newserial=$(cat dig.out.ns3.test$n.2 | awk '$0 !~ /SOA/ {print $3}') + sleep 1 + try=$((try + 1)) +done +newinception=$(cat dig.out.ns3.test$n.2 | awk '/SOA/ {print $6}' | sort -u) +#echo "$oldserial : $newserial" +#echo "$oldinception : $newinception" + +[ "$oldserial" = "$newserial" ] && ret=1 +[ "$oldinception" = "$newinception" ] && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "preparing ZSK roll" +starttime=$($PERL -e 'print time(), "\n";') +oldfile=$(cat active.key) +oldid=$(keyfile_to_key_id "$(cat active.key)") +newfile=$(cat standby.key) +newid=$(keyfile_to_key_id "$(cat standby.key)") +$SETTIME -K ns1 -I now -D now+25 $oldfile >settime.out.test$n.1 || ret=1 +$SETTIME -K ns1 -i 0 -S $oldfile $newfile >settime.out.test$n.2 || ret=1 + +# note previous zone serial number +oldserial=$($DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}') + +($RNDCCMD 10.53.0.1 freeze . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +cp ns1/root.db.signed ns1/root.db.1 +$SIGNER -S -o . -O full -K ns1 -f ns1/root.db.signed ns1/root.db.1 >signing.root.out$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.1 thaw . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +sleep 4 + +echo_i "revoking key to duplicated key ID" +$SETTIME -R now -K ns2 Kbar.+013+59973.key >settime.out.test$n.3 || ret=1 + +($RNDCCMD 10.53.0.2 freeze bar. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 +cp ns2/bar.db.signed ns2/bar.db +$SIGNER -S -o bar. -O full -K ns2 ns2/bar.db >signing.bar.out$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.2 thaw bar. 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1 + +echo_i "waiting for changes to take effect" +sleep 5 + +echo_i "checking former standby key $newid is now active ($n)" +ret=0 +$DIG $DIGOPTS dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking former standby key has only signed incrementally ($n)" +ret=0 +$DIG $DIGOPTS txt . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n >/dev/null && ret=1 +grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that signing records have been marked as complete ($n)" +ret=0 +checkprivate example 10.53.0.2 0 type65280 || ret=1 # sig-signing-type 65280 +checkprivate private.secure.example 10.53.0.3 2 || ret=1 # pre-signed +checkprivate nsec3.example 10.53.0.3 || ret=1 +checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1 +checkprivate nsec3.optout.example 10.53.0.3 || ret=1 +checkprivate nsec3-to-nsec.example 10.53.0.3 2 || ret=1 # automatically removed +checkprivate nsec3-to-nsec3.example 10.53.0.3 2 || ret=1 # automatically removed +if [ $RSASHA1_SUPPORTED = 1 ]; then + checkprivate nsec-only.example 10.53.0.3 || ret=1 +fi +checkprivate oldsigs.example 10.53.0.3 2 || ret=1 # pre-signed +checkprivate optout.example 10.53.0.3 || ret=1 +checkprivate optout.nsec3.example 10.53.0.3 || ret=1 +checkprivate optout.optout.example 10.53.0.3 || ret=1 +checkprivate prepub.example 10.53.0.3 2 || ret=1 # pre-signed +checkprivate rsasha256.example 10.53.0.3 || ret=1 +checkprivate rsasha512.example 10.53.0.3 || ret=1 +checkprivate secure.example 10.53.0.3 || ret=1 +checkprivate secure.nsec3.example 10.53.0.3 || ret=1 +checkprivate secure.optout.example 10.53.0.3 || ret=1 +checkprivate ttl1.example 10.53.0.3 || ret=1 +checkprivate ttl2.example 10.53.0.3 || ret=1 +checkprivate ttl3.example 10.53.0.3 || ret=1 +checkprivate ttl4.example 10.53.0.3 || ret=1 +n=$((n + 1)) +status=$((status + ret)) + +echo_i "forcing full sign ($n)" +ret=0 +($RNDCCMD 10.53.0.1 freeze . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +cp ns1/root.db.signed ns1/root.db.2 +$SIGNER -S -o . -O full -K ns1 -f ns1/root.db.signed ns1/root.db >signing.root.out$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.1 thaw . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +echo_i "waiting for change to take effect" +sleep 5 + +echo_i "checking former standby key $newid has now signed fully ($n)" +ret=0 +$DIG $DIGOPTS txt . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking SOA serial number has been incremented ($n)" +ret=0 +newserial=$($DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}') +[ "$newserial" != "$oldserial" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "preparing to test key change corner cases" +echo_i "removing a private key file" +file="ns1/$(cat vanishing.key).private" +rm -f $file + +echo_i "checking delayed key publication/activation ($n)" +ret=0 +zsk=$(cat delayzsk.key) +ksk=$(cat delayksk.key) +# publication and activation times should be unset +$SETTIME -K ns3 -pA -pP $zsk >settime.out.test$n.zsk || ret=1 +grep -v UNSET settime.out.test$n.zsk >/dev/null && ret=1 +$SETTIME -K ns3 -pA -pP $ksk >settime.out.test$n.ksk || ret=1 +grep -v UNSET settime.out.test$n.ksk >/dev/null && ret=1 +$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 >dig.out.ns3.test$n || ret=1 +# DNSKEY not expected: +awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking scheduled key publication, not activation ($n)" +ret=0 +# Ensure initial zone is loaded. +wait_for_notifies "delay.example" "ns3" || ret=1 +$SETTIME -K ns3 -P now -A none $zsk >settime.out.test$n.zsk || ret=1 +$SETTIME -K ns3 -P now -A none $ksk >settime.out.test$n.ksk || ret=1 +cp ns3/delay.example.db ns3/delay.example.1 +# This will create a non valid DNSSEC zone, disable post-sign verification +$SIGNER -P -S -o delay.example. -O full -N increment -K ns3 -f ns3/delay.example.db ns3/delay.example.1 >signing.delay.out.$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.3 reload delay.example | sed 's/^/ns3 /' | cat_i) || ret=1 +check_has_dnskey() { + $DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 >dig.out.ns3.test$n || return 1 + # DNSKEY expected: + awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n || return 1 + # RRSIG not expected: + awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.test$n && return 1 + return 0 +} +retry_quiet 5 check_has_dnskey || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking scheduled key activation ($n)" +ret=0 +sleep 1 # ensure file system time stamp of ns3/delay.example.db changes +$SETTIME -K ns3 -A now $zsk >settime.out.test$n.zsk || ret=1 +$SETTIME -K ns3 -A now $ksk >settime.out.test$n.ksk || ret=1 +cp ns3/delay.example.db ns3/delay.example.2 +$SIGNER -S -o delay.example. -O full -N increment -K ns3 -f ns3/delay.example.db ns3/delay.example.2 >signing.delay.out.$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.3 reload delay.example | sed 's/^/ns3 /' | cat_i) || ret=1 +check_is_signed() { + $DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 >dig.out.ns3.1.test$n || return 1 + # DNSKEY expected: + awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1 + # RRSIG expected: + awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || return 1 + $DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 >dig.out.ns3.2.test$n || return 1 + # A expected: + awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1 + # RRSIG expected: + awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || return 1 + return 0 +} +retry_quiet 5 check_is_signed || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking former active key was removed ($n)" +# +# Work out how long we need to sleep. Allow 4 seconds for the records +# to be removed. +# +now=$($PERL -e 'print time(), "\n";') +sleep=$((starttime + 29 - now)) +case $sleep in + -* | 0) ;; + *) + echo_i "waiting $sleep seconds for timer to have activated" + sleep $sleep + ;; +esac +ret=0 +($RNDCCMD 10.53.0.1 freeze . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +cp ns1/root.db.signed ns1/root.db.3 +$SIGNER -v 3 -S -o . -O full -K ns1 -f ns1/root.db.signed ns1/root.db.3 >signing.root.out$n 2>&1 || ret=1 +($RNDCCMD 10.53.0.1 thaw . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +$DIG $DIGOPTS +multi dnskey . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '; key id = '"$oldid"'$' dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +id=$(keyfile_to_key_id "$(cat vanishing.key)") +echo_i "checking private key file $id removal caused no immediate harm ($n)" +ret=0 +id=$(keyfile_to_key_id "$(cat vanishing.key)") +$DIG $DIGOPTS soa . @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking revoked key with duplicate key ID ($n)" +ret=0 +id=59973 +rid=60101 +$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep '; key id = '"$id"'$' dig.out.ns2.test$n >/dev/null && ret=1 +keys=$(grep '; key id = '"$rid"'$' dig.out.ns2.test$n | wc -l) +test $keys -eq 2 || ret=1 +$DIG $DIGOPTS dnskey bar @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking key event timers are always set ($n)" +ret=0 +# this is a regression test for a bug in which the next key event could +# be scheduled for the present moment, and then never fire. check for +# visible evidence of this error in the logs: +awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "forcing full sign with unreadable keys ($n)" +ret=0 +chmod 0 ns1/K.+*+*.key ns1/K.+*+*.private || ret=1 +($RNDCCMD 10.53.0.1 sign . 2>&1 | sed 's/^/ns1 /' | cat_i) || ret=1 +$DIG $DIGOPTS . @10.53.0.1 dnskey >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "test turning on dnssec-policy during reconfig ($n)" +ret=0 +# first create a zone that doesn't have dnssec-policy +($RNDCCMD 10.53.0.3 addzone reconf.example '{ type primary; file "reconf.example.db"; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 +rekey_calls=$(grep "zone reconf.example.*next key event" ns3/named.run | wc -l) +[ "$rekey_calls" -eq 0 ] || ret=1 +# ...then we add dnssec-policy and reconfigure +($RNDCCMD 10.53.0.3 modzone reconf.example '{ type primary; file "reconf.example.db"; allow-update { any; }; dnssec-policy default; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 +rndc_reconfig ns3 10.53.0.3 +for i in 0 1 2 3 4 5 6 7 8 9; do + lret=0 + rekey_calls=$(grep "zone reconf.example.*next key event" ns3/named.run | wc -l) + [ "$rekey_calls" -gt 0 ] || lret=1 + if [ "$lret" -eq 0 ]; then break; fi + echo_i "waiting ... ($i)" + sleep 1 +done +n=$((n + 1)) +if [ "$lret" != 0 ]; then ret=$lret; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "test CDS and CDNSKEY auto generation ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 sync.example cds >dig.out.ns3.cdstest$n || ret=1 +$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey >dig.out.ns3.cdnskeytest$n || ret=1 +grep -i "sync.example.*in.cds.*[1-9][0-9]* " dig.out.ns3.cdstest$n >/dev/null || ret=1 +grep -i "sync.example.*in.cdnskey.*257 " dig.out.ns3.cdnskeytest$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "test 'csk' affects DNSKEY/CDS/CDNSKEY ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 sync.example dnskey >dig.out.ns3.dnskeytest$n || ret=1 +$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey >dig.out.ns3.cdnskeytest$n || ret=1 +$DIG $DIGOPTS @10.53.0.3 sync.example cds >dig.out.ns3.cdstest$n || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l) +test ${lines:-0} -eq 2 || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l) +test ${lines:-0} -eq 2 || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l) +test ${lines:-0} -eq 2 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "test 'ksk' affects DNSKEY/CDS/CDNSKEY ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 kskonly.example dnskey >dig.out.ns3.dnskeytest$n || ret=1 +$DIG $DIGOPTS @10.53.0.3 kskonly.example cdnskey >dig.out.ns3.cdnskeytest$n || ret=1 +$DIG $DIGOPTS @10.53.0.3 kskonly.example cds >dig.out.ns3.cdstest$n || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l) +test ${lines:-0} -eq 1 || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l) +test ${lines:-0} -eq 1 || ret=1 +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l) +test ${lines:-0} -eq 1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# XXXWMM Replace this test with dnssec-policy equivalent once we have +# implemented 'cdnskey "only-during-rollovers";'. +#echo_i "setting CDS and CDNSKEY deletion times and calling 'rndc loadkeys'" +#$SETTIME -D sync now $(cat sync.key) > settime.out.test$n || ret=1 +#($RNDCCMD 10.53.0.3 loadkeys sync.example | sed 's/^/ns3 /' | cat_i) || ret=1 +# +#echo_i "checking that the CDS and CDNSKEY are deleted ($n)" +#ret=0 +#ensure_cds_and_cdnskey_are_deleted() { +# $DIG $DIGOPTS @10.53.0.3 sync.example. CDS > dig.out.ns3.cdstest$n || return 1 +# awk '$1 == "sync.example." && $4 == "CDS" { exit 1; }' dig.out.ns3.cdstest$n || return 1 +# $DIG $DIGOPTS @10.53.0.3 sync.example. CDNSKEY > dig.out.ns3.cdnskeytest$n || return 1 +# awk '$1 == "sync.example." && $4 == "CDNSKEY" { exit 1; }' dig.out.ns3.cdnskeytest$n || return 1 +#} +#retry 10 ensure_cds_and_cdnskey_are_deleted || ret=1 +#n=$((n + 1)) +#if [ $ret != 0 ]; then echo_i "failed"; fi +#status=$((status + ret)) + +echo_i "check that dnssec-settime -p Dsync works ($n)" +ret=0 +$SETTIME -p Dsync $(cat sync.key) >settime.out.test$n || ret=1 +grep "SYNC Delete:" settime.out.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that dnssec-settime -p Psync works ($n)" +ret=0 +$SETTIME -p Psync $(cat sync.key) >settime.out.test$n || ret=1 +grep "SYNC Publish:" settime.out.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that zone with inactive ZSK and active KSK is properly autosigned ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 axfr inaczsk2.example >dig.out.ns3.test$n || ret=1 +grep "SOA ${DEFAULT_ALGORITHM_NUMBER} 2" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for out-of-zone NSEC3 records after ZSK removal ($n)" +ret=0 +# Delete the ZSK +file="ns3/inactive/$(cat delzsk.key).key" +$NSUPDATE >nsupdate.out.test$n 2>&1 <dig.out.ns3.test$n || return 1 + grep '; key id = '"$oldid"'$' dig.out.ns3.test$n >/dev/null && return 1 + return 0 +} +retry_quiet 5 zsk_is_gone || ret=1 +if [ $ret -ne 0 ]; then + echo_i "timed out waiting for key removal" +fi + +# Check whether key removal caused NSEC3 records to be erroneously created for +# glue records due to a secure delegation already being signed by the active key +# (i.e. a key other than the one being removed but using the same algorithm). +# +# For reference: +# +# $ nsec3hash 12345678 1 10 ns.sub.delzsk.example. +# 589R358VSPJUFVAJU949JPVF74D9PTGH (salt=12345678, hash=1, iterations=10) +# +$DIG $DIGOPTS delzsk.example AXFR @10.53.0.3 >dig.out.ns3.3.test$n || ret=1 +grep "589R358VSPJUFVAJU949JPVF74D9PTGH" dig.out.ns3.3.test$n >/dev/null 2>&1 && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-policy) ($n)" +ret=0 +$DIG $DIGOPTS txt dname-at-apex-nsec3.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "RRSIG NSEC3 ${DEFAULT_ALGORITHM_NUMBER} 3 600" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that DNAME is not treated as a delegation when signing ($n)" +ret=0 +$DIG $DIGOPTS dname-and-txt.secure.example. DNAME @10.53.0.3 >dig.out.ns3.1.test$n || ret=1 +grep "dname-and-txt.secure.example.*RRSIG.*DNAME" dig.out.ns3.1.test$n >/dev/null 2>&1 || ret=1 +$DIG $DIGOPTS dname-and-txt.secure.example. TXT @10.53.0.3 >dig.out.ns3.2.test$n || ret=1 +grep "dname-and-txt.secure.example.*RRSIG.*TXT" dig.out.ns3.2.test$n >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking key maintenance events were logged correctly ($n)" +ret=0 +pub=$(grep "DNSKEY .* is now published" ns2/named.run | grep -v "CDNSKEY" | wc -l) +[ "$pub" -eq 10 ] || ret=1 +act=$(grep "DNSKEY .* is now active" ns2/named.run | wc -l) +[ "$act" -eq 10 ] || ret=1 +rev=$(grep "DNSKEY .* is now revoked" ns2/named.run | wc -l) +[ "$rev" -eq 0 ] || ret=1 +inac=$(grep "DNSKEY .* is now inactive" ns2/named.run | wc -l) +[ "$inac" -eq 0 ] || ret=1 +del=$(grep "DNSKEY .* is now deleted" ns2/named.run | wc -l) +[ "$del" -eq 0 ] || ret=1 +pub=$(grep "DNSKEY .* is now published" ns3/named.run | grep -v "CDNSKEY" | wc -l) +act=$(grep "DNSKEY .* is now active" ns3/named.run | wc -l) +if [ $RSASHA1_SUPPORTED = 1 ]; then + # Include two log lines for nsec-only zone. + [ "$pub" -eq 53 ] || ret=1 + [ "$act" -eq 53 ] || ret=1 +else + [ "$pub" -eq 51 ] || ret=1 + [ "$act" -eq 51 ] || ret=1 +fi +rev=$(grep "DNSKEY .* is now revoked" ns3/named.run | wc -l) +[ "$rev" -eq 0 ] || ret=1 +inac=$(grep "DNSKEY .* is now inactive" ns3/named.run | wc -l) +[ "$inac" -eq 0 ] || ret=1 +del=$(grep "DNSKEY .* is now deleted" ns3/named.run | wc -l) +[ "$del" -eq 3 ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check removal of ENT NSEC3 records when delegations are removed ($n)" +zone=nsec3-with-ent +hash=M9SFFA181BCTR8D18LQUPST4N6BL304D + +# check that NSEC3 for ENT is present +echo_i "check ENT NSEC3 is initially present" +ret=0 +$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" >dig.out.pre.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 4, " dig.out.pre.ns2.test$n >/dev/null || ret=1 +grep "^${hash}.${zone}." dig.out.pre.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check ENT NSEC3 is still present after removing one of two delegations ($n)" +ret=0 +# remove first delegation of two delegations, NSEC3 for ENT should remain. +( + echo zone $zone + echo server 10.53.0.2 "$PORT" + echo update del sub1.ent.$zone NS + echo send +) | $NSUPDATE +# check that NSEC3 for ENT is still present +$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" >dig.out.pre.ns2.test$n || ret=1 +$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" >dig.out.mid.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.mid.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 4, " dig.out.mid.ns2.test$n >/dev/null || ret=1 +grep "^${hash}.${zone}." dig.out.mid.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check ENT NSEC3 is gone after removing the second delegation ($n)" +ret=0 +# remove second delegation of two delegations, NSEC3 for ENT should be deleted. +( + echo zone $zone + echo server 10.53.0.2 "$PORT" + echo update del sub2.ent.$zone NS + echo send +) | $NSUPDATE +# check that NSEC3 for ENT is gone +echo_i "check ENT NSEC3 is gone for zone $zone hash $hash" +$DIG $DIGOPTS @10.53.0.2 a "ent.${zone}" >dig.out.post.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.post.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 4, " dig.out.post.ns2.test$n >/dev/null || ret=1 +grep "^${hash}.${zone}." dig.out.post.ns2.test$n >/dev/null && ret=1 +$DIG $DIGOPTS @10.53.0.2 axfr "${zone}" >dig.out.axfr.ns2.test$n || ret=1 +grep "^${hash}.${zone}." dig.out.axfr.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that the startup change from NSEC3 to NSEC is properly signed ($n)" +ret=0 +$JOURNALPRINT ns3/nsec3-to-nsec.example.db.jnl \ + | awk 'BEGIN { private=0; rrsig=0; ok=0 } +$1 == "del" && $5 == "SOA" { if (private || rrsig) { if (private == rrsig) { exit(0); } else { exit(1); } } } +$1 == "add" && $5 == "TYPE65534" { private=1 } +$1 == "add" && $5 == "RRSIG" && $6 == "TYPE65534" { rrsig=1 } +END { if (private || rrsig) { if (private == rrsig) { exit(0); } else { exit(1); } } else { exit (1); } } +' || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that NSEC3 to NSEC builds the NSEC chain first ($n)" +ret=0 +$JOURNALPRINT ns3/nsec3-to-nsec.example.db.jnl \ + | awk 'BEGIN { nsec3param=0; nsec=0 } +$1 == "del" && $5 == "SOA" { if (nsec3param || nsec) { if (nsec3param && !nsec) { exit(1); } else { exit(0); } } } +$1 == "del" && $5 == "NSEC3PARAM" { nsec3param=1 } +$1 == "add" && $2 == "nsec3-to-nsec.example." && $5 == "NSEC" { nsec=1 } +END { if (nsec3param || nsec) { if (nsec3param && !nsec) { exit(1); } else { exit(0); } } else { exit(1); } } +' || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that NSEC3 to NSEC3 builds the new NSEC3 chain first ($n)" +ret=0 +$JOURNALPRINT ns3/nsec3-to-nsec3.example.db.jnl \ + | awk 'BEGIN { addnsec3param=0; delnsec3param=0; nsec3=0 } +$1 == "del" && $5 == "SOA" { if (delnsec3param || nsec3 || addnsec3param) { if (delnsec3param && (!nsec3 || !addnsec3param)) { exit(1); } else { exit(0); } } } +$1 == "del" && $5 == "NSEC3PARAM" { delnsec3param=1 } +$1 == "add" && $5 == "NSEC3PARAM" { addnsec3param=1 } +$1 == "add" && $5 == "NSEC3" { nsec3=1 } +END { if (delnsec3param || nsec3 || addnsec3param) { if (delnsec3param && (!nsec3 || !addnsec3param)) { exit(1); } else { exit(0); } } else { exit(1); } } +' || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/autosign/tests_sh_autosign.py b/bin/tests/system/autosign/tests_sh_autosign.py new file mode 100644 index 0000000..b373e03 --- /dev/null +++ b/bin/tests/system/autosign/tests_sh_autosign.py @@ -0,0 +1,156 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "active.key", + "activate-now-publish-1day.key", + "autoksk.key", + "autozsk.key", + "del.key", + "delayksk.key", + "delayzsk.key", + "delzsk.key", + "dig.out.*", + "dsset-.", + "dsset-bar.", + "dsset-delay.example.", + "inact.key", + "inaczsk-ksk.key", + "inaczsk-zsk.key", + "noksk-ksk.key", + "nopriv.key", + "nozsk-ksk.key", + "nozsk-zsk.key", + "nsupdate.out.*", + "prepub.key", + "rev.key", + "settime.out.*", + "signing.*out*", + "standby.key", + "sync.key", + "unpub.key", + "vanishing.key", + "*/K*", + "*/dsset-*", + "*/*.signed", + "*/*.jnl", + "*/*.bk", + "ns*/_default.nzf*", + "ns*/_default.nzd*", + "ns1/root.db", + "ns1/root.db.1", + "ns1/root.db.2", + "ns1/root.db.3", + "ns1/signing.out", + "ns1/trusted.conf", + "ns2/bar.db", + "ns2/child.nsec3.example.db", + "ns2/child.optout.example.db", + "ns2/dsset-dname-at-apex-nsec3.example.", + "ns2/dsset-example.", + "ns2/dsset-nsec3-to-nsec.example.", + "ns2/dsset-nsec3.example.", + "ns2/dsset-oldsigs.example.", + "ns2/dsset-optout.example.", + "ns2/dsset-private.secure.example.", + "ns2/dsset-rsasha256.example.", + "ns2/dsset-rsasha512.example.", + "ns2/dsset-secure.example.", + "ns2/example.db", + "ns2/insecure.secure.example.db", + "ns2/nsec3-with-ent.db", + "ns2/private.conf", + "ns2/private.secure.example.db", + "ns2/signing.bar.out", + "ns2/signing.privsec.out", + "ns2/trusted.conf", + "ns3/autonsec3.example.db", + "ns3/delay.example.1", + "ns3/delay.example.2", + "ns3/delay.example.db", + "ns3/delzsk.example.db", + "ns3/dname-at-apex-nsec3.example.db", + "ns3/dsset-autonsec3.example.", + "ns3/dsset-dname-at-apex-nsec3.example.", + "ns3/dsset-inaczsk.example.", + "ns3/dsset-inaczsk2.example.", + "ns3/dsset-kskonly.example.", + "ns3/dsset-noksk.example.", + "ns3/dsset-nozsk.example.", + "ns3/dsset-nsec-only.example.", + "ns3/dsset-nsec3-to-nsec.example.", + "ns3/dsset-nsec3-to-nsec3.example.", + "ns3/dsset-nsec3.example.", + "ns3/dsset-nsec3.nsec3.example.", + "ns3/dsset-nsec3.optout.example.", + "ns3/dsset-oldsigs.example.", + "ns3/dsset-optout.example.", + "ns3/dsset-optout.nsec3.example.", + "ns3/dsset-optout.optout.example.", + "ns3/dsset-prepub.example.", + "ns3/dsset-rsasha256.example.", + "ns3/dsset-rsasha512.example.", + "ns3/dsset-secure.example.", + "ns3/dsset-secure.nsec3.example.", + "ns3/dsset-secure.optout.example.", + "ns3/dsset-sync.example.", + "ns3/inactive", + "ns3/inaczsk.example.db", + "ns3/inaczsk2.example.db", + "ns3/jitter.nsec3.example.db", + "ns3/kg.out", + "ns3/kskonly.example.db", + "ns3/kskonly.example.db.jbk", + "ns3/noksk.example.db", + "ns3/nozsk.example.db", + "ns3/nsec-only.example.db", + "ns3/nsec3-to-nsec.example.db", + "ns3/nsec3-to-nsec3.example.db", + "ns3/nsec3.example.db", + "ns3/nsec3.nsec3.example.db", + "ns3/nsec3.optout.example.db", + "ns3/oldsigs.example.db", + "ns3/oldsigs.example.db.bak", + "ns3/optout.example.db", + "ns3/optout.example.db.jbk", + "ns3/optout.nsec3.example.db", + "ns3/optout.optout.example.db", + "ns3/prepub.example.db", + "ns3/reconf.example.db", + "ns3/reconf.example.db.jbk", + "ns3/rsasha256.example.db", + "ns3/rsasha512.example.db", + "ns3/s.out", + "ns3/secure.example.db", + "ns3/secure.nsec3.example.db", + "ns3/secure.optout.example.db", + "ns3/st.out", + "ns3/sync.example.db", + "ns3/trusted.conf", + "ns3/ttl1.example.db", + "ns3/ttl2.example.db", + "ns3/ttl3.example.db", + "ns3/ttl4.example.db", + "ns4/private.conf", + "ns4/trusted.conf", + "ns5/trusted.conf", + ] +) + + +@isctest.mark.flaky(max_runs=2) +def test_autosign(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/builtin/ns1/named.conf.j2 b/bin/tests/system/builtin/ns1/named.conf.j2 new file mode 100644 index 0000000..d2abad7 --- /dev/null +++ b/bin/tests/system/builtin/ns1/named.conf.j2 @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation no; +}; diff --git a/bin/tests/system/builtin/ns2/named.conf.j2 b/bin/tests/system/builtin/ns2/named.conf.j2 new file mode 100644 index 0000000..64327db --- /dev/null +++ b/bin/tests/system/builtin/ns2/named.conf.j2 @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + server-id hostname; + dnssec-validation no; +}; diff --git a/bin/tests/system/builtin/ns3/named.conf.j2 b/bin/tests/system/builtin/ns3/named.conf.j2 new file mode 100644 index 0000000..c3a1372 --- /dev/null +++ b/bin/tests/system/builtin/ns3/named.conf.j2 @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + hostname "this.is.a.test.of.hostname"; + server-id "this.is.a.test.of.server-id"; + version "this is a test of version"; + dnssec-validation no; +}; diff --git a/bin/tests/system/builtin/tests.sh b/bin/tests/system/builtin/tests.sh new file mode 100644 index 0000000..96b1a2c --- /dev/null +++ b/bin/tests/system/builtin/tests.sh @@ -0,0 +1,288 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +status=0 +n=0 + +emptyzones=" +10.IN-ADDR.ARPA +16.172.IN-ADDR.ARPA +17.172.IN-ADDR.ARPA +18.172.IN-ADDR.ARPA +19.172.IN-ADDR.ARPA +20.172.IN-ADDR.ARPA +21.172.IN-ADDR.ARPA +22.172.IN-ADDR.ARPA +23.172.IN-ADDR.ARPA +24.172.IN-ADDR.ARPA +25.172.IN-ADDR.ARPA +26.172.IN-ADDR.ARPA +27.172.IN-ADDR.ARPA +28.172.IN-ADDR.ARPA +29.172.IN-ADDR.ARPA +30.172.IN-ADDR.ARPA +31.172.IN-ADDR.ARPA +168.192.IN-ADDR.ARPA +64.100.IN-ADDR.ARPA +65.100.IN-ADDR.ARPA +66.100.IN-ADDR.ARPA +67.100.IN-ADDR.ARPA +68.100.IN-ADDR.ARPA +69.100.IN-ADDR.ARPA +70.100.IN-ADDR.ARPA +71.100.IN-ADDR.ARPA +72.100.IN-ADDR.ARPA +73.100.IN-ADDR.ARPA +74.100.IN-ADDR.ARPA +75.100.IN-ADDR.ARPA +76.100.IN-ADDR.ARPA +77.100.IN-ADDR.ARPA +78.100.IN-ADDR.ARPA +79.100.IN-ADDR.ARPA +80.100.IN-ADDR.ARPA +81.100.IN-ADDR.ARPA +82.100.IN-ADDR.ARPA +83.100.IN-ADDR.ARPA +84.100.IN-ADDR.ARPA +85.100.IN-ADDR.ARPA +86.100.IN-ADDR.ARPA +87.100.IN-ADDR.ARPA +88.100.IN-ADDR.ARPA +89.100.IN-ADDR.ARPA +90.100.IN-ADDR.ARPA +91.100.IN-ADDR.ARPA +92.100.IN-ADDR.ARPA +93.100.IN-ADDR.ARPA +94.100.IN-ADDR.ARPA +95.100.IN-ADDR.ARPA +96.100.IN-ADDR.ARPA +97.100.IN-ADDR.ARPA +98.100.IN-ADDR.ARPA +99.100.IN-ADDR.ARPA +100.100.IN-ADDR.ARPA +101.100.IN-ADDR.ARPA +102.100.IN-ADDR.ARPA +103.100.IN-ADDR.ARPA +104.100.IN-ADDR.ARPA +105.100.IN-ADDR.ARPA +106.100.IN-ADDR.ARPA +107.100.IN-ADDR.ARPA +108.100.IN-ADDR.ARPA +109.100.IN-ADDR.ARPA +110.100.IN-ADDR.ARPA +111.100.IN-ADDR.ARPA +112.100.IN-ADDR.ARPA +113.100.IN-ADDR.ARPA +114.100.IN-ADDR.ARPA +115.100.IN-ADDR.ARPA +116.100.IN-ADDR.ARPA +117.100.IN-ADDR.ARPA +118.100.IN-ADDR.ARPA +119.100.IN-ADDR.ARPA +120.100.IN-ADDR.ARPA +121.100.IN-ADDR.ARPA +122.100.IN-ADDR.ARPA +123.100.IN-ADDR.ARPA +124.100.IN-ADDR.ARPA +125.100.IN-ADDR.ARPA +126.100.IN-ADDR.ARPA +127.100.IN-ADDR.ARPA +0.IN-ADDR.ARPA +127.IN-ADDR.ARPA +254.169.IN-ADDR.ARPA +2.0.192.IN-ADDR.ARPA +100.51.198.IN-ADDR.ARPA +113.0.203.IN-ADDR.ARPA +255.255.255.255.IN-ADDR.ARPA +0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA +D.F.IP6.ARPA +8.E.F.IP6.ARPA +9.E.F.IP6.ARPA +A.E.F.IP6.ARPA +B.E.F.IP6.ARPA +8.B.D.0.1.0.0.2.IP6.ARPA +EMPTY.AS112.ARPA +HOME.ARPA +RESOLVER.ARPA" + +n=$((n + 1)) +ret=0 +count=0 +echo_i "Checking expected empty zones were configured ($n)" +for zone in ${emptyzones}; do + grep "automatic empty zone: $zone" ns1/named.run >/dev/null || { + echo_i "failed (empty zone $zone missing)" + ret=1 + } + count=$((count + 1)) +done +lines=$(grep "automatic empty zone: " ns1/named.run | wc -l) +test $count -eq $lines -a $count -eq 100 || { + ret=1 + echo_i "failed (count mismatch)" +} +if [ $ret != 0 ]; then status=$((status + ret)); fi + +n=$((n + 1)) +echo_i "Checking that reconfiguring empty zones is silent ($n)" +$RNDCCMD 10.53.0.1 reconfig +ret=0 +grep "automatic empty zone" ns1/named.run >/dev/null || ret=1 +grep "received control channel command 'reconfig'" ns1/named.run >/dev/null || ret=1 +grep "reloading configuration succeeded" ns1/named.run >/dev/null || ret=1 +sleep 1 +grep "zone serial (0) unchanged." ns1/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "Checking that reloading empty zones is silent ($n)" +rndc_reload ns1 10.53.0.1 +ret=0 +grep "automatic empty zone" ns1/named.run >/dev/null || ret=1 +grep "received control channel command 'reload'" ns1/named.run >/dev/null || ret=1 +grep "reloading configuration succeeded" ns1/named.run >/dev/null || ret=1 +sleep 1 +grep "zone serial (0) unchanged." ns1/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +HOST_NAME=$($FEATURETEST --gethostname) +BIND_VERSION_STRING=$($NAMED -V | head -1) +BIND_VERSION=$($NAMED -V | sed -ne 's/^BIND \([^ ]*\).*/\1/p') + +n=$((n + 1)) +ret=0 +echo_i "Checking that default version works for rndc ($n)" +$RNDCCMD 10.53.0.1 status >rndc.status.ns1.$n 2>&1 +grep -F "version: $BIND_VERSION_STRING" rndc.status.ns1.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that custom version works for rndc ($n)" +$RNDCCMD 10.53.0.3 status >rndc.status.ns3.$n 2>&1 +grep -F "version: $BIND_VERSION_STRING (this is a test of version)" rndc.status.ns3.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that default version works for query ($n)" +$DIG $DIGOPTS +short version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "^\"$BIND_VERSION\"$" dig.out.ns1.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that custom version works for query ($n)" +$DIG $DIGOPTS +short version.bind txt ch @10.53.0.3 >dig.out.ns3.$n || ret=1 +grep "^\"this is a test of version\"$" dig.out.ns3.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that default hostname works for query ($n)" +$DIG $DIGOPTS +short hostname.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "^\"$HOST_NAME\"$" dig.out.ns1.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that custom hostname works for query ($n)" +$DIG $DIGOPTS +short hostname.bind txt ch @10.53.0.3 >dig.out.ns3.$n || ret=1 +grep "^\"this.is.a.test.of.hostname\"$" dig.out.ns3.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that default server-id is none for query ($n)" +$DIG $DIGOPTS id.server txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns1.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that server-id hostname works for query ($n)" +$DIG $DIGOPTS +short id.server txt ch @10.53.0.2 >dig.out.ns2.$n || ret=1 +grep "^\"$HOST_NAME\"$" dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that server-id hostname works for EDNS name server ID request ($n)" +$DIG $DIGOPTS +norec +nsid foo @10.53.0.2 >dig.out.ns2.$n || ret=1 +grep "^; NSID: .* (\"$HOST_NAME\")$" dig.out.ns2.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that custom server-id works for query ($n)" +$DIG $DIGOPTS +short id.server txt ch @10.53.0.3 >dig.out.ns3.$n || ret=1 +grep "^\"this.is.a.test.of.server-id\"$" dig.out.ns3.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +n=$((n + 1)) +ret=0 +echo_i "Checking that custom server-id works for EDNS name server ID request ($n)" +$DIG $DIGOPTS +norec +nsid foo @10.53.0.3 >dig.out.ns3.$n || ret=1 +grep "^; NSID: .* (\"this.is.a.test.of.server-id\")$" dig.out.ns3.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=$((status + ret)) +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/builtin/tests_sh_builtin.py b/bin/tests/system/builtin/tests_sh_builtin.py new file mode 100644 index 0000000..ff521db --- /dev/null +++ b/bin/tests/system/builtin/tests_sh_builtin.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.status.ns*", + ] +) + + +def test_builtin(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/cacheclean/dig.batch b/bin/tests/system/cacheclean/dig.batch new file mode 100644 index 0000000..d185204 --- /dev/null +++ b/bin/tests/system/cacheclean/dig.batch @@ -0,0 +1,924 @@ +YA.AKAMAI.com. IN A +UPR1.UPR.CLU.EDU. IN A +integra.s-integra.co.JP. IN A +avalon.iks-jena.de. IN A +NS1.GLOBALDNS.com. IN A +NS.RDU.BELLSOUTH.net. IN A +ns.space.net. IN A +SUN.MHS-RELAY.AC.UK. IN A +AYAX.UNIANDES.EDU.CO. IN A +DNS.NIC.CD. IN A +NS.DNS.PT. IN A +NS1.INTERNETSHARE.com. IN A +MASTER.DNS.BE. IN A +CATAMOUNT.middlebury.EDU. IN A +FM03.FM. IN A +NAAMAK.NCST.ERNET.IN. IN A +gateway2.BFG.com. IN A +NS3.NS.ESAT.net. IN A +DNS1.INTUIT.com. IN A +DEN-NS2.FWIDCSERVICES.net. IN A +SOL.UNDPBI.TELEPAC.net. IN A +NS2.tridog.com. IN A +DNS2.KW. IN A +NS2.MAIL.com. IN A +NS.FIRSTCOM.CL. IN A +DNS4.QUICKEN.com. IN A +bofh.cid.net. IN A +NS1.KRNIC.net. IN A +NS2.SR.net. IN A +NS1.TELSTRA.net. IN A +ns.cafax.SE. IN A +NS1.DNS.NET.NZ. IN A +NS.CONCOURSE.com. IN A +35.32/27.110.16.12.IN-ADDR.ARPA. IN PTR +CCC.champcable.com. IN A +NS.RIPE.net. IN A +NS.NIC.NU. IN A +KIM.CAMNET.CM. IN A +DOGON.SOTELMA.net. IN A +DNS02.FLAME.org. IN A +NS.MIA.BELLSOUTH.net. IN A +mail.ok.RU. IN A +NS.NIC.MX. IN A +NS2.BERKELEY.EDU. IN A +SHIKHAR.MOS.COM.NP. IN A +noc.rrz.Uni-Koeln.de. IN A +NS.KORNET.net. IN A +keith.gazpacho.org. IN A +NS2.appliedtheory.com. IN A +NS.CERNET.net. IN A +smtp.ELISTX.com. IN A +NS-AIT.THNIC.net. IN A +from.PL. IN A +mailhub.icann.org. IN A +SEC1.DNS.UK.PSI.net. IN A +isrv3-i.isc.org. IN A +PHLOEM.UOREGON.EDU. IN A +CTINA.AR. IN A +DNS2.IAM.NET.MA. IN A +10.126.39.137.IN-ADDR.ARPA. IN PTR +DNS.PRINCETON.EDU. IN A +NS.BELLSOUTH.net. IN A +NS1.SNS-FELB.DEBIS.com. IN A +localhost. IN A +hm6.vt.highmeadow.com. IN A +SYRUP.hill.com. IN A +NS99.WAIKATO.AC.NZ. IN A +NS4.CW.net. IN A +NS2.SLOWMOE.com. IN A +ns2.hypa.net. IN A +ns.sxtyptt.NET.CN. IN A +NS2.MERCHANTWARE.com. IN A +uunymdgds1.DOUBLECLICK.net. IN A +e34.co.us.IBM.com. IN A +kista.dns.swip.net. IN A +ZEBRA.UEM.MZ. IN A +NET2.GENDYN.com. IN A +NS0.UTK.EDU. IN A +NS.RELCOM.EU.net. IN A +DNS0.AXION.BT.CO.UK. IN A +mail.vhv.com. IN A +DNS4.UK.MSFT.net. IN A +NS2.ADNS.net. IN A +NS1.SEATTLE.US.NETDNS.com. IN A +NS2.UNIVIE.AC.at. IN A +NS15B.BOCA15-VERIO.com. IN A +www.BAYAREA.com. IN CNAME +ns4.onemain.com. IN A +NS2.EDIGITALS.com. IN A +MICHAEL.VATICAN.VA. IN A +AUSTIN.GH.com. IN A +sld-ns2.CNNIC.NET.CN. IN A +NS2.CDC.GOV. IN A +NS.WATSON.IBM.com. IN A +NS.NIC.SH. IN A +NS2.BAHNHOF.net. IN A +NS-AUTH2.cmates.com. IN A +ISDMNL.WR.USGS.GOV. IN A +NS2.COBEX.net. IN A +MERLE.CIRA.CA. IN A +NS.UVG.EDU.GT. IN A +NS1.CWVA.DOUBLECLICK.net. IN A +eliot.diebold.com. IN A +NS.ALMADEN.IBM.com. IN A +NS2.INTERNETSQUARE.com. IN A +mail.QUEST-NET.com. IN A +Z1.NS.LHR1.GLOBIX.net. IN A +DNS1.AVANTEL.NET.MX. IN A +vh80040.vh8.INFI.net. IN A +NS.LEB.net. IN A +NS.DCC.UCHILE.CL. IN A +CLOUSO.RISQ.QC.CA. IN A +muenster.westfalen.de. IN A +us.a1.YIMG.com. IN CNAME +NS.DEMOS.SU. IN A +south.NAVPOINT.com. IN A +netconsult.netconx.de. IN A +DNS2.btinternet.com. IN A +NS2.CINE.net. IN A +castor.cmc.ec.gc.CA. IN A +EX2-DNS0.AVENUEA.com. IN A +firewall3.glaxowellcome.com. IN A +MACU.MA.MT.NP.ELS-GMS.att.net. IN A +NS.PA. IN A +TGSERV.TELE.GL. IN A +KYNSE02.MESSAGESECURE.com. IN A +GORGON.XTRA.CO.NZ. IN A +DNS.NIC.IT. IN A +pop.VERMONTEL.net. IN CNAME +NS2.REGISTRY.HM. IN A +NAMESERVER1.CONCENTRIC.net. IN A +47.131.127.204.IN-ADDR.ARPA. IN PTR +mailhost.tfm.com. IN A +NS1.MRC.GM. IN A +NS.WIDE.AD.JP. IN A +NS.BTA.NET.CN. IN A +NS2.ISPC.org. IN A +BOW.RAIN.FR. IN A +srs.srs.state.vt.us. IN A +NS4.WEB2010.com. IN A +NS.TELECOM.NET.ET. IN A +NS1.DNS.NET.KH. IN A +GATEN.JARING.MY. IN A +shell.nominum.com. IN A +CHEOPS.ANU.EDU.AU. IN A +VANGOGH.CS.BERKELEY.EDU. IN A +NS2.NOC.NULLUS.net. IN A +NIC.LTH.SE. IN A +ns.farm.net. IN A +NS.USEC.SUN.com. IN A +NS2.YOUR-DOMAIN.com. IN A +DNS-EAST.PREP.net. IN A +ns.hcr.net. IN A +NS-RCH.nortelnetworks.com. IN A +crl.DEC.com. IN A +NS.PIXAR.ES. IN A +MEX1-M-213.UNINET.NET.MX. IN A +NS.ITU.CH. IN A +matrix.uwm.EDU.PL. IN A +gateway1.gmcr.com. IN A +NS2.DNS.BR. IN A +foxharp.boston.MA.us. IN MX +Quest-7.symquest.com. IN A +NS2.VERIO.net. IN A +NAME.IAD.GBLX.net. IN A +NS2.EMIRATES.NET.AE. IN A +supai.oit.UMASS.EDU. IN A +QUERN.EPILOGUE.com. IN A +NS3.TOPICA.com. IN A +NS1.JERKY.net. IN A +JTB.BRUNET.BN. IN A +AUTH100.NS.UU.net. IN A +BOW.INTNET.DJ. IN A +OSI2.GUA.net. IN A +AZMODAN.ULA.VE. IN A +THUMPER.RPSLMC.EDU. IN A +ICHU.RCP.NET.PE. IN A +NS.NIC.AC. IN A +DNS.NETFLIGHT.com. IN A +ns2.UTORONTO.CA. IN A +mail.giffordmed.org. IN A +RATA.VUW.AC.NZ. IN A +NS-2.ADMONITOR.net. IN A +NCC.MOC.KW. IN A +NS.EUNET.ES. IN A +NS3.best.com. IN A +zip.MAIL-LIST.com. IN MX +JATZ.AARNET.EDU.AU. IN A +DNS2.MAN.LODZ.PL. IN A +NS.VERITAS.com. IN A +218.241.103.199.IN-ADDR.ARPA. IN PTR +BOW.SNPT.KM. IN A +Z1.NS.SJC1.GLOBIX.net. IN A +DNS.NIC.TT. IN A +MAKISIG.IPHIL.net. IN A +NS.DK.net. IN A +NS.NI. IN A +CIUP1.NCC.UP.PT. IN A +ns2.verisign-grs.com. IN A +NS1.UMASS.EDU. IN A +NS.NEWACCOUNT.net. IN A +UDNS2.ULTRADNS.net. IN A +NS2.LATNET.LV. IN A +info-server.surrey.AC.UK. IN A +NS2.SQUONK.net. IN A +NS2.DSO.net. IN A +www.energyenhancement.org. IN A +DNS1.BD. IN A +nl.COMPUWARE.com. IN MX +NS.DHIRAAGU.MV. IN A +TRANTOR.UMD.EDU. IN A +NS.ALCANET.NO. IN A +Z6.MSFT.AKADNS.com. IN A +NS4.ync.net. IN A +CMTU.MT.NS.ELS-GMS.att.net. IN A +vh40099.vh4.INFI.net. IN A +ns2.secondary.nl. IN A +abyssinian.sleepycat.com. IN A +APHEX.MENTOR.BE. IN A +webmail.fiberia.com. IN A +localhost.moonmothers.com. IN A +NS2.DNS.LU. IN A +NS.VISUALCOM.ES. IN A +TONIC.TO. IN A +NS1.CRSNIC.net. IN A +trurl.ispid.com.PL. IN A +datingagentur.de. IN A +NS2.NSIREGISTRY.net. IN A +ICE.VIA-NET-WORKS.IE. IN A +sgi1.map.com. IN A +NS0.HS0.U-NET.net. IN A +candle.pha.pa.us. IN A +NS1.PACIFIC.NET.SG. IN A +NS.CENIAI.NET.CU. IN A +NS2.UUCP.NE.JP. IN A +za.akamaitech.net. IN A +NS.UCR.AC.CR. IN A +DNS-02.NS.cs.com. IN A +dns2.primary.net. IN A +PAPPSRV.PAPP.UNDP.org. IN A +NS1.REGME.com. IN A +DNS.CS.KULEUVEN.AC.BE. IN A +NS1.VERMONTLAW.net. IN A +mail.garmontusa.com. IN A +NS2.SAIPAN.com. IN A +NS.ARICATRA.com. IN A +ns2.reedmedia.net. IN A +NS.NETLAB.SK. IN A +RELAY.GW.tislabs.com. IN A +b.ns.tmcs.net. IN A +NS1.IBL.BM. IN A +ok.RU. IN A +NS.RICC.ALMA-ATA.SU. IN A +KITKA.MARNET.MK. IN A +dasher.dartmouth.EDU. IN A +NS0.PLANET-THREE.com. IN A +KNOCK.SER.BBNPLANET.net. IN A +tornado.webtech.elk.PL. IN A +AUTH2.NS.IDT.net. IN A +host3.VTLEGALAID.org. IN A +NS.EUNET.SK. IN A +TULKU.NIC.AR. IN A +RELAY.CDNNET.CA. IN A +DNS2.TPSA.PL. IN A +enterprise.wirbel.com. IN A +ECNET.EC. IN A +ENGINE1.UNA.net. IN A +WYCU.WY.BR.NP.ELS-GMS.att.net. IN A +ARWENA.NASK.WAW.PL. IN A +PAC2.NIPR.MIL. IN A +DAISY.EE.UND.AC.ZA. IN A +odin.ietf.org. IN A +dns.kaben-net.de. IN A +NS2.ALTAVISTA.com. IN A +CASTOR.TELEGLOBE.net. IN A +CIR.RED.SV. IN A +PIJIN.COM.SB. IN A +NS4.CTCCOM.net. IN A +NS1.SOL.NO. IN A +DNS2.TK.MSFT.net. IN A +NS.BSDI.com. IN A +NS.SVIANED.nl. IN A +NS.NOVELL.com. IN A +NS.LUCKY.net. IN A +SJC-NS2.SJC.LYCOS.com. IN A +NS1.OP.net. IN A +worldnet.att.net. IN A +APIES.FRD.AC.ZA. IN A +mail.skiinsurance.com. IN A +NS.BELNET.BE. IN A +KOMO.INET.GA. IN A +EARTH.THEPLANET.net. IN A +VASCO.USMA.AC.PA. IN A +GODFEVER.DCCSERVER.com. IN A +BOS-NS2.BOS.LYCOS.com. IN A +NS2.GOTO.com. IN A +NS1.overstock.com. IN A +NS1-PUBLIC.ZMA.COMPAQ.com. IN A +ns.ilovedomain.com. IN A +ns1.anycast.net. IN A +PASCAL.UPRR.PR. IN A +NS3-AUTH.SPRINTLINK.net. IN A +NS1-Y.DNS.PIPEX.net. IN A +prue.eim.surrey.AC.UK. IN A +TROLL-GW.GATECH.EDU. IN A +NS.SIERRATEL.SL. IN A +ns2.PSHIFT.com. IN A +NS.ERS.IBM.com. IN A +ASLAN.OPEN-RSC.org. IN A +NS2.DOMAIN-REGISTRY.nl. IN A +uranus.lan-ks.de. IN A +mail.unlisys.net. IN A +NS.AUSTRIA.EU.net. IN A +AUTH01.CONNECT.IE. IN A +SUN.SCSI.GOV.BY. IN A +NS1.SIGMAHOSTING.com. IN A +NS.CAST.EDU.JM. IN A +DS.NIC.NET.SG. IN A +PRADES.CESCA.ES. IN A +ns.sta.NET.CN. IN A +NSE00.excite.com. IN A +NS3.ABOVE.net. IN A +CASBAH.ELDJAZAIR.NET.DZ. IN A +ASKIA.SOTELMA.ML. IN A +NS.IDT.net. IN A +FXCLPR02.IS.CHRYSLER.com. IN A +SVC00.APNIC.net. IN A +NS5.DCX.YAHOO.com. IN A +ns1.ray.net. IN A +NS.NIC.MC. IN A +ns.runway.CN.net. IN A +benoni.uit.NO. IN A +SCRATCHY.MINDSPRING.net. IN A +ns1.pcode.com. IN A +ns1.aha.RU. IN A +ns2.uwaterloo.CA. IN A +ns2.NIC.AD.JP. IN A +a.ns.foxharp.boston.MA.us. IN A +NS.NIC.IO. IN A +A-GTLD-SERVERS.dot-god.com. IN A +SMTP.slac.stanford.EDU. IN A +52.87.198.209.IN-ADDR.ARPA. IN PTR +BARNEY.ADVSYS.CO.UK. IN A +NS1.TELEPAC.PT. IN A +NICOSIA.CCS.UCY.AC.CY. IN A +NS.PUNCHDOWN.org. IN A +SYNAESTHESIA.COGNOSCENTI.org. IN A +NS2.PLANET-THREE.net. IN A +DNS.CIT.CORNELL.EDU. IN A +MODOR.VERISIGN.net. IN A +SUNSTROKE.IS.RPSLMC.EDU. IN A +NS2.SEG.net. IN A +NEMUNAS.SC-UNI.KTU.LT. IN A +MULGA.CS.MU.OZ.AU. IN A +NS1.NPLUS.GF. IN A +ns2.centralinfo.net. IN A +K.GTLD-SERVERS.net. IN A +ns1.codelocal.com. IN A +NS2.IPNS.com. IN A +NS0.DE.NIC.NU. IN A +NS.USSR.EU.net. IN A +NS.INTERNET.SK. IN A +CORREOS.SEKER.ES. IN A +mx1.buf.ADELPHIA.net. IN A +aun.UNINETT.NO. IN A +NS0.NETANET.com. IN A +www.MANY-PATHS-ENERGY-ENHANCEMENT.com. IN A +NS2.STARFIRE.DOUGLAS.MA.us. IN A +NS3.IKP.PL. IN A +pns.dtag.de. IN A +NZ.NS.NIC.NU. IN A +DAVER.bungi.com. IN A +gutenberg.bucksnet.com. IN A +DNS2.IT.net. IN A +NS2.SNS-UT.DEBIS.com. IN A +ISI.EDU. IN A +amethyst.xaos.org. IN A +PAPPILLOMA.WWEBSVS.com. IN A +NS2.bock.com. IN A +NS2.OAR.net. IN A +MINION.NETPOLICY.com. IN A +Mail.catic1.com. IN A +NS4.DNS.space.net. IN A +b.gtld-servers.ORSC. IN A +bend.madriver.com. IN A +NS4.IS-FUN.net. IN A +NS2.JPS.net. IN A +NS1.IP-PLUS.net. IN A +rush.cc1.RPSLMC.EDU. IN A +NS2.GBMTECH.net. IN A +DNS.MSEN.com. IN A +DNSSEC2.SINGNET.COM.SG. IN A +NS2.HOME.net. IN A +ACCESS.MBNET.MB.CA. IN A +DNS0.SPIN.AD.JP. IN A +Filer.PHOTOTRUST.com. IN A +jpl.NASA.GOV. IN A +NS2.TECHNOLOGIA.net. IN A +bparker.CONNACTIVITY.com. IN A +NS1.uvm.EDU. IN A +NS.SENET.net. IN A +DNS2.UTCC.UTORONTO.CA. IN A +localhost.costorf.com. IN A +DNS2.AD. IN A +HYDRA.HELSINKI.FI. IN A +NAME.PHX.GBLX.net. IN A +NS2.FOOL.com. IN A +NS01-SERVER.CURINFO.AN. IN A +NS.CR. IN A +mail.pshift.net. IN A +NS.IRD.FR. IN A +NS.UZ. IN A +DNS.INTELCOM.SM. IN A +DNS2.UNIV-NKC.MR. IN A +HNS3.hns.com. IN A +bay.cs.UTORONTO.CA. IN A +NS0.BT.net. IN A +BAYONET.SJMERCURY.com. IN A +PAN.BIJT.net. IN A +NAVI.SUBTEND.net. IN A +NS.CIX.CX. IN A +waldorf.Informatik.Uni-Dortmund.de. IN A +NS2.ivillage.com. IN A +DNS.NIC.XLINK.net. IN A +NS1.MERCHANTWARE.CON. IN A +NS.TO.GD-ES.com. IN A +NS-A.RNC.RO. IN A +REGGAE.NCREN.net. IN A +SSS-NL.DENIC.de. IN A +NS1.TDC.TO. IN A +NS.NIC.HU. IN A +JOANNA.WILLIAM.org. IN A +NS0.IIJ.AD.JP. IN A +maus.spack.org. IN A +B.NS.VERIO.net. IN A +SECDNS.EUNET.BE. IN A +NS3.EUROPE.YAHOO.com. IN A +A.ROOT-SERVERS.net. IN A +sherickpm.com. IN MX +NS2.MEDIASERVICES.net. IN A +YARDBIRD.CNS.vt.EDU. IN A +SUNIC.SUNET.SE. IN A +NS.MT. IN A +CNDVG001.usa.net. IN A +NS1.CX.ESCROW.IOCOMM.NET.CX. IN A +DNS-02.NS.AOL.com. IN A +ns2.tesserae.com. IN A +SV10.BATELCO.COM.BH. IN A +dec.anr.state.vt.us. IN MX +3.133.188.192.IN-ADDR.ARPA. IN PTR +NS1.LONDON.UK.NETDNS.com. IN A +NS.NIC.MG. IN A +DNS1.VN. IN A +DENS20.DEN.nps.GOV. IN A +z.ip6.INT. IN A +NS3.TRIVALLEY.com. IN A +isis.imag.FR. IN A +NS.SOVAM.com. IN A +NS-SOA.DARENET.DK. IN A +NS4.NIC.TV. IN A +DNSSRV1X.mitre.org. IN A +GATEKEEPER.NYTIMES.com. IN A +D.I-DNS.net. IN A +NS.KOLO.net. IN A +NS4.FIRSTWORLD.net. IN A +DECST.CERIST.DZ. IN A +NS4.DNS.WS. IN A +NS0.GDGSC.com. IN A +UCTHPX.UCT.AC.ZA. IN A +NS2.HOTWIRED.com. IN A +ns02.ca.us.ibm.net. IN A +NS2.SPEAKEASY.net. IN A +TELCOM.ZPTC.CO.ZW. IN A +NS.DK-HOSTMASTER.DK. IN A +NS.NIC.LK. IN A +NS2.zama.net. IN A +CZ.EUNET.CZ. IN A +NS.AC.ID. IN A +NS1.CUBE.de. IN A +NS1.QUASAR.net. IN A +NS1.OFFSHORE.AI. IN A +NS5.NRSITE.com. IN A +NS.AIC.net. IN A +OWL.NCC.nps.GOV. IN A +MAXIM.gbch.net. IN A +BOW.INTNET.TD. IN A +ns1.cacheware.com. IN A +NS2.SPEEDHOST.com. IN A +NS1.COMMIT.GM. IN A +NAME.ROC.GBLX.net. IN A +90.198.245.204.IN-ADDR.ARPA. IN PTR +BOLOGNA.NETTUNO.IT. IN A +NIC.IBD.com. IN A +NS.WESTOL.com. IN A +time.SOVER.net. IN CNAME +UNIX1.CS.UMASS.EDU. IN A +AARDVARK.WR.UMIST.AC.UK. IN A +NS1.NIC.YU. IN A +mail.velco.com. IN A +DNSAUTH2.SYS.GTEI.net. IN A +NS.TELE.FI. IN A +state.vt.us. IN MX +NS.NYC.juno.com. IN A +NS1.g-world.com. IN A +AUTH2.AMERICA.net. IN A +KIRA.ECS.UMASS.EDU. IN A +CONACYT.GOB.SV. IN A +DNS.SRCE.HR. IN A +NS00.ns0.com. IN A +NS2.CL.BELLSOUTH.net. IN A +jenner.med.HARVARD.EDU. IN A +p2.cavebear.com. IN A +NS1.NIC.JE. IN A +ORCU.OR.BR.NP.ELS-GMS.att.net. IN A +NS.XBILL.org. IN A +WRAITH.CS.UOW.EDU.AU. IN A +12.159.145.204.IN-ADDR.ARPA. IN PTR +ns1.pr.SUN.com. IN A +NS.SPIN.OMNES.net. IN A +smtp.188.net. IN A +TERMINAL.2GLOBE.net. IN A +NS2.HARVARD.EDU. IN A +NAMESERVER.CNR.IT. IN A +EARTH.SY. IN A +DNS2.REACCIUN.VE. IN A +NS.TMX.COM.NI. IN A +freefour.acs.rpi.EDU. IN A +242.84.198.209.IN-ADDR.ARPA. IN PTR +CORREU.STA.AD. IN A +NS.DRUKNET.NET.BT. IN A +NS4.US.PRSERV.net. IN A +KAASASSUK.GH.GL. IN A +ECUA.NET.EC. IN A +NS.CONCYT.GOB.GT. IN A +NS2.NAP.net. IN A +DNS2.CN.net. IN A +MX.NSI.NASA.GOV. IN A +NS.TDS.net. IN A +tdns-me1.NETSCAPE.com. IN A +NS2.METU.EDU.TR. IN A +NS2.SETARNET.AW. IN A +87.184.152.204.IN-ADDR.ARPA. IN PTR +DNS.OMNIWAY.SM. IN A +NS0.U-NET.net. IN A +elektro.CMHNET.org. IN A +ns2.HIGGS.net. IN A +NS2.SKYNETWEB.com. IN A +MAGIC.MN. IN A +NS1.YAHOO.com. IN A +mx1.cdp.ADELPHIA.net. IN A +SANTO.VANUATU.COM.VU. IN A +www.mmuuf.org. IN MX +ns1.timeheart.net. IN A +NS2.TOGETHER.net. IN A +NS.AMNIC.net. IN A +NS.EENET.EE. IN A +www.ONLINEPHOTOCONTEST.com. IN A +VIC20.BLIPP.com. IN A +DNS.FROGHOUSE.org. IN A +NS2.ELI.net. IN A +NS.CAIS.com. IN A +BAABEN.AFRIQ.net. IN A +NS2.NJ.EXODUS.net. IN A +DOMREG.NIC.CH. IN A +NS.EU.net. IN A +NS1.DIEBOLD.net. IN A +NS3.CP.net. IN A +DNS.FUW.EDU.PL. IN A +www.retro.com. IN A +NS2.UNI2.net. IN A +ns1.alcatrazmedia.com. IN A +dns6.CP.MSFT.net. IN A +NS1.SEYCHELLES.net. IN A +NS2.INTERNIC.net. IN A +front.macrosoft.WAW.PL. IN A +NISC.JVNC.net. IN A +AUTH03.NS.DE.UU.net. IN A +BURDELL.CC.GATECH.EDU. IN A +NS4.AH.net. IN A +ns1.sgh-net.de. IN A +Leland2.stanford.EDU. IN A +CBRU.BR.NS.ELS-GMS.att.net. IN A +DENEB.DOMAINNT.net. IN A +ns1.ivm.net. IN A +NS0.CWCI.net. IN A +35.110.16.12.IN-ADDR.ARPA. IN CNAME +f.trns. IN A +ODISEJ.TELEKOM.YU. IN A +FRCU.EUN.EG. IN A +NS.HHS.net. IN A +FOO.GRNET.GR. IN A +mail.WonderWorks.com. IN A +NS1.IAFRICA.com. IN A +NS.KACST.EDU.SA. IN A +srs.state.vt.us. IN A +OM4.OMANTEL.NET.OM. IN A +Yeshua.Christ.com. IN A +NS1.SIMORGH.com. IN A +OLKETA.SOLOMON.COM.SB. IN A +BANBA.DOMAINREGISTRY.IE. IN A +NOC.IOS.com. IN A +ns.schnism.net. IN A +e4.ny.us.IBM.com. IN A +DNS2.SEANET.com. IN A +doubt.dd.org. IN A +AMBER.ELEKTRON.PL. IN A +gw.rge.com. IN A +NS2.ZTNET.com. IN A +NS3.INFI.net. IN A +ZA.AKADNS.net. IN A +ESTIA.CSI.FORTH.GR. IN A +vtagr04.agr.state.vt.us. IN A +NS1-PUBLIC.ZTX.COMPAQ.com. IN A +ADMII.ARL.MIL. IN A +NS.NIXU.FI. IN A +DNS2.PIONEERNET.net. IN A +NS.NIC.CL. IN A +NS2.UTZ. IN A +NS4.LUXNOC.com. IN A +NS2.PBI.net. IN A +annwfn.erfurt.thur.de. IN A +NS1.MW.mediaone.net. IN A +NS1.ISU.NET.SA. IN A +pop.SHOREHAM.net. IN CNAME +DNS2.GUERNSEY.net. IN A +NS1.BEACHSHORE.net. IN A +HKUXB.HKU.HK. IN A +NS.DOLEH.com. IN A +NS.hactrn.net. IN A +MALAKULA.BONDY.IRD.FR. IN A +NS1.mediaone.net. IN A +NS2.GPG.com. IN A +noc.BelWue.de. IN A +NS2.GIP.net. IN A +RS.ISLES.net. IN A +BOW.INTNET.GQ. IN A +A.OPEN.BY. IN A +us.i1.YIMG.com. IN CNAME +athome.wetlogic.net. IN CNAME +NS1.NIST.GOV. IN A +mail.jerusalem-mail.com. IN A +ISDSUN.cr.USGS.GOV. IN A +NS.BOSTON.juno.com. IN A +NS2.CADABRA.com. IN A +nps.GOV. IN MX +RELAY.HUJI.AC.IL. IN A +styx.tahina.priv.at. IN A +ISGATE.IS. IN A +ns0.lux.dot-eu.org. IN A +BILBO.NASK.ORG.PL. IN A +MAIL.TARSUS.com. IN A +SUN.REDIRIS.ES. IN A +NS2.NEASE.net. IN A +OHCU.OH.MT.NP.ELS-GMS.att.net. IN A +NS2.NF. IN A +MIRAF-SERVER3.HONDUTEL.HN. IN A +ns3.worldnet.att.net. IN A +NS2.NETNAMES.net. IN A +ITGBOX.IAT.CNR.IT. IN A +NS2.ADELPHIA.net. IN A +NS2.RIPN.net. IN A +NS1.cinenet.net. IN A +jengate.thur.de. IN A +NOC.ULCC.JA.net. IN A +NS.NOC.UZ. IN A +NS0.JA.net. IN A +NS2.INR.net. IN A +netsage.org. IN A +TERI.USP.AC.FJ. IN A +NS2.NETSOL.com. IN A +NS2.ABAC.com. IN A +NS2.NIC.FR. IN A +KANIN.ARNES.SI. IN A +NS.EDU.GU. IN A +DNS.INRIA.FR. IN A +HEDNS1.GOOGLE.com. IN A +asylum.sf.ca.us. IN A +ACT2.ACT2000.net. IN A +ICM1.ICP.net. IN A +202.192.103.198.209.IN-ADDR.ARPA. IN PTR +ECSEL.jhuapl.EDU. IN A +NS2.DCNY.DOUBLECLICK.net. IN A +keith.netsage.org. IN A +MANTA.OUTREMER.com. IN A +NS2.globalnetisp.net. IN A +NS2.CCSRS.net. IN A +NS1.NL.CONCENTRIC.com. IN A +NS2.VI.net. IN A +NS2.NEO.net. IN A +cgi.MERCURYCENTER.com. IN CNAME +ORSTOM.RIO.net. IN A +NS2.CONRADPROMOTIONS.com. IN A +YARRINA.CONNECT.COM.AU. IN A +dns03.OPS.usa.net. IN A +APPSRV.HAITIWORLD.com. IN A +NS.RELCOM.KZ. IN A +NS1.MAGIC-MOMENTS.com. IN A +NS.ALCATEL.com. IN A +ns2.terra.net. IN A +NS3.hotmail.com. IN A +vtc.VSC.EDU. IN MX +www.vmba.org. IN MX +NAHOURI.ONATEL.BF. IN A +SERVER2.INFN.IT. IN A +NS2.AI-R.com. IN A +NS1.FREE.net. IN A +vcmr-54.server.rpi.EDU. IN A +haig.CS.UCL.AC.UK. IN A +mail.nova-data.com. IN A +MOEVAX.EDU.TW. IN A +NS2.LTWCC.org. IN A +NS.BA. IN A +noc.HRZ.uni-bielefeld.de. IN A +VANILLA.WRO.nps.GOV. IN A +NS2.SZTAKI.HU. IN A +SECIU.EDU.UY. IN A +COL2.CARIBSURF.com. IN A +NS2.QATAR.NET.QA. IN A +NS2.E-SYNC.net. IN A +ns1.eu.SUN.com. IN A +NS1.UUSJ.DOUBLECLICK.net. IN A +NS2.CUHK.EDU.HK. IN A +NS1.MEITCA.com. IN A +NS2.DSL.net. IN A +techfac.techfak.uni-bielefeld.de. IN A +listserv.performancediver.com. IN A +foolusmf.D4P.net. IN CNAME +pedic-med.vrx.net. IN A +GRUMPY.NET.NA. IN A +BK.tifosi.com. IN A +ns3.PAIR.com. IN A +ns2.ar.com. IN A +MASSIRA.ONPT.NET.MA. IN A +NS.KBFI.EE. IN A +ns3.Algebra.com. IN A +faerber.muc.de. IN MX +9.206.203.192.IN-ADDR.ARPA. IN PTR +PUKU.UNZA.ZM. IN A +ATLNET.ATLONLINE.com. IN A +Z1.NS.NYC1.GLOBIX.net. IN A +www.hometownbands.com. IN A +SIMON.CS.CORNELL.EDU. IN A +EKEKO.RCPIP.net. IN A +emerald.itnet.com.PL. IN A +DNS1.ICS.FORTH.GR. IN A +NS.ATL.BELLSOUTH.net. IN A +ntp.ctr.COLUMBIA.EDU. IN CNAME +NS2.GLOBECOMM.net. IN A +UUNS1DNS1.FLONETWORK.com. IN A +GRIN.GNOSH.net. IN A +NS.DIGSYS.BG. IN A +uunet.UU.net. IN MX +ns1.vermontel.com. IN A +NS2.GREENMOUNTAINACCESS.net. IN A +38.241.5.198.IN-ADDR.ARPA. IN PTR +NS1.NIC.UK. IN A +DNS.FCCN.PT. IN A +NS2.NIC.TJ. IN A +NS4.NEWACCOUNT.com. IN A +NS2.IHUG.NET.NZ. IN A +NS.SIGNALZ.com. IN A +DNS.NIC.AD. IN A +3.2.39.137.IN-ADDR.ARPA. IN PTR +UUCP-GW-2.PA.DEC.com. IN A +NS.LANDLORDS.com. IN A +NS2.EXODUS.net. IN A +NS2.SCRUZ.net. IN A +NS.PIPEX-SZ.net. IN A +saturn.SUN.com. IN A +e24.nc.us.IBM.com. IN A +NMS.CYFRONET.KRAKOW.PL. IN A +NS.TWNIC.net. IN A +ns2.alcatel.NO. IN A +INPAKSODNS.AKSO.nps.GOV. IN A +mail.reptiles.org. IN A +59.187.152.204.IN-ADDR.ARPA. IN PTR +ns1.mobydark.com. IN A +NS.KG. IN A +NS.SPB.SU. IN A +PENDRAGON.CS.PURDUE.EDU. IN A +NS1.IGC.APC.org. IN A +USDNS.NIC.us. IN A +NS2.WEBTRENDS.com. IN A +URANUS.DAIMI.AAU.DK. IN A +ANTANA.IRD.MG. IN A +NS.JERSEY.juno.com. IN A +NS2.INTERNET-TOOLS.com. IN A +ns-tk012.ocn.AD.JP. IN A +bvt-ext.gdarm.com. IN A +NS1.ID. IN A +NS2.MAHNET.net. IN A +NS.ALCANET.COM.AU. IN A +UTAMA.BOLNET.BO. IN A +NS.CNC.AC.CN. IN A +NS.KREN.NE.KR. IN A +NS1.REDHAT.com. IN A +db.rc.VIX.com. IN A +198.103.198.209.IN-ADDR.ARPA. IN CNAME +alf.pbks.PL. IN A +FLAG.EP.net. IN A +DNS2.IUNET.IT. IN A +NS2.QUANTIFIED.net. IN A +INTERNET-SERVER.ZURICH.IBM.com. IN A +seaipsvcs.idx.com. IN A +lebanon.valley.net. IN A +SERVER.NORDU.net. IN A +NS.NIC.DO. IN A +isc-01.iscvt.org. IN A +NAC.NO. IN A +SAVA.UTIC.NET.BA. IN A +NS1.TOKYO.JP.NETDNS.com. IN A +NETSERV2.ITS.rpi.EDU. IN A +IFI.UIO.NO. IN A +www.TOAPLAN.com. IN A +ns2.the-frontier.org. IN A +NS.UNAM.MX. IN A +ARISTO.TAU.AC.IL. IN A +DNS.CS.WISC.EDU. IN A +NS1.NIC.IR. IN A +NS1.RETINA.AR. IN A +mailer.connriver.net. IN A +NS.ATI.TN. IN A +NS2.CLEAR.NET.NZ. IN A +NS4.EARTHLINK.net. IN A +mejac.palo-alto.ca.us. IN A +New-York4.NY.ALTER.net. IN A +falcon.tallship.net. IN A +ZEUS.CC.UCY.AC.CY. IN A +NS2.SECURE.net. IN A +NS0.FLIRBLE.org. IN A +dns.zenon.net. IN A +SERVIDOR.MICROASTUR.ES. IN A +DOWNSTAGE.MCS.VUW.AC.NZ. IN A +ns2.GNAC.com. IN A +PRIFI.EUNET.FI. IN A +ns2.k12.vt.us. IN A +ns2.nic.mnet. IN A +NS0.PIPEX.net. IN A +NS1.SANFRANCISCO.US.NETDNS.com. IN A +AMRA.NIC.GOV.JO. IN A +kw.com.CN. IN MX +SHNS.163.net. IN A +NS.ER.USGS.GOV. IN A +FAITH.MYNET.net. IN A +mail.smuggs.com. IN A +MIMOS.MY. IN A +NS.GU. IN A +mx00.schlund.de. IN A +CADDSYS.IPTEK.net. IN A +NS0.TELIA.NIC.NU. IN A +NS2.GRANITECANYON.com. IN A +GATEKEEPER.corning.com. IN A +NS2.2DAY.com. IN A +1.0.0.127.IN-ADDR.ARPA. IN PTR +RAIN.PSG.com. IN A +STRAWB.MIT.EDU. IN A +NS2.DIGISERVE.com. IN A +UMACSN2.UMAC.MO. IN A +NS.JM. IN A +12.153.66.206.IN-ADDR.ARPA. IN PTR +EAST.ISI.EDU. IN A +NS2.UUNET.CA. IN A +SUNNY.STAT-USA.GOV. IN A +BOW.INTNET.CF. IN A +NS4.TELE.DK. IN A +NS2.sodak.net. IN A +NS1.NEWYORK.US.NETDNS.com. IN A +NS2.PSI.net. IN A +NS.KREONET.RE.KR. IN A +GIANT.MINDLINK.net. IN A +NS0.SECTOR001.org. IN A +DNS.SEABONE.net. IN A +NS2.MANA.PF. IN A +NRWEB.CENPAC.NET.NR. IN A +www.TRAVELPHOTOCONTESTS.com. IN A +NS1.REGEX.com. IN A +BIGBIRD.ITD.nps.GOV. IN A +CUNIXD.CC.COLUMBIA.EDU. IN A +NS1.CLASSIFIEDMONSTER.com. IN A +SERVER1.SANS.org. IN A +BRONZE.COIL.com. IN A +SCSNMS.SWITCH.CH. IN A +SCE.CNC.UNA.PY. IN A +RELAY.LA.TIS.com. IN A +NS.AUSTIN.IBM.com. IN A +SERVICE.robert-morris.EDU. IN A +MERCURY.ML.org. IN A +proxy.pccf.net. IN A +DUB-NAME-SVC-1.compuserve.com. IN A +NS.CNRI.reston.va.us. IN A +NS.UCAD.SN. IN A +ns01.ny.us.ibm.net. IN A +NS4-AUTH.ALASKA.net. IN A +BOW.INTNET.NE. IN A +NS-JP.SINET.AD.JP. IN A +ns.musin.de. IN A +ip1.romkey.SEG.net. IN A +DNS2.ITD.UMICH.EDU. IN A +mail.rpi.EDU. IN A +INECO.NIC.ES. IN A +DNS2.FIREHOUSE.net. IN A +BOW.INTNET.BJ. IN A +sundown.vtc.VSC.EDU. IN A +NIC.AIX.GR. IN A +NIC.AD.JP. IN A +NS.DC.IGC.org. IN A +LHR.NS.GDNS.net. IN A +NS2.WEBMAGIC.net. IN A +MUNNARI.OZ.AU. IN A +HIPPO.RU.AC.ZA. IN A +PEBBLES.IOM.com. IN A +penpal.dmz.RPSLMC.EDU. IN A +netnews.HINET.net. IN A +INS2.TOSA.TWTELECOM.net. IN A +proxy6.cisco.com. IN A +NS2.HOST4U.net. IN A +POIPARAU.OYSTER.NET.CK. IN A +NS-EXT.VIX.com. IN A +NS2.NURSAT.net. IN A +mail2.kw.com.CN. IN A +NS-02B.ANS.net. IN A +DNS.RCCN.net. IN A +B.ROOT-SERVERS.ORSC. IN A +FIREHOUSE.net. IN A diff --git a/bin/tests/system/cacheclean/knowngood.dig.out b/bin/tests/system/cacheclean/knowngood.dig.out new file mode 100644 index 0000000..a0f087e --- /dev/null +++ b/bin/tests/system/cacheclean/knowngood.dig.out @@ -0,0 +1,953 @@ +YA.AKAMAI.com. 604800 IN A 204.178.118.68 +UPR1.UPR.CLU.EDU. 604800 IN A 136.145.1.4 +integra.s-integra.co.JP. 604800 IN A 210.162.202.34 +avalon.iks-jena.de. 604800 IN A 194.221.90.34 +NS1.GLOBALDNS.com. 604800 IN A 206.253.214.11 +NS.RDU.BELLSOUTH.net. 604800 IN A 205.152.32.20 +ns.space.net. 604800 IN A 195.30.0.1 +SUN.MHS-RELAY.AC.UK. 604800 IN A 128.86.8.25 +AYAX.UNIANDES.EDU.CO. 604800 IN A 157.253.50.30 +DNS.NIC.CD. 604800 IN A 194.38.74.11 +NS.DNS.PT. 604800 IN A 193.136.0.1 +NS1.INTERNETSHARE.com. 604800 IN A 63.207.108.53 +MASTER.DNS.BE. 604800 IN A 194.7.171.243 +CATAMOUNT.middlebury.EDU. 604800 IN A 140.233.2.204 +FM03.FM. 604800 IN A 206.49.89.4 +NAAMAK.NCST.ERNET.IN. 604800 IN A 202.41.110.66 +gateway2.BFG.com. 604800 IN A 166.102.214.66 +NS3.NS.ESAT.net. 604800 IN A 192.111.39.100 +DNS1.INTUIT.com. 604800 IN A 208.157.255.4 +DEN-NS2.FWIDCSERVICES.net. 604800 IN A 216.7.160.32 +SOL.UNDPBI.TELEPAC.net. 604800 IN A 194.65.87.2 +NS2.tridog.com. 604800 IN A 206.168.112.51 +DNS2.KW. 604800 IN A 161.252.48.150 +NS2.MAIL.com. 604800 IN A 165.251.1.3 +NS.FIRSTCOM.CL. 604800 IN A 200.27.2.2 +DNS4.QUICKEN.com. 604800 IN A 198.3.99.252 +bofh.cid.net. 604800 IN A 212.172.21.254 +NS1.KRNIC.net. 604800 IN A 202.30.50.51 +NS2.SR.net. 604800 IN A 200.1.156.11 +NS1.TELSTRA.net. 604800 IN A 139.130.4.5 +ns.cafax.SE. 604800 IN A 192.71.228.17 +NS1.DNS.NET.NZ. 604800 IN A 202.46.161.3 +NS.CONCOURSE.com. 604800 IN A 199.218.113.2 +35.32/27.110.16.12.IN-ADDR.ARPA. 604800 IN PTR mail.nova-data.com. +CCC.champcable.com. 604800 IN A 207.41.53.11 +NS.RIPE.net. 604800 IN A 193.0.0.193 +NS.NIC.NU. 604800 IN A 128.11.47.50 +KIM.CAMNET.CM. 604800 IN A 195.24.192.35 +DOGON.SOTELMA.net. 604800 IN A 208.144.230.1 +DNS02.FLAME.org. 604800 IN A 204.152.184.97 +NS.MIA.BELLSOUTH.net. 604800 IN A 205.152.16.20 +mail.ok.RU. 604800 IN A 195.2.83.162 +NS.NIC.MX. 604800 IN A 200.23.1.1 +NS2.BERKELEY.EDU. 604800 IN A 128.32.136.12 +NS2.BERKELEY.EDU. 604800 IN A 128.32.206.12 +SHIKHAR.MOS.COM.NP. 604800 IN A 202.52.255.5 +noc.rrz.Uni-Koeln.de. 604800 IN A 134.95.100.209 +NS.KORNET.net. 604800 IN A 168.126.63.1 +keith.gazpacho.org. 604800 IN A 209.67.235.37 +NS2.appliedtheory.com. 604800 IN A 168.75.17.11 +NS.CERNET.net. 604800 IN A 202.112.0.44 +smtp.ELISTX.com. 604800 IN A 209.116.252.130 +NS-AIT.THNIC.net. 604800 IN A 192.41.170.219 +from.PL. 604800 IN A 212.160.132.114 +mailhub.icann.org. 604800 IN A 192.0.34.33 +SEC1.DNS.UK.PSI.net. 604800 IN A 154.32.105.34 +isrv3-i.isc.org. 604800 IN A 204.152.184.87 +PHLOEM.UOREGON.EDU. 604800 IN A 128.223.32.35 +CTINA.AR. 604800 IN A 200.16.97.17 +DNS2.IAM.NET.MA. 604800 IN A 212.217.0.12 +10.126.39.137.IN-ADDR.ARPA. 604800 IN PTR Fddi0-0.New-York4.NY.ALTER.NET. +DNS.PRINCETON.EDU. 604800 IN A 128.112.129.15 +NS.BELLSOUTH.net. 604800 IN A 205.152.0.5 +NS1.SNS-FELB.DEBIS.com. 604800 IN A 53.122.1.10 +localhost. 604800 IN A 127.0.0.1 +hm6.vt.highmeadow.com. 604800 IN A 207.136.209.6 +SYRUP.hill.com. 604800 IN A 208.162.106.3 +NS99.WAIKATO.AC.NZ. 604800 IN A 130.217.76.27 +NS4.CW.net. 604800 IN A 204.70.49.234 +NS2.SLOWMOE.com. 604800 IN A 137.118.8.50 +ns2.hypa.net. 604800 IN A 63.160.181.11 +ns.sxtyptt.NET.CN. 604800 IN A 202.99.192.68 +NS2.MERCHANTWARE.com. 604800 IN A 209.170.142.35 +uunymdgds1.DOUBLECLICK.net. 604800 IN A 206.65.183.21 +e34.co.us.IBM.com. 604800 IN A 32.97.110.132 +kista.dns.swip.net. 604800 IN A 192.71.220.9 +ZEBRA.UEM.MZ. 604800 IN A 196.3.96.67 +NET2.GENDYN.com. 604800 IN A 204.60.171.9 +NS0.UTK.EDU. 604800 IN A 160.36.0.66 +NS.RELCOM.EU.net. 604800 IN A 193.124.23.3 +DNS0.AXION.BT.CO.UK. 604800 IN A 132.146.5.1 +mail.vhv.com. 604800 IN A 208.5.161.11 +DNS4.UK.MSFT.net. 604800 IN A 213.199.144.152 +NS2.ADNS.net. 604800 IN A 199.5.157.3 +NS1.SEATTLE.US.NETDNS.com. 604800 IN A 206.253.214.13 +NS2.UNIVIE.AC.at. 604800 IN A 193.171.255.66 +NS15B.BOCA15-VERIO.com. 604800 IN A 208.55.91.51 +www.BAYAREA.com. 604800 IN CNAME vh80040.vh8.infi.net. +ns4.onemain.com. 604800 IN A 63.208.210.11 +NS2.EDIGITALS.com. 604800 IN A 211.39.139.36 +MICHAEL.VATICAN.VA. 604800 IN A 212.77.0.2 +AUSTIN.GH.com. 604800 IN A 196.3.64.1 +sld-ns2.CNNIC.NET.CN. 604800 IN A 202.97.16.197 +NS2.CDC.GOV. 604800 IN A 198.246.96.92 +NS.WATSON.IBM.com. 604800 IN A 198.81.209.2 +NS.NIC.SH. 604800 IN A 194.205.62.60 +NS2.BAHNHOF.net. 604800 IN A 212.85.64.4 +NS-AUTH2.cmates.com. 604800 IN A 208.23.213.3 +ISDMNL.WR.USGS.GOV. 604800 IN A 130.118.4.2 +NS2.COBEX.net. 604800 IN A 207.102.129.72 +MERLE.CIRA.CA. 604800 IN A 64.26.149.98 +NS.UVG.EDU.GT. 604800 IN A 168.234.68.2 +NS1.CWVA.DOUBLECLICK.net. 604800 IN A 205.138.3.20 +eliot.diebold.com. 604800 IN A 204.151.249.21 +NS.ALMADEN.IBM.com. 604800 IN A 198.4.83.35 +NS2.INTERNETSQUARE.com. 604800 IN A 205.227.232.9 +mail.QUEST-NET.com. 604800 IN A 207.140.30.11 +Z1.NS.LHR1.GLOBIX.net. 604800 IN A 212.111.32.38 +DNS1.AVANTEL.NET.MX. 604800 IN A 200.33.213.66 +vh80040.vh8.INFI.net. 604800 IN A 209.97.59.245 +NS.LEB.net. 604800 IN A 206.127.55.2 +NS.DCC.UCHILE.CL. 604800 IN A 146.83.5.204 +CLOUSO.RISQ.QC.CA. 604800 IN A 192.26.210.1 +muenster.westfalen.de. 604800 IN A 193.174.5.2 +us.a1.YIMG.com. 604800 IN CNAME a32.g.a.YIMG.com. +NS.DEMOS.SU. 604800 IN A 194.87.0.8 +NS.DEMOS.SU. 604800 IN A 194.87.0.9 +south.NAVPOINT.com. 604800 IN A 207.106.42.12 +netconsult.netconx.de. 604800 IN A 193.141.75.1 +DNS2.btinternet.com. 604800 IN A 194.73.73.94 +NS2.CINE.net. 604800 IN A 207.168.250.12 +castor.cmc.ec.gc.CA. 604800 IN A 142.135.4.14 +EX2-DNS0.AVENUEA.com. 604800 IN A 216.34.88.20 +firewall3.glaxowellcome.com. 604800 IN A 192.58.204.207 +MACU.MA.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.145.136 +NS.PA. 604800 IN A 168.77.8.2 +TGSERV.TELE.GL. 604800 IN A 194.177.224.7 +KYNSE02.MESSAGESECURE.com. 604800 IN A 216.142.252.201 +GORGON.XTRA.CO.NZ. 604800 IN A 202.27.158.34 +DNS.NIC.IT. 604800 IN A 193.205.245.5 +pop.VERMONTEL.net. 604800 IN CNAME loomis.VERMONTEL.net. +NS2.REGISTRY.HM. 604800 IN A 209.54.168.55 +NAMESERVER1.CONCENTRIC.net. 604800 IN A 207.155.183.73 +47.131.127.204.IN-ADDR.ARPA. 604800 IN PTR mtiwmhc22.worldnet.att.net. +mailhost.tfm.com. 604800 IN A 192.231.224.11 +NS1.MRC.GM. 604800 IN A 212.60.69.1 +NS.WIDE.AD.JP. 604800 IN A 203.178.136.63 +NS.BTA.NET.CN. 604800 IN A 202.96.0.133 +NS2.ISPC.org. 604800 IN A 209.124.64.11 +BOW.RAIN.FR. 604800 IN A 194.51.3.49 +srs.srs.state.vt.us. 604800 IN A 159.105.101.150 +NS4.WEB2010.com. 604800 IN A 216.157.55.6 +NS.TELECOM.NET.ET. 604800 IN A 196.27.22.43 +NS1.DNS.NET.KH. 604800 IN A 203.127.100.21 +GATEN.JARING.MY. 604800 IN A 161.142.227.17 +shell.nominum.com. 604800 IN A 204.152.187.59 +CHEOPS.ANU.EDU.AU. 604800 IN A 150.203.224.24 +VANGOGH.CS.BERKELEY.EDU. 604800 IN A 128.32.33.5 +NS2.NOC.NULLUS.net. 604800 IN A 63.119.253.254 +NIC.LTH.SE. 604800 IN A 130.235.20.3 +ns.farm.net. 604800 IN A 216.112.179.160 +NS.USEC.SUN.com. 604800 IN A 192.9.48.3 +NS2.YOUR-DOMAIN.com. 604800 IN A 216.167.31.177 +DNS-EAST.PREP.net. 604800 IN A 129.250.252.10 +ns.hcr.net. 604800 IN A 208.240.246.4 +NS-RCH.nortelnetworks.com. 604800 IN A 192.135.215.2 +crl.DEC.com. 604800 IN A 192.58.206.2 +NS.PIXAR.ES. 604800 IN A 194.143.196.3 +MEX1-M-213.UNINET.NET.MX. 604800 IN A 200.33.146.213 +NS.ITU.CH. 604800 IN A 156.106.192.121 +matrix.uwm.EDU.PL. 604800 IN A 213.184.3.136 +gateway1.gmcr.com. 604800 IN A 12.34.108.130 +NS2.DNS.BR. 604800 IN A 200.19.119.99 +foxharp.boston.MA.us. 604800 IN MX 10 bparker.connactivity.com. +Quest-7.symquest.com. 604800 IN A 64.69.102.131 +NS2.VERIO.net. 604800 IN A 129.250.31.190 +NAME.IAD.GBLX.net. 604800 IN A 204.152.166.155 +NS2.EMIRATES.NET.AE. 604800 IN A 194.170.1.7 +supai.oit.UMASS.EDU. 604800 IN A 128.119.175.6 +QUERN.EPILOGUE.com. 604800 IN A 128.224.1.136 +NS3.TOPICA.com. 604800 IN A 206.111.131.72 +NS1.JERKY.net. 604800 IN A 204.57.55.100 +JTB.BRUNET.BN. 604800 IN A 202.160.8.2 +AUTH100.NS.UU.net. 604800 IN A 198.6.1.202 +BOW.INTNET.DJ. 604800 IN A 193.251.143.253 +OSI2.GUA.net. 604800 IN A 205.161.188.3 +AZMODAN.ULA.VE. 604800 IN A 150.185.130.16 +THUMPER.RPSLMC.EDU. 604800 IN A 144.74.22.8 +ICHU.RCP.NET.PE. 604800 IN A 161.132.5.14 +NS.NIC.AC. 604800 IN A 194.205.62.120 +DNS.NETFLIGHT.com. 604800 IN A 207.88.32.2 +ns2.UTORONTO.CA. 604800 IN A 128.100.102.202 +mail.giffordmed.org. 604800 IN A 130.189.100.51 +RATA.VUW.AC.NZ. 604800 IN A 130.195.2.11 +NS-2.ADMONITOR.net. 604800 IN A 216.35.185.40 +NCC.MOC.KW. 604800 IN A 196.1.69.98 +NS.EUNET.ES. 604800 IN A 193.127.1.11 +NS3.best.com. 604800 IN A 209.24.149.42 +zip.MAIL-LIST.com. 604800 IN MX 5 zip.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 20 sluice.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 20 pipeline.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 20 transport.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 50 brisk.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 50 swifty.MAIL-LIST.com. +zip.MAIL-LIST.com. 604800 IN MX 50 velocity.MAIL-LIST.com. +JATZ.AARNET.EDU.AU. 604800 IN A 139.130.204.4 +DNS2.MAN.LODZ.PL. 604800 IN A 212.51.192.5 +NS.VERITAS.com. 604800 IN A 204.177.156.38 +218.241.103.199.IN-ADDR.ARPA. 604800 IN PTR abyssinian.sleepycat.com. +BOW.SNPT.KM. 604800 IN A 195.101.19.253 +Z1.NS.SJC1.GLOBIX.net. 604800 IN A 209.10.34.55 +DNS.NIC.TT. 604800 IN A 24.3.198.194 +MAKISIG.IPHIL.net. 604800 IN A 203.176.28.135 +NS.DK.net. 604800 IN A 193.88.44.42 +NS.NI. 604800 IN A 200.30.36.8 +NS.NI. 604800 IN A 165.98.1.2 +CIUP1.NCC.UP.PT. 604800 IN A 193.136.51.52 +ns2.verisign-grs.com. 604800 IN A 198.41.3.108 +NS1.UMASS.EDU. 604800 IN A 128.119.166.14 +NS.NEWACCOUNT.net. 604800 IN A 216.121.96.26 +UDNS2.ULTRADNS.net. 604800 IN A 204.74.101.1 +NS2.LATNET.LV. 604800 IN A 159.148.108.1 +info-server.surrey.AC.UK. 604800 IN A 131.227.102.6 +NS2.SQUONK.net. 604800 IN A 63.84.12.135 +NS2.DSO.net. 604800 IN A 206.16.77.11 +www.energyenhancement.org. 604800 IN A 216.121.175.228 +DNS1.BD. 604800 IN A 209.58.24.5 +nl.COMPUWARE.com. 604800 IN MX 150 uucp.nl.net. +nl.COMPUWARE.com. 604800 IN MX 50 bitbucket.extern.uniface.nl. +nl.COMPUWARE.com. 604800 IN MX 100 smtp.nl.net. +NS.DHIRAAGU.MV. 604800 IN A 202.1.192.196 +TRANTOR.UMD.EDU. 604800 IN A 128.8.10.14 +NS.ALCANET.NO. 604800 IN A 193.213.238.10 +Z6.MSFT.AKADNS.com. 604800 IN A 207.229.152.20 +NS4.ync.net. 604800 IN A 206.185.20.9 +CMTU.MT.NS.ELS-GMS.att.net. 604800 IN A 12.127.16.69 +vh40099.vh4.INFI.net. 604800 IN A 209.97.59.121 +ns2.secondary.nl. 604800 IN A 194.229.138.6 +abyssinian.sleepycat.com. 604800 IN A 199.103.241.218 +APHEX.MENTOR.BE. 604800 IN A 193.121.64.5 +webmail.fiberia.com. 604800 IN A 216.55.147.2 +localhost.moonmothers.com. 604800 IN A 127.0.0.1 +NS2.DNS.LU. 604800 IN A 158.64.229.3 +NS.VISUALCOM.ES. 604800 IN A 194.143.202.202 +TONIC.TO. 604800 IN A 206.184.59.10 +NS1.CRSNIC.net. 604800 IN A 198.41.3.39 +trurl.ispid.com.PL. 604800 IN A 195.150.99.3 +datingagentur.de. 604800 IN A 212.227.216.57 +NS2.NSIREGISTRY.net. 604800 IN A 198.41.3.108 +ICE.VIA-NET-WORKS.IE. 604800 IN A 212.17.32.2 +sgi1.map.com. 604800 IN A 204.71.19.20 +NS0.HS0.U-NET.net. 604800 IN A 194.119.128.70 +candle.pha.pa.us. 604800 IN A 162.33.245.46 +NS1.PACIFIC.NET.SG. 604800 IN A 192.169.33.3 +NS.CENIAI.NET.CU. 604800 IN A 169.158.128.136 +NS2.UUCP.NE.JP. 604800 IN A 210.141.111.69 +za.akamaitech.net. 604800 IN A 204.178.107.226 +NS.UCR.AC.CR. 604800 IN A 163.178.88.2 +DNS-02.NS.cs.com. 604800 IN A 205.188.157.235 +dns2.primary.net. 604800 IN A 205.242.187.235 +PAPPSRV.PAPP.UNDP.org. 604800 IN A 192.115.229.1 +NS1.REGME.com. 604800 IN A 207.153.57.14 +DNS.CS.KULEUVEN.AC.BE. 604800 IN A 134.58.40.4 +NS1.VERMONTLAW.net. 604800 IN A 63.89.26.15 +mail.garmontusa.com. 604800 IN A 64.30.8.178 +NS2.SAIPAN.com. 604800 IN A 202.128.28.2 +NS.ARICATRA.com. 604800 IN A 206.64.112.114 +ns2.reedmedia.net. 604800 IN A 209.241.86.6 +NS.NETLAB.SK. 604800 IN A 195.168.1.4 +RELAY.GW.tislabs.com. 604800 IN A 192.94.214.100 +b.ns.tmcs.net. 604800 IN A 209.104.33.252 +NS1.IBL.BM. 604800 IN A 199.172.192.1 +ok.RU. 604800 IN A 195.2.83.162 +NS.RICC.ALMA-ATA.SU. 604800 IN A 194.87.112.4 +KITKA.MARNET.MK. 604800 IN A 194.149.131.2 +dasher.dartmouth.EDU. 604800 IN A 129.170.208.6 +NS0.PLANET-THREE.com. 604800 IN A 212.49.219.164 +KNOCK.SER.BBNPLANET.net. 604800 IN A 192.239.16.129 +tornado.webtech.elk.PL. 604800 IN A 212.244.162.100 +AUTH2.NS.IDT.net. 604800 IN A 169.132.133.1 +host3.VTLEGALAID.org. 604800 IN A 207.136.208.115 +NS.EUNET.SK. 604800 IN A 192.108.130.33 +TULKU.NIC.AR. 604800 IN A 200.16.97.77 +RELAY.CDNNET.CA. 604800 IN A 192.73.5.1 +DNS2.TPSA.PL. 604800 IN A 194.204.152.34 +enterprise.wirbel.com. 604800 IN A 194.231.54.2 +ECNET.EC. 604800 IN A 157.100.45.2 +ENGINE1.UNA.net. 604800 IN A 208.136.52.74 +WYCU.WY.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.128.43 +ARWENA.NASK.WAW.PL. 604800 IN A 193.59.201.28 +PAC2.NIPR.MIL. 604800 IN A 199.252.155.234 +DAISY.EE.UND.AC.ZA. 604800 IN A 146.230.192.18 +odin.ietf.org. 604800 IN A 132.151.1.176 +dns.kaben-net.de. 604800 IN A 195.179.28.17 +NS2.ALTAVISTA.com. 604800 IN A 209.73.164.7 +CASTOR.TELEGLOBE.net. 604800 IN A 199.202.55.2 +CIR.RED.SV. 604800 IN A 168.243.254.1 +PIJIN.COM.SB. 604800 IN A 202.139.42.10 +NS4.CTCCOM.net. 604800 IN A 64.69.100.35 +NS1.SOL.NO. 604800 IN A 195.225.2.10 +DNS2.TK.MSFT.net. 604800 IN A 207.46.232.38 +NS.BSDI.com. 604800 IN A 207.174.116.8 +NS.SVIANED.nl. 604800 IN A 143.177.1.3 +NS.NOVELL.com. 604800 IN A 137.65.1.1 +NS.LUCKY.net. 604800 IN A 193.193.193.100 +SJC-NS2.SJC.LYCOS.com. 604800 IN A 206.79.171.40 +NS1.OP.net. 604800 IN A 209.152.193.4 +worldnet.att.net. 604800 IN A 199.70.151.234 +APIES.FRD.AC.ZA. 604800 IN A 137.214.80.1 +mail.skiinsurance.com. 604800 IN A 207.136.205.152 +NS.BELNET.BE. 604800 IN A 193.190.198.2 +NS.BELNET.BE. 604800 IN A 193.190.198.10 +KOMO.INET.GA. 604800 IN A 208.148.44.1 +EARTH.THEPLANET.net. 604800 IN A 195.92.195.222 +VASCO.USMA.AC.PA. 604800 IN A 208.141.92.2 +GODFEVER.DCCSERVER.com. 604800 IN A 208.137.22.6 +BOS-NS2.BOS.LYCOS.com. 604800 IN A 209.67.228.40 +NS2.GOTO.com. 604800 IN A 204.71.128.137 +NS1.overstock.com. 604800 IN A 207.225.194.13 +NS1-PUBLIC.ZMA.COMPAQ.com. 604800 IN A 161.114.64.24 +ns.ilovedomain.com. 604800 IN A 211.175.164.170 +ns1.anycast.net. 604800 IN A 216.196.51.4 +PASCAL.UPRR.PR. 604800 IN A 134.202.1.120 +NS3-AUTH.SPRINTLINK.net. 604800 IN A 144.228.255.10 +NS1-Y.DNS.PIPEX.net. 604800 IN A 158.43.193.89 +prue.eim.surrey.AC.UK. 604800 IN A 131.227.76.5 +TROLL-GW.GATECH.EDU. 604800 IN A 130.207.244.251 +NS.SIERRATEL.SL. 604800 IN A 194.133.124.5 +ns2.PSHIFT.com. 604800 IN A 208.153.85.21 +NS.ERS.IBM.com. 604800 IN A 204.146.173.35 +ASLAN.OPEN-RSC.org. 604800 IN A 199.5.157.128 +NS2.DOMAIN-REGISTRY.nl. 604800 IN A 193.176.144.130 +uranus.lan-ks.de. 604800 IN A 194.45.71.1 +mail.unlisys.net. 604800 IN A 195.21.255.252 +NS.AUSTRIA.EU.net. 604800 IN A 192.92.138.35 +AUTH01.CONNECT.IE. 604800 IN A 194.106.128.50 +SUN.SCSI.GOV.BY. 604800 IN A 195.50.5.103 +NS1.SIGMAHOSTING.com. 604800 IN A 209.241.86.6 +NS.CAST.EDU.JM. 604800 IN A 200.9.115.2 +DS.NIC.NET.SG. 604800 IN A 202.42.194.205 +PRADES.CESCA.ES. 604800 IN A 192.94.163.152 +ns.sta.NET.CN. 604800 IN A 202.96.199.133 +NSE00.excite.com. 604800 IN A 198.3.102.250 +NS3.ABOVE.net. 604800 IN A 207.126.105.146 +CASBAH.ELDJAZAIR.NET.DZ. 604800 IN A 193.194.81.45 +ASKIA.SOTELMA.ML. 604800 IN A 208.144.230.3 +NS.IDT.net. 604800 IN A 198.4.75.100 +FXCLPR02.IS.CHRYSLER.com. 604800 IN A 204.189.94.37 +SVC00.APNIC.net. 604800 IN A 202.12.28.131 +NS5.DCX.YAHOO.com. 604800 IN A 216.32.74.10 +ns1.ray.net. 604800 IN A 195.238.228.131 +NS.NIC.MC. 604800 IN A 195.78.6.131 +ns.runway.CN.net. 604800 IN A 211.101.132.8 +benoni.uit.NO. 604800 IN A 129.242.4.254 +SCRATCHY.MINDSPRING.net. 604800 IN A 207.69.200.211 +ns1.pcode.com. 604800 IN A 216.15.192.135 +ns1.aha.RU. 604800 IN A 195.2.80.142 +ns2.uwaterloo.CA. 604800 IN A 129.97.128.100 +ns2.NIC.AD.JP. 604800 IN A 202.12.30.133 +a.ns.foxharp.boston.MA.us. 604800 IN A 24.147.209.205 +NS.NIC.IO. 604800 IN A 194.205.62.100 +A-GTLD-SERVERS.dot-god.com. 604800 IN A 205.189.73.123 +SMTP.slac.stanford.EDU. 604800 IN A 134.79.18.80 +52.87.198.209.IN-ADDR.ARPA. 604800 IN PTR mqueue0.sover.net. +BARNEY.ADVSYS.CO.UK. 604800 IN A 194.72.124.2 +NS1.TELEPAC.PT. 604800 IN A 194.65.3.20 +NICOSIA.CCS.UCY.AC.CY. 604800 IN A 194.42.6.97 +NS.PUNCHDOWN.org. 604800 IN A 140.174.131.100 +SYNAESTHESIA.COGNOSCENTI.org. 604800 IN A 207.208.112.4 +NS2.PLANET-THREE.net. 604800 IN A 212.49.219.190 +DNS.CIT.CORNELL.EDU. 604800 IN A 192.35.82.50 +MODOR.VERISIGN.net. 604800 IN A 205.139.94.55 +SUNSTROKE.IS.RPSLMC.EDU. 604800 IN A 144.74.21.8 +NS2.SEG.net. 604800 IN A 206.34.181.16 +NEMUNAS.SC-UNI.KTU.LT. 604800 IN A 193.219.32.13 +MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.1.22 +MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.37.150 +NS1.NPLUS.GF. 604800 IN A 195.6.144.3 +ns2.centralinfo.net. 604800 IN A 63.102.204.130 +K.GTLD-SERVERS.net. 604800 IN A 213.177.194.5 +ns1.codelocal.com. 604800 IN A 216.15.192.130 +NS2.IPNS.com. 604800 IN A 63.230.183.1 +NS0.DE.NIC.NU. 604800 IN A 216.200.116.40 +NS.USSR.EU.net. 604800 IN A 193.124.22.65 +NS.INTERNET.SK. 604800 IN A 192.108.130.91 +CORREOS.SEKER.ES. 604800 IN A 194.179.87.1 +mx1.buf.ADELPHIA.net. 604800 IN A 24.48.36.10 +aun.UNINETT.NO. 604800 IN A 129.241.1.99 +NS0.NETANET.com. 604800 IN A 195.172.127.72 +NS0.NETANET.com. 604800 IN A 194.6.96.218 +www.MANY-PATHS-ENERGY-ENHANCEMENT.com. 604800 IN A 66.33.4.50 +NS2.STARFIRE.DOUGLAS.MA.us. 604800 IN A 216.129.136.9 +NS3.IKP.PL. 604800 IN A 157.25.5.30 +pns.dtag.de. 604800 IN A 194.25.0.125 +NZ.NS.NIC.NU. 604800 IN A 203.97.132.66 +DAVER.bungi.com. 604800 IN A 207.126.97.2 +DAVER.bungi.com. 604800 IN A 206.14.228.2 +gutenberg.bucksnet.com. 604800 IN A 207.113.15.5 +DNS2.IT.net. 604800 IN A 151.1.2.1 +NS2.SNS-UT.DEBIS.com. 604800 IN A 53.122.2.10 +ISI.EDU. 604800 IN A 128.9.176.32 +amethyst.xaos.org. 604800 IN A 204.145.159.12 +PAPPILLOMA.WWEBSVS.com. 604800 IN A 209.233.37.10 +NS2.bock.com. 604800 IN A 64.30.29.4 +NS2.OAR.net. 604800 IN A 192.88.195.10 +MINION.NETPOLICY.com. 604800 IN A 207.87.121.66 +Mail.catic1.com. 604800 IN A 207.190.204.103 +NS4.DNS.space.net. 604800 IN A 195.222.210.93 +b.gtld-servers.ORSC. 604800 IN A 216.13.126.116 +bend.madriver.com. 604800 IN A 207.136.232.15 +NS4.IS-FUN.net. 604800 IN A 212.162.54.34 +NS2.JPS.net. 604800 IN A 216.224.156.252 +NS1.IP-PLUS.net. 604800 IN A 164.128.36.34 +rush.cc1.RPSLMC.EDU. 604800 IN A 144.74.150.23 +NS2.GBMTECH.net. 604800 IN A 208.243.164.3 +DNS.MSEN.com. 604800 IN A 148.59.19.11 +DNSSEC2.SINGNET.COM.SG. 604800 IN A 195.13.10.226 +NS2.HOME.net. 604800 IN A 24.2.0.27 +ACCESS.MBNET.MB.CA. 604800 IN A 130.179.16.143 +DNS0.SPIN.AD.JP. 604800 IN A 165.76.0.98 +Filer.PHOTOTRUST.com. 604800 IN A 64.85.86.172 +jpl.NASA.GOV. 604800 IN A 137.78.160.180 +NS2.TECHNOLOGIA.net. 604800 IN A 207.253.59.4 +bparker.CONNACTIVITY.com. 604800 IN A 206.34.200.200 +NS1.uvm.EDU. 604800 IN A 132.198.201.10 +NS.SENET.net. 604800 IN A 206.155.163.195 +DNS2.UTCC.UTORONTO.CA. 604800 IN A 128.100.102.201 +localhost.costorf.com. 604800 IN A 127.0.0.1 +DNS2.AD. 604800 IN A 194.158.64.8 +HYDRA.HELSINKI.FI. 604800 IN A 128.214.4.29 +NAME.PHX.GBLX.net. 604800 IN A 206.165.6.10 +NS2.FOOL.com. 604800 IN A 208.51.76.222 +NS01-SERVER.CURINFO.AN. 604800 IN A 200.44.117.129 +NS.CR. 604800 IN A 163.178.8.2 +mail.pshift.net. 604800 IN A 208.153.85.30 +NS.IRD.FR. 604800 IN A 195.83.14.1 +NS.UZ. 604800 IN A 213.68.88.11 +DNS.INTELCOM.SM. 604800 IN A 194.183.64.11 +DNS2.UNIV-NKC.MR. 604800 IN A 193.251.145.154 +HNS3.hns.com. 604800 IN A 208.236.67.3 +bay.cs.UTORONTO.CA. 604800 IN A 128.100.1.1 +NS0.BT.net. 604800 IN A 194.72.6.51 +BAYONET.SJMERCURY.com. 604800 IN A 207.1.134.34 +PAN.BIJT.net. 604800 IN A 213.196.2.97 +NAVI.SUBTEND.net. 604800 IN A 208.186.117.224 +NS.CIX.CX. 604800 IN A 195.222.235.216 +waldorf.Informatik.Uni-Dortmund.de. 604800 IN A 129.217.4.42 +NS2.ivillage.com. 604800 IN A 209.185.162.16 +DNS.NIC.XLINK.net. 604800 IN A 193.141.40.42 +NS1.MERCHANTWARE.CON. 604800 IN A 209.170.142.34 +NS.TO.GD-ES.com. 604800 IN A 199.107.240.66 +NS-A.RNC.RO. 604800 IN A 192.162.16.31 +REGGAE.NCREN.net. 604800 IN A 128.109.131.3 +SSS-NL.DENIC.de. 604800 IN A 193.0.0.237 +NS1.TDC.TO. 604800 IN A 206.86.247.250 +NS.NIC.HU. 604800 IN A 193.6.27.62 +JOANNA.WILLIAM.org. 604800 IN A 195.153.6.2 +NS0.IIJ.AD.JP. 604800 IN A 202.232.2.34 +maus.spack.org. 604800 IN A 204.245.198.90 +B.NS.VERIO.net. 604800 IN A 129.250.35.32 +SECDNS.EUNET.BE. 604800 IN A 193.74.208.139 +NS3.EUROPE.YAHOO.com. 604800 IN A 217.12.4.71 +A.ROOT-SERVERS.net. 604800 IN A 198.41.0.4 +sherickpm.com. 604800 IN MX 10 inbound.sherickpm.com.criticalpath.net. +NS2.MEDIASERVICES.net. 604800 IN A 64.65.16.237 +YARDBIRD.CNS.vt.EDU. 604800 IN A 198.82.247.34 +SUNIC.SUNET.SE. 604800 IN A 192.36.125.2 +NS.MT. 604800 IN A 193.188.47.252 +CNDVG001.usa.net. 604800 IN A 165.212.12.1 +NS1.CX.ESCROW.IOCOMM.NET.CX. 604800 IN A 203.132.96.2 +DNS-02.NS.AOL.com. 604800 IN A 205.188.157.232 +ns2.tesserae.com. 604800 IN A 209.157.194.3 +SV10.BATELCO.COM.BH. 604800 IN A 193.188.124.227 +dec.anr.state.vt.us. 604800 IN MX 0 dec.anr.state.vt.us. +dec.anr.state.vt.us. 604800 IN MX 10 mx1.state.vt.us. +dec.anr.state.vt.us. 604800 IN MX 10 mx2.state.vt.us. +3.133.188.192.IN-ADDR.ARPA. 604800 IN PTR elektro.com. +NS1.LONDON.UK.NETDNS.com. 604800 IN A 212.62.6.38 +NS.NIC.MG. 604800 IN A 194.214.107.253 +DNS1.VN. 604800 IN A 203.162.3.235 +DENS20.DEN.nps.GOV. 604800 IN A 165.83.24.20 +z.ip6.INT. 604800 IN A 198.32.2.66 +NS3.TRIVALLEY.com. 604800 IN A 206.25.132.30 +isis.imag.FR. 604800 IN A 129.88.32.24 +NS.SOVAM.com. 604800 IN A 194.67.2.97 +NS-SOA.DARENET.DK. 604800 IN A 130.226.1.4 +NS4.NIC.TV. 604800 IN A 207.151.24.23 +DNSSRV1X.mitre.org. 604800 IN A 199.94.97.51 +GATEKEEPER.NYTIMES.com. 604800 IN A 199.181.175.201 +D.I-DNS.net. 604800 IN A 211.169.245.170 +NS.KOLO.net. 604800 IN A 209.66.103.20 +NS4.FIRSTWORLD.net. 604800 IN A 216.7.160.162 +DECST.CERIST.DZ. 604800 IN A 193.194.64.11 +NS4.DNS.WS. 604800 IN A 216.52.234.102 +NS0.GDGSC.com. 604800 IN A 192.160.62.66 +UCTHPX.UCT.AC.ZA. 604800 IN A 137.158.128.1 +NS2.HOTWIRED.com. 604800 IN A 209.185.151.6 +ns02.ca.us.ibm.net. 604800 IN A 165.87.201.243 +NS2.SPEAKEASY.net. 604800 IN A 216.231.41.22 +TELCOM.ZPTC.CO.ZW. 604800 IN A 194.133.122.47 +NS.DK-HOSTMASTER.DK. 604800 IN A 193.163.102.2 +NS.NIC.LK. 604800 IN A 192.248.1.65 +NS2.zama.net. 604800 IN A 203.142.130.5 +CZ.EUNET.CZ. 604800 IN A 193.85.3.130 +NS.AC.ID. 604800 IN A 202.159.124.34 +NS1.CUBE.de. 604800 IN A 212.162.54.243 +NS1.QUASAR.net. 604800 IN A 199.166.31.3 +NS1.OFFSHORE.AI. 604800 IN A 209.88.68.34 +NS5.NRSITE.com. 604800 IN A 208.178.169.4 +NS.AIC.net. 604800 IN A 195.250.64.65 +OWL.NCC.nps.GOV. 604800 IN A 165.83.34.60 +MAXIM.gbch.net. 604800 IN A 203.9.155.249 +BOW.INTNET.TD. 604800 IN A 193.251.147.253 +ns1.cacheware.com. 604800 IN A 64.221.210.242 +NS2.SPEEDHOST.com. 604800 IN A 216.42.31.169 +NS1.COMMIT.GM. 604800 IN A 63.77.152.177 +NAME.ROC.GBLX.net. 604800 IN A 209.130.187.10 +90.198.245.204.IN-ADDR.ARPA. 604800 IN PTR maus.spack.org. +BOLOGNA.NETTUNO.IT. 604800 IN A 193.43.2.5 +NIC.IBD.com. 604800 IN A 209.249.61.18 +NS.WESTOL.com. 604800 IN A 63.93.137.4 +time.SOVER.net. 604800 IN CNAME garnet.SOVER.net. +UNIX1.CS.UMASS.EDU. 604800 IN A 128.119.40.12 +AARDVARK.WR.UMIST.AC.UK. 604800 IN A 130.88.146.3 +AARDVARK.WR.UMIST.AC.UK. 604800 IN A 128.16.5.31 +NS1.NIC.YU. 604800 IN A 147.91.8.6 +mail.velco.com. 604800 IN A 198.136.217.106 +DNSAUTH2.SYS.GTEI.net. 604800 IN A 4.2.49.3 +NS.TELE.FI. 604800 IN A 193.210.19.19 +state.vt.us. 604800 IN MX 10 mx1.state.vt.us. +state.vt.us. 604800 IN MX 10 mx2.state.vt.us. +NS.NYC.juno.com. 604800 IN A 205.231.108.1 +NS1.g-world.com. 604800 IN A 216.26.39.10 +AUTH2.AMERICA.net. 604800 IN A 209.17.197.18 +KIRA.ECS.UMASS.EDU. 604800 IN A 128.119.91.10 +CONACYT.GOB.SV. 604800 IN A 168.243.64.2 +DNS.SRCE.HR. 604800 IN A 161.53.3.7 +NS00.ns0.com. 604800 IN A 216.92.60.60 +NS2.CL.BELLSOUTH.net. 604800 IN A 205.152.16.8 +jenner.med.HARVARD.EDU. 604800 IN A 134.174.141.2 +p2.cavebear.com. 604800 IN A 199.184.128.35 +NS1.NIC.JE. 604800 IN A 216.110.45.224 +ORCU.OR.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.129.139 +NS.XBILL.org. 604800 IN A 204.152.186.163 +WRAITH.CS.UOW.EDU.AU. 604800 IN A 130.130.64.1 +12.159.145.204.IN-ADDR.ARPA. 604800 IN PTR amethyst.xaos.org. +ns1.pr.SUN.com. 604800 IN A 192.18.16.2 +NS.SPIN.OMNES.net. 604800 IN A 192.23.90.196 +smtp.188.net. 604800 IN A 202.96.125.104 +TERMINAL.2GLOBE.net. 604800 IN A 195.178.183.230 +NS2.HARVARD.EDU. 604800 IN A 128.103.1.1 +NAMESERVER.CNR.IT. 604800 IN A 194.119.192.34 +EARTH.SY. 604800 IN A 195.22.198.6 +DNS2.REACCIUN.VE. 604800 IN A 150.188.4.212 +NS.TMX.COM.NI. 604800 IN A 205.218.253.2 +freefour.acs.rpi.EDU. 604800 IN A 128.113.24.91 +242.84.198.209.IN-ADDR.ARPA. 604800 IN PTR dlawren-gw.burl.sover.net. +CORREU.STA.AD. 604800 IN A 194.158.67.1 +NS.DRUKNET.NET.BT. 604800 IN A 202.144.128.200 +NS4.US.PRSERV.net. 604800 IN A 165.87.201.244 +KAASASSUK.GH.GL. 604800 IN A 194.177.232.3 +ECUA.NET.EC. 604800 IN A 157.100.1.2 +NS.CONCYT.GOB.GT. 604800 IN A 168.234.106.2 +NS2.NAP.net. 604800 IN A 206.54.224.1 +DNS2.CN.net. 604800 IN A 202.97.18.61 +MX.NSI.NASA.GOV. 604800 IN A 128.102.18.31 +NS.TDS.net. 604800 IN A 204.246.1.20 +tdns-me1.NETSCAPE.com. 604800 IN A 205.188.247.67 +NS2.METU.EDU.TR. 604800 IN A 144.122.199.93 +NS2.SETARNET.AW. 604800 IN A 206.48.100.11 +87.184.152.204.IN-ADDR.ARPA. 604800 IN PTR isrv3-i.isc.org. +DNS.OMNIWAY.SM. 604800 IN A 194.183.64.10 +NS0.U-NET.net. 604800 IN A 194.119.128.65 +elektro.CMHNET.org. 604800 IN A 192.188.133.3 +ns2.HIGGS.net. 604800 IN A 204.80.125.145 +NS2.SKYNETWEB.com. 604800 IN A 208.231.1.35 +MAGIC.MN. 604800 IN A 202.131.0.10 +NS1.YAHOO.com. 604800 IN A 204.71.200.33 +mx1.cdp.ADELPHIA.net. 604800 IN A 24.48.58.221 +SANTO.VANUATU.COM.VU. 604800 IN A 202.139.40.7 +www.mmuuf.org. 604800 IN MX 10 gro.dd.org. +ns1.timeheart.net. 604800 IN A 63.197.231.203 +NS2.TOGETHER.net. 604800 IN A 204.97.120.31 +NS.AMNIC.net. 604800 IN A 195.250.64.90 +NS.EENET.EE. 604800 IN A 193.40.56.245 +www.ONLINEPHOTOCONTEST.com. 604800 IN A 64.85.86.152 +VIC20.BLIPP.com. 604800 IN A 195.163.165.35 +DNS.FROGHOUSE.org. 604800 IN A 207.121.69.243 +NS2.ELI.net. 604800 IN A 207.173.86.2 +NS.CAIS.com. 604800 IN A 205.177.10.10 +BAABEN.AFRIQ.net. 604800 IN A 165.231.1.3 +NS2.NJ.EXODUS.net. 604800 IN A 209.1.10.234 +DOMREG.NIC.CH. 604800 IN A 130.59.1.80 +NS.EU.net. 604800 IN A 192.16.202.11 +NS1.DIEBOLD.net. 604800 IN A 65.196.80.10 +NS3.CP.net. 604800 IN A 209.228.14.4 +DNS.FUW.EDU.PL. 604800 IN A 193.0.80.11 +www.retro.com. 604800 IN A 205.179.181.195 +NS2.UNI2.net. 604800 IN A 195.82.195.99 +ns1.alcatrazmedia.com. 604800 IN A 167.160.132.2 +dns6.CP.MSFT.net. 604800 IN A 207.46.138.20 +NS1.SEYCHELLES.net. 604800 IN A 202.84.235.33 +NS2.INTERNIC.net. 604800 IN A 198.41.0.11 +front.macrosoft.WAW.PL. 604800 IN A 194.196.86.66 +NISC.JVNC.net. 604800 IN A 128.121.50.7 +AUTH03.NS.DE.UU.net. 604800 IN A 192.76.144.16 +BURDELL.CC.GATECH.EDU. 604800 IN A 130.207.3.207 +NS4.AH.net. 604800 IN A 203.21.205.20 +ns1.sgh-net.de. 604800 IN A 212.86.129.142 +Leland2.stanford.EDU. 604800 IN A 171.64.14.58 +CBRU.BR.NS.ELS-GMS.att.net. 604800 IN A 199.191.128.105 +DENEB.DOMAINNT.net. 604800 IN A 207.211.220.90 +ns1.ivm.net. 604800 IN A 62.204.1.1 +NS0.CWCI.net. 604800 IN A 194.6.79.162 +35.110.16.12.IN-ADDR.ARPA. 604800 IN CNAME 35.32/27.110.16.12.IN-ADDR.ARPA. +f.trns. 604800 IN A 209.133.38.16 +ODISEJ.TELEKOM.YU. 604800 IN A 195.178.32.2 +FRCU.EUN.EG. 604800 IN A 193.227.1.1 +NS.HHS.net. 604800 IN A 63.93.136.29 +FOO.GRNET.GR. 604800 IN A 194.177.210.211 +mail.WonderWorks.com. 604800 IN A 192.203.206.67 +NS1.IAFRICA.com. 604800 IN A 196.7.0.139 +NS.KACST.EDU.SA. 604800 IN A 212.26.44.3 +srs.state.vt.us. 604800 IN A 159.105.101.150 +OM4.OMANTEL.NET.OM. 604800 IN A 206.49.101.5 +Yeshua.Christ.com. 604800 IN A 207.54.4.5 +NS1.SIMORGH.com. 604800 IN A 209.1.163.10 +OLKETA.SOLOMON.COM.SB. 604800 IN A 202.139.42.4 +BANBA.DOMAINREGISTRY.IE. 604800 IN A 193.1.142.2 +NOC.IOS.com. 604800 IN A 198.4.75.69 +ns.schnism.net. 604800 IN A 195.88.150.3 +e4.ny.us.IBM.com. 604800 IN A 32.97.182.104 +DNS2.SEANET.com. 604800 IN A 199.181.164.2 +doubt.dd.org. 604800 IN A 209.198.103.193 +AMBER.ELEKTRON.PL. 604800 IN A 195.117.6.10 +gw.rge.com. 604800 IN A 157.225.178.11 +NS2.ZTNET.com. 604800 IN A 63.211.17.252 +NS3.INFI.net. 604800 IN A 205.219.239.5 +ZA.AKADNS.net. 604800 IN A 209.185.188.39 +ESTIA.CSI.FORTH.GR. 604800 IN A 139.91.191.3 +vtagr04.agr.state.vt.us. 604800 IN A 159.105.50.4 +NS1-PUBLIC.ZTX.COMPAQ.com. 604800 IN A 161.114.1.204 +ADMII.ARL.MIL. 604800 IN A 128.63.31.4 +ADMII.ARL.MIL. 604800 IN A 128.63.5.4 +NS.NIXU.FI. 604800 IN A 193.209.237.29 +DNS2.PIONEERNET.net. 604800 IN A 208.240.196.10 +NS.NIC.CL. 604800 IN A 146.83.4.11 +NS2.UTZ. 604800 IN A 160.124.112.10 +NS4.LUXNOC.com. 604800 IN A 195.206.104.201 +NS2.PBI.net. 604800 IN A 206.13.29.11 +annwfn.erfurt.thur.de. 604800 IN A 194.122.210.3 +NS1.MW.mediaone.net. 604800 IN A 24.131.1.8 +NS1.ISU.NET.SA. 604800 IN A 212.26.18.3 +pop.SHOREHAM.net. 604800 IN CNAME SHOREHAM.net. +DNS2.GUERNSEY.net. 604800 IN A 195.226.128.3 +NS1.BEACHSHORE.net. 604800 IN A 199.166.31.250 +HKUXB.HKU.HK. 604800 IN A 147.8.16.15 +NS.DOLEH.com. 604800 IN A 204.255.25.63 +NS.hactrn.net. 604800 IN A 216.254.68.12 +MALAKULA.BONDY.IRD.FR. 604800 IN A 193.50.53.1 +NS1.mediaone.net. 604800 IN A 24.128.1.80 +NS2.GPG.com. 604800 IN A 209.1.163.50 +noc.BelWue.de. 604800 IN A 129.143.2.1 +NS2.GIP.net. 604800 IN A 204.59.1.222 +RS.ISLES.net. 604800 IN A 212.100.224.90 +BOW.INTNET.GQ. 604800 IN A 195.101.152.253 +A.OPEN.BY. 604800 IN A 194.226.121.36 +us.i1.YIMG.com. 604800 IN CNAME a1.g.a.YIMG.com. +athome.wetlogic.net. 604800 IN CNAME c1059495-a.snvl1.sfba.home.com. +NS1.NIST.GOV. 604800 IN A 129.6.13.2 +mail.jerusalem-mail.com. 604800 IN A 216.251.232.93 +ISDSUN.cr.USGS.GOV. 604800 IN A 136.177.16.3 +NS.BOSTON.juno.com. 604800 IN A 64.136.25.53 +NS2.CADABRA.com. 604800 IN A 209.157.194.109 +nps.GOV. 604800 IN MX 10 ccmail2.itd.nps.GOV. +nps.GOV. 604800 IN MX 5 ccmail.itd.nps.GOV. +RELAY.HUJI.AC.IL. 604800 IN A 128.139.6.1 +styx.tahina.priv.at. 604800 IN A 194.152.163.253 +ISGATE.IS. 604800 IN A 193.4.58.51 +ns0.lux.dot-eu.org. 604800 IN A 195.206.105.102 +BILBO.NASK.ORG.PL. 604800 IN A 195.187.245.51 +BILBO.NASK.ORG.PL. 604800 IN A 148.81.16.51 +MAIL.TARSUS.com. 604800 IN A 208.130.9.252 +SUN.REDIRIS.ES. 604800 IN A 130.206.1.2 +NS2.NEASE.net. 604800 IN A 202.103.134.4 +OHCU.OH.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.144.75 +NS2.NF. 604800 IN A 203.12.249.101 +MIRAF-SERVER3.HONDUTEL.HN. 604800 IN A 206.48.104.142 +ns3.worldnet.att.net. 604800 IN A 204.127.160.1 +NS2.NETNAMES.net. 604800 IN A 212.53.77.28 +ITGBOX.IAT.CNR.IT. 604800 IN A 146.48.65.46 +NS2.ADELPHIA.net. 604800 IN A 24.48.62.35 +NS2.RIPN.net. 604800 IN A 195.209.0.6 +NS1.cinenet.net. 604800 IN A 198.147.76.65 +jengate.thur.de. 604800 IN A 193.174.15.34 +NOC.ULCC.JA.net. 604800 IN A 193.63.94.25 +NS.NOC.UZ. 604800 IN A 194.67.52.42 +NS0.JA.net. 604800 IN A 128.86.1.20 +NS0.JA.net. 604800 IN A 193.63.94.20 +NS2.INR.net. 604800 IN A 198.77.208.3 +netsage.org. 604800 IN A 209.67.235.38 +TERI.USP.AC.FJ. 604800 IN A 144.120.8.1 +NS2.NETSOL.com. 604800 IN A 198.17.208.71 +NS2.ABAC.com. 604800 IN A 216.55.144.4 +NS2.NIC.FR. 604800 IN A 192.93.0.4 +KANIN.ARNES.SI. 604800 IN A 193.2.1.66 +NS.EDU.GU. 604800 IN A 168.123.2.50 +DNS.INRIA.FR. 604800 IN A 193.51.208.13 +HEDNS1.GOOGLE.com. 604800 IN A 64.209.200.10 +asylum.sf.ca.us. 604800 IN A 192.48.232.17 +ACT2.ACT2000.net. 604800 IN A 207.42.132.227 +ICM1.ICP.net. 604800 IN A 192.94.207.66 +202.192.103.198.209.IN-ADDR.ARPA. 604800 IN PTR fraud.dd.org. +ECSEL.jhuapl.EDU. 604800 IN A 128.244.65.29 +NS2.DCNY.DOUBLECLICK.net. 604800 IN A 204.253.104.10 +keith.netsage.org. 604800 IN A 209.67.235.37 +MANTA.OUTREMER.com. 604800 IN A 213.16.1.106 +NS2.globalnetisp.net. 604800 IN A 207.136.213.2 +NS2.CCSRS.net. 604800 IN A 206.253.214.73 +NS1.NL.CONCENTRIC.com. 604800 IN A 195.18.114.5 +NS2.VI.net. 604800 IN A 212.78.64.10 +NS2.NEO.net. 604800 IN A 206.109.7.65 +cgi.MERCURYCENTER.com. 604800 IN CNAME vh80167.vh8.infi.net. +ORSTOM.RIO.net. 604800 IN A 192.33.151.1 +NS2.CONRADPROMOTIONS.com. 604800 IN A 208.24.118.203 +YARRINA.CONNECT.COM.AU. 604800 IN A 192.189.54.17 +dns03.OPS.usa.net. 604800 IN A 204.68.24.136 +APPSRV.HAITIWORLD.com. 604800 IN A 206.152.15.34 +NS.RELCOM.KZ. 604800 IN A 212.110.240.65 +NS1.MAGIC-MOMENTS.com. 604800 IN A 195.224.53.80 +NS.ALCATEL.com. 604800 IN A 192.160.6.91 +ns2.terra.net. 604800 IN A 199.103.128.2 +NS3.hotmail.com. 604800 IN A 209.185.130.68 +vtc.VSC.EDU. 604800 IN MX 0 eve.vtc.VSC.EDU. +www.vmba.org. 604800 IN MX 10 gro.dd.org. +NAHOURI.ONATEL.BF. 604800 IN A 206.82.130.195 +SERVER2.INFN.IT. 604800 IN A 131.154.1.3 +NS2.AI-R.com. 604800 IN A 66.33.4.51 +NS1.FREE.net. 604800 IN A 147.45.15.34 +vcmr-54.server.rpi.EDU. 604800 IN A 128.113.113.44 +haig.CS.UCL.AC.UK. 604800 IN A 128.16.6.8 +mail.nova-data.com. 604800 IN A 12.16.110.35 +MOEVAX.EDU.TW. 604800 IN A 140.111.1.2 +NS2.LTWCC.org. 604800 IN A 12.33.66.62 +NS.BA. 604800 IN A 195.130.35.5 +noc.HRZ.uni-bielefeld.de. 604800 IN A 129.70.5.16 +VANILLA.WRO.nps.GOV. 604800 IN A 165.83.71.3 +NS2.SZTAKI.HU. 604800 IN A 193.225.86.1 +SECIU.EDU.UY. 604800 IN A 164.73.128.5 +COL2.CARIBSURF.com. 604800 IN A 205.214.192.202 +NS2.QATAR.NET.QA. 604800 IN A 212.77.192.13 +NS2.E-SYNC.net. 604800 IN A 192.206.57.128 +ns1.eu.SUN.com. 604800 IN A 192.18.240.8 +NS1.UUSJ.DOUBLECLICK.net. 604800 IN A 204.176.177.10 +NS2.CUHK.EDU.HK. 604800 IN A 137.189.6.21 +NS1.MEITCA.com. 604800 IN A 137.203.5.1 +NS2.DSL.net. 604800 IN A 209.87.79.232 +techfac.techfak.uni-bielefeld.de. 604800 IN A 129.70.132.100 +listserv.performancediver.com. 604800 IN A 216.34.185.155 +foolusmf.D4P.net. 604800 IN CNAME a100.g.akamai.net. +pedic-med.vrx.net. 604800 IN A 199.166.24.2 +GRUMPY.NET.NA. 604800 IN A 196.20.23.1 +BK.tifosi.com. 604800 IN A 208.58.189.13 +ns3.PAIR.com. 604800 IN A 209.68.1.15 +ns2.ar.com. 604800 IN A 64.124.80.42 +MASSIRA.ONPT.NET.MA. 604800 IN A 206.103.26.1 +NS.KBFI.EE. 604800 IN A 192.121.251.13 +ns3.Algebra.com. 604800 IN A 216.254.54.22 +faerber.muc.de. 604800 IN MX 10 slarti.muc.de. +9.206.203.192.IN-ADDR.ARPA. 604800 IN PTR ice.WonderWorks.COM. +PUKU.UNZA.ZM. 604800 IN A 196.7.240.1 +ATLNET.ATLONLINE.com. 604800 IN A 207.153.72.193 +Z1.NS.NYC1.GLOBIX.net. 604800 IN A 209.10.66.55 +www.hometownbands.com. 604800 IN A 209.67.235.38 +SIMON.CS.CORNELL.EDU. 604800 IN A 128.84.154.10 +EKEKO.RCPIP.net. 604800 IN A 209.45.127.2 +emerald.itnet.com.PL. 604800 IN A 195.116.64.3 +DNS1.ICS.FORTH.GR. 604800 IN A 139.91.151.70 +NS.ATL.BELLSOUTH.net. 604800 IN A 205.152.0.20 +ntp.ctr.COLUMBIA.EDU. 604800 IN CNAME sirius.ctr.COLUMBIA.EDU. +NS2.GLOBECOMM.net. 604800 IN A 165.251.1.3 +UUNS1DNS1.FLONETWORK.com. 604800 IN A 209.167.79.5 +GRIN.GNOSH.net. 604800 IN A 216.15.87.207 +NS.DIGSYS.BG. 604800 IN A 192.92.129.1 +uunet.UU.net. 604800 IN MX 10 Mail.UU.net. +ns1.vermontel.com. 604800 IN A 204.164.106.2 +NS2.GREENMOUNTAINACCESS.net. 604800 IN A 208.144.252.31 +38.241.5.198.IN-ADDR.ARPA. 604800 IN PTR cmr0.ash.ops.us.uu.net. +NS1.NIC.UK. 604800 IN A 195.66.240.130 +DNS.FCCN.PT. 604800 IN A 193.136.192.10 +NS2.NIC.TJ. 604800 IN A 209.77.224.1 +NS4.NEWACCOUNT.com. 604800 IN A 209.78.16.6 +NS2.IHUG.NET.NZ. 604800 IN A 203.29.160.2 +NS.SIGNALZ.com. 604800 IN A 209.67.230.71 +DNS.NIC.AD. 604800 IN A 194.158.67.251 +3.2.39.137.IN-ADDR.ARPA. 604800 IN PTR New-York4.NY.ALTER.NET. +UUCP-GW-2.PA.DEC.com. 604800 IN A 16.1.0.19 +NS.LANDLORDS.com. 604800 IN A 63.64.164.68 +NS2.EXODUS.net. 604800 IN A 207.82.198.150 +NS2.SCRUZ.net. 604800 IN A 165.227.2.10 +NS.PIPEX-SZ.net. 604800 IN A 196.15.232.19 +saturn.SUN.com. 604800 IN A 192.9.25.2 +e24.nc.us.IBM.com. 604800 IN A 32.97.136.230 +NMS.CYFRONET.KRAKOW.PL. 604800 IN A 149.156.1.3 +NS.TWNIC.net. 604800 IN A 192.83.166.11 +ns2.alcatel.NO. 604800 IN A 193.213.238.2 +INPAKSODNS.AKSO.nps.GOV. 604800 IN A 165.83.49.9 +mail.reptiles.org. 604800 IN A 198.96.117.157 +59.187.152.204.IN-ADDR.ARPA. 604800 IN PTR shell.nominum.com. +ns1.mobydark.com. 604800 IN A 216.13.76.21 +NS.KG. 604800 IN A 195.38.160.36 +NS.SPB.SU. 604800 IN A 193.124.83.69 +PENDRAGON.CS.PURDUE.EDU. 604800 IN A 128.10.2.5 +NS1.IGC.APC.org. 604800 IN A 192.82.108.38 +USDNS.NIC.us. 604800 IN A 198.41.3.87 +NS2.WEBTRENDS.com. 604800 IN A 63.88.212.11 +URANUS.DAIMI.AAU.DK. 604800 IN A 130.225.16.40 +ANTANA.IRD.MG. 604800 IN A 194.214.107.1 +NS.JERSEY.juno.com. 604800 IN A 64.136.17.178 +NS2.INTERNET-TOOLS.com. 604800 IN A 206.109.113.140 +ns-tk012.ocn.AD.JP. 604800 IN A 203.139.160.74 +bvt-ext.gdarm.com. 604800 IN A 166.19.32.42 +NS1.ID. 604800 IN A 202.155.30.227 +NS2.MAHNET.net. 604800 IN A 207.219.173.132 +NS.ALCANET.COM.AU. 604800 IN A 203.62.196.10 +UTAMA.BOLNET.BO. 604800 IN A 166.114.1.40 +NS.CNC.AC.CN. 604800 IN A 159.226.1.1 +NS.KREN.NE.KR. 604800 IN A 147.47.1.1 +NS1.REDHAT.com. 604800 IN A 216.148.218.250 +db.rc.VIX.com. 604800 IN A 204.152.187.21 +198.103.198.209.IN-ADDR.ARPA. 604800 IN CNAME 198.192.103.198.209.IN-ADDR.ARPA. +alf.pbks.PL. 604800 IN A 195.205.33.200 +FLAG.EP.net. 604800 IN A 198.32.4.13 +DNS2.IUNET.IT. 604800 IN A 192.106.1.31 +NS2.QUANTIFIED.net. 604800 IN A 63.212.171.3 +INTERNET-SERVER.ZURICH.IBM.com. 604800 IN A 195.212.119.252 +seaipsvcs.idx.com. 604800 IN A 172.22.64.42 +lebanon.valley.net. 604800 IN A 198.115.160.16 +SERVER.NORDU.net. 604800 IN A 193.10.252.19 +NS.NIC.DO. 604800 IN A 207.176.16.50 +isc-01.iscvt.org. 604800 IN A 207.136.209.131 +NAC.NO. 604800 IN A 129.240.2.40 +SAVA.UTIC.NET.BA. 604800 IN A 195.130.35.3 +NS1.TOKYO.JP.NETDNS.com. 604800 IN A 64.56.164.118 +NETSERV2.ITS.rpi.EDU. 604800 IN A 128.113.1.3 +IFI.UIO.NO. 604800 IN A 129.240.64.2 +www.TOAPLAN.com. 604800 IN A 216.42.31.169 +ns2.the-frontier.org. 604800 IN A 216.86.199.115 +NS.UNAM.MX. 604800 IN A 132.248.253.1 +ARISTO.TAU.AC.IL. 604800 IN A 132.66.32.10 +DNS.CS.WISC.EDU. 604800 IN A 128.105.2.10 +NS1.NIC.IR. 604800 IN A 194.225.70.83 +NS1.RETINA.AR. 604800 IN A 200.10.202.3 +mailer.connriver.net. 604800 IN A 63.93.137.13 +NS.ATI.TN. 604800 IN A 193.95.66.10 +NS2.CLEAR.NET.NZ. 604800 IN A 203.97.37.14 +NS4.EARTHLINK.net. 604800 IN A 209.179.179.19 +mejac.palo-alto.ca.us. 604800 IN A 192.147.236.1 +New-York4.NY.ALTER.net. 604800 IN A 137.39.2.3 +New-York4.NY.ALTER.net. 604800 IN A 137.39.126.10 +falcon.tallship.net. 604800 IN A 208.179.112.2 +ZEUS.CC.UCY.AC.CY. 604800 IN A 194.42.1.1 +NS2.SECURE.net. 604800 IN A 161.58.9.10 +NS0.FLIRBLE.org. 604800 IN A 195.40.6.20 +dns.zenon.net. 604800 IN A 195.2.83.107 +SERVIDOR.MICROASTUR.ES. 604800 IN A 195.76.178.5 +DOWNSTAGE.MCS.VUW.AC.NZ. 604800 IN A 130.195.6.10 +ns2.GNAC.com. 604800 IN A 209.182.195.77 +PRIFI.EUNET.FI. 604800 IN A 193.66.1.146 +ns2.k12.vt.us. 604800 IN A 170.222.64.130 +ns2.nic.mnet. 604800 IN A 208.109.83.110 +NS0.PIPEX.net. 604800 IN A 158.43.128.8 +NS1.SANFRANCISCO.US.NETDNS.com. 604800 IN A 207.82.50.166 +AMRA.NIC.GOV.JO. 604800 IN A 193.188.66.103 +kw.com.CN. 604800 IN MX 15 mail2.kw.com.CN. +SHNS.163.net. 604800 IN A 61.129.65.108 +NS.ER.USGS.GOV. 604800 IN A 130.11.48.2 +FAITH.MYNET.net. 604800 IN A 207.13.11.2 +mail.smuggs.com. 604800 IN A 209.67.230.71 +MIMOS.MY. 604800 IN A 192.228.128.18 +NS.GU. 604800 IN A 168.123.4.10 +mx00.schlund.de. 604800 IN A 195.20.224.67 +mx00.schlund.de. 604800 IN A 195.20.224.68 +mx00.schlund.de. 604800 IN A 195.20.224.130 +mx00.schlund.de. 604800 IN A 195.20.224.152 +mx00.schlund.de. 604800 IN A 195.20.224.198 +CADDSYS.IPTEK.net. 604800 IN A 202.46.1.2 +NS0.TELIA.NIC.NU. 604800 IN A 212.181.91.4 +NS2.GRANITECANYON.com. 604800 IN A 204.1.217.148 +GATEKEEPER.corning.com. 604800 IN A 149.42.1.2 +NS2.2DAY.com. 604800 IN A 202.89.128.74 +1.0.0.127.IN-ADDR.ARPA. 604800 IN PTR localhost. +RAIN.PSG.com. 604800 IN A 147.28.0.34 +STRAWB.MIT.EDU. 604800 IN A 18.71.0.151 +NS2.DIGISERVE.com. 604800 IN A 204.91.84.216 +UMACSN2.UMAC.MO. 604800 IN A 161.64.3.2 +NS.JM. 604800 IN A 196.2.1.6 +12.153.66.206.IN-ADDR.ARPA. 604800 IN PTR d.dd.org. +EAST.ISI.EDU. 604800 IN A 38.245.76.2 +NS2.UUNET.CA. 604800 IN A 142.77.1.5 +SUNNY.STAT-USA.GOV. 604800 IN A 192.239.70.8 +BOW.INTNET.CF. 604800 IN A 194.206.73.253 +NS4.TELE.DK. 604800 IN A 194.239.134.84 +NS2.sodak.net. 604800 IN A 63.65.239.225 +NS1.NEWYORK.US.NETDNS.com. 604800 IN A 216.32.212.86 +NS2.PSI.net. 604800 IN A 38.8.50.2 +NS.KREONET.RE.KR. 604800 IN A 134.75.30.1 +GIANT.MINDLINK.net. 604800 IN A 204.174.18.2 +NS0.SECTOR001.org. 604800 IN A 24.4.49.117 +DNS.SEABONE.net. 604800 IN A 195.22.205.163 +NS2.MANA.PF. 604800 IN A 202.3.225.20 +NRWEB.CENPAC.NET.NR. 604800 IN A 203.98.224.66 +www.TRAVELPHOTOCONTESTS.com. 604800 IN A 64.85.86.156 +NS1.REGEX.com. 604800 IN A 202.152.12.227 +BIGBIRD.ITD.nps.GOV. 604800 IN A 165.83.208.5 +CUNIXD.CC.COLUMBIA.EDU. 604800 IN A 128.59.35.142 +NS1.CLASSIFIEDMONSTER.com. 604800 IN A 216.254.54.22 +SERVER1.SANS.org. 604800 IN A 167.216.133.33 +BRONZE.COIL.com. 604800 IN A 198.4.94.1 +SCSNMS.SWITCH.CH. 604800 IN A 130.59.1.30 +SCSNMS.SWITCH.CH. 604800 IN A 130.59.10.30 +SCE.CNC.UNA.PY. 604800 IN A 200.10.228.133 +RELAY.LA.TIS.com. 604800 IN A 198.51.22.11 +NS.AUSTIN.IBM.com. 604800 IN A 192.35.232.34 +SERVICE.robert-morris.EDU. 604800 IN A 205.146.48.22 +MERCURY.ML.org. 604800 IN A 209.68.0.85 +proxy.pccf.net. 604800 IN A 205.189.73.123 +DUB-NAME-SVC-1.compuserve.com. 604800 IN A 149.174.213.5 +NS.CNRI.reston.va.us. 604800 IN A 132.151.1.1 +NS.UCAD.SN. 604800 IN A 196.1.95.1 +ns01.ny.us.ibm.net. 604800 IN A 165.87.194.244 +NS4-AUTH.ALASKA.net. 604800 IN A 209.112.130.4 +BOW.INTNET.NE. 604800 IN A 194.51.164.253 +NS-JP.SINET.AD.JP. 604800 IN A 150.100.2.3 +ns.musin.de. 604800 IN A 194.113.40.45 +ip1.romkey.SEG.net. 604800 IN A 207.121.69.234 +DNS2.ITD.UMICH.EDU. 604800 IN A 141.211.125.15 +mail.rpi.EDU. 604800 IN A 128.113.100.7 +INECO.NIC.ES. 604800 IN A 194.69.254.2 +DNS2.FIREHOUSE.net. 604800 IN A 63.160.175.18 +BOW.INTNET.BJ. 604800 IN A 194.51.163.253 +sundown.vtc.VSC.EDU. 604800 IN A 155.42.12.12 +NIC.AIX.GR. 604800 IN A 195.130.89.210 +NIC.AD.JP. 604800 IN A 202.12.30.33 +NS.DC.IGC.org. 604800 IN A 199.75.208.10 +LHR.NS.GDNS.net. 604800 IN A 212.250.25.101 +NS2.WEBMAGIC.net. 604800 IN A 64.168.49.66 +MUNNARI.OZ.AU. 604800 IN A 128.250.1.21 +HIPPO.RU.AC.ZA. 604800 IN A 146.231.128.1 +PEBBLES.IOM.com. 604800 IN A 194.72.124.1 +penpal.dmz.RPSLMC.EDU. 604800 IN A 144.74.60.151 +netnews.HINET.net. 604800 IN A 168.95.195.16 +INS2.TOSA.TWTELECOM.net. 604800 IN A 204.95.160.4 +proxy6.cisco.com. 604800 IN A 203.41.198.245 +NS2.HOST4U.net. 604800 IN A 209.150.129.3 +POIPARAU.OYSTER.NET.CK. 604800 IN A 202.65.32.127 +NS-EXT.VIX.com. 604800 IN A 204.152.184.64 +NS2.NURSAT.net. 604800 IN A 212.13.167.1 +mail2.kw.com.CN. 604800 IN A 159.226.25.8 +NS-02B.ANS.net. 604800 IN A 207.24.245.178 +DNS.RCCN.net. 604800 IN A 193.136.7.17 +B.ROOT-SERVERS.ORSC. 604800 IN A 216.13.126.116 +FIREHOUSE.net. 604800 IN A 63.160.175.19 diff --git a/bin/tests/system/cacheclean/ns1/example.db b/bin/tests/system/cacheclean/ns1/example.db new file mode 100644 index 0000000..7262109 --- /dev/null +++ b/bin/tests/system/cacheclean/ns1/example.db @@ -0,0 +1,2942 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +$ORIGIN . +. IN SOA hostmaster.nominum.com. a.root-servers.nil. ( + 2000042100 + 600 + 600 + 1200 + 600 + ) +. NS a.root-servers.nil. +a.root-servers.nil IN A 10.53.0.1 +localhost IN A 127.0.0.1 +$ORIGIN NIC.AC. +NS IN A 194.205.62.120 +$ORIGIN AD. +DNS2 IN A 194.158.64.8 +DINIS IN A 194.158.64.7 +$ORIGIN NIC.AD. +DNS IN A 194.158.67.251 +$ORIGIN STA.AD. +CORREU IN A 194.158.67.1 +$ORIGIN EMIRATES.NET.AE. +NS2 IN A 194.170.1.7 +NS1 IN A 194.170.1.6 +$ORIGIN BA. +NS IN A 195.130.35.5 +$ORIGIN UTIC.NET.BA. +SAVA IN A 195.130.35.3 +$ORIGIN OFFSHORE.AI. +NS1 IN A 209.88.68.34 +$ORIGIN BD. +DNS1 IN A 209.58.24.5 +DNS IN A 209.58.24.3 +$ORIGIN MENTOR.BE. +APHEX IN A 193.121.64.5 +$ORIGIN EUNET.BE. +SECDNS IN A 193.74.208.139 +$ORIGIN BELNET.BE. +NS IN A 193.190.198.10 + IN A 193.190.198.2 +$ORIGIN DNS.BE. +MASTER IN A 194.7.171.243 +$ORIGIN CS.KULEUVEN.AC.BE. +DNS IN A 134.58.40.4 +$ORIGIN CURINFO.AN. +NS01-SERVER IN A 200.44.117.129 +KADUSHI IN A 200.44.117.130 +$ORIGIN ONATEL.BF. +NAHOURI IN A 206.82.130.195 +$ORIGIN DIGSYS.BG. +NS IN A 192.92.129.1 +$ORIGIN BATELCO.COM.BH. +SV10 IN A 193.188.124.227 +NS2 IN A 193.188.97.212 +NS IN A 193.188.97.197 +$ORIGIN UTORONTO.CA. +ns2 IN A 128.100.102.202 +ns1 IN A 128.100.100.129 +chime IN A 128.100.102.201 +$ORIGIN cs.UTORONTO.CA. +bay IN A 128.100.1.1 +$ORIGIN UTCC.UTORONTO.CA. +DNS2 IN A 128.100.102.201 +$ORIGIN UUNET.CA. +NS2 IN A 142.77.1.5 +NS IN A 142.77.1.1 +$ORIGIN CIRA.CA. +MERLE IN A 64.26.149.98 +$ORIGIN cmc.ec.gc.CA. +castor IN A 142.135.4.14 +$ORIGIN RISQ.QC.CA. +CLOUSO IN A 192.26.210.1 +$ORIGIN MBNET.MB.CA. +ACCESS IN A 130.179.16.143 +$ORIGIN CDNNET.CA. +RELAY IN A 192.73.5.1 +$ORIGIN uwaterloo.CA. +ns2 IN A 129.97.128.100 +math IN A 129.97.140.144 + IN A 129.97.216.42 + IN MX 0 math.uwaterloo.ca. +ns1 IN A 129.97.128.10 +$ORIGIN AR. +CTINA IN A 200.16.97.17 +ATHEA IN A 200.16.98.2 +$ORIGIN NIC.AR. +TULKU IN A 200.16.97.77 +$ORIGIN RETINA.AR. +NS1 IN A 200.10.202.3 +$ORIGIN INTNET.BJ. +BOW IN A 194.51.163.253 +$ORIGIN NIC.CD. +DNS IN A 194.38.74.11 +$ORIGIN tahina.priv.at. +styx IN A 194.152.163.253 +$ORIGIN UNIVIE.AC.at. +NS2 IN A 193.171.255.66 +NS7 IN A 194.246.96.192 +NS1 IN A 193.171.255.2 +$ORIGIN OZ.AU. +MUNNARI IN A 128.250.1.21 +$ORIGIN CS.MU.OZ.AU. +MULGA IN A 128.250.1.22 + IN A 128.250.37.150 +$ORIGIN AARNET.EDU.AU. +JATZ IN A 139.130.204.4 +$ORIGIN ANU.EDU.AU. +CHEOPS IN A 150.203.224.24 +$ORIGIN CS.UOW.EDU.AU. +WRAITH IN A 130.130.64.1 +$ORIGIN ALCANET.COM.AU. +NS IN A 203.62.196.10 +$ORIGIN CONNECT.COM.AU. +YARRINA IN A 192.189.54.17 +$ORIGIN IBL.BM. +NS1 IN A 199.172.192.1 +$ORIGIN BRUNET.BN. +JTB IN A 202.160.8.2 +$ORIGIN INTNET.CF. +BOW IN A 194.206.73.253 +$ORIGIN SETARNET.AW. +NS2 IN A 206.48.100.11 +NS1 IN A 206.48.100.5 +$ORIGIN BOLNET.BO. +UTAMA IN A 166.114.1.40 +$ORIGIN SWITCH.CH. +SCSNMS IN A 130.59.1.30 + IN A 130.59.10.30 +MERAPI IN A 130.59.211.10 +$ORIGIN ITU.CH. +NS IN A 156.106.192.121 +$ORIGIN NIC.CH. +DOMREG IN A 130.59.1.80 +$ORIGIN ip6.INT. +z IN A 198.32.2.66 + IN AAAA 3ffe:0:1::c60:242 +$ORIGIN DNS.BR. +NS2 IN A 200.19.119.99 +NS1 IN A 200.255.253.234 +NS IN A 143.108.23.2 +$ORIGIN OYSTER.NET.CK. +POIPARAU IN A 202.65.32.127 +PARAU IN A 202.65.32.128 +$ORIGIN DRUKNET.NET.BT. +NS IN A 202.144.128.200 +$ORIGIN DCC.UCHILE.CL. +NS IN A 146.83.5.204 +$ORIGIN NIC.CL. +NS IN A 146.83.4.11 +$ORIGIN FIRSTCOM.CL. +NS IN A 200.27.2.2 +$ORIGIN EDU. +ISI IN A 128.9.176.32 +UMASS IN MX 20 vcmr-54.server.rpi.edu. + IN MX 1 mail.rpi.edu. +dartmouth IN A 129.170.16.6 + IN MX 10 donner.dartmouth.edu. + IN MX 10 prancer.dartmouth.edu. + IN MX 10 vixen.dartmouth.edu. + IN MX 10 blitzen.dartmouth.edu. + IN MX 0 mailhub.dartmouth.edu. + IN MX 10 dasher.dartmouth.edu. +rush IN MX 30 penpal.dmz.rpslmc.edu. + IN MX 10 detox.cc1.rpslmc.edu. + IN MX 20 rush.cc1.rpslmc.edu. +NYU IN A 128.122.253.92 +GATECH IN A 130.207.244.244 +ARIZONA IN A 128.196.128.233 +stanford IN A 171.64.14.120 + IN MX 20 Leland.stanford.edu. + IN MX 20 Leland2.stanford.edu. + IN MX 20 Leland3.stanford.edu. +$ORIGIN jhuapl.EDU. +ECSEL IN A 128.244.65.29 +APLDNS2 IN A 128.244.194.100 +ABACUS IN A 128.244.197.32 +$ORIGIN MIT.EDU. +STRAWB IN A 18.71.0.151 +W20NS IN A 18.70.0.160 +BITSY IN A 18.72.0.3 +$ORIGIN ITD.UMICH.EDU. +DNS2 IN A 141.211.125.15 +$ORIGIN ISI.EDU. +EAST IN A 38.245.76.2 +VENERA IN A 128.9.176.32 +NS IN A 128.9.128.127 +$ORIGIN CS.PURDUE.EDU. +PENDRAGON IN A 128.10.2.5 +$ORIGIN CS.WISC.EDU. +DNS IN A 128.105.2.10 +$ORIGIN UMD.EDU. +TRANTOR IN A 128.8.10.14 +$ORIGIN RPSLMC.EDU. +THUMPER IN A 144.74.22.8 +$ORIGIN dmz.RPSLMC.EDU. +penpal IN A 144.74.60.151 +$ORIGIN cc1.RPSLMC.EDU. +rush IN A 144.74.150.23 +detox IN A 144.74.150.44 +$ORIGIN IS.RPSLMC.EDU. +SUNSTROKE IN A 144.74.21.8 +$ORIGIN VSC.EDU. +vtc IN MX 0 eve.vtc.vsc.edu. +MAZE IN A 155.42.1.89 +ENIGMA IN A 155.42.1.7 +$ORIGIN vtc.VSC.EDU. +sundown IN A 155.42.12.12 +eve IN A 155.42.12.102 +$ORIGIN UMASS.EDU. +NS1 IN A 128.119.166.14 +NIC IN A 128.119.175.14 +$ORIGIN oit.UMASS.EDU. +supai IN A 128.119.175.6 +ponzi IN A 128.119.166.18 +$ORIGIN ECS.UMASS.EDU. +KIRA IN A 128.119.91.10 +$ORIGIN CS.UMASS.EDU. +UNIX1 IN A 128.119.40.12 +$ORIGIN UPR.CLU.EDU. +UPR1 IN A 136.145.1.4 +$ORIGIN PRINCETON.EDU. +DNS IN A 128.112.129.15 +$ORIGIN rpi.EDU. +mail IN A 128.113.100.7 +$ORIGIN server.rpi.EDU. +vcmr-54 IN A 128.113.113.44 +$ORIGIN acs.rpi.EDU. +freefour IN A 128.113.24.91 +$ORIGIN ITS.rpi.EDU. +NETSERV2 IN A 128.113.1.3 +NETSERV1 IN A 128.113.1.5 +$ORIGIN uvm.EDU. +NS1 IN A 132.198.201.10 +NS2 IN A 132.198.202.10 +$ORIGIN dartmouth.EDU. +dasher IN A 129.170.208.6 +mailhub IN A 129.170.16.6 +donner IN A 129.170.208.3 +prancer IN A 129.170.208.2 +vixen IN A 129.170.208.15 +NS1 IN A 129.170.17.4 +blitzen IN A 129.170.208.4 +NS2 IN A 129.170.16.4 +$ORIGIN middlebury.EDU. +CATAMOUNT IN A 140.233.2.204 +LION IN A 140.233.1.4 +$ORIGIN CIT.CORNELL.EDU. +DNS IN A 192.35.82.50 +$ORIGIN CS.CORNELL.EDU. +SIMON IN A 128.84.154.10 +$ORIGIN BERKELEY.EDU. +NS2 IN A 128.32.136.12 + IN A 128.32.206.12 +NS1 IN A 128.32.136.9 + IN A 128.32.206.9 +$ORIGIN CS.BERKELEY.EDU. +VANGOGH IN A 128.32.33.5 +$ORIGIN ctr.COLUMBIA.EDU. +ntp IN CNAME sirius.ctr.columbia.edu. +sirius IN A 128.59.64.60 +$ORIGIN CC.COLUMBIA.EDU. +CUNIXD IN A 128.59.35.142 +$ORIGIN UOREGON.EDU. +PHLOEM IN A 128.223.32.35 +$ORIGIN GATECH.EDU. +TROLL-GW IN A 130.207.244.251 +$ORIGIN CC.GATECH.EDU. +BURDELL IN A 130.207.3.207 +$ORIGIN UTK.EDU. +NS0 IN A 160.36.0.66 +NS1 IN A 160.36.128.66 +$ORIGIN robert-morris.EDU. +SERVICE IN A 205.146.48.22 +COLONIAL-SERVER IN A 205.146.48.25 +$ORIGIN CNS.vt.EDU. +YARDBIRD IN A 198.82.247.34 +MILO IN A 198.82.247.98 +$ORIGIN stanford.EDU. +Leland2 IN A 171.64.14.58 +AVALLONE IN A 171.64.2.210 +ATALANTE IN A 171.64.2.220 +ARGUS IN A 171.64.2.230 +$ORIGIN slac.stanford.EDU. +SMTP IN A 134.79.18.80 +NS2 IN A 134.79.16.10 +NS1 IN A 134.79.16.9 +$ORIGIN HARVARD.EDU. +NS2 IN A 128.103.1.1 +ns IN A 128.103.201.100 +NS1 IN A 128.103.200.101 +$ORIGIN med.HARVARD.EDU. +jenner IN A 134.174.141.2 +knight IN A 134.174.141.46 +eno IN A 134.174.141.50 +heckle IN A 134.174.146.152 +$ORIGIN de. +datingagentur IN A 212.227.216.57 + IN MX 10 mx01.schlund.de. + IN MX 10 mx00.schlund.de. +$ORIGIN schlund.de. +mx00 IN A 195.20.224.130 + IN A 195.20.224.198 + IN A 195.20.224.67 + IN A 195.20.224.68 + IN A 195.20.224.152 +ns4 IN A 195.20.225.36 +mx01 IN A 195.20.224.131 + IN A 195.20.224.236 + IN A 195.20.224.237 + IN A 195.20.224.238 +ns3 IN A 195.20.224.95 +$ORIGIN Informatik.Uni-Dortmund.de. +waldorf IN A 129.217.4.42 +$ORIGIN muc.de. +faerber IN MX 10 slarti.muc.de. + IN A 193.149.49.70 +ns2 IN A 193.149.48.2 +slarti IN A 193.149.48.10 +ns1 IN A 193.149.48.11 +$ORIGIN westfalen.de. +muenster IN A 193.174.5.2 +$ORIGIN lan-ks.de. +uranus IN A 194.45.71.1 +$ORIGIN kaben-net.de. +dns IN A 195.179.28.17 +$ORIGIN thur.de. +jengate IN A 193.174.15.34 +$ORIGIN erfurt.thur.de. +annwfn IN A 194.122.210.3 +$ORIGIN sgh-net.de. +ns1 IN A 212.86.129.142 +$ORIGIN DENIC.de. +SSS-NL IN A 193.0.0.237 +SSS-AT IN A 193.171.255.34 +DNS IN A 194.246.96.79 +$ORIGIN iks-jena.de. +avalon IN A 194.221.90.34 +$ORIGIN musin.de. +ns IN A 194.113.40.45 +$ORIGIN rrz.Uni-Koeln.de. +noc IN A 134.95.100.209 +$ORIGIN BelWue.de. +noc IN A 129.143.2.1 +$ORIGIN HRZ.uni-bielefeld.de. +noc IN A 129.70.5.16 +$ORIGIN techfak.uni-bielefeld.de. +techfac IN A 129.70.132.100 +$ORIGIN CUBE.de. +NS1 IN A 212.162.54.243 +$ORIGIN dtag.de. +pns IN A 194.25.0.125 +$ORIGIN netconx.de. +netconsult IN A 193.141.75.1 +$ORIGIN CAMNET.CM. +KIM IN A 195.24.192.35 +LOM IN A 195.24.192.34 +SANAGA IN A 195.24.192.17 +$ORIGIN sxtyptt.NET.CN. +ns IN A 202.99.192.68 +$ORIGIN sta.NET.CN. +ns IN A 202.96.199.133 +$ORIGIN BTA.NET.CN. +NS IN A 202.96.0.133 +$ORIGIN CNNIC.NET.CN. +sld-ns2 IN A 202.97.16.197 +DNS2 IN A 202.97.16.196 +sld-ns1 IN A 159.226.1.3 +$ORIGIN com.CN. +kw IN MX 15 mail2.kw.com.cn. +$ORIGIN kw.com.CN. +mail2 IN A 159.226.25.8 +ns IN A 159.226.25.8 +$ORIGIN CNC.AC.CN. +NS IN A 159.226.1.1 +$ORIGIN UNIANDES.EDU.CO. +AYAX IN A 157.253.50.30 +CDCNET IN A 157.253.1.13 +$ORIGIN SCSI.GOV.BY. +SUN IN A 195.50.5.103 +NS2 IN A 194.67.193.130 +$ORIGIN OPEN.BY. +A IN A 194.226.121.36 +$ORIGIN CR. +NS IN A 163.178.8.2 +$ORIGIN UCR.AC.CR. +NS IN A 163.178.88.2 +$ORIGIN INTNET.DJ. +BOW IN A 193.251.143.253 +$ORIGIN DARENET.DK. +NS-SOA IN A 130.226.1.4 +$ORIGIN TELE.DK. +NS4 IN A 194.239.134.84 +$ORIGIN DAIMI.AAU.DK. +URANUS IN A 130.225.16.40 +$ORIGIN DK-HOSTMASTER.DK. +NS IN A 193.163.102.2 +$ORIGIN EC. +ECNET IN A 157.100.45.2 +$ORIGIN NET.EC. +ECUA IN A 157.100.1.2 +$ORIGIN CENIAI.NET.CU. +NS IN A 169.158.128.136 +$ORIGIN EENET.EE. +NS IN A 193.40.56.245 +$ORIGIN KBFI.EE. +NS IN A 192.121.251.13 +$ORIGIN NIC.DO. +NS IN A 207.176.16.50 +$ORIGIN EUN.EG. +FRCU IN A 193.227.1.1 +$ORIGIN CIX.CX. +NS IN A 195.222.235.216 +$ORIGIN CX.ESCROW.IOCOMM.NET.CX. +NS1 IN A 203.132.96.2 +$ORIGIN CCS.UCY.AC.CY. +NICOSIA IN A 194.42.6.97 +$ORIGIN CC.UCY.AC.CY. +ZEUS IN A 194.42.1.1 +$ORIGIN EUNET.CZ. +CZ IN A 193.85.3.130 +$ORIGIN EUNET.FI. +PRIFI IN A 193.66.1.146 +$ORIGIN NIXU.FI. +NS IN A 193.209.237.29 +$ORIGIN TELE.FI. +NS IN A 193.210.19.19 +$ORIGIN HELSINKI.FI. +HYDRA IN A 128.214.4.29 +$ORIGIN INET.GA. +KOMO IN A 208.148.44.1 +$ORIGIN CERIST.DZ. +DECST IN A 193.194.64.11 +$ORIGIN ELDJAZAIR.NET.DZ. +CASBAH IN A 193.194.81.45 +$ORIGIN USP.AC.FJ. +TERI IN A 144.120.8.1 +$ORIGIN EUNET.ES. +NS IN A 193.127.1.11 +$ORIGIN NIC.ES. +INECO IN A 194.69.254.2 +NS1 IN A 194.69.254.1 +$ORIGIN VISUALCOM.ES. +NS IN A 194.143.202.202 +$ORIGIN MICROASTUR.ES. +SERVIDOR IN A 195.76.178.5 +$ORIGIN CESCA.ES. +PRADES IN A 192.94.163.152 +$ORIGIN PIXAR.ES. +NS IN A 194.143.196.3 +$ORIGIN REDIRIS.ES. +SUN IN A 130.206.1.2 +$ORIGIN SEKER.ES. +CORREOS IN A 194.179.87.1 +$ORIGIN TELECOM.NET.ET. +NS IN A 196.27.22.43 +$ORIGIN FM. +FM03 IN A 206.49.89.4 +FM01 IN A 206.49.89.2 +$ORIGIN NPLUS.GF. +NS1 IN A 195.6.144.3 +$ORIGIN trns. +f IN A 209.133.38.16 +d IN A 207.112.147.14 +e IN A 145.89.234.7 +c IN A 212.172.21.254 +a IN A 64.6.65.10 +$ORIGIN IRD.FR. +NS IN A 195.83.14.1 +$ORIGIN BONDY.IRD.FR. +MALAKULA IN A 193.50.53.1 +$ORIGIN RAIN.FR. +BOW IN A 194.51.3.49 +$ORIGIN imag.FR. +isis IN A 129.88.32.24 +imag IN A 129.88.30.1 +$ORIGIN INRIA.FR. +DNS IN A 193.51.208.13 +$ORIGIN NIC.FR. +NS2 IN A 192.93.0.4 +NS1 IN A 192.93.0.1 +NS3 IN A 192.134.0.49 +$ORIGIN GH.GL. +KAASASSUK IN A 194.177.232.3 +$ORIGIN TELE.GL. +TGSERV IN A 194.177.224.7 +$ORIGIN COMMIT.GM. +NS1 IN A 63.77.152.177 +$ORIGIN MRC.GM. +NS1 IN A 212.60.69.1 +$ORIGIN INTNET.GQ. +BOW IN A 195.101.152.253 +$ORIGIN AIX.GR. +NIC IN A 195.130.89.210 +$ORIGIN GRNET.GR. +FOO IN A 194.177.210.211 +NIC IN A 194.177.210.210 +$ORIGIN CSI.FORTH.GR. +ESTIA IN A 139.91.191.3 +$ORIGIN ICS.FORTH.GR. +DNS1 IN A 139.91.151.70 +GRDNS IN A 139.91.1.1 +$ORIGIN HKU.HK. +HKUXB IN A 147.8.16.15 +$ORIGIN CUHK.EDU.HK. +NS2 IN A 137.189.6.21 +NS1 IN A 137.189.6.1 +$ORIGIN CONCYT.GOB.GT. +NS IN A 168.234.106.2 +$ORIGIN UVG.EDU.GT. +NS IN A 168.234.68.2 +$ORIGIN ID. +NS1 IN A 202.155.30.227 +$ORIGIN AC.ID. +NS IN A 202.159.124.34 +$ORIGIN GU. +NS IN A 168.123.4.10 +$ORIGIN EDU.GU. +NS IN A 168.123.2.50 +$ORIGIN REGISTRY.HM. +NS2 IN A 209.54.168.55 +NS3 IN A 202.169.102.24 +NS1 IN A 204.144.183.78 +$ORIGIN CONNECT.IE. +AUTH01 IN A 194.106.128.50 +$ORIGIN DOMAINREGISTRY.IE. +BANBA IN A 193.1.142.2 +$ORIGIN VIA-NET-WORKS.IE. +ICE IN A 212.17.32.2 +$ORIGIN HONDUTEL.HN. +MIRAF-SERVER3 IN A 206.48.104.142 +$ORIGIN SRCE.HR. +DNS IN A 161.53.3.7 +$ORIGIN HUJI.AC.IL. +RELAY IN A 128.139.6.1 +$ORIGIN TAU.AC.IL. +ARISTO IN A 132.66.32.10 +$ORIGIN NIC.JE. +NS1 IN A 216.110.45.224 +$ORIGIN SZTAKI.HU. +NS2 IN A 193.225.86.1 +$ORIGIN NIC.HU. +NS IN A 193.6.27.62 +$ORIGIN NCST.ERNET.IN. +NAAMAK IN A 202.41.110.66 +SS585 IN A 202.141.150.18 +$ORIGIN NIC.IO. +NS IN A 194.205.62.100 +$ORIGIN NIC.IR. +NS1 IN A 194.225.70.83 +$ORIGIN IS. +ISGATE IN A 193.4.58.51 +$ORIGIN IUNET.IT. +DNS2 IN A 192.106.1.31 +NS IN A 192.106.1.1 +$ORIGIN INFN.IT. +SERVER2 IN A 131.154.1.3 +$ORIGIN CNR.IT. +NAMESERVER IN A 194.119.192.34 +$ORIGIN IAT.CNR.IT. +ITGBOX IN A 146.48.65.46 +$ORIGIN NETTUNO.IT. +BOLOGNA IN A 193.43.2.5 +$ORIGIN NIC.IT. +DNS IN A 193.205.245.5 +$ORIGIN JM. +NS IN A 196.2.1.6 +$ORIGIN CAST.EDU.JM. +NS IN A 200.9.115.2 +$ORIGIN NIC.GOV.JO. +AMRA IN A 193.188.66.103 +PETRA IN A 193.188.66.2 +$ORIGIN KG. +NS IN A 195.38.160.36 +$ORIGIN AD.JP. +NIC IN A 202.12.30.33 +$ORIGIN ocn.AD.JP. +ns-tk012 IN A 203.139.160.74 +$ORIGIN IIJ.AD.JP. +NS0 IN A 202.232.2.34 +$ORIGIN SINET.AD.JP. +NS-JP IN A 150.100.2.3 +$ORIGIN SPIN.AD.JP. +DNS0 IN A 165.76.0.98 +$ORIGIN NIC.AD.JP. +ns2 IN A 202.12.30.133 +TRF IN A 192.41.192.2 +NS-JP IN A 61.120.151.100 +NS0 IN A 202.12.30.131 +ns1 IN A 202.12.30.33 +$ORIGIN WIDE.AD.JP. +NS IN A 203.178.136.63 + IN MX 10 integra.s-integra.co.jp. +$ORIGIN s-integra.co.JP. +integra IN A 210.162.202.34 +$ORIGIN UUCP.NE.JP. +NS2 IN A 210.141.111.69 +$ORIGIN DNS.NET.KH. +NS1 IN A 203.127.100.21 +$ORIGIN org. +netsage IN A 209.67.235.38 +ietf IN A 132.151.1.19 + IN MX 10 odin.ietf.org. +vmba IN MX 10 gro.dd.org. +bnfinfo IN MX 10 mail.sover.net. + IN MX 20 mqueue.sover.net. +dd IN MX 10 gro.dd.org. + IN MX 50 mqueue.sover.net. + IN MX 100 mail.uu.net. +vtvast IN A 207.217.96.38 + IN A 207.217.96.39 + IN A 207.217.96.40 + IN A 207.217.96.41 + IN A 207.217.96.42 + IN A 207.217.96.43 + IN A 207.217.96.44 + IN A 207.217.96.45 + IN A 207.217.96.28 + IN A 207.217.96.29 + IN A 207.217.96.30 + IN A 207.217.96.31 + IN A 207.217.96.32 + IN A 207.217.96.33 + IN A 207.217.96.34 + IN A 207.217.96.35 + IN A 207.217.96.36 + IN A 207.217.96.37 + IN MX 10 vipmailgate.earthlink.net. +gazpacho IN A 209.67.235.38 +bikeclub IN MX 20 pop.shoreham.net. + IN MX 50 smtp.america.net. +giffordmed IN A 130.189.100.57 + IN MX 20 quest-net.com. + IN MX 10 mail.giffordmed.org. +isc IN A 204.152.184.101 +icann IN MX 100 mail.icann.org. + IN MX 95 mailhub.icann.org. +xaos IN A 24.93.15.22 + IN TXT "XAOS Associates Online Services" + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. + IN LOC 43 02 20.000 N 77 43 12.000 W 170.00m 1.00m 30.00m 10.00m +mmuuf IN MX 10 gro.dd.org. +reptiles IN A 198.96.117.142 + IN MX 10 mail2.reptiles.org. + IN MX 20 mail.vex.net. + IN MX 5 mail.reptiles.org. +iscvt IN A 207.136.209.132 + IN MX 10 isc-01.iscvt.org. + IN MX 20 mqueue.sover.net. +mailinglists IN A 63.160.175.18 +lawlinevt IN MX 20 mqueue.sover.net. + IN MX 10 host3.vtlegalaid.org. +mail-abuse IN A 204.152.184.74 +$ORIGIN SECTOR001.org. +NS0 IN A 24.4.49.117 +NS1 IN A 24.4.49.246 +$ORIGIN ML.org. +MERCURY IN A 209.68.0.85 +$ORIGIN XBILL.org. +NS IN A 204.152.186.163 +$ORIGIN spack.org. +maus IN A 204.245.198.90 +$ORIGIN netsage.org. +keith IN A 209.67.235.37 +www IN CNAME netsage.org. +sure IN A 209.67.235.38 +$ORIGIN ietf.org. +odin IN A 132.151.1.176 +www2 IN A 4.17.168.6 +www IN CNAME www2.ietf.org. +$ORIGIN lux.dot-eu.org. +ns0 IN A 195.206.105.102 +$ORIGIN the-frontier.org. +ns2 IN A 216.86.199.115 +ns1 IN A 216.86.199.114 +$ORIGIN vmba.org. +www IN MX 10 gro.dd.org. + IN A 209.198.103.206 +$ORIGIN WILLIAM.org. +JOANNA IN A 195.153.6.2 +$ORIGIN FROGHOUSE.org. +DNS IN A 207.121.69.243 +$ORIGIN VTLEGALAID.org. +host3 IN A 207.136.208.115 +$ORIGIN dd.org. +doubt IN A 209.198.103.193 +news IN CNAME gro.dd.org. +gro IN A 209.198.103.200 +d IN A 209.198.103.199 +workgroup IN A 209.198.103.201 +dhcp1 IN A 209.198.103.194 +go IN A 209.198.103.198 +mail IN CNAME gro.dd.org. +localhost IN A 127.0.0.1 +dhcp2 IN A 209.198.103.195 +www IN CNAME gro.dd.org. +dhcp3 IN A 209.198.103.196 +dhcp4 IN A 209.198.103.197 +moderators IN CNAME moderators.isc.org. +ns IN CNAME gro.dd.org. +$ORIGIN gazpacho.org. +keith IN A 209.67.235.37 +sure IN A 209.67.235.38 +$ORIGIN FLAME.org. +DNS02 IN A 204.152.184.97 +www IN A 204.152.184.97 +DNS01 IN A 204.152.184.80 +$ORIGIN giffordmed.org. +mail IN A 130.189.100.51 +$ORIGIN isc.org. +isrv3-i IN A 204.152.184.87 +$ORIGIN energyenhancement.org. +www IN A 216.121.175.228 +$ORIGIN icann.org. +mailhub IN A 192.0.34.33 +mail IN A 198.32.1.99 +$ORIGIN PAPP.UNDP.org. +PAPPSRV IN A 192.115.229.1 +$ORIGIN xaos.org. +amethyst IN A 204.145.159.12 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +sure IN A 209.67.235.38 +taiyoo IN A 204.145.159.13 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +gw IN A 24.93.15.22 +reimei IN A 204.145.159.17 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +gwi IN A 204.145.159.2 + IN HINFO "Firewall" "Gateway" + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +keith IN A 209.67.235.37 +axis IN A 204.145.159.20 +mail IN CNAME furii.xaos.org. +all IN A 24.95.203.33 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +www IN CNAME gw.xaos.org. +kadou IN A 204.145.159.14 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +furii IN A 204.145.159.11 + IN MX 0 mail.xaos.org. + IN MX 5 gw.xaos.org. +ftp IN CNAME gw.xaos.org. +gwe IN CNAME gw.xaos.org. +$ORIGIN PUNCHDOWN.org. +NS IN A 140.174.131.100 +$ORIGIN mmuuf.org. +www IN MX 10 gro.dd.org. + IN A 209.198.103.205 +$ORIGIN OPEN-RSC.org. +ASLAN IN A 199.5.157.128 +UNICORN IN A 207.126.103.16 +$ORIGIN COGNOSCENTI.org. +SYNAESTHESIA IN A 207.208.112.4 +ANAESTHESIA IN A 207.208.112.3 +$ORIGIN DC.IGC.org. +NS IN A 199.75.208.10 +$ORIGIN mitre.org. +DNSSRV1X IN A 199.94.97.51 +mbunix IN A 199.94.97.52 +DNSSRV3X IN A 198.76.173.100 +smtpproxy1 IN A 129.83.20.90 +linus IN A 129.83.10.1 + IN MX 1 linus.mitre.org. + IN MX 5 smtpproxy1.mitre.org. + IN MX 10 smtpproxy2.mitre.org. +smtpproxy2 IN A 128.29.154.90 +mwunix IN A 198.76.173.52 +$ORIGIN reptiles.org. +mail IN A 198.96.117.157 +NS2 IN A 192.75.253.138 +NS IN A 198.96.117.136 +$ORIGIN ISPC.org. +NS2 IN A 209.124.64.11 +NS3 IN A 207.230.32.23 +NS1 IN A 207.106.7.7 +$ORIGIN IGC.APC.org. +NS1 IN A 192.82.108.38 +$ORIGIN iscvt.org. +isc-01 IN A 207.136.209.131 +$ORIGIN FLIRBLE.org. +NS0 IN A 195.40.6.20 +$ORIGIN SANS.org. +SERVER1 IN A 167.216.133.33 +$ORIGIN LTWCC.org. +NS2 IN A 12.33.66.62 +NS1 IN A 12.33.66.61 +$ORIGIN CMHNET.org. +elektro IN A 192.188.133.3 +$ORIGIN SNPT.KM. +BOW IN A 195.101.19.253 +$ORIGIN ONPT.NET.MA. +MASSIRA IN A 206.103.26.1 +$ORIGIN IAM.NET.MA. +DNS2 IN A 212.217.0.12 +DNS3 IN A 212.217.1.1 +DNS1 IN A 212.217.0.1 +$ORIGIN KREONET.RE.KR. +NS IN A 134.75.30.1 +$ORIGIN KREN.NE.KR. +NS IN A 147.47.1.1 +$ORIGIN NIC.LK. +NS IN A 192.248.1.65 +$ORIGIN NIC.MC. +NS IN A 195.78.6.131 +$ORIGIN 110.16.12.IN-ADDR.ARPA. +35 IN CNAME 35.32/27.110.16.12.in-addr.arpa. +$ORIGIN 32/27.110.16.12.IN-ADDR.ARPA. +35 IN PTR mail.nova-data.com. +$ORIGIN 0.0.127.IN-ADDR.ARPA. +1 IN PTR localhost. +$ORIGIN 184.152.204.IN-ADDR.ARPA. +87 IN PTR isrv3-i.isc.org. +$ORIGIN 187.152.204.IN-ADDR.ARPA. +59 IN PTR shell.nominum.com. +$ORIGIN 131.127.204.IN-ADDR.ARPA. +47 IN PTR mtiwmhc22.worldnet.att.net. +$ORIGIN 198.245.204.IN-ADDR.ARPA. +90 IN PTR maus.spack.org. +$ORIGIN 159.145.204.IN-ADDR.ARPA. +12 IN PTR amethyst.xaos.org. +13 IN PTR taiyoo.xaos.org. +14 IN PTR kadou.xaos.org. +17 IN PTR reimei.xaos.org. +20 IN PTR axis.xaos.org. +2 IN PTR gwi.xaos.org. +11 IN PTR furii.xaos.org. +$ORIGIN 241.5.198.IN-ADDR.ARPA. +38 IN PTR cmr0.ash.ops.us.uu.net. +39 IN PTR cmr1.ash.ops.us.uu.net. +$ORIGIN 241.103.199.IN-ADDR.ARPA. +218 IN PTR abyssinian.sleepycat.com. +$ORIGIN 153.66.206.IN-ADDR.ARPA. +12 IN PTR d.dd.org. +102 IN PTR gro.dd.org. +128 IN PTR www.vmba.org. +1 IN PTR workgroup.dd.org. +2 IN PTR doubt.dd.org. +136 IN PTR www.mmuuf.org. +4 IN PTR nila.dd.org. +10 IN PTR go.dd.org. +$ORIGIN 84.198.209.IN-ADDR.ARPA. +242 IN PTR dlawren-gw.burl.sover.net. +$ORIGIN 87.198.209.IN-ADDR.ARPA. +52 IN PTR mqueue0.sover.net. +$ORIGIN 103.198.209.IN-ADDR.ARPA. +198 IN CNAME 198.192.103.198.209.in-addr.arpa. +205 IN CNAME 205.192.103.198.209.in-addr.arpa. +199 IN CNAME 199.192.103.198.209.in-addr.arpa. +206 IN CNAME 206.192.103.198.209.in-addr.arpa. +193 IN CNAME 193.192.103.198.209.in-addr.arpa. +200 IN CNAME 200.192.103.198.209.in-addr.arpa. +201 IN CNAME 201.192.103.198.209.in-addr.arpa. +$ORIGIN 192.103.198.209.IN-ADDR.ARPA. +202 IN PTR fraud.dd.org. +195 IN PTR dhcp2.dd.org. +203 IN PTR fraud.dd.org. +196 IN PTR dhcp3.dd.org. +204 IN PTR ppp.dd.org. +197 IN PTR dhcp4.dd.org. +205 IN PTR www.mmuuf.org. +198 IN PTR go.dd.org. +206 IN PTR www.vmba.org. +199 IN PTR d.dd.org. +207 IN PTR broadcast.dd.org. +200 IN PTR gro.dd.org. +193 IN PTR doubt.dd.org. +201 IN PTR workgroup.dd.org. +194 IN PTR dhcp1.dd.org. +$ORIGIN 133.188.192.IN-ADDR.ARPA. +3 IN PTR elektro.com. +$ORIGIN 206.203.192.IN-ADDR.ARPA. +9 IN PTR ice.WonderWorks.COM. +$ORIGIN 2.39.137.IN-ADDR.ARPA. +3 IN PTR New-York4.NY.ALTER.NET. +$ORIGIN 126.39.137.IN-ADDR.ARPA. +10 IN PTR Fddi0-0.New-York4.NY.ALTER.NET. +$ORIGIN IRD.MG. +ANTANA IN A 194.214.107.1 +$ORIGIN NIC.MG. +NS IN A 194.214.107.253 +$ORIGIN KW. +DNS2 IN A 161.252.48.150 +DNS1 IN A 161.252.48.140 +$ORIGIN MOC.KW. +NCC IN A 196.1.69.98 +$ORIGIN NET.NA. +GRUMPY IN A 196.20.23.1 +$ORIGIN RELCOM.KZ. +NS IN A 212.110.240.65 +$ORIGIN MARNET.MK. +KITKA IN A 194.149.131.2 +$ORIGIN SC-UNI.KTU.LT. +NEMUNAS IN A 193.219.32.13 +$ORIGIN SOTELMA.ML. +ASKIA IN A 208.144.230.3 +$ORIGIN DNS.LU. +NS2 IN A 158.64.229.3 +NS5 IN A 194.246.96.193 +NS1 IN A 158.64.229.2 +$ORIGIN INTNET.NE. +BOW IN A 194.51.164.253 +$ORIGIN MN. +MAGIC IN A 202.131.0.10 +$ORIGIN NF. +NS2 IN A 203.12.249.101 +NS1 IN A 203.12.249.100 +$ORIGIN LATNET.LV. +NS2 IN A 159.148.108.1 +NS IN A 159.148.60.2 +$ORIGIN UMAC.MO. +UMACSN2 IN A 161.64.3.2 +NS2 IN A 161.64.7.2 +UMACSN1 IN A 161.64.3.1 +NS1 IN A 161.64.7.1 +$ORIGIN NI. +NS IN A 165.98.1.2 + IN A 200.30.36.8 +$ORIGIN TMX.COM.NI. +NS IN A 205.218.253.2 +$ORIGIN UNIV-NKC.MR. +DNS2 IN A 193.251.145.154 +DNS1 IN A 193.251.145.155 +$ORIGIN SVIANED.nl. +NS IN A 143.177.1.3 +$ORIGIN secondary.nl. +ns2 IN A 194.229.138.6 +$ORIGIN DOMAIN-REGISTRY.nl. +NS2 IN A 193.176.144.130 +NS IN A 193.176.144.2 +$ORIGIN MT. +NS IN A 193.188.47.252 +$ORIGIN DHIRAAGU.MV. +NS IN A 202.1.192.196 +$ORIGIN NO. +NAC IN A 129.240.2.40 +ALCANET IN MX 15 tyholt.uninett.no. + IN MX 20 nac.no. + IN A 158.39.5.5 +$ORIGIN UIO.NO. +IFI IN A 129.240.64.2 +$ORIGIN SOL.NO. +NS1 IN A 195.225.2.10 +$ORIGIN uit.NO. +benoni IN A 129.242.4.254 +$ORIGIN ALCANET.NO. +NS IN A 193.213.238.10 +$ORIGIN UNINETT.NO. +aun IN A 129.241.1.99 +tyholt IN A 158.38.60.10 +NN IN A 158.38.0.181 +$ORIGIN alcatel.NO. +ns2 IN A 193.213.238.2 +$ORIGIN UNINET.NET.MX. +MEX1-M-213 IN A 200.33.146.213 +$ORIGIN AVANTEL.NET.MX. +DNS1 IN A 200.33.213.66 +$ORIGIN UNAM.MX. +NS IN A 132.248.253.1 +$ORIGIN NIC.MX. +NS IN A 200.23.1.1 +$ORIGIN MOS.COM.NP. +SHIKHAR IN A 202.52.255.5 +$ORIGIN MY. +MIMOS IN A 192.228.128.18 +JARING IN A 192.228.128.20 +$ORIGIN JARING.MY. +GATEN IN A 161.142.227.17 +GATE1 IN A 161.142.2.17 +$ORIGIN PA. +NS IN A 168.77.8.2 +$ORIGIN USMA.AC.PA. +VASCO IN A 208.141.92.2 +$ORIGIN UEM.MZ. +ZEBRA IN A 196.3.96.67 +OCEANO IN A 196.3.96.69 +DZOWO IN A 196.3.96.66 +$ORIGIN CENPAC.NET.NR. +NRWEB IN A 203.98.224.66 +$ORIGIN NIC.NU. +NS IN A 128.11.47.50 +$ORIGIN DE.NIC.NU. +NS0 IN A 216.200.116.40 +$ORIGIN TELIA.NIC.NU. +NS0 IN A 212.181.91.4 +$ORIGIN NS.NIC.NU. +NZ IN A 203.97.132.66 +$ORIGIN OMANTEL.NET.OM. +OM4 IN A 206.49.101.5 +OM10 IN A 206.49.101.6 +$ORIGIN RCP.NET.PE. +ICHU IN A 161.132.5.14 +$ORIGIN MANA.PF. +NS2 IN A 202.3.225.20 +NS1 IN A 202.3.225.10 +$ORIGIN QATAR.NET.QA. +NS2 IN A 212.77.192.13 +NS3 IN A 212.77.192.15 +NS1 IN A 212.77.192.10 +$ORIGIN CLEAR.NET.NZ. +NS2 IN A 203.97.37.14 +NS1 IN A 203.97.33.14 +$ORIGIN DNS.NET.NZ. +NS1 IN A 202.46.161.3 +$ORIGIN IHUG.NET.NZ. +NS2 IN A 203.29.160.2 +$ORIGIN XTRA.CO.NZ. +GORGON IN A 202.27.158.34 +$ORIGIN WAIKATO.AC.NZ. +NS99 IN A 130.217.76.27 +$ORIGIN VUW.AC.NZ. +RATA IN A 130.195.2.11 +$ORIGIN MCS.VUW.AC.NZ. +DOWNSTAGE IN A 130.195.6.10 +CIRCA IN A 130.195.5.12 +$ORIGIN PL. +from IN A 212.160.132.114 +$ORIGIN NASK.ORG.PL. +BILBO IN A 148.81.16.51 + IN A 195.187.245.51 +$ORIGIN pbks.PL. +alf IN A 195.205.33.200 +$ORIGIN CYFRONET.KRAKOW.PL. +NMS IN A 149.156.1.3 +$ORIGIN MAN.LODZ.PL. +DNS2 IN A 212.51.192.5 +$ORIGIN ispid.com.PL. +trurl IN A 195.150.99.3 +$ORIGIN itnet.com.PL. +emerald IN A 195.116.64.3 +$ORIGIN ELEKTRON.PL. +AMBER IN A 195.117.6.10 +$ORIGIN macrosoft.WAW.PL. +front IN A 194.196.86.66 +$ORIGIN NASK.WAW.PL. +ARWENA IN A 193.59.201.28 +$ORIGIN webtech.elk.PL. +tornado IN A 212.244.162.100 +$ORIGIN IKP.PL. +NS3 IN A 157.25.5.30 +$ORIGIN TPSA.PL. +DNS2 IN A 194.204.152.34 +$ORIGIN uwm.EDU.PL. +matrix IN A 213.184.3.136 +$ORIGIN FUW.EDU.PL. +DNS IN A 193.0.80.11 +$ORIGIN UPRR.PR. +PASCAL IN A 134.202.1.120 +DESCARTES IN A 134.202.1.125 +$ORIGIN NCC.UP.PT. +CIUP1 IN A 193.136.51.52 +$ORIGIN FCCN.PT. +DNS IN A 193.136.192.10 +$ORIGIN DNS.PT. +NS IN A 193.136.0.1 +$ORIGIN TELEPAC.PT. +NS1 IN A 194.65.3.20 +VIVALDI IN A 194.65.3.21 +$ORIGIN CNC.UNA.PY. +SCE IN A 200.10.228.133 +NS IN A 200.10.228.132 +$ORIGIN ISU.NET.SA. +NS1 IN A 212.26.18.3 +$ORIGIN KACST.EDU.SA. +NS IN A 212.26.44.3 +$ORIGIN COM.SB. +PIJIN IN A 202.139.42.10 +$ORIGIN SOLOMON.COM.SB. +OLKETA IN A 202.139.42.4 +$ORIGIN cafax.SE. +ns IN A 192.71.228.17 +$ORIGIN LTH.SE. +NIC IN A 130.235.20.3 +$ORIGIN SUNET.SE. +SUNIC IN A 192.36.125.2 +$ORIGIN PACIFIC.NET.SG. +NS1 IN A 192.169.33.3 +$ORIGIN NIC.NET.SG. +DS IN A 202.42.194.205 +$ORIGIN SINGNET.COM.SG. +DNSSEC2 IN A 195.13.10.226 +DNSSEC3 IN A 165.21.100.11 +DNSSEC1 IN A 165.21.83.11 +$ORIGIN RNC.RO. +NS-A IN A 192.162.16.31 +NS IN A 192.162.16.21 +$ORIGIN NIC.SH. +NS IN A 194.205.62.60 +$ORIGIN ARNES.SI. +KANIN IN A 193.2.1.66 +SREBRNJAK IN A 193.2.1.91 +$ORIGIN INTERNET.SK. +NS IN A 192.108.130.91 +$ORIGIN EUNET.SK. +NS IN A 192.108.130.33 +$ORIGIN NETLAB.SK. +NS IN A 195.168.1.4 +$ORIGIN SIERRATEL.SL. +NS IN A 194.133.124.5 +$ORIGIN INTNET.TD. +BOW IN A 193.251.147.253 +$ORIGIN RU. +ok IN A 195.2.83.162 + IN MX 50 mail.ok.ru. + IN MX 100 relay1.aha.ru. + IN MX 300 relay3.aha.ru. +$ORIGIN aha.RU. +ns1 IN A 195.2.80.142 +$ORIGIN ok.RU. +mail IN A 195.2.83.162 +ns IN A 195.2.64.36 +$ORIGIN INTELCOM.SM. +DNS IN A 194.183.64.11 +$ORIGIN OMNIWAY.SM. +DNS IN A 194.183.64.10 +$ORIGIN UCAD.SN. +NS IN A 196.1.95.1 +$ORIGIN NIC.TJ. +NS2 IN A 209.77.224.1 +NS1 IN A 209.77.250.1 +$ORIGIN SPB.SU. +NS IN A 193.124.83.69 +$ORIGIN RICC.ALMA-ATA.SU. +NS IN A 194.87.112.4 +$ORIGIN DEMOS.SU. +NS IN A 194.87.0.8 + IN A 194.87.0.9 +$ORIGIN RED.SV. +CIR IN A 168.243.254.1 +$ORIGIN GOB.SV. +CONACYT IN A 168.243.64.2 +ANTEL IN A 168.243.65.1 +$ORIGIN ATI.TN. +NS IN A 193.95.66.10 +$ORIGIN TO. +TONIC IN A 206.184.59.10 +COLO IN A 206.86.247.253 +$ORIGIN TDC.TO. +NS1 IN A 206.86.247.250 +$ORIGIN SY. +EARTH IN A 195.22.198.6 +$ORIGIN VATICAN.VA. +MICHAEL IN A 212.77.0.2 +$ORIGIN METU.EDU.TR. +NS2 IN A 144.122.199.93 +NS1 IN A 144.122.199.90 +$ORIGIN NIC.UK. +NS1 IN A 195.66.240.130 +$ORIGIN AXION.BT.CO.UK. +DNS0 IN A 132.146.5.1 +$ORIGIN ADVSYS.CO.UK. +BARNEY IN A 194.72.124.2 +$ORIGIN WR.UMIST.AC.UK. +AARDVARK IN A 130.88.146.3 + IN A 128.16.5.31 + IN MX 10 bells.cs.ucl.ac.uk. + IN MX 11 haig.cs.ucl.ac.uk. +$ORIGIN CS.UCL.AC.UK. +haig IN A 128.16.6.8 +bells IN A 128.16.5.31 +NS1 IN A 128.16.5.32 +$ORIGIN surrey.AC.UK. +info-server IN A 131.227.102.6 +eim IN MX 6 phoebe.eim.surrey.ac.uk. + IN MX 6 prue.eim.surrey.ac.uk. +$ORIGIN eim.surrey.AC.UK. +prue IN A 131.227.76.5 +phoebe IN A 131.227.74.4 +$ORIGIN MHS-RELAY.AC.UK. +SUN IN A 128.86.8.25 +$ORIGIN NIC.TT. +DNS IN A 24.3.198.194 +$ORIGIN REACCIUN.VE. +DNS2 IN A 150.188.4.212 +DNS IN A 150.188.4.210 +$ORIGIN ULA.VE. +AZMODAN IN A 150.185.130.16 +$ORIGIN UTZ. +NS2 IN A 160.124.112.10 +NS3 IN A 160.124.147.1 +NS1 IN A 160.124.48.4 +$ORIGIN NIC.TV. +NS4 IN A 207.151.24.23 +NS2 IN A 208.184.1.167 +NS6 IN A 64.56.165.153 +NS7 IN A 64.69.172.153 +NS1 IN A 209.143.242.138 +$ORIGIN EDU.TW. +MOEVAX IN A 140.111.1.2 +$ORIGIN vt.us. +state IN MX 10 mx1.state.vt.us. + IN MX 10 mx2.state.vt.us. +$ORIGIN k12.vt.us. +ns2 IN A 170.222.64.130 +morristown IN MX 0 mail.k12.vt.us. +ns1 IN A 170.222.64.130 +jericho IN MX 0 mail.k12.vt.us. +founders IN MX 0 mail.k12.vt.us. +$ORIGIN state.vt.us. +srs IN A 159.105.101.150 + IN MX 0 srs.srs.state.vt.us. + IN MX 10 mx1.state.vt.us. + IN MX 10 mx2.state.vt.us. +defgen IN MX 0 mail.state.vt.us. + IN MX 10 mx1.state.vt.us. + IN MX 10 mx2.state.vt.us. + IN MX 5 vtagr02.agr.state.vt.us. + IN MX 15 mx1.state.vt.us. + IN MX 20 mx2.state.vt.us. +mail IN A 170.222.64.134 +ns1 IN A 159.105.23.130 +ns2 IN A 170.222.64.130 +$ORIGIN srs.state.vt.us. +srs IN A 159.105.101.150 +$ORIGIN agr.state.vt.us. +vtagr04 IN A 159.105.50.4 +vtagr02 IN A 159.105.50.2 +$ORIGIN anr.state.vt.us. +dec IN MX 10 mx1.state.vt.us. + IN MX 10 mx2.state.vt.us. + IN MX 0 dec.anr.state.vt.us. + IN A 159.105.46.4 +$ORIGIN pha.pa.us. +candle IN A 162.33.245.46 +$ORIGIN CNRI.reston.va.us. +NS IN A 132.151.1.1 +$ORIGIN boston.MA.us. +foxharp IN MX 10 bparker.connactivity.com. +$ORIGIN ns.foxharp.boston.MA.us. +a IN A 24.147.209.205 +$ORIGIN STARFIRE.DOUGLAS.MA.us. +NS2 IN A 216.129.136.9 +DNS IN A 206.225.44.40 +NS1 IN A 216.129.136.9 +$ORIGIN NIC.us. +USDNS IN A 198.41.3.87 +$ORIGIN sf.ca.us. +asylum IN A 192.48.232.17 +$ORIGIN palo-alto.ca.us. +mejac IN A 192.147.236.1 +$ORIGIN VN. +DNS1 IN A 203.162.3.235 +$ORIGIN EDU.UY. +SECIU IN A 164.73.128.5 +$ORIGIN UZ. +NS IN A 213.68.88.11 +$ORIGIN NOC.UZ. +NS IN A 194.67.52.42 +$ORIGIN VANUATU.COM.VU. +SANTO IN A 202.139.40.7 +FUTUNA IN A 202.139.40.3 +EFATE IN A 202.139.40.5 +$ORIGIN nic.mnet. +ns2 IN A 208.109.83.110 +ns1 IN A 216.61.39.172 +$ORIGIN DNS.WS. +NS4 IN A 216.52.234.102 +NS2 IN A 216.35.187.250 +NS1 IN A 202.4.48.217 +NS5 IN A 216.35.188.8 +NS3 IN A 216.52.234.99 +$ORIGIN UCT.AC.ZA. +UCTHPX IN A 137.158.128.1 +$ORIGIN FRD.AC.ZA. +APIES IN A 137.214.80.1 +$ORIGIN EE.UND.AC.ZA. +DAISY IN A 146.230.192.18 +$ORIGIN RU.AC.ZA. +HIPPO IN A 146.231.128.1 +$ORIGIN UNZA.ZM. +PUKU IN A 196.7.240.1 +$ORIGIN NIC.YU. +NS1 IN A 147.91.8.6 +$ORIGIN TELEKOM.YU. +ODISEJ IN A 195.178.32.2 +$ORIGIN gtld-servers.ORSC. +b IN A 216.13.126.116 +$ORIGIN ROOT-SERVERS.ORSC. +B IN A 216.13.126.116 +C IN A 65.196.80.102 +A IN A 199.166.24.1 +$ORIGIN ZPTC.CO.ZW. +TELCOM IN A 194.133.122.47 +$ORIGIN NIPR.MIL. +PAC2 IN A 199.252.155.234 +EUR2 IN A 199.252.143.234 +CON2 IN A 199.252.173.234 +PAC1 IN A 199.252.180.234 +EUR1 IN A 199.252.154.234 +CON1 IN A 199.252.175.234 +$ORIGIN ARL.MIL. +ADMII IN A 128.63.31.4 + IN A 128.63.5.4 +$ORIGIN GOV. +nps IN MX 5 ccmail.itd.nps.gov. + IN MX 10 ccmail2.itd.nps.gov. +$ORIGIN STAT-USA.GOV. +SUNNY IN A 192.239.70.8 +$ORIGIN NASA.GOV. +jpl IN A 137.78.160.180 +NASANS4 IN A 198.116.144.33 +NASANS3 IN A 198.116.144.49 +NASANS1 IN A 192.77.84.32 +$ORIGIN NSI.NASA.GOV. +MX IN A 128.102.18.31 +$ORIGIN CDC.GOV. +NS2 IN A 198.246.96.92 +NS1 IN A 198.246.96.61 +$ORIGIN NIST.GOV. +NS1 IN A 129.6.13.2 +$ORIGIN cr.USGS.GOV. +ISDSUN IN A 136.177.16.3 +ns IN A 136.177.16.3 +rgfsparc IN A 136.177.164.192 +$ORIGIN ER.USGS.GOV. +NS IN A 130.11.48.2 +$ORIGIN WR.USGS.GOV. +ISDMNL IN A 130.118.4.2 +$ORIGIN DEN.nps.GOV. +DENS20 IN A 165.83.24.20 +$ORIGIN ITD.nps.GOV. +BIGBIRD IN A 165.83.208.5 +$ORIGIN AKSO.nps.GOV. +INPAKSODNS IN A 165.83.49.9 +$ORIGIN WRO.nps.GOV. +VANILLA IN A 165.83.71.3 +$ORIGIN NCC.nps.GOV. +OWL IN A 165.83.34.60 +$ORIGIN net. +FIREHOUSE IN A 63.160.175.19 +gbch IN MX 0 maxim.gbch.net. +VERMONTEL IN A 63.167.45.2 + IN MX 0 pop.vermontel.net. +reedmedia IN A 63.145.197.178 +goldstats IN A 66.33.12.17 +zama IN A 203.142.132.46 +helicon IN A 63.93.137.2 +wetlogic IN MX 10 athome.wetlogic.net. +188 IN A 202.96.125.100 + IN A 202.96.125.101 + IN MX 10 mx2.188.net. + IN MX 20 smtp.188.net. + IN MX 10 mx1.188.net. +valley IN MX 0 lebanon.valley.net. +primary IN A 216.87.34.253 +SOVER IN A 209.198.87.53 + IN A 209.198.87.34 + IN MX 10 mail.sover.net. + IN MX 20 mqueue.sover.net. +UU IN MX 10 external-mail-router.UU.NET. +connriver IN A 63.93.137.13 + IN MX 10 ns.hcr.net. + IN MX 1 mailer.connriver.net. +SHOREHAM IN A 199.170.121.2 +$ORIGIN cinenet.net. +NS1 IN A 198.147.76.65 +$ORIGIN TOGETHER.net. +NS2 IN A 204.97.120.31 +NS1 IN A 204.97.120.30 +$ORIGIN IPHIL.net. +MAKISIG IN A 203.176.28.135 +$ORIGIN PLANET-THREE.net. +NS2 IN A 212.49.219.190 +$ORIGIN FIREHOUSE.net. +DNS2 IN A 63.160.175.18 +DNS1 IN A 63.160.175.19 +$ORIGIN space.net. +ns IN A 195.30.0.1 +$ORIGIN DNS.space.net. +NS4 IN A 195.222.210.93 +NS3 IN A 193.149.44.49 +$ORIGIN ALASKA.net. +NS4-AUTH IN A 209.112.130.4 +NS1-AUTH IN A 209.112.160.4 +$ORIGIN FWIDCSERVICES.net. +DEN-NS2 IN A 216.7.160.32 +IRV-NS1 IN A 216.23.160.51 +DEN-NS1 IN A 216.7.160.31 +NS1 IN A 64.78.224.58 +$ORIGIN BIJT.net. +PAN IN A 213.196.2.97 +$ORIGIN SEABONE.net. +DNS IN A 195.22.205.163 +$ORIGIN SPIN.OMNES.net. +NS IN A 192.23.90.196 +$ORIGIN VERIO.net. +NS2 IN A 129.250.31.190 +NS0 IN A 129.250.15.61 +NS1 IN A 204.91.99.140 +$ORIGIN NS.VERIO.net. +B IN A 129.250.35.32 +T IN A 192.67.14.16 +$ORIGIN GNOSH.net. +GRIN IN A 216.15.87.207 +$ORIGIN NEASE.net. +NS2 IN A 202.103.134.4 +$ORIGIN CRSNIC.net. +NS1 IN A 198.41.3.39 +$ORIGIN VERISIGN.net. +MODOR IN A 205.139.94.55 +CITADEL IN A 205.139.94.15 +PAGOSA IN A 205.139.94.16 +KAOS IN A 208.202.137.126 +$ORIGIN terra.net. +ns2 IN A 199.103.128.2 +ns1 IN A 199.103.128.1 +$ORIGIN ADMONITOR.net. +NS-2 IN A 216.35.185.40 +ads IN A 216.35.185.145 +SC-NS1 IN A 64.70.20.85 +$ORIGIN NORDU.net. +SERVER IN A 193.10.252.19 +$ORIGIN TELEGLOBE.net. +CASTOR IN A 199.202.55.2 +$ORIGIN sodak.net. +NS2 IN A 63.65.239.225 +RINGNECK IN A 63.65.238.65 +$ORIGIN gbch.net. +MAXIM IN A 203.9.155.249 +$ORIGIN VERMONTEL.net. +pop IN CNAME loomis.vermontel.net. +NS2 IN A 204.164.106.8 +loomis IN A 204.164.106.19 +NS1 IN A 204.164.106.2 +$ORIGIN farm.net. +ns IN A 216.112.179.160 +$ORIGIN NAP.net. +NS2 IN A 206.54.224.1 +$ORIGIN AH.net. +NS4 IN A 203.21.205.20 +NS2 IN A 203.21.205.1 +$ORIGIN NS.GDNS.net. +LHR IN A 212.250.25.101 +DCA IN A 209.207.221.1 +$ORIGIN CONCENTRIC.net. +NAMESERVER1 IN A 207.155.183.73 +NAMESERVER3 IN A 206.173.119.72 +NAMESERVER IN A 207.155.183.72 +NIC2 IN A 207.88.60.5 +NAMESERVER2 IN A 207.155.184.72 +$ORIGIN att.net. +worldnet IN A 199.70.151.234 +$ORIGIN worldnet.att.net. +ns3 IN A 204.127.160.1 +ns4 IN A 204.127.160.2 +mtiwmhc22 IN A 204.127.131.47 +ns1 IN A 204.127.129.1 +ns IN A 204.127.160.2 + IN A 12.102.240.1 + IN A 12.102.240.2 + IN A 12.102.244.1 + IN A 12.102.244.2 + IN A 204.127.129.1 + IN A 204.127.129.2 + IN A 204.127.160.1 +ns2 IN A 204.127.129.2 +$ORIGIN OR.BR.NP.ELS-GMS.att.net. +ORCU IN A 199.191.129.139 +$ORIGIN WY.BR.NP.ELS-GMS.att.net. +WYCU IN A 199.191.128.43 +$ORIGIN OH.MT.NP.ELS-GMS.att.net. +OHCU IN A 199.191.144.75 +$ORIGIN MA.MT.NP.ELS-GMS.att.net. +MACU IN A 199.191.145.136 +$ORIGIN MT.NS.ELS-GMS.att.net. +CMTU IN A 12.127.16.69 +DMTU IN A 12.127.16.70 +$ORIGIN BR.NS.ELS-GMS.att.net. +CBRU IN A 199.191.128.105 +DBRU IN A 199.191.128.106 +$ORIGIN LEB.net. +NS IN A 206.127.55.2 +$ORIGIN SEG.net. +NS2 IN A 206.34.181.16 +NS1 IN A 206.34.181.15 +$ORIGIN romkey.SEG.net. +ip1 IN A 207.121.69.234 +$ORIGIN ync.net. +NS4 IN A 206.185.20.9 +NS2 IN A 216.34.185.21 +NS5 IN A 206.185.20.10 +NS3 IN A 206.185.20.8 +ns1 IN A 216.34.185.20 +$ORIGIN GLOBECOMM.net. +NS2 IN A 165.251.1.3 +NS1 IN A 165.251.1.2 +$ORIGIN PREP.net. +DNS-EAST IN A 129.250.252.10 +$ORIGIN EARTHLINK.net. +NS4 IN A 209.179.179.19 +DNS2 IN A 207.217.77.12 +DNS3 IN A 207.217.120.13 +DNS4 IN A 209.179.179.18 +NS1 IN A 207.217.126.41 +NS2 IN A 207.217.77.42 +$ORIGIN SPRINTLINK.net. +NS3-AUTH IN A 144.228.255.10 +NS2-AUTH IN A 144.228.254.10 +NS1-AUTH IN A 206.228.179.10 +$ORIGIN OP.net. +NS1 IN A 209.152.193.4 +$ORIGIN CERNET.net. +NS IN A 202.112.0.44 +$ORIGIN zenon.net. +dns IN A 195.2.83.107 +$ORIGIN INFI.net. +NS3 IN A 205.219.239.5 +NS4 IN A 216.33.106.19 +NS001 IN A 208.131.160.201 +NS1 IN A 198.22.1.107 +NS2 IN A 198.22.1.108 +$ORIGIN vh8.INFI.net. +vh80040 IN A 209.97.59.245 +vh80167 IN A 209.97.57.116 +$ORIGIN vh4.INFI.net. +vh40099 IN A 209.97.59.121 +$ORIGIN SCRUZ.net. +NS2 IN A 165.227.2.10 +NS IN A 165.227.1.1 +$ORIGIN HINET.net. +netnews IN A 168.95.195.16 + IN MX 0 netnews.hinet.net. +HNTP1 IN A 168.95.192.1 +HNTP3 IN A 168.95.192.2 +DNS IN A 168.95.1.1 +$ORIGIN reedmedia.net. +ns2 IN A 209.241.86.6 +NS1 IN A 63.145.197.178 +$ORIGIN schnism.net. +ns IN A 195.88.150.3 +$ORIGIN unlisys.net. +mail IN A 195.21.255.252 +$ORIGIN AIC.net. +NS IN A 195.250.64.65 +$ORIGIN PIPEX-SZ.net. +NS IN A 196.15.232.19 +$ORIGIN DOMAINNT.net. +DENEB IN A 207.211.220.90 +RIGEL IN A 212.0.205.5 +VEGA IN A 209.26.120.5 +POLARIS IN A 209.26.120.2 +ANTARES IN A 209.26.120.3 +$ORIGIN GUERNSEY.net. +DNS2 IN A 195.226.128.3 +$ORIGIN usa.net. +CNDVG001 IN A 165.212.12.1 +$ORIGIN OPS.usa.net. +dns03 IN A 204.68.24.136 +DNS01 IN A 204.68.24.137 +$ORIGIN INR.net. +NS2 IN A 198.77.208.3 +NS1 IN A 198.77.208.2 +$ORIGIN CP.MSFT.net. +dns6 IN A 207.46.138.20 +DNS4 IN A 207.46.138.11 +dns7 IN A 207.46.138.21 +dns IN A 207.46.138.10 +DNS5 IN A 207.46.138.12 +$ORIGIN UK.MSFT.net. +DNS4 IN A 213.199.144.152 +DNS3 IN A 213.199.144.151 +$ORIGIN TK.MSFT.net. +DNS2 IN A 207.46.232.38 +DNS1 IN A 207.46.232.37 +$ORIGIN HHS.net. +NS IN A 63.93.136.29 +$ORIGIN NEWACCOUNT.net. +NS IN A 216.121.96.26 +$ORIGIN PBI.net. +NS2 IN A 206.13.29.11 +NS1 IN A 206.13.28.11 +$ORIGIN timeheart.net. +ns1 IN A 63.197.231.203 +$ORIGIN TOSA.TWTELECOM.net. +INS2 IN A 204.95.160.4 +INS1 IN A 204.95.160.2 +$ORIGIN zama.net. +NS2 IN A 203.142.130.5 +NS1 IN A 203.142.130.4 +$ORIGIN MINDLINK.net. +GIANT IN A 204.174.18.2 +DEEP IN A 204.174.16.4 +$ORIGIN SER.BBNPLANET.net. +KNOCK IN A 192.239.16.129 +$ORIGIN MEDIASERVICES.net. +NS2 IN A 64.65.16.237 +NS IN A 64.65.15.147 +$ORIGIN KOLO.net. +NS IN A 209.66.103.20 +$ORIGIN SEYCHELLES.net. +NS1 IN A 202.84.235.33 +$ORIGIN BT.net. +NS0 IN A 194.72.6.51 +$ORIGIN JERKY.net. +NS1 IN A 204.57.55.100 +$ORIGIN CN.net. +DNS2 IN A 202.97.18.61 +NS1 IN A 202.97.7.17 +NS IN A 202.97.16.195 +$ORIGIN runway.CN.net. +ns IN A 211.101.132.8 +$ORIGIN APNIC.net. +SVC00 IN A 202.12.28.131 +TECKLA IN A 202.12.28.129 +NS IN A 203.37.255.97 +$ORIGIN BELLSOUTH.net. +NS IN A 205.152.0.5 +$ORIGIN ATL.BELLSOUTH.net. +NS IN A 205.152.0.20 +$ORIGIN CL.BELLSOUTH.net. +NS2 IN A 205.152.16.8 +NS3 IN A 205.152.32.8 +$ORIGIN MIA.BELLSOUTH.net. +NS IN A 205.152.16.20 +$ORIGIN RDU.BELLSOUTH.net. +NS IN A 205.152.32.20 +$ORIGIN 163.net. +SHNS IN A 61.129.65.108 +BJNS IN A 202.108.255.202 +NS IN A 202.108.255.201 +$ORIGIN ca.us.ibm.net. +ns02 IN A 165.87.201.243 +ns01 IN A 165.87.201.244 +$ORIGIN ny.us.ibm.net. +ns01 IN A 165.87.194.244 +$ORIGIN CP.net. +NS3 IN A 209.228.14.4 +NS1 IN A 209.228.15.4 +$ORIGIN tallship.net. +falcon IN A 208.179.112.2 +condor IN A 12.28.140.20 +nomad IN A 204.107.129.2 +satan IN A 204.107.129.3 +rectum IN A 204.107.129.10 +$ORIGIN ns.tmcs.net. +b IN A 209.104.33.252 +c IN A 209.104.39.252 +a IN A 209.104.63.252 +$ORIGIN pshift.net. +mail IN A 208.153.85.30 +$ORIGIN CTCCOM.net. +NS4 IN A 64.69.100.35 +NS3 IN A 64.69.100.67 +$ORIGIN cid.net. +bofh IN A 212.172.21.254 +$ORIGIN PIPEX.net. +NS0 IN A 158.43.128.8 +NS1 IN A 158.43.192.7 +$ORIGIN DNS.PIPEX.net. +NS1-Y IN A 158.43.193.89 +NS0-Y IN A 158.43.129.89 +$ORIGIN SOTELMA.net. +DOGON IN A 208.144.230.1 +CIWARA IN A 208.144.230.2 +$ORIGIN DK.net. +NS IN A 193.88.44.42 +$ORIGIN HIGGS.net. +ns2 IN A 204.80.125.145 +ns3 IN A 204.80.101.94 +ns IN A 204.80.101.90 +ns1 IN A 204.80.125.130 +PINE IN A 204.80.125.130 +$ORIGIN E-SYNC.net. +NS2 IN A 192.206.57.128 +NS1 IN A 192.206.57.127 +$ORIGIN ABOVE.net. +NS3 IN A 207.126.105.146 +NS IN A 207.126.96.162 +$ORIGIN COBEX.net. +NS2 IN A 207.102.129.72 +NS1 IN A 207.102.129.71 +$ORIGIN NEO.net. +NS2 IN A 206.109.7.65 +NS IN A 206.109.1.1 +$ORIGIN AFRIQ.net. +BAABEN IN A 165.231.1.3 +NEENE IN A 165.231.1.2 +$ORIGIN CW.net. +NS4 IN A 204.70.49.234 +NS2 IN A 204.70.57.242 +NS3 IN A 204.70.25.234 +NS IN A 204.70.128.1 +$ORIGIN hactrn.net. +NS IN A 216.254.68.12 +$ORIGIN QUASAR.net. +NS1 IN A 199.166.31.3 +$ORIGIN VERMONTLAW.net. +NS1 IN A 63.89.26.15 +NS IN A 63.89.26.16 +$ORIGIN ICP.net. +ICM1 IN A 192.94.207.66 +$ORIGIN wetlogic.net. +athome IN CNAME c1059495-a.snvl1.sfba.home.com. +$ORIGIN NY.ALTER.net. +New-York4 IN A 137.39.126.10 + IN A 137.39.2.3 +$ORIGIN pccf.net. +proxy IN A 205.189.73.123 +$ORIGIN IS-FUN.net. +NS4 IN A 212.162.54.34 +$ORIGIN GUA.net. +OSI2 IN A 205.161.188.3 +$ORIGIN 2GLOBE.net. +TERMINAL IN A 195.178.183.230 +NS IN A 195.178.183.200 +$ORIGIN SYS.GTEI.net. +DNSAUTH2 IN A 4.2.49.3 +DNSAUTH3 IN A 4.2.49.4 +DNSAUTH1 IN A 4.2.49.2 +$ORIGIN SPEAKEASY.net. +NS2 IN A 216.231.41.22 +NS1 IN A 216.254.0.9 +$ORIGIN PSI.net. +NS2 IN A 38.8.50.2 +$ORIGIN DNS.UK.PSI.net. +SEC1 IN A 154.32.105.34 +$ORIGIN ray.net. +ns1 IN A 195.238.228.131 +$ORIGIN anycast.net. +ns1 IN A 216.196.51.4 +$ORIGIN EP.net. +FLAG IN A 198.32.4.13 +$ORIGIN SR.net. +NS2 IN A 200.1.156.11 +NS1 IN A 200.1.157.10 +$ORIGIN IPTEK.net. +CADDSYS IN A 202.46.1.2 +$ORIGIN NIC.XLINK.net. +DNS IN A 193.141.40.42 +$ORIGIN NURSAT.net. +NS2 IN A 212.13.167.1 +NS IN A 194.226.128.1 +$ORIGIN 188.net. +smtp IN A 202.96.125.104 +mx2 IN A 202.96.125.101 +ns2 IN A 202.103.134.4 +mx1 IN A 202.96.125.100 +NS IN A 202.96.125.106 +$ORIGIN KORNET.net. +NS IN A 168.126.63.1 +$ORIGIN CCSRS.net. +NS2 IN A 206.253.214.73 +NS1 IN A 209.237.73.73 +$ORIGIN EU.net. +NS IN A 192.16.202.11 +$ORIGIN USSR.EU.net. +NS IN A 193.124.22.65 +$ORIGIN RELCOM.EU.net. +NS IN A 193.124.23.3 +$ORIGIN AUSTRIA.EU.net. +NS IN A 192.92.138.35 +NS3 IN A 193.154.160.110 +$ORIGIN hypa.net. +ns2 IN A 63.160.181.11 +ns1 IN A 63.160.181.10 + IN A 209.166.167.208 +$ORIGIN IDT.net. +NS IN A 198.4.75.100 +$ORIGIN NS.IDT.net. +AUTH2 IN A 169.132.133.1 +$ORIGIN ROOT-SERVERS.net. +A IN A 198.41.0.4 +B IN A 128.9.0.107 +C IN A 192.33.4.12 +D IN A 128.8.10.90 +E IN A 192.203.230.10 +F IN A 192.5.5.241 +G IN A 192.112.36.4 +H IN A 128.63.2.53 +I IN A 192.36.148.17 +$ORIGIN I-DNS.net. +D IN A 211.169.245.170 +B IN A 208.184.25.199 +F IN A 216.200.119.128 +E IN A 202.160.253.152 +C IN A 210.189.254.50 +A IN A 208.184.174.7 +$ORIGIN US.PRSERV.net. +NS4 IN A 165.87.201.244 +NS1 IN A 165.87.194.244 +NS3 IN A 165.87.201.243 +$ORIGIN U-NET.net. +NS0 IN A 194.119.128.65 +NS1 IN A 194.119.128.66 +$ORIGIN HS0.U-NET.net. +NS0 IN A 194.119.128.70 +NS1 IN A 194.119.128.71 +$ORIGIN ULTRADNS.net. +UDNS2 IN A 204.74.101.1 +UDNS1 IN A 204.69.234.1 +$ORIGIN WEBMAGIC.net. +NS2 IN A 64.168.49.66 +NS1 IN A 209.119.182.2 +$ORIGIN HOST4U.net. +NS2 IN A 209.150.129.3 +NS IN A 209.150.128.30 +$ORIGIN RCCN.net. +DNS IN A 193.136.7.17 +$ORIGIN valley.net. +lebanon IN A 198.115.160.16 +NS2 IN A 198.115.160.16 +DNS IN A 198.115.160.10 +$ORIGIN primary.net. +dns2 IN A 205.242.187.235 +NS2 IN A 205.242.176.103 +dns1 IN A 205.242.187.234 +NS1 IN A 205.242.92.2 +$ORIGIN SQUONK.net. +NS2 IN A 63.84.12.135 +NS1 IN A 63.84.12.133 +$ORIGIN IP-PLUS.net. +NS1 IN A 164.128.36.34 +$ORIGIN TECHNOLOGIA.net. +NS2 IN A 207.253.59.4 +NS1 IN A 207.253.214.199 +NS3 IN A 195.115.180.67 +$ORIGIN VI.net. +NS2 IN A 212.78.64.10 +NS1 IN A 194.88.77.1 +$ORIGIN ISLES.net. +RS IN A 212.100.224.90 +$ORIGIN SOVER.net. +time IN CNAME garnet.sover.net. +mqueue IN A 209.198.87.52 +etrn IN A 209.198.87.58 +garnet IN A 209.198.87.53 +MAPLE IN A 209.198.87.41 +CLOVER IN A 209.198.87.40 +mail IN A 209.198.87.53 + IN A 209.198.87.34 +mqueue0 IN A 209.198.87.52 +$ORIGIN ACT2000.net. +ACT2 IN A 207.42.132.227 +ACT1 IN A 207.42.132.226 +$ORIGIN AKADNS.net. +ZA IN A 209.185.188.39 +ZB IN A 216.32.65.105 +ZC IN A 204.178.107.227 +ZD IN A 204.178.110.67 +ZE IN A 216.200.14.118 +ZF IN A 208.5.85.132 +ZG IN A 206.132.160.36 +ZH IN A 63.208.48.42 +$ORIGIN NS.ESAT.net. +NS3 IN A 192.111.39.100 +$ORIGIN THEPLANET.net. +EARTH IN A 195.92.195.222 +PLUTO IN A 194.207.6.30 +VENUS IN A 194.152.65.222 +$ORIGIN UU.net. +uunet IN MX 10 Mail.uu.net. +external-mail-router IN A 198.5.241.39 + IN A 198.5.241.38 + IN A 198.5.241.40 +NS IN A 137.39.1.3 +$ORIGIN NS.DE.UU.net. +AUTH03 IN A 192.76.144.16 +$ORIGIN NS.UU.net. +AUTH100 IN A 198.6.1.202 +AUTH00 IN A 198.6.1.65 +AUTH02 IN A 198.6.1.82 +AUTH03 IN A 198.6.1.83 +AUTH60 IN A 198.6.1.181 +AUTH61 IN A 198.6.1.182 +AUTH110 IN A 198.6.1.114 +AUTH50 IN A 198.6.1.161 +AUTH51 IN A 198.6.1.162 +$ORIGIN PIONEERNET.net. +DNS2 IN A 208.240.196.10 +DNS1 IN A 208.240.196.9 +$ORIGIN HOME.net. +NS2 IN A 24.2.0.27 +NS1 IN A 24.0.0.27 +$ORIGIN QUANTIFIED.net. +NS2 IN A 63.212.171.3 +NS1 IN A 63.212.171.2 +$ORIGIN SECURE.net. +NS2 IN A 161.58.9.10 +NS1 IN A 192.41.1.10 +$ORIGIN DSL.net. +NS2 IN A 209.87.79.232 +NS1 IN A 209.87.64.70 +$ORIGIN JA.net. +NS0 IN A 128.86.1.20 + IN A 193.63.94.20 +$ORIGIN ULCC.JA.net. +NOC IN A 193.63.94.25 +$ORIGIN CINE.net. +NS2 IN A 207.168.250.12 +$ORIGIN ANS.net. +NS-02B IN A 207.24.245.178 +NS-01B IN A 199.221.47.8 +NS-02A IN A 207.24.245.179 +NS-01A IN A 199.221.47.7 +$ORIGIN OAR.net. +NS2 IN A 192.88.195.10 +NS1 IN A 192.88.193.144 +$ORIGIN MAHNET.net. +NS2 IN A 207.219.173.132 +NS1 IN A 24.69.168.121 +$ORIGIN NCREN.net. +REGGAE IN A 128.109.131.3 +NCNOC IN A 192.101.21.1 +$ORIGIN AMERICA.net. +AUTH2 IN A 209.17.197.18 +AUTH1 IN A 209.17.197.2 +$ORIGIN EXODUS.net. +NS2 IN A 207.82.198.150 +NS IN A 206.79.230.10 +NS3 IN A 206.79.240.13 +$ORIGIN NJ.EXODUS.net. +NS2 IN A 209.1.10.234 +NS IN A 206.79.7.50 +$ORIGIN DOUBLECLICK.net. +uunymdgds1 IN A 206.65.183.21 +dcnymdgds1 IN A 204.253.104.202 +exnjmdgds1 IN A 209.67.38.22 +dcnyadgds1 IN A 204.253.104.11 +bbvamdgds1 IN A 128.11.60.75 +exnjadgds1 IN A 209.67.38.48 +annyadgds1 IN A 208.184.29.250 +annyadgds2 IN A 208.184.29.252 +cwvamdgds1 IN A 205.138.3.240 +uucamdgds1 IN A 204.178.112.124 +cwvaadgds1 IN A 205.138.3.242 +spnjadgds1 IN A 208.32.211.70 +cwvaadgds2 IN A 205.138.3.243 +ctukadgds1 IN A 213.86.246.20 +tlseadgds1 IN A 194.237.107.6 +uusjmdgds1 IN A 204.176.177.20 +uuvamdgds1 IN A 204.178.112.168 +$ORIGIN DCNY.DOUBLECLICK.net. +NS2 IN A 204.253.104.10 +NS1 IN A 208.211.225.10 +$ORIGIN UUSJ.DOUBLECLICK.net. +NS1 IN A 204.176.177.10 +$ORIGIN CWVA.DOUBLECLICK.net. +NS1 IN A 205.138.3.20 +$ORIGIN DSO.net. +NS2 IN A 206.16.77.11 +NS1 IN A 206.16.77.10 +$ORIGIN GIP.net. +NS2 IN A 204.59.1.222 +NS1 IN A 204.59.144.222 +NS3 IN A 204.59.64.222 +$ORIGIN AMNIC.net. +NS IN A 195.250.64.90 +$ORIGIN TELSTRA.net. +NS1 IN A 139.130.4.5 +$ORIGIN ELI.net. +NS2 IN A 207.173.86.2 +NS IN A 209.63.0.2 +$ORIGIN TWNIC.net. +NS IN A 192.83.166.11 +$ORIGIN BAHNHOF.net. +NS2 IN A 212.85.64.4 +NS1 IN A 195.178.160.2 +$ORIGIN ivm.net. +ns1 IN A 62.204.1.1 +$ORIGIN BEACHSHORE.net. +NS1 IN A 199.166.31.250 +$ORIGIN TDS.net. +NS IN A 204.246.1.20 +$ORIGIN FIRSTWORLD.net. +NS4 IN A 216.7.160.162 +NS2 IN A 216.127.92.78 +NS1 IN A 216.7.160.75 +NS3 IN A 216.7.160.161 +$ORIGIN centralinfo.net. +ns2 IN A 63.102.204.130 +ns1 IN A 63.102.200.2 +$ORIGIN NOC.NULLUS.net. +NS2 IN A 63.119.253.254 +NS3 IN A 63.168.101.254 +NS1 IN A 209.136.161.254 +$ORIGIN FREE.net. +NS1 IN A 147.45.15.34 +$ORIGIN mediaone.net. +NS1 IN A 24.128.1.80 +NS2 IN A 24.128.1.81 +$ORIGIN MW.mediaone.net. +NS1 IN A 24.131.1.8 +$ORIGIN JVNC.net. +NISC IN A 128.121.50.7 +$ORIGIN NS.NYC1.GLOBIX.net. +Z1 IN A 209.10.66.55 +$ORIGIN NS.LHR1.GLOBIX.net. +Z1 IN A 212.111.32.38 +$ORIGIN NS.SJC1.GLOBIX.net. +Z1 IN A 209.10.34.55 +$ORIGIN akamaitech.net. +za IN A 204.178.107.226 +n6g IN A 216.52.121.175 +ZB IN A 128.11.47.240 +n2g IN A 216.52.56.47 +ZC IN A 216.32.65.14 +ZD IN A 38.144.120.147 +n5g IN A 216.52.56.33 +ZE IN A 216.200.14.134 +n1g IN A 216.52.56.36 +ZF IN A 204.178.110.73 +n8g IN A 216.52.56.33 +ZG IN A 209.185.188.14 +n4g IN A 216.52.56.33 +ZH IN A 213.161.66.165 +n0g IN A 216.52.56.33 +n7g IN A 216.52.196.5 +n3g IN A 216.52.56.48 +$ORIGIN THNIC.net. +NS-AIT IN A 192.41.170.219 +NS IN A 202.28.0.1 +$ORIGIN connriver.net. +mailer IN A 63.93.137.13 +ns2 IN A 208.240.246.5 +netserver IN A 204.249.74.100 +$ORIGIN IT.net. +DNS2 IN A 151.1.2.1 +DNS IN A 151.1.1.1 +$ORIGIN D4P.net. +foolusmf IN CNAME a100.g.akamai.net. +$ORIGIN LUCKY.net. +NS IN A 193.193.193.100 +$ORIGIN SENET.net. +NS IN A 206.155.163.195 +$ORIGIN RIPE.net. +NS IN A 193.0.0.193 +$ORIGIN ADELPHIA.net. +NS2 IN A 24.48.62.35 +NS3 IN A 208.239.78.134 +NS1 IN A 24.48.43.3 +$ORIGIN cdp.ADELPHIA.net. +mx1 IN A 24.48.58.221 +$ORIGIN buf.ADELPHIA.net. +mx1 IN A 24.48.36.10 +$ORIGIN INTERNIC.net. +NS2 IN A 198.41.0.11 +$ORIGIN UNDPBI.TELEPAC.net. +SOL IN A 194.65.87.2 +$ORIGIN KRNIC.net. +NS1 IN A 202.30.50.51 +NS IN A 202.30.50.50 +$ORIGIN UNI2.net. +NS2 IN A 195.82.195.99 +NS IN A 129.142.7.99 +$ORIGIN GTLD-SERVERS.net. +K IN A 213.177.194.5 +A IN A 198.41.3.38 +B IN A 203.181.106.5 +M IN A 202.153.114.101 +C IN A 205.188.185.18 +D IN A 208.206.240.5 +E IN A 207.200.81.69 +F IN A 198.17.208.67 +G IN A 198.41.3.101 +I IN A 192.36.144.133 +J IN A 210.132.100.101 +$ORIGIN dns.swip.net. +kista IN A 192.71.220.9 +$ORIGIN RCPIP.net. +EKEKO IN A 209.45.127.2 +$ORIGIN UNA.net. +ENGINE1 IN A 208.136.52.74 +$ORIGIN hcr.net. +ns IN A 208.240.246.4 +$ORIGIN NSIREGISTRY.net. +NS2 IN A 198.41.3.108 +$ORIGIN SUBTEND.net. +NAVI IN A 208.186.117.224 +NS1 IN A 208.186.117.71 +$ORIGIN IAD.GBLX.net. +NAME IN A 204.152.166.155 +$ORIGIN PHX.GBLX.net. +NAME IN A 206.165.6.10 +$ORIGIN ROC.GBLX.net. +NAME IN A 209.130.187.10 +$ORIGIN SHOREHAM.net. +pop IN CNAME shoreham.net. +$ORIGIN GREENMOUNTAINACCESS.net. +NS2 IN A 208.144.252.31 +NS1 IN A 208.144.252.30 +$ORIGIN MINDSPRING.net. +SCRATCHY IN A 207.69.200.211 +ITCHY IN A 207.69.200.210 +$ORIGIN RIPN.net. +NS2 IN A 195.209.0.6 +NS IN A 194.85.119.1 +$ORIGIN CWCI.net. +NS0 IN A 194.6.79.162 +$ORIGIN GBMTECH.net. +NS2 IN A 208.243.164.3 +NS1 IN A 208.243.164.2 +$ORIGIN vrx.net. +pedic-med IN A 199.166.24.2 +ns2 IN A 65.196.80.102 +ns3 IN A 199.166.24.3 +ns1 IN A 199.166.24.1 + IN A 216.13.76.2 +$ORIGIN globalnetisp.net. +NS2 IN A 207.136.213.2 +NS1 IN A 207.136.213.1 +$ORIGIN MYNET.net. +FAITH IN A 207.13.11.2 +$ORIGIN ADNS.net. +NS2 IN A 199.5.157.3 +KOVU IN A 199.5.157.52 +NS1 IN A 199.5.157.2 +$ORIGIN DIEBOLD.net. +NS1 IN A 65.196.80.10 +$ORIGIN JPS.net. +NS2 IN A 216.224.156.252 +NS1 IN A 216.119.0.192 +$ORIGIN NETNAMES.net. +NS2 IN A 212.53.77.28 +NS1 IN A 212.53.64.60 +$ORIGIN RIO.net. +ORSTOM IN A 192.33.151.1 +$ORIGIN com. +sherickpm IN MX 10 inbound.sherickpm.com.criticalpath.net. +ultradevices IN A 209.249.61.20 +verisign IN A 205.139.94.60 +vermontel IN A 204.164.106.2 + IN MX 0 pop.vermontel.net. +TOPICA IN A 206.132.75.196 +unknown IN A 168.143.148.168 +vietmercury IN A 207.1.134.34 +moonmothers IN A 24.218.253.157 + IN MX 10 costorf.ne.mediaone.net. +vhv IN MX 0 mail.vhv.com. +BURSTNET IN MX 15 mail.ar.com. + IN MX 5 ibd.ar.com. +velco IN A 207.217.96.41 + IN A 207.217.96.42 + IN A 207.217.96.43 + IN A 207.217.96.44 + IN A 207.217.96.45 + IN A 207.217.96.28 + IN A 207.217.96.29 + IN A 207.217.96.30 + IN A 207.217.96.31 + IN A 207.217.96.32 + IN A 207.217.96.33 + IN A 207.217.96.34 + IN A 207.217.96.35 + IN A 207.217.96.36 + IN A 207.217.96.37 + IN A 207.217.96.38 + IN A 207.217.96.39 + IN A 207.217.96.40 + IN MX 10 mail.velco.com. +ffic IN A 64.84.58.128 + IN MX 5 mail.mailconnect.com. +overstock IN A 64.78.130.251 +madriver IN MX 10 bend.madriver.com. +catic1 IN MX 10 Mail.catic1.com. + IN MX 20 smtp-Relay.CTCCom.net. +goldstats IN A 66.33.12.17 +nominum IN A 204.152.184.170 +hill IN A 208.162.106.6 + IN MX 20 mail.hill.com. +garmontusa IN MX 20 mail.garmontusa.com. +bt IN A 62.7.244.127 +xraylitho IN MX 10 mail.sover.net. + IN MX 20 mqueue.sover.net. +glaxowellcome IN MX 10 firewall1.glaxowellcome.com. + IN MX 10 firewall3.glaxowellcome.com. +nova-data IN A 64.70.144.14 + IN MX 10 mail.nova-data.com. +AVENUEA IN MX 100 mail2.louisdreyfus.co.uk. + IN MX 10 ldfwsvr2.l-dreyfus.com. + IN MX 50 ldfwsvr02-hme1.l-dreyfus.com. + IN MX 75 mail.louisdreyfus.co.uk. +best IN MX 10 mail1.best.com. + IN MX 10 mail2.best.com. + IN MX 20 mail3.best.com. + IN MX 20 mail4.best.com. +biketrack IN MX 20 mqueue.sover.net. + IN MX 10 mail.sover.net. +ilovedomain IN A 211.175.164.170 +symquest IN A 64.69.102.131 + IN MX 10 Quest-7.symquest.com. +QUEST-NET IN A 207.140.30.11 + IN MX 5 mail.quest-net.com. +cacheware IN A 209.128.82.20 +Algebra IN A 208.233.99.160 +gmcr IN A 12.34.108.130 + IN MX 10 gateway1.gmcr.com. +YAHOO IN A 216.115.108.243 + IN A 216.115.108.245 +ogud IN MX 90 smtp.elistx.com. + IN MX 10 mail.dc.ogud.com. +costorf IN A 24.218.253.157 + IN MX 10 costorf.ne.mediaone.net. +highmeadow IN A 207.136.209.6 + IN MX 10 hm6.vt.highmeadow.com. + IN MX 20 mqueue.sover.net. +broadsoft IN A 208.39.36.48 +cmates IN MX 10 popmail.u-net.com. +mt-mansfield IN A 208.153.85.16 + IN MX 10 mail.pshift.net. + IN MX 30 pomail.pshift.com. +skiinsurance IN MX 10 mail.skiinsurance.com. + IN MX 20 etrn.sover.net. +map IN A 206.98.40.150 +idx IN MX 30 isdev.idx.com. + IN MX 50 drawbridge.idx.com. + IN MX 10 idx.idx.com. + IN MX 20 bvtsweeper.idx.com. +msgbox IN A 216.71.82.42 +sleepycat IN A 192.41.61.122 +cisco IN A 198.133.219.25 + IN MX 10 proxy2.cisco.com. + IN MX 10 proxy3.cisco.com. + IN MX 20 proxy6.cisco.com. + IN MX 20 proxy9.cisco.com. + IN MX 10 proxy1.cisco.com. +TOAPLAN IN A 216.42.31.169 +hometownbands IN A 209.67.235.38 +smuggs IN MX 10 mail.smuggs.com. +clothncanvas IN A 208.153.85.16 + IN MX 10 mail.pshift.net. + IN MX 30 mail.pshift.com. +quantified IN A 63.212.171.4 +arabia IN A 216.251.232.40 +bostic IN A 199.103.241.218 +verisign-grs IN A 198.41.3.55 +gdarm IN MX 10 bvt-ext.gdarm.com. +retro IN A 205.179.181.194 + IN MX 10 gw.retro.com. + IN MX 20 www.retro.com. + IN MX 50 mail.scruznet.com. +vssg IN A 216.157.26.252 +jerusalem-mail IN A 216.251.232.93 + IN MX 10 mail.jerusalem-mail.com. +tfm IN MX 50 mtbaker.tfm.com. + IN MX 20 mailhost.tfm.com. +fratfunz IN A 216.226.16.150 +elektro IN A 192.188.133.3 +WonderWorks IN A 192.203.206.65 + IN MX 50 mail.wonderworks.com. +fiberia IN MX 10 webmail.fiberia.com. +tifosi IN MX 10 gutenberg.bucksnet.com. +ivillage IN A 209.185.162.150 +pwshift IN A 208.153.85.36 +goputney IN MX 10 mail.sover.net. + IN MX 20 mqueue.sover.net. +$ORIGIN IPNS.com. +NS2 IN A 63.230.183.1 +NS IN A 208.187.190.2 +$ORIGIN appliedtheory.com. +NS2 IN A 168.75.17.11 +NS1 IN A 204.168.28.9 +ns3 IN A 207.127.101.8 +$ORIGIN COMPUWARE.com. +nl IN MX 150 uucp.nl.net. + IN MX 50 bitbucket.extern.uniface.nl. + IN MX 100 smtp.nl.net. +$ORIGIN YOUR-DOMAIN.com. +NS2 IN A 216.167.31.177 +NS1 IN A 216.167.31.176 +$ORIGIN nortelnetworks.com. +NS-RCH IN A 192.135.215.2 +NS-OTT IN A 192.58.194.71 +ns-har IN A 192.100.101.3 +$ORIGIN SJMERCURY.com. +BAYONET IN A 207.1.134.34 +$ORIGIN excite.com. +NSE00 IN A 198.3.102.250 +NS00 IN A 198.3.98.250 +NSE01 IN A 198.3.102.251 +NS01 IN A 198.3.98.251 +$ORIGIN PLANET-THREE.com. +NS0 IN A 212.49.219.164 +$ORIGIN TOKYO.JP.NETDNS.com. +NS1 IN A 64.56.164.118 +$ORIGIN LONDON.UK.NETDNS.com. +NS1 IN A 212.62.6.38 +$ORIGIN SANFRANCISCO.US.NETDNS.com. +NS1 IN A 207.82.50.166 +$ORIGIN NEWYORK.US.NETDNS.com. +NS1 IN A 216.32.212.86 +$ORIGIN SEATTLE.US.NETDNS.com. +NS1 IN A 206.253.214.13 +$ORIGIN ARICATRA.com. +NS IN A 206.64.112.114 +$ORIGIN REGME.com. +NS1 IN A 207.153.57.14 +$ORIGIN ELISTX.com. +smtp IN A 209.116.252.130 +NS IN A 209.116.252.130 +$ORIGIN SIGMAHOSTING.com. +NS1 IN A 209.241.86.6 +$ORIGIN champcable.com. +CCC IN A 207.41.53.11 +$ORIGIN IAFRICA.com. +NS1 IN A 196.7.0.139 +NS3 IN A 196.7.0.137 +$ORIGIN dot-god.com. +A-GTLD-SERVERS IN A 205.189.73.123 +B-GTLD-SERVERS IN A 205.189.71.10 +$ORIGIN CONRADPROMOTIONS.com. +NS2 IN A 208.24.118.203 +NS1 IN A 208.158.96.118 +$ORIGIN onemain.com. +ns4 IN A 63.208.210.11 +NS2 IN A 166.90.148.68 +NS1 IN A 166.90.148.67 +ns3 IN A 63.208.210.10 +$ORIGIN SIMORGH.com. +NS1 IN A 209.1.163.10 +$ORIGIN Christ.com. +Yeshua IN A 207.54.4.5 +Abba IN A 63.229.15.59 +$ORIGIN TRAVELPHOTOCONTESTS.com. +www IN A 64.85.86.156 +$ORIGIN WEB2010.com. +NS4 IN A 216.157.55.6 +NS2 IN A 216.157.79.246 +NS3 IN A 216.157.47.6 +NS IN A 209.235.31.149 +$ORIGIN 2DAY.com. +NS2 IN A 202.89.128.74 +NS1 IN A 202.37.240.13 +NS3 IN A 209.240.128.25 +$ORIGIN NETSCAPE.com. +tdns-me1 IN A 205.188.247.67 +tdns-me2 IN A 205.188.247.68 +tdns2 IN A 207.200.77.53 +tdns3 IN A 207.200.73.72 +NS IN A 198.95.251.10 +NS2 IN A 207.200.73.80 +$ORIGIN WWEBSVS.com. +PAPPILLOMA IN A 209.233.37.10 +$ORIGIN vermontel.com. +ns1 IN A 204.164.106.2 +$ORIGIN LA.TIS.com. +RELAY IN A 198.51.22.11 +$ORIGIN MSEN.com. +DNS IN A 148.59.19.11 +$ORIGIN bungi.com. +DAVER IN A 206.14.228.2 + IN A 207.126.97.2 +max IN A 206.14.228.7 + IN A 207.126.97.7 +$ORIGIN SPEEDHOST.com. +NS2 IN A 216.42.31.169 +NS3 IN A 216.42.31.130 +$ORIGIN GPG.com. +NS2 IN A 209.1.163.50 +NS1 IN A 209.1.163.30 +$ORIGIN NL.CONCENTRIC.com. +NS1 IN A 195.18.114.5 +$ORIGIN SJC.LYCOS.com. +SJC-NS2 IN A 206.79.171.40 +SJC-NS1 IN A 206.79.171.39 +$ORIGIN BOS.LYCOS.com. +BOS-NS2 IN A 209.67.228.40 +BOS-NS1 IN A 209.67.228.39 +$ORIGIN TOPICA.com. +NS3 IN A 206.111.131.72 +ns-ext IN A 206.132.75.195 +inmta011 IN A 206.132.75.197 +inmta009 IN A 206.132.75.226 +dns IN A 206.111.131.72 +outmta004 IN A 206.132.75.201 +inmta001 IN A 206.132.75.197 + IN A 206.111.131.79 +inmta003 IN A 206.132.75.213 +outmta010 IN A 206.132.75.222 +inmta005 IN A 206.132.75.217 +NS1 IN A 206.132.75.195 +NS2 IN A 208.184.76.200 +$ORIGIN DOLEH.com. +NS IN A 204.255.25.63 +$ORIGIN BSDI.com. +NS IN A 207.174.116.8 +$ORIGIN NYTIMES.com. +GATEKEEPER IN A 199.181.175.201 +$ORIGIN GDGSC.com. +NS0 IN A 192.160.62.66 +NS2 IN A 204.162.124.66 +$ORIGIN EDIGITALS.com. +NS2 IN A 211.39.139.36 +NS3 IN A 211.175.164.170 +NS1 IN A 211.39.139.35 +$ORIGIN INTERNETSQUARE.com. +NS2 IN A 205.227.232.9 +NS1 IN A 216.226.16.146 +$ORIGIN MAIL.com. +NS2 IN A 165.251.1.3 +GTLD IN A 165.251.1.239 +NS1 IN A 165.251.1.2 +$ORIGIN moonmothers.com. +localhost IN A 127.0.0.1 +www IN CNAME moonmothers.com. +$ORIGIN vhv.com. +mail IN A 208.5.161.11 +$ORIGIN BOCA15-VERIO.com. +NS15B IN A 208.55.91.51 +NS15A IN A 208.55.91.50 +$ORIGIN ar.com. +ns2 IN A 64.124.80.42 +ibd IN A 63.194.205.75 +mail IN A 63.194.205.74 +NS1 IN A 63.194.205.74 +$ORIGIN BLIPP.com. +VIC20 IN A 195.163.165.35 +$ORIGIN CONCOURSE.com. +NS IN A 199.218.113.2 +$ORIGIN velco.com. +mail IN A 198.136.217.106 +$ORIGIN FLONETWORK.com. +UUNS1DNS1 IN A 209.167.79.5 +UUNS1DNS2 IN A 209.167.79.6 +$ORIGIN overstock.com. +NS1 IN A 207.225.194.13 +$ORIGIN NEWACCOUNT.com. +NS4 IN A 209.78.16.6 +NS2 IN A 209.78.16.5 +NS3 IN A 216.121.32.205 +NS IN A 216.121.32.10 +$ORIGIN tridog.com. +NS2 IN A 206.168.112.51 +TRIDOG1 IN A 206.168.112.71 +$ORIGIN madriver.com. +bend IN A 207.136.232.15 +FUSION IN A 207.136.232.11 +PRIMUS IN A 207.136.232.12 +$ORIGIN catic1.com. +Mail IN A 207.190.204.103 +$ORIGIN IBD.com. +NIC IN A 209.249.61.18 +$ORIGIN IOM.com. +PEBBLES IN A 194.72.124.1 +$ORIGIN nominum.com. +shell IN A 204.152.187.59 +GNS2 IN A 198.133.199.2 +gns1 IN A 198.133.199.1 +$ORIGIN ATLONLINE.com. +ATLNET IN A 207.153.72.193 +ATLWEB1 IN A 207.153.72.194 +$ORIGIN hill.com. +SYRUP IN A 208.162.106.3 +$ORIGIN garmontusa.com. +mail IN A 64.30.8.178 +$ORIGIN VIX.com. +NS-EXT IN A 204.152.184.64 +ns-int IN A 204.152.184.65 +$ORIGIN rc.VIX.com. +db IN A 204.152.187.21 +$ORIGIN SOVAM.com. +NS IN A 194.67.2.97 +$ORIGIN IOS.com. +NOC IN A 198.4.75.69 +$ORIGIN BOSTON.juno.com. +NS IN A 64.136.25.53 +$ORIGIN JERSEY.juno.com. +NS IN A 64.136.17.178 +$ORIGIN NYC.juno.com. +NS IN A 205.231.108.1 +$ORIGIN MEITCA.com. +NS1 IN A 137.203.5.1 +$ORIGIN glaxowellcome.com. +firewall3 IN A 192.58.204.207 +firewall1 IN A 192.58.204.204 +NS IN A 192.58.204.113 +$ORIGIN EPILOGUE.com. +QUERN IN A 128.224.1.136 +$ORIGIN CLASSIFIEDMONSTER.com. +NS1 IN A 216.254.54.22 +$ORIGIN nova-data.com. +mail IN A 12.16.110.35 +$ORIGIN corning.com. +GATEKEEPER IN A 149.42.1.2 +$ORIGIN a1.YIMG.com. +us IN CNAME a32.g.a.yimg.com. +$ORIGIN i1.YIMG.com. +us IN CNAME a1.g.a.yimg.com. +$ORIGIN nc.us.IBM.com. +e24 IN A 32.97.136.230 +e22 IN A 32.97.136.228 +e23 IN A 32.97.136.229 +e21 IN A 32.97.136.227 +$ORIGIN co.us.IBM.com. +e34 IN A 32.97.110.132 +e32 IN A 32.97.110.130 +e33 IN A 32.97.110.131 +e31 IN A 32.97.110.129 +$ORIGIN ny.us.IBM.com. +e4 IN A 32.97.182.104 +e2 IN A 32.97.182.102 +e3 IN A 32.97.182.103 +e1 IN A 32.97.182.101 +$ORIGIN AUSTIN.IBM.com. +NS IN A 192.35.232.34 +$ORIGIN ZURICH.IBM.com. +INTERNET-SERVER IN A 195.212.119.252 +$ORIGIN ALMADEN.IBM.com. +NS IN A 198.4.83.35 +$ORIGIN ERS.IBM.com. +NS IN A 204.146.173.35 +$ORIGIN WATSON.IBM.com. +NS IN A 198.81.209.2 +$ORIGIN DCCSERVER.com. +GODFEVER IN A 208.137.22.6 +$ORIGIN SUN.com. +saturn IN A 192.9.25.2 +venus IN A 192.9.25.5 +east IN MX 40 mars.sun.com. + IN MX 40 mondzo.sun.com. + IN MX 5 venus.sun.com. + IN MX 5 lukla.sun.com. + IN MX 5 saturn.sun.com. + IN MX 5 patan.sun.com. + IN MX 15 mercury.sun.com. +mondzo IN A 192.18.100.1 +lukla IN A 192.18.98.31 +NS-BRM IN A 192.18.99.5 +ns-os IN A 192.9.9.6 +patan IN A 192.18.98.43 +mars IN A 192.9.22.1 +mercury IN A 192.9.25.1 +NS IN A 192.9.9.3 +$ORIGIN pr.SUN.com. +ns1 IN A 192.18.16.2 +$ORIGIN eu.SUN.com. +ns1 IN A 192.18.240.8 +$ORIGIN USEC.SUN.com. +NS IN A 192.9.48.3 +$ORIGIN PSHIFT.com. +ns2 IN A 208.153.85.21 +NS1 IN A 208.153.85.20 +$ORIGIN mobydark.com. +ns1 IN A 216.13.76.21 +$ORIGIN compuserve.com. +DUB-NAME-SVC-1 IN A 149.174.213.5 +ARL-NAME-SVC-1 IN A 149.174.211.5 +$ORIGIN NS.cs.com. +DNS-02 IN A 205.188.157.235 +DNS-01 IN A 152.163.159.235 +$ORIGIN pcode.com. +ns1 IN A 216.15.192.135 +$ORIGIN AVENUEA.com. +EX2-DNS0 IN A 216.34.88.20 +SEA2DNS IN A 63.251.8.150 +$ORIGIN PHOTOTRUST.com. +Filer IN A 64.85.86.172 +NS02 IN A 64.85.86.142 +www IN A 64.85.86.151 +NS01 IN A 64.85.86.141 +$ORIGIN GOOGLE.com. +HEDNS1 IN A 64.209.200.10 +helbdns IN A 64.209.200.252 +valbdns IN A 216.239.37.252 +exlbdns IN A 64.208.34.252 +sulbdns IN A 64.208.32.252 +NS IN A 209.185.108.134 +sjlbdns IN A 216.239.35.252 +NS2 IN A 209.185.108.135 +$ORIGIN ns0.com. +NS00 IN A 216.92.60.60 +ns0 IN A 209.197.64.1 +$ORIGIN best.com. +NS3 IN A 209.24.149.42 +mail2 IN A 206.184.139.12 + IN A 206.184.139.13 + IN A 206.184.139.16 + IN A 206.184.139.18 +mail3 IN A 206.184.139.12 + IN A 206.184.139.13 + IN A 206.184.139.16 + IN A 206.184.139.18 +mail4 IN A 206.184.139.12 + IN A 206.184.139.13 + IN A 206.184.139.16 + IN A 206.184.139.18 +NS1 IN A 209.24.149.41 +mail1 IN A 206.184.139.12 + IN A 206.184.139.13 + IN A 206.184.139.16 + IN A 206.184.139.18 +NS2 IN A 209.157.102.11 +$ORIGIN WESTOL.com. +NS IN A 63.93.137.4 +$ORIGIN ilovedomain.com. +ns IN A 211.175.164.170 +$ORIGIN symquest.com. +Quest-7 IN A 64.69.102.131 +$ORIGIN QUEST-NET.com. +mail IN A 207.140.30.11 +NS2 IN A 207.140.30.13 +NS1 IN A 207.140.30.11 +$ORIGIN cavebear.com. +p2 IN A 199.184.128.35 +npax IN A 192.203.17.71 +$ORIGIN cacheware.com. +ns1 IN A 64.221.210.242 +$ORIGIN Algebra.com. +ns3 IN A 216.254.54.22 +ns1 IN A 160.79.196.177 +NS5 IN A 208.233.99.161 +$ORIGIN gmcr.com. +gateway1 IN A 12.34.108.130 +$ORIGIN YAHOO.com. +NS1 IN A 204.71.200.33 +$ORIGIN EUROPE.YAHOO.com. +NS3 IN A 217.12.4.71 +$ORIGIN DCX.YAHOO.com. +NS5 IN A 216.32.74.10 +$ORIGIN GRANITECANYON.com. +NS2 IN A 204.1.217.148 +NS1 IN A 205.166.226.38 +$ORIGIN costorf.com. +localhost IN A 127.0.0.1 +www IN CNAME costorf.com. +$ORIGIN PSG.com. +RAIN IN A 147.28.0.34 +RIP IN A 147.28.0.39 +$ORIGIN vt.highmeadow.com. +hm6 IN A 207.136.209.6 +$ORIGIN btinternet.com. +DNS2 IN A 194.73.73.94 +DNS1 IN A 194.73.73.95 +$ORIGIN INTERNET-TOOLS.com. +NS2 IN A 206.109.113.140 +NS IN A 208.239.1.2 +NS3 IN A 38.153.179.2 +$ORIGIN CADABRA.com. +NS2 IN A 209.157.194.109 +NS IN A 209.143.240.148 +$ORIGIN SLOWMOE.com. +NS2 IN A 137.118.8.50 +NS1 IN A 137.118.8.49 +$ORIGIN ZTNET.com. +NS2 IN A 63.211.17.252 +NS1 IN A 63.211.17.251 +$ORIGIN HOTWIRED.com. +NS2 IN A 209.185.151.6 +NS4 IN A 209.185.151.4 +NS1 IN A 216.32.228.8 +NS3 IN A 216.32.228.9 +$ORIGIN g-world.com. +NS1 IN A 216.26.39.10 +$ORIGIN alcatrazmedia.com. +ns1 IN A 167.160.132.2 +$ORIGIN MESSAGESECURE.com. +KYNSE02 IN A 216.142.252.201 +KYNSE01 IN A 216.142.252.199 +$ORIGIN HAITIWORLD.com. +APPSRV IN A 206.152.15.34 +NS IN A 206.152.15.33 +$ORIGIN NETSOL.com. +NS2 IN A 198.17.208.71 +RS0 IN A 216.168.224.206 +NS3 IN A 216.168.224.201 +NS1 IN A 216.168.224.200 +$ORIGIN cmates.com. +NS-AUTH2 IN A 208.23.213.3 +ns-auth1 IN A 208.23.213.2 +$ORIGIN skiinsurance.com. +mail IN A 207.136.205.152 +$ORIGIN GH.com. +AUSTIN IN A 196.3.64.1 +$ORIGIN DIGISERVE.com. +NS2 IN A 204.91.84.216 +NS1 IN A 151.196.69.5 +$ORIGIN map.com. +sgi1 IN A 204.71.19.20 +WORMHOLE IN A 204.71.19.10 +$ORIGIN SNS-UT.DEBIS.com. +NS2 IN A 53.122.2.10 +$ORIGIN SNS-FELB.DEBIS.com. +NS1 IN A 53.122.1.10 +$ORIGIN idx.com. +seaipsvcs IN A 172.22.64.42 +BOSDOC IN A 198.114.171.109 +drawbridge IN A 204.165.241.2 +IDXNMS IN A 204.165.242.7 +idx IN A 198.114.171.160 +isdev IN A 198.181.234.9 +bvtipsvcs IN A 198.114.172.50 +bosdns IN A 198.114.171.109 +bvtsweeper IN A 198.181.234.69 +$ORIGIN VERITAS.com. +NS IN A 204.177.156.38 +$ORIGIN BFG.com. +gateway2 IN A 166.102.214.66 +aisvt IN MX 0 gateway2.bfg.com. +GATEWAY IN A 131.187.253.2 +$ORIGIN sleepycat.com. +abyssinian IN A 199.103.241.218 +$ORIGIN cisco.com. +proxy6 IN A 203.41.198.245 +proxy9 IN A 192.135.250.71 +proxy1 IN A 192.31.7.88 +proxy2 IN A 192.31.7.89 +proxy3 IN A 192.31.7.90 +ns1 IN A 128.107.241.185 +NS2 IN A 192.135.250.69 +$ORIGIN TOAPLAN.com. +www IN A 216.42.31.169 +$ORIGIN INTUIT.com. +DNS1 IN A 208.157.255.4 +$ORIGIN REGEX.com. +NS1 IN A 202.152.12.227 +$ORIGIN DEC.com. +crl IN A 192.58.206.2 +ns IN A 204.123.2.42 +$ORIGIN PA.DEC.com. +UUCP-GW-2 IN A 16.1.0.19 +UUCP-GW-1 IN A 16.1.0.18 + IN A 204.123.2.18 +$ORIGIN LANDLORDS.com. +NS IN A 63.64.164.68 +$ORIGIN hometownbands.com. +www IN A 209.67.235.38 +$ORIGIN MSFT.AKADNS.com. +Z6 IN A 207.229.152.20 +Z2 IN A 32.96.80.17 +Z4 IN A 208.148.96.220 +Z7 IN A 213.161.66.158 +Z3 IN A 63.215.198.67 +Z1 IN A 216.32.118.104 +$ORIGIN smuggs.com. +mail IN A 209.67.230.71 +$ORIGIN OUTREMER.com. +MANTA IN A 213.16.1.106 +$ORIGIN hns.com. +HNS3 IN A 208.236.67.3 +$ORIGIN TRIVALLEY.com. +NS3 IN A 206.25.132.30 +$ORIGIN AI-R.com. +NS2 IN A 66.33.4.51 +NS1 IN A 66.33.0.143 +$ORIGIN ALCATEL.com. +NS IN A 192.160.6.91 +PRIMARY IN A 192.160.6.90 +$ORIGIN GENDYN.com. +NET2 IN A 204.60.171.9 +NET1 IN A 204.60.171.8 +$ORIGIN ONLINEPHOTOCONTEST.com. +www IN A 64.85.86.152 +$ORIGIN performancediver.com. +listserv IN A 216.34.185.155 +$ORIGIN rge.com. +gw IN A 157.225.178.11 +$ORIGIN NS.AOL.com. +DNS-02 IN A 205.188.157.232 +DNS-01 IN A 152.163.159.232 +$ORIGIN MANY-PATHS-ENERGY-ENHANCEMENT.com. +www IN A 66.33.4.50 +$ORIGIN IS.CHRYSLER.com. +FXCLPR02 IN A 204.189.94.37 +FXIOD01 IN A 204.189.94.70 +$ORIGIN TO.GD-ES.com. +NS IN A 199.107.240.66 +$ORIGIN GNAC.com. +ns2 IN A 209.182.195.77 +NS1 IN A 209.182.195.77 +$ORIGIN AKAMAI.com. +YA IN A 204.178.118.68 +ACCESS IN A 4.17.143.9 +YB IN A 204.212.232.16 +YC IN A 209.246.46.48 +YD IN A 209.189.112.39 +YE IN A 192.215.168.18 +YF IN A 216.32.118.14 +YG IN A 204.178.110.35 +YH IN A 128.11.61.225 +$ORIGIN QUICKEN.com. +DNS4 IN A 198.3.99.252 +DNS2 IN A 206.154.105.67 +news IN MX 10 mail1.emailpub.com. + IN MX 10 mail2.emailpub.com. + IN MX 10 mail3.emailpub.com. + IN MX 10 mail4.emailpub.com. + IN MX 10 mail5.emailpub.com. + IN MX 10 mail6.emailpub.com. + IN A 207.211.106.100 +DNS3 IN A 198.3.96.252 +DNS1 IN A 206.154.105.66 +$ORIGIN LUXNOC.com. +NS4 IN A 195.206.104.201 +NS2 IN A 195.206.105.102 +NS0 IN A 195.206.105.1 +NS5 IN A 195.206.104.211 +NS3 IN A 195.206.104.1 +NS1 IN A 195.206.105.101 +$ORIGIN MAGIC-MOMENTS.com. +NS1 IN A 195.224.53.80 +$ORIGIN ABAC.com. +NS2 IN A 216.55.144.4 +NS1 IN A 216.55.128.4 +$ORIGIN GOTO.com. +NS2 IN A 204.71.128.137 +NS1 IN A 206.132.152.241 +$ORIGIN WEBTRENDS.com. +NS2 IN A 63.88.212.11 +NS1 IN A 63.88.212.10 +$ORIGIN hotmail.com. +NS3 IN A 209.185.130.68 +NS1 IN A 216.200.206.140 +$ORIGIN MERCHANTWARE.com. +NS2 IN A 209.170.142.35 +$ORIGIN MERCURYCENTER.com. +cgi IN CNAME vh80167.vh8.infi.net. +$ORIGIN CARIBSURF.com. +COL2 IN A 205.214.192.202 +COL1 IN A 205.214.192.201 +$ORIGIN MAIL-LIST.com. +zip IN MX 20 sluice.mail-list.com. + IN MX 20 pipeline.mail-list.com. + IN MX 20 transport.mail-list.com. + IN MX 50 swifty.mail-list.com. + IN MX 50 velocity.mail-list.com. + IN MX 50 brisk.mail-list.com. + IN MX 5 zip.mail-list.com. +$ORIGIN NAVPOINT.com. +south IN A 207.106.42.12 +north IN A 207.106.42.10 +NS2 IN A 207.106.42.12 +NS IN A 207.106.42.10 +$ORIGIN verisign-grs.com. +ns2 IN A 198.41.3.108 +ns1 IN A 198.41.3.39 +$ORIGIN gdarm.com. +bvt-ext IN A 166.19.32.42 +$ORIGIN REDHAT.com. +NS1 IN A 216.148.218.250 +$ORIGIN SKYNETWEB.com. +NS2 IN A 208.231.1.35 +NS1 IN A 208.231.1.34 +$ORIGIN COIL.com. +BRONZE IN A 198.4.94.1 +$ORIGIN ZTX.COMPAQ.com. +NS1-PUBLIC IN A 161.114.1.204 +$ORIGIN ZMA.COMPAQ.com. +NS1-PUBLIC IN A 161.114.64.24 +$ORIGIN FOOL.com. +NS2 IN A 208.51.76.222 +NS1 IN A 208.241.66.222 +$ORIGIN retro.com. +www IN A 205.179.181.195 +gw IN A 205.179.181.194 +$ORIGIN NRSITE.com. +NS5 IN A 208.178.169.4 +NS7 IN A 206.41.20.3 +NS3 IN A 199.172.144.20 +$ORIGIN jerusalem-mail.com. +mail IN A 216.251.232.93 +$ORIGIN PAIR.com. +ns3 IN A 209.68.1.15 +NS1 IN A 209.68.1.11 +$ORIGIN GLOBALDNS.com. +NS1 IN A 206.253.214.11 +$ORIGIN tfm.com. +mailhost IN A 192.231.224.11 +mtbaker IN A 192.231.224.2 +NS2 IN A 208.236.160.42 +NS1 IN A 209.83.142.82 +NS IN A 192.231.224.1 +$ORIGIN bock.com. +NS2 IN A 64.30.29.4 +NS1 IN A 64.30.29.3 +$ORIGIN TARSUS.com. +MAIL IN A 208.130.9.252 +BEAR IN A 208.130.9.248 +$ORIGIN NETANET.com. +NS0 IN A 194.6.96.218 + IN A 195.172.127.72 +NS1 IN A 194.6.96.218 +$ORIGIN SEANET.com. +DNS2 IN A 199.181.164.2 +DNS3 IN A 199.181.164.3 +DNS1 IN A 199.181.164.1 +$ORIGIN INTERNETSHARE.com. +NS1 IN A 63.207.108.53 +$ORIGIN ALTAVISTA.com. +NS2 IN A 209.73.164.7 +NS3 IN A 209.73.176.204 +NS1 IN A 209.73.164.76 +$ORIGIN NOVELL.com. +NS IN A 137.65.1.1 +$ORIGIN SAIPAN.com. +NS2 IN A 202.128.28.2 +NS IN A 202.128.27.2 +$ORIGIN diebold.com. +eliot IN A 204.151.249.21 +ness IN A 208.228.181.21 +$ORIGIN WonderWorks.com. +mail IN A 192.203.206.67 +ice IN A 192.203.206.9 +$ORIGIN SIGNALZ.com. +NS IN A 209.67.230.71 +$ORIGIN GW.tislabs.com. +RELAY IN A 192.94.214.100 +$ORIGIN CAIS.com. +NS IN A 205.177.10.10 +$ORIGIN tesserae.com. +ns2 IN A 209.157.194.3 +NS IN A 209.157.194.2 +$ORIGIN NETPOLICY.com. +MINION IN A 207.87.121.66 +$ORIGIN wirbel.com. +enterprise IN A 194.231.54.2 +$ORIGIN fiberia.com. +webmail IN A 216.55.147.2 +$ORIGIN BAYAREA.com. +www IN CNAME vh80040.vh8.infi.net. +$ORIGIN CONNACTIVITY.com. +bparker IN A 206.34.200.200 +NS2 IN A 206.34.200.3 +CONNACTIVITY IN A 206.34.200.2 +$ORIGIN tifosi.com. +BK IN A 208.58.189.13 +daytona IN A 192.104.156.3 +$ORIGIN bucksnet.com. +gutenberg IN A 207.113.15.5 +$ORIGIN ivillage.com. +NS2 IN A 209.185.162.16 +NS1 IN A 209.185.162.15 +$ORIGIN codelocal.com. +ns1 IN A 216.15.192.130 +$ORIGIN NETFLIGHT.com. +DNS IN A 207.88.32.2 +$ORIGIN MERCHANTWARE.CON. +NS1 IN A 209.170.142.34 diff --git a/bin/tests/system/cacheclean/ns1/expire-test.db b/bin/tests/system/cacheclean/ns1/expire-test.db new file mode 100644 index 0000000..8085543 --- /dev/null +++ b/bin/tests/system/cacheclean/ns1/expire-test.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA hostmaster.ns ns ( + 2011072900 + 600 + 600 + 1200 + 3600 + ) + NS ns +ns IN A 10.53.0.1 diff --git a/bin/tests/system/cacheclean/ns1/flushtest.db b/bin/tests/system/cacheclean/ns1/flushtest.db new file mode 100644 index 0000000..ac6b408 --- /dev/null +++ b/bin/tests/system/cacheclean/ns1/flushtest.db @@ -0,0 +1,44 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +$ORIGIN flushtest.example. +@ IN SOA flushtest.example. ns.flushtest.example. ( + 2011072900 + 600 + 600 + 1200 + 3600 + ) + NS ns +ns IN A 10.53.0.1 + +top1 IN TXT "text" +second1.top1 IN TXT "text" +third1.second1.top1 IN TXT "text" +third2.second1.top1 IN TXT "text" +second2.top1 IN TXT "text" +second3.top1 IN TXT "text" + +; top2 node is omitted for testing with an empty nonterminal +second1.top2 IN TXT "text" +second2.top2 IN TXT "text" +second3.top2 IN TXT "text" + +top3 IN TXT "text" +second1.top3 IN TXT "text" +third1.second1.top3 IN TXT "text" +third2.second1.top3 IN TXT "text" +; second2.top3 is omitted for testing with an empty nontermianl +third1.second2.top3 IN TXT "text" +third2.second2.top3 IN TXT "text" +second3.top3 IN TXT "text" + diff --git a/bin/tests/system/cacheclean/ns1/named.args b/bin/tests/system/cacheclean/ns1/named.args new file mode 100644 index 0000000..43721b6 --- /dev/null +++ b/bin/tests/system/cacheclean/ns1/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 1 -D cacheclean-ns1 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/cacheclean/ns1/named.conf.j2 b/bin/tests/system/cacheclean/ns1/named.conf.j2 new file mode 100644 index 0000000..fa6fe27 --- /dev/null +++ b/bin/tests/system/cacheclean/ns1/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; + notify yes; + check-integrity no; + minimal-responses no; +}; + +zone "." { + type primary; + file "example.db"; +}; + +zone "flushtest.example" { + type primary; + file "flushtest.db"; +}; + +zone "expire-test" { + type primary; + file "expire-test.db"; +}; diff --git a/bin/tests/system/cacheclean/ns2/named.args b/bin/tests/system/cacheclean/ns2/named.args new file mode 100644 index 0000000..2482aad --- /dev/null +++ b/bin/tests/system/cacheclean/ns2/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 3 -D cacheclean-ns2 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/cacheclean/ns2/named.conf.j2 b/bin/tests/system/cacheclean/ns2/named.conf.j2 new file mode 100644 index 0000000..418209c --- /dev/null +++ b/bin/tests/system/cacheclean/ns2/named.conf.j2 @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + notify yes; + disable-empty-zone 127.IN-ADDR.ARPA; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "flushtest.example" { + type forward; + forwarders { 10.53.0.1; }; +}; + +zone "expire-test" { + type secondary; + primaries { 10.53.0.1; }; +}; diff --git a/bin/tests/system/cacheclean/tests.sh b/bin/tests/system/cacheclean/tests.sh new file mode 100755 index 0000000..9b27ec2 --- /dev/null +++ b/bin/tests/system/cacheclean/tests.sh @@ -0,0 +1,279 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +RNDCOPTS="-c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT}" +DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm \ + +nostat @10.53.0.2 -p ${PORT}" + +# fill the cache with nodes from flushtest.example zone +load_cache() { + # empty all existing cache data + $RNDC $RNDCOPTS flush + + # load the positive cache entries + $DIG $DIGOPTS -f - </dev/null 2>&1 +txt top1.flushtest.example +txt second1.top1.flushtest.example +txt third1.second1.top1.flushtest.example +txt third2.second1.top1.flushtest.example +txt second2.top1.flushtest.example +txt second3.top1.flushtest.example +txt second1.top2.flushtest.example +txt second2.top2.flushtest.example +txt second3.top2.flushtest.example +txt top3.flushtest.example +txt second1.top3.flushtest.example +txt third1.second1.top3.flushtest.example +txt third2.second1.top3.flushtest.example +txt third1.second2.top3.flushtest.example +txt third2.second2.top3.flushtest.example +txt second3.top3.flushtest.example +EOF + + # load the negative cache entries + # nxrrset: + $DIG $DIGOPTS a third1.second1.top1.flushtest.example >/dev/null + # nxdomain: + $DIG $DIGOPTS txt top4.flushtest.example >/dev/null + # empty nonterminal: + $DIG $DIGOPTS txt second2.top3.flushtest.example >/dev/null + + # sleep 2 seconds ensure the TTLs will be lower on cached data + sleep 2 +} + +dump_cache() { + rndc_dumpdb ns2 -cache _default +} + +clear_cache() { + $RNDC $RNDCOPTS flush +} + +in_cache() { + ttl=$($DIG $DIGOPTS "$@" | awk '{print $2}') + [ -z "$ttl" ] && { + ttl=$($DIG $DIGOPTS +noanswer +auth "$@" | awk '{print $2}') + [ "$ttl" -ge 3599 ] && return 1 + return 0 + } + [ "$ttl" -ge 3599 ] && return 1 + return 0 +} + +# Extract records at and below name "$1" from the cache dump in file "$2". +filter_tree() { + tree="$1" + file="$2" + perl -n -e ' + next if /^;/; + if (/'"$tree"'/ || (/^\t/ && $print)) { + $print = 1; + } else { + $print = 0; + } + print if $print; + ' "$file" +} + +n=$((n + 1)) +echo_i "check correctness of routine cache cleaning ($n)" +$DIG $DIGOPTS +tcp +keepopen -b 10.53.0.7 -f dig.batch >dig.out.ns2 || status=1 + +digcomp --lc dig.out.ns2 knowngood.dig.out || status=1 + +n=$((n + 1)) +echo_i "only one tcp socket was used ($n)" +tcpclients=$(awk '$3 == "client" && $5 ~ /10.53.0.7#[0-9]*:/ {print $5}' ns2/named.run | sort | uniq -c | wc -l) + +test $tcpclients -eq 1 || { + status=1 + echo_i "failed" +} + +n=$((n + 1)) +echo_i "reset and check that records are correctly cached initially ($n)" +ret=0 +load_cache +dump_cache +nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l) +[ $nrecords -eq 18 ] || { + ret=1 + echo_i "found $nrecords records expected 18" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing of the full cache ($n)" +ret=0 +clear_cache +dump_cache +nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | wc -l) +[ $nrecords -eq 0 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing of individual nodes (interior node) ($n)" +ret=0 +clear_cache +load_cache +# interior node +in_cache txt top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushname top1.flushtest.example +in_cache txt top1.flushtest.example && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing of individual nodes (leaf node, under the interior node) ($n)" +ret=0 +# leaf node, under the interior node (should still exist) +in_cache txt third2.second1.top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushname third2.second1.top1.flushtest.example +in_cache txt third2.second1.top1.flushtest.example && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing of individual nodes (another leaf node, with both positive and negative cache entries) ($n)" +ret=0 +# another leaf node, with both positive and negative cache entries +in_cache a third1.second1.top1.flushtest.example || ret=1 +in_cache txt third1.second1.top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushname third1.second1.top1.flushtest.example +in_cache a third1.second1.top1.flushtest.example && ret=1 +in_cache txt third1.second1.top1.flushtest.example && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing a nonexistent name ($n)" +ret=0 +$RNDC $RNDCOPTS flushname fake.flushtest.example || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing of namespaces ($n)" +ret=0 +clear_cache +load_cache +# flushing leaf node should leave the interior node: +in_cache txt third1.second1.top1.flushtest.example || ret=1 +in_cache txt top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushtree third1.second1.top1.flushtest.example +in_cache txt third1.second1.top1.flushtest.example && ret=1 +in_cache txt top1.flushtest.example || ret=1 +in_cache txt second1.top1.flushtest.example || ret=1 +in_cache txt third2.second1.top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushtree second1.top1.flushtest.example +in_cache txt top1.flushtest.example || ret=1 +in_cache txt second1.top1.flushtest.example && ret=1 +in_cache txt third2.second1.top1.flushtest.example && ret=1 + +# flushing from an empty node should still remove all its children +in_cache txt second1.top2.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushtree top2.flushtest.example +in_cache txt second1.top2.flushtest.example && ret=1 +in_cache txt second2.top2.flushtest.example && ret=1 +in_cache txt second3.top2.flushtest.example && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushing a nonexistent namespace ($n)" +ret=0 +$RNDC $RNDCOPTS flushtree fake.flushtest.example || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check the number of cached records remaining ($n)" +ret=0 +dump_cache +nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -v '^;' | grep -E '(TXT|ANY)' | wc -l) +[ $nrecords -eq 17 ] || { + ret=1 + echo_i "found $nrecords records expected 17" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check the check that flushname of a partial match works ($n)" +ret=0 +in_cache txt second2.top1.flushtest.example || ret=1 +$RNDC $RNDCOPTS flushtree example +in_cache txt second2.top1.flushtest.example && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check the number of cached records remaining ($n)" +ret=0 +dump_cache +nrecords=$(filter_tree flushtest.example ns2/named_dump.db.test$n | grep -E '(TXT|ANY)' | wc -l) +[ $nrecords -eq 1 ] || { + ret=1 + echo_i "found $nrecords records expected 1" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check flushtree clears adb correctly ($n)" +ret=0 +load_cache +dump_cache +mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.a +sed -n '/plain success\/timeout/,/Unassociated entries/p' \ + ns2/named_dump.db.test$n.a >sed.out.$n.a +grep 'plain success/timeout' sed.out.$n.a >/dev/null 2>&1 || ret=1 +grep 'ns.flushtest.example' sed.out.$n.a >/dev/null 2>&1 || ret=1 +$RNDC $RNDCOPTS flushtree flushtest.example || ret=1 +dump_cache +mv ns2/named_dump.db.test$n ns2/named_dump.db.test$n.b +sed -n '/plain success\/timeout/,/Unassociated entries/p' \ + ns2/named_dump.db.test$n.b >sed.out.$n.b +grep 'plain success/timeout' sed.out.$n.b >/dev/null 2>&1 || ret=1 +grep 'ns.flushtest.example' sed.out.$n.b >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check expire option returned from primary zone ($n)" +ret=0 +$DIG @10.53.0.1 -p ${PORT} +expire soa expire-test >dig.out.expire || ret=1 +grep EXPIRE: dig.out.expire >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check expire option returned from secondary zone ($n)" +ret=0 +$DIG @10.53.0.2 -p ${PORT} +expire soa expire-test >dig.out.expire || ret=1 +grep EXPIRE: dig.out.expire >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/cacheclean/tests_sh_cacheclean.py b/bin/tests/system/cacheclean/tests_sh_cacheclean.py new file mode 100644 index 0000000..780e2d7 --- /dev/null +++ b/bin/tests/system/cacheclean/tests_sh_cacheclean.py @@ -0,0 +1,25 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "sed.out.*", + "ns2/named_dump.db.*", + ] +) + + +def test_cacheclean(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/camp/ns1/named.conf.j2 b/bin/tests/system/camp/ns1/named.conf.j2 new file mode 100644 index 0000000..208a651 --- /dev/null +++ b/bin/tests/system/camp/ns1/named.conf.j2 @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/camp/ns1/root.db b/bin/tests/system/camp/ns1/root.db new file mode 100644 index 0000000..64c8ac5 --- /dev/null +++ b/bin/tests/system/camp/ns1/root.db @@ -0,0 +1,51 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +tld0. NS ns.tld0. +ns.tld0. A 10.53.0.2 + +tld1. NS ns.tld1. +ns.tld1. A 10.53.0.2 + +tld2. NS ns.tld2. +ns.tld2. A 10.53.0.2 + +tld3. NS ns.tld3. +ns.tld3. A 10.53.0.2 + +tld4. NS ns.tld4. +ns.tld4. A 10.53.0.2 + +tld5. NS ns.tld5. +ns.tld5. A 10.53.0.2 + +tld6. NS ns.tld6. +ns.tld6. A 10.53.0.2 + +tld7. NS ns.tld7. +ns.tld7. A 10.53.0.2 + +tld8. NS ns.tld8. +ns.tld8. A 10.53.0.2 + +tld9. NS ns.tld9. +ns.tld9. A 10.53.0.2 diff --git a/bin/tests/system/camp/ns2/named.conf.j2 b/bin/tests/system/camp/ns2/named.conf.j2 new file mode 100644 index 0000000..52b2043 --- /dev/null +++ b/bin/tests/system/camp/ns2/named.conf.j2 @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; +}; + +zone "tld0" { + type primary; + file "tld0.db"; +}; diff --git a/bin/tests/system/camp/ns2/setup.sh b/bin/tests/system/camp/ns2/setup.sh new file mode 100644 index 0000000..d75a190 --- /dev/null +++ b/bin/tests/system/camp/ns2/setup.sh @@ -0,0 +1,57 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns2/setup.sh" + +cp template.db.in tld0.db +echo "final.tld0. IN NS ns.final.tld0." >>tld0.db +echo "ns.final.tld0. IN A 10.53.0.3" >>tld0.db + +DEPTH=5 + +tld=1 +while [ $tld -le $DEPTH ]; do + + cat >>"named.conf" <>tld${tld}.db + echo "ns.label${label}.tld${tld}. IN A 10.53.0.3" >>tld${tld}.db + echo "" >>tld${tld}.db + + label=$((label + 1)) + done + + tld=$((tld + 1)) +done + +goto=1 +tld=1 +while [ $goto -le $DEPTH ]; do + echo "goto${goto}.tld${tld}. IN NS ns.goto${goto}.tld${tld}." >>tld${tld}.db + echo "ns.goto${goto}.tld${tld}. IN A 10.53.0.3" >>tld${tld}.db + echo "" >>tld${tld}.db + + goto=$((goto + 1)) +done diff --git a/bin/tests/system/camp/ns2/template.db.in b/bin/tests/system/camp/ns2/template.db.in new file mode 100644 index 0000000..278478e --- /dev/null +++ b/bin/tests/system/camp/ns2/template.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 + NS ns +ns A 10.53.0.2 + +; camp attack diff --git a/bin/tests/system/camp/ns3/named.conf.j2 b/bin/tests/system/camp/ns3/named.conf.j2 new file mode 100644 index 0000000..958119b --- /dev/null +++ b/bin/tests/system/camp/ns3/named.conf.j2 @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + + max-query-count 150; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "final.tld0" { + type primary; + file "final.tld0.db"; +}; diff --git a/bin/tests/system/camp/ns3/setup.sh b/bin/tests/system/camp/ns3/setup.sh new file mode 100644 index 0000000..79d1f6c --- /dev/null +++ b/bin/tests/system/camp/ns3/setup.sh @@ -0,0 +1,79 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns3/setup.sh" + +cp template.db.in final.tld0.db +echo "q.final.tld0. IN A 1.2.3.4" >>final.tld0.db + +DEPTH=5 + +tld=1 +while [ $tld -le $DEPTH ]; do + nexttld=$((tld + 1)) + + label=1 + while [ $label -le $DEPTH ]; do + nextlabel=$((label + 1)) + + cat >>"named.conf" <>label${label}.tld${tld}.db + elif [ $tld -eq $DEPTH ]; then + nextlabel=$((label + 1)) + echo "q.label${label}.tld${tld}. IN CNAME q.label${nextlabel}.tld1." >>label${label}.tld${tld}.db + else + echo "q.label${label}.tld${tld}. IN CNAME q.label${label}.tld${nexttld}." >>label${label}.tld${tld}.db + fi + + label=$nextlabel + done + + echo "" >>label${label}.tld${tld}.db + tld=$nexttld +done + +goto=1 +tld=1 +while [ $goto -le $DEPTH ]; do + nextgoto=$((goto + 1)) + + cat >>"named.conf" <>goto${goto}.tld${tld}.db + else + echo "q.goto${goto}.tld${tld}. IN CNAME q.goto${nextgoto}.tld${tld}." >>goto${goto}.tld${tld}.db + fi + + echo "" >>label${label}.tld${tld}.db + goto=$nextgoto +done diff --git a/bin/tests/system/camp/ns3/template.db.in b/bin/tests/system/camp/ns3/template.db.in new file mode 100644 index 0000000..dc6bd9b --- /dev/null +++ b/bin/tests/system/camp/ns3/template.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns + NS ns3 +ns A 10.53.0.3 +ns3 A 10.53.0.3 + +; camp attack diff --git a/bin/tests/system/camp/ns9/hints.db b/bin/tests/system/camp/ns9/hints.db new file mode 100644 index 0000000..691e813 --- /dev/null +++ b/bin/tests/system/camp/ns9/hints.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 60 IN NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/camp/ns9/named.conf.j2 b/bin/tests/system/camp/ns9/named.conf.j2 new file mode 100644 index 0000000..89045ad --- /dev/null +++ b/bin/tests/system/camp/ns9/named.conf.j2 @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS9 + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + + max-recursion-queries 50; + max-query-restarts 50; + max-query-count 100; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/camp/setup.sh b/bin/tests/system/camp/setup.sh new file mode 100644 index 0000000..7b059e2 --- /dev/null +++ b/bin/tests/system/camp/setup.sh @@ -0,0 +1,27 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +( + cd ns3 + $SHELL setup.sh +) + +( + cd ns2 + $SHELL setup.sh +) diff --git a/bin/tests/system/camp/tests.sh b/bin/tests/system/camp/tests.sh new file mode 100755 index 0000000..3f831f4 --- /dev/null +++ b/bin/tests/system/camp/tests.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=../conf.sh +. ../conf.sh + +dig_with_opts() { + "${DIG}" -p "${PORT}" "${@}" +} + +status=0 +n=0 + +n=$((n + 1)) +echo_i "checking max-query-count is in effect ($n)" +ret=0 +dig_with_opts q.label1.tld1. @10.53.0.9 a >dig.out.ns9.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns9.test${n} >/dev/null || ret=1 +grep "exceeded global max queries resolving" ns9/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/camp/tests_sh_camp.py b/bin/tests/system/camp/tests_sh_camp.py new file mode 100644 index 0000000..177a0f2 --- /dev/null +++ b/bin/tests/system/camp/tests_sh_camp.py @@ -0,0 +1,25 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + "ans*/ans.run", + "ns*/*.jnl", + "ns*/*tld*.db", + ] +) + + +def test_camp(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/case/dynamic.good b/bin/tests/system/case/dynamic.good new file mode 100644 index 0000000..66f8afd --- /dev/null +++ b/bin/tests/system/case/dynamic.good @@ -0,0 +1,6 @@ +DyNaMiC. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600 +DyNaMiC. 300 IN NS ns1.DYNAMIC. +DynamiC. 300 IN MX 0 mail.eXaMpLe. +mAiL.DynamiC. 300 IN A 10.53.0.1 +ns1.DYNAMIC. 300 IN A 10.53.0.1 +DyNaMiC. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600 diff --git a/bin/tests/system/case/ns1/dynamic.db b/bin/tests/system/case/ns1/dynamic.db new file mode 100644 index 0000000..b39b519 --- /dev/null +++ b/bin/tests/system/case/ns1/dynamic.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +$ORIGIN DyNaMiC. +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +$ORIGIN DYNAMIC. + NS ns1 +ns1 A 10.53.0.1 +$ORIGIN DynamiC. +@ MX 0 mail.eXaMpLe. +mAiL A 10.53.0.1 diff --git a/bin/tests/system/case/ns1/example.db b/bin/tests/system/case/ns1/example.db new file mode 100644 index 0000000..b58414c --- /dev/null +++ b/bin/tests/system/case/ns1/example.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns1 +ns1 A 10.53.0.1 +@ MX 0 mail.eXaMpLe. +mAiL A 10.53.0.1 diff --git a/bin/tests/system/case/ns1/named.conf.j2 b/bin/tests/system/case/ns1/named.conf.j2 new file mode 100644 index 0000000..5e90084 --- /dev/null +++ b/bin/tests/system/case/ns1/named.conf.j2 @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + minimal-responses no; + dnssec-validation no; +}; + +zone "example" { + type primary; + file "example.db"; + also-notify { 10.53.0.2; }; +}; + +zone "dynamic" { + type primary; + file "dynamic.db"; + allow-update { any; }; + also-notify { 10.53.0.2; }; +}; diff --git a/bin/tests/system/case/ns2/named.conf.j2 b/bin/tests/system/case/ns2/named.conf.j2 new file mode 100644 index 0000000..5ea648b --- /dev/null +++ b/bin/tests/system/case/ns2/named.conf.j2 @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + no-case-compress { 10.53.0.2; }; + minimal-responses no; + dnssec-validation no; +}; + +zone "example" { + type secondary; + file "example.bk"; + primaries { 10.53.0.1; }; +}; + +zone "dynamic" { + type secondary; + file "dynamic.bk"; + primaries { 10.53.0.1; }; +}; diff --git a/bin/tests/system/case/postns1.good b/bin/tests/system/case/postns1.good new file mode 100644 index 0000000..fcb3f9c --- /dev/null +++ b/bin/tests/system/case/postns1.good @@ -0,0 +1,6 @@ +dYNAMIc. 300 IN SOA mname1. . 2000042409 20 20 1814400 3600 +DyNaMiC. 300 IN NS ns1.DYNAMIC. +DynamiC. 300 IN MX 0 mail.eXaMpLe. +mAiL.DynamiC. 300 IN A 10.53.0.1 +Ns1.DyNaMIC. 300 IN A 10.53.0.1 +dYNAMIc. 300 IN SOA mname1. . 2000042409 20 20 1814400 3600 diff --git a/bin/tests/system/case/postupdate.good b/bin/tests/system/case/postupdate.good new file mode 100644 index 0000000..7755928 --- /dev/null +++ b/bin/tests/system/case/postupdate.good @@ -0,0 +1,6 @@ +dYNAMIc. 300 IN SOA mname1. . 2000042408 20 20 1814400 3600 +DyNaMiC. 300 IN NS ns1.DYNAMIC. +DynamiC. 300 IN MX 0 mail.eXaMpLe. +mAiL.DynamiC. 300 IN A 10.53.0.1 +ns1.DYNAMIC. 300 IN A 10.53.0.1 +dYNAMIc. 300 IN SOA mname1. . 2000042408 20 20 1814400 3600 diff --git a/bin/tests/system/case/tests.sh b/bin/tests/system/case/tests.sh new file mode 100644 index 0000000..c5bc0e7 --- /dev/null +++ b/bin/tests/system/case/tests.sh @@ -0,0 +1,149 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}" + +wait_for_serial() ( + $DIG $DIGOPTS "@$1" "$2" SOA >"$4" + serial=$(awk '$4 == "SOA" { print $7 }' "$4") + [ "$3" -eq "${serial:--1}" ] +) + +status=0 +n=0 + +n=$((n + 1)) +echo_i "waiting for zone transfer to complete ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9; do + $DIG $DIGOPTS soa example. @10.53.0.2 >dig.ns2.test$n || true + grep SOA dig.ns2.test$n >/dev/null && break + sleep 1 +done +for i in 1 2 3 4 5 6 7 8 9; do + $DIG $DIGOPTS soa dynamic. @10.53.0.2 >dig.ns2.test$n || true + grep SOA dig.ns2.test$n >/dev/null && break + sleep 1 +done + +n=$((n + 1)) +echo_i "testing case preserving responses - no acl ($n)" +ret=0 +$DIG $DIGOPTS mx example. @10.53.0.1 >dig.ns1.test$n || ret=1 +grep "0.mail.eXaMpLe" dig.ns1.test$n >/dev/null || ret=1 +grep "mAiL.example" dig.ns1.test$n >/dev/null || ret=1 +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing no-case-compress acl '{ 10.53.0.2; }' ($n)" +ret=0 + +# check that we preserve zone case for non-matching query (10.53.0.1) +$DIG $DIGOPTS mx example. -b 10.53.0.1 @10.53.0.1 >dig.ns1.test$n || ret=1 +grep "0.mail.eXaMpLe" dig.ns1.test$n >/dev/null || ret=1 +grep "mAiL.example" dig.ns1.test$n >/dev/null || ret=1 + +# check that we don't preserve zone case for match (10.53.0.2) +$DIG $DIGOPTS mx example. -b 10.53.0.2 @10.53.0.2 >dig.ns2.test$n || ret=1 +grep "0.mail.example" dig.ns2.test$n >/dev/null || ret=1 +grep "mail.example" dig.ns2.test$n >/dev/null || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing load of dynamic zone with various \$ORIGIN values ($n)" +ret=0 +$DIG $DIGOPTS axfr dynamic @10.53.0.1 >dig.ns1.test$n || ret=1 +digcomp dig.ns1.test$n dynamic.good || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "transfer of dynamic zone with various \$ORIGIN values ($n)" +ret=0 +$DIG $DIGOPTS axfr dynamic @10.53.0.2 >dig.ns2.test$n || ret=1 +digcomp dig.ns2.test$n dynamic.good || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "change SOA owner case via update ($n)" +$NSUPDATE <dig.ns1.test$n || ret=1 +digcomp dig.ns1.test$n postupdate.good || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "wait for zone to transfer ($n)" +retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042408 dig.ns2.test$n || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check SOA owner case is transferred to secondary ($n)" +ret=0 +$DIG $DIGOPTS axfr dynamic @10.53.0.2 >dig.ns2.test$n || ret=1 +digcomp dig.ns2.test$n postupdate.good || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +#update delete Ns1.DyNaMIC. 300 IN A 10.53.0.1 +n=$((n + 1)) +echo_i "change A record owner case via update ($n)" +$NSUPDATE <dig.ns1.test$n || ret=1 +digcomp dig.ns1.test$n postns1.good || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "wait for zone to transfer ($n)" +retry_quiet 20 wait_for_serial 10.53.0.2 dynamic 2000042409 dig.ns2.test$n || ret=1 + +test $ret -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check A owner case is transferred to secondary ($n)" +ret=0 +$DIG $DIGOPTS axfr dynamic @10.53.0.2 >dig.ns2.test$n || ret=1 +digcomp dig.ns2.test$n postns1.good || ret=1 +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/case/tests_sh_case.py b/bin/tests/system/case/tests_sh_case.py new file mode 100644 index 0000000..90b7272 --- /dev/null +++ b/bin/tests/system/case/tests_sh_case.py @@ -0,0 +1,27 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.ns*.test*", + "ns1/dynamic.db", + "ns1/dynamic.db.jnl", + "ns2/dynamic.bk", + "ns2/dynamic.bk.jnl", + "ns2/example.bk", + ] +) + + +def test_case(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/catz/ns1/catalog-bad1.example.db b/bin/tests/system/catz/ns1/catalog-bad1.example.db new file mode 100644 index 0000000..b8402de --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog-bad1.example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. diff --git a/bin/tests/system/catz/ns1/catalog-bad2.example.db b/bin/tests/system/catz/ns1/catalog-bad2.example.db new file mode 100644 index 0000000..06b9121 --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog-bad2.example.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN TXT "99" diff --git a/bin/tests/system/catz/ns1/catalog-bad3.example.db b/bin/tests/system/catz/ns1/catalog-bad3.example.db new file mode 100644 index 0000000..0116697 --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog-bad3.example.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN TXT "1" +version IN TXT "2" diff --git a/bin/tests/system/catz/ns1/catalog-bad4.example.db b/bin/tests/system/catz/ns1/catalog-bad4.example.db new file mode 100644 index 0000000..d04bab3 --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog-bad4.example.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN A 10.53.0.1 diff --git a/bin/tests/system/catz/ns1/catalog-bad5.example.db b/bin/tests/system/catz/ns1/catalog-bad5.example.db new file mode 100644 index 0000000..b014d0a --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog-bad5.example.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 CH NS invalid. +version CH TXT "2" diff --git a/bin/tests/system/catz/ns1/catalog.example.db.in b/bin/tests/system/catz/ns1/catalog.example.db.in new file mode 100644 index 0000000..6b52947 --- /dev/null +++ b/bin/tests/system/catz/ns1/catalog.example.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN TXT "2" diff --git a/bin/tests/system/catz/ns1/named.conf.in b/bin/tests/system/catz/ns1/named.conf.in new file mode 100644 index 0000000..fdf8041 --- /dev/null +++ b/bin/tests/system/catz/ns1/named.conf.in @@ -0,0 +1,145 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + tls-port @TLSPORT@; + allow-new-zones yes; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on port @EXTRAPORT1@ { 10.53.0.1; }; + listen-on tls ephemeral { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + notify-delay 0; + recursion no; + allow-transfer { any; }; + dnssec-validation no; +}; + +view "default" { + + zone "catalog1.example" { + type primary; + file "catalog1.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + /* catalog2 is provided by the ns3 primary */ + + zone "catalog3.example" { + type primary; + file "catalog3.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + zone "catalog4.example" { + type primary; + file "catalog4.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + /* catalog5 is missing on purpose */ + + # No "version" property + zone "catalog-bad1.example" { + type primary; + file "catalog-bad1.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + # Unsupported "version" property + zone "catalog-bad2.example" { + type primary; + file "catalog-bad2.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + # Two RRs in TXT RRset for the "version" property + zone "catalog-bad3.example" { + type primary; + file "catalog-bad3.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + # Type A "version" property + zone "catalog-bad4.example" { + type primary; + file "catalog-bad4.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + + # A catalog zone that requires TLS to be used + zone "catalog-tls.example" { + type primary; + file "catalog-tls.example.db"; + allow-transfer transport tls { key tsig_key; }; + allow-update { any; }; + also-notify { 10.53.0.4; }; + notify explicit; + }; +}; + +view "ch" ch { + + # Non-IN class catalog zone + zone "catalog-bad5.example" ch { + type primary; + file "catalog-bad5.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; + }; + +}; + +key tsig_key. { + secret "LSAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; + +key next_key. { + secret "LaAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/catz/ns2/dom-existing.example.db b/bin/tests/system/catz/ns2/dom-existing.example.db new file mode 100644 index 0000000..b8402de --- /dev/null +++ b/bin/tests/system/catz/ns2/dom-existing.example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. diff --git a/bin/tests/system/catz/ns2/named1.conf.in b/bin/tests/system/catz/ns2/named1.conf.in new file mode 100644 index 0000000..e16416d --- /dev/null +++ b/bin/tests/system/catz/ns2/named1.conf.in @@ -0,0 +1,196 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + allow-transfer { any; }; + notify no; + notify-delay 0; + recursion no; +#T5 allow-query { 10.53.0.99; }; + serial-query-rate 100; + dnssec-validation no; +}; + +/* + * The comment lines starting with "#Tn" markers below are designed to be + * uncommented by "tests.sh" when running the tests to perform some of required + * tests which need ns2 reconfgiuration. + */ + +view "default" { + + catalog-zones { + zone "catalog1.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + in-memory no + zone-directory "zonedir"; + zone "catalog2.example" + default-primaries { 10.53.0.1 port @EXTRAPORT1@; } + min-update-interval 1s + in-memory yes; + zone "catalog3.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + zone-directory "nonexistent"; +#T1 zone "catalog4.example" +#T1 min-update-interval 1s +#T1 default-masters { 10.53.0.1; }; +#T2 zone "catalog5.example" +#T2 min-update-interval 1s +#T2 default-primaries { 10.53.0.1; }; + zone "catalog-bad1.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + in-memory yes; + zone "catalog-bad2.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + in-memory yes; + zone "catalog-bad3.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + in-memory yes; + zone "catalog-bad4.example" + default-masters { 10.53.0.1; } + min-update-interval 1s + in-memory yes; + }; + + # A faulty dlz configuration to check if named and catz survive a certain class + # of failed configuration attempts (see GL #3060). + # We use "dlz" because the dlz processing code is located in an ideal place in + # the view configuration function for the test to cover the view reverting code. +#T3 dlz "bad-dlz" { +#T3 database "dlopen bad-dlz.so example.org"; +#T3 }; + + zone "dom-existing.example" { + type primary; + file "dom-existing.example.db"; + }; + + zone "dom-existing-forward.example" { + type forward; + forward only; + forwarders { 10.53.0.1; }; + }; + + zone "dom-existing-forward-off.example" { + type forward; + forward only; + forwarders { }; + }; + + zone "catalog1.example" { + type secondary; + file "catalog1.example.db"; + primaries { 10.53.0.1; }; + }; + + zone "catalog2.example" { + type secondary; + file "catalog2.example.db"; + primaries { 10.53.0.3; }; + }; + + zone "catalog3.example" { + type secondary; + file "catalog3.example.db"; + primaries { 10.53.0.1; }; + }; + + zone "catalog4.example" { + type secondary; + file "catalog4.example.db"; + primaries { 10.53.0.1; }; + }; + + # When the following zone configuration is enabled, "dom3.example" should + # already exist as a member of "catalog1.example", and named should be able + # to deal with that situation (see GL #3911). Make sure that this duplicate + # zone comes after the the "catalog1.example" zone in the configuration file. +#T4 zone "dom3.example" { +#T4 type secondary; +#T4 file "dom2.example.db"; +#T4 }; + + # No "version" property + zone "catalog-bad1.example" { + type secondary; + file "catalog-bad1.example.db"; + primaries { 10.53.0.1; }; + }; + + # Unsupported "version" property + zone "catalog-bad2.example" { + type secondary; + file "catalog-bad2.example.db"; + primaries { 10.53.0.1; }; + }; + + # Two RRs in TXT RRset for the "version" property + zone "catalog-bad3.example" { + type secondary; + file "catalog-bad3.example.db"; + primaries { 10.53.0.1; }; + }; + + # Type A "version" property + zone "catalog-bad4.example" { + type secondary; + file "catalog-bad4.example.db"; + primaries { 10.53.0.1; }; + }; + +}; + +view "ch" ch { + + catalog-zones { + zone "catalog-bad5.example" + default-masters { 10.53.0.1; } + in-memory yes; + }; + + # Non-IN class catalog zone + zone "catalog-bad5.example" ch { + type secondary; + file "catalog-bad5.example.db"; + primaries { 10.53.0.1; }; + }; + +}; + +key tsig_key. { + secret "LSAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; + +key next_key. { + secret "LaAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/catz/ns2/named2.conf.in b/bin/tests/system/catz/ns2/named2.conf.in new file mode 100644 index 0000000..ead45a8 --- /dev/null +++ b/bin/tests/system/catz/ns2/named2.conf.in @@ -0,0 +1,129 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + allow-transfer { any; }; + notify no; + notify-delay 0; + recursion no; + serial-query-rate 100; + dnssec-validation no; +}; + +view "default" { + + # Removed catalog-zone option, otherwise this is + # identical to named1.conf.in + + zone "dom-existing.example" { + type primary; + file "dom-existing.example.db"; + }; + + zone "dom-existing-forward.example" { + type forward; + forward only; + forwarders { 10.53.0.1; }; + }; + + zone "dom-existing-forward-off.example" { + type forward; + forward only; + forwarders { }; + }; + + zone "catalog1.example" { + type secondary; + file "catalog1.example.db"; + primaries { 10.53.0.1; }; + }; + + zone "catalog2.example" { + type secondary; + file "catalog2.example.db"; + primaries { 10.53.0.3; }; + }; + + zone "catalog3.example" { + type secondary; + file "catalog3.example.db"; + primaries { 10.53.0.1; }; + }; + + zone "catalog4.example" { + type secondary; + file "catalog4.example.db"; + primaries { 10.53.0.1; }; + }; + + # No "version" property + zone "catalog-bad1.example" { + type secondary; + file "catalog-bad1.example.db"; + primaries { 10.53.0.1; }; + }; + + # Unsupported "version" property + zone "catalog-bad2.example" { + type secondary; + file "catalog-bad2.example.db"; + primaries { 10.53.0.1; }; + }; + + # Two RRs in TXT RRset for the "version" property + zone "catalog-bad3.example" { + type secondary; + file "catalog-bad3.example.db"; + primaries { 10.53.0.1; }; + }; + + # Type A "version" property + zone "catalog-bad4.example" { + type secondary; + file "catalog-bad4.example.db"; + primaries { 10.53.0.1; }; + }; + +}; + +view "ch" ch { + + # Removed catalog-zone option, otherwise this is + # identical to named1.conf.in + + # Non-IN class catalog zone + zone "catalog-bad5.example" ch { + type secondary; + file "catalog-bad5.example.db"; + primaries { 10.53.0.1; }; + }; + +}; + +key tsig_key. { + secret "LSAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/catz/ns3/catalog.example.db.in b/bin/tests/system/catz/ns3/catalog.example.db.in new file mode 100644 index 0000000..eccb4f1 --- /dev/null +++ b/bin/tests/system/catz/ns3/catalog.example.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 2670950424 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN TXT "1" diff --git a/bin/tests/system/catz/ns3/dom5.example.db b/bin/tests/system/catz/ns3/dom5.example.db new file mode 100644 index 0000000..5779aaf --- /dev/null +++ b/bin/tests/system/catz/ns3/dom5.example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 IN SOA . . 1 3600 3600 3600 3600 +@ IN NS invalid. diff --git a/bin/tests/system/catz/ns3/dom6.example.db b/bin/tests/system/catz/ns3/dom6.example.db new file mode 100644 index 0000000..5779aaf --- /dev/null +++ b/bin/tests/system/catz/ns3/dom6.example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 IN SOA . . 1 3600 3600 3600 3600 +@ IN NS invalid. diff --git a/bin/tests/system/catz/ns3/named.conf.in b/bin/tests/system/catz/ns3/named.conf.in new file mode 100644 index 0000000..934eced --- /dev/null +++ b/bin/tests/system/catz/ns3/named.conf.in @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + allow-new-zones yes; + pid-file "named.pid"; + provide-ixfr no; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + allow-transfer { any; }; + notify no; + notify-delay 0; + recursion no; + dnssec-validation no; +}; + +zone "catalog2.example" { + type primary; + file "catalog2.example.db"; + allow-transfer { any; }; + allow-update { any; }; + also-notify { 10.53.0.2; }; + notify explicit; +}; + +zone "dom5.example" { + type primary; + file "dom5.example.db"; + allow-transfer { any; }; + allow-update { any; }; + notify explicit; +}; + +zone "dom6.example" { + type primary; + file "dom6.example.db"; + allow-transfer { any; }; + allow-update { any; }; + notify explicit; +}; diff --git a/bin/tests/system/catz/ns4/catalog.example.db.in b/bin/tests/system/catz/ns4/catalog.example.db.in new file mode 100644 index 0000000..a0bab0d --- /dev/null +++ b/bin/tests/system/catz/ns4/catalog.example.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 1 86400 3600 86400 3600 +@ 3600 IN NS invalid. +version IN TXT "1" diff --git a/bin/tests/system/catz/ns4/named.conf.in b/bin/tests/system/catz/ns4/named.conf.in new file mode 100644 index 0000000..75cb19e --- /dev/null +++ b/bin/tests/system/catz/ns4/named.conf.in @@ -0,0 +1,67 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { fd92:7065:b8e:ffff::4; }; + allow-transfer { any; }; + notify no; + notify-delay 0; + recursion no; + serial-query-rate 100; + ixfr-from-differences yes; // GL #3777 + dnssec-validation no; + + catalog-zones { + zone "catalog-tls.example" + min-update-interval 1s + default-primaries { 10.53.0.1 key tsig_key tls ephemeral; }; + zone "catalog-self.example" + min-update-interval 1s + default-primaries { 10.53.0.4; }; + }; +}; + +zone "catalog-tls.example" { + type secondary; + file "catalog-tls.example.db"; + primaries { 10.53.0.1 key tsig_key tls ephemeral; }; +}; + +zone "catalog-self.example" { + type primary; + file "catalog-self.example.db"; + notify explicit; +}; + +key tsig_key. { + secret "LSAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; + +key next_key. { + secret "LaAnCU+Z"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/catz/setup.sh b/bin/tests/system/catz/setup.sh new file mode 100644 index 0000000..c33ce7f --- /dev/null +++ b/bin/tests/system/catz/setup.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named1.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +cp -f ns1/catalog.example.db.in ns1/catalog1.example.db +cp -f ns3/catalog.example.db.in ns3/catalog2.example.db +cp -f ns1/catalog.example.db.in ns1/catalog3.example.db +cp -f ns1/catalog.example.db.in ns1/catalog4.example.db +cp -f ns1/catalog.example.db.in ns1/catalog-tls.example.db +cp -f ns4/catalog.example.db.in ns4/catalog-self.example.db + +mkdir -p ns2/zonedir diff --git a/bin/tests/system/catz/tests.sh b/bin/tests/system/catz/tests.sh new file mode 100644 index 0000000..80cbc81 --- /dev/null +++ b/bin/tests/system/catz/tests.sh @@ -0,0 +1,2674 @@ +#!/bin/sh -x + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +dig_with_opts() { + "$DIG" -p "${PORT}" "$@" +} + +rndccmd() ( + "$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "$@" +) + +_wait_for_message() ( + nextpartpeek "$1" >wait_for_message.$n + grep -F "$2" wait_for_message.$n >/dev/null +) + +wait_for_message() ( + retry_quiet 20 _wait_for_message "$@" +) + +_wait_for_rcode() ( + rcode="$1" + qtype="$2" + ns="$3" + qname="$4" + file="$5" + shift 5 + dig_with_opts "$ns" "$qtype" "$qname" "$@" >"$file" || return 1 + grep "status: $rcode" "$file" >/dev/null +) + +wait_for_rcode() ( + retry_quiet 10 _wait_for_rcode "$@" +) + +wait_for_soa() ( + wait_for_rcode NOERROR SOA "$@" +) + +wait_for_a() ( + wait_for_rcode NOERROR A "$@" +) + +wait_for_no_soa() { + wait_for_rcode REFUSED SOA "$@" +} + +_wait_for_zonefile() ( + # shellcheck disable=SC2234 + [ -f "$1" ] +) + +wait_for_zonefile() ( + retry_quiet 10 _wait_for_zonefile "$@" +) + +_wait_for_no_zonefile() ( + # shellcheck disable=SC2234 + [ ! -f "$1" ] +) + +wait_for_no_zonefile() ( + retry_quiet 10 _wait_for_no_zonefile "$@" +) + +status=0 +n=0 + +########################################################################## +n=$((n + 1)) +echo_i "checking that catalog-bad1.example (with no version) has failed to load ($n)" +ret=0 +wait_for_message ns2/named.run "catz: zone 'catalog-bad1.example' has no 'version' record and will not be processed" \ + && if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that catalog-bad2.example (with unsupported version) has failed to load ($n)" +ret=0 +wait_for_message ns2/named.run "catz: zone 'catalog-bad2.example' unsupported version '99'" \ + && wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad2.example' is broken and will not be processed" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that catalog-bad3.example (with two supported version records) has failed to load ($n)" +ret=0 +wait_for_message ns2/named.run "catz: 'version' property TXT RRset contains more than one record, which is invalid" \ + && wait_for_message ns2/named.run "catz: invalid record in catalog zone - version.catalog-bad3.example IN TXT (failure) - ignoring" \ + && wait_for_message ns2/named.run "catz: zone 'catalog-bad3.example' version is not set" \ + && wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad3.example' is broken and will not be processed" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that catalog-bad4.example (with only spurious type A version record) has failed to load ($n)" +ret=0 +wait_for_message ns2/named.run "catz: invalid record in catalog zone - version.catalog-bad4.example IN A (failure) - ignoring" \ + && wait_for_message ns2/named.run "catz: zone 'catalog-bad4.example' version is not set" \ + && wait_for_message ns2/named.run "catz: new catalog zone 'catalog-bad4.example' is broken and will not be processed" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that catalog-bad5.example (non-IN class) has failed to load ($n)" +ret=0 +wait_for_message ns2/named.run "'catalog-zones' option is only supported for views with class IN" \ + && wait_for_message ns2/named.run "all zones loaded" || ret=1 +grep -F "catz: dns_catz_zone_add catalog-bad5.example" ns2/named.run && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +########################################################################## +echo_i "Testing adding/removing of domain in catalog zone" +n=$((n + 1)) +echo_i "checking that dom1.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom1.example. to primary via RNDC ($n)" +ret=0 +# enough initial content for IXFR response when TXT record is added below +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom1.example.db +echo "@ 3600 IN NS invalid." >>ns1/dom1.example.db +echo "foo 3600 IN TXT some content here" >>ns1/dom1.example.db +echo "bar 3600 IN TXT some content here" >>ns1/dom1.example.db +echo "xxx 3600 IN TXT some content here" >>ns1/dom1.example.db +echo "yyy 3600 IN TXT some content here" >>ns1/dom1.example.db +rndccmd 10.53.0.1 addzone dom1.example. in default '{ type primary; file "dom1.example.db"; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom1.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom1.example. to catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN PTR dom1.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom1.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom1.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom1.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that zone-directory is populated ($n)" +ret=0 +wait_for_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "update dom1.example. ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom1.example 0 IN TXT added record + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for secondary to be updated ($n)" +ret=0 +wait_for_txt() { + dig_with_opts @10.53.0.2 TXT dom1.example. >dig.out.test$n || return 1 + grep "ANSWER: 1," dig.out.test$n >/dev/null || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + grep "IN.TXT." dig.out.test$n >/dev/null || return 1 +} +retry_quiet 10 wait_for_txt || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that journal was created for cleanup test ($n)" +ret=0 +test -f ns2/zonedir/__catz__default_catalog1.example_dom1.example.db.jnl || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "update catalog zone serial ($n)" +ret=0 +# default minimum update rate is once / 5 seconds +sleep 5 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add catalog1.example 3600 SOA . . 20 86400 3600 86400 3600 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for catalog zone to transfer ($n)" +ret=0 +wait_for_soa_equal_20() { + dig_with_opts @10.53.0.2 SOA catalog1.example. >dig.out.test$n || return 1 + grep "ANSWER: 1," dig.out.test$n >/dev/null || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + grep 'IN.SOA.\. \. 20 ' dig.out.test$n >/dev/null || return 1 +} +retry_quiet 10 wait_for_soa_equal_20 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "update dom1.example. again ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add foo.dom1.example 0 IN TXT added record + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for secondary to be updated again ($n)" +ret=0 +wait_for_txt() { + dig_with_opts @10.53.0.2 TXT foo.dom1.example. >dig.out.test$n || return 1 + grep "ANSWER: 2," dig.out.test$n >/dev/null || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + grep "IN.TXT." dig.out.test$n >/dev/null || return 1 +} +retry_quiet 10 wait_for_txt || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing domain dom1.example. from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom1.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom1.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that zone-directory is emptied ($n)" +ret=0 +wait_for_no_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db" || ret=1 +wait_for_no_zonefile "ns2/zonedir/__catz__default_catalog1.example_dom1.example.db.jnl" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +########################################################################## +echo_i "Testing various simple operations on domains, including using multiple catalog zones and garbage in zone" +n=$((n + 1)) +echo_i "adding domain dom2.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom2.example.db +echo "@ IN NS invalid." >>ns1/dom2.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom2.example.db +rndccmd 10.53.0.1 addzone dom2.example. in default '{type primary; file "dom2.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom2.example. to primary ns3 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns3/dom2.example.db +echo "@ IN NS invalid." >>ns3/dom2.example.db +echo "@ IN A 192.0.2.2" >>ns3/dom2.example.db +rndccmd 10.53.0.3 addzone dom2.example. '{type primary; file "dom2.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom4.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom4.example.db +echo "@ IN NS invalid." >>ns1/dom4.example.db +rndccmd 10.53.0.1 addzone dom4.example. in default '{type primary; file "dom4.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domains dom2.example, dom3.example. and some garbage to catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + update add coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example." + update add b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example. + update add e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar. + update add trash.catalog1.example. 3600 IN A 1.2.3.4 + update add trash2.foo.catalog1.example. 3600 IN A 1.2.3.4 + update add trash3.zones.catalog1.example. 3600 IN NS a.dom2.example. + update add foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example. + update add blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + update add foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN APL 1:1.2.3.4/30 + update add blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "blah blah" + update add version.catalog1.example. 3600 IN A 1.2.3.4 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom4.example. to catalog2 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: updating catalog zone 'catalog2.example' with serial 2670950425" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom3.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom4.example' from catalog 'catalog2.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom4.example/IN/default' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom4.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom4.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom3.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding a domain dom3.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom3.example.db +echo "@ IN NS invalid." >>ns1/dom3.example.db +rndccmd 10.53.0.1 addzone dom3.example. in default '{type primary; file "dom3.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom3.example. is served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "transfer of 'dom2.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" \ + && wait_for_message ns2/named.run "transfer of 'dom3.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom3.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +# The member zone's PTR RRset must have only one record in it. +# Check that adding a second record to the RRset is caught and such a +# catalog zone is not processed. +n=$((n + 1)) +echo_i "adding domain dom4-reused-label.example. to catalog2 zone, reusing a label ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up, and checking that the reused label has been caught ($n)" +ret=0 +wait_for_message ns2/named.run "de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example IN PTR (failure)" \ + && wait_for_message ns2/named.run "catz: new catalog zone 'catalog2.example' is broken and will not be processed" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "deleting domain dom4-reused-label.example. from catalog2 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4-reused-label.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +# Test zone associated state reset. +n=$((n + 1)) +echo_i "renaming the label of domain dom4.example. in catalog2 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete de26b88d855397a03f77ff1162fd055d8b419584.zones.catalog2.example. 3600 IN PTR dom4.example. + update add dom4-renamed-label.zones.catalog2.example. 3600 IN PTR dom4.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up, and checking that the zone has been reset ($n)" +ret=0 +wait_for_message ns2/named.run "catz: zone 'dom4.example' unique label has changed, reset state" \ + && wait_for_message ns2/named.run "catz: deleting zone 'dom4.example' from catalog 'catalog2.example' - success" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom4.example' from catalog 'catalog2.example' - success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domain dom2.example. to catalog2 zone to test change of ownership ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add dom2-without-coo.zones.catalog2.example. 3600 IN PTR dom2.example. + update add primaries.dom2-without-coo.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog2.example'" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that unpermitted change of ownership did not happen ($n)" +ret=0 +wait_for_message ns2/named.run "catz_addmodzone_cb: zone 'dom2.example' will not be added because another catalog zone already contains an entry with that zone" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom2.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding change of ownership permission record for dom2.example. into catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR catalog2.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: updating catalog zone 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "updating catalog2 zone to initiate a zone transfer ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete dom2-without-coo.zones.catalog2.example. 3600 IN PTR dom2.example. + update delete primaries.dom2-without-coo.zones.catalog2.example. 3600 IN A 10.53.0.3 + update add dom2-with-coo.zones.catalog2.example. 3600 IN PTR dom2.example. + update add primaries.dom2-with-coo.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up and checking that the change of ownership was successful ($n)" +ret=0 +wait_for_message ns2/named.run "catz: zone 'dom2.example' change of ownership from 'catalog1.example' to 'catalog2.example'" \ + && wait_for_message ns2/named.run "catz: deleting zone 'dom2.example' from catalog 'catalog1.example' - success" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom2.example' from catalog 'catalog2.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom2.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom2.example. is served by secondary and that it's now the one from ns3 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1 +grep "192.0.2.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "removing dom2.example. and its change of ownership permission record from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + update delete coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR catalog2.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: iteration finished" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding change of ownership permission record for dom2.example. into catalog2 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add coo.dom2-with-coo.zones.catalog2.example. 3600 IN PTR catalog1.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: iteration finished" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding back dom2.example. into catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the change of ownership did not happen because version '1' catalog2 zone does not support the 'coo' property ($n)" +ret=0 +wait_for_message ns2/named.run "catz_addmodzone_cb: zone 'dom2.example' will not be added because another catalog zone already contains an entry with that zone" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom2.example. is still served by secondary and that it's still the one from ns3 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom2.example. dig.out.test$n || ret=1 +grep "192.0.2.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +# GL #3060 +n=$((n + 1)) +echo_i "reconfiguring secondary - checking if catz survives a certain class of failed reconfiguration attempts ($n)" +ret=0 +sed -e "s/^#T3//" ns2/named.conf.tmp +copy_setports ns2/named.conf.tmp ns2/named.conf +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig >/dev/null 2>&1 && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking again that dom3.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reconfiguring secondary - reverting the bad configuration ($n)" +ret=0 +copy_setports ns2/named1.conf.in ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +# GL #3911 +n=$((n + 1)) +echo_i "reconfiguring secondary - checking if catz survives another type of failed reconfiguration attempts ($n)" +ret=0 +sed -e "s/^#T4//" ns2/named.conf.tmp +copy_setports ns2/named.conf.tmp ns2/named.conf +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig >/dev/null 2>&1 && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# catalog zone update can be deferred +sleep 2 + +n=$((n + 1)) +echo_i "checking again that dom3.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# GL #4733 +n=$((n + 1)) +echo_i "reconfiguring secondary - checking if catz member zones are reconfigured ($n)" +ret=0 +sed -e "s/^#T5//" ns2/named.conf.tmp +copy_setports ns2/named.conf.tmp ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom3.example. is refused by secondary because of an activated allow-query ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom3.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reconfiguring secondary - reverting the bad configuration ($n)" +ret=0 +copy_setports ns2/named1.conf.in ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding a domain dom-existing.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom-existing.example.db +echo "@ IN NS invalid." >>ns1/dom-existing.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom-existing.example.db +rndccmd 10.53.0.1 addzone dom-existing.example. in default '{type primary; file "dom-existing.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing.example. is served by primary ($n)" +ret=0 +wait_for_a @10.53.0.1 dom-existing.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom-existing.example. to catalog1 zone to test that existing zones don't get overwritten ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom-existing.zones.catalog1.example. 3600 IN PTR dom-existing.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom-existing.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz_addmodzone_cb: zone 'dom-existing.example' will not be added because it is an explicitly configured zone" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing.example. is served by secondary and that it's not the one from the primary ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom-existing.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding a domain dom-existing-forward.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom-existing-forward.example.db +echo "@ IN NS invalid." >>ns1/dom-existing-forward.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom-existing-forward.example.db +rndccmd 10.53.0.1 addzone dom-existing-forward.example. in default '{type primary; file "dom-existing-forward.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing-forward.example. is served by primary ($n)" +ret=0 +wait_for_a @10.53.0.1 dom-existing-forward.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom-existing-forward.example. to catalog1 zone to test that existing forward zones don't get overwritten ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom-existing-forward.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom-existing-forward.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz_addmodzone_cb: zone 'dom-existing-forward.example' will not be processed because of the explicitly configured forwarding for that zone" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing-forward.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom-existing-forward.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding a domain dom-existing-forward-off.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom-existing-forward-off.example.db +echo "@ IN NS invalid." >>ns1/dom-existing-forward-off.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom-existing-forward-off.example.db +rndccmd 10.53.0.1 addzone dom-existing-forward-off.example. in default '{type primary; file "dom-existing-forward-off.example.db"; also-notify { 10.53.0.2; }; notify explicit; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing-forward-off.example. is served by primary ($n)" +ret=0 +wait_for_a @10.53.0.1 dom-existing-forward-off.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domain dom-existing-forward-off.example. to catalog1 zone to test that a zone with turned off forwarding can be used in a catalog zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom-existing-forward-off.zones.catalog1.example. 3600 IN PTR dom-existing-forward-off.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom-existing-forward-off.example' from catalog 'catalog1.example'" \ + && if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom-existing-forward-off.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom-existing-forward-off.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing all records from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + update delete coo.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "catalog2.example." + update delete b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example. + update delete e721433b6160b450260d4f54b3ec8bab30cb3b83.zones.catalog1.example. 3600 IN NS foo.bar. + update delete trash.catalog1.example. 3600 IN A 1.2.3.4 + update delete trash2.foo.catalog1.example. 3600 IN A 1.2.3.4 + update delete trash3.zones.catalog1.example. 3600 IN NS a.dom2.example. + update delete foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN PTR dom3.example. + update delete blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN PTR dom2.example. + update delete foobarbaz.b901f492f3ebf6c1e5b597e51766f02f0479eb03.zones.catalog1.example. 3600 IN APL 1:1.2.3.4/30 + update delete blahblah.636722929740e507aaf27c502812fc395d30fb17.zones.catalog1.example. 3600 IN TXT "blah blah" + update delete version.catalog1.example. 3600 IN A 1.2.3.4 + update delete dom-existing.zones.catalog1.example. 3600 IN PTR dom-existing.example. + update delete dom-existing-forward.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example. + update delete dom-existing-forward-off.zones.catalog1.example. 3600 IN PTR dom-existing-forward.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing all records from catalog2 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete dom2-with-coo.zones.catalog2.example. 3600 IN PTR dom2.example. + update delete primaries.dom2-with-coo.zones.catalog2.example. 3600 IN A 10.53.0.3 + update delete coo.dom2-with-coo.zones.catalog2.example. 3600 IN PTR catalog1.example. + update delete dom4-renamed-label.zones.catalog2.example. 3600 IN PTR dom4.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing primaries suboption and random labels" +n=$((n + 1)) +echo_i "adding dom5.example. with a valid primaries suboption (IP without TSIG) and a random label ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add somerandomlabel.zones.catalog1.example. 3600 IN PTR dom5.example. + update add primaries.ext.somerandomlabel.zones.catalog1.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom5.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom5.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom5.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom5.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing dom5.example. ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete somerandomlabel.zones.catalog1.example. 3600 IN PTR dom5.example. + update delete primaries.somerandomlabel.zones.catalog1.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom5.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom5.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom5.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing primaries global option" +n=$((n + 1)) +echo_i "adding dom6.example. and a valid global primaries option (IP without TSIG) ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add primaries.ext.catalog1.example. 3600 IN A 10.53.0.3 + update add primaries.ext.catalog1.example. 3600 IN AAAA fd92:7065:b8e:ffff::3 + update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom6.example/IN/default' from " >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom6.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom6.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing dom6.example. ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete primaries.ext.catalog1.example. 3600 IN A 10.53.0.3 + update delete primaries.ext.catalog1.example. 3600 IN AAAA fd92:7065:b8e:ffff::3 + update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom6.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom6.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom6.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding dom6.example. and an invalid global primaries option (TSIG without IP) ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add label1.primaries.ext.catalog1.example. 3600 IN TXT "tsig_key" + update add 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom6.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "error \"failure\" while trying to generate config for zone 'dom6.example'" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing dom6.example. ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete label1.primaries.ext.catalog1.example. 3600 IN TXT "tsig_key" + update delete 4346f565b4d63ddb99e5d2497ff22d04e878e8f8.zones.catalog1.example. 3600 IN PTR dom6.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: deleting zone 'dom6.example' from catalog 'catalog1.example' - success" >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +n=$((n + 1)) +echo_i "Checking that a missing zone directory forces in-memory ($n)" +ret=0 +grep "'nonexistent' not found; zone files will not be saved" ns2/named.run >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing allow-query and allow-transfer ACLs" +n=$((n + 1)) +echo_i "adding domains dom7.example. and dom8.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom7.example.db +echo "@ IN NS invalid." >>ns1/dom7.example.db +rndccmd 10.53.0.1 addzone dom7.example. in default '{type primary; file "dom7.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom8.example.db +echo "@ IN NS invalid." >>ns1/dom8.example.db +rndccmd 10.53.0.1 addzone dom8.example. in default '{type primary; file "dom8.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom7.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom7.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domain dom7.example. to catalog1 zone with an allow-query statement ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 78833ec3c0059fd4540fee81c7eaddce088e7cd7.zones.catalog1.example. 3600 IN PTR dom7.example. + update add allow-query.ext.78833ec3c0059fd4540fee81c7eaddce088e7cd7.zones.catalog1.example. 3600 IN APL 1:10.53.0.1/32 !1:10.53.0.0/30 1:0.0.0.0/0 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom7.example' from catalog 'catalog1.example'" >/dev/null \ + && wait_for_message ns2/named.run "transfer of 'dom7.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom7.example. is accessible from 10.53.0.1 ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom7.example. is not accessible from 10.53.0.2 ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.2 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom7.example. is accessible from 10.53.0.5 ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.5 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null +n=$((n + 1)) +echo_i "adding dom8.example. domain and global allow-query and allow-transfer ACLs ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add cba95222e308baba42417be6021026fdf20827b6.zones.catalog1.example. 3600 IN PTR dom8.example + update add allow-query.ext.catalog1.example. 3600 IN APL 1:10.53.0.1/32 + update add allow-transfer.ext.catalog1.example. 3600 IN APL 1:10.53.0.2/32 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" \ + && wait_for_message ns2/named.run "transfer of 'dom8.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is accessible from 10.53.0.1 ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is not accessible from 10.53.0.2 ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.2 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is not AXFR accessible from 10.53.0.1 ($n)" +ret=0 +dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.1 >dig.out.test$n || ret=1 +grep "Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.2 ($n)" +ret=0 +dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.2 >dig.out.test$n || ret=1 +grep -v "Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null +n=$((n + 1)) +echo_i "deleting global allow-query and allow-domain ACLs ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete allow-query.ext.catalog1.example. 3600 IN APL 1:10.53.0.1/32 + update delete allow-transfer.ext.catalog1.example. 3600 IN APL 1:10.53.0.2/32 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is accessible from 10.53.0.1 ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is accessible from 10.53.0.2 ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom8.example. dig.out.test$n -b 10.53.0.2 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.1 ($n)" +ret=0 +dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.1 >dig.out.test$n || ret=1 +grep -v "Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. is AXFR accessible from 10.53.0.2 ($n)" +ret=0 +dig_with_opts @10.53.0.2 axfr dom8.example. -b 10.53.0.2 >dig.out.test$n || ret=1 +grep -v "Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing TSIG keys for primaries set per-domain" +n=$((n + 1)) +echo_i "adding a domain dom9.example. to primary via RNDC, with transfers allowed only with TSIG key ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom9.example.db +echo "@ IN NS invalid." >>ns1/dom9.example.db +rndccmd 10.53.0.1 addzone dom9.example. in default '{type primary; file "dom9.example.db"; allow-transfer { key tsig_key; }; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom9.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom9.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domain dom9.example. to catalog1 zone with a valid primaries suboption (IP with TSIG) ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example. + update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN A 10.53.0.1 + update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom9.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom9.example. is accessible on secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom9.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "change TSIG key name on primary ($n)" +ret=0 +rndccmd 10.53.0.1 modzone dom9.example. in default '{type primary; notify yes; file "dom9.example.db"; allow-transfer { key next_key; }; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "update TSIG key name in catalog zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update del label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key" + update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "next_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: modifying zone 'dom9.example' from catalog 'catalog1.example'" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "update zone contents and reload ($n)" +ret=0 +echo "@ 3600 IN SOA . . 2 3600 3600 3600 3600" >ns1/dom9.example.db +echo "@ IN NS ns2" >>ns1/dom9.example.db +echo "ns2 IN A 10.53.0.2" >>ns1/dom9.example.db +rndccmd 10.53.0.1 reload dom9.example. || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for primary to update zone ($n)" +ret=0 +wait_for_a @10.53.0.1 ns2.dom9.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for secondary to update zone ($n)" +ret=0 +wait_for_a @10.53.0.2 ns2.dom9.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "deleting domain dom9.example. from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example. + update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN A 10.53.0.1 + update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "next_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: deleting zone 'dom9.example' from catalog 'catalog1.example' - success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom9.example. is no longer accessible on secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom9.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domain dom9.example. to catalog1 zone with an invalid primaries suboption (TSIG without IP) ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example. + update add label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom9.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "error \"failure\" while trying to generate config for zone 'dom9.example'" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "deleting domain dom9.example. from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN PTR dom9.example. + update delete label1.primaries.ext.f0f989bc71c5c8ca3a1eb9c9ab5246521907e3af.zones.catalog1.example. 3600 IN TXT "tsig_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: deleting zone 'dom9.example' from catalog 'catalog1.example'" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing catalog entries that can't be represented as filenames" +# note: we need 4 backslashes in the shell to get 2 backslashes in DNS +# presentation format, which is 1 backslash on the wire. +for special in \ + this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example \ + this.zone/domain.has.a.slash.dom10.example \ + this.zone\\\\domain.has.backslash.dom10.example \ + this.zone:domain.has.a.colon.dom.10.example; do + # hashes below are generated by: + # python ${TOP}/contrib/scripts/catzhash.py "${special}" + + case "$special" in + this.is.a.very.very.long.long.long.domain.that.will.cause.catalog.zones.to.generate.hash.instead.of.using.regular.filename.dom10.example) + hash=825f48b1ce1b4cf5a041d20255a0c8e98d114858 + db=__catz__a35e0a044ff9f37436068e1e83e9b99fb9da51b0fe7b699bdb404f7755d68276.db + ;; + this.zone/domain.has.a.slash.dom10.example) + hash=e64cc64c99bf52d0a77fb16dd7ed57cf925a36aa + db=__catz__765197c8050c794f4ec5bbf5dbdf64d0551459c08a91a4217768fcd16cd3b7ce.db + ;; + this.zone\\\\domain.has.backslash.dom10.example) + hash=91e27e02153d38cf656a9b376d7747fbcd19f985 + db=__catz__0f2f3beaf2ef70e0086063ae28a69444cdf3847cb85e668bfe52c89f7f756b29.db + ;; + this.zone:domain.has.a.colon.dom.10.example) + hash=8b7238bf4c34045834c573ba4116557ebb24d33c + db=__catz__ba75ab860533508a62b0937c5c6b8537e4186e4d5e7685161287260d07418251.db + ;; + esac + + n=$((n + 1)) + echo_i "checking that ${special}. is not served by primary ($n)" + ret=0 + wait_for_no_soa @10.53.0.1 "${special}" dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "Adding a domain ${special}. to primary via RNDC ($n)" + ret=0 + echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom10.example.db + echo "@ IN NS invalid." >>ns1/dom10.example.db + rndccmd 10.53.0.1 addzone '"'"${special}"'"' in default '{type primary; file "dom10.example.db";};' || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking that ${special}. is now served by primary ($n)" + ret=0 + wait_for_soa @10.53.0.1 "${special}." dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + nextpart ns2/named.run >/dev/null + + n=$((n + 1)) + echo_i "Adding domain ${special}. to catalog1 zone ($n)" + ret=0 + $NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add ${hash}.zones.catalog1.example 3600 IN PTR ${special}. + send +END + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "waiting for secondary to sync up ($n)" + ret=0 + wait_for_message ns2/named.run "catz: adding zone '$special' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of '$special/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking that ${special}. is served by secondary ($n)" + ret=0 + wait_for_soa @10.53.0.2 "${special}." dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking that zone-directory is populated with a hashed filename ($n)" + ret=0 + wait_for_zonefile "ns2/zonedir/$db" || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "removing domain ${special}. from catalog1 zone ($n)" + ret=0 + $NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete ${hash}.zones.catalog1.example + send +END + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "waiting for secondary to sync up ($n)" + ret=0 + wait_for_message ns2/named.run "catz: catz_delzone_cb: zone '${special}' deleted" || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking that ${special}. is not served by secondary ($n)" + ret=0 + wait_for_no_soa @10.53.0.2 "${special}." dig.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking that zone-directory is emptied ($n)" + ret=0 + wait_for_no_zonefile "ns2/zonedir/$db" || ret=1 + wait_for_no_zonefile "ns2/zonedir/$db.jnl" || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +########################################################################## +echo_i "Testing adding a domain and a subdomain of it" +n=$((n + 1)) +echo_i "checking that dom11.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom11.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom11.example.db +echo "@ IN NS invalid." >>ns1/dom11.example.db +rndccmd 10.53.0.1 addzone dom11.example. in default '{type primary; file "dom11.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom11.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom11.example. to catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 0580d70e769c86c8b951a488d8b776627f427d7a.zones.catalog1.example. 3600 IN PTR dom11.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom11.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom11.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom11.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that subdomain.of.dom11.example. is not served by primary ($n)" +ret=0 +wait_for_rcode NXDOMAIN SOA @10.53.0.1 subdomain.of.dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain subdomain.of.dom11.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/subdomain.of.dom11.example.db +echo "@ IN NS invalid." >>ns1/subdomain.of.dom11.example.db +rndccmd 10.53.0.1 addzone subdomain.of.dom11.example. in default '{type primary; file "subdomain.of.dom11.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that subdomain.of.dom11.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 subdomain.of.dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain subdomain.of.dom11.example. to catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 25557e0bdd10cb3710199bb421b776df160f241e.zones.catalog1.example. 3600 IN PTR subdomain.of.dom11.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'subdomain.of.dom11.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'subdomain.of.dom11.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that subdomain.of.dom11.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 subdomain.of.dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing domain dom11.example. from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 0580d70e769c86c8b951a488d8b776627f427d7a.zones.catalog1.example + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom11.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom11.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that subdomain.of.dom11.example. is still served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 subdomain.of.dom11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing domain subdomain.of.dom11.example. from catalog1 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 25557e0bdd10cb3710199bb421b776df160f241e.zones.catalog1.example + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'subdomain.of.dom11.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that subdomain.of.dom11.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 subdomain.of.d11.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing adding a catalog zone at runtime with rndc reconfig" +n=$((n + 1)) +echo_i "checking that dom12.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom12.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom12.example. to primary via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom12.example.db +echo "@ IN NS invalid." >>ns1/dom12.example.db +rndccmd 10.53.0.1 addzone dom12.example. in default '{type primary; file "dom12.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom12.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom12.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom12.example. to catalog4 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 871d51e5433543c0f6fb263c40f359fbc152c8ae.zones.catalog4.example. 3600 IN PTR dom12.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom12.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reconfiguring secondary - adding catalog4 catalog zone ($n)" +ret=0 +sed -e "s/^#T1//g" ns2/named.conf.tmp +copy_setports ns2/named.conf.tmp ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom12.example' from catalog 'catalog4.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom12.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom7.example. is still served by secondary after reconfiguration ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom7.example. dig.out.test$n -b 10.53.0.1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "checking that dom12.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reconfiguring secondary - removing catalog4 catalog zone, adding non-existent catalog5 catalog zone ($n)" +ret=0 +sed -e "s/^#T2//" ns2/named.conf.tmp +copy_setports ns2/named.conf.tmp ns2/named.conf +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p "${CONTROLPORT}" reconfig >/dev/null 2>&1 && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reconfiguring secondary - removing non-existent catalog5 catalog zone ($n)" +ret=0 +copy_setports ns2/named1.conf.in ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom12.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom12.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "removing domain dom12.example. from catalog4 zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 871d51e5433543c0f6fb263c40f359fbc152c8ae.zones.catalog4.example. 3600 IN PTR dom12.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing having a zone in two different catalogs" +n=$((n + 1)) +echo_i "checking that dom13.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom13.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom13.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom13.example.db +echo "@ IN NS invalid." >>ns1/dom13.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom13.example.db +rndccmd 10.53.0.1 addzone dom13.example. in default '{type primary; file "dom13.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom13.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom13.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom13.example. to primary ns3 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns3/dom13.example.db +echo "@ IN NS invalid." >>ns3/dom13.example.db +echo "@ IN A 192.0.2.2" >>ns3/dom13.example.db +rndccmd 10.53.0.3 addzone dom13.example. '{type primary; file "dom13.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom13.example. is now served by primary ns3 ($n)" +ret=0 +wait_for_soa @10.53.0.3 dom13.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom13.example. to catalog1 zone with ns1 as primary ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN PTR dom13.example. + update add primaries.ext.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN A 10.53.0.1 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom13.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom13.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "checking that dom13.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding domain dom13.example. to catalog2 zone with ns3 as primary ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN PTR dom13.example. + update add primaries.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom13.example. is served by secondary and that it's still the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Deleting domain dom13.example. from catalog2 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN PTR dom13.example. + update delete primaries.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom13.example. is served by secondary and that it's still the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom13.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Deleting domain dom13.example. from catalog1 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete 8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN PTR dom13.example. + update delete primaries.ext.8d7989c746b3f92b3bba2479e72afd977198363f.zones.catalog1.example. 3600 IN A 10.53.0.2 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom13.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom13.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing recreation of a manually deleted zone after a reload" +n=$((n + 1)) +echo_i "checking that dom16.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom16.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom16.example.db +echo "@ IN NS invalid." >>ns1/dom16.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom16.example.db +rndccmd 10.53.0.1 addzone dom16.example. in default '{type primary; file "dom16.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom16.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom16.example. to catalog1 zone with ns1 as primary ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example. + update add masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom16.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom16.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +echo_i "Deleting dom16.example. from secondary ns2 via RNDC ($n)" +ret=0 +rndccmd 10.53.0.2 delzone dom16.example. in default >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom16.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +echo_i "Reloading secondary ns2 via RNDC ($n)" +ret=0 +rndccmd 10.53.0.2 reload >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: zone 'dom16.example' was expected to exist but can not be found, will be restored" || ret=1 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +wait_for_message ns2/named.run "catz: catalog1.example: reload done: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom16.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom8.example. was not accidentally deleted during the configuration ($n)" +ret=0 +_wait_for_message ns2/named.run "catz: zone 'dom8.example' was expected to exist but can not be found, will be restored" && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Deleting domain dom16.example. from catalog1 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN PTR dom16.example. + update delete masters.efe725d0cf430ffb113b9bcf59266f066a21216b.zones.catalog1.example. 3600 IN A 10.53.0.1 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom16.example. is no longer served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom16.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing having a regular zone and a zone in catalog zone of the same name" +n=$((n + 1)) +echo_i "checking that dom14.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom14.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom14.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom14.example.db +echo "@ IN NS invalid." >>ns1/dom14.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom14.example.db +rndccmd 10.53.0.1 addzone dom14.example. in default '{type primary; file "dom14.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom14.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom14.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom14.example. to primary ns3 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns3/dom14.example.db +echo "@ IN NS invalid." >>ns3/dom14.example.db +echo "@ IN A 192.0.2.2" >>ns3/dom14.example.db +rndccmd 10.53.0.3 addzone dom14.example. '{type primary; file "dom14.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom14.example. is now served by primary ns3 ($n)" +ret=0 +wait_for_soa @10.53.0.3 dom14.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain dom14.example. with rndc with ns1 as primary ($n)" +ret=0 +rndccmd 10.53.0.2 addzone dom14.example. in default '{type secondary; primaries {10.53.0.1;};};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "transfer of 'dom14.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "checking that dom14.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding domain dom14.example. to catalog2 zone with ns3 as primary ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add 45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN PTR dom14.example. + update add primaries.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom14.example. is served by secondary and that it's still the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Deleting domain dom14.example. from catalog2 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete 45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN PTR dom14.example. + update delete primaries.45e3d45ea5f7bd01c395ccbde6ae2e750a3ee8ab.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom14.example. is served by secondary and that it's still the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom14.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing changing label for a member zone" +n=$((n + 1)) +echo_i "checking that dom15.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom15.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Adding a domain dom15.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom15.example.db +echo "@ IN NS invalid." >>ns1/dom15.example.db +rndccmd 10.53.0.1 addzone dom15.example. in default '{type primary; file "dom15.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom15.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom15.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +echo_i "Adding domain dom15.example. to catalog1 zone with 'dom15label1' label ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom15label1.zones.catalog1.example. 3600 IN PTR dom15.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 3 + +n=$((n + 1)) +echo_i "checking that dom15.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom15.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Changing label of domain dom15.example. from 'dom15label1' to 'dom15label2' ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete dom15label1.zones.catalog1.example. 3600 IN PTR dom15.example. + update add dom15label2.zones.catalog1.example. 3600 IN PTR dom15.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: update_from_db: new zone merged" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom15.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.2 dom15.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "Testing custom properties version '1' and version '2' syntaxes" +n=$((n + 1)) +echo_i "checking that dom17.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is not served by primary ($n)" +ret=0 +wait_for_no_soa @10.53.0.1 dom18.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domains dom17.example. and dom18.example. to primary ns1 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom17.example.db +echo "@ IN NS invalid." >>ns1/dom17.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom17.example.db +rndccmd 10.53.0.1 addzone dom17.example. in default '{type primary; file "dom17.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom18.example.db +echo "@ IN NS invalid." >>ns1/dom18.example.db +echo "@ IN A 192.0.2.1" >>ns1/dom18.example.db +rndccmd 10.53.0.1 addzone dom18.example. in default '{type primary; file "dom18.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom17.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is now served by primary ns1 ($n)" +ret=0 +wait_for_soa @10.53.0.1 dom18.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom17.example. is not served by primary ns3 ($n)" +ret=0 +wait_for_no_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is not served by primary ns3 ($n)" +ret=0 +wait_for_no_soa @10.53.0.3 dom18.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "adding domains dom17.example. and dom18.example. to primary ns3 via RNDC ($n)" +ret=0 +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns3/dom17.example.db +echo "@ IN NS invalid." >>ns3/dom17.example.db +echo "@ IN A 192.0.2.2" >>ns3/dom17.example.db +rndccmd 10.53.0.3 addzone dom17.example. '{type primary; file "dom17.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns3/dom18.example.db +echo "@ IN NS invalid." >>ns3/dom18.example.db +echo "@ IN A 192.0.2.2" >>ns3/dom18.example.db +rndccmd 10.53.0.3 addzone dom18.example. '{type primary; file "dom18.example.db";};' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom17.example. is now served by primary ns3 ($n)" +ret=0 +wait_for_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is now served by primary ns3 ($n)" +ret=0 +wait_for_soa @10.53.0.3 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domains dom17.example. and dom18.example. to catalog1 zone with ns3 as custom primary using different custom properties syntax ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add dom17.zones.catalog1.example. 3600 IN PTR dom17.example. + update add dom18.zones.catalog1.example. 3600 IN PTR dom18.example. + update add primaries.dom17.zones.catalog1.example. 3600 IN A 10.53.0.3 + update add primaries.ext.dom18.zones.catalog1.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.dom17.zones.catalog1.example IN A (failure) - ignoring" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom17.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" \ + && wait_for_message ns2/named.run "transfer of 'dom18.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The "primaries" custom property for dom17.example. was added using the legacy +# syntax into a version 2 catalog1 zone, so we expect that it was ignored, no +# override of the default setting happened, and dom17.example. was transferred +# from the ns1 primary (the default). +n=$((n + 1)) +echo_i "checking that dom17.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom17.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The "primaries" custom property for dom18.example. was added using a supported +# syntax into a version 2 catalog1 zone, so we expect that it was processed, +# will override the default setting, and dom18.example. was transferred +# from the ns3 primary. +n=$((n + 1)) +echo_i "checking that dom18.example. is served by secondary and that it's the one from ns3 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom18.example. dig.out.test$n || ret=1 +grep "192.0.2.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "deleting domain dom17.example. and dom18.example. from catalog1 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update delete dom17.zones.catalog1.example. 3600 IN PTR dom17.example. + update delete dom18.zones.catalog1.example. 3600 IN PTR dom18.example. + update delete primaries.dom17.zones.catalog1.example. 3600 IN A 10.53.0.3 + update delete primaries.ext.dom18.zones.catalog1.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom17.example' deleted" \ + && wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom18.example' deleted" \ + && if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom17.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom18.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "adding domains dom17.example. and dom18.example. to catalog2 zone with ns3 as custom primary using different custom properties syntax ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update add dom17.zones.catalog2.example. 3600 IN PTR dom17.example. + update add dom18.zones.catalog2.example. 3600 IN PTR dom18.example. + update add primaries.dom17.zones.catalog2.example. 3600 IN A 10.53.0.3 + update add primaries.ext.dom18.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: invalid record in catalog zone - primaries.ext.dom18.zones.catalog2.example IN A (failure) - ignoring" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom17.example' from catalog 'catalog2.example'" \ + && wait_for_message ns2/named.run "catz: adding zone 'dom18.example' from catalog 'catalog2.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom17.example/IN/default' from 10.53.0.3#${PORT}: Transfer status: success" \ + && wait_for_message ns2/named.run "transfer of 'dom18.example/IN/default' from 10.53.0.1#${EXTRAPORT1}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The "primaries" custom property for dom17.example. was added using a supported +# syntax into a version 1 catalog1 zone, so we expect that it was processed, +# will override the default setting, and dom17.example. was transferred +# from the ns3 primary. +n=$((n + 1)) +echo_i "checking that dom17.example. is served by secondary and that it's the one from ns3 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom17.example. dig.out.test$n || ret=1 +grep "192.0.2.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The "primaries" custom property for dom18.example. was added using the new +# syntax into a version 1 catalog1 zone, so we expect that it was ignored, no +# override of the default setting happened, and dom18.example. was transferred +# from the ns1 primary (the default). +n=$((n + 1)) +echo_i "checking that dom18.example. is served by secondary and that it's the one from ns1 ($n)" +ret=0 +wait_for_a @10.53.0.2 dom18.example. dig.out.test$n || ret=1 +grep "192.0.2.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "deleting domain dom17.example. and dom18.example. from catalog2 ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.3 ${PORT} + update delete dom17.zones.catalog2.example. 3600 IN PTR dom17.example. + update delete dom18.zones.catalog2.example. 3600 IN PTR dom18.example. + update delete primaries.dom17.zones.catalog2.example. 3600 IN A 10.53.0.3 + update delete primaries.ext.dom18.zones.catalog2.example. 3600 IN A 10.53.0.3 + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom17.example' deleted" \ + && wait_for_message ns2/named.run "catz: catz_delzone_cb: zone 'dom18.example' deleted" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom17.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom17.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that dom18.example. is not served by secondary ($n)" +ret=0 +wait_for_no_soa @10.53.0.2 dom18.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +n=$((n + 1)) +echo_i "checking that reconfig can delete and restore catalog zone configuration ($n)" +ret=0 +copy_setports ns2/named2.conf.in ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +copy_setports ns2/named1.conf.in ns2/named.conf +rndccmd 10.53.0.2 reconfig || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +######################################################################### + +nextpart ns2/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding a dom19.example. to primary via RNDC ($n)" +ret=0 +# enough initial content for IXFR response when TXT record is added below +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom19.example.db +echo "@ 3600 IN NS invalid." >>ns1/dom19.example.db +echo "foo 3600 IN TXT some content here" >>ns1/dom19.example.db +echo "bar 3600 IN TXT some content here" >>ns1/dom19.example.db +echo "xxx 3600 IN TXT some content here" >>ns1/dom19.example.db +echo "yyy 3600 IN TXT some content here" >>ns1/dom19.example.db +rndccmd 10.53.0.1 addzone dom19.example. in default '{ type primary; file "dom19.example.db"; allow-transfer { key tsig_key; }; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "add an entry to the restored catalog zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN PTR dom19.example. + update add label1.primaries.ext.09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN A 10.53.0.1 + update add label1.primaries.ext.09da0a318e5333a9a7f6c14c385d69f6933e8b72.zones.catalog1.example. 3600 IN TXT "tsig_key" + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns2/named.run "catz: adding zone 'dom19.example' from catalog 'catalog1.example'" \ + && wait_for_message ns2/named.run "transfer of 'dom19.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +n=$((n + 1)) +echo_i "Adding a domain tls1.example. to primary via RNDC ($n)" +ret=0 +# enough initial content for IXFR response when TXT record is added below +echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/tls1.example.db +echo "@ 3600 IN NS invalid." >>ns1/tls1.example.db +echo "foo 3600 IN TXT some content here" >>ns1/tls1.example.db +echo "bar 3600 IN TXT some content here" >>ns1/tls1.example.db +echo "xxx 3600 IN TXT some content here" >>ns1/tls1.example.db +echo "yyy 3600 IN TXT some content here" >>ns1/tls1.example.db +rndccmd 10.53.0.1 addzone tls1.example. in default '{ type primary; file "tls1.example.db"; allow-transfer transport tls { key tsig_key; }; allow-update { any; }; notify explicit; also-notify { 10.53.0.4; }; };' || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that tls1.example. is now served by primary ($n)" +ret=0 +wait_for_soa @10.53.0.1 tls1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns4/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain tls1.example. to catalog-tls zone ($n)" +ret=0 +$NSUPDATE -d <>nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + update add 1ba056ba375209a66a2c9a0617b1df714b998112.zones.catalog-tls.example. 3600 IN PTR tls1.example. + send +END +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "waiting for secondary to sync up ($n)" +ret=0 +wait_for_message ns4/named.run "catz: adding zone 'tls1.example' from catalog 'catalog-tls.example'" \ + && wait_for_message ns4/named.run "transfer of 'tls1.example/IN' from 10.53.0.1#${TLSPORT}: Transfer status: success" || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that tls1.example. is served by secondary ($n)" +ret=0 +wait_for_soa @10.53.0.4 tls1.example. dig.out.test$n || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +# GL #3777 +nextpart ns4/named.run >/dev/null + +n=$((n + 1)) +echo_i "Adding domain self.example. to catalog-self zone without updating the serial ($n)" +ret=0 +echo "self.zones.catalog-self.example. 3600 IN PTR self.example." >>ns4/catalog-self.example.db +rndccmd 10.53.0.4 reload || ret=1 + +n=$((n + 1)) +echo_i "Issuing another rndc reload command after 1 second ($n)" +sleep 1 +rndccmd 10.53.0.4 reload || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +########################################################################## +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/catz/tests_sh_catz.py b/bin/tests/system/catz/tests_sh_catz.py new file mode 100644 index 0000000..639a0f3 --- /dev/null +++ b/bin/tests/system/catz/tests_sh_catz.py @@ -0,0 +1,34 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "nsupdate.out.*", + "wait_for_message.*", + "ns*/*.jnl", + "ns*/*.nzf*", + "ns*/*.nzd*", + "ns*/catalog*.example.db", + "ns*/*dom*.example.db", + "ns1/tls1.example.db", + "ns2/__catz__*.db", + "ns2/named.conf.tmp", + "ns2/zonedir", + "ns4/__catz__*.db", + ] +) + + +def test_catz(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/cds/checkmtime.pl b/bin/tests/system/cds/checkmtime.pl new file mode 100644 index 0000000..be53584 --- /dev/null +++ b/bin/tests/system/cds/checkmtime.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +my $target = shift; +my $file = shift; +my $mtime = time - (stat $file)[9]; +die "bad mtime $mtime" + unless ($mtime - $target >= 0 && $mtime - $target < 60); diff --git a/bin/tests/system/cds/checktime.pl b/bin/tests/system/cds/checktime.pl new file mode 100644 index 0000000..d85fd91 --- /dev/null +++ b/bin/tests/system/cds/checktime.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +my $target = shift; +my $notbefore; +my $inception; +while (<>) { + $notbefore = $1 if m{^.* must not be signed before \d+ [(](\d+)[)]}; + $inception = $1 if m{^.* inception time \d+ [(](\d+)[)]}; +} +die "missing notbefore time" unless $notbefore; +die "missing inception time" unless $inception; +my $delta = $inception - $notbefore; +die "bad inception time $delta" unless abs($delta - $target) <= 10; diff --git a/bin/tests/system/cds/mangle.pl b/bin/tests/system/cds/mangle.pl new file mode 100644 index 0000000..9268cc0 --- /dev/null +++ b/bin/tests/system/cds/mangle.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +my $re = $ARGV[0]; +shift; +while (<>) { + s{($re)........}{${1}00000000}; + print; +} diff --git a/bin/tests/system/cds/setup.sh b/bin/tests/system/cds/setup.sh new file mode 100644 index 0000000..27474bc --- /dev/null +++ b/bin/tests/system/cds/setup.sh @@ -0,0 +1,138 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +set -u + +touch empty + +Z=cds.test + +keyz=$($KEYGEN -q -a $DEFAULT_ALGORITHM $Z) +key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK $Z) +key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK $Z) + +idz=$(keyfile_to_key_id $keyz) +id1=$(keyfile_to_key_id $key1) +id2=$(keyfile_to_key_id $key2) + +cat <vars.sh +Z=$Z +key1=$key1 +key2=$key2 +idz=$idz +id1=$id1 +id2=$id2 +EOF + +tac() { + $PERL -e 'print reverse <>' +} + +convert() { + key=$1 + n=$2 + $DSFROMKEY -12 $key >DS.$n + grep " ${DEFAULT_ALGORITHM_NUMBER} 1 " DS.$n >DS.$n-1 + grep " ${DEFAULT_ALGORITHM_NUMBER} 2 " DS.$n >DS.$n-2 + sed 's/ IN DS / IN CDS /' >CDS.$n + sed 's/ IN DS / IN CDS /' >CDS.$n-1 + sed 's/ IN DS / IN CDS /' >CDS.$n-2 + sed 's/ IN DNSKEY / IN CDNSKEY /' <$key.key >CDNSKEY.$n + sed 's/ IN DS / 3600 IN DS /' DS.ttl$n + sed 's/ IN DS / 7200 IN DS /' DS.ttlong$n + tac DS.rev$n +} +convert $key1 1 +convert $key2 2 + +# consistent order wrt IDs +sort DS.1 DS.2 >DS.both + +cp DS.1 DS.inplace +$PERL -we 'utime time, time - 7200, "DS.inplace" or die' + +mangle="$PERL mangle.pl" + +$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} 1 " DS.broke1 +$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} 2 " DS.broke2 +$mangle " IN DS $id1 ${DEFAULT_ALGORITHM_NUMBER} [12] " DS.broke12 + +sed 's/^/update add / +$a\ +send +' UP.add2 + +sed 's/^/update del / +$a\ +send +' UP.del1 + +cat UP.add2 UP.del1 | sed 3d >UP.swap + +sed 's/ add \(.*\) IN DS / add \1 3600 IN DS /' UP.swapttl + +sign() { + cat >db.$1 + $SIGNER >/dev/null \ + -S -O full -o $Z -f sig.$1 db.$1 +} + +sign null <brk.unsigned-cds + +cat db.null CDS.1 | sign cds.1 +cat db.null CDS.2 | sign cds.2 +cat db.null CDS.1 CDS.2 | sign cds.both + +tac sig.cds.rev1 + +cat db.null CDNSKEY.2 | sign cdnskey.2 +cat db.null CDS.2 CDNSKEY.2 | sign cds.cdnskey.2 +cat db.null CDS.1 CDNSKEY.2 | sign cds1.cdnskey2 + +cat db.null CDS.2-1 | sign cds.2.sha1 +cat db.null CDS.2-1 CDNSKEY.2 | sign cds.cdnskey.2.sha1 + +$mangle '\s+IN\s+RRSIG\s+CDS .* '$idz' '$Z'\. ' \ + brk.rrsig.cds.zsk +$mangle '\s+IN\s+RRSIG\s+CDS .* '$id1' '$Z'\. ' \ + brk.rrsig.cds.ksk + +$mangle " IN CDS $id1 ${DEFAULT_ALGORITHM_NUMBER} 1 " out.$n 2>err.$n + echo $? + ) || true +} + +testcase() { + n=$((n + 1)) + echo_i "$name ($n)" + expect=$1 + shift + result=$(runcmd "$@") + check_stdout + check_stderr + if [ "$expect" -ne "$result" ]; then + echo_d "exit status does not match $expect" + fail + fi + unset name err out +} + +check_stderr() { + if [ -n "${err:=}" ]; then + grep -E "$err" err.$n >/dev/null && return 0 + echo_d "stderr did not match '$err'" + else + [ -s err.$n ] || return 0 + fi + cat err.$n | cat_d + fail +} + +check_stdout() { + diff out.$n "${out:-empty}" >/dev/null && return + echo_d "stdout did not match '$out'" + ( + echo "wanted" + cat "$out" + echo "got" + cat out.$n + ) | cat_d + fail +} + +Z=cds.test + +name='usage' +err='Usage' +testcase 1 $CDS + +name='need a DS file' +err='DS pathname' +testcase 1 $CDS $Z + +name='name of dsset in directory' +err="./dsset-$Z.: file not found" +testcase 1 $CDS -d . $Z + +name='load a file' +err='could not find DS records' +testcase 1 $CDS -d empty $Z + +name='load DS records' +err='path to file containing child data must be specified' +testcase 1 $CDS -d DS.1 $Z + +name='missing DNSKEY' +err='could not find signed DNSKEY RRset' +testcase 1 $CDS -f db.null -d DS.1 $Z + +name='sigs too old' +err='could not validate child DNSKEY RRset' +testcase 1 $CDS -f sig.null -d DS.1 $Z + +name='sigs too old, verbosely' +err='skip RRSIG by key [0-9]+: too old' +testcase 1 $CDS -v1 -f sig.null -d DS.1 $Z + +name='old sigs are allowed' +err='found RRSIG by key' +out=DS.1 +testcase 0 $CDS -v1 -s -7200 -f sig.null -d DS.1 $Z + +name='no CDS/CDNSKEY records' +out=DS.1 +testcase 0 $CDS -s -7200 -f sig.null -d DS.1 $Z + +name='no child records, verbosely' +err='has neither CDS nor CDNSKEY records' +out=DS.1 +testcase 0 $CDS -v1 -s -7200 -f sig.null -d DS.1 $Z + +name='unsigned CDS' +err='missing RRSIG CDS records' +testcase 1 $CDS -f brk.unsigned-cds -d DS.1 $Z + +name='correct signature inception time' +$CDS -v3 -s -7200 -f sig.cds.1 -d DS.1 $Z 1>xout 2>xerr +testcase 0 $PERL checktime.pl 3600 xerr + +name='in-place reads modification time' +testcase 0 $CDS -a1 -a2 -f sig.cds.1 -i.bak -d DS.inplace $Z + +name='in-place output correct modification time' +testcase 0 $PERL checkmtime.pl 3600 DS.inplace + +name='in-place backup correct modification time' +testcase 0 $PERL checkmtime.pl 7200 DS.inplace.bak + +name='in-place correct output' +testcase 0 diff DS.1 DS.inplace + +name='in-place backup unmodified' +testcase 0 diff DS.1 DS.inplace.bak + +name='one mangled DS' +err='found RRSIG by key' +out=DS.1 +testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke1 $Z + +name='other mangled DS' +err='found RRSIG by key' +out=DS.1 +testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke2 $Z + +name='both mangled DS' +err='could not validate child DNSKEY RRset' +testcase 1 $CDS -v1 -a1 -a2 -s -7200 -f sig.cds.1 -d DS.broke12 $Z + +name='mangle RRSIG CDS by ZSK' +err='found RRSIG by key' +out=DS.1 +testcase 0 $CDS -v1 -a1 -a2 -s -7200 -f brk.rrsig.cds.zsk -d DS.1 $Z + +name='mangle RRSIG CDS by KSK' +err='could not validate child CDS RRset' +testcase 1 $CDS -v1 -s -7200 -f brk.rrsig.cds.ksk -d DS.1 $Z + +name='mangle CDS 1' +err='could not validate child DNSKEY RRset with new DS records' +testcase 1 $CDS -a1 -a2 -s -7200 -f sig.cds-mangled -d DS.1 $Z + +name='inconsistent digests' +err='do not cover each key with the same set of digest types' +testcase 1 $CDS -a1 -a2 -s -7200 -f sig.bad-digests -d DS.1 $Z + +name='inconsistent algorithms' +err='missing signature for algorithm' +testcase 1 $CDS -s -7200 -f sig.bad-algos -d DS.1 $Z + +name='add DS records' +out=DS.both +$CDS -a1 -a2 -s -7200 -f sig.cds.both -d DS.1 $Z >DS.out +# sort to allow for numerical vs lexical order of key tags +testcase 0 sort DS.out + +name='update add' +out=UP.add2 +testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.both -d DS.1 $Z + +name='remove DS records' +out=DS.2 +testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.2 -d DS.both $Z + +name='update del' +out=UP.del1 +testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.both $Z + +name='swap DS records' +out=DS.2 +testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.2 -d DS.1 $Z + +name='update swap' +out=UP.swap +testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.1 $Z + +name='TTL from -T' +out=DS.ttl2 +testcase 0 $CDS -a1 -a2 -T 3600 -s -7200 -f sig.cds.2 -d DS.1 $Z + +name='update TTL from -T' +out=UP.swapttl +testcase 0 $CDS -a1 -a2 -u -T 3600 -s -7200 -f sig.cds.2 -d DS.1 $Z + +name='update TTL from dsset' +out=UP.swapttl +testcase 0 $CDS -a1 -a2 -u -s -7200 -f sig.cds.2 -d DS.ttl1 $Z + +name='TTL from -T overrides dsset' +out=DS.ttlong2 +testcase 0 $CDS -a1 -a2 -T 7200 -s -7200 -f sig.cds.2 -d DS.ttl1 $Z + +name='stable DS record order (changes)' +out=DS.1 +testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.rev1 -d DS.2 $Z + +name='CDNSKEY default algorithm' +out=DS.2-2 +testcase 0 $CDS -s -7200 -f sig.cdnskey.2 -d DS.1 $Z + +name='CDNSKEY SHA1' +out=DS.2-1 +testcase 0 $CDS -a SHA1 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z + +name='CDNSKEY two algorithms' +out=DS.2 +testcase 0 $CDS -a SHA1 -a SHA256 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z + +name='CDNSKEY two algorithms, reversed' +out=DS.2 +testcase 0 $CDS -a SHA256 -a SHA1 -s -7200 -f sig.cdnskey.2 -d DS.1 $Z + +name='CDNSKEY and CDS' +out=DS.2 +testcase 0 $CDS -a1 -a2 -s -7200 -f sig.cds.cdnskey.2 -d DS.1 $Z + +name='prefer CDNSKEY' +out=DS.2-2 +testcase 0 $CDS -D -s -7200 -f sig.cds1.cdnskey2 -d DS.1 $Z + +name='CDS subset default (SHA-256)' +out=DS.2-2 +testcase 0 $CDS -s -7200 -f sig.cds.2 -d DS.1 $Z + +name='CDS subset replace SHA1 with SHA2' +out=DS.2-2 +testcase 0 $CDS -s -7200 -f sig.cds.cdnskey.2.sha1 -d DS.1 $Z + +name='CDS subset mismatch' +err='do not match any -a digest types' +testcase 1 $CDS -s -7200 -f sig.cds.2.sha1 -d DS.1 $Z + +name='CDS algorithm unavailable, use CDNSKEY' +err='using CDNSKEY instead' +out=DS.2-2 +testcase 0 $CDS -v1 -a SHA256 -s -7200 -f sig.cds.cdnskey.2.sha1 -d DS.1 $Z + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/cds/tests_sh_cds.py b/bin/tests/system/cds/tests_sh_cds.py new file mode 100644 index 0000000..3a99ac1 --- /dev/null +++ b/bin/tests/system/cds/tests_sh_cds.py @@ -0,0 +1,35 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "CDNSKEY.*", + "CDS.*", + "DS.*", + "K*", + "UP.*", + "brk.*", + "db.*", + "empty", + "err.*", + "out.*", + "sig.*", + "vars.sh", + "xerr", + "xout", + ] +) + + +def test_cds(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/chain/README b/bin/tests/system/chain/README new file mode 100644 index 0000000..649142e --- /dev/null +++ b/bin/tests/system/chain/README @@ -0,0 +1,22 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +ns1 is the root server. + +ns2 and ns5 are both authoritative servers. + +ans3 is a mock authoritative server that can return various broken +responses. + +ans4 is a mock authoritative server that can return CNAME or DNAME +responses of arbitrary size in arbitrary order. + +ns7 is the resolver under test. diff --git a/bin/tests/system/chain/ans3/ans.pl b/bin/tests/system/chain/ans3/ans.pl new file mode 100644 index 0000000..434eaa9 --- /dev/null +++ b/bin/tests/system/chain/ans3/ans.pl @@ -0,0 +1,167 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +use IO::File; +use Getopt::Long; +use Net::DNS::Nameserver; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; +sub term { }; + +$SIG{INT} = \&rmpid; +if ($Net::DNS::VERSION > 1.41) { + $SIG{TERM} = \&term; +} else { + $SIG{TERM} = \&rmpid; +} + +my $localaddr = "10.53.0.3"; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $verbose = 0; +my $ttl = 60; +my $zone = "example.broken"; +my $nsname = "ns3.$zone"; +my $synth = "synth-then-dname.$zone"; +my $synth2 = "synth2-then-dname.$zone"; + +sub reply_handler { + my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_; + my ($rcode, @ans, @auth, @add); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + if ($qname eq "example.broken") { + if ($qtype eq "SOA") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0"); + push @ans, $rr; + } elsif ($qtype eq "NS") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass NS $nsname"); + push @ans, $rr; + $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr"); + push @add, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "cname-to-$synth2") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name.$synth2"); + push @ans, $rr; + $rr = new Net::DNS::RR("name.$synth2 $ttl $qclass CNAME name"); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "$synth" || $qname eq "$synth2") { + if ($qtype eq "DNAME") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME ."); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "name.$synth") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name."); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "name.$synth2") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME name."); + push @ans, $rr; + $rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME ."); + push @ans, $rr; + $rcode = "NOERROR"; + # The following three code branches referring to the "example.dname" + # zone are necessary for the resolver variant of the CVE-2021-25215 + # regression test to work. A named instance cannot be used for + # serving the DNAME records below as a version of BIND vulnerable to + # CVE-2021-25215 would crash while answering the queries asked by + # the tested resolver. + } elsif ($qname eq "ns3.example.dname") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass A 10.53.0.3"); + push @ans, $rr; + } + if ($qtype eq "AAAA") { + my $rr = new Net::DNS::RR("example.dname. $ttl $qclass SOA . . 0 0 0 0 $ttl"); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "self.example.self.example.dname") { + my $rr = new Net::DNS::RR("self.example.dname. $ttl $qclass DNAME dname."); + push @ans, $rr; + $rr = new Net::DNS::RR("$qname $ttl $qclass CNAME self.example.dname."); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "self.example.dname") { + if ($qtype eq "DNAME") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME dname."); + push @ans, $rr; + } + $rcode = "NOERROR"; + # The next few branches produce a zone with an illegal NS below a DNAME. + } elsif ($qname eq "jeff.dname") { + if ($qtype eq "SOA") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass SOA . . 0 0 0 0 0"); + push @ans, $rr; + } elsif ($qtype eq "NS") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass NS ns.jeff.dname."); + push @ans, $rr; + $rr = new Net::DNS::RR("$nsname $ttl $qclass A $localaddr"); + push @add, $rr; + } elsif ($qtype eq "DNAME") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME mutt.example."); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "ns.jeff.dname") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR("$qname $ttl $qclass A 10.53.0.3"); + push @ans, $rr; + } elsif ($qtype eq "AAAA") { + my $rr = new Net::DNS::RR("jeff.dname. $ttl $qclass SOA . . 0 0 0 0 $ttl"); + push @auth, $rr; + } + $rcode = "NOERROR"; + } else { + $rcode = "REFUSED"; + } + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); +} + +GetOptions( + 'port=i' => \$localport, + 'verbose!' => \$verbose, +); + +my $ns = Net::DNS::Nameserver->new( + LocalAddr => $localaddr, + LocalPort => $localport, + ReplyHandler => \&reply_handler, + Verbose => $verbose, +); + +if ($Net::DNS::VERSION >= 1.42) { + $ns->start_server(); + select(undef, undef, undef, undef); + $ns->stop_server(); + unlink "ans.pid"; +} else { + $ns->main_loop; +} diff --git a/bin/tests/system/chain/ans4/README.anspy b/bin/tests/system/chain/ans4/README.anspy new file mode 100644 index 0000000..7cb0bf0 --- /dev/null +++ b/bin/tests/system/chain/ans4/README.anspy @@ -0,0 +1,24 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +REQUIREMENTS +ans.py requires at least dnspython 1.12.0. + +"ans.py" is a fairly simple Python script that will respond as an +authoritative server to DNS queries. It opens a UDP socket on 10.53.0.4 +and fd92:7065:b8e:ffff::8, port 5300 (or PORT) (these are for DNS queries) +and a TCP socket addresses on 10.53.0.4 at port 5301 (or EXTRAPORT1) +(this is the control channel). + +Please note that all functionality and formatting are subject to change as +we determine what features the tool will need. + +"ans.py" will respond to queries as follows: TBD diff --git a/bin/tests/system/chain/ans4/ans.py b/bin/tests/system/chain/ans4/ans.py new file mode 100755 index 0000000..839067f --- /dev/null +++ b/bin/tests/system/chain/ans4/ans.py @@ -0,0 +1,386 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +############################################################################ +# ans.py: See README.anspy for details. +############################################################################ + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import functools + +import dns, dns.message, dns.query +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + +############################################################################ +# set up the RRs to be returned in the next answer +# +# the message contains up to two pipe-separated ('|') fields. +# +# the first field of the message is a comma-separated list +# of actions indicating what to put into the answer set +# (e.g., a dname, a cname, another cname, etc) +# +# supported actions: +# - cname (cname from the current name to a new one in the same domain) +# - dname (dname to a new domain, plus a synthesized cname) +# - xname ("external" cname, to a new name in a new domain) +# +# example: xname, dname, cname represents a CNAME to an external +# domain which is then answered by a DNAME and synthesized +# CNAME pointing to yet another domain, which is then answered +# by a CNAME within the same domain, and finally an answer +# to the query. each RR in the answer set has a corresponding +# RRSIG. these signatures are not valid, but will exercise the +# response parser. +# +# the second field is a comma-separated list of which RRs in the +# answer set to include in the answer, in which order. if prepended +# with 's', the number indicates which signature to include. +# +# examples: for the answer set "cname, cname, cname", an rr set +# '1, s1, 2, s2, 3, s3, 4, s4' indicates that all four RRs should +# be included in the answer, with siagntures, in the original +# order, while 4, s4, 3, s3, 2, s2, 1, s1' indicates the order +# should be reversed, 's3, s3, s3, s3' indicates that the third +# RRSIG should be repeated four times and everything else should +# be omitted, and so on. +# +# if there is no second field (i.e., no pipe symbol appears in +# the line) , the default is to send all answers and signatures. +# if a pipe symbol exists but the second field is empty, then +# nothing is sent at all. +############################################################################ +actions = [] +rrs = [] + + +def ctl_channel(msg): + global actions, rrs + + msg = msg.splitlines().pop(0) + print("received control message: %s" % msg) + + msg = msg.split(b"|") + if len(msg) == 0: + return + + actions = [x.strip() for x in msg[0].split(b",")] + n = functools.reduce( + lambda n, act: (n + (2 if act == b"dname" else 1)), [0] + actions + ) + + if len(msg) == 1: + rrs = [] + for i in range(n): + for b in [False, True]: + rrs.append((i, b)) + return + + rlist = [x.strip() for x in msg[1].split(b",")] + rrs = [] + for item in rlist: + if item[0] == b"s"[0]: + i = int(item[1:].strip()) - 1 + if i > n: + print("invalid index %d" + (i + 1)) + continue + rrs.append((int(item[1:]) - 1, True)) + else: + i = int(item) - 1 + if i > n: + print("invalid index %d" % (i + 1)) + continue + rrs.append((i, False)) + + +############################################################################ +# Respond to a DNS query. +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + labels = qname.lower().split(".") + wantsigs = True if m.ednsflags & dns.flags.DO else False + + # get qtype + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + + # for 'www.example.com.'... + # - name is 'www' + # - domain is 'example.com.' + # - sld is 'example' + # - tld is 'com.' + name = labels.pop(0) + domain = ".".join(labels) + sld = labels.pop(0) + tld = ".".join(labels) + + print("query: " + qname + "/" + typename) + print("domain: " + domain) + + # default answers, depending on QTYPE. + # currently only A, AAAA, TXT and NS are supported. + ttl = 86400 + additionalA = "10.53.0.4" + additionalAAAA = "fd92:7065:b8e:ffff::4" + if typename == "A": + final = "10.53.0.4" + elif typename == "AAAA": + final = "fd92:7065:b8e:ffff::4" + elif typename == "TXT": + final = "Some\ text\ here" + elif typename == "NS": + domain = qname + final = "ns1.%s" % domain + else: + final = None + + # RRSIG rdata - won't validate but will exercise response parsing + t = datetime.now() + delta = timedelta(30) + t1 = t - delta + t2 = t + delta + inception = t1.strftime("%Y%m%d000000") + expiry = t2.strftime("%Y%m%d000000") + sigdata = "OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso=" + + # construct answer set. + answers = [] + sigs = [] + curdom = domain + curname = name + i = 0 + + for action in actions: + if name != "test": + continue + if action == b"xname": + owner = curname + "." + curdom + newname = "cname%d" % i + i += 1 + newdom = "domain%d.%s" % (i, tld) + i += 1 + target = newname + "." + newdom + print("add external CNAME %s to %s" % (owner, target)) + answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add external RRISG(CNAME) %s to %s" % (owner, target)) + sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) + curname = newname + curdom = newdom + continue + + if action == b"cname": + owner = curname + "." + curdom + newname = "cname%d" % i + target = newname + "." + curdom + i += 1 + print("add CNAME %s to %s" % (owner, target)) + answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(CNAME) %s to %s" % (owner, target)) + sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) + curname = newname + continue + + if action == b"dname": + owner = curdom + newdom = "domain%d.%s" % (i, tld) + i += 1 + print("add DNAME %s to %s" % (owner, newdom)) + answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom)) + rrsig = "DNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(DNAME) %s to %s" % (owner, newdom)) + sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) + owner = curname + "." + curdom + target = curname + "." + newdom + print("add synthesized CNAME %s to %s" % (owner, target)) + answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add synthesized RRSIG(CNAME) %s to %s" % (owner, target)) + sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) + curdom = newdom + continue + + # now add the final answer + owner = curname + "." + curdom + answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final)) + rrsig = "%s 5 3 %d %s %s 12345 %s %s" % ( + typename, + ttl, + expiry, + inception, + domain, + sigdata, + ) + sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) + + # prepare the response and convert to wire format + r = dns.message.make_response(m) + + if name != "test": + r.answer.append(answers[-1]) + if wantsigs: + r.answer.append(sigs[-1]) + else: + for i, sig in rrs: + if sig and not wantsigs: + continue + elif sig: + r.answer.append(sigs[i]) + else: + r.answer.append(answers[i]) + + if typename != "NS": + r.authority.append( + dns.rrset.from_text(domain, ttl, IN, "NS", ("ns1.%s" % domain)) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, A, additionalA) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, AAAA, additionalAAAA) + ) + + r.flags |= dns.flags.AA + r.use_edns() + return r.to_wire() + + +def sigterm(signum, frame): + print("Shutting down now...") + os.remove("ans.pid") + running = False + sys.exit(0) + + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.4" +ip6 = "fd92:7065:b8e:ffff::4" + +try: + port = int(os.environ["PORT"]) +except: + port = 5300 + +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) + +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False + +ctrl_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +ctrl_socket.bind((ip4, ctrlport)) +ctrl_socket.listen(5) + +signal.signal(signal.SIGTERM, sigterm) + +f = open("ans.pid", "w") +pid = os.getpid() +print(pid, file=f) +f.close() + +running = True + +print("Listening on %s port %d" % (ip4, port)) +if havev6: + print("Listening on %s port %d" % (ip6, port)) +print("Control channel on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket, ctrl_socket] +else: + input = [query4_socket, ctrl_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == ctrl_socket: + # Handle control channel input + conn, addr = s.accept() + print("Control channel connected") + while True: + msg = conn.recv(65535) + if not msg: + break + ctl_channel(msg) + conn.close() + if s == query4_socket or s == query6_socket: + print("Query received on %s" % (ip4 if s == query4_socket else ip6)) + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + s.sendto(rsp, msg[1]) + if not running: + break diff --git a/bin/tests/system/chain/ns1/named.conf.in b/bin/tests/system/chain/ns1/named.conf.in new file mode 100644 index 0000000..95ccf89 --- /dev/null +++ b/bin/tests/system/chain/ns1/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation yes; + notify yes; +}; + +trust-anchors { }; + +zone "." { type primary; file "root.db"; }; diff --git a/bin/tests/system/chain/ns1/root.db b/bin/tests/system/chain/ns1/root.db new file mode 100644 index 0000000..1c99ba8 --- /dev/null +++ b/bin/tests/system/chain/ns1/root.db @@ -0,0 +1,55 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA root.domain.nil a.root.servers.nil. ( + 2016012800 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 + +example.broken. NS ns3.example.broken. +ns3.example.broken. A 10.53.0.3 + +; for the resolver variant of the CVE-2021-25215 regression test +example.dname. NS ns3.example.dname. +ns3.example.dname. A 10.53.0.3 + +; regression test for illegal NS below DNAME +jeff.dname. NS ns.jeff.dname. +ns.jeff.dname. A 10.53.0.3 + +domain0.nil. NS ns2.domain0.nil +domain1.nil. NS ns2.domain0.nil +domain2.nil. NS ns2.domain0.nil +domain3.nil. NS ns2.domain0.nil +domain4.nil. NS ns2.domain0.nil +domain5.nil. NS ns2.domain0.nil +domain6.nil. NS ns2.domain0.nil +domain7.nil. NS ns2.domain0.nil +domain8.nil. NS ns2.domain0.nil +domain9.nil. NS ns2.domain0.nil +ns2.domain0.nil. A 10.53.0.2 +ns2.domain0.nil. AAAA fd92:7065:b8e:ffff::2 + +domain.nil. NS ns4.domain.nil +ns4.domain.nil. A 10.53.0.4 +ns4.domain.nil. AAAA fd92:7065:b8e:ffff::4 + +domain. NS ns4.domain. +ns4.domain. A 10.53.0.4 diff --git a/bin/tests/system/chain/ns2/example.db b/bin/tests/system/chain/ns2/example.db new file mode 100644 index 0000000..a5a4811 --- /dev/null +++ b/bin/tests/system/chain/ns2/example.db @@ -0,0 +1,72 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a.short A 10.0.0.1 +short-dname DNAME short +a.longlonglonglonglonglonglonglonglonglonglonglonglong A 10.0.0.2 +long-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong +toolong-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong +cname CNAME a.cnamedname +cnamedname DNAME target +a.target A 10.0.0.3 + +; CNAME to delegation +; (unsigned delegations, external and internal) +sub5 NS ns5.sub5 +ns5.sub5 A 10.53.0.5 +a CNAME a.sub5 +sub2 NS ns2.sub2 +ns2.sub2 A 10.53.0.2 +b CNAME b.sub2 + +; (signed delegation, external and internal) +; note: these DS records are fake and will not validate; we're only +; testing that the resolver handles their presence in a reply correctly +signed-sub5 NS ns5.sub5 +signed-sub5 DS 44137 8 2 1CB4F54E0B4F4F85109143113A3C679716A2377D86EB0907846A03FB 0C0A3927 +c CNAME c.signed-sub5 +signed-sub2 NS ns2.sub2 +signed-sub2 DS 44137 8 2 1CB4F54E0B4F4F85109143113A3C679716A2377D86EB0907846A03FB 0C0A3927 +d CNAME d.signed-sub2 + +mutt NS ns5.mutt +ns5.mutt A 10.53.0.5 + +; long CNAME loop +loop CNAME goop +goop CNAME boop +boop CNAME soup +soup CNAME gump +gump CNAME bump +bump CNAME lump +lump CNAME rump +rump CNAME romp +romp CNAME bomp +bomp CNAME stomp +stomp CNAME clomp +clomp CNAME clump +clump CNAME hunk +hunk CNAME hank +hank CNAME bank +bank CNAME wank +wank CNAME woop +woop CNAME loop diff --git a/bin/tests/system/chain/ns2/generic.db b/bin/tests/system/chain/ns2/generic.db new file mode 100644 index 0000000..9d59378 --- /dev/null +++ b/bin/tests/system/chain/ns2/generic.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 86400 SOA ns2.domain0.nil. hostmaster.ns2.nil. 0 1 1 1 1 +@ 86400 NS ns2.domain0.nil. +ns2 86400 A 10.53.0.2 +ns2 86400 AAAA fd92:7065:b8e:ffff::2 + +@ 86400 A 1.2.3.4 +@ 86400 AAAA 1:2:3::4 +* 86400 A 1.2.3.4 +* 86400 AAAA 1:2:3::4 +; CVE-2021-25215 regression test data +self 86400 DNAME nil. diff --git a/bin/tests/system/chain/ns2/named.conf.in b/bin/tests/system/chain/ns2/named.conf.in new file mode 100644 index 0000000..6f75c07 --- /dev/null +++ b/bin/tests/system/chain/ns2/named.conf.in @@ -0,0 +1,79 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; +}; + +zone . { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db.signed"; + allow-update { any; }; +}; + +zone "sub2.example" { + type primary; + file "sub.db"; +}; + +zone "signed-sub2.example" { + type primary; + file "sub.db"; +}; + +zone "wildcard-secure.example" { + type primary; + file "wildcard-secure.example.db.signed"; +}; + +zone "wildcard-nsec.example" { + type primary; + file "wildcard-nsec.example.db.signed"; +}; + +zone "wildcard-nsec3.example" { + type primary; + file "wildcard-nsec3.example.db.signed"; +}; + +zone "wildcard-nsec3-optout.example" { + type primary; + file "wildcard-nsec3-optout.example.db.signed"; +}; + +zone "domain0.nil" { type primary; file "generic.db"; }; +zone "domain1.nil" { type primary; file "generic.db"; }; +zone "domain2.nil" { type primary; file "generic.db"; }; +zone "domain3.nil" { type primary; file "generic.db"; }; +zone "domain4.nil" { type primary; file "generic.db"; }; +zone "domain5.nil" { type primary; file "generic.db"; }; +zone "domain6.nil" { type primary; file "generic.db"; }; +zone "domain7.nil" { type primary; file "generic.db"; }; +zone "domain8.nil" { type primary; file "generic.db"; }; +zone "domain9.nil" { type primary; file "generic.db"; }; diff --git a/bin/tests/system/chain/ns2/sign.sh b/bin/tests/system/chain/ns2/sign.sh new file mode 100644 index 0000000..f2b9e12 --- /dev/null +++ b/bin/tests/system/chain/ns2/sign.sh @@ -0,0 +1,54 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=example. +zonefile=example.db +signedfile=example.db.signed + +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone) +$SIGNER -S -o $zone -f $signedfile $zonefile >/dev/null + +zone=wildcard-secure.example. +zonefile=wildcard-secure.db +signedfile=wildcard-secure.example.db.signed + +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone) +$SIGNER -S -o $zone -f $signedfile $zonefile >/dev/null + +zone=wildcard-nsec.example. +zonefile=wildcard.db +signedfile=wildcard-nsec.example.db.signed + +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone) +$SIGNER -S -o $zone -f $signedfile $zonefile >/dev/null + +zone=wildcard-nsec3.example. +zonefile=wildcard.db +signedfile=wildcard-nsec3.example.db.signed + +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone) +$SIGNER -S -3 - -H 0 -o $zone -f $signedfile $zonefile >/dev/null + +zone=wildcard-nsec3-optout.example. +zonefile=wildcard.db +signedfile=wildcard-nsec3-optout.example.db.signed + +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -b ${DEFAULT_BITS} $zone) +$SIGNER -S -3 - -H 0 -A -o $zone -f $signedfile $zonefile >/dev/null diff --git a/bin/tests/system/chain/ns2/sub.db b/bin/tests/system/chain/ns2/sub.db new file mode 100644 index 0000000..ad03165 --- /dev/null +++ b/bin/tests/system/chain/ns2/sub.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2017031001 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 diff --git a/bin/tests/system/chain/ns2/wildcard-secure.db b/bin/tests/system/chain/ns2/wildcard-secure.db new file mode 100644 index 0000000..e39237a --- /dev/null +++ b/bin/tests/system/chain/ns2/wildcard-secure.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2021051901 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS localhost. + +delegation NS localhost. + DS 12345 13 2 0000000000000000000000000000000000000000000000000000000000000000 + +; CNAME pointing into a child zone +cname CNAME delegation + +; wildcard CNAME pointing at a CNAME pointing into a child zone +* CNAME cname diff --git a/bin/tests/system/chain/ns2/wildcard.db b/bin/tests/system/chain/ns2/wildcard.db new file mode 100644 index 0000000..cc39e9c --- /dev/null +++ b/bin/tests/system/chain/ns2/wildcard.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2021051901 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS localhost. + +delegation NS localhost. + +; CNAME pointing into a child zone +cname CNAME delegation + +; wildcard CNAME pointing at a CNAME pointing into a child zone +* CNAME cname diff --git a/bin/tests/system/chain/ns5/named.conf.in b/bin/tests/system/chain/ns5/named.conf.in new file mode 100644 index 0000000..00f0de5 --- /dev/null +++ b/bin/tests/system/chain/ns5/named.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "sub5.example" { + type primary; + file "sub.db"; +}; + +zone "signed-sub5.example" { + type primary; + file "sub.db"; +}; + +zone "mutt.example" { + type primary; + file "mutt.db"; +}; diff --git a/bin/tests/system/chain/ns5/sub.db b/bin/tests/system/chain/ns5/sub.db new file mode 100644 index 0000000..df571fb --- /dev/null +++ b/bin/tests/system/chain/ns5/sub.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2017031001 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns5 +ns5 A 10.53.0.5 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 diff --git a/bin/tests/system/chain/ns7/named.conf.in b/bin/tests/system/chain/ns7/named.conf.in new file mode 100644 index 0000000..0d95bc8 --- /dev/null +++ b/bin/tests/system/chain/ns7/named.conf.in @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { fd92:7065:b8e:ffff::7; }; + recursion yes; + allow-recursion { any; }; + dnssec-validation yes; + deny-answer-aliases { + "example"; + } except-from { + "example"; + }; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key restart16 { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view restart16 { + match-clients { key restart16; none; }; + max-query-restarts 16; + + zone "." { + type hint; + file "root.hint"; + }; +}; + +view default { + zone "." { + type hint; + file "root.hint"; + }; +}; diff --git a/bin/tests/system/chain/ns7/root.hint b/bin/tests/system/chain/ns7/root.hint new file mode 100644 index 0000000..4f3f48b --- /dev/null +++ b/bin/tests/system/chain/ns7/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/chain/prereq.sh b/bin/tests/system/chain/prereq.sh new file mode 100644 index 0000000..fe84055 --- /dev/null +++ b/bin/tests/system/chain/prereq.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS::Nameserver -e ''; then + echo_i "perl Net::DNS::Nameserver module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/chain/setup.sh b/bin/tests/system/chain/setup.sh new file mode 100644 index 0000000..6f52e65 --- /dev/null +++ b/bin/tests/system/chain/setup.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns7/named.conf.in ns7/named.conf + +cd ns2 +$SHELL sign.sh diff --git a/bin/tests/system/chain/tests.sh b/bin/tests/system/chain/tests.sh new file mode 100644 index 0000000..7128b6c --- /dev/null +++ b/bin/tests/system/chain/tests.sh @@ -0,0 +1,653 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +sendcmd() { + send 10.53.0.4 "${EXTRAPORT1}" +} + +status=0 +n=0 + +n=$((n + 1)) +echo_i "checking short DNAME from authoritative ($n)" +ret=0 +$DIG $DIGOPTS a.short-dname.example @10.53.0.2 a >dig.out.ns2.short || ret=1 +grep "status: NOERROR" dig.out.ns2.short >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking short DNAME from recursive ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS a.short-dname.example @10.53.0.7 a >dig.out.ns4.short || ret=1 +grep "status: NOERROR" dig.out.ns4.short >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking long DNAME from authoritative ($n)" +ret=0 +$DIG $DIGOPTS a.long-dname.example @10.53.0.2 a >dig.out.ns2.long || ret=1 +grep "status: NOERROR" dig.out.ns2.long >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking long DNAME from recursive ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS a.long-dname.example @10.53.0.7 a >dig.out.ns4.long || ret=1 +grep "status: NOERROR" dig.out.ns4.long >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking (too) long DNAME from authoritative ($n)" +ret=0 +$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.2 a >dig.out.ns2.toolong || ret=1 +grep "status: YXDOMAIN" dig.out.ns2.toolong >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking (too) long DNAME from recursive with cached DNAME ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.7 a >dig.out.ns4.cachedtoolong || ret=1 +grep "status: YXDOMAIN" dig.out.ns4.cachedtoolong >/dev/null || ret=1 +grep '^long-dname\.example\..*DNAME.*long' dig.out.ns4.cachedtoolong >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking (too) long DNAME from recursive without cached DNAME ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglong.toolong-dname.example @10.53.0.7 a >dig.out.ns4.uncachedtoolong || ret=1 +grep "status: YXDOMAIN" dig.out.ns4.uncachedtoolong >/dev/null || ret=1 +grep '^toolong-dname\.example\..*DNAME.*long' dig.out.ns4.uncachedtoolong >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +find_records() { + owner_name="$1" + rr_type="$2" + file="$3" + awk '$1 == "'"$owner_name"'" && $4 == "'"$rr_type"'" { print }' <"$file" +} + +count_records() { + owner_name="$1" + rr_type="$2" + file="$3" + find_records "$owner_name" "$rr_type" "$file" | wc -l +} + +exactly_one_record_exists_for() { + owner_name="$1" + rr_type="$2" + file="$3" + test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 1 +} + +no_records_exist_for() { + owner_name="$1" + rr_type="$2" + file="$3" + test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 0 +} + +ensure_no_ds_in_bitmap() { + owner_name="$1" + rr_type="$2" + file="$3" + case "$rr_type" in + NSEC) start_index=6 ;; + NSEC3) start_index=10 ;; + *) exit 1 ;; + esac + find_records "$owner_name" "$rr_type" "$file" | awk '{ for (i='"$start_index"'; i<=NF; i++) if ($i == "DS") exit 1 }' +} + +n=$((n + 1)) +echo_i "checking secure delegation prepared using CNAME chaining ($n)" +ret=0 +# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a +# DS RRset. +$DIG $DIGOPTS @10.53.0.2 cname.wildcard-secure.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains the expected NS and DS RRsets. +exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1 +exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking secure delegation prepared using wildcard expansion + CNAME chaining ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset, an +# NSEC record proving nonexistence of QNAME, and a DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-secure.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains the expected NS and DS RRsets. +exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1 +exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1 +# Check NSEC records in the AUTHORITY section. +no_records_exist_for "wildcard-secure.example." NSEC dig.out.2.$n || ret=1 +exactly_one_record_exists_for "*.wildcard-secure.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "cname.wildcard-secure.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-secure.example." NSEC dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using CNAME chaining, NSEC ($n)" +ret=0 +# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a +# single NSEC record proving nonexistence of a DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1 +# Check NSEC records in the AUTHORITY section. +no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +# Ensure the NSEC record for the zone cut does not have the DS bit set in the +# type bit map. +ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #1 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, these two NSEC records are different. +$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1 +# Check NSEC records in the AUTHORITY section. +no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +exactly_one_record_exists_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +# Ensure the NSEC record for the zone cut does not have the DS bit set in the +# type bit map. +ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #2 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, the same NSEC record proves nonexistence of both the +# QNAME and the DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1 +# Check NSEC records in the AUTHORITY section. +no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +# Ensure the NSEC record for the zone cut does not have the DS bit set in the +# type bit map. +ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Relevant NSEC3 hashes: +# +# - existing names: +# +# $ nsec3hash - 1 0 wildcard-nsec3.example. +# 38IVP9CN0LBISO6H3V5REQCKMTHLI5AN (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 cname.wildcard-nsec3.example. +# 3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 delegation.wildcard-nsec3.example. +# AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 *.wildcard-nsec3.example. +# Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2 (salt=-, hash=1, iterations=0) +# +# - nonexistent names: +# +# $ nsec3hash - 1 0 a-nonexistent-name.wildcard-nsec3.example. +# PST9IH6M0DG3M139CO3G12NUP4ER88SH (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3.example. +# SG2DEHEAOGCKP7FTNQAUVC3I3TIPJH0J (salt=-, hash=1, iterations=0) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 ($n)" +ret=0 +# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a +# single NSEC3 record proving nonexistence of a DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #1 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, these two NSEC3 records are different. +$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #2 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, the same NSEC3 record proves nonexistence of both the +# QNAME and the DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec3.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Relevant NSEC3 hashes: +# +# - existing names with corresponding NSEC3 records: +# +# $ nsec3hash - 1 0 *.wildcard-nsec3-optout.example. +# 2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 cname.wildcard-nsec3-optout.example. +# OKRFKC9SS1O60E8U2980UD62MUSMKGUG (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 wildcard-nsec3-optout.example. +# SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI (salt=-, hash=1, iterations=0) +# +# - existing name with no corresponding NSEC3 record due to opt-out: +# +# $ nsec3hash - 1 0 delegation.wildcard-nsec3-optout.example. +# UFP8PVECFTD57HU5PUD2HE0ES37QEOAP (salt=-, hash=1, iterations=0) +# +# - nonexistent names: +# +# $ nsec3hash - 1 0 b-nonexistent-name.wildcard-nsec3-optout.example. +# 3J38JE2OU0O7B4CE2ADMBBKJ5HT994S5 (salt=-, hash=1, iterations=0) +# $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3-optout.example. +# V7OTS4791T9SU0HKVL93EVNAJ9JH2CH3 (salt=-, hash=1, iterations=0) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 with opt-out ($n)" +ret=0 +# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a +# single NSEC3 record proving nonexistence of a DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3-optout.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #1 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, these two NSEC3 records are different. +$DIG $DIGOPTS @10.53.0.2 b-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +exactly_one_record_exists_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #2 ($n)" +ret=0 +# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and +# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone +# cut. In this test case, the same NSEC3 record proves nonexistence of both the +# QNAME and the DS RRset at the zone cut. +$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec >dig.out.2.$n 2>&1 || ret=1 +# Ensure that the AUTHORITY section contains an NS RRset without an associated +# DS RRset. +exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1 +no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1 +# Check NSEC3 records in the AUTHORITY section. +no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in +# the type bit map. +ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to DNAME from authoritative ($n)" +ret=0 +$DIG $DIGOPTS cname.example @10.53.0.2 a >dig.out.ns2.cname +grep "status: NOERROR" dig.out.ns2.cname >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to DNAME from recursive" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS cname.example @10.53.0.7 a >dig.out.ns4.cname +grep "status: NOERROR" dig.out.ns4.cname >/dev/null || ret=1 +grep '^cname.example.' dig.out.ns4.cname >/dev/null || ret=1 +grep '^cnamedname.example.' dig.out.ns4.cname >/dev/null || ret=1 +grep '^a.cnamedname.example.' dig.out.ns4.cname >/dev/null || ret=1 +grep '^a.target.example.' dig.out.ns4.cname >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME is returned with synthesized CNAME before DNAME ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 name.synth-then-dname.example.broken A >dig.out.test$n +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep '^name.synth-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n >/dev/null || ret=1 +grep '^synth-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME is returned with CNAME to synthesized CNAME before DNAME ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 cname-to-synth2-then-dname.example.broken A >dig.out.test$n +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep '^cname-to-synth2-then-dname\.example\.broken\..*CNAME.*name\.synth2-then-dname\.example\.broken.$' dig.out.test$n >/dev/null || ret=1 +grep '^name\.synth2-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n >/dev/null || ret=1 +grep '^synth2-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME loops are detected (resolver) ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 loop.example >dig.out.1.test$n +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "ANSWER: 12" dig.out.1.test$n >/dev/null || ret=1 +# also check with max-query-restarts 16: +$DIG $DIGOPTS @10.53.0.7 -y "${DEFAULT_HMAC}:restart16:1234abcd8765" loop.example >dig.out.2.test$n +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "ANSWER: 17" dig.out.2.test$n >/dev/null || ret=1 + +n=$((n + 1)) +echo_i "checking CNAME loops are detected (auth) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 loop.example >dig.out.test$n +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "max. restarts reached" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 12" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to external delegated zones is handled ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 a.example >dig.out.test$n +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to internal delegated zones is handled ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 b.example >dig.out.test$n +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to signed external delegation is handled ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 c.example >dig.out.$n +grep "status: NOERROR" dig.out.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME to signed internal delegation is handled ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 d.example >dig.out.$n +grep "status: NOERROR" dig.out.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME chains in various orders ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.1.$n 2>&1 +grep 'status: NOERROR' dig.out.1.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.1.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|1,1,2,2,3,4,s4,s3,s1" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.2.$n 2>&1 +grep 'status: NOERROR' dig.out.2.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.2.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|2,1,3,4,s3,s1,s2,s4" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.3.$n 2>&1 +grep 'status: NOERROR' dig.out.3.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.3.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 4 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.4.$n 2>&1 +grep 'status: NOERROR' dig.out.4.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.4.$n >/dev/null 2>&1 || ret=1 +echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | sendcmd +$RNDCCMD 10.53.0.7 null --- start test$n - step 5 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.5.$n 2>&1 +grep 'status: NOERROR' dig.out.5.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.5.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 6 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|4,3,3,3,s1,s1,1,3,4" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.6.$n 2>&1 +grep 'status: NOERROR' dig.out.6.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.6.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that only the initial CNAME is cached ($n)" +ret=0 +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | sendcmd +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.1.$n 2>&1 +sleep 1 +$DIG $DIGOPTS +noall +answer @10.53.0.7 cname1.domain.nil >dig.out.2.$n 2>&1 +ttl=$(awk '{print $2}' dig.out.2.$n) +[ "$ttl" -eq 86400 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME chains in various orders ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.1.$n 2>&1 +grep 'status: NOERROR' dig.out.1.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 3' dig.out.1.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.2.$n 2>&1 +grep 'status: NOERROR' dig.out.2.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 3' dig.out.2.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "dname,dname|2,3,s1,s2,s3,s4,1" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.3.$n 2>&1 +grep 'status: NOERROR' dig.out.3.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 3' dig.out.3.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking external CNAME/DNAME chains in various orders ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i +echo "xname,dname|1,2,3,4,s1,s2,s3,s4" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.1.$n 2>&1 +grep 'status: NOERROR' dig.out.1.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.1.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "xname,dname|s2,2,s1,1,4,s4,3" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.2.$n 2>&1 +grep 'status: NOERROR' dig.out.2.$n >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 2' dig.out.2.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +echo "xname,dname|s2,2,2,2" | sendcmd +$DIG $DIGOPTS @10.53.0.7 test.domain.nil >dig.out.3.$n 2>&1 +grep 'status: SERVFAIL' dig.out.3.$n >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking explicit DNAME query ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 dname short-dname.example >dig.out.7.$n 2>&1 +grep 'status: NOERROR' dig.out.7.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME via ANY query ($n)" +ret=0 +$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i +$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i +$DIG $DIGOPTS @10.53.0.7 any short-dname.example >dig.out.7.$n 2>&1 +grep 'status: NOERROR' dig.out.7.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Regression test for CVE-2021-25215 (authoritative server). +n=$((n + 1)) +echo_i "checking DNAME resolution via itself (authoritative) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.2 DNAME self.domain0.self.domain0.nil. >dig.out.2.$n 2>&1 +grep 'status: NOERROR' dig.out.2.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Regression test for CVE-2021-25215 (recursive resolver). +n=$((n + 1)) +echo_i "checking DNAME resolution via itself (recursive) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.7 DNAME self.example.self.example.dname. >dig.out.7.$n 2>&1 +grep 'status: NOERROR' dig.out.7.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Regression test for GL #4652 +n=$((n + 1)) +echo_i "checking handling of illegal NS below DNAME ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.7 DNAME jeff.dname. >dig.out.ns7.1.$n 2>&1 +grep 'status: NOERROR' dig.out.ns7.1.$n >/dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.7 NS jeff.dname. >dig.out.ns7.2.$n 2>&1 +grep 'status: SERVFAIL' dig.out.ns7.2.$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/chain/tests_sh_chain.py b/bin/tests/system/chain/tests_sh_chain.py new file mode 100644 index 0000000..f7d7ac3 --- /dev/null +++ b/bin/tests/system/chain/tests_sh_chain.py @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "*/ans.run", + "ns2/K*", + "ns2/dsset-*", + "ns2/*.db.signed", + ] +) + + +def test_chain(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/checkconf/altdb.conf b/bin/tests/system/checkconf/altdb.conf new file mode 100644 index 0000000..1d8aded --- /dev/null +++ b/bin/tests/system/checkconf/altdb.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view override_bind chaos { + zone "version.bind" chaos { + type primary; + database "_builtin version"; + }; +}; diff --git a/bin/tests/system/checkconf/altdlz.conf b/bin/tests/system/checkconf/altdlz.conf new file mode 100644 index 0000000..db8eecc --- /dev/null +++ b/bin/tests/system/checkconf/altdlz.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dlz external { + database "dlopen driver.so"; + search no; +}; + +zone "example.com" { + type primary; + dlz external; +}; + +zone "." { + type redirect; + dlz external; +}; diff --git a/bin/tests/system/checkconf/ancient.conf b/bin/tests/system/checkconf/ancient.conf new file mode 100644 index 0000000..98189cc --- /dev/null +++ b/bin/tests/system/checkconf/ancient.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Ancient options are fatal. + */ +options { + fake-iquery yes; +}; diff --git a/bin/tests/system/checkconf/bad-acl.conf b/bin/tests/system/checkconf/bad-acl.conf new file mode 100644 index 0000000..5095059 --- /dev/null +++ b/bin/tests/system/checkconf/bad-acl.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl a { + { "none"; }; + { !19.0.0.0/7; }; +}; + +options { + allow-query { a; }; +}; diff --git a/bin/tests/system/checkconf/bad-also-notify.conf b/bin/tests/system/checkconf/bad-also-notify.conf new file mode 100644 index 0000000..2ab8896 --- /dev/null +++ b/bin/tests/system/checkconf/bad-also-notify.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Missing primary in also-notify clause. + */ + +zone dummy { + type primary; + file "xxxx"; + also-notify { xxxx; }; +}; diff --git a/bin/tests/system/checkconf/bad-catz-zone-dup.conf b/bin/tests/system/checkconf/bad-catz-zone-dup.conf new file mode 100644 index 0000000..08fae42 --- /dev/null +++ b/bin/tests/system/checkconf/bad-catz-zone-dup.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + catalog-zones { zone example.com; zone example.com; }; +}; + +zone example.com { + type primary; + file "example.com"; +}; diff --git a/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf b/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf new file mode 100644 index 0000000..55a2d78 --- /dev/null +++ b/bin/tests/system/checkconf/bad-catz-zone-primary-dup.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + catalog-zones { + zone "catalog.example" + default-masters { 10.53.0.1; } + default-primaries { 10.53.0.1 port 5304; } + in-memory yes; + }; +}; + +zone "catalog.example" { + type secondary; + file "catalog.example.db"; + primaries { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-catz-zone.conf b/bin/tests/system/checkconf/bad-catz-zone.conf new file mode 100644 index 0000000..6f0677a --- /dev/null +++ b/bin/tests/system/checkconf/bad-catz-zone.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + catalog-zones { + zone "nonexistent"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-checkdstype-level.conf b/bin/tests/system/checkconf/bad-checkdstype-level.conf new file mode 100644 index 0000000..f3bc1ad --- /dev/null +++ b/bin/tests/system/checkconf/bad-checkdstype-level.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * checkds only allowed at zone level + */ + +options { + checkds no; +}; + +zone dummy { + type primary; + file "xxxx"; +}; diff --git a/bin/tests/system/checkconf/bad-checkdstype.conf b/bin/tests/system/checkconf/bad-checkdstype.conf new file mode 100644 index 0000000..56cd367 --- /dev/null +++ b/bin/tests/system/checkconf/bad-checkdstype.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Bad checkds type + */ + +zone dummy { + type primary; + file "xxxx"; + checkds foobar; +}; diff --git a/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf b/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf new file mode 100644 index 0000000..24e6ef9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-checknames-primary-dup-2.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-names primary warn; + check-names primary fail; +}; diff --git a/bin/tests/system/checkconf/bad-checknames-primary-dup.conf b/bin/tests/system/checkconf/bad-checknames-primary-dup.conf new file mode 100644 index 0000000..e746e84 --- /dev/null +++ b/bin/tests/system/checkconf/bad-checknames-primary-dup.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-names master warn; + check-names primary fail; +}; diff --git a/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf b/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf new file mode 100644 index 0000000..ea83d7e --- /dev/null +++ b/bin/tests/system/checkconf/bad-checknames-secondary-dup.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-names slave ignore; + check-names secondary warn; +}; diff --git a/bin/tests/system/checkconf/bad-controls-duplicate.conf b/bin/tests/system/checkconf/bad-controls-duplicate.conf new file mode 100644 index 0000000..d53a7cf --- /dev/null +++ b/bin/tests/system/checkconf/bad-controls-duplicate.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc-key { + algorithm "hmac-sha256"; + secret "xxxxxxxxxxxxxxxxxxxxxxxx"; +}; + +key ddns-key { + algorithm "hmac-sha256"; + secret "yyyyyyyyyyyyyyyyyyyyyyyy"; +}; + +controls { + inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; }; +}; + +controls { + inet 127.0.0.1 allow { 127.0.0.1; } keys { ddns-key; }; +}; diff --git a/bin/tests/system/checkconf/bad-dnssec-policy-range1.conf b/bin/tests/system/checkconf/bad-dnssec-policy-range1.conf new file mode 100644 index 0000000..a439843 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dnssec-policy-range1.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy reverse-order { + keys { + csk lifetime unlimited algorithm rsasha256 tag-range 32767 0 2048; + }; +}; diff --git a/bin/tests/system/checkconf/bad-dnssec-policy-range2.conf b/bin/tests/system/checkconf/bad-dnssec-policy-range2.conf new file mode 100644 index 0000000..f2d2911 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dnssec-policy-range2.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy too-big-start { + keys { + csk lifetime unlimited algorithm rsasha256 tag-range 65536 0 2048; + }; +}; diff --git a/bin/tests/system/checkconf/bad-dnssec-policy-range3.conf b/bin/tests/system/checkconf/bad-dnssec-policy-range3.conf new file mode 100644 index 0000000..131a98d --- /dev/null +++ b/bin/tests/system/checkconf/bad-dnssec-policy-range3.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy too-big-end { + keys { + csk lifetime unlimited algorithm rsasha256 tag-range 0 65536 2048; + }; +}; diff --git a/bin/tests/system/checkconf/bad-dnssec-policy-range4.conf b/bin/tests/system/checkconf/bad-dnssec-policy-range4.conf new file mode 100644 index 0000000..2b3232c --- /dev/null +++ b/bin/tests/system/checkconf/bad-dnssec-policy-range4.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy start-equals-end { + keys { + csk lifetime unlimited algorithm rsasha256 tag-range 0 0 2048; + }; +}; diff --git a/bin/tests/system/checkconf/bad-dnssec.conf b/bin/tests/system/checkconf/bad-dnssec.conf new file mode 100644 index 0000000..b6974eb --- /dev/null +++ b/bin/tests/system/checkconf/bad-dnssec.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone not-inline { + type secondary; + primaries { 127.0.0.1; }; + inline-signing no; + dnssec-loadkeys-interval 10; + +}; + +zone inline { + type secondary; + primaries { 127.0.0.1; }; + inline-signing yes; + dnssec-loadkeys-interval 10; +}; diff --git a/bin/tests/system/checkconf/bad-doh-1.conf b/bin/tests/system/checkconf/bad-doh-1.conf new file mode 100644 index 0000000..a10a236 --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-1.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; +}; + +# undefined 'tls' specification +options { + listen-on port 8080 http local-http-server tls unknown { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-2.conf b/bin/tests/system/checkconf/bad-doh-2.conf new file mode 100644 index 0000000..c797eee --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-2.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +# undefined 'http' specification +options { + listen-on port 8080 http unknown tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-3.conf b/bin/tests/system/checkconf/bad-doh-3.conf new file mode 100644 index 0000000..7447a01 --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-3.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +http local-http-server { + endpoints { "/dns-query"; }; +}; + +# no 'tls' specification +options { + listen-on port 8080 http unknown { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-badpath-1.conf b/bin/tests/system/checkconf/bad-doh-badpath-1.conf new file mode 100644 index 0000000..9a0f449 --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-badpath-1.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# bad HTTP location +http local-http-server { + endpoints { "dns-query"; }; +}; + +options { + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-badpath-2.conf b/bin/tests/system/checkconf/bad-doh-badpath-2.conf new file mode 100644 index 0000000..e8013ee --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-badpath-2.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# bad HTTP location +http local-http-server { + endpoints { "//"; }; +}; + +options { + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-badpath-3.conf b/bin/tests/system/checkconf/bad-doh-badpath-3.conf new file mode 100644 index 0000000..fc5464c --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-badpath-3.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# bad HTTP location +http local-http-server { + endpoints { "/dns-query?dns="; }; +}; + +options { + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-doh-default.conf b/bin/tests/system/checkconf/bad-doh-default.conf new file mode 100644 index 0000000..dce7fe6 --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-default.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# 'default' is a built-in configuration intended to be used in +# 'listen-on' statements +http default { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; diff --git a/bin/tests/system/checkconf/bad-doh-duplicates.conf b/bin/tests/system/checkconf/bad-doh-duplicates.conf new file mode 100644 index 0000000..a598d07 --- /dev/null +++ b/bin/tests/system/checkconf/bad-doh-duplicates.conf @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +# duplicated HTTP configuration +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-1.conf b/bin/tests/system/checkconf/bad-dot-1.conf new file mode 100644 index 0000000..436a269 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# undefined 'tls' specification +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf new file mode 100644 index 0000000..7d807fd --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-port.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 99999 { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf new file mode 100644 index 0000000..cba5557 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-1.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 44344 transport blah { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf new file mode 100644 index 0000000..e772592 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-2.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 44344 transport udp { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf new file mode 100644 index 0000000..22956d2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-3.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 44344 transport http { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf new file mode 100644 index 0000000..dfc7794 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-allow-transfer-bad-proto-4.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 44344 transport http-plain { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-badciphers.conf b/bin/tests/system/checkconf/bad-dot-badciphers.conf new file mode 100644 index 0000000..42a9f64 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-badciphers.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; + ciphers "$bad:ciphers"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-badprotocol.conf b/bin/tests/system/checkconf/bad-dot-badprotocol.conf new file mode 100644 index 0000000..f1cc15a --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-badprotocol.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; + protocols { unknown; TLSv1.2; }; # bad TLS protocol version name +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-duplicatetls.conf b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf new file mode 100644 index 0000000..508290f --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-duplicatetls.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-ephemeral.conf b/bin/tests/system/checkconf/bad-dot-ephemeral.conf new file mode 100644 index 0000000..c9581f2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-ephemeral.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# ephemeral is reserved for internal use +tls ephemeral { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls ephemeral { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-nocert.conf b/bin/tests/system/checkconf/bad-dot-nocert.conf new file mode 100644 index 0000000..db02e9f --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-nocert.conf @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-nokey.conf b/bin/tests/system/checkconf/bad-dot-nokey.conf new file mode 100644 index 0000000..1d5c3c5 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-nokey.conf @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-none.conf b/bin/tests/system/checkconf/bad-dot-none.conf new file mode 100644 index 0000000..fa26ab1 --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-none.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# none is reserved for internal use +tls none { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls none { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-dot-primaries.conf b/bin/tests/system/checkconf/bad-dot-primaries.conf new file mode 100644 index 0000000..8958cbe --- /dev/null +++ b/bin/tests/system/checkconf/bad-dot-primaries.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls undefined; }; + file "example.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/checkconf/bad-duplicate-key.conf b/bin/tests/system/checkconf/bad-duplicate-key.conf new file mode 100644 index 0000000..17f2237 --- /dev/null +++ b/bin/tests/system/checkconf/bad-duplicate-key.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trust-anchors { + example. initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl + 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG + tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY + kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ + fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS + WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI + NQyrszHhWUU="; +}; + +trust-anchors { + example. static-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod + y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ + YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX + 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw + E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/ + Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn + 6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-duplicate-remote-servers-synonyms.conf b/bin/tests/system/checkconf/bad-duplicate-remote-servers-synonyms.conf new file mode 100644 index 0000000..f2de15b --- /dev/null +++ b/bin/tests/system/checkconf/bad-duplicate-remote-servers-synonyms.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers duplicate { 1.2.3.4; }; +primaries duplicate { 4.3.2.1; }; diff --git a/bin/tests/system/checkconf/bad-duplicate-remote-servers.conf b/bin/tests/system/checkconf/bad-duplicate-remote-servers.conf new file mode 100644 index 0000000..dc35ee9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-duplicate-remote-servers.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers duplicate { 1.2.3.4; }; +remote-servers duplicate { 4.3.2.1; }; diff --git a/bin/tests/system/checkconf/bad-duplicate-root-key.conf b/bin/tests/system/checkconf/bad-duplicate-root-key.conf new file mode 100644 index 0000000..1cbc7d4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-duplicate-root-key.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trust-anchors { + . initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl + 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG + tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY + kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ + fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS + WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI + NQyrszHhWUU="; +}; + +trusted-keys { + . 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod + y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ + YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX + 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw + E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/ + Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn + 6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-duration.conf b/bin/tests/system/checkconf/bad-duration.conf new file mode 100644 index 0000000..1fbecc7 --- /dev/null +++ b/bin/tests/system/checkconf/bad-duration.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "test" { + dnskey-ttl xPT1H; +}; diff --git a/bin/tests/system/checkconf/bad-empty-include.conf b/bin/tests/system/checkconf/bad-empty-include.conf new file mode 100644 index 0000000..ef47166 --- /dev/null +++ b/bin/tests/system/checkconf/bad-empty-include.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include ""; diff --git a/bin/tests/system/checkconf/bad-fetchparam.conf b/bin/tests/system/checkconf/bad-fetchparam.conf new file mode 100644 index 0000000..b416741 --- /dev/null +++ b/bin/tests/system/checkconf/bad-fetchparam.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* Bad fetch-quota-params */ +options { + fetch-quota-params 1 2 3 2; +}; diff --git a/bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf new file mode 100644 index 0000000..68c1f14 --- /dev/null +++ b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-1.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls test-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; +}; + +# Bad: trying to use a TLS profile that has not been specified (another-tls). +zone "example" { + type forward; + forward only; + forwarders port 5300 tls test-tls { 10.53.0.1; 10.53.0.2 port 5301 tls another-tls; }; +}; diff --git a/bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf new file mode 100644 index 0000000..d95af2d --- /dev/null +++ b/bin/tests/system/checkconf/bad-forwarders-dot-badtls-2.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls test-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; +}; + +# Bad: trying to use a TLS profile that has not been specified (another-tls). +zone "example" { + type forward; + forward only; + forwarders port 5300 tls another-tls { 10.53.0.1; 10.53.0.2 port 5301 tls test-tls; }; +}; diff --git a/bin/tests/system/checkconf/bad-hint.conf b/bin/tests/system/checkconf/bad-hint.conf new file mode 100644 index 0000000..7214a00 --- /dev/null +++ b/bin/tests/system/checkconf/bad-hint.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + masterfile-format raw; + file "hint"; +}; diff --git a/bin/tests/system/checkconf/bad-in-view-dup.conf b/bin/tests/system/checkconf/bad-in-view-dup.conf new file mode 100644 index 0000000..1d8bd17 --- /dev/null +++ b/bin/tests/system/checkconf/bad-in-view-dup.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view a { + zone x { type primary; file "x"; }; +}; + +view b { + zone x { type primary; file "x"; }; + zone x { in-view a; }; +}; diff --git a/bin/tests/system/checkconf/bad-inline-options.conf b/bin/tests/system/checkconf/bad-inline-options.conf new file mode 100644 index 0000000..f7c62dd --- /dev/null +++ b/bin/tests/system/checkconf/bad-inline-options.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * inline-signing not allowed at options level. + */ +options { + inline-signing yes; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/checkconf/bad-inline-secondary.conf b/bin/tests/system/checkconf/bad-inline-secondary.conf new file mode 100644 index 0000000..3646216 --- /dev/null +++ b/bin/tests/system/checkconf/bad-inline-secondary.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + /* + * An inline-signing secondary should be forced to have a file option + */ + + zone "." { + type secondary; + inline-signing yes; + primaries { 10.53.0.1; }; + }; diff --git a/bin/tests/system/checkconf/bad-inline-view.conf b/bin/tests/system/checkconf/bad-inline-view.conf new file mode 100644 index 0000000..e46bd0b --- /dev/null +++ b/bin/tests/system/checkconf/bad-inline-view.conf @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * inline-signing not allowed at view level. + */ +view "a" { + inline-signing yes; + + zone "." { + type primary; + file "root.db.signed"; + }; +}; + +view "b" { + zone "." { + type primary; + file "root.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-interface-interval.conf b/bin/tests/system/checkconf/bad-interface-interval.conf new file mode 100644 index 0000000..ba8341a --- /dev/null +++ b/bin/tests/system/checkconf/bad-interface-interval.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + interface-interval 1x; +}; diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf new file mode 100644 index 0000000..d7604eb --- /dev/null +++ b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted1.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl myacl { + 127.1; /* Incomplete dotted IPv4 address / prefix */ +}; diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf new file mode 100644 index 0000000..cb53741 --- /dev/null +++ b/bin/tests/system/checkconf/bad-ipv4-prefix-dotted2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl myacl { + 127.1/8; /* No-zero bits */ +}; diff --git a/bin/tests/system/checkconf/bad-ipv4-prefix2.conf b/bin/tests/system/checkconf/bad-ipv4-prefix2.conf new file mode 100644 index 0000000..98e724a --- /dev/null +++ b/bin/tests/system/checkconf/bad-ipv4-prefix2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl myacl { + 127; /* Non-dotted quad IPv4 address (0.0.0.127) / prefix without length. */ +}; diff --git a/bin/tests/system/checkconf/bad-kasp-define-default.conf b/bin/tests/system/checkconf/bad-kasp-define-default.conf new file mode 100644 index 0000000..73c90ef --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-define-default.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// 'default' is a built-in policy, redefinition not allowed. +dnssec-policy "default" { + signatures-refresh P5D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-define-insecure.conf b/bin/tests/system/checkconf/bad-kasp-define-insecure.conf new file mode 100644 index 0000000..b2d22d3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-define-insecure.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// 'insecure' is a built-in policy, redefinition not allowed. +dnssec-policy "insecure" { + signatures-refresh P5D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-define-none.conf b/bin/tests/system/checkconf/bad-kasp-define-none.conf new file mode 100644 index 0000000..cea9988 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-define-none.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// 'none' is a built-in policy, redefinition not allowed. +dnssec-policy "none" { + signatures-refresh P5D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "none"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-digest-type.conf b/bin/tests/system/checkconf/bad-kasp-digest-type.conf new file mode 100644 index 0000000..f1bd4d3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-digest-type.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-digesttype" { + cds-digest-types { foobar; 2; }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "baddigesttype"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-digest-unsupported.conf b/bin/tests/system/checkconf/bad-kasp-digest-unsupported.conf new file mode 100644 index 0000000..bdb8c37 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-digest-unsupported.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-digesttype" { + cds-digest-types { GOST; 2; }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "baddigesttype"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-duplicate.conf b/bin/tests/system/checkconf/bad-kasp-duplicate.conf new file mode 100644 index 0000000..7f3ade6 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-duplicate.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy a { }; +dnssec-policy a { }; diff --git a/bin/tests/system/checkconf/bad-kasp-duration.conf b/bin/tests/system/checkconf/bad-kasp-duration.conf new file mode 100644 index 0000000..74f0827 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-duration.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "invalid-sigrefresh" { + keys { + csk lifetime unlimited algorithm 13; + }; + signatures-refresh P7.5D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "invalid-sigrefresh"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-inline-signing.conf b/bin/tests/system/checkconf/bad-kasp-inline-signing.conf new file mode 100644 index 0000000..178be5e --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-inline-signing.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * inline-signing is a boolean value. + */ +dnssec-policy "inline" { + inline-signing never-ever; +}; + +zone "." { + type primary; + file "root.db"; + dnssec-policy "inline"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-jitter.conf b/bin/tests/system/checkconf/bad-kasp-jitter.conf new file mode 100644 index 0000000..e358957 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-jitter.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy jitter is more than signatures-validity, + * which is not allowed. + */ +dnssec-policy high-jitter { + signatures-jitter P8DT1S; + signatures-validity P8D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy high-jitter; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-key1.conf b/bin/tests/system/checkconf/bad-kasp-key1.conf new file mode 100644 index 0000000..0bf80de --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-key1.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "badalg" { + keys { + csk lifetime unlimited algorithm ceasarscipher; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badalg"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-key2.conf b/bin/tests/system/checkconf/bad-kasp-key2.conf new file mode 100644 index 0000000..8e97e2a --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-key2.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "badalg" { + keys { + csk lifetime unlimited algorithm 8 4097; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badalg"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-key3.conf b/bin/tests/system/checkconf/bad-kasp-key3.conf new file mode 100644 index 0000000..85e4e48 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-key3.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "badalg" { + keys { + csk lifetime unlimited algorithm rsasha512 1023; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badalg"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-key4.conf b/bin/tests/system/checkconf/bad-kasp-key4.conf new file mode 100644 index 0000000..ca142a3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-key4.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "badalg" { + keys { + csk lifetime unlimited algorithm 5 511; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badalg"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore1.conf b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore1.conf new file mode 100644 index 0000000..f01ded4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore1.conf @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The same zone in different views is using different DNSSEC policies, so it + * may not use the same directory for storing keys. + */ + + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store2" { + directory "."; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store2" lifetime unlimited algorithm 13; + }; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "default"; + key-directory "."; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore2.conf b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore2.conf new file mode 100644 index 0000000..efe09e3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore2.conf @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * In view "example1" no key-directory is set, so the default is used. + * In view "example2" the key-store directory is set to "." which is the + * default. This should fail because the same zone in different views is using + * different DNSSEC policies. + */ + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store2" { + directory "."; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store2" lifetime unlimited algorithm 13; + }; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore3.conf b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore3.conf new file mode 100644 index 0000000..fdc8577 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore3.conf @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The zone in view "example1" inherits the key directory value from "options", + * but in view "example2" sets the key-store directory to the same value. + * This should be detected as an error because the zone is using different + * DNSSEC policies and should thus use different key directories. + */ + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store2" { + directory "keys"; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store2" lifetime unlimited algorithm 13; + }; +}; + +options { + key-directory "keys"; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + /* key-directory inherited from options. */ + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore4.conf b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore4.conf new file mode 100644 index 0000000..ddfbebc --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir-vs-keystore4.conf @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The zone inherits the key-directory from the "view" level. Both views use the + * same directory for storing keys, but the zone uses a different DNSSEC policy + * per view. This is a configuration error. + */ + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store2" { + directory "keys"; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store2" lifetime unlimited algorithm 13; + }; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + key-directory "keys"; + + zone "example.net" { + type primary; + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir1.conf.j2 b/bin/tests/system/checkconf/bad-kasp-keydir1.conf.j2 new file mode 100644 index 0000000..b0deaea --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir1.conf.j2 @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The same zone in different views is using different DNSSEC policies, so it + * may not have the same key-directory. + */ + + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "default"; + key-directory "."; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "insecure"; + key-directory "."; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir2.conf.j2 b/bin/tests/system/checkconf/bad-kasp-keydir2.conf.j2 new file mode 100644 index 0000000..699c193 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir2.conf.j2 @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * No key-directory is set, so the default is used. + * Should fail because the same zone in different views is using different + * DNSSEC policies. + */ + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "insecure"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir3.conf.j2 b/bin/tests/system/checkconf/bad-kasp-keydir3.conf.j2 new file mode 100644 index 0000000..0dbd7e2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir3.conf.j2 @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The zone in view "example1" inherits the key directory value from "options", + * but in view "example2" sets the key directory to the same value. This should + * be detected as an error because the zone is using different DNSSEC policies + * and should thus use different key directories. + */ + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +options { + key-directory "keys"; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + /* key-directory inherited from options. */ + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "insecure"; + key-directory "keys"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir4.conf.j2 b/bin/tests/system/checkconf/bad-kasp-keydir4.conf.j2 new file mode 100644 index 0000000..af4a8f9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir4.conf.j2 @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The zone inherits the key-directory from the "view" level. Both views use the + * same key-directory, but the zone uses a different DNSSEC policy per view. + * This is a configuration error. + */ + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + key-directory "keys"; + + zone "example.net" { + type primary; + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + key-directory "keys"; + + zone "example.net" { + type primary; + dnssec-policy "insecure"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keydir5.conf.j2 b/bin/tests/system/checkconf/bad-kasp-keydir5.conf.j2 new file mode 100644 index 0000000..1cca608 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keydir5.conf.j2 @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * In one view, the zone inherits the key-directory from the "view" level, while + * in the other it is set explicitly at the "zone" level. In both cases, the + * same key-directory is used, but the zone uses a different DNSSEC policy per + * view. This is a configuration error. + */ + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + key-directory "keys"; + + zone "example.net" { + type primary; + dnssec-policy "default"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "insecure"; + key-directory "keys"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keystore.conf b/bin/tests/system/checkconf/bad-kasp-keystore.conf new file mode 100644 index 0000000..8bbe9a3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keystore.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// Bad dnssec-policy configuration because there is no key-store with this name. +dnssec-policy "bad" { + keys { + csk key-store "ks404" lifetime unlimited algorithm 13; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keystore1.conf b/bin/tests/system/checkconf/bad-kasp-keystore1.conf new file mode 100644 index 0000000..68540fa --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keystore1.conf @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The same zone in different views is using different DNSSEC policies, so it + * may not use the same key-store directory. + */ + + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store1" { + directory "keys"; +}; + +key-store "store2" { + directory "keys"; +}; + +dnssec-policy "policy1" { + keys { + csk key-store "store1" lifetime unlimited algorithm 13; + }; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store2" lifetime unlimited algorithm 13; + }; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy1"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-keystore2.conf b/bin/tests/system/checkconf/bad-kasp-keystore2.conf new file mode 100644 index 0000000..19be1bd --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-keystore2.conf @@ -0,0 +1,64 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Both policies use the same key-store. Should fail because the same zone in + * different views is using different DNSSEC policies. + */ + +key "keyforview1" { + algorithm "hmac-sha1"; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm "hmac-sha1"; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "store" { + directory "keys"; +}; + +dnssec-policy "policy1" { + keys { + csk key-store "store" lifetime unlimited algorithm 13; + }; +}; + +dnssec-policy "policy2" { + keys { + csk key-store "store" lifetime unlimited algorithm 13; + }; +}; + + +view "example1" { + match-clients { key "keyforview1"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy1"; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + dnssec-policy "policy2"; + file "example2.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-max-zone-ttl.conf b/bin/tests/system/checkconf/bad-kasp-max-zone-ttl.conf new file mode 100644 index 0000000..0b59394 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-max-zone-ttl.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy is not defined. Should also be caught if it is inherited. + */ + +options { + dnssec-policy default; +}; + +zone "example.net" { + type primary; + file "example.db"; + max-zone-ttl 600; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf new file mode 100644 index 0000000..ff25ece --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "badnsec3alg" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; + nsec3param iterations 0 optout 0 salt-length 0; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badnsec3alg"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf new file mode 100644 index 0000000..12a26d3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited-view.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy is not defined. Should also be caught if it is inherited. + */ + +view "test" { + dnssec-policy "notdefined"; + + zone "example.net" { + type primary; + file "example.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf new file mode 100644 index 0000000..48514ac --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-policy-undefined-inherited.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy is not defined. Should also be caught if it is inherited. + */ + +options { + dnssec-policy "notdefined"; +}; + +zone "example.net" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/checkconf/bad-kasp10.conf b/bin/tests/system/checkconf/bad-kasp10.conf new file mode 100644 index 0000000..8253fae --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp10.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone with dnssec-policy 'none', one zone with dnssec-policy 'insecure', +// both using the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "none"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp11.conf b/bin/tests/system/checkconf/bad-kasp11.conf new file mode 100644 index 0000000..68177c2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp11.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone with a dnssec-policy, the other with allow-update, +// with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + allow-update { any; }; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp12.conf b/bin/tests/system/checkconf/bad-kasp12.conf new file mode 100644 index 0000000..0ae8c1e --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp12.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone with a dnssec-policy, the other with update-policy, +// with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + update-policy { + grant * self * TXT; + }; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp13.conf b/bin/tests/system/checkconf/bad-kasp13.conf new file mode 100644 index 0000000..c74a5d7 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp13.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone transitioning to insecure, the other with allow-update, +// with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + allow-update { any; }; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp3.conf b/bin/tests/system/checkconf/bad-kasp3.conf new file mode 100644 index 0000000..8c6d7b4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp3.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "good-kasp.conf"; + +// Bad zone configuration because this has dnssec-policy with no matching +// dnssec-policy configuration (good-kasp.conf has "test", zone refers to +// "nosuchpolicy". +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "nosuchpolicy"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp4.conf b/bin/tests/system/checkconf/bad-kasp4.conf new file mode 100644 index 0000000..d35d12f --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp4.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// Bad kasp configuration because this has an invalid duration for +// signatures-refresh. +dnssec-policy "badduration" { + signatures-refresh PT20Sabcd; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badduration"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp6.conf b/bin/tests/system/checkconf/bad-kasp6.conf new file mode 100644 index 0000000..3304038 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp6.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// Two zones with dnssec-policy with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp7.conf b/bin/tests/system/checkconf/bad-kasp7.conf new file mode 100644 index 0000000..c5dfbe8 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp7.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// Two zones with dnssec-policy 'insecure' (transitioning to insecure) +// with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp8.conf b/bin/tests/system/checkconf/bad-kasp8.conf new file mode 100644 index 0000000..1712fd0 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp8.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone with dnssec-policy, the other zone has 'dnssec-policy none', +// both with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + dnssec-policy "none"; +}; + diff --git a/bin/tests/system/checkconf/bad-kasp9.conf b/bin/tests/system/checkconf/bad-kasp9.conf new file mode 100644 index 0000000..3bb5448 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp9.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// One zone with dnssec-policy, the other zone has 'dnssec-policy insecure' +// (transitioning to inseure), both with the same zone file. + +zone "example1.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; + +zone "example2.net" { + type primary; + file "example.db"; + dnssec-policy "insecure"; +}; + diff --git a/bin/tests/system/checkconf/bad-keystore-key-directory.conf b/bin/tests/system/checkconf/bad-keystore-key-directory.conf new file mode 100644 index 0000000..7007cf8 --- /dev/null +++ b/bin/tests/system/checkconf/bad-keystore-key-directory.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// Bad key-store configuration because the keyword 'key-directory' may not +// be used. +key-store "key-directory" { + directory "."; +}; + +dnssec-policy "bad" { + keys { + csk key-store "key-directory" lifetime unlimited algorithm 13; + }; +}; diff --git a/bin/tests/system/checkconf/bad-ksk-without-zsk.conf b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf new file mode 100644 index 0000000..66e1b7f --- /dev/null +++ b/bin/tests/system/checkconf/bad-ksk-without-zsk.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy ksk-without-zsk { + keys { + ksk lifetime 30d algorithm 13; + }; +}; + +zone "example" { + type primary; + file "example.db"; + dnssec-policy ksk-without-zsk; +}; diff --git a/bin/tests/system/checkconf/bad-lifetime.conf b/bin/tests/system/checkconf/bad-lifetime.conf new file mode 100644 index 0000000..f268076 --- /dev/null +++ b/bin/tests/system/checkconf/bad-lifetime.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + nta-lifetime 8d; +}; diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf new file mode 100644 index 0000000..5655a16 --- /dev/null +++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-bogus.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize bogusvalue; +}; diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf new file mode 100644 index 0000000..006ca7d --- /dev/null +++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toolarge.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize 2048G; +}; diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf new file mode 100644 index 0000000..5dd1720 --- /dev/null +++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-toosmall.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize 1; +}; diff --git a/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf b/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf new file mode 100644 index 0000000..f1e7b88 --- /dev/null +++ b/bin/tests/system/checkconf/bad-lmdb-mapsize-unlimited.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize unlimited; +}; diff --git a/bin/tests/system/checkconf/bad-master-request-ixfr.conf b/bin/tests/system/checkconf/bad-master-request-ixfr.conf new file mode 100644 index 0000000..770afb3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-master-request-ixfr.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * request-ixfr clause is not allowed in zone of type primary. + */ + +zone dummy { + type primary; + request-ixfr no; + file "xxxx"; +}; diff --git a/bin/tests/system/checkconf/bad-masterfile-format-map.conf b/bin/tests/system/checkconf/bad-masterfile-format-map.conf new file mode 100644 index 0000000..634ca14 --- /dev/null +++ b/bin/tests/system/checkconf/bad-masterfile-format-map.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { ::1; }; + masterfile-format map; +}; diff --git a/bin/tests/system/checkconf/bad-maxcachettl.conf b/bin/tests/system/checkconf/bad-maxcachettl.conf new file mode 100644 index 0000000..47f0643 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxcachettl.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + max-cache-ttl 1x; +}; diff --git a/bin/tests/system/checkconf/bad-maxncachettl-1.conf b/bin/tests/system/checkconf/bad-maxncachettl-1.conf new file mode 100644 index 0000000..ad852c3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxncachettl-1.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + max-ncache-ttl 1x; +}; diff --git a/bin/tests/system/checkconf/bad-maxncachettl-2.conf b/bin/tests/system/checkconf/bad-maxncachettl-2.conf new file mode 100644 index 0000000..ada5c83 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxncachettl-2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view two { + max-ncache-ttl 604801; +}; diff --git a/bin/tests/system/checkconf/bad-maxncachettl-3.conf b/bin/tests/system/checkconf/bad-maxncachettl-3.conf new file mode 100644 index 0000000..771a0f3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxncachettl-3.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view three { + max-ncache-ttl 4000000000; +}; +view four { + max-ncache-ttl -1; +}; diff --git a/bin/tests/system/checkconf/bad-maxncachettl-4.conf b/bin/tests/system/checkconf/bad-maxncachettl-4.conf new file mode 100644 index 0000000..d9cd939 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxncachettl-4.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view four { + max-ncache-ttl -1; +}; diff --git a/bin/tests/system/checkconf/bad-maxratio1.conf b/bin/tests/system/checkconf/bad-maxratio1.conf new file mode 100644 index 0000000..ade4de1 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxratio1.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + masterfile-format raw; + file "example.db"; + max-ixfr-ratio 0.9; +}; diff --git a/bin/tests/system/checkconf/bad-maxratio2.conf b/bin/tests/system/checkconf/bad-maxratio2.conf new file mode 100644 index 0000000..adb63f3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-maxratio2.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + masterfile-format raw; + file "example.db"; + max-ixfr-ratio 0%; +}; diff --git a/bin/tests/system/checkconf/bad-mincachettl.conf b/bin/tests/system/checkconf/bad-mincachettl.conf new file mode 100644 index 0000000..cd02c66 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mincachettl.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + min-cache-ttl 1x; +}; diff --git a/bin/tests/system/checkconf/bad-minncachettl.conf b/bin/tests/system/checkconf/bad-minncachettl.conf new file mode 100644 index 0000000..1148bcc --- /dev/null +++ b/bin/tests/system/checkconf/bad-minncachettl.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + min-ncache-ttl 1x; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf new file mode 100644 index 0000000..1f4c8fe --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-allow-recursion-none.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + recursion yes; + allow-recursion { none; }; +}; + +zone "." { + type mirror; + primaries { 127.0.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf new file mode 100644 index 0000000..27ad850 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-explicit-notify-yes.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type mirror; + notify yes; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf new file mode 100644 index 0000000..c9c8b03 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-non-root-zone-without-masters.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "foo." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-recursion-no.conf b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf new file mode 100644 index 0000000..f5536ac --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-recursion-no.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + recursion no; +}; + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/bad-mirror-zonename.conf b/bin/tests/system/checkconf/bad-mirror-zonename.conf new file mode 100644 index 0000000..6fc11c1 --- /dev/null +++ b/bin/tests/system/checkconf/bad-mirror-zonename.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "\0example" { + type mirror; + file "example.db"; +}; diff --git a/bin/tests/system/checkconf/bad-no-trusted-key.conf b/bin/tests/system/checkconf/bad-no-trusted-key.conf new file mode 100644 index 0000000..42cfe1f --- /dev/null +++ b/bin/tests/system/checkconf/bad-no-trusted-key.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; diff --git a/bin/tests/system/checkconf/bad-noddns.conf b/bin/tests/system/checkconf/bad-noddns.conf new file mode 100644 index 0000000..203bf4d --- /dev/null +++ b/bin/tests/system/checkconf/bad-noddns.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "test" { + inline-signing no; +}; + +zone example { + type primary; + file "example.db"; + dnssec-policy test; + allow-update { none; }; +}; diff --git a/bin/tests/system/checkconf/bad-notify-source-v6.conf b/bin/tests/system/checkconf/bad-notify-source-v6.conf new file mode 100644 index 0000000..ef53c96 --- /dev/null +++ b/bin/tests/system/checkconf/bad-notify-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + notify-source-v6 fd92:7065:b8e:ffff::1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-notify-source.conf b/bin/tests/system/checkconf/bad-notify-source.conf new file mode 100644 index 0000000..b950784 --- /dev/null +++ b/bin/tests/system/checkconf/bad-notify-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + notify-source 10.53.0.1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-options-also-notify.conf b/bin/tests/system/checkconf/bad-options-also-notify.conf new file mode 100644 index 0000000..889a88f --- /dev/null +++ b/bin/tests/system/checkconf/bad-options-also-notify.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + also-notify { missing; }; +}; + +zone "example.net" { + type secondary; + primaries { 192.168.1.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf b/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf new file mode 100644 index 0000000..a10cf04 --- /dev/null +++ b/bin/tests/system/checkconf/bad-options-query-source-address-v4-v6.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source none; + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-options.conf b/bin/tests/system/checkconf/bad-parental-agents-def-options.conf new file mode 100644 index 0000000..2091155 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-def-options.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + parental-agents { 192.168.1.2; }; +}; + +zone "example.net" { + type primary; + file "example.net.db"; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-view.conf b/bin/tests/system/checkconf/bad-parental-agents-def-view.conf new file mode 100644 index 0000000..47c062a --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-def-view.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "test" { + parental-agents { 192.168.1.2; }; + zone "example.net" { + type primary; + file "example.net.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf b/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf new file mode 100644 index 0000000..c0312a5 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-def-view2.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "test" { + remote-servers "net" { + 192.168.1.2; + }; + zone "example.net" { + type primary; + file "example.net.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf b/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf new file mode 100644 index 0000000..e2a8389 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-def-zone.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents "net" { 192.168.1.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-dup.conf b/bin/tests/system/checkconf/bad-parental-agents-dup.conf new file mode 100644 index 0000000..cb5ac44 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-dup.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents { 192.168.1.1; }; + parental-agents { 192.168.1.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf b/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf new file mode 100644 index 0000000..c5e1f12 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-dupdef.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers "net" { + 192.168.1.1; +}; + +remote-servers "net" { + 192.168.1.2; +}; + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents { "net"; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-empty.conf b/bin/tests/system/checkconf/bad-parental-agents-empty.conf new file mode 100644 index 0000000..0bd52a9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-empty.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers "net" { }; + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents { "net"; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-empty2.conf b/bin/tests/system/checkconf/bad-parental-agents-empty2.conf new file mode 100644 index 0000000..93b8f7b --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-empty2.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents { }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-mirror.conf b/bin/tests/system/checkconf/bad-parental-agents-mirror.conf new file mode 100644 index 0000000..62926e2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-mirror.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type mirror; + file "root.mirror"; + parental-agents { 192.168.1.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-agents-notfound.conf b/bin/tests/system/checkconf/bad-parental-agents-notfound.conf new file mode 100644 index 0000000..40fd75c --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-agents-notfound.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers "com" { + 192.168.1.2; +}; + +zone "example.net" { + type primary; + file "example.net.db"; + parental-agents { "net"; }; +}; diff --git a/bin/tests/system/checkconf/bad-parental-source-v6.conf b/bin/tests/system/checkconf/bad-parental-source-v6.conf new file mode 100644 index 0000000..1b053d0 --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + parental-source-v6 fd92:7065:b8e:ffff::1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-parental-source.conf b/bin/tests/system/checkconf/bad-parental-source.conf new file mode 100644 index 0000000..9587b3e --- /dev/null +++ b/bin/tests/system/checkconf/bad-parental-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + parental-source 10.53.0.1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-port.conf b/bin/tests/system/checkconf/bad-port.conf new file mode 100644 index 0000000..9650c8f --- /dev/null +++ b/bin/tests/system/checkconf/bad-port.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 99999; +}; diff --git a/bin/tests/system/checkconf/bad-primaries-dup.conf b/bin/tests/system/checkconf/bad-primaries-dup.conf new file mode 100644 index 0000000..ed761c9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-primaries-dup.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.net" { + type secondary; + primaries { 192.168.1.1; }; + masters { 192.168.1.2; }; +}; diff --git a/bin/tests/system/checkconf/bad-primaries-key.conf b/bin/tests/system/checkconf/bad-primaries-key.conf new file mode 100644 index 0000000..f592293 --- /dev/null +++ b/bin/tests/system/checkconf/bad-primaries-key.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type secondary; + primaries { 1.2.3.4 key a..b; }; +}; diff --git a/bin/tests/system/checkconf/bad-primaries-notfound.conf b/bin/tests/system/checkconf/bad-primaries-notfound.conf new file mode 100644 index 0000000..543d97c --- /dev/null +++ b/bin/tests/system/checkconf/bad-primaries-notfound.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers "net" { + 192.168.1.2; +}; + +zone "example.net" { + type secondary; + primaries { "foo"; }; +}; diff --git a/bin/tests/system/checkconf/bad-primaries-tls.conf b/bin/tests/system/checkconf/bad-primaries-tls.conf new file mode 100644 index 0000000..7858d1d --- /dev/null +++ b/bin/tests/system/checkconf/bad-primaries-tls.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type secondary; + primaries { 1.2.3.4 tls a..b; }; +}; diff --git a/bin/tests/system/checkconf/bad-printtime.conf b/bin/tests/system/checkconf/bad-printtime.conf new file mode 100644 index 0000000..80a53cb --- /dev/null +++ b/bin/tests/system/checkconf/bad-printtime.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +logging { + channel one { + file "one.out"; + print-time bogus; + }; +}; diff --git a/bin/tests/system/checkconf/bad-proxy-encrypted-do53.conf b/bin/tests/system/checkconf/bad-proxy-encrypted-do53.conf new file mode 100644 index 0000000..4d28fbb --- /dev/null +++ b/bin/tests/system/checkconf/bad-proxy-encrypted-do53.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + listen-on proxy encrypted { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-proxy-encrypted-doh-plain.conf b/bin/tests/system/checkconf/bad-proxy-encrypted-doh-plain.conf new file mode 100644 index 0000000..7824e96 --- /dev/null +++ b/bin/tests/system/checkconf/bad-proxy-encrypted-doh-plain.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on port 8080 proxy encrypted tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf b/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf new file mode 100644 index 0000000..497c2f0 --- /dev/null +++ b/bin/tests/system/checkconf/bad-query-source-address-v4-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +server 1.2.3.4 { + query-source none; +}; diff --git a/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf b/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf new file mode 100644 index 0000000..4ea1ba7 --- /dev/null +++ b/bin/tests/system/checkconf/bad-query-source-address-v6-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +server fd92:7065:b8e:ffff::1 { + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/bad-random-device.conf b/bin/tests/system/checkconf/bad-random-device.conf new file mode 100644 index 0000000..bc1451d --- /dev/null +++ b/bin/tests/system/checkconf/bad-random-device.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + random-device "/dev/urandom"; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-acl.conf b/bin/tests/system/checkconf/bad-rate-limit-acl.conf new file mode 100644 index 0000000..06543fb --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-acl.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + responses-per-second 10; + exempt-clients { localhost; localnets; unknownacl; }; + log-only yes; + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf new file mode 100644 index 0000000..aae353e --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-all-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + all-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf new file mode 100644 index 0000000..b2c6097 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-errors-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + errors-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf b/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf new file mode 100644 index 0000000..b728575 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-ipv4-prefix-length.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + ipv4-prefix-length 33; // greater than bits in address + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf b/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf new file mode 100644 index 0000000..6b5fda5 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-ipv6-prefix-length.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + ipv6-prefix-length 65; // max 64 + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf b/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf new file mode 100644 index 0000000..95309db --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-max-table-size.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + max-table-size 30; // less than min-table-size default of 500 + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf new file mode 100644 index 0000000..ecfb5f8 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-nodata-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + nodata-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf new file mode 100644 index 0000000..77c5749 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-nxdomains-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + nxdomains-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf b/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf new file mode 100644 index 0000000..0dc4532 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-qps-scale.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + qps-scale 0; // must be greater than zero + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf new file mode 100644 index 0000000..0ea4836 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-referrals-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + referrals-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf b/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf new file mode 100644 index 0000000..8187244 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-responses-per-second.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + responses-per-second 1001; // greater than DNS_RRL_MAX_RATE + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-slip.conf b/bin/tests/system/checkconf/bad-rate-limit-slip.conf new file mode 100644 index 0000000..15d270c --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-slip.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + slip 11; // greater than default of 10 + }; +}; diff --git a/bin/tests/system/checkconf/bad-rate-limit-window.conf b/bin/tests/system/checkconf/bad-rate-limit-window.conf new file mode 100644 index 0000000..7ded786 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rate-limit-window.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + window 3601; // greater than default of 3600 + }; +}; diff --git a/bin/tests/system/checkconf/bad-root-mixed-key.conf b/bin/tests/system/checkconf/bad-root-mixed-key.conf new file mode 100644 index 0000000..7035066 --- /dev/null +++ b/bin/tests/system/checkconf/bad-root-mixed-key.conf @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (19036) is to be phased out starting in 2017. It will + # remain in the root zone for some time after its successor key + # has been added. It will remain this file until it is removed from + # the root zone. + . static-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq + QxA+Uk1ihz0="; + + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/bad-rpz-ede.conf b/bin/tests/system/checkconf/bad-rpz-ede.conf new file mode 100644 index 0000000..8d78f8d --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-ede.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." ede unsupported; + }; +}; diff --git a/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf b/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf new file mode 100644 index 0000000..0eb9ef3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-too-many-zones.conf @@ -0,0 +1,148 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + response-policy { + zone "max1"; + zone "max2"; + zone "max3"; + zone "max4"; + zone "max5"; + zone "max6"; + zone "max7"; + zone "max8"; + zone "max9"; + zone "max10"; + zone "max11"; + zone "max12"; + zone "max13"; + zone "max14"; + zone "max15"; + zone "max16"; + zone "max17"; + zone "max18"; + zone "max19"; + zone "max20"; + zone "max21"; + zone "max22"; + zone "max23"; + zone "max24"; + zone "max25"; + zone "max26"; + zone "max27"; + zone "max28"; + zone "max29"; + zone "max30"; + zone "max31"; + zone "max32"; + zone "max33"; + zone "max34"; + zone "max35"; + zone "max36"; + zone "max37"; + zone "max38"; + zone "max39"; + zone "max40"; + zone "max41"; + zone "max42"; + zone "max43"; + zone "max44"; + zone "max45"; + zone "max46"; + zone "max47"; + zone "max48"; + zone "max49"; + zone "max50"; + zone "max51"; + zone "max52"; + zone "max53"; + zone "max54"; + zone "max55"; + zone "max56"; + zone "max57"; + zone "max58"; + zone "max59"; + zone "max60"; + zone "max61"; + zone "max62"; + zone "max63"; + zone "max64"; + zone "max65"; + }; +}; + +zone "max1" { type primary; file "rpz.db"; }; +zone "max2" { type primary; file "rpz.db"; }; +zone "max3" { type primary; file "rpz.db"; }; +zone "max4" { type primary; file "rpz.db"; }; +zone "max5" { type primary; file "rpz.db"; }; +zone "max6" { type primary; file "rpz.db"; }; +zone "max7" { type primary; file "rpz.db"; }; +zone "max8" { type primary; file "rpz.db"; }; +zone "max9" { type primary; file "rpz.db"; }; +zone "max10" { type primary; file "rpz.db"; }; +zone "max11" { type primary; file "rpz.db"; }; +zone "max12" { type primary; file "rpz.db"; }; +zone "max13" { type primary; file "rpz.db"; }; +zone "max14" { type primary; file "rpz.db"; }; +zone "max15" { type primary; file "rpz.db"; }; +zone "max16" { type primary; file "rpz.db"; }; +zone "max17" { type primary; file "rpz.db"; }; +zone "max18" { type primary; file "rpz.db"; }; +zone "max19" { type primary; file "rpz.db"; }; +zone "max20" { type primary; file "rpz.db"; }; +zone "max21" { type primary; file "rpz.db"; }; +zone "max22" { type primary; file "rpz.db"; }; +zone "max23" { type primary; file "rpz.db"; }; +zone "max24" { type primary; file "rpz.db"; }; +zone "max25" { type primary; file "rpz.db"; }; +zone "max26" { type primary; file "rpz.db"; }; +zone "max27" { type primary; file "rpz.db"; }; +zone "max28" { type primary; file "rpz.db"; }; +zone "max29" { type primary; file "rpz.db"; }; +zone "max30" { type primary; file "rpz.db"; }; +zone "max31" { type primary; file "rpz.db"; }; +zone "max32" { type primary; file "rpz.db"; }; +zone "max33" { type primary; file "rpz.db"; }; +zone "max34" { type primary; file "rpz.db"; }; +zone "max35" { type primary; file "rpz.db"; }; +zone "max36" { type primary; file "rpz.db"; }; +zone "max37" { type primary; file "rpz.db"; }; +zone "max38" { type primary; file "rpz.db"; }; +zone "max39" { type primary; file "rpz.db"; }; +zone "max40" { type primary; file "rpz.db"; }; +zone "max41" { type primary; file "rpz.db"; }; +zone "max42" { type primary; file "rpz.db"; }; +zone "max43" { type primary; file "rpz.db"; }; +zone "max44" { type primary; file "rpz.db"; }; +zone "max45" { type primary; file "rpz.db"; }; +zone "max46" { type primary; file "rpz.db"; }; +zone "max47" { type primary; file "rpz.db"; }; +zone "max48" { type primary; file "rpz.db"; }; +zone "max49" { type primary; file "rpz.db"; }; +zone "max50" { type primary; file "rpz.db"; }; +zone "max51" { type primary; file "rpz.db"; }; +zone "max52" { type primary; file "rpz.db"; }; +zone "max53" { type primary; file "rpz.db"; }; +zone "max54" { type primary; file "rpz.db"; }; +zone "max55" { type primary; file "rpz.db"; }; +zone "max56" { type primary; file "rpz.db"; }; +zone "max57" { type primary; file "rpz.db"; }; +zone "max58" { type primary; file "rpz.db"; }; +zone "max59" { type primary; file "rpz.db"; }; +zone "max60" { type primary; file "rpz.db"; }; +zone "max61" { type primary; file "rpz.db"; }; +zone "max62" { type primary; file "rpz.db"; }; +zone "max63" { type primary; file "rpz.db"; }; +zone "max64" { type primary; file "rpz.db"; }; +zone "max65" { type primary; file "rpz.db"; }; diff --git a/bin/tests/system/checkconf/bad-rpz-ttl.conf b/bin/tests/system/checkconf/bad-rpz-ttl.conf new file mode 100644 index 0000000..7b3a6ef --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-ttl.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." policy given; + } + max-policy-ttl 1x; +}; diff --git a/bin/tests/system/checkconf/bad-rpz-update.conf b/bin/tests/system/checkconf/bad-rpz-update.conf new file mode 100644 index 0000000..a03f179 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-update.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." + policy given + min-update-interval 5x; + }; +}; diff --git a/bin/tests/system/checkconf/bad-rpz-zone.conf b/bin/tests/system/checkconf/bad-rpz-zone.conf new file mode 100644 index 0000000..4aadc61 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rpz-zone.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + response-policy { + zone "nonexistent"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-rrl-table-size.conf b/bin/tests/system/checkconf/bad-rrl-table-size.conf new file mode 100644 index 0000000..3325406 --- /dev/null +++ b/bin/tests/system/checkconf/bad-rrl-table-size.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rate-limit { + responses-per-second 2; + all-per-second 50; + slip 3; + exempt-clients { 10.53.0.7; }; + log-only yes; + + min-table-size 0; + max-table-size 0; + }; +}; diff --git a/bin/tests/system/checkconf/bad-sharedwritable1.conf b/bin/tests/system/checkconf/bad-sharedwritable1.conf new file mode 100644 index 0000000..3fcb1af --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedwritable1.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone a { + type primary; + file "shared.db"; +}; +zone b { + type secondary; + file "shared.db"; + primaries { 1.2.3.4; }; +}; diff --git a/bin/tests/system/checkconf/bad-sharedwritable2.conf b/bin/tests/system/checkconf/bad-sharedwritable2.conf new file mode 100644 index 0000000..e8c940c --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedwritable2.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone a { + type secondary; + file "shared.db"; + primaries { 1.2.3.4; }; +}; +zone b { + type secondary; + file "shared.db"; + primaries { 1.2.3.4; }; +}; diff --git a/bin/tests/system/checkconf/bad-sharedzone1.conf b/bin/tests/system/checkconf/bad-sharedzone1.conf new file mode 100644 index 0000000..fccffe9 --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedzone1.conf @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "first" { + match-clients { + "none"; + }; + zone "clone" { + type primary; + file "xxx"; + }; +}; +view "second" { + match-clients { + "any"; + }; + zone "clone" { + in-view "first"; + type secondary; + }; +}; diff --git a/bin/tests/system/checkconf/bad-sharedzone2.conf b/bin/tests/system/checkconf/bad-sharedzone2.conf new file mode 100644 index 0000000..76032e3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedzone2.conf @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "first" { + match-clients { + "none"; + }; + zone "clone" { + type primary; + file "xxx"; + }; +}; +view "second" { + match-clients { + "any"; + }; + zone "clone" { + in-view "first"; + forward only; + forwarders { 10.0.0.100; }; + type secondary; + }; +}; diff --git a/bin/tests/system/checkconf/bad-sharedzone3.conf b/bin/tests/system/checkconf/bad-sharedzone3.conf new file mode 100644 index 0000000..07e92bd --- /dev/null +++ b/bin/tests/system/checkconf/bad-sharedzone3.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view first { + zone shared.example { + in-view second; + }; +}; + +view second { + zone shared.example { + type primary; + file "shared.example.db"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-sig0checks-quota-exempt.conf b/bin/tests/system/checkconf/bad-sig0checks-quota-exempt.conf new file mode 100644 index 0000000..c54227d --- /dev/null +++ b/bin/tests/system/checkconf/bad-sig0checks-quota-exempt.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + sig0checks-quota-exempt { unknownacl; }; +}; diff --git a/bin/tests/system/checkconf/bad-static-initial-1.conf b/bin/tests/system/checkconf/bad-static-initial-1.conf new file mode 100644 index 0000000..91a5c10 --- /dev/null +++ b/bin/tests/system/checkconf/bad-static-initial-1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3"; + example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6"; +}; diff --git a/bin/tests/system/checkconf/bad-static-initial-2.conf b/bin/tests/system/checkconf/bad-static-initial-2.conf new file mode 100644 index 0000000..3b4754d --- /dev/null +++ b/bin/tests/system/checkconf/bad-static-initial-2.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3"; + example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-static-initial-3.conf b/bin/tests/system/checkconf/bad-static-initial-3.conf new file mode 100644 index 0000000..c396d9c --- /dev/null +++ b/bin/tests/system/checkconf/bad-static-initial-3.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3"; + example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-static-initial-4.conf b/bin/tests/system/checkconf/bad-static-initial-4.conf new file mode 100644 index 0000000..2170d52 --- /dev/null +++ b/bin/tests/system/checkconf/bad-static-initial-4.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. initial-key 257 3 5 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafGtURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJYkYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJfpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaSWG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjINQyrszHhWUU="; + example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-stub-masters-dialup.conf b/bin/tests/system/checkconf/bad-stub-masters-dialup.conf new file mode 100644 index 0000000..a30236c --- /dev/null +++ b/bin/tests/system/checkconf/bad-stub-masters-dialup.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + heartbeat-interval 2; + recursion no; +}; +zone "." { + type hint; + file "hint"; +}; +zone "example." { + type stub; + dialup notify; + notify no; + file "example.bk"; + // primaries { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-tls-cipher-suites-ciphers-string.conf b/bin/tests/system/checkconf/bad-tls-cipher-suites-ciphers-string.conf new file mode 100644 index 0000000..524239c --- /dev/null +++ b/bin/tests/system/checkconf/bad-tls-cipher-suites-ciphers-string.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.3; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + cipher-suites "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-tls-cipher-suites-empty-string.conf b/bin/tests/system/checkconf/bad-tls-cipher-suites-empty-string.conf new file mode 100644 index 0000000..7e0ebcf --- /dev/null +++ b/bin/tests/system/checkconf/bad-tls-cipher-suites-empty-string.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.3; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + cipher-suites ""; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-tls-cipher-suites-wrong-string.conf b/bin/tests/system/checkconf/bad-tls-cipher-suites-wrong-string.conf new file mode 100644 index 0000000..44f74fe --- /dev/null +++ b/bin/tests/system/checkconf/bad-tls-cipher-suites-wrong-string.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.3; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + cipher-suites "lalalalalgggg"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/bad-transfer-source-v6.conf b/bin/tests/system/checkconf/bad-transfer-source-v6.conf new file mode 100644 index 0000000..da182ff --- /dev/null +++ b/bin/tests/system/checkconf/bad-transfer-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + transfer-source-v6 fd92:7065:b8e:ffff::1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-transfer-source.conf b/bin/tests/system/checkconf/bad-transfer-source.conf new file mode 100644 index 0000000..315c410 --- /dev/null +++ b/bin/tests/system/checkconf/bad-transfer-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + transfer-source 10.53.0.1 port 5300; +}; diff --git a/bin/tests/system/checkconf/bad-tsig.conf.j2 b/bin/tests/system/checkconf/bad-tsig.conf.j2 new file mode 100644 index 0000000..3e3023c --- /dev/null +++ b/bin/tests/system/checkconf/bad-tsig.conf.j2 @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* Bad secret */ +key "badtsig" { + algorithm @DEFAULT_HMAC@; + secret "jEdD+BPKg=="; +}; diff --git a/bin/tests/system/checkconf/bad-unix-domain-socket.conf b/bin/tests/system/checkconf/bad-unix-domain-socket.conf new file mode 100644 index 0000000..53daa54 --- /dev/null +++ b/bin/tests/system/checkconf/bad-unix-domain-socket.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { + unix "/tmp/socket" perm 0700 owner 0 group 0; +}; diff --git a/bin/tests/system/checkconf/bad-unpaired-keys.conf b/bin/tests/system/checkconf/bad-unpaired-keys.conf new file mode 100644 index 0000000..63b6dc2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-unpaired-keys.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy unpaired-keys { + keys { + /* zsk without ksk */ + zsk lifetime 30d algorithm 13; + /* ksk without zsk */ + ksk lifetime 30d algorithm 7; + }; +}; + +zone "example" { + type primary; + file "example.db"; + dnssec-policy unpaired-keys; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy1.conf b/bin/tests/system/checkconf/bad-update-policy1.conf new file mode 100644 index 0000000..fa1330c --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy1.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * self TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy10.conf b/bin/tests/system/checkconf/bad-update-policy10.conf new file mode 100644 index 0000000..39ac656 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy10.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * krb5-selfsub TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy11.conf b/bin/tests/system/checkconf/bad-update-policy11.conf new file mode 100644 index 0000000..d148b58 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy11.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * ms-selfsub TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy12.conf b/bin/tests/system/checkconf/bad-update-policy12.conf new file mode 100644 index 0000000..dc79db3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy12.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * external TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy13.conf b/bin/tests/system/checkconf/bad-update-policy13.conf new file mode 100644 index 0000000..694c73b --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy13.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant a-key-name name TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy14.conf b/bin/tests/system/checkconf/bad-update-policy14.conf new file mode 100644 index 0000000..af02ef2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy14.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant a-key-name subdomain TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy15.conf b/bin/tests/system/checkconf/bad-update-policy15.conf new file mode 100644 index 0000000..f8f7d13 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy15.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant a-key-name wildcard TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy16.conf b/bin/tests/system/checkconf/bad-update-policy16.conf new file mode 100644 index 0000000..747c381 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy16.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * tcp-self . "ptr(10 )"; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy17.conf b/bin/tests/system/checkconf/bad-update-policy17.conf new file mode 100644 index 0000000..a2955f2 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy17.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant realm krb5-subdomain-self-rhs PTR; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy18.conf b/bin/tests/system/checkconf/bad-update-policy18.conf new file mode 100644 index 0000000..090f621 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy18.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant realm krb5-subdomain-self-rhs SRV; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy19.conf b/bin/tests/system/checkconf/bad-update-policy19.conf new file mode 100644 index 0000000..b8c636b --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy19.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant realm ms-subdomain-self-rhs PTR; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy2.conf b/bin/tests/system/checkconf/bad-update-policy2.conf new file mode 100644 index 0000000..0d5adf6 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy2.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfsub TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy20.conf b/bin/tests/system/checkconf/bad-update-policy20.conf new file mode 100644 index 0000000..9775e2c --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy20.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant realm ms-subdomain-self-rhs SRV; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy3.conf b/bin/tests/system/checkconf/bad-update-policy3.conf new file mode 100644 index 0000000..4583ede --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy3.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfwild TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy4.conf b/bin/tests/system/checkconf/bad-update-policy4.conf new file mode 100644 index 0000000..52a074d --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy4.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * ms-self TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy5.conf b/bin/tests/system/checkconf/bad-update-policy5.conf new file mode 100644 index 0000000..38a6d4f --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy5.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * krb5-self TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy6.conf b/bin/tests/system/checkconf/bad-update-policy6.conf new file mode 100644 index 0000000..acca627 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy6.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * ms-subdomain TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy7.conf b/bin/tests/system/checkconf/bad-update-policy7.conf new file mode 100644 index 0000000..95541d4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy7.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * krb5-subdomain TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy8.conf b/bin/tests/system/checkconf/bad-update-policy8.conf new file mode 100644 index 0000000..d0534c4 --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy8.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * tcp-self TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-update-policy9.conf b/bin/tests/system/checkconf/bad-update-policy9.conf new file mode 100644 index 0000000..96d201c --- /dev/null +++ b/bin/tests/system/checkconf/bad-update-policy9.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * 6to4-self TXT; + }; +}; diff --git a/bin/tests/system/checkconf/bad-validation-auto-key.conf b/bin/tests/system/checkconf/bad-validation-auto-key.conf new file mode 100644 index 0000000..bd6f547 --- /dev/null +++ b/bin/tests/system/checkconf/bad-validation-auto-key.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation auto; +}; + +trust-anchors { + . static-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod + y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ + YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX + 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw + E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/ + Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn + 6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/bad-view-also-notify.conf b/bin/tests/system/checkconf/bad-view-also-notify.conf new file mode 100644 index 0000000..071a621 --- /dev/null +++ b/bin/tests/system/checkconf/bad-view-also-notify.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view example { + also-notify { missing; }; + zone "example.net" { + type secondary; + primaries { 192.168.1.1; }; + }; +}; diff --git a/bin/tests/system/checkconf/bad-zsk-without-ksk.conf b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf new file mode 100644 index 0000000..31b031c --- /dev/null +++ b/bin/tests/system/checkconf/bad-zsk-without-ksk.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy zsk-without-ksk { + keys { + zsk lifetime 30d algorithm 13; + }; +}; + +zone "example" { + type primary; + file "example.db"; + dnssec-policy zsk-without-ksk; +}; diff --git a/bin/tests/system/checkconf/check-dup-records-fail.conf b/bin/tests/system/checkconf/check-dup-records-fail.conf new file mode 100644 index 0000000..04880b6 --- /dev/null +++ b/bin/tests/system/checkconf/check-dup-records-fail.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-integrity yes; // default is yes +}; + +zone "check-dup-records" { + type primary; + file "check-dup-records.db"; + check-dup-records fail; +}; + diff --git a/bin/tests/system/checkconf/check-dup-records.db b/bin/tests/system/checkconf/check-dup-records.db new file mode 100644 index 0000000..558686c --- /dev/null +++ b/bin/tests/system/checkconf/check-dup-records.db @@ -0,0 +1,33 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail + +mail A 10.0.0.1 +ns2 A 10.53.0.2 + +; following records are not de-duplicated +; and will be matched by check-dup-records +duplicate HIP ( 2 200100107B1A74DF365639CC39F1D578 + AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D + rvs.example.com. ) +duplicate HIP ( 2 200100107B1A74DF365639CC39F1D578 + AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D + RVS.example.com. ) diff --git a/bin/tests/system/checkconf/check-missing-zone.conf b/bin/tests/system/checkconf/check-missing-zone.conf new file mode 100644 index 0000000..daf2cf7 --- /dev/null +++ b/bin/tests/system/checkconf/check-missing-zone.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view missing { + zone missing.example { + type primary; + file "missing.example.db"; + }; +}; + +view good { + zone shared.example { + type primary; + file "shared.example.db"; + }; +}; diff --git a/bin/tests/system/checkconf/check-mixed-keys.conf b/bin/tests/system/checkconf/check-mixed-keys.conf new file mode 100644 index 0000000..1dd018d --- /dev/null +++ b/bin/tests/system/checkconf/check-mixed-keys.conf @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (19036) is to be phased out starting in 2017. It will + # remain in the root zone for some time after its successor key + # has been added. It will remain this file until it is removed from + # the root zone. + . static-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq + QxA+Uk1ihz0="; +}; + +managed-keys { + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/check-mx-cname-fail.conf b/bin/tests/system/checkconf/check-mx-cname-fail.conf new file mode 100644 index 0000000..ac52ec0 --- /dev/null +++ b/bin/tests/system/checkconf/check-mx-cname-fail.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-integrity yes; // default is yes +}; + +zone "check-mx-cname" { + type primary; + file "check-mx-cname.db"; + check-mx-cname fail; +}; diff --git a/bin/tests/system/checkconf/check-mx-cname.db b/bin/tests/system/checkconf/check-mx-cname.db new file mode 100644 index 0000000..dc30f08 --- /dev/null +++ b/bin/tests/system/checkconf/check-mx-cname.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail + +; MX points to a CNAME which is detected by check-mx-cname +mail CNAME ns2 + +ns2 A 10.53.0.2 diff --git a/bin/tests/system/checkconf/check-mx-fail.conf b/bin/tests/system/checkconf/check-mx-fail.conf new file mode 100644 index 0000000..aa7a666 --- /dev/null +++ b/bin/tests/system/checkconf/check-mx-fail.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-integrity yes; // default is yes +}; + +zone "check-mx" { + type primary; + file "check-mx.db"; + check-mx fail; +}; diff --git a/bin/tests/system/checkconf/check-mx.db b/bin/tests/system/checkconf/check-mx.db new file mode 100644 index 0000000..dced644 --- /dev/null +++ b/bin/tests/system/checkconf/check-mx.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +; MX appears to be an address and will be detected by check-mx + MX 10 10.0.0.1 + +ns2 A 10.53.0.2 diff --git a/bin/tests/system/checkconf/check-names-fail.conf b/bin/tests/system/checkconf/check-names-fail.conf new file mode 100644 index 0000000..86be82d --- /dev/null +++ b/bin/tests/system/checkconf/check-names-fail.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-integrity yes; // default is yes +}; + +zone "check-names" { + type primary; + file "check-names.db"; + check-names fail; +}; diff --git a/bin/tests/system/checkconf/check-names.db b/bin/tests/system/checkconf/check-names.db new file mode 100644 index 0000000..0274ec9 --- /dev/null +++ b/bin/tests/system/checkconf/check-names.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail + +mail A 10.0.0.1 +ns2 A 10.53.0.2 + +; the RDATA of this record contains a name that may be considered +; invalid and will be detected by check-names configuration. +check-names SRV 1 2 3 _underscore diff --git a/bin/tests/system/checkconf/check-root-ksk-2010.conf b/bin/tests/system/checkconf/check-root-ksk-2010.conf new file mode 100644 index 0000000..d422635 --- /dev/null +++ b/bin/tests/system/checkconf/check-root-ksk-2010.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (19036) is to be phased out starting in 2017. It will + # remain in the root zone for some time after its successor key + # has been added. It will remain this file until it is removed from + # the root zone. + . initial-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq + QxA+Uk1ihz0="; +}; diff --git a/bin/tests/system/checkconf/check-root-ksk-2017.conf b/bin/tests/system/checkconf/check-root-ksk-2017.conf new file mode 100644 index 0000000..72f6fb4 --- /dev/null +++ b/bin/tests/system/checkconf/check-root-ksk-2017.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/check-root-ksk-both.conf b/bin/tests/system/checkconf/check-root-ksk-both.conf new file mode 100644 index 0000000..88c308f --- /dev/null +++ b/bin/tests/system/checkconf/check-root-ksk-both.conf @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (19036) is to be phased out starting in 2017. It will + # remain in the root zone for some time after its successor key + # has been added. It will remain this file until it is removed from + # the root zone. + . initial-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq + QxA+Uk1ihz0="; + + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/check-root-static-ds.conf b/bin/tests/system/checkconf/check-root-static-ds.conf new file mode 100644 index 0000000..eb37b85 --- /dev/null +++ b/bin/tests/system/checkconf/check-root-static-ds.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + . static-ds 20326 8 2 "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"; +}; diff --git a/bin/tests/system/checkconf/check-root-static-key.conf b/bin/tests/system/checkconf/check-root-static-key.conf new file mode 100644 index 0000000..7be5304 --- /dev/null +++ b/bin/tests/system/checkconf/check-root-static-key.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . static-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/check-root-trusted-key.conf b/bin/tests/system/checkconf/check-root-trusted-key.conf new file mode 100644 index 0000000..65261a8 --- /dev/null +++ b/bin/tests/system/checkconf/check-root-trusted-key.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trusted-keys { + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; diff --git a/bin/tests/system/checkconf/check-srv-cname-fail.conf b/bin/tests/system/checkconf/check-srv-cname-fail.conf new file mode 100644 index 0000000..3897bf8 --- /dev/null +++ b/bin/tests/system/checkconf/check-srv-cname-fail.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + check-integrity yes; // default is yes +}; + +zone "check-srv-cname" { + type primary; + file "check-srv-cname.db"; + check-srv-cname fail; +}; diff --git a/bin/tests/system/checkconf/check-srv-cname.db b/bin/tests/system/checkconf/check-srv-cname.db new file mode 100644 index 0000000..0671ab1 --- /dev/null +++ b/bin/tests/system/checkconf/check-srv-cname.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail + +mail A 10.0.0.1 +ns2 A 10.53.0.2 + +check-srv-cname SRV 1 2 3 target +; SRV points to a CNAME which is detected by check-srv-cname configuration +target CNAME mail diff --git a/bin/tests/system/checkconf/check-wildcard-no.conf b/bin/tests/system/checkconf/check-wildcard-no.conf new file mode 100644 index 0000000..beb641a --- /dev/null +++ b/bin/tests/system/checkconf/check-wildcard-no.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "check-wildcard" { + type primary; + file "check-wildcard.db"; + check-wildcard no; +}; diff --git a/bin/tests/system/checkconf/check-wildcard.conf b/bin/tests/system/checkconf/check-wildcard.conf new file mode 100644 index 0000000..263f8b4 --- /dev/null +++ b/bin/tests/system/checkconf/check-wildcard.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "check-wildcard" { + type primary; + file "check-wildcard.db"; + check-wildcard yes; +}; diff --git a/bin/tests/system/checkconf/check-wildcard.db b/bin/tests/system/checkconf/check-wildcard.db new file mode 100644 index 0000000..1db5af0 --- /dev/null +++ b/bin/tests/system/checkconf/check-wildcard.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 +; an interior wildcard name +foo.* TXT The owner name contains an interior wildcard diff --git a/bin/tests/system/checkconf/deprecated.conf b/bin/tests/system/checkconf/deprecated.conf new file mode 100644 index 0000000..e90d946 --- /dev/null +++ b/bin/tests/system/checkconf/deprecated.conf @@ -0,0 +1,65 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +server 1.2.3.4 { + query-source 10.10.10.10 port 5353; +}; + +options { + dnssec-validation yes; + max-zone-ttl 600; + + dialup yes; + heartbeat-interval 60; + + use-v4-udp-ports { range 1024 65535; }; + use-v6-udp-ports { range 1024 65535; }; + avoid-v4-udp-ports { range 1 1023; }; + avoid-v6-udp-ports { range 1 1023; }; + + dnssec-must-be-secure mustbesecure.example yes; + + sortlist { }; + + rrset-order { + name "fixed.example" order fixed; + }; +}; + +trusted-keys { + fake.trusted. 257 3 8 + "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX + bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD + X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz + W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS + Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq + QxA+Uk1ihz0="; +}; + +managed-keys { + fake.managed. initial-key 257 3 8 + "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; +}; + +zone example.com { + type primary; + file "maxttl-bad.db"; + max-zone-ttl 120; +}; diff --git a/bin/tests/system/checkconf/dlz-bad.conf b/bin/tests/system/checkconf/dlz-bad.conf new file mode 100644 index 0000000..7332112 --- /dev/null +++ b/bin/tests/system/checkconf/dlz-bad.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dlz one { + database "one"; +}; + +dlz two { + database "two"; + search no; +}; + +zone primary { + type primary; + database "none"; + dlz two; +}; diff --git a/bin/tests/system/checkconf/good-acl.conf b/bin/tests/system/checkconf/good-acl.conf new file mode 100644 index 0000000..be32923 --- /dev/null +++ b/bin/tests/system/checkconf/good-acl.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl a { + { "none"; }; + { !19.0.0.0/8; }; +}; + +options { + allow-query { a; }; +}; diff --git a/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf b/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf new file mode 100644 index 0000000..5bc9232 --- /dev/null +++ b/bin/tests/system/checkconf/good-allow-update-forwarding-view.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + allow-update-forwarding { any; }; +}; diff --git a/bin/tests/system/checkconf/good-allow-update-forwarding.conf b/bin/tests/system/checkconf/good-allow-update-forwarding.conf new file mode 100644 index 0000000..d7e89be --- /dev/null +++ b/bin/tests/system/checkconf/good-allow-update-forwarding.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + allow-update-forwarding { any; }; +}; diff --git a/bin/tests/system/checkconf/good-allow-update-view.conf b/bin/tests/system/checkconf/good-allow-update-view.conf new file mode 100644 index 0000000..da799a2 --- /dev/null +++ b/bin/tests/system/checkconf/good-allow-update-view.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + allow-update { any; }; +}; diff --git a/bin/tests/system/checkconf/good-allow-update.conf b/bin/tests/system/checkconf/good-allow-update.conf new file mode 100644 index 0000000..6b7a67e --- /dev/null +++ b/bin/tests/system/checkconf/good-allow-update.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + allow-update { any; }; +}; diff --git a/bin/tests/system/checkconf/good-class.conf b/bin/tests/system/checkconf/good-class.conf new file mode 100644 index 0000000..2f8c321 --- /dev/null +++ b/bin/tests/system/checkconf/good-class.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "example" class00 { }; diff --git a/bin/tests/system/checkconf/good-dnssec-policy-range.conf b/bin/tests/system/checkconf/good-dnssec-policy-range.conf new file mode 100644 index 0000000..68f9afd --- /dev/null +++ b/bin/tests/system/checkconf/good-dnssec-policy-range.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy restricted-range { + keys { + ksk lifetime unlimited algorithm rsasha256 tag-range 0 32767 2048; + zsk lifetime unlimited algorithm rsasha256 tag-range 0 32767; + }; +}; + +dnssec-policy unrestricted-range { + keys { + ksk lifetime unlimited algorithm rsasha256 2048; + zsk lifetime unlimited algorithm rsasha256; + }; +}; diff --git a/bin/tests/system/checkconf/good-doh-1.conf b/bin/tests/system/checkconf/good-doh-1.conf new file mode 100644 index 0000000..0c642ec --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-1.conf @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-doh-2.conf b/bin/tests/system/checkconf/good-doh-2.conf new file mode 100644 index 0000000..1bbe9e0 --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-2.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +http local-http-server { + endpoints { "/dns-query"; }; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + listen-on port 443 http local-http-server tls local-tls { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-doh-3.conf b/bin/tests/system/checkconf/good-doh-3.conf new file mode 100644 index 0000000..cd410b9 --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-3.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + listen-on port 8080 tls none http default { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-doh-4.conf b/bin/tests/system/checkconf/good-doh-4.conf new file mode 100644 index 0000000..d191347 --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-4.conf @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +# Use the default values only - just to make sure that we could +# override only values which we need and there is no required ones. +http empty-http-server { +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + listen-on port 443 tls local-tls http empty-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http empty-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-doh-tlsopts.conf b/bin/tests/system/checkconf/good-doh-tlsopts.conf new file mode 100644 index 0000000..7ba4bdb --- /dev/null +++ b/bin/tests/system/checkconf/good-doh-tlsopts.conf @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + listen-on { 10.53.0.1; }; + http-port 80; + https-port 443; + http-listener-clients 100; + http-streams-per-connection 100; + listen-on port 443 tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-1.conf b/bin/tests/system/checkconf/good-dot-1.conf new file mode 100644 index 0000000..d94616a --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-1.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + key-file "key.pem"; + cert-file "cert.pem"; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf new file mode 100644 index 0000000..74c7969 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-allow-transfer-encrypted.conf @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example1" { + type primary; + file "example1.db"; + allow-transfer port 44344 transport tls { any; }; +}; + +zone "example2" { + type primary; + file "example2.db"; + allow-transfer port 44344 transport tcp { any; }; +}; + +zone "example3" { + type primary; + file "example3.db"; + allow-transfer transport tls { any; }; +}; + +zone "example4" { + type primary; + file "example4.db"; + allow-transfer transport tcp { any; }; +}; + + +zone "example5" { + type primary; + file "example5.db"; + allow-transfer port 53 { any; }; +}; + +zone "example6" { + type primary; + file "example6.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf b/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf new file mode 100644 index 0000000..d541d15 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-doh-tls-nokeycert.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# In some cases a "tls" statement may omit key-file and cert-file. +tls local-tls { + protocols {TLSv1.2;}; + remote-hostname "fqdn.example.com"; +}; diff --git a/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf b/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf new file mode 100644 index 0000000..2b33cf3 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-primaries-ephemeral.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls ephemeral; }; + file "example.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-primaries.conf b/bin/tests/system/checkconf/good-dot-primaries.conf new file mode 100644 index 0000000..592a94c --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-primaries.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls local-tls; }; + file "example.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/checkconf/good-dot-tlsopts.conf b/bin/tests/system/checkconf/good-dot-tlsopts.conf new file mode 100644 index 0000000..fc7e248 --- /dev/null +++ b/bin/tests/system/checkconf/good-dot-tlsopts.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-ds-key-1.conf b/bin/tests/system/checkconf/good-ds-key-1.conf new file mode 100644 index 0000000..de7de84 --- /dev/null +++ b/bin/tests/system/checkconf/good-ds-key-1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3"; + example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/good-ds-key-2.conf b/bin/tests/system/checkconf/good-ds-key-2.conf new file mode 100644 index 0000000..060fb2f --- /dev/null +++ b/bin/tests/system/checkconf/good-ds-key-2.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3"; + example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/good-dup-managed-key.conf b/bin/tests/system/checkconf/good-dup-managed-key.conf new file mode 100644 index 0000000..2f91247 --- /dev/null +++ b/bin/tests/system/checkconf/good-dup-managed-key.conf @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trust-anchors { + example. initial-key 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl + 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG + tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY + kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ + fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS + WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI + NQyrszHhWUU="; + example. initial-key 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod + y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ + YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX + 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw + E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/ + Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn + 6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/good-dup-trusted-key.conf b/bin/tests/system/checkconf/good-dup-trusted-key.conf new file mode 100644 index 0000000..46089c4 --- /dev/null +++ b/bin/tests/system/checkconf/good-dup-trusted-key.conf @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trusted-keys { + example. 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl + 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG + tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY + kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ + fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS + WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI + NQyrszHhWUU="; + example. 257 3 8 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbod + y0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQ + YfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX + 2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuw + E60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/ + Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn + 6zqCkwuMmrU="; +}; diff --git a/bin/tests/system/checkconf/good-empty-trust-anchors.conf b/bin/tests/system/checkconf/good-empty-trust-anchors.conf new file mode 100644 index 0000000..f6277a3 --- /dev/null +++ b/bin/tests/system/checkconf/good-empty-trust-anchors.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trust-anchors {}; diff --git a/bin/tests/system/checkconf/good-empty-trusted-keys.conf b/bin/tests/system/checkconf/good-empty-trusted-keys.conf new file mode 100644 index 0000000..b153d45 --- /dev/null +++ b/bin/tests/system/checkconf/good-empty-trusted-keys.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trusted-keys {}; diff --git a/bin/tests/system/checkconf/good-forwarders-dot.conf b/bin/tests/system/checkconf/good-forwarders-dot.conf new file mode 100644 index 0000000..0d9bfa3 --- /dev/null +++ b/bin/tests/system/checkconf/good-forwarders-dot.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls test-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; +}; + +tls another-tls { + protocols { TLSv1.2; }; + session-tickets no; +}; + +zone "example" { + type forward; + forward only; + forwarders port 5300 tls test-tls { 10.53.0.1; 10.53.0.2 port 5301 tls another-tls; }; +}; diff --git a/bin/tests/system/checkconf/good-initial-ds.conf b/bin/tests/system/checkconf/good-initial-ds.conf new file mode 100644 index 0000000..b54a2b3 --- /dev/null +++ b/bin/tests/system/checkconf/good-initial-ds.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. initial-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6"; +}; diff --git a/bin/tests/system/checkconf/good-interface-interval.conf b/bin/tests/system/checkconf/good-interface-interval.conf new file mode 100644 index 0000000..60c50b3 --- /dev/null +++ b/bin/tests/system/checkconf/good-interface-interval.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + interface-interval 1h; +}; diff --git a/bin/tests/system/checkconf/good-kasp.conf b/bin/tests/system/checkconf/good-kasp.conf new file mode 100644 index 0000000..e0a3241 --- /dev/null +++ b/bin/tests/system/checkconf/good-kasp.conf @@ -0,0 +1,77 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * This is just a random selection of DNSSEC configuration options. + */ + +/* cut here */ +dnssec-policy "test" { + cdnskey yes; + cds-digest-types { + "sha-256"; + }; + dnskey-ttl 3600; + inline-signing yes; + keys { + ksk key-directory lifetime P1Y algorithm ecdsa256; + zsk lifetime P30D algorithm 13; + csk key-store "hsm" lifetime unlimited algorithm rsasha256 2048; + }; + max-zone-ttl 86400; + nsec3param iterations 0 optout no salt-length 8; + offline-ksk no; + parent-ds-ttl 7200; + parent-propagation-delay PT1H; + publish-safety PT3600S; + retire-safety PT3600S; + signatures-jitter PT12H; + signatures-refresh P3D; + signatures-validity P2W; + signatures-validity-dnskey P14D; + zone-propagation-delay PT5M; +}; +key-store "hsm" { + directory "."; + pkcs11-uri "pkcs11:token=bind9;pin-value=1234"; +}; +options { + dnssec-policy "default"; +}; +zone "example1" { + type primary; + file "example1.db"; +}; +zone "example2" { + type primary; + file "example2.db"; + allow-update { + "any"; + }; + dnssec-policy "test"; +}; +zone "example3" { + type primary; + file "example3.db"; + dnssec-policy "default"; +}; +zone "dnssec-policy-none-shared-zonefile1" { + type primary; + file "shared.db"; + dnssec-policy "none"; +}; +zone "dnssec-policy-none-shared-zonefile2" { + type primary; + file "shared.db"; + dnssec-policy "none"; +}; diff --git a/bin/tests/system/checkconf/good-key-directory.conf b/bin/tests/system/checkconf/good-key-directory.conf new file mode 100644 index 0000000..063c4a9 --- /dev/null +++ b/bin/tests/system/checkconf/good-key-directory.conf @@ -0,0 +1,70 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "internet" { + keys { + ksk key-directory lifetime unlimited algorithm ecdsa256; + zsk key-directory lifetime P90D algorithm ecdsa256; + }; + + nsec3param iterations 0 optout no salt-length 8; +}; + +dnssec-policy "intranet" { + keys { + ksk key-directory lifetime unlimited algorithm ecdsa256; + zsk key-directory lifetime P30D algorithm ecdsa256; + }; + nsec3param iterations 0 optout no salt-length 8; +}; + +dnssec-policy "localhost" { + keys { + ksk key-directory lifetime unlimited algorithm ecdsa256; + zsk key-directory lifetime P30D algorithm ecdsa256; + }; + nsec3param iterations 0 optout no salt-length 8; +}; + +options { + key-directory "global/keys"; +}; + +view "localhost" { + match-clients { 127.0.0.1; ::1; }; + zone "example.com" IN { + type primary; + file "localhost/example.com.zone"; + dnssec-policy "localhost"; + }; +}; + +view "external" { + match-clients { 0/0; }; + key-directory "external/keys"; + zone "example.com" IN { + type primary; + file "external/example.com.zone"; + dnssec-policy "internet"; + }; +}; + +view "internal" { + match-clients { ::/0; }; + key-directory "internal/keys"; + zone "example.com" IN { + type primary; + file "internal/example.com.zone"; + dnssec-policy "intranet"; + }; +}; diff --git a/bin/tests/system/checkconf/good-masterfile-format-raw.conf b/bin/tests/system/checkconf/good-masterfile-format-raw.conf new file mode 100644 index 0000000..b6f3cbf --- /dev/null +++ b/bin/tests/system/checkconf/good-masterfile-format-raw.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { ::1; }; + masterfile-format raw; +}; diff --git a/bin/tests/system/checkconf/good-masterfile-format-text.conf b/bin/tests/system/checkconf/good-masterfile-format-text.conf new file mode 100644 index 0000000..8138058 --- /dev/null +++ b/bin/tests/system/checkconf/good-masterfile-format-text.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { ::1; }; + masterfile-format text; +}; diff --git a/bin/tests/system/checkconf/good-maxcachettl.conf b/bin/tests/system/checkconf/good-maxcachettl.conf new file mode 100644 index 0000000..58f6901 --- /dev/null +++ b/bin/tests/system/checkconf/good-maxcachettl.conf @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + max-cache-ttl 0; +}; +view two { + max-cache-ttl 86400; +}; +view three { + max-cache-ttl 4000000000; +}; +view four { + max-cache-ttl 3600s; +}; +view five { + max-cache-ttl 1h; +}; +view six { + max-cache-ttl 1d; +}; +view seven { + max-cache-ttl 1w; +}; diff --git a/bin/tests/system/checkconf/good-maxncachettl.conf b/bin/tests/system/checkconf/good-maxncachettl.conf new file mode 100644 index 0000000..80dc753 --- /dev/null +++ b/bin/tests/system/checkconf/good-maxncachettl.conf @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + max-ncache-ttl 0; +}; +view two { + max-ncache-ttl 86400; +}; +view three { + max-ncache-ttl 604800; +}; +view four { + max-ncache-ttl 3600s; +}; +view five { + max-ncache-ttl 1h; +}; +view six { + max-ncache-ttl 1d; +}; +view seven { + max-ncache-ttl 1w; +}; diff --git a/bin/tests/system/checkconf/good-maxratio1.conf b/bin/tests/system/checkconf/good-maxratio1.conf new file mode 100644 index 0000000..4161a24 --- /dev/null +++ b/bin/tests/system/checkconf/good-maxratio1.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + masterfile-format raw; + file "example.db"; + max-ixfr-ratio 50%; +}; diff --git a/bin/tests/system/checkconf/good-maxratio2.conf b/bin/tests/system/checkconf/good-maxratio2.conf new file mode 100644 index 0000000..0ef2f3c --- /dev/null +++ b/bin/tests/system/checkconf/good-maxratio2.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + masterfile-format raw; + file "example.db"; + max-ixfr-ratio unlimited; +}; diff --git a/bin/tests/system/checkconf/good-mincachettl.conf b/bin/tests/system/checkconf/good-mincachettl.conf new file mode 100644 index 0000000..b619a73 --- /dev/null +++ b/bin/tests/system/checkconf/good-mincachettl.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + min-cache-ttl 0; +}; +view two { + min-cache-ttl 30; +}; +view three { + min-cache-ttl 60; +}; +view four { + min-cache-ttl 90s; +}; +view five { + min-cache-ttl 1m; +}; diff --git a/bin/tests/system/checkconf/good-minncachettl.conf b/bin/tests/system/checkconf/good-minncachettl.conf new file mode 100644 index 0000000..3e4101b --- /dev/null +++ b/bin/tests/system/checkconf/good-minncachettl.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + min-ncache-ttl 0; +}; +view two { + min-ncache-ttl 30; +}; +view three { + min-ncache-ttl 60; +}; +view four { + min-ncache-ttl 90s; +}; +view five { + min-ncache-ttl 1m; +}; diff --git a/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf new file mode 100644 index 0000000..09bbf94 --- /dev/null +++ b/bin/tests/system/checkconf/good-mirror-inherited-notify-yes.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + notify yes; +}; + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf new file mode 100644 index 0000000..9723b7a --- /dev/null +++ b/bin/tests/system/checkconf/good-mirror-root-zone-without-masters.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type mirror; +}; diff --git a/bin/tests/system/checkconf/good-multiple-remote-servers-synonyms.conf b/bin/tests/system/checkconf/good-multiple-remote-servers-synonyms.conf new file mode 100644 index 0000000..891538c --- /dev/null +++ b/bin/tests/system/checkconf/good-multiple-remote-servers-synonyms.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers "one" { + 1.2.3.4; +}; + +parental-agents "two" { + 1.2.3.5; +}; + +primaries "three" { + 1.2.3.6; +}; + +masters "four" { + 1.2.3.7; +}; diff --git a/bin/tests/system/checkconf/good-multiple-remote-servers.conf b/bin/tests/system/checkconf/good-multiple-remote-servers.conf new file mode 100644 index 0000000..f06c2bb --- /dev/null +++ b/bin/tests/system/checkconf/good-multiple-remote-servers.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +remote-servers a { 1.2.3.4; }; +remote-servers b { 1.2.3.4; }; diff --git a/bin/tests/system/checkconf/good-nested.conf b/bin/tests/system/checkconf/good-nested.conf new file mode 100644 index 0000000..12a027c --- /dev/null +++ b/bin/tests/system/checkconf/good-nested.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl a { 127.0.0.1; ::1; }; +acl b { a; }; +acl c { !b; }; + +options { + allow-query { c; }; +}; diff --git a/bin/tests/system/checkconf/good-nonempty-trust-anchors.conf b/bin/tests/system/checkconf/good-nonempty-trust-anchors.conf new file mode 100644 index 0000000..8f9e048 --- /dev/null +++ b/bin/tests/system/checkconf/good-nonempty-trust-anchors.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trust-anchors { + example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6"; +}; diff --git a/bin/tests/system/checkconf/good-nonempty-trusted-keys.conf b/bin/tests/system/checkconf/good-nonempty-trusted-keys.conf new file mode 100644 index 0000000..43c9b49 --- /dev/null +++ b/bin/tests/system/checkconf/good-nonempty-trusted-keys.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnssec-validation yes; +}; + +trusted-keys { + example. 257 3 8 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl + 25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafG + tURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJY + kYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJ + fpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaS + WG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjI + NQyrszHhWUU="; +}; diff --git a/bin/tests/system/checkconf/good-notify-source-v6.conf b/bin/tests/system/checkconf/good-notify-source-v6.conf new file mode 100644 index 0000000..797f966 --- /dev/null +++ b/bin/tests/system/checkconf/good-notify-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + notify-source-v6 fd92:7065:b8e:ffff::1; +}; diff --git a/bin/tests/system/checkconf/good-notify-source.conf b/bin/tests/system/checkconf/good-notify-source.conf new file mode 100644 index 0000000..6b97314 --- /dev/null +++ b/bin/tests/system/checkconf/good-notify-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + notify-source 10.53.0.1; +}; diff --git a/bin/tests/system/checkconf/good-options-also-notify.conf b/bin/tests/system/checkconf/good-options-also-notify.conf new file mode 100644 index 0000000..e10403d --- /dev/null +++ b/bin/tests/system/checkconf/good-options-also-notify.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + also-notify { missing; }; +}; + +zone "example.net" { + type secondary; + notify no; + primaries { 192.168.1.1; }; +}; diff --git a/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf b/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf new file mode 100644 index 0000000..5e0159d --- /dev/null +++ b/bin/tests/system/checkconf/good-options-query-source-address-v4-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source none; +}; diff --git a/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf b/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf new file mode 100644 index 0000000..4298881 --- /dev/null +++ b/bin/tests/system/checkconf/good-options-query-source-address-v6-none.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source-v6 none; +}; diff --git a/bin/tests/system/checkconf/good-parental-source-v6.conf b/bin/tests/system/checkconf/good-parental-source-v6.conf new file mode 100644 index 0000000..fe998f1 --- /dev/null +++ b/bin/tests/system/checkconf/good-parental-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + parental-source-v6 fd92:7065:b8e:ffff::1; +}; diff --git a/bin/tests/system/checkconf/good-parental-source.conf b/bin/tests/system/checkconf/good-parental-source.conf new file mode 100644 index 0000000..e45856a --- /dev/null +++ b/bin/tests/system/checkconf/good-parental-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + parental-source 10.53.0.1; +}; diff --git a/bin/tests/system/checkconf/good-printtime.conf b/bin/tests/system/checkconf/good-printtime.conf new file mode 100644 index 0000000..06bb7be --- /dev/null +++ b/bin/tests/system/checkconf/good-printtime.conf @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +logging { + channel one { + file "one.out"; + print-time no; + }; + channel two { + file "two.out"; + print-time yes; + }; + channel three { + file "three.out"; + print-time local; + }; + channel four { + file "four.out"; + print-time iso8601; + }; + channel five { + file "five.out"; + print-time iso8601-utc; + }; +}; diff --git a/bin/tests/system/checkconf/good-proxy-doh.conf b/bin/tests/system/checkconf/good-proxy-doh.conf new file mode 100644 index 0000000..69f2bda --- /dev/null +++ b/bin/tests/system/checkconf/good-proxy-doh.conf @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +http local-http-server { + endpoints { "/dns-query"; }; + listener-clients 100; + streams-per-connection 100; +}; + +options { + allow-proxy { any; }; + allow-proxy-on { any; }; + listen-on port 443 proxy encrypted tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 4430 proxy plain tls local-tls http local-http-server { 10.53.0.1; }; + listen-on port 8080 proxy plain tls none http local-http-server { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-proxy.conf b/bin/tests/system/checkconf/good-proxy.conf new file mode 100644 index 0000000..1f085a5 --- /dev/null +++ b/bin/tests/system/checkconf/good-proxy.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.2; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + ciphers "HIGH:!aNULL:!MD5:!RC4"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + allow-proxy { any; }; + allow-proxy-on { any; }; + listen-on proxy plain { 10.53.0.1; }; + listen-on port 853 proxy encrypted tls local-tls { 10.53.0.1; }; + listen-on port 8530 proxy plain tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-response-dot.conf b/bin/tests/system/checkconf/good-response-dot.conf new file mode 100644 index 0000000..f21daeb --- /dev/null +++ b/bin/tests/system/checkconf/good-response-dot.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." policy given; + }; +}; diff --git a/bin/tests/system/checkconf/good-rpz-ede-none.conf b/bin/tests/system/checkconf/good-rpz-ede-none.conf new file mode 100644 index 0000000..c0ffab9 --- /dev/null +++ b/bin/tests/system/checkconf/good-rpz-ede-none.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." ede none; + }; +}; diff --git a/bin/tests/system/checkconf/good-rpz-ede.conf b/bin/tests/system/checkconf/good-rpz-ede.conf new file mode 100644 index 0000000..616f9ee --- /dev/null +++ b/bin/tests/system/checkconf/good-rpz-ede.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." ede filtered; + }; +}; diff --git a/bin/tests/system/checkconf/good-rpz-ttl.conf b/bin/tests/system/checkconf/good-rpz-ttl.conf new file mode 100644 index 0000000..26d41bb --- /dev/null +++ b/bin/tests/system/checkconf/good-rpz-ttl.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." policy given; + } + max-policy-ttl 1h; +}; diff --git a/bin/tests/system/checkconf/good-rpz-update.conf b/bin/tests/system/checkconf/good-rpz-update.conf new file mode 100644 index 0000000..34b3ec5 --- /dev/null +++ b/bin/tests/system/checkconf/good-rpz-update.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com." { + type primary; + file "example.com.zone"; +}; + +options { + response-policy { + zone "example.com." + policy given + min-update-interval 5m; + }; +}; diff --git a/bin/tests/system/checkconf/good-rrset-order-none.conf b/bin/tests/system/checkconf/good-rrset-order-none.conf new file mode 100644 index 0000000..f0818ca --- /dev/null +++ b/bin/tests/system/checkconf/good-rrset-order-none.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + rrset-order { + order none; + }; +}; diff --git a/bin/tests/system/checkconf/good-server-christmas-tree.conf b/bin/tests/system/checkconf/good-server-christmas-tree.conf new file mode 100644 index 0000000..f619913 --- /dev/null +++ b/bin/tests/system/checkconf/good-server-christmas-tree.conf @@ -0,0 +1,63 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key example { + algorithm hmac-sha256; + secret "aaaaaaaaaaaaaaaaaaaaaaaa"; +}; + +server 0.0.0.0 { + bogus no; + edns no; + edns-udp-size 512; + edns-version 0; + keys example; + max-udp-size 512; + notify-source 0.0.0.0; + padding 512; + provide-ixfr no; + query-source 0.0.0.0; + request-expire no; + request-ixfr no; + request-nsid no; + require-cookie no; + send-cookie no; + tcp-keepalive no; + tcp-only no; + transfer-format one-answer; + transfer-source 0.0.0.0; + transfers 1; +}; + +server :: { + bogus no; + edns no; + edns-udp-size 512; + edns-version 0; + keys example; + max-udp-size 512; + notify-source-v6 ::; + padding 512; + provide-ixfr no; + query-source-v6 ::; + request-expire no; + request-ixfr no; + request-nsid no; + require-cookie no; + send-cookie no; + tcp-keepalive no; + tcp-only no; + transfer-format one-answer; + transfer-source-v6 ::; + transfers 1; +}; diff --git a/bin/tests/system/checkconf/good-sig-signing-type.conf b/bin/tests/system/checkconf/good-sig-signing-type.conf new file mode 100644 index 0000000..dda1b73 --- /dev/null +++ b/bin/tests/system/checkconf/good-sig-signing-type.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + file "example.db"; + sig-signing-type 65280; +}; diff --git a/bin/tests/system/checkconf/good-sig0checks-quota-exempt.conf b/bin/tests/system/checkconf/good-sig0checks-quota-exempt.conf new file mode 100644 index 0000000..2968ebe --- /dev/null +++ b/bin/tests/system/checkconf/good-sig0checks-quota-exempt.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl goodacl { + 192.168.0.1; +}; + +options { + sig0checks-quota-exempt { 10.0.0.0/8; 2001:db8::100; goodacl; }; +}; diff --git a/bin/tests/system/checkconf/good-static-ds.conf b/bin/tests/system/checkconf/good-static-ds.conf new file mode 100644 index 0000000..be7412a --- /dev/null +++ b/bin/tests/system/checkconf/good-static-ds.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6"; +}; diff --git a/bin/tests/system/checkconf/good-tls-cipher-suites-multiple-cipher-suites.conf b/bin/tests/system/checkconf/good-tls-cipher-suites-multiple-cipher-suites.conf new file mode 100644 index 0000000..6ef3df6 --- /dev/null +++ b/bin/tests/system/checkconf/good-tls-cipher-suites-multiple-cipher-suites.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.3; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-tls-cipher-suites-one-cipher-suite.conf b/bin/tests/system/checkconf/good-tls-cipher-suites-one-cipher-suite.conf new file mode 100644 index 0000000..da52e66 --- /dev/null +++ b/bin/tests/system/checkconf/good-tls-cipher-suites-one-cipher-suite.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls local-tls { + protocols { TLSv1.3; }; + key-file "key.pem"; + cert-file "cert.pem"; + dhparam-file "dhparam.pem"; + cipher-suites "TLS_CHACHA20_POLY1305_SHA256"; + prefer-server-ciphers yes; + session-tickets no; +}; + +options { + listen-on port 853 tls local-tls { 10.53.0.1; }; +}; diff --git a/bin/tests/system/checkconf/good-transfer-source-v6.conf b/bin/tests/system/checkconf/good-transfer-source-v6.conf new file mode 100644 index 0000000..0527b85 --- /dev/null +++ b/bin/tests/system/checkconf/good-transfer-source-v6.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + transfer-source-v6 fd92:7065:b8e:ffff::1; +}; diff --git a/bin/tests/system/checkconf/good-transfer-source.conf b/bin/tests/system/checkconf/good-transfer-source.conf new file mode 100644 index 0000000..df23d1c --- /dev/null +++ b/bin/tests/system/checkconf/good-transfer-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + transfer-source 10.53.0.1; +}; diff --git a/bin/tests/system/checkconf/good-update-policy1.conf b/bin/tests/system/checkconf/good-update-policy1.conf new file mode 100644 index 0000000..b312590 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy1.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * self * TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy10.conf b/bin/tests/system/checkconf/good-update-policy10.conf new file mode 100644 index 0000000..3605834 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy10.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * krb5-subdomain . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy11.conf b/bin/tests/system/checkconf/good-update-policy11.conf new file mode 100644 index 0000000..92be340 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy11.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * tcp-self . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy12.conf b/bin/tests/system/checkconf/good-update-policy12.conf new file mode 100644 index 0000000..b76e583 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy12.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * 6to4-self . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy13.conf b/bin/tests/system/checkconf/good-update-policy13.conf new file mode 100644 index 0000000..e0030e8 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy13.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * tcp-self . ptr(1); + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy2.conf b/bin/tests/system/checkconf/good-update-policy2.conf new file mode 100644 index 0000000..9af4d8a --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy2.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * self . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy3.conf b/bin/tests/system/checkconf/good-update-policy3.conf new file mode 100644 index 0000000..2d4f8ee --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy3.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfsub . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy4.conf b/bin/tests/system/checkconf/good-update-policy4.conf new file mode 100644 index 0000000..480ec5e --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy4.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfsub * TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy5.conf b/bin/tests/system/checkconf/good-update-policy5.conf new file mode 100644 index 0000000..5619188 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy5.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfwild * TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy6.conf b/bin/tests/system/checkconf/good-update-policy6.conf new file mode 100644 index 0000000..7e9d8c0 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy6.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * selfwild . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy7.conf b/bin/tests/system/checkconf/good-update-policy7.conf new file mode 100644 index 0000000..8b0b821 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy7.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * krb5-self . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy8.conf b/bin/tests/system/checkconf/good-update-policy8.conf new file mode 100644 index 0000000..b00e8c4 --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy8.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * ms-self . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-update-policy9.conf b/bin/tests/system/checkconf/good-update-policy9.conf new file mode 100644 index 0000000..491e07c --- /dev/null +++ b/bin/tests/system/checkconf/good-update-policy9.conf @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant * ms-subdomain . TXT; + }; +}; diff --git a/bin/tests/system/checkconf/good-view-also-notify.conf b/bin/tests/system/checkconf/good-view-also-notify.conf new file mode 100644 index 0000000..54d90ba --- /dev/null +++ b/bin/tests/system/checkconf/good-view-also-notify.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view example { + also-notify { missing; }; + zone "example.net" { + type secondary; + notify no; + primaries { 192.168.1.1; }; + }; +}; diff --git a/bin/tests/system/checkconf/good.conf.j2 b/bin/tests/system/checkconf/good.conf.j2 new file mode 100644 index 0000000..f9d7f77 --- /dev/null +++ b/bin/tests/system/checkconf/good.conf.j2 @@ -0,0 +1,285 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * This is just a random selection of configuration options. + */ + +/* cut here */ +dnssec-policy "test" { + cdnskey yes; + cds-digest-types { + "sha-256"; + }; + dnskey-ttl 3600; + keys { + ksk key-directory lifetime P1Y algorithm 13 tag-range 0 32767; + zsk lifetime P30D algorithm 13; + csk key-store "hsm" lifetime P30D algorithm 8 2048; + }; + max-zone-ttl 86400; + nsec3param ; + parent-ds-ttl 7200; + parent-propagation-delay PT1H; + publish-safety PT3600S; + purge-keys P90D; + retire-safety PT3600S; + signatures-jitter PT12H; + signatures-refresh P3D; + signatures-validity P2W; + signatures-validity-dnskey P14D; + zone-propagation-delay PT5M; +}; +key-store "hsm" { + directory "."; + pkcs11-uri "pkcs11:token=bind9;pin-value=1234"; +}; +options { + avoid-v4-udp-ports { + 100; + }; + avoid-v6-udp-ports { + 100; + }; + blackhole { + 10.0.0.0/8; + }; + directory "."; + dump-file "named_dumpdb"; + heartbeat-interval 30; + hostname none; + interface-interval 30; + listen-on port 90 { + "any"; + }; + listen-on port 100 { + 127.0.0.1/32; + }; + listen-on-v6 port 53 { + "none"; + }; + match-mapped-addresses yes; + memstatistics-file "named.memstats"; + pid-file none; + port 5300; + querylog yes; + recursing-file "named.recursing"; + recursive-clients 3000; + serial-query-rate 100; + server-id none; + update-quota 200; + check-names primary warn; + check-names secondary ignore; + max-cache-size 20000000000000; + max-query-count 100; + max-query-restarts 10; + nta-lifetime 604800; + nta-recheck 604800; + validate-except { + "corp"; + }; + dnssec-policy "test"; + max-ixfr-ratio 90%; + transfer-source 0.0.0.0; + zone-statistics none; +}; +remote-servers "parents" port 5353 source 10.10.10.10 port 5354 source-v6 2001:db8::10 port 5355 { + 10.10.10.11; + 2001:db8::11; +}; +view "first" { + match-clients { + "none"; + }; + zone "example1" { + type primary; + file "xxx"; + update-policy local; + max-ixfr-ratio 20%; + notify-source 10.10.10.10 port 53; + }; + zone "clone" { + type primary; + file "yyy"; + max-ixfr-ratio unlimited; + }; + dnssec-validation auto; + max-query-restarts 15; + zone-statistics terse; +}; +view "second" { + match-clients { + "any"; + }; + zone "example1" { + type primary; + file "zzz"; + update-policy local; + zone-statistics yes; + }; + zone "example2" { + type static-stub; + forward only; + forwarders tls "ephemeral" { + 10.53.0.4 port 8053 tls "ephemeral"; + }; + zone-statistics no; + }; + zone "example3" { + type static-stub; + server-addresses { + 1.2.3.4; + }; + }; + zone "clone" { + in-view "first"; + }; + zone "." { + type redirect; + primaries { + 1.2.3.4; + }; + }; + dnssec-validation auto; + zone-statistics full; +}; +view "third" { + match-clients { + "none"; + }; + zone "clone" { + in-view "first"; + forward only; + forwarders { + 10.0.0.100; + }; + }; + zone "dnssec" { + type primary; + file "file"; + allow-update { + "any"; + }; + dnssec-policy "default"; + }; + zone "p" { + type primary; + file "pfile"; + }; + zone "s" { + type secondary; + file "sfile"; + primaries { + 1.2.3.4; + }; + notify primary-only; + }; +}; +view "fourth" { + zone "dnssec-test" { + type primary; + checkds explicit; + file "dnssec-test.db"; + parental-agents { + 1.2.3.4; + 1.2.3.5; + }; + dnssec-policy "test"; + parental-source 10.10.10.10 port 53; + }; + zone "dnssec-default" { + type primary; + file "dnssec-default.db"; + parental-agents { + "parents"; + }; + dnssec-policy "default"; + }; + zone "dnssec-inherit" { + type primary; + checkds no; + file "dnssec-inherit.db"; + }; + zone "dnssec-none" { + type primary; + file "dnssec-none.db"; + dnssec-policy "none"; + }; + zone "dnssec-view1" { + type primary; + checkds yes; + file "dnssec-view41.db"; + dnssec-policy "test"; + }; + zone "dnssec-view2" { + type primary; + file "dnssec-view42.db"; + }; + zone "dnssec-view3" { + type primary; + file "dnssec-view43.db"; + dnssec-policy "none"; + key-directory "keys"; + }; + zone "dnssec-view4" { + type primary; + file "dnssec-view44.db"; + dnssec-policy "none"; + }; + dnssec-policy "default"; + key-directory "."; +}; +view "fifth" { + zone "dnssec-view1" { + type primary; + file "dnssec-view51.db"; + dnssec-policy "test"; + }; + zone "dnssec-view2" { + type primary; + file "dnssec-view52.db"; + dnssec-policy "test"; + key-directory "keys"; + }; + zone "dnssec-view3" { + type primary; + file "dnssec-view53.db"; + dnssec-policy "default"; + key-directory "keys"; + }; + zone "dnssec-view4" { + type primary; + file "dnssec-view54.db"; + dnssec-policy "none"; + }; + key-directory "."; +}; +view "chaos" chaos { + zone "hostname.bind" chaos { + type primary; + database "_builtin hostname"; + }; +}; +dyndb "name" "library.so" { + this; + \}; + is a { + "test" { \{ of; the; }; + } bracketed; + "text \""; + system; +}; +key "mykey" { + algorithm "@DEFAULT_HMAC@"; + secret "qwertyuiopasdfgh"; +}; diff --git a/bin/tests/system/checkconf/good.zonelist b/bin/tests/system/checkconf/good.zonelist new file mode 100644 index 0000000..a5fbfda --- /dev/null +++ b/bin/tests/system/checkconf/good.zonelist @@ -0,0 +1,24 @@ +example1 IN first primary +clone IN first primary +example1 IN second primary +example2 IN second static-stub +example3 IN second static-stub +clone IN second in-view first +. IN second redirect +clone IN third in-view first +dnssec IN third primary +p IN third primary +s IN third secondary +dnssec-test IN fourth primary +dnssec-default IN fourth primary +dnssec-inherit IN fourth primary +dnssec-none IN fourth primary +dnssec-view1 IN fourth primary +dnssec-view2 IN fourth primary +dnssec-view3 IN fourth primary +dnssec-view4 IN fourth primary +dnssec-view1 IN fifth primary +dnssec-view2 IN fifth primary +dnssec-view3 IN fifth primary +dnssec-view4 IN fifth primary +hostname.bind chaos chaos primary diff --git a/bin/tests/system/checkconf/hint-nofile.conf b/bin/tests/system/checkconf/hint-nofile.conf new file mode 100644 index 0000000..1d1dee2 --- /dev/null +++ b/bin/tests/system/checkconf/hint-nofile.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "nonexistent.db"; +}; diff --git a/bin/tests/system/checkconf/in-view-good.conf b/bin/tests/system/checkconf/in-view-good.conf new file mode 100644 index 0000000..e5e860d --- /dev/null +++ b/bin/tests/system/checkconf/in-view-good.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view internal { + zone shared.example { + type primary; + file "shared.example.db"; + }; +}; + +view external { + zone shared.example { + in-view internal; + }; +}; diff --git a/bin/tests/system/checkconf/inline-bad.conf b/bin/tests/system/checkconf/inline-bad.conf new file mode 100644 index 0000000..3485291 --- /dev/null +++ b/bin/tests/system/checkconf/inline-bad.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl "transferees" {}; +remote-servers "stealthPrimaries" {127.0.0.1;}; +remote-servers "publicSecondaries" {127.0.0.1;}; +zone "example.net" { + type secondary; + key-directory "/var/lib/bind/example.net"; + dnssec-policy default; + inline-signing yes; + primaries { stealthPrimaries; }; + notify explicit; + also-notify { publicSecondaries; }; + allow-transfer { localhost; transferees; }; +}; + diff --git a/bin/tests/system/checkconf/inline-good.conf b/bin/tests/system/checkconf/inline-good.conf new file mode 100644 index 0000000..c290c93 --- /dev/null +++ b/bin/tests/system/checkconf/inline-good.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl "transferees" {}; +remote-servers "stealthPrimaries" {127.0.0.1;}; +remote-servers "publicSecondaries" {127.0.0.1;}; +zone "example.net" { + type secondary; + file "/var/cache/bind/example.net.db"; + key-directory "/var/lib/bind/example.net"; + dnssec-policy default; + inline-signing yes; + primaries { stealthPrimaries; }; + notify explicit; + also-notify { publicSecondaries; }; + allow-transfer { localhost; transferees; }; +}; + diff --git a/bin/tests/system/checkconf/inline-no.conf b/bin/tests/system/checkconf/inline-no.conf new file mode 100644 index 0000000..44635e6 --- /dev/null +++ b/bin/tests/system/checkconf/inline-no.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl "transferees" {}; +remote-servers "stealthPrimaries" {127.0.0.1;}; +remote-servers "publicSecondaries" {127.0.0.1;}; +zone "example.net" { + type secondary; + key-directory "/var/lib/bind/example.net"; + dnssec-policy default; + inline-signing no; + primaries { stealthPrimaries; }; + notify explicit; + also-notify { publicSecondaries; }; + allow-transfer { localhost; transferees; }; +}; + diff --git a/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf b/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf new file mode 100644 index 0000000..6e2f8c7 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "good-kasp.conf"; + +zone "nsec3.net" { + type primary; + file "nsec3.db"; + dnssec-policy "test"; + inline-signing no; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-keylen.conf b/bin/tests/system/checkconf/kasp-bad-keylen.conf new file mode 100644 index 0000000..385de8c --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-keylen.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-keylen" { + keys { + csk lifetime P10Y algorithm rsasha256 511; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "bad-keylen"; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-lifetime.conf b/bin/tests/system/checkconf/kasp-bad-lifetime.conf new file mode 100644 index 0000000..225b386 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-lifetime.conf @@ -0,0 +1,91 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-lifetime-ksk" { + /* + * The KSK lifetime is too short. + * The ZSK lifetime is good enough but should trigger a warning. + */ + keys { + ksk lifetime PT3H algorithm 13; + zsk lifetime P8DT2H1S algorithm 13; + }; + + dnskey-ttl PT1H; + publish-safety PT1H; + retire-safety PT1H; + zone-propagation-delay PT1H; + max-zone-ttl P1D; + signatures-validity P10D; + signatures-refresh P3D; + parent-ds-ttl PT1H; + parent-propagation-delay PT5M; +}; + +dnssec-policy "bad-lifetime-zsk" { + /* + * The ZSK lifetime is too short. + * The KSK lifetime is good enough but should trigger a warning. + */ + keys { + ksk lifetime PT3H1S algorithm 13; + zsk lifetime P8DT2H algorithm 13; + }; + + dnskey-ttl PT1H; + publish-safety PT1H; + retire-safety PT1H; + zone-propagation-delay PT1H; + max-zone-ttl P1D; + signatures-validity P10D; + signatures-refresh P3D; + parent-ds-ttl PT1H; + parent-propagation-delay PT5M; +}; + +dnssec-policy "bad-lifetime-csk" { + /* + * The CSK lifetime is too short. + */ + keys { + csk lifetime PT3H algorithm 13; + }; + + dnskey-ttl PT1H; + publish-safety PT1H; + retire-safety PT1H; + zone-propagation-delay PT1H; + max-zone-ttl P1D; + signatures-validity P10D; + signatures-refresh P3D; + parent-ds-ttl PT1H; + parent-propagation-delay PT5M; +}; + +zone "bad-lifetime-ksk.example.net" { + type primary; + file "bad-lifetime-ksk.example.db"; + dnssec-policy "bad-lifetime-ksk"; +}; + +zone "bad-lifetime-zsk.example.net" { + type primary; + file "bad-lifetime-zsk.example.db"; + dnssec-policy "bad-lifetime-zsk"; +}; + +zone "bad-lifetime-csk.example.net" { + type primary; + file "bad-lifetime-csk.example.db"; + dnssec-policy "bad-lifetime-csk"; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf new file mode 100644 index 0000000..8691b6c --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-nsec3-alg.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-salt" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; + nsec3param ; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "bad-salt"; +}; + diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-iter-fips.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-iter-fips.conf new file mode 100644 index 0000000..da896a2 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-nsec3-iter-fips.conf @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "rsasha256" { + keys { + csk lifetime P10Y algorithm rsasha256 2048; + }; + nsec3param iterations 0; +}; + +dnssec-policy "rsasha256-bad" { + keys { + csk lifetime P10Y algorithm rsasha256 2048; + }; + nsec3param iterations 1; +}; + +dnssec-policy "rsasha512" { + keys { + csk lifetime P10Y algorithm rsasha512 4096; + }; + nsec3param iterations 0; +}; + +dnssec-policy "rsasha512-bad" { + keys { + csk lifetime P10Y algorithm rsasha512 4096; + }; + nsec3param iterations 1; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "default"; + inline-signing yes; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf new file mode 100644 index 0000000..967c29f --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-nsec3-iter.conf @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "rsasha1" { + keys { + csk lifetime P10Y algorithm nsec3rsasha1 1024; + }; + nsec3param iterations 0; +}; + +dnssec-policy "rsasha1-bad" { + keys { + csk lifetime P10Y algorithm nsec3rsasha1 1024; + }; + nsec3param iterations 1; +}; + +dnssec-policy "rsasha256" { + keys { + csk lifetime P10Y algorithm rsasha256 2048; + }; + nsec3param iterations 0; +}; + +dnssec-policy "rsasha256-bad" { + keys { + csk lifetime P10Y algorithm rsasha256 2048; + }; + nsec3param iterations 1; +}; + +dnssec-policy "rsasha512" { + keys { + csk lifetime P10Y algorithm rsasha512 4096; + }; + nsec3param iterations 0; +}; + +dnssec-policy "rsasha512-bad" { + keys { + csk lifetime P10Y algorithm rsasha512 4096; + }; + nsec3param iterations 1; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "default"; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf b/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf new file mode 100644 index 0000000..708e580 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-nsec3-salt.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-salt" { + nsec3param salt "pepper"; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "bad-salt"; +}; + diff --git a/bin/tests/system/checkconf/kasp-bad-offline-ksk.conf b/bin/tests/system/checkconf/kasp-bad-offline-ksk.conf new file mode 100644 index 0000000..4a44d92 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-offline-ksk.conf @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Offline KSK is not possible with CSK + * (even if there are other key roles present). + */ +dnssec-policy "bad-offline-ksk" { + offline-ksk yes; + keys { + ksk lifetime P10Y algorithm rsasha256; + zsk lifetime P10Y algorithm rsasha256; + csk lifetime P10Y algorithm rsasha256; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "bad-offline-ksk"; +}; diff --git a/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf b/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf new file mode 100644 index 0000000..dd907dd --- /dev/null +++ b/bin/tests/system/checkconf/kasp-bad-signatures-refresh.conf @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "bad-sigrefresh" { + keys { + csk lifetime unlimited algorithm 13; + }; + + signatures-validity P10D; + signatures-validity-dnskey P20D; + signatures-refresh P9DT1S; +}; + +dnssec-policy "bad-sigrefresh-dnskey" { + keys { + csk lifetime unlimited algorithm 13; + }; + + signatures-validity P20D; + signatures-validity-dnskey P10D; + signatures-refresh P9DT1S; +}; + +zone "sigrefresh.example.net" { + type primary; + file "sigrefresh.example.db"; + dnssec-policy "bad-sigrefresh"; +}; + +zone "dnskey.example.net" { + type primary; + file "dnskey.example.db"; + dnssec-policy "bad-sigrefresh-dnskey"; +}; diff --git a/bin/tests/system/checkconf/kasp-ignore-keylen.conf b/bin/tests/system/checkconf/kasp-ignore-keylen.conf new file mode 100644 index 0000000..fae3e41 --- /dev/null +++ b/bin/tests/system/checkconf/kasp-ignore-keylen.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "warn-length" { + keys { + // Algorithm 13 has predefined length, warn about length param. + csk lifetime unlimited algorithm ecdsa256 2048; + }; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "warn-length"; +}; + diff --git a/bin/tests/system/checkconf/kasp-warning.conf b/bin/tests/system/checkconf/kasp-warning.conf new file mode 100644 index 0000000..4c05b5a --- /dev/null +++ b/bin/tests/system/checkconf/kasp-warning.conf @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "warn1" { + keys { + // This policy has keys in the same algorithm with the same + // role, this should trigger a warning. + ksk lifetime unlimited algorithm ecdsa256; + zsk lifetime unlimited algorithm ecdsa256; + zsk lifetime unlimited algorithm ecdsa256; + ksk lifetime unlimited algorithm ecdsa256; + }; +}; + +dnssec-policy "warn2" { + keys { + // This policy has keys in the same algorithm with the same + // role, this should trigger a warning. + csk lifetime unlimited algorithm rsasha256; + ksk lifetime unlimited algorithm rsasha256; + zsk lifetime unlimited algorithm rsasha256; + }; +}; + +dnssec-policy "warn3" { + keys { + // This policy has a key with a very short lifetime. + csk lifetime PT2591999S algorithm rsasha256; + }; +}; + +zone "warn1.example.net" { + type primary; + file "warn1.example.db"; + dnssec-policy "warn1"; +}; + +zone "warn2.example.net" { + type primary; + file "warn2.example.db"; + dnssec-policy "warn2"; +}; + +zone "warn3.example.net" { + type primary; + file "warn3.example.db"; + dnssec-policy "warn3"; +}; + diff --git a/bin/tests/system/checkconf/lmdb-mapsize-largest.conf b/bin/tests/system/checkconf/lmdb-mapsize-largest.conf new file mode 100644 index 0000000..a55b835 --- /dev/null +++ b/bin/tests/system/checkconf/lmdb-mapsize-largest.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize 1024G; +}; diff --git a/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf b/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf new file mode 100644 index 0000000..4478706 --- /dev/null +++ b/bin/tests/system/checkconf/lmdb-mapsize-smallest.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + lmdb-mapsize 1M; +}; diff --git a/bin/tests/system/checkconf/max-cache-size-good.conf b/bin/tests/system/checkconf/max-cache-size-good.conf new file mode 100644 index 0000000..bb12775 --- /dev/null +++ b/bin/tests/system/checkconf/max-cache-size-good.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + max-cache-size 60%; +}; diff --git a/bin/tests/system/checkconf/max-ttl.conf b/bin/tests/system/checkconf/max-ttl.conf new file mode 100644 index 0000000..b91a5fd --- /dev/null +++ b/bin/tests/system/checkconf/max-ttl.conf @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + max-zone-ttl 600; +}; + +zone "maxttl1.example" { + type primary; + file "maxttl-bad.db"; +}; + +zone "maxttl2.example" { + type primary; + file "maxttl-bad.db"; + max-zone-ttl 300; +}; + +zone "maxttl3.example" { + type primary; + file "maxttl-bad.db"; + max-zone-ttl 120; +}; diff --git a/bin/tests/system/checkconf/maxttl-bad.conf b/bin/tests/system/checkconf/maxttl-bad.conf new file mode 100644 index 0000000..66bbebd --- /dev/null +++ b/bin/tests/system/checkconf/maxttl-bad.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + max-zone-ttl 8000w; +}; + +zone "maxttl.example" { + type primary; + file "maxttl-bad.db"; +}; + + diff --git a/bin/tests/system/checkconf/maxttl-bad.db b/bin/tests/system/checkconf/maxttl-bad.db new file mode 100644 index 0000000..978f0ec --- /dev/null +++ b/bin/tests/system/checkconf/maxttl-bad.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a 600 A 10.0.0.1 +mail 900 A 10.0.0.2 diff --git a/bin/tests/system/checkconf/maxttl.db b/bin/tests/system/checkconf/maxttl.db new file mode 100644 index 0000000..3ad695e --- /dev/null +++ b/bin/tests/system/checkconf/maxttl.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 ; 10 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/checkconf/notify.conf b/bin/tests/system/checkconf/notify.conf new file mode 100644 index 0000000..2978118 --- /dev/null +++ b/bin/tests/system/checkconf/notify.conf @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view one { + notify primary-only; + + # also-notify inconsistent with primary-only notify option + zone "secondary" { + type secondary; + primaries { 1.2.3.4; }; + also-notify { 5.6.7.8; }; + }; + + # OK + zone "primary" { + type primary; + file "filename"; + also-notify { 5.6.7.8; }; + }; +}; + +view two { + notify no; + + # also-notify inconsistent with notify option at the view level + zone "secondary" { + type secondary; + primaries { 1.2.3.4; }; + also-notify { 5.6.7.8; }; + }; + + # OK + zone "primary" { + type primary; + file "filename"; + notify yes; + also-notify { 5.6.7.8; }; + }; +}; + +view three { + # also-notify inconsistent with notify option at the zone level + zone "secondary" { + type secondary; + primaries { 1.2.3.4; }; + notify no; + also-notify { 5.6.7.8; }; + }; + + # OK + zone "primary" { + type primary; + file "filename"; + also-notify { 5.6.7.8; }; + }; +}; + +view four { + also-notify { 5.6.7.8; }; + + # OK + zone "secondary" { + type secondary; + primaries { 1.2.3.4; }; + notify primary-only; + }; + + # OK + zone "primary" { + type primary; + file "filename"; + notify no; + }; +}; diff --git a/bin/tests/system/checkconf/portrange-good.conf b/bin/tests/system/checkconf/portrange-good.conf new file mode 100644 index 0000000..3b51cb0 --- /dev/null +++ b/bin/tests/system/checkconf/portrange-good.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + avoid-v4-udp-ports { + 1935; + 2605; + 4321; + 6514; + range 8610 8614; + }; +}; + +server 1.2.3.4 { + query-source 10.10.10.10; +}; diff --git a/bin/tests/system/checkconf/range.conf b/bin/tests/system/checkconf/range.conf new file mode 100644 index 0000000..c254f5c --- /dev/null +++ b/bin/tests/system/checkconf/range.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 999999; +}; diff --git a/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf b/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf new file mode 100644 index 0000000..3ff6b0d --- /dev/null +++ b/bin/tests/system/checkconf/servestale.stale-refresh-time.0.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + stale-refresh-time 0; +}; diff --git a/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf b/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf new file mode 100644 index 0000000..9e0669c --- /dev/null +++ b/bin/tests/system/checkconf/servestale.stale-refresh-time.29.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + stale-refresh-time 29; +}; diff --git a/bin/tests/system/checkconf/shared.example.db b/bin/tests/system/checkconf/shared.example.db new file mode 100644 index 0000000..5dcdd1b --- /dev/null +++ b/bin/tests/system/checkconf/shared.example.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh new file mode 100644 index 0000000..fc776b1 --- /dev/null +++ b/bin/tests/system/checkconf/tests.sh @@ -0,0 +1,795 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +mkdir -p keys + +n=$((n + 1)) +echo_i "checking that named-checkconf handles a known good config ($n)" +ret=0 +$CHECKCONF good.conf >checkconf.out$n 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf prints a known good config ($n)" +ret=0 +awk 'BEGIN { ok = 0; } /cut here/ { ok = 1; getline } ok == 1 { print }' good.conf >good.conf.raw +[ -s good.conf.raw ] || ret=1 +$CHECKCONF -p good.conf.raw >checkconf.out$n || ret=1 +grep -v '^good.conf.raw:' good.conf.out 2>&1 || ret=1 +cmp good.conf.raw good.conf.out || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -x removes secrets ($n)" +ret=0 +# ensure there is a secret and that it is not the check string. +grep 'secret "' good.conf.raw >/dev/null || ret=1 +grep 'secret "????????????????"' good.conf.raw >/dev/null 2>&1 && ret=1 +$CHECKCONF -p -x good.conf.raw >checkconf.out$n || ret=1 +grep -v '^good.conf.raw:' good.conf.out 2>&1 || ret=1 +grep 'secret "????????????????"' good.conf.out >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +for bad in bad-*.conf; do + n=$((n + 1)) + echo_i "checking that named-checkconf detects error in $bad ($n)" + ret=0 + { + $CHECKCONF $bad >checkconf.out$n 2>&1 + rc=$? + } || true + if [ $rc -ne 1 ]; then ret=1; fi + grep "^$bad:[0-9]*: " /dev/null || ret=1 + case $bad in + bad-update-policy[123].conf) + pat="identity and name fields are not the same" + grep "$pat" /dev/null || ret=1 + ;; + bad-update-policy[4589].conf | bad-update-policy1[01].conf) + pat="name field not set to placeholder value" + grep "$pat" /dev/null || ret=1 + ;; + bad-update-policy[67].conf | bad-update-policy1[2345789].conf | bad-update-policy20.conf) + pat="missing name field type '.*' found" + grep "$pat" /dev/null || ret=1 + ;; + esac + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for good in good-*.conf; do + n=$((n + 1)) + echo_i "checking that named-checkconf detects no error in $good ($n)" + ret=0 + if ! $FEATURETEST --with-libnghttp2; then + case $good in + good-doh-*.conf) continue ;; + good-dot-*.conf) continue ;; + good-proxy-*doh*.conf) continue ;; + bad-proxy-*doh*.conf) continue ;; + esac + elif ! $FEATURETEST --have-openssl-cipher-suites; then + case $good in + good-tls-cipher-suites-*.conf) continue ;; + esac + fi + { + $CHECKCONF $good >checkconf.out$n 2>&1 + rc=$? + } || true + if [ $rc -ne 0 ]; then + echo_i "failed" + ret=1 + fi + status=$((status + ret)) +done + +for lmdb in lmdb-*.conf; do + n=$((n + 1)) + ret=0 + + if $FEATURETEST --with-lmdb; then + echo_i "checking that named-checkconf detects no error in $lmdb ($n)" + { + $CHECKCONF $lmdb >checkconf.out$n 2>&1 + rc=$? + } || true + if [ $rc -ne 0 ]; then + echo_i "failed" + ret=1 + fi + else + echo_i "checking that named-checkconf detects error in $lmdb ($n)" + { + $CHECKCONF $lmdb >checkconf.out$n 2>&1 + rc=$? + } || true + if [ $rc -eq 0 ]; then + echo_i "failed" + ret=1 + fi + fi + status=$((status + ret)) +done + +n=$((n + 1)) +echo_i "checking that ancient options report a fatal error ($n)" +ret=0 +$CHECKCONF ancient.conf >ancient.out 2>&1 && ret=1 +grep "no longer exists" ancient.out >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z catches missing hint file ($n)" +ret=0 +$CHECKCONF -z hint-nofile.conf >hint-nofile.out 2>&1 && ret=1 +grep "could not configure root hints from 'nonexistent.db': file not found" hint-nofile.out >/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf catches range errors ($n)" +ret=0 +$CHECKCONF range.conf >checkconf.out$n 2>&1 && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf warns of notify inconsistencies ($n)" +ret=0 +$CHECKCONF notify.conf >checkconf.out$n 2>&1 +warnings=$(grep "'notify' is disabled" /dev/null 2>&1; then + test_fixed=true +else + test_fixed=false +fi + +n=$((n + 1)) +echo_i "checking named-checkconf deprecate warnings ($n)" +ret=0 +$CHECKCONF deprecated.conf >checkconf.out$n.1 2>&1 +grep "option 'managed-keys' is deprecated" /dev/null || ret=1 +grep "option 'trusted-keys' is deprecated" /dev/null || ret=1 +grep "option 'max-zone-ttl' is deprecated" /dev/null || ret=1 +grep "option 'use-v4-udp-ports' is deprecated" /dev/null || ret=1 +grep "option 'use-v6-udp-ports' is deprecated" /dev/null || ret=1 +grep "option 'avoid-v4-udp-ports' is deprecated" /dev/null || ret=1 +grep "option 'avoid-v6-udp-ports' is deprecated" /dev/null || ret=1 +grep "option 'dialup' is deprecated" /dev/null || ret=1 +grep "option 'heartbeat-interval' is deprecated" /dev/null || ret=1 +grep "option 'dnssec-must-be-secure' is deprecated" /dev/null || ret=1 +grep "option 'sortlist' is deprecated" /dev/null || ret=1 +grep "token 'port' is deprecated" /dev/null || ret=1 +if $test_fixed; then + grep "rrset-order: order 'fixed' is deprecated" /dev/null || ret=1 +else + grep "rrset-order: order 'fixed' was disabled at compilation time" /dev/null || ret=1 +fi +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +# set -i to ignore deprecate warnings +$CHECKCONF -i deprecated.conf 2>&1 | grep_v "rrset-order: order 'fixed' was disabled at compilation time" >checkconf.out$n.2 +grep '^.+$' /dev/null && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf servestale warnings ($n)" +ret=0 +$CHECKCONF servestale.stale-refresh-time.0.conf >checkconf.out$n.1 2>&1 +grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" /dev/null && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +ret=0 +$CHECKCONF servestale.stale-refresh-time.29.conf >checkconf.out$n.1 2>&1 +grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "range checking fields that do not allow zero ($n)" +ret=0 +for field in max-retry-time min-retry-time max-refresh-time min-refresh-time; do + cat >badzero.conf <checkconf.out$n.1 2>&1 + rc=$? + } || true + [ $rc -eq 1 ] || { + echo_i "options $field failed" + ret=1 + } + cat >badzero.conf <checkconf.out$n.2 2>&1 + rc=$? + } || true + [ $rc -eq 1 ] || { + echo_i "view $field failed" + ret=1 + } + cat >badzero.conf <checkconf.out$n.3 2>&1 + rc=$? + } || true + [ $rc -eq 1 ] || { + echo_i "options + view $field failed" + ret=1 + } + cat >badzero.conf <checkconf.out$n.4 2>&1 + rc=$? + } || true + [ $rc -eq 1 ] || { + echo_i "zone $field failed" + ret=1 + } +done +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking options allowed in inline-signing secondaries ($n)" +ret=0 +$CHECKCONF bad-dnssec.conf >checkconf.out$n.2 2>&1 && ret=1 +l=$(grep "dnssec-loadkeys-interval.*requires inline" checkconf.out$n.1 2>&1 && ret=1 +l=$(grep "missing 'file' entry" checkconf.out$n.2 2>&1 || ret=1 +l=$(grep "missing 'file' entry" checkconf.out$n.3 2>&1 && ret=1 +l=$(grep "missing 'file' entry" checkconf.out$n 2>&1 && ret=1 +grep "'dlz' and 'database'" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking for missing key directory warning ($n)" +ret=0 +rm -rf test.keydir +rm -rf test.keystoredir +$CHECKCONF warn-keydir.conf >checkconf.out$n.1 2>&1 +l=$(grep "'test.keydir' does not exist" checkconf.out$n.2 2>&1 +l=$(grep "'test.keydir' is not a directory" checkconf.out$n.3 2>&1 +l=$(grep "key-directory" check.out 2>&1 && ret=1 +grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out >/dev/null 2>&1 || ret=1 +grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out >/dev/null 2>&1 || ret=1 +grep 'TTL 900 exceeds configured max-zone-ttl 600' check.out >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z catches invalid max-ttl ($n)" +ret=0 +$CHECKCONF -z max-ttl-bad.conf >checkconf.out$n 2>&1 && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z skips zone check with alternate databases ($n)" +ret=0 +$CHECKCONF -z altdb.conf >checkconf.out$n 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z skips zone check with DLZ ($n)" +ret=0 +$CHECKCONF -z altdlz.conf >checkconf.out$n 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z fails on view with ANY class ($n)" +ret=0 +$CHECKCONF -z view-class-any1.conf >checkconf.out$n 2>&1 && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z fails on view with CLASS255 class ($n)" +ret=0 +$CHECKCONF -z view-class-any2.conf >checkconf.out$n 2>&1 && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z passes on view with IN class ($n)" +ret=0 +$CHECKCONF -z view-class-in1.conf >checkconf.out$n 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf -z passes on view with CLASS1 class ($n)" +ret=0 +$CHECKCONF -z view-class-in2.conf >checkconf.out$n 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-names fails as configured ($n)" +ret=0 +$CHECKCONF -z check-names-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "near '_underscore': bad name (check-names)" /dev/null || ret=1 +grep "zone check-names/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-mx fails as configured ($n)" +ret=0 +$CHECKCONF -z check-mx-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "near '10.0.0.1': MX is an address" /dev/null || ret=1 +grep "zone check-mx/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-dup-records fails as configured ($n)" +ret=0 +$CHECKCONF -z check-dup-records-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "has semantically identical records" /dev/null || ret=1 +grep "zone check-dup-records/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-mx fails as configured ($n)" +ret=0 +$CHECKCONF -z check-mx-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "failed: MX is an address" /dev/null || ret=1 +grep "zone check-mx/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-mx-cname fails as configured ($n)" +ret=0 +$CHECKCONF -z check-mx-cname-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "MX.* is a CNAME (illegal)" /dev/null || ret=1 +grep "zone check-mx-cname/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that check-srv-cname fails as configured ($n)" +ret=0 +$CHECKCONF -z check-srv-cname-fail.conf >checkconf.out$n 2>&1 && ret=1 +grep "SRV.* is a CNAME (illegal)" /dev/null || ret=1 +grep "zone check-mx-cname/IN: loaded serial" /dev/null && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that named-checkconf -p properly print a port range ($n)" +ret=0 +$CHECKCONF -p portrange-good.conf >checkconf.out$n 2>&1 || ret=1 +grep "range 8610 8614;" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that named-checkconf -z handles in-view ($n)" +ret=0 +$CHECKCONF -z in-view-good.conf >checkconf.out$n 2>&1 || ret=1 +grep "zone shared.example/IN: loaded serial" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that named-checkconf -z returns error when a later view is okay ($n)" +ret=0 +$CHECKCONF -z check-missing-zone.conf >checkconf.out$n 2>&1 && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that named-checkconf prints max-cache-size correctly ($n)" +ret=0 +$CHECKCONF -p max-cache-size-good.conf >checkconf.out$n 2>&1 || ret=1 +grep "max-cache-size 60%;" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that named-checkconf -l prints out the zone list ($n)" +ret=0 +$CHECKCONF -l good.conf \ + | grep -v "is deprecated" \ + | grep -v "is not implemented" \ + | grep -v "is not recommended" \ + | grep -v "no longer exists" \ + | grep -v "is obsolete" >checkconf.out$n || ret=1 +diff good.zonelist checkconf.out$n >diff.out$n || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the 2010 ICANN ROOT KSK without the 2017 ICANN ROOT KSK generates a warning ($n)" +ret=0 +$CHECKCONF check-root-ksk-2010.conf >checkconf.out$n 2>/dev/null || ret=1 +[ -s checkconf.out$n ] || ret=1 +grep "key without the updated" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the 2010 ICANN ROOT KSK with the 2017 ICANN ROOT KSK does not generate a warning ($n)" +ret=0 +$CHECKCONF check-root-ksk-both.conf >checkconf.out$n 2>/dev/null || ret=1 +[ -s checkconf.out$n ] && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the 2017 ICANN ROOT KSK alone does not generate a warning ($n)" +ret=0 +$CHECKCONF check-root-ksk-2017.conf >checkconf.out$n 2>/dev/null || ret=1 +[ -s checkconf.out$n ] && ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that a static root key generates a warning ($n)" +ret=0 +$CHECKCONF check-root-static-key.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "static entry for the root zone WILL FAIL" checkconf.out$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that a static root DS trust anchor generates a warning ($n)" +ret=0 +$CHECKCONF check-root-static-ds.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "static entry for the root zone WILL FAIL" checkconf.out$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that a trusted-keys entry for root generates a warning ($n)" +ret=0 +$CHECKCONF check-root-trusted-key.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "trusted-keys entry for the root zone WILL FAIL" checkconf.out$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that using trust-anchors and managed-keys generates an error ($n)" +ret=0 +$CHECKCONF check-mixed-keys.conf >checkconf.out$n 2>/dev/null && ret=1 +grep "use of managed-keys is not allowed" checkconf.out$n >/dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp errors ($n)" +ret=0 +$CHECKCONF kasp-and-other-dnssec-options.conf >checkconf.out$n 2>&1 && ret=1 +grep "'inline-signing yes;' must also be configured explicitly for zones using dnssec-policy without a configured 'allow-update' or 'update-policy'" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp nsec3 iterations errors ($n)" +ret=0 +if [ $RSASHA1_SUPPORTED = 0 ]; then + conf=kasp-bad-nsec3-iter-fips.conf + expect=2 +else + conf=kasp-bad-nsec3-iter.conf + expect=3 +fi +$CHECKCONF $conf >checkconf.out$n 2>&1 && ret=1 +grep "dnssec-policy: nsec3 iterations value 1 not allowed, must be zero" /dev/null || ret=1 +lines=$(wc -l <"checkconf.out$n") +if [ $lines -ne $expect ]; then ret=1; fi +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp nsec3 algorithm errors ($n)" +ret=0 +$CHECKCONF kasp-bad-nsec3-alg.conf >checkconf.out$n 2>&1 && ret=1 +if [ $RSASHA1_SUPPORTED = 0 ]; then + grep "dnssec-policy: algorithm rsasha1 not supported" /dev/null || ret=1 +else + grep "dnssec-policy: cannot use nsec3 with algorithm 'RSASHA1'" /dev/null || ret=1 +fi +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp key errors ($n)" +ret=0 +$CHECKCONF kasp-bad-keylen.conf >checkconf.out$n 2>&1 && ret=1 +grep "dnssec-policy: key with algorithm rsasha256 has invalid key length 511" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp offline-ksk with csk errors ($n)" +ret=0 +$CHECKCONF kasp-bad-offline-ksk.conf >checkconf.out$n 2>&1 && ret=1 +grep "dnssec-policy: csk keys are not allowed when offline-ksk is enabled" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp signatures refresh errors ($n)" +ret=0 +$CHECKCONF kasp-bad-signatures-refresh.conf >checkconf.out$n 2>&1 && ret=1 +grep "dnssec-policy: policy 'bad-sigrefresh' signatures-refresh must be at most 90% of the signatures-validity" /dev/null || ret=1 +grep "dnssec-policy: policy 'bad-sigrefresh-dnskey' signatures-refresh must be at most 90% of the signatures-validity-dnskey" /dev/null || ret=1 +lines=$(wc -l <"checkconf.out$n") +if [ $lines -ne 2 ]; then ret=1; fi +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp key lifetime errors ($n)" +ret=0 +$CHECKCONF kasp-bad-lifetime.conf >checkconf.out$n 2>&1 && ret=1 +lines=$(grep "dnssec-policy: key lifetime is shorter than the time it takes to do a rollover" checkconf.out$n 2>&1 || ret=1 +grep "dnssec-policy: key algorithm ecdsa256 has predefined length; ignoring length value 2048" /dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking named-checkconf kasp warns about weird policies ($n)" +ret=0 +$CHECKCONF kasp-warning.conf >checkconf.out$n 2>&1 || ret=1 +grep "dnssec-policy: algorithm 8 has multiple keys with ZSK role" /dev/null || ret=1 +grep "dnssec-policy: algorithm 8 has multiple keys with ZSK role" /dev/null || ret=1 +grep "dnssec-policy: algorithm 13 has multiple keys with KSK role" /dev/null || ret=1 +grep "dnssec-policy: algorithm 13 has multiple keys with ZSK role" /dev/null || ret=1 +grep "dnssec-policy: key lifetime is shorter than 30 days" /dev/null || ret=1 +lines=$(wc -l <"checkconf.out$n") +if [ $lines -ne 5 ]; then ret=1; fi +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that a good 'kasp' configuration is accepted ($n)" +ret=0 +$CHECKCONF good-kasp.conf >checkconf.out$n 2>/dev/null || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-checkconf prints a known good kasp config ($n)" +ret=0 +awk 'BEGIN { ok = 0; } /cut here/ { ok = 1; getline } ok == 1 { print }' good-kasp.conf >good-kasp.conf.in +[ -s good-kasp.conf.in ] || ret=1 +$CHECKCONF -p good-kasp.conf.in | grep -v '^good-kasp.conf.in:' >good-kasp.conf.out 2>&1 || ret=1 +cmp good-kasp.conf.in good-kasp.conf.out || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that max-ixfr-ratio 100% generates a warning ($n)" +ret=0 +$CHECKCONF warn-maxratio1.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "exceeds 100%" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that *-source options with specified port generate warnings ($n)" +ret=0 +$CHECKCONF warn-transfer-source.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "not recommended" /dev/null || ret=1 +$CHECKCONF warn-notify-source.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "not recommended" /dev/null || ret=1 +$CHECKCONF warn-parental-source.conf >checkconf.out$n 2>/dev/null || ret=1 +grep "not recommended" /dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'check-wildcard no;' succeeds as configured ($n)" +ret=0 +$CHECKCONF -z check-wildcard-no.conf >checkconf.out$n 2>&1 || ret=1 +grep -F "warning: ownername 'foo.*.check-wildcard' contains an non-terminal wildcard" checkconf.out$n >/dev/null && ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'check-wildcard yes;' warns as configured ($n)" +ret=0 +$CHECKCONF -z check-wildcard.conf >checkconf.out$n 2>&1 || ret=1 +grep -F "warning: ownername 'foo.*.check-wildcard' contains an non-terminal wildcard" checkconf.out$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/checkconf/tests_sh_checkconf.py b/bin/tests/system/checkconf/tests_sh_checkconf.py new file mode 100644 index 0000000..c94a9fa --- /dev/null +++ b/bin/tests/system/checkconf/tests_sh_checkconf.py @@ -0,0 +1,36 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "*.out", + "bad-kasp-keydir1.conf", + "bad-kasp-keydir2.conf", + "bad-kasp-keydir3.conf", + "bad-kasp-keydir4.conf", + "bad-kasp-keydir5.conf", + "bad-tsig.conf", + "badzero.conf", + "checkconf.out*", + "diff.out*", + "good-kasp.conf.in", + "good-server-christmas-tree.conf", + "good.conf", + "good.conf.raw", + "keys", + ] +) + + +def test_checkconf(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/checkconf/view-class-any1.conf b/bin/tests/system/checkconf/view-class-any1.conf new file mode 100644 index 0000000..8b39456 --- /dev/null +++ b/bin/tests/system/checkconf/view-class-any1.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "example" any { }; diff --git a/bin/tests/system/checkconf/view-class-any2.conf b/bin/tests/system/checkconf/view-class-any2.conf new file mode 100644 index 0000000..049ccf6 --- /dev/null +++ b/bin/tests/system/checkconf/view-class-any2.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "example" class255 { }; diff --git a/bin/tests/system/checkconf/view-class-in1.conf b/bin/tests/system/checkconf/view-class-in1.conf new file mode 100644 index 0000000..1d203e6 --- /dev/null +++ b/bin/tests/system/checkconf/view-class-in1.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "example" in { }; diff --git a/bin/tests/system/checkconf/view-class-in2.conf b/bin/tests/system/checkconf/view-class-in2.conf new file mode 100644 index 0000000..38b356e --- /dev/null +++ b/bin/tests/system/checkconf/view-class-in2.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "example" class1 { }; diff --git a/bin/tests/system/checkconf/warn-keydir.conf b/bin/tests/system/checkconf/warn-keydir.conf new file mode 100644 index 0000000..abcdbc8 --- /dev/null +++ b/bin/tests/system/checkconf/warn-keydir.conf @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * key-directory defined but doesn't exist. + */ +options { + directory "."; +}; + +key-store "test" { + directory "test.keystoredir"; +}; + +zone dummy { + type primary; + file "xxxx"; + key-directory "test.keydir"; +}; diff --git a/bin/tests/system/checkconf/warn-maxratio1.conf b/bin/tests/system/checkconf/warn-maxratio1.conf new file mode 100644 index 0000000..eedf263 --- /dev/null +++ b/bin/tests/system/checkconf/warn-maxratio1.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone example { + type primary; + masterfile-format raw; + file "example.db"; + max-ixfr-ratio 101%; +}; diff --git a/bin/tests/system/checkconf/warn-notify-source.conf b/bin/tests/system/checkconf/warn-notify-source.conf new file mode 100644 index 0000000..f1a46eb --- /dev/null +++ b/bin/tests/system/checkconf/warn-notify-source.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + notify-source 10.53.0.1 port 100; +}; + +server fd92:7065:b8e:ffff::1 { + query-source-v6 fd92:7065:b8e:ffff::2; +}; diff --git a/bin/tests/system/checkconf/warn-parental-source.conf b/bin/tests/system/checkconf/warn-parental-source.conf new file mode 100644 index 0000000..2bbb34b --- /dev/null +++ b/bin/tests/system/checkconf/warn-parental-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + parental-source 10.53.0.1 port 100; +}; diff --git a/bin/tests/system/checkconf/warn-transfer-source.conf b/bin/tests/system/checkconf/warn-transfer-source.conf new file mode 100644 index 0000000..eb31041 --- /dev/null +++ b/bin/tests/system/checkconf/warn-transfer-source.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port 5300; +}; + +zone example { + type secondary; + primaries { 1.2.3.4; }; + transfer-source 10.53.0.1 port 100; +}; diff --git a/bin/tests/system/checkds/README b/bin/tests/system/checkds/README new file mode 100644 index 0000000..ec38140 --- /dev/null +++ b/bin/tests/system/checkds/README @@ -0,0 +1,98 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The test setup for the checkds tests. + +These servers are parent servers: +- ns1 is the root server. + +- ns2 is a primary authoritative server that serves the parent zone for zones + configured in ns9. +- ns4 is the secondary server for ns2. +- ns8 is the secondary server for ns2 that is not part of the NS RRset, + used for testing explicit parental-agents. + +- ns5 is a primary authoritative server that serves the parent zone for zones + configured in ns9, but this one does not publish DS records (to test cases + where the DS is missing and the DS needs to be withdrawn). +- ns7 is the secondary server for ns5. +- ns10 is the secondary server for ns5 that is not part of the NS RRset, + used for testing explicit parental-agents. + +- ns6 is an authoritative server for a different zone, to test badly configured + parental agents. + +- ns3 is a resolver that can be configured as a parental agent. + +- Finally, ns9 is the authoritative server for the various DNSSEC enabled test + domains. + +We need multiple test cases for testing the "checkds" functionality. Basically, +the behavior of "checkds" is of importance in three cases: + +1. Enabling DNSSEC +2. KSK rollover +3. Going insecure + +All these three cases involve publishing DS records into the parent, and +withdrawing them. The named instance is responsible for checking that the +relevant DS records are published or removed from the parent zone. Therefor, +it needs to know what the parental agents are (the servers that it can send +the DS queries to). + +Then there are two ways of retrieving parental agents, either through explicit +configuration ("checkds explicit;"), or through discovery ("checkds yes;"). In +the latter case, the parental agents are retrieved by querying for the parent NS +RRset. + +The third value is "checkds no;", which disables the feature. + +Depending on the DS publication status, the DS state of the key needs to be +updated. In case of DS publication, the "DSPublish" state should be set, only +if all parental agents have the relevant DS published. In case of DS withdrawal, +the "DSRemoved" state should be set, only if none of the parental agents have +the relevant DS in their zone. + +Regardless of how parental agents are retrieved, we identify the following test +cases: + +1. Enabling DNSSEC + +1.1. - With one parental agent +1.1.1. - DS is correctly published in the parent: DSPublish +1.1.2. - DS is not (yet) published in the parent: !DSPublish +1.1.3. - The parental agent is badly configured: !DSPublish +1.1.4. - DS is published, but has bogus signature: !DSPublish + +1.2. - With multiple parental agents +1.2.1. - DS is correctly published in all parents: DSPublish +1.2.2. - DS is not (yet) published in some parents: !DSPublish +1.2.3. - One parental agent is badly configured: !DSPublish +1.2.4. - DS is completely published, bogus signature: !DSPublish + +2. Going insecure + +2.1. - With one parental agent +2.1.1. - DS is correctly withdrawn from the parent: DSRemoved +2.1.2. - DS is (still) published in the parent: !DSRemoved +2.1.3. - The parental agent is badly configured: !DSRemoved +2.1.4. - DS is withdrawn, but has bogus signature: !DSRemoved + +2.2. - With multiple parental agents +2.2.1. - DS is correctly withdrawn from all parents: DSRemoved +2.2.2. - DS is not (yet) withdrawn from some parents: !DSRemoved +2.2.3. - One parental agent is badly configured: !DSRemoved +2.2.4. - DS is removed completely, bogus signature: !DSRemoved + +We deliberately don't test the "KSK Rollover" case in this system test as this +can be considered as the same as "Enabling DNSSEC" for one key and +"Going insecure" for another case. In other words, it is covered by the two +other scenarios (although we might still add the test cases in the future). diff --git a/bin/tests/system/checkds/ns1/named.conf.in b/bin/tests/system/checkds/ns1/named.conf.in new file mode 100644 index 0000000..5b1c9fe --- /dev/null +++ b/bin/tests/system/checkds/ns1/named.conf.in @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; diff --git a/bin/tests/system/checkds/ns1/root.db.in b/bin/tests/system/checkds/ns1/root.db.in new file mode 100644 index 0000000..89e1b93 --- /dev/null +++ b/bin/tests/system/checkds/ns1/root.db.in @@ -0,0 +1,68 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +ns2. NS ns2.ns2. +ns2.ns2. A 10.53.0.2 + +ns2-4. NS ns2.ns2-4. +ns2-4. NS ns4.ns2-4. +ns2.ns2-4. A 10.53.0.2 +ns4.ns2-4. A 10.53.0.4 + +ns2-4-5. NS ns2.ns2-4-5. +ns2-4-5. NS ns4.ns2-4-5. +ns2-4-5. NS ns5.ns2-4-5. +ns2.ns2-4-5. A 10.53.0.2 +ns4.ns2-4-5. A 10.53.0.4 +ns5.ns2-4-5. A 10.53.0.5 + +ns2-4-6. NS ns2.ns2-4-6. +ns2-4-6. NS ns4.ns2-4-6. +ns2-4-6. NS ns6.ns2-4-6. +ns2.ns2-4-6. A 10.53.0.2 +ns4.ns2-4-6. A 10.53.0.4 +ns6.ns2-4-6. A 10.53.0.6 + +ns2-5-7. NS ns2.ns2-5-7. +ns2-5-7. NS ns5.ns2-5-7. +ns2-5-7. NS ns7.ns2-5-7. +ns2.ns2-5-7. A 10.53.0.2 +ns5.ns2-5-7. A 10.53.0.5 +ns7.ns2-5-7. A 10.53.0.7 + +ns5. NS ns5.ns5. +ns5.ns5. A 10.53.0.5 + +ns5-6-7. NS ns5.ns5-6-7. +ns5-6-7. NS ns6.ns5-6-7. +ns5-6-7. NS ns7.ns5-6-7. +ns5.ns5-6-7. A 10.53.0.5 +ns6.ns5-6-7. A 10.53.0.6 +ns7.ns5-6-7. A 10.53.0.7 + +ns5-7. NS ns5.ns5-7. +ns5-7. NS ns7.ns5-7. +ns5.ns5-7. A 10.53.0.5 +ns7.ns5-7. A 10.53.0.7 + +ns6. NS ns6.ns6. +ns6.ns6. A 10.53.0.6 diff --git a/bin/tests/system/checkds/ns1/setup.sh b/bin/tests/system/checkds/ns1/setup.sh new file mode 100644 index 0000000..97ee1c2 --- /dev/null +++ b/bin/tests/system/checkds/ns1/setup.sh @@ -0,0 +1,34 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +zone=. +infile=root.db.in +zonefile=root.db + +echo_i "ns1/setup.sh" + +ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# Configure the resolving server with a static key. +keyfile_to_static_ds "$ksk" >trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns9/trusted.conf diff --git a/bin/tests/system/checkds/ns10/named.conf.in b/bin/tests/system/checkds/ns10/named.conf.in new file mode 100644 index 0000000..ef2ec41 --- /dev/null +++ b/bin/tests/system/checkds/ns10/named.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS10 + +options { + query-source address 10.53.0.10; + notify-source 10.53.0.10; + transfer-source 10.53.0.10; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.10; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "ns2" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns2.db"; +}; + +zone "ns2-4" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns5-7.db"; +}; + +zone "ns6" { + type secondary; + primaries source 10.53.0.10 { 10.53.0.5 port @PORT@; }; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns2/named.conf.in b/bin/tests/system/checkds/ns2/named.conf.in new file mode 100644 index 0000000..8342f94 --- /dev/null +++ b/bin/tests/system/checkds/ns2/named.conf.in @@ -0,0 +1,122 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "ns2" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns2.db"; +}; + +zone "ns2-4" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns5-7.db"; +}; + +zone "ns6" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.2; 10.53.0.4; 10.53.0.8; }; + also-notify { 10.53.0.4; 10.53.0.8; }; + dnssec-policy default; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns2/ns2-4-5.db.in b/bin/tests/system/checkds/ns2/ns2-4-5.db.in new file mode 100644 index 0000000..3a8b694 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns2-4-5.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 + NS ns5 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 +ns5 A 10.53.0.5 + +$ORIGIN explicit.dspublish.ns2-4-5. +incomplete NS ns9.incomplete +ns9.imcomplete A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4-5. +incomplete NS ns9.incomplete +ns9.imcomplete A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns2-4-6.db.in b/bin/tests/system/checkds/ns2/ns2-4-6.db.in new file mode 100644 index 0000000..b29fabc --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns2-4-6.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 + NS ns6 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 +ns6 A 10.53.0.6 + +$ORIGIN explicit.dspublish.ns2-4-6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4-6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns2-4.db.in b/bin/tests/system/checkds/ns2/ns2-4.db.in new file mode 100644 index 0000000..d5761a5 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns2-4.db.in @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 + +$ORIGIN explicit.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns2-5-7.db.in b/bin/tests/system/checkds/ns2/ns2-5-7.db.in new file mode 100644 index 0000000..b1fe39c --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns2-5-7.db.in @@ -0,0 +1,34 @@ + ; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns5 + NS ns7 +ns2 A 10.53.0.2 +ns5 A 10.53.0.5 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns2-5-7. +incomplete NS ns9.incomplete +ns9.incomplete A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns2-5-7. +incomplete NS ns9.incomplete +ns9.incomplete A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns2.db.in b/bin/tests/system/checkds/ns2/ns2.db.in new file mode 100644 index 0000000..5d59a06 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns2.db.in @@ -0,0 +1,49 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 + +no-ent NS ns9.no-ent +ns9.no-ent A 10.53.0.9 + +$ORIGIN explicit.dspublish.ns2. +good NS ns9.good +reference NS ns9.reference +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.reference A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dspublish.ns2. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns2. +still-there NS ns9.still-there +ns9.still-there A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns2. +still-there NS ns9.still-there +ns9.still-there A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns5-6-7.db.in b/bin/tests/system/checkds/ns2/ns5-6-7.db.in new file mode 100644 index 0000000..6be4649 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns5-6-7.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 + NS ns6 + NS ns7 +ns5 A 10.53.0.5 +ns6 A 10.53.0.6 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns5-6-7. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5-6-7. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns5-7.db.in b/bin/tests/system/checkds/ns2/ns5-7.db.in new file mode 100644 index 0000000..14e1985 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns5-7.db.in @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 + NS ns7 +ns5 A 10.53.0.5 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns5.db.in b/bin/tests/system/checkds/ns2/ns5.db.in new file mode 100644 index 0000000..640af0f --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns5.db.in @@ -0,0 +1,49 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 +ns5 A 10.53.0.5 + +no-ent NS ns9.no-ent +ns9.no-ent A 10.53.0.9 + +$ORIGIN explicit.dspublish.ns5. +not-yet NS ns9.not-yet +ns9.not-yet A 10.53.0.9 + +$ORIGIN yes.dspublish.ns5. +not-yet NS ns9.not-yet +ns9.not-yet A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns5. +good NS ns9.good +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5. +good NS ns9.good +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN no.dsremoved.ns5. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/ns6.db.in b/bin/tests/system/checkds/ns2/ns6.db.in new file mode 100644 index 0000000..59e2854 --- /dev/null +++ b/bin/tests/system/checkds/ns2/ns6.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +$ORIGIN explicit.dspublish.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dspublish.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns2/setup.sh b/bin/tests/system/checkds/ns2/setup.sh new file mode 100644 index 0000000..4af8606 --- /dev/null +++ b/bin/tests/system/checkds/ns2/setup.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns2/setup.sh" + +for zn in \ + ns2 ns2-4 ns2-4-5 ns2-4-6 ns2-5-7 \ + ns5 ns5-6-7 ns5-7 ns6; do + zone="${zn}" + infile="${zn}.db.infile" + zonefile="${zn}.db" + + # The signing key is copied from ns5. + CSK=$(cat "${zn}.keyname") + cat "${zn}.db.in" "${CSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" + $SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile >signer.out.$zone 2>&1 + + cp "dsset-${zn}." ../ns1/ +done diff --git a/bin/tests/system/checkds/ns3/named.conf.in b/bin/tests/system/checkds/ns3/named.conf.in new file mode 100644 index 0000000..3d54e11 --- /dev/null +++ b/bin/tests/system/checkds/ns3/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + session-keyfile "session.key"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/checkds/ns4/named.conf.in b/bin/tests/system/checkds/ns4/named.conf.in new file mode 100644 index 0000000..75bd470 --- /dev/null +++ b/bin/tests/system/checkds/ns4/named.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "ns2" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns2.db"; +}; + +zone "ns2-4" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns5-7.db"; +}; + +zone "ns6" { + type secondary; + primaries source 10.53.0.4 { 10.53.0.2 port @PORT@; }; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns5/named.conf.in b/bin/tests/system/checkds/ns5/named.conf.in new file mode 100644 index 0000000..ecc1486 --- /dev/null +++ b/bin/tests/system/checkds/ns5/named.conf.in @@ -0,0 +1,122 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "ns2" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns2.db"; +}; + +zone "ns2-4" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns5-7.db"; +}; + +zone "ns6" { + type primary; + allow-update { any; }; + allow-transfer { 10.53.0.5; 10.53.0.7; 10.53.0.10; }; + also-notify { 10.53.0.7; 10.53.0.10; }; + dnssec-policy default; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns5/ns2-4-5.db.in b/bin/tests/system/checkds/ns5/ns2-4-5.db.in new file mode 100644 index 0000000..3a8b694 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns2-4-5.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 + NS ns5 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 +ns5 A 10.53.0.5 + +$ORIGIN explicit.dspublish.ns2-4-5. +incomplete NS ns9.incomplete +ns9.imcomplete A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4-5. +incomplete NS ns9.incomplete +ns9.imcomplete A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns2-4-6.db.in b/bin/tests/system/checkds/ns5/ns2-4-6.db.in new file mode 100644 index 0000000..b29fabc --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns2-4-6.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 + NS ns6 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 +ns6 A 10.53.0.6 + +$ORIGIN explicit.dspublish.ns2-4-6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4-6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns2-4.db.in b/bin/tests/system/checkds/ns5/ns2-4.db.in new file mode 100644 index 0000000..d5761a5 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns2-4.db.in @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns4 +ns2 A 10.53.0.2 +ns4 A 10.53.0.4 + +$ORIGIN explicit.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dspublish.ns2-4. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns2-5-7.db.in b/bin/tests/system/checkds/ns5/ns2-5-7.db.in new file mode 100644 index 0000000..b1fe39c --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns2-5-7.db.in @@ -0,0 +1,34 @@ + ; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns5 + NS ns7 +ns2 A 10.53.0.2 +ns5 A 10.53.0.5 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns2-5-7. +incomplete NS ns9.incomplete +ns9.incomplete A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns2-5-7. +incomplete NS ns9.incomplete +ns9.incomplete A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns2.db.in b/bin/tests/system/checkds/ns5/ns2.db.in new file mode 100644 index 0000000..5d59a06 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns2.db.in @@ -0,0 +1,49 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 + +no-ent NS ns9.no-ent +ns9.no-ent A 10.53.0.9 + +$ORIGIN explicit.dspublish.ns2. +good NS ns9.good +reference NS ns9.reference +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.reference A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN yes.dspublish.ns2. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dspublish.ns2. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns2. +still-there NS ns9.still-there +ns9.still-there A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns2. +still-there NS ns9.still-there +ns9.still-there A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns5-6-7.db.in b/bin/tests/system/checkds/ns5/ns5-6-7.db.in new file mode 100644 index 0000000..6be4649 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns5-6-7.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 + NS ns6 + NS ns7 +ns5 A 10.53.0.5 +ns6 A 10.53.0.6 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns5-6-7. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5-6-7. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns5-7.db.in b/bin/tests/system/checkds/ns5/ns5-7.db.in new file mode 100644 index 0000000..14e1985 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns5-7.db.in @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 + NS ns7 +ns5 A 10.53.0.5 +ns7 A 10.53.0.7 + +$ORIGIN explicit.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 + +$ORIGIN no.dsremoved.ns5-7. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns5.db.in b/bin/tests/system/checkds/ns5/ns5.db.in new file mode 100644 index 0000000..640af0f --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns5.db.in @@ -0,0 +1,49 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 +ns5 A 10.53.0.5 + +no-ent NS ns9.no-ent +ns9.no-ent A 10.53.0.9 + +$ORIGIN explicit.dspublish.ns5. +not-yet NS ns9.not-yet +ns9.not-yet A 10.53.0.9 + +$ORIGIN yes.dspublish.ns5. +not-yet NS ns9.not-yet +ns9.not-yet A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns5. +good NS ns9.good +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns5. +good NS ns9.good +resolver NS ns9.resolver +ns9.good A 10.53.0.9 +ns9.resolver A 10.53.0.9 + +$ORIGIN no.dsremoved.ns5. +good NS ns9.good +ns9.good A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/ns6.db.in b/bin/tests/system/checkds/ns5/ns6.db.in new file mode 100644 index 0000000..59e2854 --- /dev/null +++ b/bin/tests/system/checkds/ns5/ns6.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +$ORIGIN explicit.dspublish.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN explicit.dsremoved.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dspublish.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 + +$ORIGIN yes.dsremoved.ns6. +bad NS ns9.bad +ns9.bad A 10.53.0.9 diff --git a/bin/tests/system/checkds/ns5/setup.sh b/bin/tests/system/checkds/ns5/setup.sh new file mode 100644 index 0000000..37e50c2 --- /dev/null +++ b/bin/tests/system/checkds/ns5/setup.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns5/setup.sh" + +for zn in \ + ns2 ns2-4 ns2-4-5 ns2-4-6 ns2-5-7 \ + ns5 ns5-6-7 ns5-7 ns6; do + zone="${zn}" + infile="${zn}.db.infile" + zonefile="${zn}.db" + + CSK=$($KEYGEN -k default $zone 2>keygen.out.$zone) + cat "${zn}.db.in" "${CSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" + $SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile >signer.out.$zone 2>&1 + + # Copy key to ns2, the other primary. + echo "${CSK}" >"../ns2/${zn}.keyname" + cp "${CSK}.key" ../ns2/ + cp "${CSK}.private" ../ns2/ +done diff --git a/bin/tests/system/checkds/ns6/named.conf.in b/bin/tests/system/checkds/ns6/named.conf.in new file mode 100644 index 0000000..814caca --- /dev/null +++ b/bin/tests/system/checkds/ns6/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "foo" { + type primary; + file "foo.db"; +}; diff --git a/bin/tests/system/checkds/ns7/named.conf.in b/bin/tests/system/checkds/ns7/named.conf.in new file mode 100644 index 0000000..f3e562b --- /dev/null +++ b/bin/tests/system/checkds/ns7/named.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS7 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "ns2" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns2.db"; +}; + +zone "ns2-4" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns5-7.db"; +}; + +zone "ns6" { + type secondary; + primaries source 10.53.0.7 { 10.53.0.5 port @PORT@; }; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns8/named.conf.in b/bin/tests/system/checkds/ns8/named.conf.in new file mode 100644 index 0000000..69e75ee --- /dev/null +++ b/bin/tests/system/checkds/ns8/named.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS8 + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "ns2" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns2.db"; +}; + +zone "ns2-4" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns2-4.db"; +}; + +zone "ns2-4-5" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns2-4-5.db"; +}; + +zone "ns2-4-6" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns2-4-6.db"; +}; + +zone "ns2-5-7" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns2-5-7.db"; +}; + +zone "ns5" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns5.db"; +}; + +zone "ns5-6-7" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns5-6-7.db"; +}; + +zone "ns5-7" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns5-7.db"; +}; + +zone "ns6" { + type secondary; + primaries source 10.53.0.8 { 10.53.0.2 port @PORT@; }; + file "ns6.db"; +}; diff --git a/bin/tests/system/checkds/ns9/named.conf.in b/bin/tests/system/checkds/ns9/named.conf.in new file mode 100644 index 0000000..34d3a49 --- /dev/null +++ b/bin/tests/system/checkds/ns9/named.conf.in @@ -0,0 +1,395 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS9 + +include "trusted.conf"; + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +remote-servers "ns8" port @PORT@ { + 10.53.0.8; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +/* + * 1. Enabling DNSSEC + * 1.1 - With one parental agent + * 1.1.1. - DS is correctly published in the parent. + */ +zone "good.explicit.dspublish.ns2" { + type primary; + file "good.explicit.dspublish.ns2.db"; + dnssec-policy "default"; + parental-agents { 10.53.0.8 port @PORT@; }; +}; + +/* Same as above, but now with a reference to parental-agents. */ +zone "reference.explicit.dspublish.ns2" { + type primary; + file "reference.explicit.dspublish.ns2.db"; + dnssec-policy "default"; + parental-agents { "ns8"; }; +}; + +/* Same as above, but now with resolver parental agent configured. */ +zone "resolver.explicit.dspublish.ns2" { + type primary; + file "resolver.explicit.dspublish.ns2.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.3 port @PORT@; + }; +}; + +/* Same as above, but now with auto parental agents. */ +zone "good.yes.dspublish.ns2" { + type primary; + file "good.yes.dspublish.ns2.db"; + dnssec-policy "default"; +}; + +/* Same as above, but with checkds disabled. */ +zone "good.no.dspublish.ns2" { + type primary; + file "good.no.dspublish.ns2.db"; + dnssec-policy "default"; + checkds no; +}; + +/* Same as auto parental agents, but now without empty non-terminals. */ +zone "no-ent.ns2" { + type primary; + file "no-ent.ns2.db"; + dnssec-policy "default"; +}; + +/* + * 1. Enabling DNSSEC + * 1.1 - With one parental agent + * 1.1.2. - DS is not (yet) published in the parent. + */ +zone "not-yet.explicit.dspublish.ns5" { + type primary; + file "not-yet.explicit.dspublish.ns5.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.5 port @PORT@; // missing + }; +}; + +zone "not-yet.yes.dspublish.ns5" { + type primary; + file "not-yet.yes.dspublish.ns5.db"; + dnssec-policy "default"; +}; + +/* + * 1. Enabling DNSSEC + * 1.1 - With one parental agent + * 1.1.3. - The parental agent is badly configured. + */ +zone "bad.explicit.dspublish.ns6" { + type primary; + file "bad.explicit.dspublish.ns6.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.6 port @PORT@; // bad + }; +}; + +zone "bad.yes.dspublish.ns6" { + type primary; + file "bad.yes.dspublish.ns6.db"; + dnssec-policy "default"; +}; + +/* + * 1. Enabling DNSSEC + * 1.1 - With one parental agent + * 1.1.4. - DS is published, but has bogus signature + */ +// TODO + +/* + * 1. Enabling DNSSEC + * 1.2 - With multiple parental agent + * 1.2.1. - DS is correctly published in all parents. + */ +zone "good.explicit.dspublish.ns2-4" { + type primary; + file "good.explicit.dspublish.ns2-4.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.8 port @PORT@; + 10.53.0.4 port @PORT@; + }; +}; + +zone "good.yes.dspublish.ns2-4" { + type primary; + file "good.yes.dspublish.ns2-4.db"; + dnssec-policy "default"; +}; + +zone "good.no.dspublish.ns2-4" { + type primary; + file "good.no.dspublish.ns2-4.db"; + dnssec-policy "default"; + checkds no; +}; + +/* + * 1. Enabling DNSSEC + * 1.2 - With multiple parental agent + * 1.2.2. - DS is not (yet) published in some parents. + */ +zone "incomplete.explicit.dspublish.ns2-4-5" { + type primary; + file "incomplete.explicit.dspublish.ns2-4-5.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.8 port @PORT@; + 10.53.0.4 port @PORT@; + 10.53.0.5 port @PORT@; // missing + }; +}; + +zone "incomplete.yes.dspublish.ns2-4-5" { + type primary; + file "incomplete.yes.dspublish.ns2-4-5.db"; + dnssec-policy "default"; +}; + +/* + * 1. Enabling DNSSEC + * 1.2 - With multiple parental agent + * 1.2.3. - DS is not (yet) published in some parents. + */ +zone "bad.explicit.dspublish.ns2-4-6" { + type primary; + file "bad.explicit.dspublish.ns2-4-6.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.8 port @PORT@; + 10.53.0.4 port @PORT@; + 10.53.0.6 port @PORT@; // bad + }; +}; + +zone "bad.yes.dspublish.ns2-4-6" { + type primary; + file "bad.yes.dspublish.ns2-4-6.db"; + dnssec-policy "default"; +}; + +/* + * 1. Enabling DNSSEC + * 1.2 - With multiple parental agent + * 1.2.4. - DS is completely published, bogus signature. + */ +// TODO + +// TODO: Other test cases: +// - check with TSIG +// - check with TLS + +/* + * 2. Going insecure + * 2.1 - With one parental agent + * 2.1.1. - DS is correctly withdrawn from the parent. + */ +zone "good.explicit.dsremoved.ns5" { + type primary; + file "good.explicit.dsremoved.ns5.db"; + dnssec-policy "insecure"; + parental-agents { 10.53.0.10 port @PORT@; }; +}; + +zone "resolver.explicit.dsremoved.ns5" { + type primary; + file "resolver.explicit.dsremoved.ns5.db"; + dnssec-policy "default"; + parental-agents { + 10.53.0.3 port @PORT@; + }; +}; + +zone "good.yes.dsremoved.ns5" { + type primary; + file "good.yes.dsremoved.ns5.db"; + dnssec-policy "insecure"; +}; + +zone "good.no.dsremoved.ns5" { + type primary; + file "good.no.dsremoved.ns5.db"; + dnssec-policy "insecure"; + checkds no; +}; + +zone "no-ent.ns5" { + type primary; + file "no-ent.ns5.db"; + dnssec-policy "default"; +}; + +/* + * 2. Going insecure + * 2.1 - With one parental agent + * 2.1.2. - DS is (still) published in the parent. + */ +zone "still-there.explicit.dsremoved.ns2" { + type primary; + file "still-there.explicit.dsremoved.ns2.db"; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.2 port @PORT@; // still published + }; +}; + +zone "still-there.yes.dsremoved.ns2" { + type primary; + file "still-there.yes.dsremoved.ns2.db"; + dnssec-policy "insecure"; +}; + +/* + * 2. Going insecure + * 2.1 - With one parental agent + * 2.1.3. - The parental agent is badly configured. + */ +zone "bad.explicit.dsremoved.ns6" { + type primary; + file "bad.explicit.dsremoved.ns6.db"; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.6 port @PORT@; // bad + }; +}; + +zone "bad.yes.dsremoved.ns6" { + type primary; + file "bad.yes.dsremoved.ns6.db"; + dnssec-policy "insecure"; +}; + +/* + * 2. Going insecure + * 2.1 - With one parental agent + * 2.1.4. - DS is withdrawn, but has bogus signature. + */ +// TODO + +/* + * 2. Going insecure + * 2.2. - With multiple parental agents + * 2.2.1. - DS is correctly withdrawn from all parents. + */ +zone "good.explicit.dsremoved.ns5-7" { + type primary; + file "good.explicit.dsremoved.ns5-7.db"; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.10 port @PORT@; + 10.53.0.7 port @PORT@; + }; +}; + +zone "good.yes.dsremoved.ns5-7" { + type primary; + file "good.yes.dsremoved.ns5-7.db"; + dnssec-policy "insecure"; +}; + +zone "good.no.dsremoved.ns5-7" { + type primary; + file "good.no.dsremoved.ns5-7.db"; + dnssec-policy "insecure"; + checkds no; +}; + +/* + * 2. Going insecure + * 2.2. - With multiple parental agents + * 2.2.2. - DS is not (yet) withdrawn from some parents. + */ +zone "incomplete.explicit.dsremoved.ns2-5-7" { + type primary; + file "incomplete.explicit.dsremoved.ns2-5-7.db"; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.2 port @PORT@; // still published + 10.53.0.10 port @PORT@; + 10.53.0.7 port @PORT@; + }; +}; + +zone "incomplete.yes.dsremoved.ns2-5-7" { + type primary; + file "incomplete.yes.dsremoved.ns2-5-7.db"; + dnssec-policy "insecure"; +}; + +/* + * 2. Going insecure + * 2.2. - With multiple parental agents + * 2.2.3. - One parental agent is badly configured. + */ +zone "bad.explicit.dsremoved.ns5-6-7" { + type primary; + file "bad.explicit.dsremoved.ns5-6-7.db"; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.10 port @PORT@; + 10.53.0.7 port @PORT@; + 10.53.0.6 port @PORT@; // bad + }; +}; + +zone "bad.yes.dsremoved.ns5-6-7" { + type primary; + file "bad.yes.dsremoved.ns5-6-7.db"; + dnssec-policy "insecure"; +}; + +/* + * 2. Going insecure + * 2.2. - With multiple parental agents + * 2.2.4. - DS is removed completely, bogus signature + */ +// TODO diff --git a/bin/tests/system/checkds/ns9/setup.sh b/bin/tests/system/checkds/ns9/setup.sh new file mode 100644 index 0000000..75d16e3 --- /dev/null +++ b/bin/tests/system/checkds/ns9/setup.sh @@ -0,0 +1,94 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns9/setup.sh" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" + echo "$zone" >>zones +} + +sign_dspublish() { + cp template.db.in "$zonefile" + keytimes="-P $T -P sync $T -A $T" + CSK=$($KEYGEN -k default $keytimes $zone 2>keygen.out.$zone) + $SETTIME -s -g $O -k $O $T -r $O $T -z $O $T -d $R $T "$CSK" >settime.out.$zone 2>&1 + cat "$zonefile" "${CSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + cp "dsset-${zone}." ../ns2/ +} + +sign_dsremoved() { + cp template.db.in "$zonefile" + keytimes="-P $Y -P sync $Y -A $Y" + CSK=$($KEYGEN -k default $keytimes $zone 2>keygen.out.$zone) + $SETTIME -s -g $H -k $O $T -r $O $T -z $O $T -d $U $T "$CSK" >settime.out.$zone 2>&1 + cat "$zonefile" "${CSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + cp "dsset-${zone}." ../ns2/ +} + +# Short environment variable names for key states and times. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" +T="now-30d" +Y="now-1y" + +# DS Publication. +for checkds in explicit yes no; do + for zn in \ + good.${checkds}.dspublish.ns2 \ + reference.${checkds}.dspublish.ns2 \ + resolver.${checkds}.dspublish.ns2 \ + not-yet.${checkds}.dspublish.ns5 \ + bad.${checkds}.dspublish.ns6 \ + good.${checkds}.dspublish.ns2-4 \ + incomplete.${checkds}.dspublish.ns2-4-5 \ + bad.${checkds}.dspublish.ns2-4-6; do + setup "${zn}" + sign_dspublish + done +done + +# DS Withdrawal. +for checkds in explicit yes no; do + for zn in \ + good.${checkds}.dsremoved.ns5 \ + resolver.${checkds}.dsremoved.ns5 \ + still-there.${checkds}.dsremoved.ns2 \ + bad.${checkds}.dsremoved.ns6 \ + good.${checkds}.dsremoved.ns5-7 \ + incomplete.${checkds}.dsremoved.ns2-5-7 \ + bad.${checkds}.dsremoved.ns5-6-7; do + setup "${zn}" + sign_dsremoved + done +done + +setup "no-ent.ns2" +sign_dspublish + +setup "no-ent.ns5" +sign_dsremoved diff --git a/bin/tests/system/checkds/ns9/template.db.in b/bin/tests/system/checkds/ns9/template.db.in new file mode 100644 index 0000000..cf06015 --- /dev/null +++ b/bin/tests/system/checkds/ns9/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns9 +ns9 A 10.53.0.9 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/checkds/setup.sh b/bin/tests/system/checkds/setup.sh new file mode 100644 index 0000000..0fc415e --- /dev/null +++ b/bin/tests/system/checkds/setup.sh @@ -0,0 +1,46 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf +copy_setports ns9/named.conf.in ns9/named.conf +copy_setports ns10/named.conf.in ns10/named.conf + +# Setup zones +( + cd ns9 + $SHELL setup.sh +) +( + cd ns5 + $SHELL setup.sh +) +( + cd ns2 + $SHELL setup.sh +) +( + cd ns1 + $SHELL setup.sh +) diff --git a/bin/tests/system/checkds/tests_checkds.py b/bin/tests/system/checkds/tests_checkds.py new file mode 100755 index 0000000..7fed526 --- /dev/null +++ b/bin/tests/system/checkds/tests_checkds.py @@ -0,0 +1,484 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + + +from typing import NamedTuple, Tuple + +import os +import sys +import time + +import isctest +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import dns.exception +import dns.message +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype + + +pytestmark = [ + pytest.mark.skipif( + sys.version_info < (3, 7), reason="Python >= 3.7 required [GL #3001]" + ), + pytest.mark.extra_artifacts( + [ + "*.out", + "ns*/*.db", + "ns*/*.db.infile", + "ns*/*.db.signed", + "ns*/*.jnl", + "ns*/*.jbk", + "ns*/*.keyname", + "ns*/dsset-*", + "ns*/K*", + "ns*/keygen.out*", + "ns*/settime.out*", + "ns*/signer.out*", + "ns*/trusted.conf", + "ns*/zones", + ] + ), +] + + +def has_signed_apex_nsec(zone, response): + has_nsec = False + has_rrsig = False + + ttl = 300 + nextname = "a." + labelcount = zone.count(".") # zone is specified as FQDN + types = "NS SOA RRSIG NSEC DNSKEY" + match = f"{zone} {ttl} IN NSEC {nextname}{zone} {types}" + sig = f"{zone} {ttl} IN RRSIG NSEC 13 {labelcount} 300" + + for rr in response.answer: + if match in rr.to_text(): + has_nsec = True + if sig in rr.to_text(): + has_rrsig = True + + if not has_nsec: + print("error: missing apex NSEC record in response") + if not has_rrsig: + print("error: missing NSEC signature in response") + + return has_nsec and has_rrsig + + +def do_query(server, qname, qtype, tcp=False): + msg = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) + query_func = isctest.query.tcp if tcp else isctest.query.udp + response = query_func(msg, server.ip, expected_rcode=dns.rcode.NOERROR) + return response + + +def verify_zone(zone, transfer): + verify = os.getenv("VERIFY") + assert verify is not None + + filename = f"{zone}out" + with open(filename, "w", encoding="utf-8") as file: + for rr in transfer.answer: + file.write(rr.to_text()) + file.write("\n") + + # dnssec-verify command with default arguments. + verify_cmd = [verify, "-z", "-o", zone, filename] + + verifier = isctest.run.cmd(verify_cmd) + + if verifier.returncode != 0: + print(f"error: dnssec-verify {zone} failed") + sys.stderr.buffer.write(verifier.stderr) + + return verifier.returncode == 0 + + +def read_statefile(server, zone): + count = 0 + keyid = 0 + state = {} + + response = do_query(server, zone, "DS", tcp=True) + # fetch key id from response. + for rr in response.answer: + if rr.match( + dns.name.from_text(zone), + dns.rdataclass.IN, + dns.rdatatype.DS, + dns.rdatatype.NONE, + ): + if count == 0: + keyid = list(dict(rr.items).items())[0][0].key_tag + count += 1 + + assert ( + count == 1 + ), f"expected a single DS in response for {zone} from {server.ip}, got {count}" + + filename = f"ns9/K{zone}+013+{keyid:05d}.state" + print(f"read state file {filename}") + + try: + with open(filename, "r", encoding="utf-8") as file: + for line in file: + if line.startswith(";"): + continue + key, val = line.strip().split(":", 1) + state[key.strip()] = val.strip() + except FileNotFoundError: + # file may not be written just yet. + return {} + + return state + + +def zone_check(server, zone): + fqdn = f"{zone}." + + # check zone is fully signed. + response = do_query(server, fqdn, "NSEC") + assert has_signed_apex_nsec(fqdn, response) + + # check if zone if DNSSEC valid. + transfer = do_query(server, fqdn, "AXFR", tcp=True) + assert verify_zone(fqdn, transfer) + + +def keystate_check(server, zone, key): + fqdn = f"{zone}." + val = 0 + deny = False + + search = key + if key.startswith("!"): + deny = True + search = key[1:] + + for _ in range(10): + state = read_statefile(server, fqdn) + try: + val = state[search] + except KeyError: + pass + + if not deny and val != 0: + break + if deny and val == 0: + break + + time.sleep(1) + + if deny: + assert val == 0 + else: + assert val != 0 + + +def rekey(zone): + rndc = os.getenv("RNDC") + assert rndc is not None + + port = os.getenv("CONTROLPORT") + assert port is not None + + # rndc loadkeys. + rndc_cmd = [ + rndc, + "-c", + "../_common/rndc.conf", + "-p", + port, + "-s", + "10.53.0.9", + "loadkeys", + zone, + ] + controller = isctest.run.cmd(rndc_cmd) + + if controller.returncode != 0: + print(f"error: rndc loadkeys {zone} failed") + sys.stderr.buffer.write(controller.stderr) + + assert controller.returncode == 0 + + +class CheckDSTest(NamedTuple): + zone: str + logs_to_wait_for: Tuple[str] + expected_parent_state: str + + +parental_agents_tests = [ + # Using a reference to parental-agents. + CheckDSTest( + zone="reference.explicit.dspublish.ns2", + logs_to_wait_for=("DS response from 10.53.0.8",), + expected_parent_state="DSPublish", + ), + # Using a resolver as parental-agent (ns3). + CheckDSTest( + zone="resolver.explicit.dspublish.ns2", + logs_to_wait_for=("DS response from 10.53.0.3",), + expected_parent_state="DSPublish", + ), + # Using a resolver as parental-agent (ns3). + CheckDSTest( + zone="resolver.explicit.dsremoved.ns5", + logs_to_wait_for=("empty DS response from 10.53.0.3",), + expected_parent_state="DSRemoved", + ), +] + +no_ent_tests = [ + CheckDSTest( + zone="no-ent.ns2", + logs_to_wait_for=("DS response from 10.53.0.2",), + expected_parent_state="DSPublish", + ), + CheckDSTest( + zone="no-ent.ns5", + logs_to_wait_for=("DS response from 10.53.0.5",), + expected_parent_state="DSRemoved", + ), +] + + +def dspublished_tests(checkds, addr): + return [ + # + # 1.1.1: DS is correctly published in parent. + # parental-agents: ns2 + # + # The simple case. + CheckDSTest( + zone=f"good.{checkds}.dspublish.ns2", + logs_to_wait_for=(f"DS response from {addr}",), + expected_parent_state="DSPublish", + ), + # + # 1.1.2: DS is not published in parent. + # parental-agents: ns5 + # + CheckDSTest( + zone=f"not-yet.{checkds}.dspublish.ns5", + logs_to_wait_for=("empty DS response from 10.53.0.5",), + expected_parent_state="!DSPublish", + ), + # + # 1.1.3: The parental agent is badly configured. + # parental-agents: ns6 + # + CheckDSTest( + zone=f"bad.{checkds}.dspublish.ns6", + logs_to_wait_for=( + ( + "bad DS response from 10.53.0.6" + if checkds == "explicit" + else "error during parental-agents processing" + ), + ), + expected_parent_state="!DSPublish", + ), + # + # 1.1.4: DS is published, but has bogus signature. + # + # TBD + # + # 1.2.1: DS is correctly published in all parents. + # parental-agents: ns2, ns4 + # + CheckDSTest( + zone=f"good.{checkds}.dspublish.ns2-4", + logs_to_wait_for=(f"DS response from {addr}", "DS response from 10.53.0.4"), + expected_parent_state="DSPublish", + ), + # + # 1.2.2: DS is not published in some parents. + # parental-agents: ns2, ns4, ns5 + # + CheckDSTest( + zone=f"incomplete.{checkds}.dspublish.ns2-4-5", + logs_to_wait_for=( + f"DS response from {addr}", + "DS response from 10.53.0.4", + "empty DS response from 10.53.0.5", + ), + expected_parent_state="!DSPublish", + ), + # + # 1.2.3: One parental agent is badly configured. + # parental-agents: ns2, ns4, ns6 + # + CheckDSTest( + zone=f"bad.{checkds}.dspublish.ns2-4-6", + logs_to_wait_for=( + f"DS response from {addr}", + "DS response from 10.53.0.4", + "bad DS response from 10.53.0.6", + ), + expected_parent_state="!DSPublish", + ), + # + # 1.2.4: DS is completely published, bogus signature. + # + # TBD + # TBD: Check with TSIG + # TBD: Check with TLS + ] + + +def dswithdrawn_tests(checkds, addr): + return [ + # + # 2.1.1: DS correctly withdrawn from the parent. + # parental-agents: ns5 + # + # The simple case. + CheckDSTest( + zone=f"good.{checkds}.dsremoved.ns5", + logs_to_wait_for=(f"empty DS response from {addr}",), + expected_parent_state="DSRemoved", + ), + # + # 2.1.2: DS is published in the parent. + # parental-agents: ns2 + # + CheckDSTest( + zone=f"still-there.{checkds}.dsremoved.ns2", + logs_to_wait_for=("DS response from 10.53.0.2",), + expected_parent_state="!DSRemoved", + ), + # + # 2.1.3: The parental agent is badly configured. + # parental-agents: ns6 + # + CheckDSTest( + zone=f"bad.{checkds}.dsremoved.ns6", + logs_to_wait_for=( + ( + "bad DS response from 10.53.0.6" + if checkds == "explicit" + else "error during parental-agents processing" + ), + ), + expected_parent_state="!DSRemoved", + ), + # + # 2.1.4: DS is withdrawn, but has bogus signature. + # + # TBD + # + # 2.2.1: DS is correctly withdrawn from all parents. + # parental-agents: ns5, ns7 + # + CheckDSTest( + zone=f"good.{checkds}.dsremoved.ns5-7", + logs_to_wait_for=( + f"empty DS response from {addr}", + "empty DS response from 10.53.0.7", + ), + expected_parent_state="DSRemoved", + ), + # + # 2.2.2: DS is not withdrawn from some parents. + # parental-agents: ns2, ns5, ns7 + # + CheckDSTest( + zone=f"incomplete.{checkds}.dsremoved.ns2-5-7", + logs_to_wait_for=( + "DS response from 10.53.0.2", + f"empty DS response from {addr}", + "empty DS response from 10.53.0.7", + ), + expected_parent_state="!DSRemoved", + ), + # + # 2.2.3: One parental agent is badly configured. + # parental-agents: ns5, ns6, ns7 + # + CheckDSTest( + zone=f"bad.{checkds}.dsremoved.ns5-6-7", + logs_to_wait_for=( + f"empty DS response from {addr}", + "empty DS response from 10.53.0.7", + "bad DS response from 10.53.0.6", + ), + expected_parent_state="!DSRemoved", + ), + # + # 2.2.4:: DS is removed completely, bogus signature. + # + # TBD + ] + + +checkds_no_tests = [ + CheckDSTest( + zone="good.no.dspublish.ns2", + logs_to_wait_for=(), + expected_parent_state="!DSPublish", + ), + CheckDSTest( + zone="good.no.dspublish.ns2-4", + logs_to_wait_for=(), + expected_parent_state="!DSPublish", + ), + CheckDSTest( + zone="good.no.dsremoved.ns5", + logs_to_wait_for=(), + expected_parent_state="!DSRemoved", + ), + CheckDSTest( + zone="good.no.dsremoved.ns5-7", + logs_to_wait_for=(), + expected_parent_state="!DSRemoved", + ), +] + + +checkds_tests = ( + parental_agents_tests + + no_ent_tests + + dspublished_tests("explicit", "10.53.0.8") + + dspublished_tests("yes", "10.53.0.2") + + dswithdrawn_tests("explicit", "10.53.0.10") + + dswithdrawn_tests("yes", "10.53.0.5") + + checkds_no_tests +) + + +@pytest.mark.parametrize("params", checkds_tests, ids=lambda t: t.zone) +def test_checkds(servers, params): + # Wait until the provided zone is signed and then verify its DNSSEC data. + zone_check(servers["ns9"], params.zone) + + # Wait up to 10 seconds until all the expected log lines are found in the + # log file for the provided server. Rekey every second if necessary. + time_remaining = 10 + for log_string in params.logs_to_wait_for: + line = f"zone {params.zone}/IN (signed): checkds: {log_string}" + while line not in servers["ns9"].log: + rekey(params.zone) + time_remaining -= 1 + assert time_remaining, f'Timed out waiting for "{log_string}" to be logged' + time.sleep(1) + + # Check whether key states on the parent server provided match + # expectations. + keystate_check(servers["ns2"], params.zone, params.expected_parent_state) diff --git a/bin/tests/system/checknames/ns1/fail.example.db b/bin/tests/system/checknames/ns1/fail.example.db new file mode 100644 index 0000000..c4c06c3 --- /dev/null +++ b/bin/tests/system/checknames/ns1/fail.example.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.fail.example. hostmaster.fail.example. ( + 1 3600 1200 604800 3600 ) + NS ns1.fail.example. +ns1.fail.example. A 10.53.0.1 +xx_xx.fail.example. A 127.0.0.1 diff --git a/bin/tests/system/checknames/ns1/fail.update.db b/bin/tests/system/checknames/ns1/fail.update.db new file mode 100644 index 0000000..a360cfd --- /dev/null +++ b/bin/tests/system/checknames/ns1/fail.update.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.fail.update. hostmaster.fail.update. ( + 1 3600 1200 604800 3600 ) + NS ns1.fail.update. +ns1.fail.update. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns1/ignore.example.db b/bin/tests/system/checknames/ns1/ignore.example.db new file mode 100644 index 0000000..148fa6a --- /dev/null +++ b/bin/tests/system/checknames/ns1/ignore.example.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.ignore.example. hostmaster.ignore.example. ( + 1 3600 1200 604800 3600 ) + NS ns1.ignore.example. +ns1.ignore.example. A 10.53.0.1 +yy_yy.ignore.example. A 10.53.0.1 +mx.ignore.example. MX 10 zz_zz.ignore.example. diff --git a/bin/tests/system/checknames/ns1/ignore.update.db b/bin/tests/system/checknames/ns1/ignore.update.db new file mode 100644 index 0000000..0925cef --- /dev/null +++ b/bin/tests/system/checknames/ns1/ignore.update.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.ignore.update. hostmaster.ignore.update. ( + 1 3600 1200 604800 3600 ) + NS ns1.ignore.update. +ns1.ignore.update. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns1/named.conf.j2 b/bin/tests/system/checknames/ns1/named.conf.j2 new file mode 100644 index 0000000..a6a3a66 --- /dev/null +++ b/bin/tests/system/checknames/ns1/named.conf.j2 @@ -0,0 +1,70 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; + check-integrity no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "ignore.example" { + type primary; + file "ignore.example.db"; + check-names ignore; +}; + +zone "warn.example" { + type primary; + file "warn.example.db"; + check-names warn; +}; + +zone "fail.example" { + type primary; + file "fail.example.db"; + check-names fail; +}; + +zone "ignore.update" { + type primary; + file "ignore.update.db"; + allow-update { any; }; + check-names ignore; +}; + +zone "warn.update" { + type primary; + file "warn.update.db"; + allow-update { any; }; + check-names warn; +}; + +zone "fail.update" { + type primary; + file "fail.update.db"; + allow-update { any; }; + check-names fail; +}; diff --git a/bin/tests/system/checknames/ns1/root.db b/bin/tests/system/checknames/ns1/root.db new file mode 100644 index 0000000..bc026a5 --- /dev/null +++ b/bin/tests/system/checknames/ns1/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1. hostmaster.warn.example. ( + 1 3600 1200 604800 3600 ) + NS ns1. +ns1. A 10.53.0.1 +; +ignore.example. NS ns1.ignore.example. +ns1.ignore.example. A 10.53.0.1 +warn.example. NS ns1.warn.example. +ns1.warn.example. A 10.53.0.1 +fail.example. NS ns1.fail.example. +ns1.fail.example. A 10.53.0.1 +; +ignore.update. NS ns1.ignore.update. +ns1.ignore.update. A 10.53.0.1 +warn.update. NS ns1.warn.update. +ns1.warn.update. A 10.53.0.1 +fail.update. NS ns1.fail.update. +ns1.fail.update. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns1/warn.example.db b/bin/tests/system/checknames/ns1/warn.example.db new file mode 100644 index 0000000..7b636fd --- /dev/null +++ b/bin/tests/system/checknames/ns1/warn.example.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.warn.example. hostmaster.warn.example. ( + 1 3600 1200 604800 3600 ) + NS ns1.warn.example. +ns1.warn.example. A 10.53.0.1 +xx_xx.warn.example. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns1/warn.update.db b/bin/tests/system/checknames/ns1/warn.update.db new file mode 100644 index 0000000..9a9af97 --- /dev/null +++ b/bin/tests/system/checknames/ns1/warn.update.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns1.warn.update. hostmaster.warn.update. ( + 1 3600 1200 604800 3600 ) + NS ns1.warn.update. +ns1.warn.update. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns2/named.conf.j2 b/bin/tests/system/checknames/ns2/named.conf.j2 new file mode 100644 index 0000000..105a88d --- /dev/null +++ b/bin/tests/system/checknames/ns2/named.conf.j2 @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + check-names response warn; + notify yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hints"; +}; diff --git a/bin/tests/system/checknames/ns2/root.hints b/bin/tests/system/checknames/ns2/root.hints new file mode 100644 index 0000000..5e89d74 --- /dev/null +++ b/bin/tests/system/checknames/ns2/root.hints @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. NS ns1. +ns1. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns3/named.conf.j2 b/bin/tests/system/checknames/ns3/named.conf.j2 new file mode 100644 index 0000000..487cecc --- /dev/null +++ b/bin/tests/system/checknames/ns3/named.conf.j2 @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + check-names response fail; + notify yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hints"; +}; diff --git a/bin/tests/system/checknames/ns3/root.hints b/bin/tests/system/checknames/ns3/root.hints new file mode 100644 index 0000000..5e89d74 --- /dev/null +++ b/bin/tests/system/checknames/ns3/root.hints @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. NS ns1. +ns1. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns4/named.conf.j2 b/bin/tests/system/checknames/ns4/named.conf.j2 new file mode 100644 index 0000000..7b121fe --- /dev/null +++ b/bin/tests/system/checknames/ns4/named.conf.j2 @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation yes; + check-names primary ignore; + check-names secondary ignore; + notify yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hints"; +}; + +zone "primary-ignore.update" { + type primary; + file "primary-ignore.update.db"; + allow-update { any; }; +}; + +zone "master-ignore.update" { + type secondary; + primaries { 10.53.0.5; }; + file "secondary-ignore.update.db"; +}; diff --git a/bin/tests/system/checknames/ns4/primary-ignore.update.db b/bin/tests/system/checknames/ns4/primary-ignore.update.db new file mode 100644 index 0000000..b343cb1 --- /dev/null +++ b/bin/tests/system/checknames/ns4/primary-ignore.update.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns4 hostmaster.ignore.update. ( + 1 3600 1200 604800 3600 ) + NS ns4 + NS ns5 +ns4 A 10.53.0.4 +ns5 A 10.53.0.5 diff --git a/bin/tests/system/checknames/ns4/root.hints b/bin/tests/system/checknames/ns4/root.hints new file mode 100644 index 0000000..5e89d74 --- /dev/null +++ b/bin/tests/system/checknames/ns4/root.hints @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. NS ns1. +ns1. A 10.53.0.1 diff --git a/bin/tests/system/checknames/ns5/master-ignore.update.db b/bin/tests/system/checknames/ns5/master-ignore.update.db new file mode 100644 index 0000000..1057248 --- /dev/null +++ b/bin/tests/system/checknames/ns5/master-ignore.update.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA ns5. hostmaster.ignore.update. ( + 1 3600 1200 604800 3600 ) + NS ns4 + NS ns5 +ns4 A 10.53.0.4 +ns5 A 10.53.0.5 diff --git a/bin/tests/system/checknames/ns5/named.conf.j2 b/bin/tests/system/checknames/ns5/named.conf.j2 new file mode 100644 index 0000000..62c870b --- /dev/null +++ b/bin/tests/system/checknames/ns5/named.conf.j2 @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation yes; + check-names master ignore; + check-names slave ignore; + notify yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hints"; +}; + +zone "master-ignore.update" { + type primary; + file "master-ignore.update.db"; + allow-update { any; }; +}; + +zone "primary-ignore.update" { + type secondary; + primaries { 10.53.0.4; }; + file "primary-ignore.update.db"; +}; diff --git a/bin/tests/system/checknames/ns5/root.hints b/bin/tests/system/checknames/ns5/root.hints new file mode 100644 index 0000000..5e89d74 --- /dev/null +++ b/bin/tests/system/checknames/ns5/root.hints @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. NS ns1. +ns1. A 10.53.0.1 diff --git a/bin/tests/system/checknames/tests.sh b/bin/tests/system/checknames/tests.sh new file mode 100644 index 0000000..143727b --- /dev/null +++ b/bin/tests/system/checknames/tests.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=1 + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}" + +wait_for_record() { + $DIG $DIGOPTS "$1" "$2" "$3" >"$4" || return 1 + grep NOERROR "$4" >/dev/null || return 1 + return 0 +} + +# Entry should exist. +echo_i "check for failure from on zone load for 'check-names fail;' ($n)" +ret=0 +$DIG $DIGOPTS fail.example. @10.53.0.1 a >dig.out.ns1.test$n || ret=1 +grep SERVFAIL dig.out.ns1.test$n >/dev/null || ret=1 +grep 'xx_xx.fail.example: bad owner name (check-names)' ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +# Entry should exist. +echo_i "check for warnings from on zone load for 'check-names warn;' ($n)" +ret=0 +grep 'xx_xx.warn.example: bad owner name (check-names)' ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +# Entry should not exist. +echo_i "check for warnings from on zone load for 'check-names ignore;' ($n)" +ret=1 +grep 'yy_yy.ignore.example: bad owner name (check-names)' ns1/named.run || ret=0 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +# Entry should exist +echo_i "check that 'check-names response warn;' works ($n)" +ret=0 +$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.1 a >dig.out.ns1.test$n || ret=1 +$DIG $DIGOPTS +noauth yy_yy.ignore.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +digcomp dig.out.ns1.test$n dig.out.ns2.test$n || ret=1 +grep "check-names warning yy_yy.ignore.example/A/IN" ns2/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +# Entry should exist +echo_i "check that 'check-names response (owner) fails;' works ($n)" +ret=0 +$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.1 a >dig.out.ns1.test$n || ret=1 +$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +grep NOERROR dig.out.ns1.test$n >/dev/null || ret=1 +grep REFUSED dig.out.ns3.test$n >/dev/null || ret=1 +grep "check-names failure yy_yy.ignore.example/A/IN" ns3/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +# Entry should exist +echo_i "check that 'check-names response (rdata) fails;' works ($n)" +ret=0 +$DIG $DIGOPTS mx.ignore.example. @10.53.0.1 MX >dig.out.ns1.test$n || ret=1 +$DIG $DIGOPTS mx.ignore.example. @10.53.0.3 MX >dig.out.ns3.test$n || ret=1 +grep NOERROR dig.out.ns1.test$n >/dev/null || ret=1 +grep SERVFAIL dig.out.ns3.test$n >/dev/null || ret=1 +grep "check-names failure mx.ignore.example/MX/IN" ns3/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names fail;' are rejected ($n)" +ret=0 +not=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || not=0 +check-names off +server 10.53.0.1 ${PORT} +update add xxx_xxx.fail.update. 600 A 10.10.10.1 +send +END +if [ $not != 0 ]; then ret=1; fi +$DIG $DIGOPTS xxx_xxx.fail.update @10.53.0.1 A >dig.out.ns1.test$n || ret=1 +grep "xxx_xxx.fail.update/A: bad owner name (check-names)" ns1/named.run >/dev/null || ret=1 +grep NXDOMAIN dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names warn;' succeed and are logged ($n)" +ret=0 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +check-names off +server 10.53.0.1 ${PORT} +update add xxx_xxx.warn.update. 600 A 10.10.10.1 +send +END +$DIG $DIGOPTS xxx_xxx.warn.update @10.53.0.1 A >dig.out.ns1.test$n || ret=1 +grep "xxx_xxx.warn.update/A: bad owner name (check-names)" ns1/named.run >/dev/null || ret=1 +grep NOERROR dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names ignore;' succeed and are not logged ($n)" +ret=0 +not=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +check-names off +server 10.53.0.1 ${PORT} +update add xxx_xxx.ignore.update. 600 A 10.10.10.1 +send +END +grep "xxx_xxx.ignore.update/A.*(check-names)" ns1/named.run >/dev/null || not=0 +if [ $not != 0 ]; then ret=1; fi +$DIG $DIGOPTS xxx_xxx.ignore.update @10.53.0.1 A >dig.out.ns1.test$n || ret=1 +grep NOERROR dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names primary ignore;' succeed and are not logged ($n)" +ret=0 +not=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +check-names off +server 10.53.0.4 ${PORT} +update add xxx_xxx.primary-ignore.update. 600 A 10.10.10.1 +send +END +grep "xxx_xxx.primary-ignore.update/A.*(check-names)" ns4/named.run >/dev/null || not=0 +if [ $not != 0 ]; then ret=1; fi +$DIG $DIGOPTS xxx_xxx.primary-ignore.update @10.53.0.4 A >dig.out.ns4.test$n || ret=1 +grep NOERROR dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names master ignore;' succeed and are not logged ($n)" +ret=0 +not=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +check-names off +server 10.53.0.5 ${PORT} +update add xxx_xxx.master-ignore.update. 600 A 10.10.10.1 +send +END +grep "xxx_xxx.master-ignore.update/A.*(check-names)" ns5/named.run >/dev/null || not=0 +if [ $not != 0 ]; then ret=1; fi +$DIG $DIGOPTS xxx_xxx.master-ignore.update @10.53.0.5 A >dig.out.ns5.test$n || ret=1 +grep NOERROR dig.out.ns5.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names secondary ignore;' succeed and are not logged ($n)" +ret=0 +# takes a while for the transfer to succeed as ns5 (primary) is started after ns4 (secondary) +# and the zone is still loading when we get to this point. +retry_quiet 35 wait_for_record xxx_xxx.master-ignore.update @10.53.0.4 A dig.out.ns4.test$n || ret=1 +grep "xxx_xxx.master-ignore.update/A.*(check-names)" ns4/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "check that updates to 'check-names master ignore;' succeed and are not logged ($n)" +ret=0 +retry_quiet 35 wait_for_record xxx_xxx.primary-ignore.update @10.53.0.5 A dig.out.ns5.test$n || ret=1 +grep "xxx_xxx.primary-ignore.update/A.*(check-names)" ns5/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/checknames/tests_sh_checknames.py b/bin/tests/system/checknames/tests_sh_checknames.py new file mode 100644 index 0000000..326a347 --- /dev/null +++ b/bin/tests/system/checknames/tests_sh_checknames.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.ns*.test*", + "nsupdate.out.*", + "ns1/*.example.db", + "ns1/*.update.db", + "ns1/*.update.db.jnl", + "ns4/*.update.db", + "ns4/*.update.db.jnl", + "ns5/*.update.db", + "ns5/*.update.db.jnl", + ] +) + + +def test_checknames(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/checkzone/setup.sh b/bin/tests/system/checkzone/setup.sh new file mode 100644 index 0000000..a48aa59 --- /dev/null +++ b/bin/tests/system/checkzone/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +ln -s $CHECKZONE named-compilezone + +./named-compilezone -D -F raw -o good1.db.raw example \ + zones/good1.db >/dev/null 2>&1 + +copy_setports zones/bad-tsig.db.in zones/bad-tsig.db diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh new file mode 100644 index 0000000..bda5e37 --- /dev/null +++ b/bin/tests/system/checkzone/tests.sh @@ -0,0 +1,216 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=1 + +for db in zones/good*.db; do + echo_i "checking $db ($n)" + ret=0 + case $db in + zones/good-gc-msdcs.db | zones/good-spf-exception.db) + $CHECKZONE -k fail -i local example $db >test.out.$n 2>&1 || ret=1 + ;; + zones/good-dns-sd-reverse.db) + $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db >test.out.$n 2>&1 || ret=1 + ;; + *) + $CHECKZONE -i local example $db >test.out.$n 2>&1 || ret=1 + ;; + esac + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for db in zones/bad*.db; do + echo_i "checking $db ($n)" + ret=0 v=0 + case $db in + zones/bad-dns-sd-reverse.db | zones/bad-svcb-servername.db) + $CHECKZONE -k fail -i local 0.0.0.0.in-addr.arpa $db >test.out.$n 2>&1 || v=$? + ;; + bad-cname-and*.db) + $CHECKZONE -i local example $db >test.out.$n 2>&1 || v=$? + grep "CNAME and other data" test.out.$n >/dev/null || ret=1 + ;; + *) + $CHECKZONE -i local example $db >test.out.$n 2>&1 || v=$? + ;; + esac + test $v = 1 || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +echo_i "checking with journal file ($n)" +ret=0 +$CHECKZONE -D -o test.orig.db test zones/test1.db >/dev/null 2>&1 || ret=1 +$CHECKZONE -D -o test.changed.db test zones/test2.db >/dev/null 2>&1 || ret=1 +$MAKEJOURNAL test test.orig.db test.changed.db test.orig.db.jnl 2>&1 || ret=1 +jlines=$($JOURNALPRINT test.orig.db.jnl | wc -l) +[ $jlines = 3 ] || ret=1 +$CHECKZONE -D -j -o test.out1.db test test.orig.db >/dev/null 2>&1 || ret=1 +cmp -s test.changed.db test.out1.db || ret=1 +mv -f test.orig.db.jnl test.journal +$CHECKZONE -D -J test.journal -o test.out2.db test test.orig.db >/dev/null 2>&1 || ret=1 +cmp -s test.changed.db test.out2.db || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking with spf warnings ($n)" +ret=0 +$CHECKZONE example zones/spf.db >test.out1.$n 2>&1 || ret=1 +$CHECKZONE -T ignore example zones/spf.db >test.out2.$n 2>&1 || ret=1 +grep "'x.example' found type SPF" test.out1.$n >/dev/null && ret=1 +grep "'y.example' found type SPF" test.out1.$n >/dev/null || ret=1 +grep "'example' found type SPF" test.out1.$n >/dev/null && ret=1 +grep "'x.example' found type SPF" test.out2.$n >/dev/null && ret=1 +grep "'y.example' found type SPF" test.out2.$n >/dev/null && ret=1 +grep "'example' found type SPF" test.out2.$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking with max ttl (text) ($n)" +ret=0 +$CHECKZONE -i local -l 300 example zones/good1.db >test.out1.$n 2>&1 && ret=1 +$CHECKZONE -i local -l 600 example zones/good1.db >test.out2.$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking with max ttl (raw) ($n)" +ret=0 +$CHECKZONE -f raw -l 300 example good1.db.raw >test.out1.$n 2>&1 && ret=1 +$CHECKZONE -f raw -l 600 example good1.db.raw >test.out2.$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for no 'inherited owner' warning on '\$INCLUDE file' with no new \$ORIGIN ($n)" +ret=0 +$CHECKZONE example zones/nowarn.inherited.owner.db >test.out1.$n 2>&1 || ret=1 +grep "inherited.owner" test.out1.$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for 'inherited owner' warning on '\$ORIGIN + \$INCLUDE file' ($n)" +ret=0 +$CHECKZONE example zones/warn.inherit.origin.db >test.out1.$n 2>&1 || ret=1 +grep "inherited.owner" test.out1.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking for 'inherited owner' warning on '\$INCLUDE file origin' ($n)" +ret=0 +$CHECKZONE example zones/warn.inherited.owner.db >test.out1.$n 2>&1 || ret=1 +grep "inherited.owner" test.out1.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that raw zone with bad class is handled ($n)" +ret=0 +$CHECKZONE -f raw example zones/bad-badclass.raw >test.out.$n 2>&1 && ret=1 +grep "failed: bad class" test.out.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that expirations that loop using serial arithmetic are handled ($n)" +ret=0 +q=-q +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +test $ret -eq 1 || $CHECKZONE $q dyn.example.net zones/crashzone.db || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that nameserver below DNAME is reported even with occulted address record present ($n)" +ret=0 +$CHECKZONE example.com zones/ns-address-below-dname.db >test.out.$n 2>&1 && ret=1 +grep "is below a DNAME" test.out.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that delegating nameserver below DNAME is reported even with occulted address record present ($n)" +ret=0 +$CHECKZONE example.com zones/delegating-ns-address-below-dname.db >test.out.$n 2>&1 || ret=1 +grep "is below a DNAME" test.out.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named-compilezone works when reading input from stdin ($n)" +ret=0 +# Step 1: take raw input from stdin and convert it to text/relative format. +# Last argument "-" is optional, but it says more explicitly that we're reading from stdin. +cat zones/zone1.db | ./named-compilezone -f text -F text -s relative \ + -o zones/zone1_stdin.txt zone1.com - >/dev/null || ret=1 +status=$((status + ret)) + +ret=0 +# Step 2: take raw input from file and convert it to text format. +./named-compilezone -f text -F text -s relative -o zones/zone1_file.txt \ + zone1.com zones/zone1.db >/dev/null || ret=1 +status=$((status + ret)) + +ret=0 +# Step 3: Ensure that output conversion from stdin is the same as the output conversion from a file. +diff zones/zone1_file.txt zones/zone1_stdin.txt >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "checking integer overflow is prevented in \$GENERATE ($n)" +$CHECKZONE -D example.com zones/generate-overflow.db >test.out.$n 2>&1 || ret=1 +lines=$(grep -c CNAME test.out.$n) +echo $lines +[ "$lines" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/checkzone/tests_sh_checkzone.py b/bin/tests/system/checkzone/tests_sh_checkzone.py new file mode 100644 index 0000000..26134aa --- /dev/null +++ b/bin/tests/system/checkzone/tests_sh_checkzone.py @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "good1.db.raw", + "named-compilezone", + "test.*", + "zones/bad-tsig.db", + "zones/zone1_*.txt", + ] +) + + +def test_checkzone(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/checkzone/zones/.gitattributes b/bin/tests/system/checkzone/zones/.gitattributes new file mode 100644 index 0000000..a1b3cec --- /dev/null +++ b/bin/tests/system/checkzone/zones/.gitattributes @@ -0,0 +1 @@ +*.raw -text diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb1.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb1.db new file mode 100644 index 0000000..539db80 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb1.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no alpn specified +_dns SVCB 1 ns dohpath=/{?dns} diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb2.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb2.db new file mode 100644 index 0000000..43cfb6b --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb2.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no dohpath +_dns SVCB 1 ns alpn=http/1.1 diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb3.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb3.db new file mode 100644 index 0000000..8323af5 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb3.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no dohpath +_dns SVCB 1 ns alpn=h2 diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb4.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb4.db new file mode 100644 index 0000000..389f1a3 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb4.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no dohpath +_dns SVCB 1 ns alpn=h3 diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb5.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb5.db new file mode 100644 index 0000000..50265a3 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb5.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no dohpath +_443._dns SVCB 1 ns alpn=h1\\,h2 diff --git a/bin/tests/system/checkzone/zones/bad-_dns-svcb6.db b/bin/tests/system/checkzone/zones/bad-_dns-svcb6.db new file mode 100644 index 0000000..7a563df --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-_dns-svcb6.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; no dohpath +_443._dns SVCB 1 ns alpn=x1\\,h2 diff --git a/bin/tests/system/checkzone/zones/bad-badclass.raw b/bin/tests/system/checkzone/zones/bad-badclass.raw new file mode 100644 index 0000000..d8f1bf7 Binary files /dev/null and b/bin/tests/system/checkzone/zones/bad-badclass.raw differ diff --git a/bin/tests/system/checkzone/zones/bad-caa-rr.db b/bin/tests/system/checkzone/zones/bad-caa-rr.db new file mode 100644 index 0000000..fb7b861 Binary files /dev/null and b/bin/tests/system/checkzone/zones/bad-caa-rr.db differ diff --git a/bin/tests/system/checkzone/zones/bad-cdnskey.db b/bin/tests/system/checkzone/zones/bad-cdnskey.db new file mode 100644 index 0000000..d109423 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cdnskey.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +example. 0 CDNSKEY 257 3 14 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTXXXX WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= diff --git a/bin/tests/system/checkzone/zones/bad-cds.db b/bin/tests/system/checkzone/zones/bad-cds.db new file mode 100644 index 0000000..2ce4a0d --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cds.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +example. 0 CDS 14364 14 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0B diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-a.db b/bin/tests/system/checkzone/zones/bad-cname-and-a.db new file mode 100644 index 0000000..b6406dc --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-a.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad A 192.0.2.1 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-a6.db b/bin/tests/system/checkzone/zones/bad-cname-and-a6.db new file mode 100644 index 0000000..b2f4482 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-a6.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A6 0 ::1 +bad WKS 10.0.0.1 tcp telnet ftp 0 1 2 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-aaaa.db b/bin/tests/system/checkzone/zones/bad-cname-and-aaaa.db new file mode 100644 index 0000000..eeef3cd --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-aaaa.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad AAAA ::1 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-afsdb.db b/bin/tests/system/checkzone/zones/bad-cname-and-afsdb.db new file mode 100644 index 0000000..a1072e5 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-afsdb.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad BAD 65535 . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-apl.db b/bin/tests/system/checkzone/zones/bad-cname-and-apl.db new file mode 100644 index 0000000..4edb617 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-apl.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad APL +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-atma.db b/bin/tests/system/checkzone/zones/bad-cname-and-atma.db new file mode 100644 index 0000000..ba3cb5f --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-atma.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad ATMA +61200000000 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-atmrelay.db b/bin/tests/system/checkzone/zones/bad-cname-and-atmrelay.db new file mode 100644 index 0000000..dc193af --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-atmrelay.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad ATMRELAY 0 0 0 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-avc.db b/bin/tests/system/checkzone/zones/bad-cname-and-avc.db new file mode 100644 index 0000000..6edbfe1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-avc.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad AVC foo:bar +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-caa.db b/bin/tests/system/checkzone/zones/bad-cname-and-caa.db new file mode 100644 index 0000000..19ecd2d --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-caa.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad CAA 128 tbs "Unknown" +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-cdnskey.db b/bin/tests/system/checkzone/zones/bad-cname-and-cdnskey.db new file mode 100644 index 0000000..32cb385 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-cdnskey.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad CDNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY + 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV + sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg + a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-cds.db b/bin/tests/system/checkzone/zones/bad-cname-and-cds.db new file mode 100644 index 0000000..3cfdcf5 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-cds.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEA A3B9 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-cert.db b/bin/tests/system/checkzone/zones/bad-cname-and-cert.db new file mode 100644 index 0000000..e926125 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-cert.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad CERT 65534 65535 254 ( + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I + kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t + VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-csync.db b/bin/tests/system/checkzone/zones/bad-cname-and-csync.db new file mode 100644 index 0000000..4604572 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-csync.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad CSYNC 0 0 A NS AAAA +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-dhcid.db b/bin/tests/system/checkzone/zones/bad-cname-and-dhcid.db new file mode 100644 index 0000000..b454084 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-dhcid.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69l OjxfNuVAA2kjEA= +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-dlv.db b/bin/tests/system/checkzone/zones/bad-cname-and-dlv.db new file mode 100644 index 0000000..fdba5af --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-dlv.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad DLV 30795 1 1 ( + 310D27F4D82C1FC2400704EA9939FE6E1CEA + A3B9 ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-dname.db b/bin/tests/system/checkzone/zones/bad-cname-and-dname.db new file mode 100644 index 0000000..8e041df --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-dname.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad DNAME @ +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-doa.db b/bin/tests/system/checkzone/zones/bad-cname-and-doa.db new file mode 100644 index 0000000..7d764e1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-doa.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8= +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-eid.db b/bin/tests/system/checkzone/zones/bad-cname-and-eid.db new file mode 100644 index 0000000..8ec5ce3 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-eid.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad EID 12 89 AB +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-eui48.db b/bin/tests/system/checkzone/zones/bad-cname-and-eui48.db new file mode 100644 index 0000000..65b2550 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-eui48.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad EUI48 01-23-45-67-89-ab +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-eui64.db b/bin/tests/system/checkzone/zones/bad-cname-and-eui64.db new file mode 100644 index 0000000..de5b82b --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-eui64.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad EUI64 01-23-45-67-89-ab-cd-ef +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-gpos.db b/bin/tests/system/checkzone/zones/bad-cname-and-gpos.db new file mode 100644 index 0000000..9337531 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-gpos.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad GPOS -22.6882 116.8652 250.0 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-hinfo.db b/bin/tests/system/checkzone/zones/bad-cname-and-hinfo.db new file mode 100644 index 0000000..112ebef --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-hinfo.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad HINFO . . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-hip.db b/bin/tests/system/checkzone/zones/bad-cname-and-hip.db new file mode 100644 index 0000000..518cea9 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-hip.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad HIP ( 2 200100107B1A74DF365639CC39F1D578 + AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D + rvs.example.com. ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-https.db b/bin/tests/system/checkzone/zones/bad-cname-and-https.db new file mode 100644 index 0000000..f6be58f --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-https.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad HTTPS 0 example.net. +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-ipseckey.db b/bin/tests/system/checkzone/zones/bad-cname-and-ipseckey.db new file mode 100644 index 0000000..02d670d --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-ipseckey.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-isdn.db b/bin/tests/system/checkzone/zones/bad-cname-and-isdn.db new file mode 100644 index 0000000..c647250 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-isdn.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad ISDN isdn-address +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-kx.db b/bin/tests/system/checkzone/zones/bad-cname-and-kx.db new file mode 100644 index 0000000..58868d5 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-kx.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad KX 10 kcd +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-l32.db b/bin/tests/system/checkzone/zones/bad-cname-and-l32.db new file mode 100644 index 0000000..dbe860a --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-l32.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad L32 10 1.2.3.4 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-l64.db b/bin/tests/system/checkzone/zones/bad-cname-and-l64.db new file mode 100644 index 0000000..79e6909 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-l64.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad L64 10 0014:4fff:ff20:ee64 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-loc.db b/bin/tests/system/checkzone/zones/bad-cname-and-loc.db new file mode 100644 index 0000000..f51194a --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-loc.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad LOC 60 9 N 24 39 E 10 20 2000 20 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-lp.db b/bin/tests/system/checkzone/zones/bad-cname-and-lp.db new file mode 100644 index 0000000..c524005 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-lp.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad LP 10 example.net. +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-md.db b/bin/tests/system/checkzone/zones/bad-cname-and-md.db new file mode 100644 index 0000000..83cdd05 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-md.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad MD madname +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-mg.db b/bin/tests/system/checkzone/zones/bad-cname-and-mg.db new file mode 100644 index 0000000..ef045c0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-mg.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad MG mgmname +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-minfo.db b/bin/tests/system/checkzone/zones/bad-cname-and-minfo.db new file mode 100644 index 0000000..57c8096 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-minfo.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad MINFO . . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-mx.db b/bin/tests/system/checkzone/zones/bad-cname-and-mx.db new file mode 100644 index 0000000..10883ac --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-mx.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad MX 10 . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-naptr.db b/bin/tests/system/checkzone/zones/bad-cname-and-naptr.db new file mode 100644 index 0000000..4f628db --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-naptr.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NAPTR 0 0 "" "" "" . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-nid.db b/bin/tests/system/checkzone/zones/bad-cname-and-nid.db new file mode 100644 index 0000000..c5b8458 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-nid.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NID 10 0014:4fff:ff20:ee64 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-nimloc.db b/bin/tests/system/checkzone/zones/bad-cname-and-nimloc.db new file mode 100644 index 0000000..7374d77 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-nimloc.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NIMLOC 12 89 AB +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-ninfo.db b/bin/tests/system/checkzone/zones/bad-cname-and-ninfo.db new file mode 100644 index 0000000..2f3bedb --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-ninfo.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NINFO "foo" +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-ns-soa.db b/bin/tests/system/checkzone/zones/bad-cname-and-ns-soa.db new file mode 100644 index 0000000..1d35d83 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-ns-soa.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +@ CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-nsap-ptr.db b/bin/tests/system/checkzone/zones/bad-cname-and-nsap-ptr.db new file mode 100644 index 0000000..2877f2a --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-nsap-ptr.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NSAP-PTR . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-nsap.db b/bin/tests/system/checkzone/zones/bad-cname-and-nsap.db new file mode 100644 index 0000000..dc86511 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-nsap.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad NSAP 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-opengpgkey.db b/bin/tests/system/checkzone/zones/bad-cname-and-opengpgkey.db new file mode 100644 index 0000000..a1e07cd --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-opengpgkey.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad OPENGPGKEY ( AQMFD5raczCJHViKtLYhWGz8hMY + 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV + sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg + a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-ptr.db b/bin/tests/system/checkzone/zones/bad-cname-and-ptr.db new file mode 100644 index 0000000..3ed9af1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-ptr.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad PTR . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-px.db b/bin/tests/system/checkzone/zones/bad-cname-and-px.db new file mode 100644 index 0000000..d4f0c8c --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-px.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad PX 65535 . . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-resinfo.db b/bin/tests/system/checkzone/zones/bad-cname-and-resinfo.db new file mode 100644 index 0000000..2451a68 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-resinfo.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad RESINFO qnamemin exterr=15,16,17 infourl=https://resolver.example.com/guide +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-rkey.db b/bin/tests/system/checkzone/zones/bad-cname-and-rkey.db new file mode 100644 index 0000000..fa25071 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-rkey.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad RKEY 0 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY + 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV + sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg + a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-rp.db b/bin/tests/system/checkzone/zones/bad-cname-and-rp.db new file mode 100644 index 0000000..8a727e2 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-rp.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad RP . . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-rt.db b/bin/tests/system/checkzone/zones/bad-cname-and-rt.db new file mode 100644 index 0000000..b9ae1c7 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-rt.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad RT 65535 . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-sink.db b/bin/tests/system/checkzone/zones/bad-cname-and-sink.db new file mode 100644 index 0000000..3f923be --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-sink.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SINK 8 0 2 l4ik +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-smimea.db b/bin/tests/system/checkzone/zones/bad-cname-and-smimea.db new file mode 100644 index 0000000..13bf1f1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-smimea.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SMIMES ( 1 1 2 92003ba34942dc74152e2f2c408d29ec + a5a520e7f2e06bb944f4dca346baf63c + 1b177615d466f6c4b71c216a50292bd5 + 8c9ebdd2f74e38fe51ffd48c43326cbc ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-spf.db b/bin/tests/system/checkzone/zones/bad-cname-and-spf.db new file mode 100644 index 0000000..faf92a3 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-spf.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SPF "v=spf1 -all" +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-srv.db b/bin/tests/system/checkzone/zones/bad-cname-and-srv.db new file mode 100644 index 0000000..f9c782b --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-srv.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SRV 0 0 0 . +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-sshfp.db b/bin/tests/system/checkzone/zones/bad-cname-and-sshfp.db new file mode 100644 index 0000000..a6715a6 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-sshfp.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-svcb.db b/bin/tests/system/checkzone/zones/bad-cname-and-svcb.db new file mode 100644 index 0000000..6ce3f54 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-svcb.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad SVCB 0 example.net. +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-ta.db b/bin/tests/system/checkzone/zones/bad-cname-and-ta.db new file mode 100644 index 0000000..3b97bd0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-ta.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TA 30795 1 1 ( + 310D27F4D82C1FC2400704EA9939FE6E1CEA + A3B9 ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-talink.db b/bin/tests/system/checkzone/zones/bad-cname-and-talink.db new file mode 100644 index 0000000..93891bc --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-talink.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TALINK . talink1 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-tlsa.db b/bin/tests/system/checkzone/zones/bad-cname-and-tlsa.db new file mode 100644 index 0000000..2fd8af4 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-tlsa.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TLSA ( 1 1 2 92003ba34942dc74152e2f2c408d29ec + a5a520e7f2e06bb944f4dca346baf63c + 1b177615d466f6c4b71c216a50292bd5 + 8c9ebdd2f74e38fe51ffd48c43326cbc ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-txt.db b/bin/tests/system/checkzone/zones/bad-cname-and-txt.db new file mode 100644 index 0000000..355838b --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-txt.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TXT 10.0.0.1 tcp telnet ftp 0 1 2 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-type54.db b/bin/tests/system/checkzone/zones/bad-cname-and-type54.db new file mode 100644 index 0000000..896de18 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-type54.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TYPE54 \# 0 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-type66.db b/bin/tests/system/checkzone/zones/bad-cname-and-type66.db new file mode 100644 index 0000000..85a095d --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-type66.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad TYPE66 \# 1 00 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-uri.db b/bin/tests/system/checkzone/zones/bad-cname-and-uri.db new file mode 100644 index 0000000..0b45952 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-uri.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad URI 10 20 "https://www.isc.org/" +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-wallet.db b/bin/tests/system/checkzone/zones/bad-cname-and-wallet.db new file mode 100644 index 0000000..5253a5f --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-wallet.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad WALLET currency-identifer wallet-identifier +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-wks.db b/bin/tests/system/checkzone/zones/bad-cname-and-wks.db new file mode 100644 index 0000000..d30f709 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-wks.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad WKS 10.0.0.1 tcp telnet ftp 0 1 2 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-x25.db b/bin/tests/system/checkzone/zones/bad-cname-and-x25.db new file mode 100644 index 0000000..b7ea5a8 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-x25.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad X25 123456789 +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-cname-and-zonemd.db b/bin/tests/system/checkzone/zones/bad-cname-and-zonemd.db new file mode 100644 index 0000000..a293ba0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-cname-and-zonemd.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +bad ZONEMD 2019020700 1 1 ( + C220B8A6ED5728A971902F7E3D4FD93A + DEEA88B0453C2E8E8C863D465AB06CF3 + 4EB95B266398C98B59124FA239CB7EEB + ) +bad CNAME @ diff --git a/bin/tests/system/checkzone/zones/bad-dhcid.db b/bin/tests/system/checkzone/zones/bad-dhcid.db new file mode 100644 index 0000000..df36eb7 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-dhcid.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 DHCID +@ 3600 DHCID diff --git a/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db b/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db new file mode 100644 index 0000000..c766c8f --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-dns-sd-reverse.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA . . 0 0 0 0 0 +@ IN NS . +; +; The following are *not* Service Discovery Prefixes from RFC 6763 and the +; PTR check-names rules for IN-ADDR.ARPA and IP6.ARPA do still apply. +; +b._fail._udp IN PTR !@#3. +db._wrong._udp IN PTR !@#3. +lb._dns-sd._tcp IN PTR !@#3. diff --git a/bin/tests/system/checkzone/zones/bad-ds-2.db b/bin/tests/system/checkzone/zones/bad-ds-2.db new file mode 100644 index 0000000..09d29f7 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-ds-2.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +foo.example. 0 DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C diff --git a/bin/tests/system/checkzone/zones/bad-ds.db b/bin/tests/system/checkzone/zones/bad-ds.db new file mode 100644 index 0000000..9363cb0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-ds.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +example. 0 DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C diff --git a/bin/tests/system/checkzone/zones/bad-eid.db b/bin/tests/system/checkzone/zones/bad-eid.db new file mode 100644 index 0000000..ba568ef --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-eid.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ EID +@ EID diff --git a/bin/tests/system/checkzone/zones/bad-generate-garbage.db b/bin/tests/system/checkzone/zones/bad-generate-garbage.db new file mode 100644 index 0000000..0d66e75 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-generate-garbage.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +$GENERATE 0-7 host$ A 1.2.3.${1,0,dgarbagegarbage} diff --git a/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db new file mode 100644 index 0000000..314583e --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-generate-missing-brace.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +$GENERATE 0-7 host$ A 1.2.3.${1000 diff --git a/bin/tests/system/checkzone/zones/bad-generate-range.db b/bin/tests/system/checkzone/zones/bad-generate-range.db new file mode 100644 index 0000000..62a9e15 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-generate-range.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; 2147483647 + 1 overflows what can be represented in an 'int' +$GENERATE 1-1 host$ TXT foo${2147483647} diff --git a/bin/tests/system/checkzone/zones/bad-generate-tkey.db b/bin/tests/system/checkzone/zones/bad-generate-tkey.db new file mode 100644 index 0000000..8c05e51 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-generate-tkey.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +$GENERATE 0-7 tkey$ TKEY "invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw==" diff --git a/bin/tests/system/checkzone/zones/bad-include-directory.db b/bin/tests/system/checkzone/zones/bad-include-directory.db new file mode 100644 index 0000000..3ccf700 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-include-directory.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$INCLUDE . +$INCLUDE .. diff --git a/bin/tests/system/checkzone/zones/bad-nimloc.db b/bin/tests/system/checkzone/zones/bad-nimloc.db new file mode 100644 index 0000000..56d04c6 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nimloc.db @@ -0,0 +1,10 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. \ No newline at end of file diff --git a/bin/tests/system/checkzone/zones/bad-nsap-empty.db b/bin/tests/system/checkzone/zones/bad-nsap-empty.db new file mode 100644 index 0000000..fb8fdd0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nsap-empty.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; NSAP with an odd number of hex digits +example NSAP 0x47000580005a0000000001e133ffffff000161000 diff --git a/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db b/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db new file mode 100644 index 0000000..d287648 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nsap-odd-nibble.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; empty NSAP address +example NSAP 0x diff --git a/bin/tests/system/checkzone/zones/bad-nsec3-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db new file mode 100644 index 0000000..8212bc4 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nsec3-padded.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; The following NSEC3 RR is invalid as the Next Hashed Owner Name field +; is padded. See RFC 5155. +0p9mhaveqvm6t7vbl5lop2u3t2rp3tom NSEC3 1 1 12 aabbccdd ( + CPNMU=== MX DNSKEY NS + SOA NSEC3PARAM RRSIG ) diff --git a/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db new file mode 100644 index 0000000..bf3c5ab --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-nsec3owner-padded.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; The following NSEC3 RR owner is invalid as the owner name is padded. +CPNMU=== NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS + SOA NSEC3PARAM RRSIG ) diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn1.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn1.db new file mode 100644 index 0000000..dcbe0d1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn1.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn (at start) due to missing double escape +svcb SVCB 1 . alpn=\,abc diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn2.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn2.db new file mode 100644 index 0000000..14c0cba --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn2.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn (in midddle) due to missing double escape +svcb SVCB 1 . alpn=a\,\,abc diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn3.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn3.db new file mode 100644 index 0000000..a479c2e --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn3.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn (at end) due to missing double escape +svcb SVCB 1 . alpn=abc\, diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn4.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn4.db new file mode 100644 index 0000000..5ba0850 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn4.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn at start +svcb SVCB 1 . alpn=,abc diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn5.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn5.db new file mode 100644 index 0000000..349521a --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn5.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn in midddle +svcb SVCB 1 . alpn=a,,abc diff --git a/bin/tests/system/checkzone/zones/bad-svcb-alpn6.db b/bin/tests/system/checkzone/zones/bad-svcb-alpn6.db new file mode 100644 index 0000000..ae41710 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-alpn6.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; invalid zero length alpn at end +svcb SVCB 1 . alpn=abc, diff --git a/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db b/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db new file mode 100644 index 0000000..368f0ca --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-mandatory.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +svcb SVCB 0 . mandatory=alpn diff --git a/bin/tests/system/checkzone/zones/bad-svcb-servername.db b/bin/tests/system/checkzone/zones/bad-svcb-servername.db new file mode 100644 index 0000000..61751a0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb-servername.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +svcb SVCB 1 _underscore.example. port=60 alpn=h3 ech="ZWFzdGVyIGVnZyE=" diff --git a/bin/tests/system/checkzone/zones/bad-svcb.db b/bin/tests/system/checkzone/zones/bad-svcb.db new file mode 100644 index 0000000..ad710bf --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-svcb.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +svcb SVCB 0 . unknown=wha diff --git a/bin/tests/system/checkzone/zones/bad-tkey.db b/bin/tests/system/checkzone/zones/bad-tkey.db new file mode 100644 index 0000000..a030074 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-tkey.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +tkey TKEY invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw== diff --git a/bin/tests/system/checkzone/zones/bad-tsig.db.in b/bin/tests/system/checkzone/zones/bad-tsig.db.in new file mode 100644 index 0000000..daef06c --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-tsig.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +tsig TSIG @DEFAULT_HMAC@ 1516135665 300 20 thBt8DheAD7qpqSFTiGK999sxGg= 54994 NOERROR 0 diff --git a/bin/tests/system/checkzone/zones/bad-unspec.db b/bin/tests/system/checkzone/zones/bad-unspec.db new file mode 100644 index 0000000..e5abefe --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad-unspec.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +example IN TYPE103 ^# 1 00 diff --git a/bin/tests/system/checkzone/zones/bad1.db b/bin/tests/system/checkzone/zones/bad1.db new file mode 100644 index 0000000..05ab829 Binary files /dev/null and b/bin/tests/system/checkzone/zones/bad1.db differ diff --git a/bin/tests/system/checkzone/zones/bad2.db b/bin/tests/system/checkzone/zones/bad2.db new file mode 100644 index 0000000..38e82e6 --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad2.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; The following GENERATE directive contains two dashes in the range +; which is a syntax error. +$GENERATE 9--10 host$ 3600 A 192.0.2.$ diff --git a/bin/tests/system/checkzone/zones/bad3.db b/bin/tests/system/checkzone/zones/bad3.db new file mode 100644 index 0000000..1391afe --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad3.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; +; A trailing '/' is not permitted. +; +$GENERATE 1-3/ $ A 1.2.3.$ diff --git a/bin/tests/system/checkzone/zones/bad4.db b/bin/tests/system/checkzone/zones/bad4.db new file mode 100644 index 0000000..99def7a --- /dev/null +++ b/bin/tests/system/checkzone/zones/bad4.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +; +; A step of zero is not permitted. +; +$GENERATE 1-3/0 $ A 1.2.3.$ diff --git a/bin/tests/system/checkzone/zones/badttl.db b/bin/tests/system/checkzone/zones/badttl.db new file mode 100644 index 0000000..95cd422 --- /dev/null +++ b/bin/tests/system/checkzone/zones/badttl.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +ns-and-dname NS ns.ns-and-dname + DNAME example.com. +ns.ns-and-dname A 203.178.141.207 diff --git a/bin/tests/system/checkzone/zones/crashzone.db b/bin/tests/system/checkzone/zones/crashzone.db new file mode 100644 index 0000000..2a62e2a --- /dev/null +++ b/bin/tests/system/checkzone/zones/crashzone.db @@ -0,0 +1,62 @@ +; Copyright (C) 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +dyn.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. ( + 6 ; serial + 43200 ; refresh (12 hours) + 1800 ; retry (30 minutes) + 1209600 ; expire (2 weeks) + 7200 ; minimum (2 hours) + ) + 7200 RRSIG SOA 7 3 7200 2010 20100225214229 30323 dyn.example.net. MuyI + 7200 NS ns1.example.net. + 7200 NS ns2.example.net. + 3600 RRSIG DNSKEY 7 3 3600 20100227180048 ( + 20100221180048 52935 dyn.example.net. + MuyIUCa3XlttWuSnaQegQnRgTrTsx0Mj4EGI + fwtZs2H3L079Y/brqMvtlIGxtlr9meLg43oo + jX1w48ilerzf1PwYhtVpFefZTgmClK0h2ej4 + Ho9Qh4/6snesVj06kWsQDkhuVs58zHmhRtEy + P4YlqP/R1CAk166RhwSmGuSx1O8= ) + 0 NSEC3PARAM 1 0 10 76931F +ns1.dyn.example.net. 7200 IN A 1.0.0.5 + 7200 AAAA 2001:db8::53 + 7200 RRSIG AAAA 7 4 7200 20100227180048 ( + 20100221180048 30323 dyn.example.net. + dk1DfG0y9qjCi3VD4e9B1NGKWEig7q8hFdaR + 3hElCIzGlflvgHRiE7iTJxDMB+kTA0by4BMZ + yssUuXP2FMlB2g== ) +ns2.dyn.example.net. 7200 IN A 1.2.0.6 +y.dyn.example.net. 7200 IN A 1.2.3.5 +z.dyn.example.net. 7200 IN A 1.2.3.6 +A54T6DKFVU4QCKFFNJ0KEU0FH0I4OJSN.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F AJHVGTICN6K0VDA53GCHFMT219SRRQLM A RRSIG + 7200 RRSIG NSEC3 7 4 7200 00100227180048 ( + 20100221180048 30323 dyn.example.net. + 9BhZcQdLwRPU/Dz38uMis/nCcddyhKEm0Zb+ + Mhh3V3OsGI202cebTaxbwVEbQQOeowpUmf8l + AmK/cNX7+IS2rw== ) +AJHVGTICN6K0VDA53GCHFMT219SRRQLM.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F FQ7RBG86KRMACA1NAAKP2KQRQALBA0C7 A RRSIG +FQ7RBG86KRMACA1NAAKP2KQRQALBA0C7.dyn.example.net. 7200 RRSIG NSEC3 7 4 7200 20100227180048 ( + 20100221180048 30323 dyn.example.net. + 577WZnTQemStx+diON9rEGXAGnU7C0KLjrFL + VyhocnBnNtxJS8eRMSWvb9XuYCMNhYKOurtt + Ar4qh4VW1+unmA== ) +I7A7A184GGMI35K1E3IR650LKO7NOB5R.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F IMQ912BREQP1POLAH3RMONG;UED541AS A RRSIG +IMQ912BREQP1POLAH3RMONG3UED541AS.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F S3USV4M1HLVJ8F88EDSG8N9PVQRQ20N7 A RRSIG + 7200 RRSIG NSEC3 7 4 7200 20100227180048 ( + 20100221180048 30323 dyn.example.net. + smsg35snQ9PpeG2r8ZGxBl44pwSReh/1rIil + u/n8aa5nKbBpkqtbcc7q1OpUgb1Q7+Tl/wes + kB6bJA== ) +S3USV4M1HLVJ8F88EDSG8N9PVQRQ20N7.dyn.example.net. 7200 RRSIG NSEC3 7 4 7200 20100227180048 ( + 20100221180048 30323 dyn.example.net. + XalRIESpdeVK1aNbwu9ym2SpK981Y127rKua + xsoals0Zn2tTjF9wpOYVGVOto3FcWBbyKD1g + 69BTRlv634UIOw== ) +T320G5LC07QE1BLR074KORIJTG9DPTI9.dyn.example.net. 7200 IN NSEC3 1 0 10 76931F A54T6DKFVU4QCAFFNJ0KEU0FH0I4OJSN NS SOA RRSIG DNSKEY NSEC3PARAM diff --git a/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db b/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db new file mode 100644 index 0000000..78c1029 --- /dev/null +++ b/bin/tests/system/checkzone/zones/delegating-ns-address-below-dname.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +example.com. SOA marka.isc.org. a.root.servers.nil. ( + 2026 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +example.com. NS ns.example.com. +ns.example.com. A 192.168.0.2 +sub.example.com. NS ns.sub2.example.com. +sub2.example.com. DNAME example.net. +ns.sub2.example.com. A 192.168.0.2 diff --git a/bin/tests/system/checkzone/zones/generate-overflow.db b/bin/tests/system/checkzone/zones/generate-overflow.db new file mode 100644 index 0000000..c16b517 --- /dev/null +++ b/bin/tests/system/checkzone/zones/generate-overflow.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +$GENERATE 19-28/2147483645 $ CNAME x diff --git a/bin/tests/system/checkzone/zones/good-cdnskey.db b/bin/tests/system/checkzone/zones/good-cdnskey.db new file mode 100644 index 0000000..7892f13 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-cdnskey.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +example. 0 CDNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= diff --git a/bin/tests/system/checkzone/zones/good-cds-unsigned.db b/bin/tests/system/checkzone/zones/good-cds-unsigned.db new file mode 100644 index 0000000..9b1737d --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-cds-unsigned.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 CDS 0 0 0 00 +example. 0 CDNSKEY 0 3 0 AA== + diff --git a/bin/tests/system/checkzone/zones/good-cds.db b/bin/tests/system/checkzone/zones/good-cds.db new file mode 100644 index 0000000..9200657 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-cds.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 0 SOA . . 0 0 0 0 0 +example. 0 NS . +example. 0 DNSKEY 257 3 10 AwEAAbqjg7xdvnU2Q/gtLw5LOfr5cDeTRjYuEbkzGrUiVSOSoxcTxuao WS/AFPQHuD8OSLiE/CeZ087JowREXl058rRfae8KMrveY17V0wmKs9N1 F1wf/hRDpXiThlRHWlskp8eSEEIqYrrHgWTesy/xDGIEOFM1gwRo0w8j KdRRJeL2hseTMa+m3rTzrYudUsI0BHLW8PiDUCbG5xgdee8/5YR4847i AAqHIiPJ1Z/IT53OIjMmtv5BUykZ8RYjlJxxX+C+dpRKiK73SQaR3hCB XAYOL9WsDp2/fpmEZpewavkMkdC+j2CX+z27MCS3ASO0AeKK0lcNXwND kgreE+Kr7gc= +example. 0 CDS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C diff --git a/bin/tests/system/checkzone/zones/good-cname-and-key.db b/bin/tests/system/checkzone/zones/good-cname-and-key.db new file mode 100644 index 0000000..554d96e --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-cname-and-key.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +good KEY 0 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY + 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV + sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg + a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= ) +good CNAME @ diff --git a/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db new file mode 100644 index 0000000..fffd27b --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-dns-sd-reverse.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA . . 0 0 0 0 0 +@ IN NS . +; +; The following are Service Discovery Prefixes from RFC 6763 and the +; PTR check-names rules for IN-ADDR.ARPA and IP6.ARPA do not apply. +; +b._dns-sd._udp IN PTR !@#3. +db._dns-sd._udp IN PTR !@#3. +r._dns-sd._udp IN PTR !@#3. +dr._dns-sd._udp IN PTR !@#3. +lb._dns-sd._udp IN PTR !@#3. diff --git a/bin/tests/system/checkzone/zones/good-gc-msdcs.db b/bin/tests/system/checkzone/zones/good-gc-msdcs.db new file mode 100644 index 0000000..defd550 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-gc-msdcs.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +gc._msdcs A 192.0.2.2 diff --git a/bin/tests/system/checkzone/zones/good-generate-modifier.db b/bin/tests/system/checkzone/zones/good-generate-modifier.db new file mode 100644 index 0000000..be4be18 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-generate-modifier.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +$GENERATE 0-7 host$ A 1.2.3.${1,0,d} +$GENERATE 8-9 host$ A 1.2.3.${1,0} +$GENERATE 10-11 host$ A 1.2.3.${1} +$GENERATE 1024-1026 ${0,3,n} AAAA 2001:db8::${0,4,x} +$GENERATE 1024-1026 ${-2000,0,n} AAAA 2001:db8::${0,4,x} diff --git a/bin/tests/system/checkzone/zones/good-nsap.db b/bin/tests/system/checkzone/zones/good-nsap.db new file mode 100644 index 0000000..8ad9ee0 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-nsap.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; empty NSAP address +example NSAP 0x47.0005.80.005a00.0000....0001.e133.ffffff000162.00 diff --git a/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db new file mode 100644 index 0000000..5bd378c --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-nsec3-nopadhash.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +; a hash that isn't a multiple of 8 characters +CPNMU NSEC3 2 1 12 aabbccdd ( CPNMU MX DNSKEY NS + SOA NSEC3PARAM RRSIG ) diff --git a/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db b/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db new file mode 100644 index 0000000..80fc4a6 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-dname.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +example. SOA marka.isc.org. a.root.servers.nil. ( + 2026 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +example. DNAME example.net. ; only the apex record exist +example. NS ns.example.net. ; out of zone +foo.example. NS exavider.example. ; no "address" records diff --git a/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db b/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db new file mode 100644 index 0000000..38913b9 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-occulted-ns-by-ns.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +example. SOA marka.isc.org. a.root.servers.nil. ( + 2026 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +example. NS ns.example.net. ; out of zone +foo.example. NS ns.example.net. ; out of zone +bar.foo.example. NS x.foo.example. ; no address records diff --git a/bin/tests/system/checkzone/zones/good-spf-exception.db b/bin/tests/system/checkzone/zones/good-spf-exception.db new file mode 100644 index 0000000..212bfbc --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-spf-exception.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 +a._spf A 192.0.2.2 +a._spf_rate A 192.0.2.2 +a._spf_verify A 192.0.2.2 diff --git a/bin/tests/system/checkzone/zones/good-svcb.db b/bin/tests/system/checkzone/zones/good-svcb.db new file mode 100644 index 0000000..df868f3 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good-svcb.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +svcb0 SVCB 0 example.net. +svcb1 SVCB 1 . port=60 alpn=h3 ech="ZWFzdGVyIGVnZyE=" +svcb2 SVCB 2 . no-default-alpn alpn=alpn +svcb3 SVCB 3 . ipv4hint="10.10.10.10" +svcb4 SVCB 4 . ipv6hint="feed:a::bee" +svcb5 SVCB 5 . key9999="something" +svcb6 SVCB 6 . mandatory=port,alpn port=60 alpn=h3 +svcb7 SVCB 7 . mandatory=port,alpn port=60 alpn=h1,h3 +svcb8 SVCB 8 . mandatory=port,alpn port=60 alpn="h1\\,h2,h3" +svcb9 SVCB 0 44._svbc.example.net. +svcb10 SVCB 7 . alpn="h2,h3" dohpath=/{?dns} diff --git a/bin/tests/system/checkzone/zones/good1.db b/bin/tests/system/checkzone/zones/good1.db new file mode 100644 index 0000000..59eaa54 --- /dev/null +++ b/bin/tests/system/checkzone/zones/good1.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2011012708 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +ns-and-dname NS ns.ns-and-dname + DNAME example.com. +ns.ns-and-dname A 203.178.141.207 diff --git a/bin/tests/system/checkzone/zones/inherit.db b/bin/tests/system/checkzone/zones/inherit.db new file mode 100644 index 0000000..e075d41 --- /dev/null +++ b/bin/tests/system/checkzone/zones/inherit.db @@ -0,0 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + NS . diff --git a/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db b/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db new file mode 100644 index 0000000..db26217 --- /dev/null +++ b/bin/tests/system/checkzone/zones/nowarn.inherited.owner.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +$INCLUDE "zones/inherit.db" diff --git a/bin/tests/system/checkzone/zones/ns-address-below-dname.db b/bin/tests/system/checkzone/zones/ns-address-below-dname.db new file mode 100644 index 0000000..71711a8 --- /dev/null +++ b/bin/tests/system/checkzone/zones/ns-address-below-dname.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +example.com. SOA marka.isc.org. a.root.servers.nil. ( + 2026 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +example.com. DNAME example.net. +example.com. NS ns.example.com. +ns.example.com. A 192.168.0.2 diff --git a/bin/tests/system/checkzone/zones/spf.db b/bin/tests/system/checkzone/zones/spf.db new file mode 100644 index 0000000..9527b1b --- /dev/null +++ b/bin/tests/system/checkzone/zones/spf.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +@ 0 IN NS . +@ 0 IN TXT "v=spf1 -all" +@ 0 IN SPF "v=spf1 -all" +x 0 IN TXT "v=spf1" +y 0 IN SPF "v=spf1" +y 0 IN TXT "a non spf record" diff --git a/bin/tests/system/checkzone/zones/test1.db b/bin/tests/system/checkzone/zones/test1.db new file mode 100644 index 0000000..55669d7 --- /dev/null +++ b/bin/tests/system/checkzone/zones/test1.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2012010901 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +addr1 A 10.53.0.1 diff --git a/bin/tests/system/checkzone/zones/test2.db b/bin/tests/system/checkzone/zones/test2.db new file mode 100644 index 0000000..0cb1184 --- /dev/null +++ b/bin/tests/system/checkzone/zones/test2.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2012010902 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +addr1 A 10.53.0.1 +addr2 A 10.53.0.2 diff --git a/bin/tests/system/checkzone/zones/warn.inherit.origin.db b/bin/tests/system/checkzone/zones/warn.inherit.origin.db new file mode 100644 index 0000000..a348a8f --- /dev/null +++ b/bin/tests/system/checkzone/zones/warn.inherit.origin.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +$ORIGIN @ +$INCLUDE "zones/inherit.db" diff --git a/bin/tests/system/checkzone/zones/warn.inherited.owner.db b/bin/tests/system/checkzone/zones/warn.inherited.owner.db new file mode 100644 index 0000000..dbbd9d1 --- /dev/null +++ b/bin/tests/system/checkzone/zones/warn.inherited.owner.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +$INCLUDE "zones/inherit.db" @ diff --git a/bin/tests/system/checkzone/zones/zone1.db b/bin/tests/system/checkzone/zones/zone1.db new file mode 100644 index 0000000..c2f395d --- /dev/null +++ b/bin/tests/system/checkzone/zones/zone1.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +zone1.com. 86400 IN SOA dns1.zone1.com. hostmaster.zone1.com. 2001062501 21600 3600 604800 86400 +zone1.com. 86400 IN NS dns1.zone1.com. +zone1.com. 86400 IN NS dns2.zone1.com. +zone1.com. 86400 IN A 10.53.0.1 +zone1.com. 86400 IN MX 10 mail1.zone1.com. +zone1.com. 86400 IN MX 20 mail2.zone1.com. +dns1.zone1.com. 86400 IN A 10.53.0.1 +dns2.zone1.com. 86400 IN A 10.53.0.2 +mail1.zone1.com. 86400 IN A 10.53.0.1 +mail2.zone1.com. 86400 IN A 10.53.0.2 diff --git a/bin/tests/system/cipher-suites/ns1/named.conf.in b/bin/tests/system/cipher-suites/ns1/named.conf.in new file mode 100644 index 0000000..8de44d1 --- /dev/null +++ b/bin/tests/system/cipher-suites/ns1/named.conf.in @@ -0,0 +1,102 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls tls-perfect-forward-secrecy { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; + session-tickets no; +}; + +tls tls-pfs-aes256 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384"; + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; + session-tickets no; +}; + +tls tls-pfs-aes128 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_128_GCM_SHA256"; + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; + session-tickets no; +}; + +tls tls-pfs-chacha20 { + protocols { TLSv1.3; }; + cipher-suites "TLS_CHACHA20_POLY1305_SHA256"; + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; + session-tickets no; +}; + +options { + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on-v6 { none; }; + listen-on { 10.53.0.1; }; + listen-on tls tls-perfect-forward-secrecy { 10.53.0.1; }; + listen-on port @EXTRAPORT1@ tls tls-pfs-aes128 { 10.53.0.1; }; + listen-on port @EXTRAPORT2@ tls tls-pfs-aes256 { 10.53.0.1; }; + listen-on port @EXTRAPORT3@ tls tls-pfs-chacha20 { 10.53.0.1; }; + recursion no; + notify explicit; + also-notify { 10.53.0.2 port @PORT@; }; + statistics-file "named.stats"; + dnssec-validation yes; + tcp-initial-timeout 1200; + transfers-in 100; + transfers-out 100; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; + allow-transfer port @TLSPORT@ transport tls { any; }; +}; + +zone "example" { + type primary; + file "example.db"; + allow-transfer port @TLSPORT@ transport tls { any; }; +}; + +zone "example-aes-128" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT1@ transport tls { any; }; +}; + +zone "example-aes-256" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT2@ transport tls { any; }; +}; + +zone "example-chacha-20" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT3@ transport tls { any; }; +}; diff --git a/bin/tests/system/cipher-suites/ns2/named.conf.in b/bin/tests/system/cipher-suites/ns2/named.conf.in new file mode 100644 index 0000000..c81429c --- /dev/null +++ b/bin/tests/system/cipher-suites/ns2/named.conf.in @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on tls local { 10.53.0.2; }; // DoT + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.3 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.3; }; + file "example.db"; + allow-transfer { any; }; +}; + +tls tls-v1.3-aes-128 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_128_GCM_SHA256"; + prefer-server-ciphers no; +}; + +zone "example-aes-128" { + type secondary; + primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-v1.3-aes-128; }; + file "example-aes-128.db"; + allow-transfer { any; }; +}; + +zone "example-aes-256" { + type secondary; + primaries port @EXTRAPORT2@ { 10.53.0.1 tls tls-v1.3-aes-128; }; + file "example-aes-256.db"; + allow-transfer { any; }; +}; + +zone "example-chacha-20" { + type secondary; + primaries port @EXTRAPORT3@ { 10.53.0.1 tls tls-v1.3-aes-128; }; + file "example-chacha-20.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/cipher-suites/ns3/named.conf.in b/bin/tests/system/cipher-suites/ns3/named.conf.in new file mode 100644 index 0000000..ab642f9 --- /dev/null +++ b/bin/tests/system/cipher-suites/ns3/named.conf.in @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on tls local { 10.53.0.3; }; // DoT + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.3 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.3; }; + file "example.db"; + allow-transfer { any; }; +}; + +tls tls-v1.3-aes-256 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384"; + prefer-server-ciphers no; +}; + +zone "example-aes-128" { + type secondary; + primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-v1.3-aes-256; }; + file "example-aes-128.db"; + allow-transfer { any; }; +}; + +zone "example-aes-256" { + type secondary; + primaries port @EXTRAPORT2@ { 10.53.0.1 tls tls-v1.3-aes-256; }; + file "example-aes-256.db"; + allow-transfer { any; }; +}; + +zone "example-chacha-20" { + type secondary; + primaries port @EXTRAPORT3@ { 10.53.0.1 tls tls-v1.3-aes-256; }; + file "example-chacha-20.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/cipher-suites/ns4/named.conf.in b/bin/tests/system/cipher-suites/ns4/named.conf.in new file mode 100644 index 0000000..a690cf5 --- /dev/null +++ b/bin/tests/system/cipher-suites/ns4/named.conf.in @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; +}; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on tls local { 10.53.0.4; }; // DoT + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.3 { + protocols { TLSv1.3; }; + cipher-suites "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.3; }; + file "example.db"; + allow-transfer { any; }; +}; + +tls tls-v1.3-chacha20 { + protocols { TLSv1.3; }; + cipher-suites "TLS_CHACHA20_POLY1305_SHA256"; + prefer-server-ciphers no; +}; + +zone "example-aes-128" { + type secondary; + primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-v1.3-chacha20; }; + file "example-aes-128.db"; + allow-transfer { any; }; +}; + +zone "example-aes-256" { + type secondary; + primaries port @EXTRAPORT2@ { 10.53.0.1 tls tls-v1.3-chacha20; }; + file "example-aes-256.db"; + allow-transfer { any; }; +}; + +zone "example-chacha-20" { + type secondary; + primaries port @EXTRAPORT3@ { 10.53.0.1 tls tls-v1.3-chacha20; }; + file "example-chacha-20.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/cipher-suites/ns5/named.conf.in b/bin/tests/system/cipher-suites/ns5/named.conf.in new file mode 100644 index 0000000..c36b374 --- /dev/null +++ b/bin/tests/system/cipher-suites/ns5/named.conf.in @@ -0,0 +1,80 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../self-signed-key.pem"; + cert-file "../self-signed-cert.pem"; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + tls-port @TLSPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on tls local { 10.53.0.5; }; // DoT + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.2 { + protocols { TLSv1.2; }; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.2; }; + file "example.db"; + allow-transfer { any; }; +}; + +zone "example-aes-128" { + type secondary; + primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-v1.2; }; + file "example-aes-128.db"; + allow-transfer { any; }; +}; + +zone "example-aes-256" { + type secondary; + primaries port @EXTRAPORT2@ { 10.53.0.1 tls tls-v1.2; }; + file "example-aes-256.db"; + allow-transfer { any; }; +}; + +zone "example-chacha-20" { + type secondary; + primaries port @EXTRAPORT3@ { 10.53.0.1 tls tls-v1.2; }; + file "example-chacha-20.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/cipher-suites/prereq.sh b/bin/tests/system/cipher-suites/prereq.sh new file mode 100644 index 0000000..9103595 --- /dev/null +++ b/bin/tests/system/cipher-suites/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --have-openssl-cipher-suites || { + echo_i "SSL_CTX_set_ciphersuites() is required for the test." + exit 255 +} + +exit 0 diff --git a/bin/tests/system/cipher-suites/self-signed-cert.pem b/bin/tests/system/cipher-suites/self-signed-cert.pem new file mode 100644 index 0000000..8fd6db3 --- /dev/null +++ b/bin/tests/system/cipher-suites/self-signed-cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICpDCCAkmgAwIBAgIUCgppsffsoMFrEULJBNaABqUJGl8wCgYIKoZIzj0EAwIw +gaYxCzAJBgNVBAYTAlVBMRwwGgYDVQQIDBNLaGFya2l2cydrYSBvYmxhc3QnMRAw +DgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5ldCBTeXN0ZW1zIENvbnNv +cnRpdW0xHzAdBgNVBAsMFkJJTkQ5IERldmVsb3BtZW50IFRlYW0xIDAeBgNVBAMM +F3NlbGYtc2lnbmVkLmV4YW1wbGUuY29tMB4XDTIzMTIwMTE1NTU0OVoXDTQzMTEz +MDE1NTU0OVowgaYxCzAJBgNVBAYTAlVBMRwwGgYDVQQIDBNLaGFya2l2cydrYSBv +Ymxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5ldCBTeXN0 +ZW1zIENvbnNvcnRpdW0xHzAdBgNVBAsMFkJJTkQ5IERldmVsb3BtZW50IFRlYW0x +IDAeBgNVBAMMF3NlbGYtc2lnbmVkLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEAvOwTFQkxZ5buinXL2II3F2Bkq7BfycqugoRJohm6avxEqKF +pByu6gWQxgWFFelXAz2FRhT4SK+E1o/b9X2EGKNTMFEwHQYDVR0OBBYEFPcvo8eC +k8kDoF2Lmpua+qMJdV5eMB8GA1UdIwQYMBaAFPcvo8eCk8kDoF2Lmpua+qMJdV5e +MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAJh6QFBC8JnHTEjD +GLevzFzjbxSNjMj0xgrX4eK+9JjCAiEAqFkj9wGs7U1cZrZI0Mnje9itHgQrMl1u +olvLJ/W2LBc= +-----END CERTIFICATE----- diff --git a/bin/tests/system/cipher-suites/self-signed-key.pem b/bin/tests/system/cipher-suites/self-signed-key.pem new file mode 100644 index 0000000..075b4d9 --- /dev/null +++ b/bin/tests/system/cipher-suites/self-signed-key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIME55eKuHtLyCHYCvJcIU1o8FdATceC7rQWwEyIhnzINoAoGCCqGSM49 +AwEHoUQDQgAEAvOwTFQkxZ5buinXL2II3F2Bkq7BfycqugoRJohm6avxEqKFpByu +6gWQxgWFFelXAz2FRhT4SK+E1o/b9X2EGA== +-----END EC PRIVATE KEY----- diff --git a/bin/tests/system/cipher-suites/setup.sh b/bin/tests/system/cipher-suites/setup.sh new file mode 100644 index 0000000..71b94b9 --- /dev/null +++ b/bin/tests/system/cipher-suites/setup.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +# Drop unusual RR sets dnspython can't handle. For more information +# see https://github.com/rthalley/dnspython/issues/1034#issuecomment-1896541899. +$SHELL "${TOP_SRCDIR}/bin/tests/system/genzone.sh" 2 \ + | sed \ + -e '/AMTRELAY.*\# 2 0004/d' \ + -e '/GPOS.*"" "" ""/d' \ + -e '/URI.*30 40 ""/d' >ns1/example.db + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf diff --git a/bin/tests/system/cipher-suites/tests_cipher_suites.py b/bin/tests/system/cipher-suites/tests_cipher_suites.py new file mode 100644 index 0000000..1be3aaf --- /dev/null +++ b/bin/tests/system/cipher-suites/tests_cipher_suites.py @@ -0,0 +1,93 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import re + +import pytest + +pytest.importorskip("dns", minversion="2.5.0") + +import dns.message + +import isctest +import isctest.mark + + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/example*.db", + ] +) + + +@pytest.fixture(scope="module") +def transfers_complete(servers): + for zone in ["example", "example-aes-128", "example-aes-256", "example-chacha-20"]: + pattern = re.compile( + f"transfer of '{zone}/IN' from 10.53.0.1#[0-9]+: Transfer completed" + ) + for ns in ["ns2", "ns3", "ns4", "ns5"]: + with servers[ns].watch_log_from_start() as watcher: + watcher.wait_for_line(pattern) + + +@pytest.mark.requires_zones_loaded("ns1", "ns2", "ns3", "ns4", "ns5") +@pytest.mark.parametrize( + "qname,ns,rcode", + [ + ("example.", 2, dns.rcode.NOERROR), + ("example.", 3, dns.rcode.NOERROR), + ("example.", 4, dns.rcode.NOERROR), + ("example-aes-128.", 2, dns.rcode.NOERROR), + ("example-aes-256.", 3, dns.rcode.NOERROR), + pytest.param( + "example-chacha-20.", + 4, + dns.rcode.NOERROR, + marks=isctest.mark.without_fips, + ), + ("example-aes-256", 2, dns.rcode.SERVFAIL), + pytest.param( + "example-chacha-20", + 2, + dns.rcode.SERVFAIL, + marks=isctest.mark.without_fips, + ), + ("example-aes-128", 3, dns.rcode.SERVFAIL), + pytest.param( + "example-chacha-20", + 3, + dns.rcode.SERVFAIL, + marks=isctest.mark.without_fips, + ), + ("example-aes-128", 4, dns.rcode.SERVFAIL), + ("example-aes-256", 4, dns.rcode.SERVFAIL), + # NS5 tries to download the zone over TLSv1.2 + ("example", 5, dns.rcode.SERVFAIL), + ("example-aes-128", 5, dns.rcode.SERVFAIL), + ("example-aes-256", 5, dns.rcode.SERVFAIL), + pytest.param( + "example-chacha-20", + 5, + dns.rcode.SERVFAIL, + marks=isctest.mark.without_fips, + ), + ], +) +# pylint: disable=redefined-outer-name,unused-argument +def test_cipher_suites_tls_xfer(qname, ns, rcode, transfers_complete): + msg = dns.message.make_query(qname, "AXFR") + ans = isctest.query.tls(msg, f"10.53.0.{ns}") + assert ans.rcode() == rcode + if rcode == dns.rcode.NOERROR: + assert ans.answer != [] + elif rcode == dns.rcode.SERVFAIL: + assert ans.answer == [] diff --git a/bin/tests/system/conf.sh b/bin/tests/system/conf.sh new file mode 100644 index 0000000..40ca821 --- /dev/null +++ b/bin/tests/system/conf.sh @@ -0,0 +1,538 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# When sourcing the script outside the pytest environment (e.g. during helper +# script development), the env variables have to be loaded. +if [ -z "$TOP_SRCDIR" ]; then + SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd | sed -E 's|(.*bin/tests/system).*|\1|') + eval "$(PYTHONPATH="$SCRIPT_DIR:$PYTHONPATH" /usr/bin/env python3 -m isctest)" +fi + +testsock6() { + if test -n "$PERL" && $PERL -e "use IO::Socket::IP;" 2>/dev/null; then + $PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@" + else + false + fi +} + +echofail() { + echo "$*" +} +echowarn() { + echo "$*" +} +echopass() { + echo "$*" +} +echoinfo() { + echo "$*" +} +echostart() { + echo "$*" +} +echoend() { + echo "$*" +} + +echo_i() { + echo "$@" | while IFS= read -r __LINE; do + echoinfo "I:$__LINE" + done +} + +echo_ic() { + echo "$@" | while IFS= read -r __LINE; do + echoinfo "I: $__LINE" + done +} + +echo_d() { + echo "$@" | while IFS= read -r __LINE; do + echoinfo "D:$__LINE" + done +} + +cat_i() { + while IFS= read -r __LINE; do + echoinfo "I:$__LINE" + done +} + +cat_d() { + while IFS= read -r __LINE; do + echoinfo "D:$__LINE" + done +} + +digcomp() { + { + output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@") + result=$? + } || true + [ -n "$output" ] && { + echo "digcomp failed:" + echo "$output" + } | cat_i + return $result +} + +start_server() { + $PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@" +} + +stop_server() { + $PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@" +} + +send() { + $PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@" +} + +# +# Useful functions in test scripts +# + +# assert_int_equal: compare two integer variables, $1 and $2 +# +# If $1 and $2 are equal, return 0; if $1 and $2 are not equal, report +# the error using the description of the tested variable provided in $3 +# and return 1. +assert_int_equal() { + found="$1" + expected="$2" + description="$3" + + if [ "${expected}" -ne "${found}" ]; then + echo_i "incorrect ${description}: got ${found}, expected ${expected}" + return 1 + fi + + return 0 +} + +# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which +# converts keyfile data into a key-style trust anchor configuration +# section using the supplied parameters +keyfile_to_keys() { + section_name=$1 + key_prefix=$2 + shift + shift + echo "$section_name {" + for keyname in $*; do + awk '!/^; /{ + printf "\t\""$1"\" " + printf "'"$key_prefix "'" + printf $4 " " $5 " " $6 " \"" + for (i=7; i<=NF; i++) printf $i + printf "\";\n" + }' $keyname.key + done + echo "};" +} + +# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys() +# converts keyfile data into a DS-style trust anchor configuration +# section using the supplied parameters +keyfile_to_dskeys() { + section_name=$1 + key_prefix=$2 + shift + shift + echo "$section_name {" + for keyname in $*; do + $DSFROMKEY $keyname.key \ + | awk '!/^; /{ + printf "\t\""$1"\" " + printf "'"$key_prefix "'" + printf $4 " " $5 " " $6 " \"" + for (i=7; i<=NF; i++) printf $i + printf "\";\n" + }' + done + echo "};" +} + +# keyfile_to_trusted_keys: convert key data contained in the keyfile(s) +# provided to a "trust-keys" section suitable for including in a +# resolver's configuration file +keyfile_to_trusted_keys() { + keyfile_to_keys "trusted-keys" "" $* +} + +# keyfile_to_static_keys: convert key data contained in the keyfile(s) +# provided to a *static-key* "trust-anchors" section suitable for including in +# a resolver's configuration file +keyfile_to_static_keys() { + keyfile_to_keys "trust-anchors" "static-key" $* +} + +# keyfile_to_initial_keys: convert key data contained in the keyfile(s) +# provided to an *initial-key* "trust-anchors" section suitable for including +# in a resolver's configuration file +keyfile_to_initial_keys() { + keyfile_to_keys "trust-anchors" "initial-key" $* +} + +# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s) +# provided to a *static-ds* "trust-anchors" section suitable for including in a +# resolver's configuration file +keyfile_to_static_ds() { + keyfile_to_dskeys "trust-anchors" "static-ds" $* +} + +# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s) +# provided to an *initial-ds* "trust-anchors" section suitable for including +# in a resolver's configuration file +keyfile_to_initial_ds() { + keyfile_to_dskeys "trust-anchors" "initial-ds" $* +} + +# keyfile_to_key_id: convert a key file name to a key ID +# +# For a given key file name (e.g. "Kexample.+013+06160") provided as $1, +# print the key ID with leading zeros stripped ("6160" for the +# aforementioned example). +keyfile_to_key_id() { + echo "$1" | sed "s/.*+0\{0,4\}//" +} + +# private_type_record: write a private type record recording the state of the +# signing process +# +# For a given zone ($1), algorithm number ($2) and key file ($3), print the +# private type record with default type value of 65534, indicating that the +# signing process for this key is completed. +private_type_record() { + _zone=$1 + _algorithm=$2 + _keyfile=$3 + + _id=$(keyfile_to_key_id "$_keyfile") + + printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id" +} + +# nextpart*() - functions for reading files incrementally +# +# These functions aim to facilitate looking for (or waiting for) +# messages which may be logged more than once throughout the lifetime of +# a given named instance by outputting just the part of the file which +# has been appended since the last time we read it. +# +# Calling some of these functions causes temporary *.prev files to be +# created. +# +# Note that unlike other nextpart*() functions, nextpartread() is not +# meant to be directly used in system tests; its sole purpose is to +# reduce code duplication below. +# +# A quick usage example: +# +# $ echo line1 > named.log +# $ echo line2 >> named.log +# $ nextpart named.log +# line1 +# line2 +# $ echo line3 >> named.log +# $ nextpart named.log +# line3 +# $ nextpart named.log +# $ echo line4 >> named.log +# $ nextpartpeek named.log +# line4 +# $ nextpartpeek named.log +# line4 +# $ nextpartreset named.log +# $ nextpartpeek named.log +# line1 +# line2 +# line3 +# line4 +# $ nextpart named.log +# line1 +# line2 +# line3 +# line4 +# $ nextpart named.log +# $ + +# nextpartreset: reset the marker used by nextpart() and nextpartpeek() +# so that it points to the start of the given file +nextpartreset() { + echo "0" >$1.prev +} + +# nextpartread: read everything that's been appended to a file since the +# last time nextpart() was called and print it to stdout, print the +# total number of lines read from that file so far to file descriptor 3 +nextpartread() { + [ -f $1.prev ] || nextpartreset $1 + prev=$(cat $1.prev) + awk "NR > $prev "'{ print } + END { print NR > "/dev/stderr" }' $1 2>&3 +} + +# nextpart: read everything that's been appended to a file since the +# last time nextpart() was called +nextpart() { + nextpartread $1 3>$1.prev.tmp + mv $1.prev.tmp $1.prev +} + +# nextpartpeek: read everything that's been appended to a file since the +# last time nextpart() was called +nextpartpeek() { + nextpartread $1 3>/dev/null +} + +# _search_log: look for message $1 in file $2 with nextpart(). +_search_log() ( + msg="$1" + file="$2" + nextpart "$file" | grep -F -e "$msg" >/dev/null +) + +# _search_log_re: same as _search_log but the message is an grep -E regex +_search_log_re() ( + msg="$1" + file="$2" + nextpart "$file" | grep -E -e "$msg" >/dev/null +) + +# _search_log_peek: look for message $1 in file $2 with nextpartpeek(). +_search_log_peek() ( + msg="$1" + file="$2" + nextpartpeek "$file" | grep -F -e "$msg" >/dev/null +) + +# wait_for_log: wait until message $2 in file $3 appears. Bail out after +# $1 seconds. This needs to be used in conjunction with a prior call to +# nextpart() or nextpartreset() on the same file to guarantee the offset is +# set correctly. Tests using wait_for_log() are responsible for cleaning up +# the created .prev files. +wait_for_log() ( + timeout="$1" + msg="$2" + file="$3" + retry_quiet "$timeout" _search_log "$msg" "$file" && return 0 + echo_i "exceeded time limit waiting for literal '$msg' in $file" + return 1 +) + +# wait_for_log_re: same as wait_for_log, but the message is an grep -E regex +wait_for_log_re() ( + timeout="$1" + msg="$2" + file="$3" + retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0 + echo_i "exceeded time limit waiting for regex '$msg' in $file" + return 1 +) + +# wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset +# does not change. +wait_for_log_peek() ( + timeout="$1" + msg="$2" + file="$3" + retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0 + echo_i "exceeded time limit waiting for literal '$msg' in $file" + return 1 +) + +# _retry: keep running a command until it succeeds, up to $1 times, with +# one-second intervals, optionally printing a message upon every attempt +_retry() { + __retries="${1}" + shift + + while :; do + if "$@"; then + return 0 + fi + __retries=$((__retries - 1)) + if [ "${__retries}" -gt 0 ]; then + if [ "${__retry_quiet}" -ne 1 ]; then + echo_i "retrying" + fi + sleep 1 + else + return 1 + fi + done +} + +# retry: call _retry() in verbose mode +retry() { + __retry_quiet=0 + _retry "$@" +} + +# retry_quiet: call _retry() in silent mode +retry_quiet() { + __retry_quiet=1 + _retry "$@" +} + +# _repeat: keep running command up to $1 times, unless it fails +_repeat() ( + __retries="${1}" + shift + while :; do + if ! "$@"; then + return 1 + fi + __retries=$((__retries - 1)) + if [ "${__retries}" -le 0 ]; then + break + fi + done + return 0 +) + +_times() { + awk "BEGIN{ for(i = 1; i <= $1; i++) print i}" +} + +rndc_reload() { + $RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$1"' /' + # reloading single zone is synchronous, if we're reloading whole server + # we need to wait for reload to finish + if [ -z "$3" ]; then + for _ in $(_times 10); do + $RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" >/dev/null || break + sleep 1 + done + fi +} + +rndc_reconfig() { + seconds=${3:-10} + $RNDC -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$1"' /' + for _ in $(_times "$seconds"); do + "$RNDC" -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" >/dev/null || break + sleep 1 + done +} + +# rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes +# +# The first argument is the name server instance to send the command to, in the +# form of "nsX" (where "X" is the instance number), e.g. "ns5". The remaining +# arguments, if any, are appended to the rndc command line after "dumpdb". +# +# Control channel configuration for the name server instance to send the +# command to must match the contents of bin/tests/system/_common/rndc.conf. +# +# rndc output is stored in a file called rndc.out.test${n}; the "n" variable is +# required to be set by the calling tests.sh script. +# +# Return 0 if the dump completes successfully; return 1 if rndc returns an exit +# code other than 0 or if the "; Dump complete" string does not appear in the +# dump within 10 seconds. +rndc_dumpdb() { + __ret=0 + __dump_complete=0 + __server="${1}" + __ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")" + + shift + ${RNDC} -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" >"rndc.out.test${n}" 2>&1 || __ret=1 + + for _ in 0 1 2 3 4 5 6 7 8 9; do + if grep '^; Dump complete$' "${__server}/named_dump.db" >/dev/null; then + mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}" + __dump_complete=1 + break + fi + sleep 1 + done + + if [ ${__dump_complete} -eq 0 ]; then + echo_i "timed out waiting for 'rndc dumpdb' to finish" + __ret=1 + fi + + return ${__ret} +} + +# get_dig_xfer_stats: extract transfer statistics from dig output stored +# in $1, converting them to a format used by some system tests. +get_dig_xfer_stats() { + LOGFILE="$1" + sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}" + sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}" + sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}" +} + +# get_named_xfer_stats: from named log file $1, extract transfer +# statistics for the last transfer for peer $2 and zone $3 (from a log +# message which has to contain the string provided in $4), converting +# them to a format used by some system tests. +get_named_xfer_stats() { + LOGFILE="$1" + PEER="$(echo $2 | sed 's/\./\\./g')" + ZONE="$(echo $3 | sed 's/\./\\./g')" + MESSAGE="$4" + grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \ + | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1 + grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \ + | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1 + grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \ + | sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1 +} + +# copy_setports - Copy Configuration File and Replace Ports +# +# Convenience function to copy a configuration file, replacing the tokens +# QUERYPORT, CONTROLPORT and EXTRAPORT[1-8] with the values of the equivalent +# environment variables. (These values are set by test runner, which calls the +# scripts invoking this function.) +# +# Usage: +# copy_setports infile outfile +# +copy_setports() { + dir=$(echo "$TMPDIR" | sed 's/\//\\\//g') + + sed -e "s/@TMPDIR@/${dir}/g" \ + -e "s/@PORT@/${PORT}/g" \ + -e "s/@TLSPORT@/${TLSPORT}/g" \ + -e "s/@HTTPPORT@/${HTTPPORT}/g" \ + -e "s/@HTTPSPORT@/${HTTPSPORT}/g" \ + -e "s/@EXTRAPORT1@/${EXTRAPORT1}/g" \ + -e "s/@EXTRAPORT2@/${EXTRAPORT2}/g" \ + -e "s/@EXTRAPORT3@/${EXTRAPORT3}/g" \ + -e "s/@EXTRAPORT4@/${EXTRAPORT4}/g" \ + -e "s/@EXTRAPORT5@/${EXTRAPORT5}/g" \ + -e "s/@EXTRAPORT6@/${EXTRAPORT6}/g" \ + -e "s/@EXTRAPORT7@/${EXTRAPORT7}/g" \ + -e "s/@EXTRAPORT8@/${EXTRAPORT8}/g" \ + -e "s/@CONTROLPORT@/${CONTROLPORT}/g" \ + -e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \ + -e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \ + -e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \ + -e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \ + -e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \ + -e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \ + -e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \ + -e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \ + -e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \ + -e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \ + $1 >$2 +} + +grep_v() { grep -v "$@" || test $? = 1; } diff --git a/bin/tests/system/conftest.py b/bin/tests/system/conftest.py new file mode 100644 index 0000000..2c80777 --- /dev/null +++ b/bin/tests/system/conftest.py @@ -0,0 +1,636 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import filecmp +import os +from pathlib import Path +import re +import shutil +import subprocess +import tempfile +import time +from typing import Any + +import pytest + +pytest.register_assert_rewrite("isctest") + +import isctest +from isctest.vars.dirs import SYSTEM_TEST_DIR_GIT_PATH + + +# Silence warnings caused by passing a pytest fixture to another fixture. +# pylint: disable=redefined-outer-name + + +isctest.log.init_conftest_logger() +isctest.log.avoid_duplicated_logs() +isctest.vars.init_vars() + +# ----------------- Older pytest / xdist compatibility ------------------- +# As of 2023-01-11, the minimal supported pytest / xdist versions are +# determined by what is available in EL8/EPEL8: +# - pytest 3.4.2 +# - pytest-xdist 1.24.1 +_pytest_ver = pytest.__version__.split(".") +_pytest_major_ver = int(_pytest_ver[0]) +if _pytest_major_ver < 7: + # pytest.Stash/pytest.StashKey mechanism has been added in 7.0.0 + # for older versions, use regular dictionary with string keys instead + FIXTURE_OK = "fixture_ok" # type: Any +else: + FIXTURE_OK = pytest.StashKey[bool]() # pylint: disable=no-member + +# ----------------------- Globals definition ----------------------------- + +XDIST_WORKER = os.environ.get("PYTEST_XDIST_WORKER", "") +FILE_DIR = os.path.abspath(Path(__file__).parent) +ENV_RE = re.compile(b"([^=]+)=(.*)") +PRIORITY_TESTS = [ + # Tests that are scheduled first. Speeds up parallel execution. + "rpz/", + "rpzrecurse/", + "serve-stale/", + "timeouts/", + "upforwd/", +] +PRIORITY_TESTS_RE = re.compile("|".join(PRIORITY_TESTS)) +SYSTEM_TEST_NAME_RE = re.compile(f"{SYSTEM_TEST_DIR_GIT_PATH}" + r"/([^/]+)") +SYMLINK_REPLACEMENT_RE = re.compile(r"/tests(_.*)\.py") + +# ----------------------- Global requirements ---------------------------- + +isctest.check.is_executable(isctest.vars.ALL["PYTHON"], "Python interpreter required") +isctest.check.is_executable(isctest.vars.ALL["PERL"], "Perl interpreter required") + +# --------------------------- pytest hooks ------------------------------- + + +def pytest_addoption(parser): + parser.addoption( + "--noclean", + action="store_true", + default=False, + help="don't remove the temporary test directories with artifacts", + ) + + +def pytest_configure(config): + # Ensure this hook only runs on the main pytest instance if xdist is + # used to spawn other workers. + if not XDIST_WORKER: + if config.pluginmanager.has_plugin("xdist") and config.option.numprocesses: + # system tests depend on module scope for setup & teardown + # enforce use "loadscope" scheduler or disable paralelism + try: + import xdist.scheduler.loadscope # pylint: disable=unused-import + except ImportError: + isctest.log.debug( + "xdist is too old and does not have " + "scheduler.loadscope, disabling parallelism" + ) + config.option.dist = "no" + else: + config.option.dist = "loadscope" + + +def pytest_ignore_collect(path): + # System tests are executed in temporary directories inside + # bin/tests/system. These temporary directories contain all files + # needed for the system tests - including tests_*.py files. Make sure to + # ignore these during test collection phase. Otherwise, test artifacts + # from previous runs could mess with the runner. Also ignore the + # convenience symlinks to those test directories. In both of those + # cases, the system test name (directory) contains an underscore, which + # is otherwise and invalid character for a system test name. + match = SYSTEM_TEST_NAME_RE.search(str(path)) + if match is None: + isctest.log.warning("unexpected test path: %s (ignored)", path) + return True + system_test_name = match.groups()[0] + return "_" in system_test_name + + +def pytest_collection_modifyitems(items): + """Schedule long-running tests first to get more benefit from parallelism.""" + priority = [] + other = [] + for item in items: + if PRIORITY_TESTS_RE.search(item.nodeid): + priority.append(item) + else: + other.append(item) + items[:] = priority + other + + +class NodeResult: + def __init__(self, report=None): + self._outcomes = {} + self.messages = {} + if report is not None: + self.update(report) + + def update(self, report): + # Allow the same nodeid/when to be overriden. This only happens when + # the test is re-run with flaky plugin. In that case, we want the + # latest result to override any previous results. + key = (report.nodeid, report.when) + self._outcomes[key] = report.outcome + self.messages[key] = report.longreprtext + + @property + def outcome(self): + for outcome in self._outcomes.values(): + if outcome != "passed": + return outcome + return "passed" + + +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_runtest_makereport(item): + """Hook that is used to expose test results to session (for use in fixtures).""" + # execute all other hooks to obtain the report object + outcome = yield + report = outcome.get_result() + + # Set the test outcome in session, so we can access it from module-level + # fixture using nodeid. Note that this hook is called three times: for + # setup, call and teardown. We only care about the overall result so we + # merge the results together and preserve the information whether a test + # passed. + test_results = {} + try: + test_results = getattr(item.session, "test_results") + except AttributeError: + setattr(item.session, "test_results", test_results) + node_result = test_results.setdefault(item.nodeid, NodeResult()) + node_result.update(report) + + +# --------------------------- Fixtures ----------------------------------- + + +@pytest.fixture(scope="session") +def modules(): + """ + Sorted list of ALL modules. + + The list includes even test modules that are not tested in the current + session. It is used to determine port distribution. Using a complete + list of all possible test modules allows independent concurrent pytest + invocations. + """ + mods = [] + for dirpath, _dirs, files in os.walk(FILE_DIR): + for file in files: + if file.startswith("tests_") and file.endswith(".py"): + mod = f"{dirpath}/{file}" + if not pytest_ignore_collect(mod): + mods.append(mod) + return sorted(mods) + + +@pytest.fixture(scope="session") +def module_base_ports(modules): + """ + Dictionary containing assigned base port for every module. + + The port numbers are deterministically assigned before any testing + starts. This fixture MUST return the same value when called again + during the same test session. When running tests in parallel, this is + exactly what happens - every worker thread will call this fixture to + determine test ports. + """ + port_min = isctest.vars.ports.PORT_MIN + port_max = ( + isctest.vars.ports.PORT_MAX - len(modules) * isctest.vars.ports.PORTS_PER_TEST + ) + if port_max < port_min: + raise RuntimeError("not enough ports to assign unique port set to each module") + + # Rotate the base port value over time to detect possible test issues + # with using random ports. This introduces a very slight race condition + # risk. If this value changes between pytest invocation and spawning + # worker threads, multiple tests may have same port values assigned. If + # these tests are then executed simultaneously, the test results will + # be misleading. + base_port = int(time.time() // 3600) % (port_max - port_min) + port_min + + return { + mod: base_port + i * isctest.vars.ports.PORTS_PER_TEST + for i, mod in enumerate(modules) + } + + +@pytest.fixture(autouse=True, scope="module") +def base_port(request, module_base_ports): + """Start of the port range assigned to a particular test module.""" + port = module_base_ports[request.fspath] + isctest.vars.ports.set_base_port(port) + return port + + +@pytest.fixture(scope="module") +def named_port(): + return int(os.environ["PORT"]) + + +@pytest.fixture(scope="module") +def named_tlsport(): + return int(os.environ["TLSPORT"]) + + +@pytest.fixture(scope="module") +def named_httpsport(): + return int(os.environ["HTTPSPORT"]) + + +@pytest.fixture(scope="module") +def control_port(): + return int(os.environ["CONTROLPORT"]) + + +@pytest.fixture(scope="module") +def system_test_name(request): + """Name of the system test directory.""" + path = Path(request.fspath) + return path.parent.name + + +def _get_marker(node, marker): + try: + # pytest >= 4.x + return node.get_closest_marker(marker) + except AttributeError: + # pytest < 4.x + return node.get_marker(marker) + + +@pytest.fixture(autouse=True) +def wait_for_zones_loaded(request, servers): + """Wait for all zones to be loaded by specified named instances.""" + instances = _get_marker(request.node, "requires_zones_loaded") + if not instances: + return + + for instance in instances.args: + with servers[instance].watch_log_from_start() as watcher: + watcher.wait_for_line("all zones loaded") + + +@pytest.fixture(scope="module", autouse=True) +def configure_algorithm_set(request): + """Configure the algorithm set to use in tests.""" + mark = _get_marker(request.node, "algorithm_set") + if not mark: + name = None + else: + name = mark.args[0] + isctest.vars.set_algorithm_set(name) + + +@pytest.fixture(autouse=True) +def logger(request, system_test_name): + """Sets up logging facility specific to a particular test.""" + isctest.log.init_test_logger(system_test_name, request.node.name) + yield + isctest.log.deinit_test_logger() + + +@pytest.fixture(scope="module") +def expected_artifacts(request): + common_artifacts = [ + "*/.hypothesis", # drop after Ubuntu 20.04 Focal Fossa gets removed from CI + ".libs/*", # possible build artifacts, see GL #5055 + "ns*/named.conf", + "ns*/named.memstats", + "ns*/named.run", + "ns*/named.run.prev", + "pytest.log.txt", + ] + + if "USE_RR" in os.environ: + common_artifacts += [ + "ns*/cpu_lock", + "ns*/latest-trace", + "ns*/named-[0-9]*", + ] + + try: + test_specific_artifacts = request.node.get_closest_marker("extra_artifacts") + except AttributeError: + return None + + if test_specific_artifacts: + return common_artifacts + test_specific_artifacts.args[0] + + return common_artifacts + + +@pytest.fixture(scope="module") +def system_test_dir(request, system_test_name, expected_artifacts): + """ + Temporary directory for executing the test. + + This fixture is responsible for creating (and potentially removing) a + copy of the system test directory which is used as a temporary + directory for the test execution. + """ + + def get_test_result(): + """Aggregate test results from all individual tests from this module + into a single result: failed > skipped > passed.""" + try: + all_test_results = request.session.test_results + except AttributeError: + # This may happen if pytest execution is interrupted and + # pytest_runtest_makereport() is never called. + isctest.log.debug("can't obtain test results, test run was interrupted") + return "error" + test_results = { + node.nodeid: all_test_results[node.nodeid] + for node in request.node.collect() + if node.nodeid in all_test_results + } + assert len(test_results) + messages = [] + for node, result in test_results.items(): + isctest.log.debug("%s %s", result.outcome.upper(), node) + messages.extend(result.messages.values()) + for message in messages: + isctest.log.debug("\n" + message) + failed = any(res.outcome == "failed" for res in test_results.values()) + skipped = any(res.outcome == "skipped" for res in test_results.values()) + if failed: + return "failed" + if skipped: + return "skipped" + assert all(res.outcome == "passed" for res in test_results.values()) + return "passed" + + def unlink(path): + try: + path.unlink() # missing_ok=True isn't available on Python 3.6 + except FileNotFoundError: + pass + + def check_artifacts(source_dir, run_dir): + def check_artifacts_recursive(dcmp): + def artifact_expected(path, expected): + for glob in expected: + if path.match(glob): + return True + return False + + # test must not remove any Git-tracked file, ignore libtool and gcov artifacts + for name in dcmp.left_only: + assert name.startswith("lt-") or name.endswith(".gcda") + for name in dcmp.diff_files: + # There should be no diff_files. However, due to how the + # obsolete dnsrps tests are launched, this workaround is + # required to ignore the dnsrps-dnsrps.gcda file which may + # get detected here as git-tracked in some circumstances + assert name.endswith( + ".gcda" + ), "test must not modify any Git-tracked file" + + dir_path = Path(dcmp.left).relative_to(source_dir) + for name in dcmp.right_only: + file = dir_path / Path(name) + if not artifact_expected(file, expected_artifacts): + unexpected_files.append(str(file)) + for subdir in dcmp.subdirs.values(): + check_artifacts_recursive(subdir) + + if expected_artifacts is None: # skip the check if artifact list is unavailable + return + + unexpected_files = [] + dcmp = filecmp.dircmp(source_dir, run_dir) + check_artifacts_recursive(dcmp) + + assert ( + not unexpected_files + ), f"Unexpected files found in test directory: {unexpected_files}" + + # Create a temporary directory with a copy of the original system test dir contents + system_test_root = Path(os.environ["builddir"]) + testdir = Path( + tempfile.mkdtemp(prefix=f"{system_test_name}_tmp_", dir=system_test_root) + ) + shutil.rmtree(testdir) + shutil.copytree(system_test_root / system_test_name, testdir) + isctest.vars.dirs.set_system_test_name(testdir.name) + + # Create a convenience symlink with a stable and predictable name + module_name = SYMLINK_REPLACEMENT_RE.sub(r"\1", str(_get_node_path(request.node))) + symlink_dst = system_test_root / module_name + unlink(symlink_dst) + symlink_dst.symlink_to(os.path.relpath(testdir, start=system_test_root)) + + isctest.log.init_module_logger(system_test_name, testdir) + + # System tests are meant to be executed from their directory - switch to it. + old_cwd = os.getcwd() + os.chdir(testdir) + isctest.log.info("switching to tmpdir: %s", testdir) + try: + yield testdir # other fixtures / tests will execute here + finally: + os.chdir(old_cwd) + isctest.log.debug("changed workdir to: %s", old_cwd) + + result = get_test_result() + + if result == "passed": + check_artifacts(system_test_root / system_test_name, testdir) + + # Clean temporary dir unless it should be kept + keep = False + if request.config.getoption("--noclean"): + isctest.log.debug( + "--noclean requested, keeping temporary directory %s", testdir + ) + keep = True + elif result == "failed": + isctest.log.debug( + "test failure detected, keeping temporary directory %s", testdir + ) + keep = True + elif not request.node.stash[FIXTURE_OK]: + isctest.log.debug( + "test setup/teardown issue detected, keeping temporary directory %s", + testdir, + ) + keep = True + + if keep: + isctest.log.info( + "test artifacts in: %s", symlink_dst.relative_to(system_test_root) + ) + else: + isctest.log.debug("deleting temporary directory") + + isctest.log.deinit_module_logger() + if not keep: + shutil.rmtree(testdir) + unlink(symlink_dst) + + +@pytest.fixture(scope="module") +def templates(system_test_dir: Path): + return isctest.template.TemplateEngine(system_test_dir) + + +def _get_node_path(node) -> Path: + if isinstance(node.parent, pytest.Session): + if _pytest_major_ver >= 8: + return Path() + return Path(node.name) + assert node.parent is not None + return _get_node_path(node.parent) / node.name + + +@pytest.fixture(scope="module") +def run_tests_sh(system_test_dir): + """Utility function to execute tests.sh as a python test.""" + + def run_tests(): + isctest.run.shell(f"{system_test_dir}/tests.sh") + + return run_tests + + +@pytest.fixture(scope="module", autouse=True) +def system_test( + request, + system_test_dir, + templates, +): + """ + Driver of the test setup/teardown process. Used automatically for every test module. + + This is the most important one-fixture-to-rule-them-all. Note the + autouse=True which causes this fixture to be loaded by every test + module without the need to explicitly specify it. + + When this fixture is used, it utilizes other fixtures, such as + system_test_dir, which handles the creation of the temporary test + directory. + + Afterwards, it checks the test environment and takes care of starting + the servers. When everything is ready, that's when the actual tests are + executed. Once that is done, this fixture stops the servers and checks + for any artifacts indicating an issue (e.g. coredumps). + + Finally, when this fixture reaches an end (or encounters an exception, + which may be caused by fail/skip invocations), any fixtures which is + used by this one are finalized - e.g. system_test_dir performs final + checks and cleans up the temporary test directory. + """ + + def check_net_interfaces(): + try: + isctest.run.perl( + f"{os.environ['srcdir']}/testsock.pl", ["-p", os.environ["PORT"]] + ) + except subprocess.CalledProcessError as exc: + isctest.log.error("testsock.pl: exited with code %d", exc.returncode) + pytest.skip("Network interface aliases not set up.") + + def check_prerequisites(): + try: + isctest.run.shell(f"{system_test_dir}/prereq.sh") + except FileNotFoundError: + pass # prereq.sh is optional + except subprocess.CalledProcessError: + pytest.skip("Prerequisites missing.") + + def setup_test(): + templates.render_auto() + try: + isctest.run.shell(f"{system_test_dir}/setup.sh") + except FileNotFoundError: + pass # setup.sh is optional + except subprocess.CalledProcessError as exc: + isctest.log.error("Failed to run test setup") + pytest.fail(f"setup.sh exited with {exc.returncode}") + + def start_servers(): + try: + isctest.run.perl( + f"{os.environ['srcdir']}/start.pl", + ["--port", os.environ["PORT"], system_test_dir.name], + ) + except subprocess.CalledProcessError as exc: + isctest.log.error("Failed to start servers") + pytest.fail(f"start.pl exited with {exc.returncode}") + + def stop_servers(): + try: + isctest.run.perl(f"{os.environ['srcdir']}/stop.pl", [system_test_dir.name]) + except subprocess.CalledProcessError as exc: + isctest.log.error("Failed to stop servers") + get_core_dumps() + pytest.fail(f"stop.pl exited with {exc.returncode}") + + def get_core_dumps(): + try: + isctest.run.shell( + f"{os.environ['srcdir']}/get_core_dumps.sh", [system_test_dir.name] + ) + except subprocess.CalledProcessError as exc: + isctest.log.error("Found core dumps or sanitizer reports") + pytest.fail(f"get_core_dumps.sh exited with {exc.returncode}") + + isctest.log.info(f"test started: {_get_node_path(request.node)}") + port = int(os.environ["PORT"]) + isctest.log.info( + "using port range: <%d, %d>", port, port + isctest.vars.ports.PORTS_PER_TEST - 1 + ) + + if not hasattr(request.node, "stash"): # compatibility with pytest<7.0.0 + request.node.stash = {} # use regular dict instead of pytest.Stash + request.node.stash[FIXTURE_OK] = True + + # Perform checks which may skip this test. + check_net_interfaces() + check_prerequisites() + + # Store the fact that this fixture hasn't successfully finished yet. + # This is checked before temporary directory teardown to decide whether + # it's okay to remove the directory. + request.node.stash[FIXTURE_OK] = False + + setup_test() + try: + start_servers() + isctest.log.debug("executing test(s)") + yield + finally: + isctest.log.debug("test(s) finished") + stop_servers() + get_core_dumps() + request.node.stash[FIXTURE_OK] = True + + +@pytest.fixture(scope="module") +def servers(system_test_dir): + instances = {} + for entry in system_test_dir.rglob("*"): + if entry.is_dir(): + try: + dir_name = entry.name + instance = isctest.instance.NamedInstance(dir_name) + instances[dir_name] = instance + except ValueError: + continue + return instances diff --git a/bin/tests/system/convert-junit-to-trs.py b/bin/tests/system/convert-junit-to-trs.py new file mode 100755 index 0000000..9675825 --- /dev/null +++ b/bin/tests/system/convert-junit-to-trs.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# Convert JUnit pytest output to automake .trs files + +import argparse +import sys +from xml.etree import ElementTree + + +def junit_to_trs(junit_xml): + root = ElementTree.fromstring(junit_xml) + testcases = root.findall(".//testcase") + + if len(testcases) < 1: + print(":test-result: ERROR convert-junit-to-trs.py") + return 99 + + has_fail = False + has_error = False + has_skipped = False + for testcase in testcases: + filename = f"{testcase.attrib['classname'].replace('.', '/')}.py" + name = f"{filename}::{testcase.attrib['name']}" + res = "PASS" + for node in testcase: + if node.tag == "failure": + res = "FAIL" + has_fail = True + elif node.tag == "error": + res = "ERROR" + has_error = True + elif node.tag == "skipped": + if node.attrib.get("type") == "pytest.xfail": + res = "XFAIL" + else: + res = "SKIP" + has_skipped = True + print(f":test-result: {res} {name}") + + if has_error: + return 99 + if has_fail: + return 1 + if has_skipped: + return 77 + return 0 + + +def main(): + parser = argparse.ArgumentParser( + description="Convert JUnit XML to Automake TRS and exit with " + "the appropriate Automake-compatible exit code." + ) + parser.add_argument( + "junit_file", + type=argparse.FileType("r", encoding="utf-8"), + help="junit xml result file", + ) + args = parser.parse_args() + + junit_xml = args.junit_file.read() + sys.exit(junit_to_trs(junit_xml)) + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/cookie/ans9/ans.py b/bin/tests/system/cookie/ans9/ans.py new file mode 100644 index 0000000..a107e93 --- /dev/null +++ b/bin/tests/system/cookie/ans9/ans.py @@ -0,0 +1,325 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns +import dns.edns +import dns.flags +import dns.message +import dns.query +import dns.tsig +import dns.tsigkeyring +import dns.version + +from dns.edns import * +from dns.name import * +from dns.rcode import * +from dns.rdataclass import * +from dns.rdatatype import * +from dns.tsig import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + + +# DNS 2.0 keyring specifies the algorithm +try: + keyring = dns.tsigkeyring.from_text( + { + "foo": {os.getenv("DEFAULT_HMAC", "hmac-sha256"), "aaaaaaaaaaaa"}, + "fake": {os.getenv("DEFAULT_HMAC", "hmac-sha256"), "aaaaaaaaaaaa"}, + } + ) +except: + keyring = dns.tsigkeyring.from_text({"foo": "aaaaaaaaaaaa", "fake": "aaaaaaaaaaaa"}) + +dopass2 = False + + +############################################################################ +# +# This server will serve valid and spoofed answers. A spoofed answer will +# have the address 10.53.0.10 included. +# +# When receiving a query over UDP: +# +# A query to "nocookie"/A will result in a spoofed answer with no cookie set. +# A query to "tcponly"/A will result in a spoofed answer with no cookie set. +# A query to "withtsig"/A will result in two responses, the first is a spoofed +# answer that is TSIG signed, the second is a valid answer with a cookie set. +# A query to anything else will result in a valid answer with a cookie set. +# +# When receiving a query over TCP: +# +# A query to "nocookie"/A will result in a valid answer with no cookie set. +# A query to anything else will result in a valid answer with a cookie set. +# +############################################################################ +def create_response(msg, tcp, first, ns10): + global dopass2 + m = dns.message.from_wire(msg, keyring=keyring) + qname = m.question[0].name.to_text() + lqname = qname.lower() + labels = lqname.split(".") + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, qname)) + print("%s %s" % (typename, qname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + if rrtype == A: + # exempt potential nameserver A records. + if labels[0] == "ns" and ns10: + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + else: + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.9")) + if not tcp and labels[0] == "nocookie": + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + if not tcp and labels[0] == "tcponly": + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + if first and not tcp and labels[0] == "withtsig": + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + dopass2 = True + elif rrtype == NS: + length = len(labels) + if length == 2: + r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, "ns." + qname)) + if ns10: + r.additional.append( + dns.rrset.from_text("ns." + qname, 1, IN, A, "10.53.0.10") + ) + else: + r.additional.append( + dns.rrset.from_text("ns." + qname, 1, IN, A, "10.53.0.9") + ) + else: + tld = ".".join(labels[length - 2 :]) + r.authority.append(dns.rrset.from_text(tld, 2, IN, SOA, ". . 0 0 0 0 2")) + elif rrtype == SOA: + r.answer.append(dns.rrset.from_text(qname, 2, IN, SOA, ". . 0 0 0 0 2")) + else: + r.authority.append(dns.rrset.from_text(qname, 2, IN, SOA, ". . 0 0 0 0 2")) + # Add a server cookie to the response + if labels[0] != "nocookie" or rrtype != A: + for o in m.options: + if o.otype == 10: # Use 10 instead of COOKIE + if first and labels[0] == "withtsig" and not tcp and rrtype == A: + r.use_tsig( + keyring=keyring, + keyname=dns.name.from_text("fake"), + algorithm=HMAC_SHA256, + ) + elif labels[0] != "tcponly" or tcp or rrtype != A: + cookie = o + try: + if len(o.server) == 0: + cookie.server = o.client + except AttributeError: # dnspython<2.7.0 compat + if len(o.data) == 8: + cookie.data = o.data + o.data + else: + cookie.data = o.data + r.use_edns(options=[cookie]) + r.flags |= dns.flags.AA + return r + + +def sigterm(signum, frame): + print("Shutting down now...") + os.remove("ans.pid") + running = False + sys.exit(0) + + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4_addr1 = "10.53.0.9" +ip4_addr2 = "10.53.0.10" +ip6_addr1 = "fd92:7065:b8e:ffff::9" +ip6_addr2 = "fd92:7065:b8e:ffff::10" + +try: + port = int(os.environ["PORT"]) +except: + port = 5300 + +query4_udp1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_udp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +query4_udp1.bind((ip4_addr1, port)) +query4_tcp1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +query4_tcp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +query4_tcp1.bind((ip4_addr1, port)) +query4_tcp1.listen(1) +query4_tcp1.settimeout(1) + +query4_udp2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_udp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +query4_udp2.bind((ip4_addr2, port)) +query4_tcp2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +query4_tcp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +query4_tcp2.bind((ip4_addr2, port)) +query4_tcp2.listen(1) +query4_tcp2.settimeout(1) + +havev6 = True +query6_udp1 = None +query6_udp2 = None +query6_tcp1 = None +query6_tcp2 = None +try: + query6_udp1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + query6_udp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + query6_udp1.bind((ip6_addr1, port)) + query6_tcp1 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + query6_tcp1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + query6_tcp1.bind((ip6_addr1, port)) + query6_tcp1.listen(1) + query6_tcp1.settimeout(1) + + query6_udp2 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + query6_udp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + query6_udp2.bind((ip6_addr2, port)) + query6_tcp2 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + query6_tcp2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + query6_tcp2.bind((ip6_addr2, port)) + query6_tcp2.listen(1) + query6_tcp2.settimeout(1) +except: + if query6_udp1 != None: + query6_udp1.close() + if query6_tcp1 != None: + query6_tcp1.close() + if query6_udp2 != None: + query6_udp2.close() + if query6_tcp2 != None: + query6_tcp2.close() + havev6 = False + +signal.signal(signal.SIGTERM, sigterm) + +f = open("ans.pid", "w") +pid = os.getpid() +print(pid, file=f) +f.close() + +running = True + +print("Using DNS version %s" % dns.version.version) +print("Listening on %s port %d" % (ip4_addr1, port)) +print("Listening on %s port %d" % (ip4_addr2, port)) +if havev6: + print("Listening on %s port %d" % (ip6_addr1, port)) + print("Listening on %s port %d" % (ip6_addr2, port)) +print("Ctrl-c to quit") + +if havev6: + input = [ + query4_udp1, + query6_udp1, + query4_tcp1, + query6_tcp1, + query4_udp2, + query6_udp2, + query4_tcp2, + query6_tcp2, + ] +else: + input = [query4_udp1, query4_tcp1, query4_udp2, query4_tcp2] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + ns10 = False + if s == query4_udp1 or s == query6_udp1 or s == query4_udp2 or s == query6_udp2: + if s == query4_udp1 or s == query6_udp1: + print( + "UDP Query received on %s" + % (ip4_addr1 if s == query4_udp1 else ip6_addr1), + end=" ", + ) + if s == query4_udp2 or s == query6_udp2: + print( + "UDP Query received on %s" + % (ip4_addr2 if s == query4_udp2 else ip6_addr2), + end=" ", + ) + ns10 = True + # Handle incoming queries + msg = s.recvfrom(65535) + dopass2 = False + rsp = create_response(msg[0], False, True, ns10) + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + if dopass2: + print("Sending second UDP response without TSIG", end=" ") + rsp = create_response(msg[0], False, False, ns10) + s.sendto(rsp.to_wire(), msg[1]) + print(dns.rcode.to_text(rsp.rcode())) + + if s == query4_tcp1 or s == query6_tcp1 or s == query4_tcp2 or s == query6_tcp2: + try: + (cs, _) = s.accept() + if s == query4_tcp1 or s == query6_tcp1: + print( + "TCP Query received on %s" + % (ip4_addr1 if s == query4_tcp1 else ip6_addr1), + end=" ", + ) + if s == query4_tcp2 or s == query6_tcp2: + print( + "TCP Query received on %s" + % (ip4_addr2 if s == query4_tcp2 else ip6_addr2), + end=" ", + ) + ns10 = True + # get TCP message length + buf = cs.recv(2) + length = struct.unpack(">H", buf[:2])[0] + # grep DNS message + msg = cs.recv(length) + rsp = create_response(msg, True, True, ns10) + print(dns.rcode.to_text(rsp.rcode())) + wire = rsp.to_wire() + cs.send(struct.pack(">H", len(wire))) + cs.send(wire) + cs.close() + except s.timeout: + pass + if not running: + break diff --git a/bin/tests/system/cookie/bad-cookie-aes.conf b/bin/tests/system/cookie/bad-cookie-aes.conf new file mode 100644 index 0000000..97a6f67 --- /dev/null +++ b/bin/tests/system/cookie/bad-cookie-aes.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + cookie-algorithm aes; + cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits +}; diff --git a/bin/tests/system/cookie/bad-cookie-badhex.conf b/bin/tests/system/cookie/bad-cookie-badhex.conf new file mode 100644 index 0000000..43c11ad --- /dev/null +++ b/bin/tests/system/cookie/bad-cookie-badhex.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + cookie-secret "012345678901234567890123456789012345678901234567890123456789012"; +}; diff --git a/bin/tests/system/cookie/bad-cookie-badsiphash24.conf b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf new file mode 100644 index 0000000..25ff78f --- /dev/null +++ b/bin/tests/system/cookie/bad-cookie-badsiphash24.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + cookie-algorithm siphash24; + cookie-secret "ebc7701beabb4a40c57d140eeb6733faaabbccdd"; // 160 bits +}; diff --git a/bin/tests/system/cookie/bad-cookie-toolong.conf b/bin/tests/system/cookie/bad-cookie-toolong.conf new file mode 100644 index 0000000..5ea67b9 --- /dev/null +++ b/bin/tests/system/cookie/bad-cookie-toolong.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + cookie-secret "01234567890123456789012345678901234567890123456789012345678901234567890"; +}; diff --git a/bin/tests/system/cookie/good-cookie-siphash24.conf b/bin/tests/system/cookie/good-cookie-siphash24.conf new file mode 100644 index 0000000..c937d71 --- /dev/null +++ b/bin/tests/system/cookie/good-cookie-siphash24.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + cookie-algorithm siphash24; + cookie-secret "ebc7701beabb4a40c57d140eeb6733fa"; // 128 bits +}; diff --git a/bin/tests/system/cookie/ns1/example.db b/bin/tests/system/cookie/ns1/example.db new file mode 100644 index 0000000..75a6d3c --- /dev/null +++ b/bin/tests/system/cookie/ns1/example.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns1 hostmaster.isc.org. 1 600 600 1200 600 +@ NS ns1 +ns1 A 10.53.0.1 +large TXT ( large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large ) diff --git a/bin/tests/system/cookie/ns1/named.conf.j2 b/bin/tests/system/cookie/ns1/named.conf.j2 new file mode 100644 index 0000000..0bd93c9 --- /dev/null +++ b/bin/tests/system/cookie/ns1/named.conf.j2 @@ -0,0 +1,62 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key foo { + secret "aaaaaaaaaaaa"; + algorithm @DEFAULT_HMAC@; +}; + +server 10.53.0.10 { + keys foo; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } + except-from { "example.org"; }; + deny-answer-aliases { "example.org"; } + except-from { "goodcname.example.net"; + "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; + send-cookie yes; + nocookie-udp-size 512; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/cookie/ns1/root.hint b/bin/tests/system/cookie/ns1/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/cookie/ns1/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/cookie/ns2/named.conf.j2 b/bin/tests/system/cookie/ns2/named.conf.j2 new file mode 100644 index 0000000..cd74d8a --- /dev/null +++ b/bin/tests/system/cookie/ns2/named.conf.j2 @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + send-cookie yes; + nocookie-udp-size 512; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/cookie/ns2/root.db b/bin/tests/system/cookie/ns2/root.db new file mode 100644 index 0000000..533ab88 --- /dev/null +++ b/bin/tests/system/cookie/ns2/root.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.2 +large.xxx TXT ( large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large ) +tld. NS ns.tld. +ns.tld A 10.53.0.9 +tsig. NS ns.tsig. +ns.tsig A 10.53.0.10 diff --git a/bin/tests/system/cookie/ns3/named.conf.j2 b/bin/tests/system/cookie/ns3/named.conf.j2 new file mode 100644 index 0000000..cbebd07 --- /dev/null +++ b/bin/tests/system/cookie/ns3/named.conf.j2 @@ -0,0 +1,54 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } + except-from { "example.org"; }; + deny-answer-aliases { "example.org"; } + except-from { "goodcname.example.net"; + "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; + send-cookie yes; + nocookie-udp-size 512; + require-server-cookie yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/cookie/ns3/root.hint b/bin/tests/system/cookie/ns3/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/cookie/ns3/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/cookie/ns4/named.conf.j2 b/bin/tests/system/cookie/ns4/named.conf.j2 new file mode 100644 index 0000000..592be13 --- /dev/null +++ b/bin/tests/system/cookie/ns4/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + cookie-algorithm siphash24; + cookie-secret "569d36a6cc27d6bf55502183302ba352"; + require-server-cookie yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/cookie/ns4/root.hint b/bin/tests/system/cookie/ns4/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/cookie/ns4/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/cookie/ns5/named.conf.j2 b/bin/tests/system/cookie/ns5/named.conf.j2 new file mode 100644 index 0000000..2f51e1b --- /dev/null +++ b/bin/tests/system/cookie/ns5/named.conf.j2 @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + cookie-algorithm siphash24; + cookie-secret "569d36a6cc27d6bf55502183302ba352"; + cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; + require-server-cookie yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/cookie/ns5/root.hint b/bin/tests/system/cookie/ns5/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/cookie/ns5/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/cookie/ns6/named.conf.j2 b/bin/tests/system/cookie/ns6/named.conf.j2 new file mode 100644 index 0000000..56c5e04 --- /dev/null +++ b/bin/tests/system/cookie/ns6/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + cookie-algorithm siphash24; + cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; + require-server-cookie yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/cookie/ns6/root.hint b/bin/tests/system/cookie/ns6/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/cookie/ns6/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/cookie/ns7/from-no-cookie-server.example.db b/bin/tests/system/cookie/ns7/from-no-cookie-server.example.db new file mode 100644 index 0000000..8e466a6 --- /dev/null +++ b/bin/tests/system/cookie/ns7/from-no-cookie-server.example.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns7 hostmaster.isc.org. 1 600 600 1200 600 +@ NS ns7 +ns7 A 10.53.0.7 diff --git a/bin/tests/system/cookie/ns7/named.conf.j2 b/bin/tests/system/cookie/ns7/named.conf.j2 new file mode 100644 index 0000000..9426d23 --- /dev/null +++ b/bin/tests/system/cookie/ns7/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion no; + answer-cookie no; + send-cookie yes; + nocookie-udp-size 512; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "from-no-cookie-server.example" { + type primary; + file "from-no-cookie-server.example.db"; +}; diff --git a/bin/tests/system/cookie/ns7/root.db b/bin/tests/system/cookie/ns7/root.db new file mode 100644 index 0000000..39a63da --- /dev/null +++ b/bin/tests/system/cookie/ns7/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA a.root-servers.nil. hostmaster.isc.org. 1 600 600 1200 600 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.2 +large.xxx TXT ( large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large + large large large large large large large large ) diff --git a/bin/tests/system/cookie/ns8/example.db b/bin/tests/system/cookie/ns8/example.db new file mode 100644 index 0000000..443d5db --- /dev/null +++ b/bin/tests/system/cookie/ns8/example.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA . . 0 0 0 0 0 +@ 3600 NS . +from-no-cookie-server 3600 NS ns7.from-no-cookie-server +ns7.from-no-cookie-server 3600 A 10.53.0.7 diff --git a/bin/tests/system/cookie/ns8/named.conf.j2 b/bin/tests/system/cookie/ns8/named.conf.j2 new file mode 100644 index 0000000..36f052b --- /dev/null +++ b/bin/tests/system/cookie/ns8/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + dnssec-validation yes; + rate-limit {}; + require-server-cookie yes; +}; + +trust-anchors { }; + +server 10.53.0.7 { require-cookie yes; }; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/cookie/prereq.sh b/bin/tests/system/cookie/prereq.sh new file mode 100644 index 0000000..b6b005f --- /dev/null +++ b/bin/tests/system/cookie/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/cookie/tests.sh b/bin/tests/system/cookie/tests.sh new file mode 100755 index 0000000..3de9185 --- /dev/null +++ b/bin/tests/system/cookie/tests.sh @@ -0,0 +1,587 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +status=0 +n=0 + +getcookie() { + awk '$2 == "COOKIE:" { + print $3; + }' <$1 +} + +fullcookie() { + awk 'BEGIN { n = 0 } + // { v[n++] = length(); } + END { print (v[1] == v[2]); }' +} + +havetc() { + grep 'flags:.* tc[^;]*;' $1 >/dev/null +} + +for bad in bad*.conf; do + n=$((n + 1)) + echo_i "checking that named-checkconf detects error in $bad ($n)" + ret=0 + $CHECKCONF $bad >/dev/null 2>&1 && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for good in good*.conf; do + n=$((n + 1)) + echo_i "checking that named-checkconf detects accepts $good ($n)" + ret=0 + $CHECKCONF $good >/dev/null 2>&1 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +n=$((n + 1)) +echo_i "checking RCODE=FORMERR to query without question section and without COOKIE option ($n)" +ret=0 +$DIG $DIGOPTS +qr +header-only +nocookie version.bind txt ch @10.53.0.1 >dig.out.test$n || ret=1 +grep COOKIE: dig.out.test$n >/dev/null && ret=1 +grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking RCODE=NOERROR to query without question section and with COOKIE option ($n)" +ret=0 +$DIG $DIGOPTS +qr +header-only +cookie version.bind txt ch @10.53.0.1 >dig.out.test$n || ret=1 +grep COOKIE: dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking COOKIE token is returned to empty COOKIE option ($n)" +ret=0 +$DIG $DIGOPTS +cookie version.bind txt ch @10.53.0.1 >dig.out.test$n || ret=1 +grep COOKIE: dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking COOKIE is not returned when answer-cookie is false ($n)" +ret=0 +oldcookie=b71d3138bb984fc50100000064a65cffbbf02482dfb99ba5 +$DIG $DIGOPTS +cookie=$oldcookie version.bind txt ch @10.53.0.7 >dig.out.test$n || ret=1 +grep COOKIE: dig.out.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking response size without COOKIE ($n)" +ret=0 +$DIG $DIGOPTS large.example txt @10.53.0.1 +ignore >dig.out.test$n || ret=1 +havetc dig.out.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking response size without valid COOKIE ($n)" +ret=0 +$DIG $DIGOPTS +cookie large.example txt @10.53.0.1 +ignore >dig.out.test$n || ret=1 +havetc dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking response size with COOKIE ($n)" +ret=0 +$DIG $DIGOPTS +cookie large.example txt @10.53.0.1 >dig.out.test$n.l || ret=1 +cookie=$(getcookie dig.out.test$n.l) +$DIG $DIGOPTS +qr +cookie=$cookie large.example txt @10.53.0.1 +ignore >dig.out.test$n || ret=1 +havetc dig.out.test$n && ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking response size with COOKIE recursive ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=$cookie large.xxx txt @10.53.0.1 +ignore >dig.out.test$n || ret=1 +havetc dig.out.test$n && ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking COOKIE is learnt for TCP retry ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie large.example txt @10.53.0.1 >dig.out.test$n || ret=1 +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $linecount != 3 ]; then ret=1; fi +checkfull=$(getcookie dig.out.test$n | fullcookie) +if [ $checkfull != 1 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking for COOKIE value in adb ($n)" +ret=0 +rndc_dumpdb ns1 +grep "10.53.0.2.*\[cookie=" ns1/named_dump.db.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking require-server-cookie default (no) ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie +nobadcookie soa @10.53.0.1 >dig.out.test$n || ret=1 +grep "status: BADCOOKIE" dig.out.test$n >/dev/null && ret=1 +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $linecount != 2 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking require-server-cookie yes ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie +nobadcookie soa @10.53.0.3 >dig.out.test$n || ret=1 +grep "flags: qr[^;]* aa[ ;]" dig.out.test$n >/dev/null && ret=1 +grep "flags: qr[^;]* ad[ ;]" dig.out.test$n >/dev/null && ret=1 +grep "status: BADCOOKIE" dig.out.test$n >/dev/null || ret=1 +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $linecount != 2 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking +qr +showbadcookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie +showbadcookie soa @10.53.0.3 >dig.out.test$n || ret=1 +noerror=$(grep "status: NOERROR" dig.out.test$n | wc -l) +badcookie=$(grep "status: BADCOOKIE" dig.out.test$n | wc -l) +server=$(grep "COOKIE: ................................................" dig.out.test$n | wc -l) +good=$(grep "COOKIE: ................................................ (good)" dig.out.test$n | wc -l) +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $noerror != 3 ]; then ret=1; fi +if [ $badcookie != 1 ]; then ret=1; fi +if [ $server != 3 ]; then ret=1; fi +if [ $good != 2 ]; then ret=1; fi +if [ $linecount != 4 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "checking +showbadcookie ($n)" +ret=0 +$DIG $DIGOPTS +cookie +showbadcookie soa @10.53.0.3 >dig.out.test$n || ret=1 +noerror=$(grep "status: NOERROR" dig.out.test$n | wc -l) +badcookie=$(grep "status: BADCOOKIE" dig.out.test$n | wc -l) +server=$(grep "COOKIE: ................................................" dig.out.test$n | wc -l) +good=$(grep "COOKIE: ................................................ (good)" dig.out.test$n | wc -l) +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $noerror != 1 ]; then ret=1; fi +if [ $badcookie != 1 ]; then ret=1; fi +if [ $server != 2 ]; then ret=1; fi +if [ $good != 2 ]; then ret=1; fi +if [ $linecount != 2 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking require-server-cookie yes with rate-limit ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie +nobadcookie soa example @10.53.0.8 >dig.out.test$n || ret=1 +grep "flags: qr[^;]* ad[ ;]" dig.out.test$n >/dev/null && ret=1 +grep "status: BADCOOKIE" dig.out.test$n >/dev/null || ret=1 +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $linecount != 2 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking 'server { require-cookie yes; };' triggers TCP when cookie not returned ($n)" +ret=0 +nextpart ns8/named.run >/dev/null +$DIG $DIGOPTS +cookie soa from-no-cookie-server.example @10.53.0.8 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +wait_for_log_peek 3 "missing required cookie from 10.53.0.7#" ns8/named.run || ret=1 +wait_for_log_peek 3 "connected from" ns8/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "send undersized cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=000000 soa @10.53.0.1 >dig.out.test$n || ret=1 +grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "send oversized for named cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.1 >dig.out.test$n || ret=1 +grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "send oversized for named cookie with server requiring a good cookie ($n)" +ret=0 +$DIG $DIGOPTS +qr +cookie=${cookie}00 soa @10.53.0.3 >dig.out.test$n || ret=1 +grep "COOKIE: [a-f0-9]* (good)" dig.out.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that BADCOOKIE is returned for a bad server COOKIE ($n)" +ret=0 +badcookie=$(echo $cookie | sed 's/[a-f0-9]/0/g') +$DIG $DIGOPTS +qr +cookie=$badcookie +nobadcookie soa example @10.53.0.1 >dig.out.test$n || ret=1 +grep "flags: qr[^;]* ad[ ;]" dig.out.test$n >/dev/null && ret=1 +grep "status: BADCOOKIE" dig.out.test$n >/dev/null || ret=1 +linecount=$(getcookie dig.out.test$n | wc -l) +if [ $linecount != 2 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Test shared cookie-secret support. +# +# NS4 has cookie-secret "569d36a6cc27d6bf55502183302ba352"; +# +# NS5 has cookie-secret "569d36a6cc27d6bf55502183302ba352"; +# NS5 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; (alternate) +# +# NS6 has cookie-secret "6b300e27a0db46d4b046e4189790fa7d"; +# +# Server cookies from NS4 are accepted by NS5 and not NS6 +# Server cookies from NS5 are accepted by NS4 and not NS6 +# Server cookies from NS6 are accepted by NS5 and not NS4 +# +# Force local address so that the client's address is the same to all servers. +# + +n=$((n + 1)) +echo_i "get NS4 cookie for cross server checking ($n)" +ret=0 +$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.4 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +ns4cookie=$(getcookie dig.out.test$n) +test -n "$ns4cookie" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "get NS5 cookie for cross server checking ($n)" +ret=0 +$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.5 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +ns5cookie=$(getcookie dig.out.test$n) +test -n "$ns5cookie" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "get NS6 cookie for cross server checking ($n)" +ret=0 +$DIG $DIGOPTS +cookie -b 10.53.0.4 soa . @10.53.0.6 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +ns6cookie=$(getcookie dig.out.test$n) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS4 cookie on NS5 (expect success) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns4cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.5 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS4 cookie on NS6 (expect badcookie) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns4cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.6 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: BADCOOKIE," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS5 cookie on NS4 (expect success) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns5cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS5 cookie on NS6 (expect badcookie) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns5cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.6 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: BADCOOKIE," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS6 cookie on NS4 (expect badcookie) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: BADCOOKIE," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS6 cookie on NS5 (expect success) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.5 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Restart NS4 with -T cookiealwaysvalid ($n)" +stop_server ns4 +touch ns4/named.cookiealwaysvalid +start_server --noclean --restart --port ${PORT} ns4 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test NS6 cookie on NS4 with -T cookiealwaysvalid (expect success) ($n)" +ret=0 +$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 >dig.out.test$n || ret=1 +grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that test server is correctly configured ($n)" +ret=0 +pat="; COOKIE: ................................ (good)" +#UDP +$DIG $DIGOPTS @10.53.0.9 +notcp tld >dig.out.test$n.1 || ret=1 +grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 +grep "$pat" dig.out.test$n.1 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.1 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.1 >/dev/null && ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +notcp tcponly.tld >dig.out.test$n.2 || ret=1 +grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 +grep "; COOKIE:" dig.out.test$n.2 >/dev/null && ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null || ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +notcp nocookie.tld >dig.out.test$n.3 || ret=1 +grep "status: NOERROR" dig.out.test$n.3 >/dev/null || ret=1 +grep "; COOKIE:" dig.out.test$n.3 >/dev/null && ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.3 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.3 >/dev/null || ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +notcp withtsig.tld >dig.out.test$n.4 || ret=1 +grep "status: NOERROR" dig.out.test$n.4 >/dev/null || ret=1 +grep "; COOKIE:" dig.out.test$n.4 >/dev/null && ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.4 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.4 >/dev/null || ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.4 >/dev/null || ret=1 + +#TCP +$DIG $DIGOPTS @10.53.0.9 +tcp tld >dig.out.test$n.5 || ret=1 +grep "status: NOERROR" dig.out.test$n.5 >/dev/null || ret=1 +grep "$pat" dig.out.test$n.5 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.5 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.5 >/dev/null && ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +tcp tcponly.tld >dig.out.test$n.6 || ret=1 +grep "status: NOERROR" dig.out.test$n.6 >/dev/null || ret=1 +grep "$pat" dig.out.test$n.6 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.6 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.6 >/dev/null && ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +tcp nocookie.tld >dig.out.test$n.7 || ret=1 +grep "status: NOERROR" dig.out.test$n.7 >/dev/null || ret=1 +grep "; COOKIE:" dig.out.test$n.7 >/dev/null && ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.7 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.7 >/dev/null && ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.1 >/dev/null && ret=1 + +$DIG $DIGOPTS @10.53.0.9 +tcp withtsig.tld >dig.out.test$n.8 || ret=1 +grep "status: NOERROR" dig.out.test$n.8 >/dev/null || ret=1 +grep "$pat" dig.out.test$n.8 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.8 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.8 >/dev/null && ret=1 +grep ";; TSIG PSEUDOSECTION:" dig.out.test$n.8 >/dev/null && ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that spoofed response is dropped when we have a server cookie ($n)" +ret=0 +msg="missing expected cookie from" +pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl' +# prime EDNS COOKIE state +$DIG $DIGOPTS @10.53.0.1 tld >dig.out.test$n.1 || ret=1 +grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 +rndc_dumpdb ns1 +grep "$pat" ns1/named_dump.db.test$n >/dev/null || ret=1 +# spoofed response contains 10.53.0.10 +nextpart ns1/named.run >/dev/null +$DIG $DIGOPTS @10.53.0.1 tcponly.tld >dig.out.test$n.2 || ret=1 +wait_for_log 5 "$msg" ns1/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that gracefully handle server disabling DNS COOKIE we have a server cookie ($n)" +ret=0 +msg="missing expected cookie from" +pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl' +# prime EDNS COOKIE state +$DIG $DIGOPTS @10.53.0.1 tld >dig.out.test$n.1 || ret=1 +grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 +rndc_dumpdb ns1 +grep "$pat" ns1/named_dump.db.test$n >/dev/null || ret=1 +# check the disabled server response +nextpart ns1/named.run >/dev/null +$DIG $DIGOPTS @10.53.0.1 nocookie.tld >dig.out.test$n.2 || ret=1 +wait_for_log 5 "$msg" ns1/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that spoofed response with a TSIG is dropped when we have a server cookie ($n)" +ret=0 +pat='10\.53\.0\.9 .*\[cookie=................................\] \[ttl' +# prime EDNS COOKIE state +$DIG $DIGOPTS @10.53.0.1 tld >dig.out.test$n.1 || ret=1 +grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 +rndc_dumpdb ns1 +grep "$pat" ns1/named_dump.db.test$n >/dev/null || ret=1 +# spoofed response contains 10.53.0.10 +nextpart ns1/named.run >/dev/null +$DIG $DIGOPTS @10.53.0.1 withtsig.tld >dig.out.test$n.2 || ret=1 +grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null && ret=1 +nextpart ns1/named.run >named.run.test$n +count=$(grep -c ') [0-9][0-9]* NOERROR 0' named.run.test$n) +test $count -eq 1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if $PYTHON -c ' +import dns.version, sys; +if dns.version.MAJOR > 1: sys.exit(0); +if dns.version.MAJOR == 1 and dns.version.MINOR >= 16: sys.exit(0); +sys.exit(1)'; then + n=$((n + 1)) + echo_i "check that TSIG test server is correctly configured ($n)" + ret=0 + pat="; COOKIE: ................................ (good)" + key="${DEFAULT_HMAC}:foo:aaaaaaaaaaaa" + #UDP + $DIG $DIGOPTS @10.53.0.10 -y $key +notcp tsig. >dig.out.test$n.1 || ret=1 + grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 + grep "$pat" dig.out.test$n.1 >/dev/null || ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.1 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.1 >/dev/null && ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + $DIG $DIGOPTS @10.53.0.10 -y $key +notcp tcponly.tsig >dig.out.test$n.2 || ret=1 + grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 + grep "; COOKIE:" dig.out.test$n.2 >/dev/null && ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null || ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + $DIG $DIGOPTS @10.53.0.10 -y $key +notcp nocookie.tsig >dig.out.test$n.3 || ret=1 + grep "status: NOERROR" dig.out.test$n.3 >/dev/null || ret=1 + grep "; COOKIE:" dig.out.test$n.3 >/dev/null && ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.3 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.3 >/dev/null || ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + #TCP + $DIG $DIGOPTS @10.53.0.10 -y $key +tcp tsig. >dig.out.test$n.5 || ret=1 + grep "status: NOERROR" dig.out.test$n.5 >/dev/null || ret=1 + grep "$pat" dig.out.test$n.5 >/dev/null || ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.5 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.5 >/dev/null && ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + $DIG $DIGOPTS @10.53.0.10 -y $key +tcp tcponly.tsig >dig.out.test$n.6 || ret=1 + grep "status: NOERROR" dig.out.test$n.6 >/dev/null || ret=1 + grep "$pat" dig.out.test$n.6 >/dev/null || ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.6 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.6 >/dev/null && ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + $DIG $DIGOPTS @10.53.0.10 -y $key +tcp nocookie.tsig >dig.out.test$n.7 || ret=1 + grep "status: NOERROR" dig.out.test$n.7 >/dev/null || ret=1 + grep "; COOKIE:" dig.out.test$n.7 >/dev/null && ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.7 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.7 >/dev/null && ret=1 + grep 'TSIG.*NOERROR' dig.out.test$n.1 >/dev/null || ret=1 + + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that missing COOKIE with a valid TSIG signed response does not trigger TCP fallback ($n)" + ret=0 + pat='10\.53\.0\.10 .*\[cookie=................................\] \[ttl' + # prime EDNS COOKIE state + $DIG $DIGOPTS @10.53.0.1 tsig. >dig.out.test$n.1 || ret=1 + grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1 + rndc_dumpdb ns1 + grep "$pat" ns1/named_dump.db.test$n >/dev/null || ret=1 + # check the disabled server response + nextpart ns1/named.run >/dev/null + $DIG $DIGOPTS @10.53.0.1 nocookie.tsig >dig.out.test$n.2 || ret=1 + grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1 + grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1 + grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null || ret=1 + nextpart ns1/named.run >named.run.test$n + count=$(grep -c ') [0-9][0-9]* NOERROR 0' named.run.test$n) + test $count -eq 2 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/cookie/tests_sh_cookie.py b/bin/tests/system/cookie/tests_sh_cookie.py new file mode 100644 index 0000000..1c9e828 --- /dev/null +++ b/bin/tests/system/cookie/tests_sh_cookie.py @@ -0,0 +1,28 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "named.run.*", + "rndc.out.*", + "ans*/ans.run", + "ans*/query.log", + "ns1/named_dump.db*", + "ns4/named.cookiealwaysvalid", + ] +) + + +def test_cookie(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/cpu/ns1/named.conf.j2 b/bin/tests/system/cpu/ns1/named.conf.j2 new file mode 100644 index 0000000..6c934b2 --- /dev/null +++ b/bin/tests/system/cpu/ns1/named.conf.j2 @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; +}; diff --git a/bin/tests/system/cpu/prereq.sh b/bin/tests/system/cpu/prereq.sh new file mode 100644 index 0000000..7f9f6c0 --- /dev/null +++ b/bin/tests/system/cpu/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +command -v cpuset >/dev/null || command -v numactl >/dev/null || command -v taskset >/dev/null || { + echo_i "This test requires cpuset, numactl, or taskset." >&2 + exit 255 +} + +exit 0 diff --git a/bin/tests/system/cpu/tests.sh b/bin/tests/system/cpu/tests.sh new file mode 100755 index 0000000..a521b4f --- /dev/null +++ b/bin/tests/system/cpu/tests.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +status=0 +n=0 + +CPUSET=$(command -v cpuset) +NUMACTL=$(command -v numactl) +TASKSET=$(command -v taskset) + +cpulist() ( + if [ -n "$CPUSET" ]; then + cpuset -g | head -1 | sed -e "s/.*: //" | tr -s ', ' '\n' + elif [ -n "$NUMACTL" ]; then + numactl --show | sed -ne 's/^physcpubind: //p' | tr -s ' ' '\n' + elif [ -n "$TASKSET" ]; then + # shellcheck disable=SC2046 + seq $(taskset -c -p $$ | sed -e 's/.*: //' | tr -s ' -' ' ') + else + echo 0 + fi +) + +cpulimit() ( + set -x + min_cpu="${1}" + shift + max_cpu="${1}" + shift + + if [ -n "$CPUSET" ]; then + cpuset -l "${min_cpu}-${max_cpu}" "$@" 2>&1 + elif [ -n "$NUMACTL" ]; then + numactl --physcpubind="${min_cpu}-${max_cpu}" "$@" 2>&1 + elif [ -n "$TASKSET" ]; then + taskset -c "${min_cpu}-${max_cpu}" "$@" 2>&1 + fi +) + +ret=0 +for cpu in $(cpulist); do + n=$((n + 1)) + echo_i "testing that limiting CPU sets to 0-${cpu} works ($n)" + cpulimit 0 "$cpu" "$NAMED" -g >named.run.$n 2>&1 || true + ncpus=$(sed -ne 's/.*found \([0-9]*\) CPU.*\([0-9]*\) worker thread.*/\1/p' named.run.$n) + [ "$ncpus" -eq "$((cpu + 1))" ] || ret=1 +done +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/cpu/tests_sh_cpu.py b/bin/tests/system/cpu/tests_sh_cpu.py new file mode 100644 index 0000000..f2f30c6 --- /dev/null +++ b/bin/tests/system/cpu/tests_sh_cpu.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "named.run.*", + "ns1/managed-keys.*", + ] +) + + +def test_cpu(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/custom-test-driver b/bin/tests/system/custom-test-driver new file mode 100755 index 0000000..278cb37 --- /dev/null +++ b/bin/tests/system/custom-test-driver @@ -0,0 +1,189 @@ +#!/bin/sh + +# test-driver - basic testsuite driver script. + +scriptversion=2021-09-20.08 # UTC + +# Copyright (C) 2011-2020 Free Software Foundation, Inc. +# +# SPDX-License-Identifier: GPL-2.0-or-later WITH Autoconf-exception-generic +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error() { + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage() { + cat <&1 | tee $log_file +else + "$@" --junit-xml $PWD/$junit_file >$log_file 2>&1 +fi + +# Run junit to trs converter script. +./convert-junit-to-trs.py $junit_file >$trs_file +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes ;; + 0:*) col=$grn res=PASS recheck=no gcopy=no ;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes ;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes ;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes ;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes ;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register other relevant test metadata. +echo ":global-test-result: $res" >>$trs_file +echo ":recheck: $recheck" >>$trs_file +echo ":copy-in-global-log: $gcopy" >>$trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/bin/tests/system/database/ns1/named.conf.j2 b/bin/tests/system/database/ns1/named.conf.j2 new file mode 100644 index 0000000..059a155 --- /dev/null +++ b/bin/tests/system/database/ns1/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "database" { + type primary; + database "_builtin empty localhost. @rname | default('hostmaster.isc.org.')@"; +}; diff --git a/bin/tests/system/database/tests_database.py b/bin/tests/system/database/tests_database.py new file mode 100644 index 0000000..476b81d --- /dev/null +++ b/bin/tests/system/database/tests_database.py @@ -0,0 +1,43 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import isctest + +import dns.message + + +def test_database(servers, templates): + msg = dns.message.make_query("database.", "SOA") + + # checking pre reload zone + res = isctest.query.tcp(msg, "10.53.0.1") + assert res.answer[0] == dns.rrset.from_text( + "database.", + 86400, + "IN", + "SOA", + "localhost. hostmaster.isc.org. 0 28800 7200 604800 86400", + ) + + templates.render("ns1/named.conf", {"rname": "marka.isc.org."}) + with servers["ns1"].watch_log_from_here() as watcher: + servers["ns1"].rndc("reload") + watcher.wait_for_line("all zones loaded") + + # checking post reload zone + res = isctest.query.tcp(msg, "10.53.0.1") + assert res.answer[0] == dns.rrset.from_text( + "database.", + 86400, + "IN", + "SOA", + "localhost. marka.isc.org. 0 28800 7200 604800 86400", + ) diff --git a/bin/tests/system/dialup/ns1/example.db b/bin/tests/system/dialup/ns1/example.db new file mode 100644 index 0000000..3ce33f9 --- /dev/null +++ b/bin/tests/system/dialup/ns1/example.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA hostmaster.ns1 ns1 ( + 1 3600 1200 3600000 1200 ) + NS ns1.example. + NS ns2.example. + NS ns3.example. +ns1 A 10.53.0.1 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/dialup/ns1/named.conf.in b/bin/tests/system/dialup/ns1/named.conf.in new file mode 100644 index 0000000..75a497b --- /dev/null +++ b/bin/tests/system/dialup/ns1/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + heartbeat-interval 1; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example." { + type primary; + notify explicit; + also-notify { 10.53.0.2; }; + dialup yes; + file "example.db"; +}; diff --git a/bin/tests/system/dialup/ns1/root.db b/bin/tests/system/dialup/ns1/root.db new file mode 100644 index 0000000..882da96 --- /dev/null +++ b/bin/tests/system/dialup/ns1/root.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 3600 SOA hostmaster.ns1.example ns1.example ( + 1 3600 1200 3600000 1200 ) + NS ns1.example +example NS ns1.example + NS ns2.example + NS ns3.example +ns1.example A 10.53.0.1 +ns2.example A 10.53.0.2 +ns3.example A 10.53.0.3 diff --git a/bin/tests/system/dialup/ns2/hint.db b/bin/tests/system/dialup/ns2/hint.db new file mode 100644 index 0000000..0198f25 --- /dev/null +++ b/bin/tests/system/dialup/ns2/hint.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 1200 NS ns1.example +ns1.example A 10.53.0.1 diff --git a/bin/tests/system/dialup/ns2/named.conf.in b/bin/tests/system/dialup/ns2/named.conf.in new file mode 100644 index 0000000..495e267 --- /dev/null +++ b/bin/tests/system/dialup/ns2/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + heartbeat-interval 1; + recursion no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "hint.db"; +}; + +zone "example." { + type secondary; + dialup passive; + notify no; + file "example.bk"; + primaries { 10.53.0.1; }; +}; diff --git a/bin/tests/system/dialup/ns3/hint.db b/bin/tests/system/dialup/ns3/hint.db new file mode 100644 index 0000000..0198f25 --- /dev/null +++ b/bin/tests/system/dialup/ns3/hint.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 1200 NS ns1.example +ns1.example A 10.53.0.1 diff --git a/bin/tests/system/dialup/ns3/named.conf.in b/bin/tests/system/dialup/ns3/named.conf.in new file mode 100644 index 0000000..31b9a12 --- /dev/null +++ b/bin/tests/system/dialup/ns3/named.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + heartbeat-interval 1; + recursion no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "hint.db"; +}; + +zone "example." { + type secondary; + dialup refresh; + notify no; + file "example.bk"; + primaries { 10.53.0.2; }; +}; diff --git a/bin/tests/system/dialup/setup.sh b/bin/tests/system/dialup/setup.sh new file mode 100644 index 0000000..dad3589 --- /dev/null +++ b/bin/tests/system/dialup/setup.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf diff --git a/bin/tests/system/dialup/tests_dialup_zone_transfer.py b/bin/tests/system/dialup/tests_dialup_zone_transfer.py new file mode 100644 index 0000000..4ac0897 --- /dev/null +++ b/bin/tests/system/dialup/tests_dialup_zone_transfer.py @@ -0,0 +1,39 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.message +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns2/example.bk", + "ns3/example.bk", + ] +) + + +@pytest.mark.parametrize("ns", [2, 3]) +def test_dialup_zone_transfer(named_port, servers, ns): + msg = dns.message.make_query("example.", "SOA") + # Drop the RD flag from the query + msg.flags &= ~dns.flags.RD + ns1response = isctest.query.tcp(msg, "10.53.0.1") + with servers[f"ns{ns}"].watch_log_from_start() as watcher: + watcher.wait_for_line( + f"transfer of 'example/IN' from 10.53.0.{ns-1}#{named_port}: Transfer status: success", + timeout=90, + ) + response = isctest.query.tcp(msg, f"10.53.0.{ns}") + if response.rcode() != dns.rcode.SERVFAIL: + assert response.answer == ns1response.answer + assert response.authority == ns1response.authority diff --git a/bin/tests/system/digcomp.pl b/bin/tests/system/digcomp.pl new file mode 100644 index 0000000..8024dea --- /dev/null +++ b/bin/tests/system/digcomp.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Compare two files, each with the output from dig, for differences. +# Ignore "unimportant" differences, like ordering of NS lines, TTL's, +# etc... + +$lc = 0; +if ($ARGV[0] eq "--lc") { + $lc = 1; + shift; +} +$file1 = $ARGV[0]; +$file2 = $ARGV[1]; + +$count = 0; +$firstname = ""; +$status = 0; +$rcode1 = "none"; +$rcode2 = "none"; + +open(FILE1, $file1) || die("open: $file1: $!\n"); +while () { + ~ s/\r\n//g; + ~ s/\n//g; + if (/^;.+status:\s+(\S+).+$/) { + $rcode1 = $1; + } + next if (/^;/); + if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) { + $name = $1; + $class = $2; + $type = $3; + $value = $4; + if ($lc) { + $name = lc($name); + $value = lc($value); + } + if ($type eq "SOA") { + $firstname = $name if ($firstname eq ""); + if ($name eq $firstname) { + $name = "$name$count"; + $count++; + } + } + if ($entry{"$name ; $class.$type ; $value"} ne "") { + $line = $entry{"$name ; $class.$type ; $value"}; + print("Duplicate entry in $file1:\n> $_\n< $line\n"); + } else { + $entry{"$name ; $class.$type ; $value"} = $_; + } + } elsif (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s*$/) { + $name = $1; + $class = $2; + $type = $3; + $value = ""; + if ($lc) { + $name = lc($name); + $value = lc($value); + } + if ($type eq "SOA") { + $firstname = $name if ($firstname eq ""); + if ($name eq $firstname) { + $name = "$name$count"; + $count++; + } + } + if ($entry{"$name ; $class.$type ; $value"} ne "") { + $line = $entry{"$name ; $class.$type ; $value"}; + print("Duplicate entry in $file1:\n> $_\n< $line\n"); + } else { + $entry{"$name ; $class.$type ; $value"} = $_; + } + } +} +close(FILE1); + +$printed = 0; + +open(FILE2, $file2) || die("open: $file2: $!\n"); +while () { + ~ s/\r\n//g; + ~ s/\n//g; + if (/^;.+status:\s+(\S+).+$/) { + $rcode2 = $1; + } + next if (/^;/); + if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) { + $name = $1; + $class = $2; + $type = $3; + $value = $4; + if ($lc) { + $name = lc($name); + $value = lc($value); + } + if (($name eq $firstname) && ($type eq "SOA")) { + $count--; + $name = "$name$count"; + } + if ($entry{"$name ; $class.$type ; $value"} ne "") { + $entry{"$name ; $class.$type ; $value"} = ""; + } else { + print("Only in $file2 (missing from $file1):\n") + if ($printed == 0); + print("> $_\n"); + $printed++; + $status = 1; + } + } elsif (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s*$/) { + $name = $1; + $class = $2; + $type = $3; + $value = ""; + if ($lc) { + $name = lc($name); + $value = lc($value); + } + if (($name eq $firstname) && ($type eq "SOA")) { + $count--; + $name = "$name$count"; + } + if ($entry{"$name ; $class.$type ; $value"} ne "") { + $entry{"$name ; $class.$type ; $value"} = ""; + } else { + print("Only in $file2 (missing from $file1):\n") + if ($printed == 0); + print("> $_\n"); + $printed++; + $status = 1; + } + } +} +close(FILE2); + +$printed = 0; + +foreach $key (keys(%entry)) { + if ($entry{$key} ne "") { + print("Only in $file1 (missing from $file2):\n") + if ($printed == 0); + print("< $entry{$key}\n"); + $status = 1; + $printed++; + } +} + +if ($rcode1 ne $rcode2) { + print("< status: $rcode1\n"); + print("> status: $rcode2\n"); + $status = 1; +} + +exit($status); diff --git a/bin/tests/system/digdelv/ans4/startme b/bin/tests/system/digdelv/ans4/startme new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/bin/tests/system/digdelv/ans4/startme @@ -0,0 +1 @@ + diff --git a/bin/tests/system/digdelv/ans5/ans.pl b/bin/tests/system/digdelv/ans5/ans.pl new file mode 100644 index 0000000..6396406 --- /dev/null +++ b/bin/tests/system/digdelv/ans5/ans.pl @@ -0,0 +1,176 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# This is a TCP-only DNS server whose aim is to facilitate testing how dig +# copes with prematurely closed TCP connections. +# +# This server can be configured (through a separate control socket) with a +# series of responses to send for subsequent incoming TCP DNS queries. Only +# one query is handled before closing each connection. In order to keep things +# simple, the server is not equipped with any mechanism for handling malformed +# queries. +# +# Available response types are defined in the %response_types hash in the +# getAnswerSection() function below. Each RR returned is generated dynamically +# based on the QNAME found in the incoming query. + +use IO::File; +use Net::DNS; +use Net::DNS::Packet; + +use strict; + +# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early +local $SIG{PIPE} = 'IGNORE'; + +# Flush logged output after every line +local $| = 1; + +my $server_addr = "10.53.0.5"; +if (@ARGV > 0) { + $server_addr = @ARGV[0]; +} + +my $mainport = int($ENV{'PORT'}); +if (!$mainport) { $mainport = 5300; } +my $ctrlport = int($ENV{'EXTRAPORT1'}); +if (!$ctrlport) { $ctrlport = 5301; } + +my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $mainport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!";; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my @response_sequence = ("complete_axfr"); +my $connection_counter = 0; + +# Return the next answer type to send, incrementing the connection counter and +# making sure the latter does not exceed the size of the array holding the +# configured response sequence. +sub getNextResponseType { + my $response_type = $response_sequence[$connection_counter]; + + $connection_counter++; + $connection_counter %= scalar(@response_sequence); + + return $response_type; +} + +# Return an array of resource records comprising the answer section of a given +# response type. +sub getAnswerSection { + my ($response_type, $qname) = @_; + + my %response_types = ( + no_response => [], + + partial_axfr => [ + Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"), + Net::DNS::RR->new("$qname NS ."), + ], + + complete_axfr => [ + Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"), + Net::DNS::RR->new("$qname NS ."), + Net::DNS::RR->new("$qname 300 IN SOA . . 0 0 0 0 300"), + ], + ); + + return $response_types{$response_type}; +} + + +# Generate a Net::DNS::Packet containing the response to send on the current +# TCP connection. If the answer section of the response is determined to be +# empty, no data will be sent on the connection at all (immediate EOF). +sub generateResponse { + my ($buf) = @_; + my $request; + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + my $qclass = $questions[0]->qclass; + my $id = $request->header->id; + + my $packet = new Net::DNS::Packet($qname, $qtype, $qclass); + $packet->header->qr(1); + $packet->header->aa(1); + $packet->header->id($id); + + my $response_type = getNextResponseType(); + my $answers = getAnswerSection($response_type, $qname); + for my $rr (@$answers) { + $packet->push("answer", $rr); + } + + print " Sending \"$response_type\" response\n"; + + return $packet->data if @$answers; +} + +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($ctlsock), 1) = 1; + vec($rin, fileno($tcpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($ctlsock), 1)) { + my $conn = $ctlsock->accept; + @response_sequence = split(' ', $conn->getline); + $connection_counter = 0; + print "Response sequence set to: @response_sequence\n"; + $conn->close; + } elsif (vec($rout, fileno($tcpsock), 1)) { + my $buf; + my $lenbuf; + my $conn = $tcpsock->accept; + my $n = $conn->sysread($lenbuf, 2); + die unless $n == 2; + my $len = unpack("n", $lenbuf); + $n = $conn->sysread($buf, $len); + die unless $n == $len; + print "TCP request\n"; + my $response = generateResponse($buf); + if ($response) { + $len = length($response); + $n = $conn->syswrite(pack("n", $len), 2); + $n = $conn->syswrite($response, $len); + print " Sent: $n chars via TCP\n"; + } else { + print " No response sent\n"; + } + $conn->close; + } +} diff --git a/bin/tests/system/digdelv/ans6/ans.pl b/bin/tests/system/digdelv/ans6/ans.pl new file mode 100755 index 0000000..39d02b2 --- /dev/null +++ b/bin/tests/system/digdelv/ans6/ans.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.6", + LocalPort => $localport, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + my $donotrespond = 0; + + $packet->header->aa(1); + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 10.53.0.5")); + } else { + $donotrespond = 1; + } + + if ($donotrespond == 0) { + my $sendsock = + IO::Socket::INET->new(LocalAddr => "10.53.1.2", + PeerAddr => $sock->peerhost, + PeerPort => $sock->peerport, + Proto => "udp") or die "$!"; + print "**** response from ", $sendsock->sockhost, " to " , + $sendsock->peerhost, " port ", $sendsock->peerport, "\n"; + $sendsock->send($packet->data); + $sendsock->close; + print "RESPONSE:\n"; + $packet->print; + print "\n"; + } else { + print "DROP:\n"; + } +} diff --git a/bin/tests/system/digdelv/ans7/ans.pl b/bin/tests/system/digdelv/ans7/ans.pl new file mode 100755 index 0000000..a7aa60e --- /dev/null +++ b/bin/tests/system/digdelv/ans7/ans.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.7", + LocalPort => $localport, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +STDOUT->autoflush(1); + +print "Net::DNS::VERSION => $Net::DNS::VERSION\n"; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + $packet->header->opcode(5); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + $packet->push("update", rr_del("$qname SOA")); + + print "RESPONSE:\n"; + $packet->print; + + $sock->send($packet->data); +} diff --git a/bin/tests/system/digdelv/ans8/ans.py b/bin/tests/system/digdelv/ans8/ans.py new file mode 100644 index 0000000..3e18edc --- /dev/null +++ b/bin/tests/system/digdelv/ans8/ans.py @@ -0,0 +1,202 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +import struct + +import dns, dns.message +from dns.rcode import * + +modes = [ + b"silent", # Do not respond + b"close", # UDP: same as silent; TCP: also close the connection + b"servfail", # Always respond with SERVFAIL + b"unstable", # Constantly switch between "silent" and "servfail" +] +mode = modes[0] +n = 0 + + +def ctrl_channel(msg): + global modes, mode, n + + msg = msg.splitlines().pop(0) + print("Received control message: %s" % msg) + + if msg in modes: + mode = msg + n = 0 + print("New mode: %s" % str(mode)) + + +def create_servfail(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, qname)) + print("%s %s" % (typename, qname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(SERVFAIL) + return r + + +def sigterm(signum, frame): + print("Shutting down now...") + os.remove("ans.pid") + running = False + sys.exit(0) + + +ip4 = "10.53.0.8" + +try: + port = int(os.environ["PORT"]) +except: + port = 5300 + +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 + +query4_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_udp.bind((ip4, port)) + +query4_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +query4_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +query4_tcp.bind((ip4, port)) +query4_tcp.listen(100) + +ctrl4_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +ctrl4_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +ctrl4_tcp.bind((ip4, ctrlport)) +ctrl4_tcp.listen(100) + +signal.signal(signal.SIGTERM, sigterm) + +f = open("ans.pid", "w") +pid = os.getpid() +print(pid, file=f) +f.close() + +running = True + +print("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") + +input = [query4_udp, query4_tcp, ctrl4_tcp] + +hung_conns = [] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_udp: + n = n + 1 + print("UDP query received on %s" % ip4, end=" ") + msg = s.recvfrom(65535) + if ( + mode == b"silent" + or mode == b"close" + or (mode == b"unstable" and n % 2 == 1) + ): + # Do not respond. + print("NO RESPONSE (%s)" % str(mode)) + continue + elif mode == b"servfail" or (mode == b"unstable" and n % 2 == 0): + rsp = create_servfail(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE (can not create a response)") + else: + raise (Exception("unsupported mode: %s" % mode)) + elif s == query4_tcp: + n = n + 1 + print("TCP query received on %s" % ip4, end=" ") + conn = None + try: + if mode == b"silent" or (mode == b"unstable" and n % 2 == 1): + conn, addr = s.accept() + # Do not respond and hang the connection. + print("NO RESPONSE (%s)" % str(mode)) + hung_conns.append(conn) + continue + elif mode == b"close": + conn, addr = s.accept() + # Do not respond and close the connection. + print("NO RESPONSE (%s)" % str(mode)) + conn.close() + continue + elif mode == b"servfail" or (mode == b"unstable" and n % 2 == 0): + conn, addr = s.accept() + # get TCP message length + msg = conn.recv(2) + if len(msg) != 2: + print("NO RESPONSE (can not read the message length)") + conn.close() + continue + length = struct.unpack(">H", msg[:2])[0] + msg = conn.recv(length) + if len(msg) != length: + print("NO RESPONSE (can not read the message)") + conn.close() + continue + rsp = create_servfail(msg) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + wire = rsp.to_wire() + conn.send(struct.pack(">H", len(wire))) + conn.send(wire) + else: + print("NO RESPONSE (can not create a response)") + else: + raise (Exception("unsupported mode: %s" % mode)) + except socket.error as e: + print("NO RESPONSE (error: %s)" % str(e)) + if conn: + conn.close() + elif s == ctrl4_tcp: + print("Control channel connected") + conn = None + try: + # Handle control channel input + conn, addr = s.accept() + msg = conn.recv(1024) + if msg: + ctrl_channel(msg) + conn.close() + except s.timeout: + pass + if conn: + conn.close() + + if not running: + break diff --git a/bin/tests/system/digdelv/ns1/named.conf.in b/bin/tests/system/digdelv/ns1/named.conf.in new file mode 100644 index 0000000..df552bd --- /dev/null +++ b/bin/tests/system/digdelv/ns1/named.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/digdelv/ns1/root.db.in b/bin/tests/system/digdelv/ns1/root.db.in new file mode 100644 index 0000000..b43cc40 --- /dev/null +++ b/bin/tests/system/digdelv/ns1/root.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +a.root-servers.nil. AAAA fd92:7065:b8e:ffff::1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +ns2.example. AAAA fd92:7065:b8e:ffff::2 diff --git a/bin/tests/system/digdelv/ns1/sign.sh b/bin/tests/system/digdelv/ns1/sign.sh new file mode 100644 index 0000000..442d717 --- /dev/null +++ b/bin/tests/system/digdelv/ns1/sign.sh @@ -0,0 +1,31 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +(cd ../ns2 && $SHELL sign.sh) + +cp "../ns2/dsset-example." . + +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone .) + +cp root.db.in root.db + +"$SIGNER" -Sgz -f root.db -o . root.db.in >/dev/null 2>&1 + +keyfile_to_key_id "$ksk" >keyid +grep -Ev '^;' <"$ksk.key" | cut -f 7- -d ' ' >keydata +keyfile_to_initial_keys "$ksk" >anchor.dnskey diff --git a/bin/tests/system/digdelv/ns2/example.db.in b/bin/tests/system/digdelv/ns2/example.db.in new file mode 100644 index 0000000..8a88e03 --- /dev/null +++ b/bin/tests/system/digdelv/ns2/example.db.in @@ -0,0 +1,90 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns2 AAAA fd92:7065:b8e:ffff::2 +ns3 A 10.53.0.3 +ns3 AAAA fd92:7065:b8e:ffff::3 + +a A 10.0.0.1 +a AAAA fd92:7065:b8e:ffff::1 +b A 10.0.0.2 +b AAAA fd92:7065:b8e:ffff::2 +c A 10.0.0.3 +c AAAA fd92:7065:b8e:ffff::3 +d A 10.0.0.0 +d AAAA fd92:7065:b8e:ffff:: + +xn--caf-dma A 10.1.2.3 + +foo TXT "testing" +foo A 10.0.1.0 +foo SSHFP 2 1 123456789abcdef67890123456789abcdef67890 + +; TTL of 3 weeks +weeks 1814400 A 10.53.0.2 +; TTL of 3 days +days 259200 A 10.53.0.2 +; TTL of 3 hours +hours 10800 A 10.53.0.2 +;TTL of 45 minutes +minutes 2700 A 10.53.0.2 +;TTL of 45 seconds +seconds 45 A 10.53.0.2 +; domain names with yaml special values and data with ': ' +yaml TXT "a: b" +'.yaml TXT "a: b" +[.yaml TXT "a: b" +{.yaml TXT "a: b" +&.yaml TXT "a: b" +#.yaml TXT "a: b" +all.yaml TXT ( \000 \001 \002 \003 \004 \005 \006 \007 + \008 \009 \010 \011 \012 \013 \014 \015 + \016 \017 \018 \019 \020 \021 \022 \023 + \024 \025 \026 \027 \028 \029 \030 \031 + \032 \033 \034 \035 \036 \037 \038 \039 + \040 \041 \042 \043 \044 \045 \046 \047 + \048 \049 \050 \051 \052 \053 \054 \055 + \056 \057 \058 \059 \060 \061 \062 \063 + \064 \065 \066 \067 \068 \069 \070 \071 + \072 \073 \074 \075 \076 \077 \078 \079 + \080 \081 \082 \083 \084 \085 \086 \087 + \088 \089 \090 \091 \092 \093 \094 \095 + \096 \097 \098 \099 \100 \101 \102 \103 + \104 \105 \106 \107 \108 \109 \110 \111 + \112 \113 \114 \115 \116 \117 \118 \119 + \120 \121 \122 \123 \124 \125 \126 \127 + \128 \129 \130 \131 \132 \133 \134 \135 + \136 \137 \138 \139 \140 \141 \142 \143 + \144 \145 \146 \147 \148 \149 \150 \151 + \152 \153 \154 \155 \156 \157 \158 \159 + \160 \161 \162 \163 \164 \165 \166 \167 + \168 \169 \170 \171 \172 \173 \174 \175 + \176 \177 \178 \179 \180 \181 \182 \183 + \184 \185 \186 \187 \188 \189 \190 \191 + \192 \193 \194 \195 \196 \197 \198 \199 + \200 \201 \202 \203 \204 \205 \206 \207 + \208 \209 \210 \211 \212 \213 \214 \215 + \216 \217 \218 \219 \220 \221 \222 \223 + \224 \225 \226 \227 \228 \229 \230 \231 + \232 \233 \234 \235 \236 \237 \238 \239 + \240 \241 \242 \243 \244 \245 \246 \247 + \248 \249 \250 \251 \252 \253 \254 \255 ) diff --git a/bin/tests/system/digdelv/ns2/named.conf.in b/bin/tests/system/digdelv/ns2/named.conf.in new file mode 100644 index 0000000..c9fdcd7 --- /dev/null +++ b/bin/tests/system/digdelv/ns2/named.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "example.tld" { + type primary; + file "example.tld.db"; +}; diff --git a/bin/tests/system/digdelv/ns2/sign.sh b/bin/tests/system/digdelv/ns2/sign.sh new file mode 100644 index 0000000..73580a6 --- /dev/null +++ b/bin/tests/system/digdelv/ns2/sign.sh @@ -0,0 +1,32 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone example.) + +cp example.db.in example.db + +"$SIGNER" -Sz -f example.db -o example example.db.in >/dev/null 2>&1 + +keyfile_to_key_id "$ksk" >keyid +grep -Ev '^;' <"$ksk.key" | cut -f 7- -d ' ' >keydata + +keyfile_to_initial_keys "$ksk" >../ns3/anchor.dnskey +keyfile_to_initial_ds "$ksk" >../ns3/anchor.ds + +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone example.tld.) +"$SIGNER" -Sz -f example.tld.db -o example.tld example.db.in >/dev/null 2>&1 diff --git a/bin/tests/system/digdelv/ns3/named.conf.in b/bin/tests/system/digdelv/ns3/named.conf.in new file mode 100644 index 0000000..90a3fa3 --- /dev/null +++ b/bin/tests/system/digdelv/ns3/named.conf.in @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + dnssec-validation no; + server-id "ns3"; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/digdelv/prereq.sh b/bin/tests/system/digdelv/prereq.sh new file mode 100644 index 0000000..32889aa --- /dev/null +++ b/bin/tests/system/digdelv/prereq.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/digdelv/setup.sh b/bin/tests/system/digdelv/setup.sh new file mode 100644 index 0000000..92dd6bf --- /dev/null +++ b/bin/tests/system/digdelv/setup.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf + +cd ns1 && $SHELL sign.sh diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh new file mode 100644 index 0000000..85f9919 --- /dev/null +++ b/bin/tests/system/digdelv/tests.sh @@ -0,0 +1,1799 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +status=0 +n=0 + +sendcmd() { + send "${1}" "$EXTRAPORT1" +} + +dig_with_opts() { + "$DIG" -p "$PORT" "$@" +} + +mdig_with_opts() { + "$MDIG" -p "$PORT" "$@" +} + +# Check if response in file $1 has the correct TTL range. +# The response record must have RRtype $2 and class IN (CLASS1). +# Maximum TTL is given by $3. This works in most cases where TTL is +# the second word on the line. TTL position can be adjusted with +# setting the position $4, but that requires updating this function. +check_ttl_range() { + file=$1 + pos=$4 + + case "$pos" in + "3") + { + awk -v rrtype="$2" -v ttl="$3" '($4 == "IN" || $4 == "CLASS1" ) && $5 == rrtype { if ($3 <= ttl) { ok=1 } } END { exit(ok?0:1) }' <$file + result=$? + } || true + ;; + *) + { + awk -v rrtype="$2" -v ttl="$3" '($3 == "IN" || $3 == "CLASS1" ) && $4 == rrtype { if ($2 <= ttl) { ok=1 } } END { exit(ok?0:1) }' <$file + result=$? + } || true + ;; + esac + + [ $result -eq 0 ] || echo_i "ttl check failed" + return $result +} + +# use delv insecure mode by default, as we're mostly not testing dnssec +delv_with_opts() { + "$DELV" +noroot -p "$PORT" "$@" +} + +KEYID="$(cat ns2/keyid)" +KEYDATA="$(sed /dev/null && HAS_PYYAML=1 +fi + +# +# test whether ans7/ans.pl will be able to send a UPDATE response. +# if it can't, we will log that below. +# +if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet; my $p = new Net::DNS::Packet; $p->header->opcode(5);' >/dev/null 2>&1; then + checkupdate=1 +else + checkupdate=0 +fi + +if [ -x "$NSLOOKUP" -a $checkupdate -eq 1 ]; then + + n=$((n + 1)) + echo_i "check nslookup handles UPDATE response ($n)" + ret=0 + "$NSLOOKUP" -q=CNAME -timeout=1 "-port=$PORT" foo.bar 10.53.0.7 >nslookup.out.test$n 2>&1 && ret=1 + grep "Opcode mismatch" nslookup.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + +fi + +if [ -x "$HOST" -a $checkupdate -eq 1 ]; then + + n=$((n + 1)) + echo_i "check host handles UPDATE response ($n)" + ret=0 + "$HOST" -W 1 -t CNAME -p $PORT foo.bar 10.53.0.7 >host.out.test$n 2>&1 && ret=1 + grep "Opcode mismatch" host.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + +fi + +if [ -x "$NSUPDATE" -a $checkupdate -eq 1 ]; then + + n=$((n + 1)) + echo_i "check nsupdate handles UPDATE response to QUERY ($n)" + ret=0 + res=0 + $NSUPDATE <nsupdate.out.test$n 2>&1 || res=$? +server 10.53.0.7 ${PORT} +add x.example.com 300 in a 1.2.3.4 +send +EOF + test $res -eq 1 || ret=1 + grep "invalid OPCODE in response to SOA query" nsupdate.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + +fi + +if [ -x "$DIG" ]; then + + if [ $checkupdate -eq 1 ]; then + + n=$((n + 1)) + echo_i "check dig handles UPDATE response ($n)" + ret=0 + dig_with_opts @10.53.0.7 +tries=1 +timeout=1 cname foo.bar >dig.out.test$n 2>&1 && ret=1 + grep "Opcode mismatch" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "Skipped UPDATE handling test" + fi + + n=$((n + 1)) + echo_i "checking dig short form works ($n)" + ret=0 + dig_with_opts @10.53.0.3 +short a a.example >dig.out.test$n || ret=1 + test "$(wc -l dig.out.test$n || ret=1 + grep " 9ABC DEF6 7890 " /dev/null || ret=1 + check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +unknownformat works ($n)" + ret=0 + dig_with_opts @10.53.0.3 +unknownformat a a.example >dig.out.test$n || ret=1 + grep "CLASS1[ ][ ]*TYPE1[ ][ ]*\\\\# 4 0A000001" /dev/null || ret=1 + check_ttl_range dig.out.test$n "TYPE1" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig with reverse lookup works ($n)" + ret=0 + dig_with_opts @10.53.0.3 -x 127.0.0.1 >dig.out.test$n 2>&1 || ret=1 + # doesn't matter if has answer + grep -i "127\\.in-addr\\.arpa\\." /dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 86400 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig over TCP works ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 a a.example >dig.out.test$n || ret=1 + grep "10\\.0\\.0\\.1$" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example >dig.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n >/dev/null && ret=1 + check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +multi +norrcomments works for SOA (when default is rrcomments)($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example >dig.out.test$n || ret=1 + grep "; serial" dig.out.test$n >/dev/null && ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +rrcomments works for DNSKEY($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example >dig.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null || ret=1 + check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +short +rrcomments works for DNSKEY ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +short +nosplit works($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example >dig.out.test$n || ret=1 + grep "$NOSPLIT" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +short +rrcomments works($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1 + grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" dig.out.nn.$n || ret=1 + dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +nomulti >dig.out.mn.$n || ret=1 + dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +multi >dig.out.nm.$n || ret=1 + dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +multi >dig.out.mm.$n || ret=1 + lcnn=$(wc -l dig.out.test$n || ret=1 + grep "Got answer:" /dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +short +rrcomments works($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1 + grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" dig.out.test$n || ret=1 + grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," /dev/null || ret=1 + grep "^;; QUESTION SECTION:" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +raflag works ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +raflag +qr example >dig.out.test$n || ret=1 + grep "^;; flags: rd ra ad; QUERY: 1, ANSWER: 0," /dev/null || ret=1 + grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," /dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +tcflag works ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +tcflag +qr example >dig.out.test$n || ret=1 + grep "^;; flags: tc rd ad; QUERY: 1, ANSWER: 0" /dev/null || ret=1 + grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," /dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +header-only works (with class and type set) ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +header-only -c IN -t A example >dig.out.test$n || ret=1 + grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," /dev/null || ret=1 + grep "^;; QUESTION SECTION:" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +zflag works, and that BIND properly ignores it ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +zflag +qr A example >dig.out.test$n || ret=1 + sed -n '/Sending:/,/Got answer:/p' dig.out.test$n | grep "^;; flags: rd ad; MBZ: 0x4;" >/dev/null || ret=1 + sed -n '/Got answer:/,/AUTHORITY SECTION:/p' dig.out.test$n | grep "^;; flags: qr rd ra; QUERY: 1" >/dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +qr +ednsopt=08 does not cause an INSIST failure ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=08 +qr a a.example >dig.out.test$n || ret=1 + grep "INSIST" /dev/null && ret=1 + grep "FORMERR" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +ttlunits works ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +ttlunits A weeks.example >dig.out.test$n || ret=1 + grep "^weeks.example. 3w" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +ttlunits A days.example >dig.out.test$n || ret=1 + grep "^days.example. 3d" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +ttlunits A hours.example >dig.out.test$n || ret=1 + grep "^hours.example. 3h" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +ttlunits A minutes.example >dig.out.test$n || ret=1 + grep "^minutes.example. 45m" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +ttlunits A seconds.example >dig.out.test$n || ret=1 + grep "^seconds.example. 45s" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig respects precedence of options with +ttlunits ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +ttlunits +nottlid A weeks.example >dig.out.test$n || ret=1 + grep "^weeks.example. IN" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +nottlid +ttlunits A weeks.example >dig.out.test$n || ret=1 + grep "^weeks.example. 3w" /dev/null || ret=1 + dig_with_opts +tcp @10.53.0.2 +nottlid +nottlunits A weeks.example >dig.out.test$n || ret=1 + grep "^weeks.example. 1814400" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig preserves origin on TCP retries ($n)" + ret=0 + # Ask ans4 to still accept TCP connections, but not respond to queries + echo "//" | sendcmd 10.53.0.4 + dig_with_opts -d +tcp @10.53.0.4 +retry=1 +time=1 +domain=bar foo >dig.out.test$n 2>&1 && ret=1 + test "$(grep -c "trying origin bar" dig.out.test$n)" -eq 2 || ret=1 + grep "using root origin" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig -6 -4 ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 -4 -6 A a.example >dig.out.test$n 2>&1 && ret=1 + grep "only one of -4 and -6 allowed" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig @IPv6addr -4 A a.example ($n)" + if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then + ret=0 + dig_with_opts +tcp @fd92:7065:b8e:ffff::2 -4 A a.example >dig.out.test$n 2>&1 && ret=1 + grep "address family not supported" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "IPv6 unavailable; skipping" + fi + + n=$((n + 1)) + echo_i "checking dig +tcp @IPv4addr -6 A a.example ($n)" + if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then + ret=0 + dig_with_opts +tcp @10.53.0.2 -6 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "SERVER: ::ffff:10.53.0.2#$PORT" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "IPv6 unavailable; skipping" + fi + n=$((n + 1)) + + echo_i "checking dig +notcp @IPv4addr -6 A a.example ($n)" + if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then + ret=0 + dig_with_opts +notcp @10.53.0.2 -6 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "SERVER: ::ffff:10.53.0.2#$PORT" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "IPv6 unavailable; skipping" + fi + + n=$((n + 1)) + echo_i "checking dig +subnet ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.1 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "CLIENT-SUBNET: 127.0.0.1/32/0" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +subnet +subnet ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.0 +subnet=127.0.0.1 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "CLIENT-SUBNET: 127.0.0.1/32/0" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +subnet with various prefix lengths ($n)" + ret=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do + dig_with_opts +tcp @10.53.0.2 +subnet=255.255.255.255/$i A a.example >dig.out.$i.test$n 2>&1 || ret=1 + case $i in + 1 | 9 | 17) octet=128 ;; + 2 | 10 | 18) octet=192 ;; + 3 | 11 | 19) octet=224 ;; + 4 | 12 | 20) octet=240 ;; + 5 | 13 | 21) octet=248 ;; + 6 | 14 | 22) octet=252 ;; + 7 | 15 | 23) octet=254 ;; + 8 | 16 | 24) octet=255 ;; + esac + case $i in + 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8) addr="${octet}.0.0.0" ;; + 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16) addr="255.${octet}.0.0" ;; + 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24) addr="255.255.${octet}.0" ;; + esac + grep "FORMERR" /dev/null && ret=1 + grep "CLIENT-SUBNET: $addr/$i/0" /dev/null || ret=1 + check_ttl_range dig.out.$i.test$n "A" 300 || ret=1 + done + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +subnet=0/0 ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +subnet=0/0 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "status: NOERROR" /dev/null || ret=1 + grep "CLIENT-SUBNET: 0.0.0.0/0/0" /dev/null || ret=1 + grep "10.0.0.1" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +subnet=0 ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.2 +subnet=0 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "status: NOERROR" /dev/null || ret=1 + grep "CLIENT-SUBNET: 0.0.0.0/0/0" /dev/null || ret=1 + grep "10.0.0.1" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking dig +subnet=0 +yaml ($n)" + ret=0 + dig_with_opts +yaml +tcp @10.53.0.2 +subnet=0 A a.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message response_message_data OPT_PSEUDOSECTION EDNS CLIENT-SUBNET >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep "status: NOERROR" /dev/null || ret=1 + grep "CLIENT-SUBNET: ::/0/0" /dev/null || ret=1 + grep "10.0.0.1" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking dig +subnet=::/0 +yaml ($n)" + ret=0 + dig_with_opts +yaml +tcp @10.53.0.2 +subnet=::/0 A a.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message response_message_data OPT_PSEUDOSECTION EDNS CLIENT-SUBNET >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS CLIENT-SUBNET >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep "status: NOERROR" /dev/null || ret=1 + grep "CLIENT-SUBNET: 0/0/0" /dev/null || ret=1 + grep "10.0.0.1" /dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +ednsopt=8:00030000 (family=3, source=0, scope=0) ($n)" + ret=0 + dig_with_opts +qr +tcp @10.53.0.2 +ednsopt=8:00030000 A a.example >dig.out.test$n 2>&1 || ret=1 + grep "status: FORMERR" /dev/null || ret=1 + grep "CLIENT-SUBNET: 00 03 00 00" /dev/null || ret=1 + test "$(grep -c "CLIENT-SUBNET: 00 03 00 00" dig.out.test$n)" -eq 1 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +subnet with prefix lengths between byte boundaries ($n)" + ret=0 + for p in 9 10 11 12 13 14 15; do + dig_with_opts +tcp @10.53.0.2 +subnet=10.53/$p A a.example >dig.out.test.$p.$n 2>&1 || ret=1 + grep "FORMERR" /dev/null && ret=1 + grep "CLIENT-SUBNET.*/$p/0" /dev/null || ret=1 + check_ttl_range dig.out.test.$p.$n "A" 300 || ret=1 + done + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +sp works as an abbreviated form of split ($n)" + ret=0 + dig_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example >dig.out.test$n || ret=1 + grep " 9ABC DEF6 7890 " /dev/null || ret=1 + check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig -c works ($n)" + ret=0 + dig_with_opts @10.53.0.3 -c CHAOS -t txt version.bind >dig.out.test$n || ret=1 + grep "version.bind. 0 CH TXT" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +ednsopt with option number ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=3 a.example >dig.out.test$n 2>&1 || ret=1 + grep 'NSID: .* ("ns3")' dig.out.test$n >/dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking dig +ednsopt with option name ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=nsid a.example >dig.out.test$n 2>&1 || ret=1 + grep 'NSID: .* ("ns3")' dig.out.test$n >/dev/null || ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking ednsopt UPDATE-LEASE prints as expected (single lease) ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=UPDATE-LEASE:00000e10 +qr a.example >dig.out.test$n 2>&1 || ret=1 + pat='UPDATE-LEASE: 3600 (1 hour)' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + n=$((n + 1)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking ednsopt UPDATE-LEASE prints as expected (single lease) +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=UPDATE-LEASE:00000e10 +qr a.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS UPDATE-LEASE LEASE >yamlget.out.test$n 2>&1 || ret=1 + read -r value /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + fi + + n=$((n + 1)) + echo_i "checking ednsopt UPDATE-LEASE prints as expected (split lease) ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=UPDATE-LEASE:00000e1000127500 +qr a.example >dig.out.test$n 2>&1 || ret=1 + pat='UPDATE-LEASE: 3600/1209600 (1 hour/2 weeks)' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking ednsopt UPDATE-LEASE prints as expected (split lease) +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=UPDATE-LEASE:00000e1000127500 +qr a.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS UPDATE-LEASE LEASE >yamlget.out.test$n 2>&1 || ret=1 + read -r value /dev/null || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS UPDATE-LEASE KEY-LEASE >yamlget.out.test$n 2>&1 || ret=1 + read -r value /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + fi + + echo_i "checking ednsopt LLQ prints as expected ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example >dig.out.test$n 2>&1 || ret=1 + pat='LLQ: Version: 1, Opcode: 2, Error: 0, Identifier: 1311768465173141112, Lifetime: 4278124286$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking ednsopt LLQ prints as expected +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS LLQ LLQ-VERSION >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep ";; WARNING: .local is reserved for Multicast DNS" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=key-tag and FORMERR is returned ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=key-tag a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; KEY-TAG: *$" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=key-tag: ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=key-tag:00010002 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; KEY-TAG: 1, 2$" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1 + check_ttl_range dig.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + ret=0 + echo_i "check that dig processes +ednsopt=key-tag: +yaml ($n)" + dig_with_opts @10.53.0.3 +yaml +ednsopt=key-tag:00010002 a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS KEY-TAG >yamlget.out.test$n 2>&1 || ret=1 + read -r value and FORMERR is returned ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=key-tag:0001000201 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; KEY-TAG: 00 01 00 02 01" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=client-tag:value ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=client-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; CLIENT-TAG: 1$" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=client-tag:value +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=client-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS CLIENT-TAG >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep "; CLIENT-TAG" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that FORMERR is returned for a too long client-tag ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=client-tag:000001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; CLIENT-TAG" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=server-tag:value ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=server-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; SERVER-TAG: 1$" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=server-tag:value +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=server-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS SERVER-TAG >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep "; SERVER-TAG" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that FORMERR is returned for a too long server-tag ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=server-tag:000001 a.example +qr >dig.out.test$n 2>&1 || ret=1 + grep "; SERVER-TAG" dig.out.test$n >/dev/null || ret=1 + grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=chain:02002200 ($n)" + ret=0 + dig_with_opts @10.53.0.3 +ednsopt=chain:02002200 'a.\000"' +qr >dig.out.test$n 2>&1 || ret=1 + grep '; CHAIN: "\\000\\""' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that dig processes +ednsopt=chain:02002200 +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml +ednsopt=chain:02002200 'a.\000"' +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS CHAIN >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep '; EXPIRE: 1200 (20 minutes)' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that dig processes +expire +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.1 +yaml +expire . soa >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message response_message_data OPT_PSEUDOSECTION EDNS EXPIRE >yamlget.out.test$n 2>&1 || ret=1 + read -r value /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + fi + + n=$((n + 1)) + echo_i "check that dig processes +keepalive ($n)" + ret=0 + dig_with_opts @10.53.0.1 +keepalive . soa +tcp >dig.out.test$n 2>&1 || ret=1 + grep '; TCP-KEEPALIVE: 30.0 secs' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that dig processes +keepalive +yaml ($n)" + ret=0 + dig_with_opts @10.53.0.1 +yaml +keepalive . soa +tcp >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message response_message_data OPT_PSEUDOSECTION EDNS TCP-KEEPALIVE >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + pat='^; EDE: 0 (Other): (foo)$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that Extended DNS Error 0 is printed correctly +yaml ($n)" + ret=0 + # add specials '"' and '\' + dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0000666f6f225c a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + pat='^; EDE: 24 (Invalid Data)$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that Extended DNS Error 25 is printed correctly ($n)" + ret=0 + # First undefined EDE code, additional text "foo". + dig_with_opts @10.53.0.3 +ednsopt=ede:0019666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1 + pat='^; EDE: 25: (foo)$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)" + ret=0 + # EDE payload is too short + dig_with_opts @10.53.0.3 +ednsopt=ede a.example +qr >dig.out.test$n 2>&1 || ret=1 + pat='^; EDE:$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that invalid Extended DNS Error (length 1) is printed ($n)" + ret=0 + # EDE payload is too short + dig_with_opts @10.53.0.3 +ednsopt=ede:00 a.example +qr >dig.out.test$n 2>&1 || ret=1 + pat='^; EDE: 00 (".")$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check that +yaml Extended DNS Error 0 is printed correctly ($n)" + ret=0 + # First defined EDE code, additional text "foo". + dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0000666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that +yaml Extended DNS Error 25 is printed correctly ($n)" + ret=0 + # First undefined EDE code, additional text "foo". + dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0019666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 && ret=1 + grep "ednsopt no code point specified" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig gracefully handles bad escape in domain name ($n)" + ret=0 + digstatus=0 + dig_with_opts @10.53.0.3 '\0.' >dig.out.test$n 2>&1 || digstatus=$? + echo digstatus=$digstatus >>dig.out.test$n + test $digstatus -eq 10 || ret=1 + grep REQUIRE dig.out.test$n >/dev/null && ret=1 + grep "is not a legal name (bad escape)" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig -q -m works ($n)" + ret=0 + dig_with_opts @10.53.0.3 -q -m >dig.out.test$n 2>&1 + pat='^;-m\..*IN.*A$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + grep "Dump of all outstanding memory allocations" dig.out.test$n >/dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (immediate -> immediate) ($n)" + ret=0 + echo "no_response no_response" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> partial AXFR) ($n)" + ret=0 + echo "partial_axfr partial_axfr" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (immediate -> partial AXFR) ($n)" + ret=0 + echo "no_response partial_axfr" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> immediate) ($n)" + ret=0 + echo "partial_axfr no_response" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (immediate -> complete AXFR) ($n)" + ret=0 + echo "no_response complete_axfr" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 || ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> complete AXFR) ($n)" + ret=0 + echo "partial_axfr complete_axfr" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 || ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking +tries=1 won't retry twice upon TCP EOF ($n)" + ret=0 + echo "no_response no_response" | sendcmd 10.53.0.5 + dig_with_opts @10.53.0.5 example AXFR +tries=1 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking +retry=0 won't retry twice upon TCP EOF ($n)" + ret=0 + dig_with_opts @10.53.0.5 example AXFR +retry=0 >dig.out.test$n 2>&1 && ret=1 + # Sanity check: ensure ans5 behaves as expected. + [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +expandaaaa works ($n)" + ret=0 + dig_with_opts @10.53.0.3 +expandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1 + grep "ns2.example.*fd92:7065:0b8e:ffff:0000:0000:0000:0002" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +noexpandaaaa works ($n)" + ret=0 + dig_with_opts @10.53.0.3 +noexpandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1 + grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig default for +[no]expandaaa (+noexpandaaaa) works ($n)" + ret=0 + dig_with_opts @10.53.0.3 AAAA ns2.example >dig.out.test$n 2>&1 || ret=1 + grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + + echo_i "check that dig +short +expandaaaa works ($n)" + ret=0 + dig_with_opts @10.53.0.3 +short +expandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1 + pat='^fd92:7065:0b8e:ffff:0000:0000:0000:0002$' + grep "$pat" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check dig +yaml ANY output ($n)" + ret=0 + dig_with_opts +qr +yaml @10.53.0.3 any ns2.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data status >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + grep "EDNS:" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +bufsize restores default bufsize ($n)" + ret=0 + dig_with_opts @10.53.0.3 a.example +bufsize=0 +bufsize +qr >dig.out.test$n 2>&1 || ret=1 + lines=$(grep "EDNS:.* udp:" dig.out.test$n | wc -l) + lines1232=$(grep "EDNS:.* udp: 1232" dig.out.test$n | wc -l) + test $lines -eq 2 || ret=1 + test $lines1232 -eq 2 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig without -u displays 'Query time' in millseconds ($n)" + ret=0 + dig_with_opts @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep ';; Query time: [0-9][0-9]* msec' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig -u displays 'Query time' in microseconds ($n)" + ret=0 + dig_with_opts -u @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep ';; Query time: [0-9][0-9]* usec' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +yaml without -u displays timestamps in milliseconds ($n)" + ret=0 + dig_with_opts +yaml @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep 'query_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1 + grep 'response_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig -u +yaml displays timestamps in microseconds ($n)" + ret=0 + dig_with_opts -u +yaml @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep 'query_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1 + grep 'response_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # See [GL #3020] for more information + n=$((n + 1)) + echo_i "check that dig handles UDP timeout followed by a SERVFAIL correctly ($n)" + # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes) + echo "unstable" | sendcmd 10.53.0.8 + ret=0 + dig_with_opts +timeout=1 +nofail @10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig handles TCP timeout followed by a SERVFAIL correctly ($n)" + # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes) + echo "unstable" | sendcmd 10.53.0.8 + ret=0 + dig_with_opts +timeout=1 +nofail +tcp @10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after a UDP socket network unreachable error ($n)" + ret=0 + dig_with_opts @192.0.2.128 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after a TCP socket network unreachable error ($n)" + ret=0 + dig_with_opts +tcp @192.0.2.128 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after a UDP socket read error ($n)" + ret=0 + dig_with_opts @10.53.0.99 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after a TCP socket read error ($n)" + # Ask ans8 to be in "close" mode, which closes the connection after accepting it + echo "close" | sendcmd 10.53.0.8 + ret=0 + dig_with_opts +tcp @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # Note that we combine TCP socket "connection error" and "timeout" cases in + # one, because it is not trivial to simulate the timeout case in a system test + # in Linux without a firewall, but the code which handles error cases during + # the connection establishment time does not differentiate between timeout and + # other types of errors (unlike during reading), so this one check should be + # sufficient for both cases. + n=$((n + 1)) + echo_i "check that dig tries the next server after a TCP socket connection error/timeout ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.99 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after UDP socket read timeouts ($n)" + # Ask ans8 to be in "silent" mode + echo "silent" | sendcmd 10.53.0.8 + ret=0 + dig_with_opts +timeout=1 @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig tries the next server after TCP socket read timeouts ($n)" + # Ask ans8 to be in "silent" mode + echo "silent" | sendcmd 10.53.0.8 + ret=0 + dig_with_opts +timeout=1 +tcp @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # See [GL #3248] for more information + n=$((n + 1)) + echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)" + ret=0 + dig_with_opts @10.53.0.8 @::ffff:10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F ";; Skipping mapped address" dig.out.test$n >/dev/null || ret=1 + grep -F ";; No acceptable nameservers" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # See [GL #3244] for more information + n=$((n + 1)) + echo_i "check that dig handles printing query information with +qr and +y when multiple queries are involved (including a failed query) ($n)" + ret=0 + dig_with_opts +timeout=1 +qr +y @127.0.0.1 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1 + grep -F "IN A 10.0.0.1" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +noedns +ednsflags= re-enables EDNS ($n)" + dig_with_opts @10.53.0.3 +qr +noedns +ednsflags=0x70 a.example >dig.out.test$n 2>&1 || ret=1 + grep "; EDNS: version: 0, flags:; MBZ: 0x0070, udp: 1232" dig.out.test$n >/dev/null || ret=1 + grep "; EDNS: version: 0, flags:; udp: 1232" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that dig +showbadvers works ($n)" + dig_with_opts @10.53.0.3 +edns=1 +qr +showbadvers a.example >dig.out.test$n 2>&1 || ret=1 + grep "; EDNS: version: 1, flags:; udp: 1232" dig.out.test$n >/dev/null || ret=1 + grep "; EDNS: version: 0, flags:; udp: 1232" dig.out.test$n >/dev/null || ret=1 + grep -F "status: BADVERS" dig.out.test$n >/dev/null || ret=1 + grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "$DIG is needed, so skipping these dig tests" +fi + +if [ -x "$MDIG" ]; then + n=$((n + 1)) + echo_i "checking mdig +tcp works with a source address and port ($n)" + ret=0 + # When running more than once in quick succession with a source address#port, + # we can get a "response failed with address not available" error because + # the address#port is still busy, but we are not interested in that error, + # as we are only looking for the unexpected error case, that's why we ignore + # the return code from mdig, but we check for the unexpected error message + # using grep. See GitLab #4969. + mdig_with_opts -b "10.53.0.3#${EXTRAPORT8}" +tcp @10.53.0.3 example >dig.out.test$n 2>&1 || true + grep -F "unexpected error" dig.out.test$n >/dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)" + ret=0 + mdig_with_opts @10.53.0.3 +ednsopt=: a.example >dig.out.test$n 2>&1 && ret=1 + grep "ednsopt no code point specified" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking mdig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)" + ret=0 + mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example >dig.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking mdig +multi +norrcomments works for SOA (when default is rrcomments)($n)" + ret=0 + mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example >dig.out.test$n || ret=1 + grep "; serial" /dev/null && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check mdig +yaml output ($n)" + ret=0 + mdig_with_opts +yaml @10.53.0.3 -t any ns2.example >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message response_message_data status >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value delv.out.test$n || ret=1 + test "$(wc -l delv.out.test$n || ret=1 + grep " 9ABC DEF6 7890 " /dev/null || ret=1 + check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +unknownformat works ($n)" + ret=0 + delv_with_opts @10.53.0.3 +unknownformat a a.example >delv.out.test$n || ret=1 + grep "CLASS1[ ][ ]*TYPE1[ ][ ]*\\\\# 4 0A000001" /dev/null || ret=1 + check_ttl_range delv.out.test$n "TYPE1" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv -4 -6 ($n)" + ret=0 + delv_with_opts @10.53.0.3 -4 -6 A a.example >delv.out.test$n 2>&1 && ret=1 + grep "only one of -4 and -6 allowed" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv with IPv6 on IPv4 does not work ($n)" + if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null; then + ret=0 + # following should fail because @IPv4 overrides earlier @IPv6 above + # and -6 forces IPv6 so this should fail, with a message + # "Use of IPv4 disabled by -6" + delv_with_opts @fd92:7065:b8e:ffff::3 @10.53.0.3 -6 -t txt foo.example >delv.out.test$n 2>&1 && ret=1 + # it should have no results but error output + grep "testing" /dev/null && ret=1 + grep "Use of IPv4 disabled by -6" delv.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "IPv6 unavailable; skipping" + fi + + n=$((n + 1)) + echo_i "checking delv with IPv4 on IPv6 does not work ($n)" + if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null; then + ret=0 + # following should fail because @IPv6 overrides earlier @IPv4 above + # and -4 forces IPv4 so this should fail, with a message + # "Use of IPv6 disabled by -4" + delv_with_opts @10.53.0.3 @fd92:7065:b8e:ffff::3 -4 -t txt foo.example >delv.out.test$n 2>&1 && ret=1 + # it should have no results but error output + grep "testing" delv.out.test$n >/dev/null && ret=1 + grep "Use of IPv6 disabled by -4" delv.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + else + echo_i "IPv6 unavailable; skipping" + fi + + n=$((n + 1)) + echo_i "checking delv with reverse lookup works ($n)" + ret=0 + delv_with_opts @10.53.0.3 -x 127.0.0.1 >delv.out.test$n 2>&1 || ret=1 + # doesn't matter if has answer + grep -i "127\\.in-addr\\.arpa\\." /dev/null || ret=1 + check_ttl_range delv.out.test$n '\\-ANY' 10800 3 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv over TCP works ($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 a a.example >delv.out.test$n || ret=1 + grep "10\\.0\\.0\\.1$" /dev/null || ret=1 + check_ttl_range delv.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 +multi +norrcomments DNSKEY example >delv.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null && ret=1 + check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +multi +norrcomments works for SOA (when default is rrcomments)($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 +multi +norrcomments SOA example >delv.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null && ret=1 + check_ttl_range delv.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +rrcomments works for DNSKEY($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example >delv.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null || ret=1 + check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +short +rrcomments works for DNSKEY ($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >delv.out.test$n || ret=1 + grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" /dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +short +rrcomments works ($n)" + ret=0 + delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >delv.out.test$n || ret=1 + grep -q "$KEYDATA ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" delv.out.test$n || ret=1 + grep -q "$NOSPLIT" delv.out.test$n || ret=1 + grep -q "$NOSPLIT\$" delv.out.test$n || ret=1 + grep " 9ABC DEF6 7890 " /dev/null || ret=1 + check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +sh works as an abbriviated form of short ($n)" + ret=0 + delv_with_opts @10.53.0.3 +sh a a.example >delv.out.test$n || ret=1 + test "$(wc -l delv.out.test$n || ret=1 + grep "a.example." /dev/null || ret=1 + check_ttl_range delv.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv -c CH is ignored, and treated like IN ($n)" + ret=0 + delv_with_opts @10.53.0.3 -c CH -t a a.example >delv.out.test$n || ret=1 + grep "a.example." /dev/null || ret=1 + check_ttl_range delv.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv -c CH is ignored, and treated like IN ($n)" + ret=0 + delv_with_opts @10.53.0.3 -c CH -t a a.example >delv.out.test$n || ret=1 + grep "a.example." /dev/null || ret=1 + check_ttl_range delv.out.test$n "A" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that delv -q -m works ($n)" + ret=0 + delv_with_opts @10.53.0.3 -q -m >delv.out.test$n 2>&1 || ret=1 + grep '^; -m\..*[0-9]*.*IN.*ANY.*;' delv.out.test$n >/dev/null || ret=1 + grep "^add " delv.out.test$n >/dev/null && ret=1 + grep "^del " delv.out.test$n >/dev/null && ret=1 + check_ttl_range delv.out.test$n '\\-ANY' 300 3 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that delv -t ANY works ($n)" + ret=0 + delv_with_opts @10.53.0.3 -t ANY example >delv.out.test$n 2>&1 || ret=1 + grep "^example." /dev/null || ret=1 + check_ttl_range delv.out.test$n NS 300 || ret=1 + check_ttl_range delv.out.test$n SOA 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that delv loads key-style trust anchors ($n)" + ret=0 + delv_with_opts -a ns3/anchor.dnskey +root=example @10.53.0.3 -t DNSKEY example >delv.out.test$n 2>&1 || ret=1 + grep "fully validated" delv.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check that delv loads DS-style trust anchors ($n)" + ret=0 + delv_with_opts -a ns3/anchor.ds +root=example @10.53.0.3 -t DNSKEY example >delv.out.test$n 2>&1 || ret=1 + grep "fully validated" delv.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "check delv +yaml ANY output ($n)" + ret=0 + delv_with_opts +yaml @10.53.0.3 any ns2.example >delv.out.test$n || ret=1 + $PYTHON yamlget.py delv.out.test$n status >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value delv.out.test$n || ret=1 + $PYTHON yamlget.py delv.out.test$n status >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value delv.out.test$n || ret=1 + $PYTHON yamlget.py delv.out.test$n status >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value delv.out.test$n 2>&1 || ret=1 + grep ";; resolution failed: broken trust chain" delv.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check NS output from delv +ns ($n)" + delv_with_opts -i +ns +nortrace +nostrace +nomtrace +novtrace +hint=../_common/root.hint ns example >delv.out.test$n || ret=1 + lines=$(awk '$1 == "example." && $4 == "NS" {print}' delv.out.test$n | wc -l) + [ $lines -eq 2 ] || ret=1 + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +ns (no validation) ($n)" + ret=0 + delv_with_opts -i +ns +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1 + grep -q '; authoritative' delv.out.test$n || ret=1 + grep -q '_.example' delv.out.test$n && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +ns +qmin (no validation) ($n)" + ret=0 + delv_with_opts -i +ns +qmin +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1 + grep -q '; authoritative' delv.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +ns (with validation) ($n)" + ret=0 + delv_with_opts -a ns1/anchor.dnskey +root +ns +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1 + grep -q '; fully validated' delv.out.test$n || ret=1 + grep -q '_.example' delv.out.test$n && ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking delv +ns +qmin (with validation) ($n)" + ret=0 + delv_with_opts -a ns1/anchor.dnskey +root +ns +qmin +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1 + grep -q '; fully validated' delv.out.test$n || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + +else + echo_i "$DELV is needed, so skipping these delv tests" +fi + +if [ $HAS_PYYAML -ne 0 ]; then + for qname in "yaml" "'.yaml" "[.yaml" "{.yaml" "&.yaml" "#.yaml"; do + n=$((n + 1)) + echo_i "check yaml special '${yaml}.example' ($n)" + ret=0 + dig_with_opts @10.53.0.3 +yaml "${qname}.example" TXT +qr >dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1 + read -r value yamlget.out.test$n 2>&1 || ret=1 + read -r value dig.out.test$n 2>&1 || ret=1 + $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1 + read -r value " "?" "@" "A" "B" "C" "D" "E" "F" "G" "H"' + expected="$expected "'"I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V"' + expected="$expected "'"W" "X" "Y" "Z" "[" "\\" "]" "^" "_" "`" "a" "b" "c" "d"' + expected="$expected "'"e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r"' + expected="$expected "'"s" "t" "u" "v" "w" "x" "y" "z" "{" "|" "}" "~" "\127"' + expected="$expected "'"\128" "\129" "\130" "\131" "\132" "\133" "\134" "\135"' + expected="$expected "'"\136" "\137" "\138" "\139" "\140" "\141" "\142" "\143"' + expected="$expected "'"\144" "\145" "\146" "\147" "\148" "\149" "\150" "\151"' + expected="$expected "'"\152" "\153" "\154" "\155" "\156" "\157" "\158" "\159"' + expected="$expected "'"\160" "\161" "\162" "\163" "\164" "\165" "\166" "\167"' + expected="$expected "'"\168" "\169" "\170" "\171" "\172" "\173" "\174" "\175"' + expected="$expected "'"\176" "\177" "\178" "\179" "\180" "\181" "\182" "\183"' + expected="$expected "'"\184" "\185" "\186" "\187" "\188" "\189" "\190" "\191"' + expected="$expected "'"\192" "\193" "\194" "\195" "\196" "\197" "\198" "\199"' + expected="$expected "'"\200" "\201" "\202" "\203" "\204" "\205" "\206" "\207"' + expected="$expected "'"\208" "\209" "\210" "\211" "\212" "\213" "\214" "\215"' + expected="$expected "'"\216" "\217" "\218" "\219" "\220" "\221" "\222" "\223"' + expected="$expected "'"\224" "\225" "\226" "\227" "\228" "\229" "\230" "\231"' + expected="$expected "'"\232" "\233" "\234" "\235" "\236" "\237" "\238" "\239"' + expected="$expected "'"\240" "\241" "\242" "\243" "\244" "\245" "\246" "\247"' + expected="$expected "'"\248" "\249" "\250" "\251" "\252" "\253" "\254" "\255"' + [ "$value" = "$expected" ] || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/digdelv/tests_sh_digdelv.py b/bin/tests/system/digdelv/tests_sh_digdelv.py new file mode 100644 index 0000000..5767bc1 --- /dev/null +++ b/bin/tests/system/digdelv/tests_sh_digdelv.py @@ -0,0 +1,38 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "delv.out.*", + "dig.out.*", + "host.out.*", + "nslookup.out.*", + "nsupdate.out.*", + "yamlget.out.*", + "ans*/ans.run", + "ans*/query.log", + "ns*/anchor.*", + "ns*/dsset-*", + "ns*/keydata", + "ns*/keyid", + "ns*/K*.key", + "ns*/K*.private", + "ns1/root.db", + "ns2/example.db", + "ns2/example.tld.db", + ] +) + + +def test_digdelv(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/digdelv/yamlget.py b/bin/tests/system/digdelv/yamlget.py new file mode 100644 index 0000000..afa582d --- /dev/null +++ b/bin/tests/system/digdelv/yamlget.py @@ -0,0 +1,35 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import sys + +try: + import yaml +# pylint: disable=bare-except +except: + print("No python yaml module, skipping") + sys.exit(1) + +with open(sys.argv[1], "r", encoding="utf-8") as f: + for item in yaml.safe_load_all(f): + for key in sys.argv[2:]: + try: + key = int(key) + except ValueError: + pass + + try: + item = item[key] + except KeyError: + print('Key "' + key + '" not found.') + sys.exit(1) + + print(item) diff --git a/bin/tests/system/dispatch/ans3/ans.py b/bin/tests/system/dispatch/ans3/ans.py new file mode 100644 index 0000000..4e4ebac --- /dev/null +++ b/bin/tests/system/dispatch/ans3/ans.py @@ -0,0 +1,99 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import select +import signal +import socket +import sys +import time + +import dns.flags +import dns.message + + +def port(): + env_port = os.getenv("PORT") + if env_port is None: + env_port = 5300 + else: + env_port = int(env_port) + + return env_port + + +def udp_listen(port): + udp = socket.socket(type=socket.SOCK_DGRAM) + udp.bind(("10.53.0.3", port)) + + return udp + + +def tcp_listen(port): + tcp = socket.socket(type=socket.SOCK_STREAM) + tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + tcp.bind(("10.53.0.3", port)) + tcp.listen(100) + + return tcp + + +def udp_tc_once(udp): + qrybytes, clientaddr = udp.recvfrom(65535) + qry = dns.message.from_wire(qrybytes) + answ = dns.message.make_response(qry) + answ.flags |= dns.flags.TC + answbytes = answ.to_wire() + udp.sendto(answbytes, clientaddr) + + +def tcp_once(tcp): + csock, _clientaddr = tcp.accept() + time.sleep(5) + csock.close() + + +def sigterm(signum, frame): + os.remove("ans.pid") + sys.exit(0) + + +def write_pid(): + with open("ans.pid", "w") as f: + pid = os.getpid() + f.write("{}".format(pid)) + + +signal.signal(signal.SIGTERM, sigterm) +write_pid() + +udp = udp_listen(port()) +tcp = tcp_listen(port()) + +input = [udp, tcp] + +while True: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error: + break + except socket.error: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == udp: + udp_tc_once(udp) + if s == tcp: + tcp_once(tcp) + +sigterm(signal.SIGTERM, 0) diff --git a/bin/tests/system/dispatch/ns1/named.conf.j2 b/bin/tests/system/dispatch/ns1/named.conf.j2 new file mode 100644 index 0000000..d3337a5 --- /dev/null +++ b/bin/tests/system/dispatch/ns1/named.conf.j2 @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + + listen-on { 10.53.0.1; }; + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + query-source-v6 address fd92:7065:b8e:ffff::1; + notify-source-v6 fd92:7065:b8e:ffff::1; + transfer-source-v6 fd92:7065:b8e:ffff::1; + + recursion no; + servfail-ttl 0; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/dispatch/ns1/root.db b/bin/tests/system/dispatch/ns1/root.db new file mode 100644 index 0000000..b6b7367 --- /dev/null +++ b/bin/tests/system/dispatch/ns1/root.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 SOA . . 0 0 0 0 0 +. 300 NS ns.nil. +ns.nil. 300 A 10.53.0.1 +example. 300 NS ns.example. +ns.example. 300 A 10.53.0.2 diff --git a/bin/tests/system/dispatch/ns2/example.db b/bin/tests/system/dispatch/ns2/example.db new file mode 100644 index 0000000..f60a47e --- /dev/null +++ b/bin/tests/system/dispatch/ns2/example.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 86400 IN SOA ns.example. root.example. 43 10800 900 604800 86400 +example. 86400 IN NS ns.example. +ns.example. A 10.53.0.2 + +ns.sub.example. A 10.53.0.3 +sub.example. NS ns.sub.example. diff --git a/bin/tests/system/dispatch/ns2/named.conf.j2 b/bin/tests/system/dispatch/ns2/named.conf.j2 new file mode 100644 index 0000000..895f40d --- /dev/null +++ b/bin/tests/system/dispatch/ns2/named.conf.j2 @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + + listen-on { 10.53.0.2; }; + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + query-source-v6 address fd92:7065:b8e:ffff::2; + notify-source-v6 fd92:7065:b8e:ffff::2; + transfer-source-v6 fd92:7065:b8e:ffff::2; + + recursion yes; + servfail-ttl 0; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/dispatch/tests_connreset.py b/bin/tests/system/dispatch/tests_connreset.py new file mode 100644 index 0000000..0b78fb8 --- /dev/null +++ b/bin/tests/system/dispatch/tests_connreset.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest +import isctest + +pytest.importorskip("dns") +import dns.message + +pytestmark = pytest.mark.extra_artifacts( + [ + "ans*/ans.run", + ] +) + + +def test_connreset(): + msg = dns.message.make_query( + "sub.example.", "A", want_dnssec=True, use_edns=0, payload=1232 + ) + res = isctest.query.udp(msg, "10.53.0.2") + isctest.check.servfail(res) diff --git a/bin/tests/system/ditch.pl b/bin/tests/system/ditch.pl new file mode 100644 index 0000000..f77d022 --- /dev/null +++ b/bin/tests/system/ditch.pl @@ -0,0 +1,94 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# This is a tool for sending queries via UDP to specified address and +# port, then exiting without waiting for a response. +# +# Usage: ditch.pl [-s
] [-p ] [filename] +# +# Input (in filename, if specified, otherwise stdin) is a series of one +# or more DNS names and types to send as queries, e.g.: +# +# www.example.com A +# www.example.org MX +# +# If not specified, address defaults to 127.0.0.1, port to 53. + +require 5.006.001; + +use strict; +use Getopt::Std; +use Net::DNS; +use Net::DNS::Packet; +use IO::File; +use IO::Socket; + +sub usage { + print ("Usage: ditch.pl [-s address] [-p port] [-b source_port] [file]\n"); + exit 1; +} + +my %options={}; +getopts("s:p:b:", \%options); + +my $addr = "127.0.0.1"; +$addr = $options{s} if defined $options{s}; + +my $port = 53; +$port = $options{p} if defined $options{p}; + +my $source_port = 0; +$source_port = $options{b} if defined $options{b}; + +my $file = "STDIN"; +if (@ARGV >= 1) { + my $filename = shift @ARGV; + open FH, "<$filename" or die "$filename: $!"; + $file = "FH"; +} + +my $input = ""; +while (defined(my $line = <$file>) ) { + chomp $line; + next if ($line =~ m/^ *#/); + my @tokens = split (' ', $line); + + my $packet; + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(); + $err and die $err; + } + + my $q = new Net::DNS::Question($tokens[0], $tokens[1], "IN"); + $packet->header->rd(1); + $packet->push(question => $q); + + my $sock = IO::Socket::INET->new( + PeerAddr => $addr, + PeerPort => $port, + Proto => "udp", + LocalPort => $source_port, + ) or die "$!"; + + my $bytes = $sock->send($packet->data); + #print ("sent $bytes bytes to $addr:$port:\n"); + #print (" ", unpack("H* ", $packet->data), "\n"); + + $sock->close; +} + +close $file; diff --git a/bin/tests/system/dlzexternal/driver/Makefile.am b/bin/tests/system/dlzexternal/driver/Makefile.am new file mode 100644 index 0000000..0028edb --- /dev/null +++ b/bin/tests/system/dlzexternal/driver/Makefile.am @@ -0,0 +1,13 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +noinst_LTLIBRARIES = dlzexternal.la + +dlzexternal_la_SOURCES = \ + driver.c \ + driver.h + +dlzexternal_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) diff --git a/bin/tests/system/dlzexternal/driver/Makefile.in b/bin/tests/system/dlzexternal/driver/Makefile.in new file mode 100644 index 0000000..c1b1103 --- /dev/null +++ b/bin/tests/system/dlzexternal/driver/Makefile.in @@ -0,0 +1,788 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = bin/tests/system/dlzexternal/driver +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +dlzexternal_la_LIBADD = +am_dlzexternal_la_OBJECTS = driver.lo +dlzexternal_la_OBJECTS = $(am_dlzexternal_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +dlzexternal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(dlzexternal_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/driver.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(dlzexternal_la_SOURCES) +DIST_SOURCES = $(dlzexternal_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = dlzexternal.la +dlzexternal_la_SOURCES = \ + driver.c \ + driver.h + +dlzexternal_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/dlzexternal/driver/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/system/dlzexternal/driver/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +dlzexternal.la: $(dlzexternal_la_OBJECTS) $(dlzexternal_la_DEPENDENCIES) $(EXTRA_dlzexternal_la_DEPENDENCIES) + $(AM_V_CCLD)$(dlzexternal_la_LINK) $(dlzexternal_la_OBJECTS) $(dlzexternal_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/driver.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/driver.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/system/dlzexternal/driver/driver.c b/bin/tests/system/dlzexternal/driver/driver.c new file mode 100644 index 0000000..9750fdc --- /dev/null +++ b/bin/tests/system/dlzexternal/driver/driver.c @@ -0,0 +1,862 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * This provides a very simple example of an external loadable DLZ + * driver, with update support. + */ + +#include "driver.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* aliases for exported symbols */ + +dlz_dlopen_version_t dlz_version; +dlz_dlopen_create_t dlz_create; +dlz_dlopen_destroy_t dlz_destroy; +dlz_dlopen_findzonedb_t dlz_findzonedb; +dlz_dlopen_lookup_t dlz_lookup; +dlz_dlopen_allowzonexfr_t dlz_allowzonexfr; +dlz_dlopen_allnodes_t dlz_allnodes; +dlz_dlopen_newversion_t dlz_newversion; +dlz_dlopen_closeversion_t dlz_closeversion; +dlz_dlopen_configure_t dlz_configure; +dlz_dlopen_ssumatch_t dlz_ssumatch; +dlz_dlopen_addrdataset_t dlz_addrdataset; +dlz_dlopen_subrdataset_t dlz_subrdataset; +dlz_dlopen_delrdataset_t dlz_delrdataset; + +#define CHECK(x) \ + do { \ + result = (x); \ + if (result != ISC_R_SUCCESS) \ + goto failure; \ + } while (0) + +#define loginfo(...) \ + ({ \ + if ((state != NULL) && (state->log != NULL)) \ + state->log(ISC_LOG_INFO, __VA_ARGS__); \ + }) +#define logerr(...) \ + ({ \ + if ((state != NULL) && (state->log != NULL)) \ + state->log(ISC_LOG_ERROR, __VA_ARGS__); \ + }) + +/* For this simple example, use fixed sized strings */ +struct record { + char name[100]; + char type[10]; + char data[200]; + dns_ttl_t ttl; +}; + +#define MAX_RECORDS 100 + +typedef void +log_t(int level, const char *fmt, ...); + +struct dlz_example_data { + char *zone_name; + + /* An example driver doesn't need good memory management :-) */ + struct record current[MAX_RECORDS]; + struct record adds[MAX_RECORDS]; + struct record deletes[MAX_RECORDS]; + + bool transaction_started; + + /* Helper functions from the dlz_dlopen driver */ + log_t *log; + dns_sdlz_putrr_t *putrr; + dns_sdlz_putnamedrr_t *putnamedrr; + dns_dlz_writeablezone_t *writeable_zone; +}; + +static bool +single_valued(const char *type) { + const char *single[] = { "soa", "cname", NULL }; + int i; + + for (i = 0; single[i]; i++) { + if (strcasecmp(single[i], type) == 0) { + return true; + } + } + return false; +} + +/* + * Add a record to a list + */ +static isc_result_t +add_name(struct dlz_example_data *state, struct record *list, const char *name, + const char *type, dns_ttl_t ttl, const char *data) { + int i; + bool single = single_valued(type); + int first_empty = -1; + + for (i = 0; i < MAX_RECORDS; i++) { + INSIST(list[i].name != NULL); + if (first_empty == -1 && strlen(list[i].name) == 0U) { + first_empty = i; + } + if (strcasecmp(list[i].name, name) != 0) { + continue; + } + if (strcasecmp(list[i].type, type) != 0) { + continue; + } + if (!single && strcasecmp(list[i].data, data) != 0) { + continue; + } + break; + } + if (i == MAX_RECORDS && first_empty != -1) { + i = first_empty; + } + if (i == MAX_RECORDS) { + logerr("dlz_example: out of record space"); + return ISC_R_FAILURE; + } + + if (strlen(name) >= sizeof(list[i].name) || + strlen(type) >= sizeof(list[i].type) || + strlen(data) >= sizeof(list[i].data)) + { + return ISC_R_NOSPACE; + } + + strncpy(list[i].name, name, sizeof(list[i].name) - 1); + list[i].name[sizeof(list[i].name) - 1] = '\0'; + + strncpy(list[i].type, type, sizeof(list[i].type) - 1); + list[i].type[sizeof(list[i].type) - 1] = '\0'; + + strncpy(list[i].data, data, sizeof(list[i].data) - 1); + list[i].data[sizeof(list[i].data) - 1] = '\0'; + + list[i].ttl = ttl; + + return ISC_R_SUCCESS; +} + +/* + * Delete a record from a list + */ +static isc_result_t +del_name(struct dlz_example_data *state, struct record *list, const char *name, + const char *type, dns_ttl_t ttl, const char *data) { + int i; + + UNUSED(state); + + for (i = 0; i < MAX_RECORDS; i++) { + if (strcasecmp(name, list[i].name) == 0 && + strcasecmp(type, list[i].type) == 0 && + strcasecmp(data, list[i].data) == 0 && ttl == list[i].ttl) + { + break; + } + } + if (i == MAX_RECORDS) { + return ISC_R_NOTFOUND; + } + memset(&list[i], 0, sizeof(struct record)); + return ISC_R_SUCCESS; +} + +static isc_result_t +fmt_address(isc_sockaddr_t *addr, char *buffer, size_t size) { + char addr_buf[INET6_ADDRSTRLEN]; + const char *ret; + uint16_t port = 0; + + switch (addr->type.sa.sa_family) { + case AF_INET: + port = ntohs(addr->type.sin.sin_port); + ret = inet_ntop(AF_INET, &addr->type.sin.sin_addr, addr_buf, + sizeof(addr_buf)); + break; + case AF_INET6: + port = ntohs(addr->type.sin6.sin6_port); + ret = inet_ntop(AF_INET6, &addr->type.sin6.sin6_addr, addr_buf, + sizeof(addr_buf)); + break; + default: + return ISC_R_FAILURE; + } + + if (ret == NULL) { + return ISC_R_FAILURE; + } + + snprintf(buffer, size, "%s#%u", addr_buf, port); + return ISC_R_SUCCESS; +} + +/* + * Return the version of the API + */ +int +dlz_version(unsigned int *flags) { + UNUSED(flags); + return DLZ_DLOPEN_VERSION; +} + +/* + * Remember a helper function from the bind9 dlz_dlopen driver + */ +static void +b9_add_helper(struct dlz_example_data *state, const char *helper_name, + void *ptr) { + if (strcmp(helper_name, "log") == 0) { + state->log = (log_t *)ptr; + } + if (strcmp(helper_name, "putrr") == 0) { + state->putrr = (dns_sdlz_putrr_t *)ptr; + } + if (strcmp(helper_name, "putnamedrr") == 0) { + state->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr; + } + if (strcmp(helper_name, "writeable_zone") == 0) { + state->writeable_zone = (dns_dlz_writeablezone_t *)ptr; + } +} + +/* + * Called to initialize the driver + */ +isc_result_t +dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, + ...) { + struct dlz_example_data *state; + const char *helper_name; + va_list ap; + char soa_data[sizeof("@ hostmaster.root 123 900 600 86400 3600")]; + isc_result_t result; + size_t n; + + UNUSED(dlzname); + + state = calloc(1, sizeof(struct dlz_example_data)); + if (state == NULL) { + return ISC_R_NOMEMORY; + } + + /* Fill in the helper functions */ + va_start(ap, dbdata); + while ((helper_name = va_arg(ap, const char *)) != NULL) { + b9_add_helper(state, helper_name, va_arg(ap, void *)); + } + va_end(ap); + + if (argc < 2 || argv[1][0] == '\0') { + logerr("dlz_example: please specify a zone name"); + dlz_destroy(state); + return ISC_R_FAILURE; + } + + /* Ensure zone name is absolute */ + state->zone_name = malloc(strlen(argv[1]) + 2); + if (state->zone_name == NULL) { + free(state); + return ISC_R_NOMEMORY; + } + if (argv[1][strlen(argv[1]) - 1] == '.') { + strcpy(state->zone_name, argv[1]); + } else { + sprintf(state->zone_name, "%s.", argv[1]); + } + + /* + * Use relative names to trigger ISC_R_NOSPACE in dns_sdlz_putrr. + */ + if (strcmp(state->zone_name, ".") == 0) { + n = strlcpy(soa_data, + "@ hostmaster.root 123 900 600 86400 3600", + sizeof(soa_data)); + } else { + n = strlcpy(soa_data, "@ hostmaster 123 900 600 86400 3600", + sizeof(soa_data)); + } + + if (n >= sizeof(soa_data)) { + CHECK(ISC_R_NOSPACE); + } + + add_name(state, &state->current[0], state->zone_name, "soa", 3600, + soa_data); + add_name(state, &state->current[0], state->zone_name, "ns", 3600, + state->zone_name); + add_name(state, &state->current[0], state->zone_name, "a", 1800, + "10.53.0.1"); + + loginfo("dlz_example: started for zone %s", state->zone_name); + + *dbdata = state; + return ISC_R_SUCCESS; + +failure: + free(state); + return result; +} + +/* + * Shut down the backend + */ +void +dlz_destroy(void *dbdata) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + loginfo("dlz_example: shutting down zone %s", state->zone_name); + free(state->zone_name); + free(state); +} + +/* + * See if we handle a given zone + */ +isc_result_t +dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + isc_sockaddr_t *src; + char addrbuf[100]; + char absolute[1024]; + + strcpy(addrbuf, "unknown"); + if (methods != NULL && methods->sourceip != NULL && + methods->version - methods->age <= DNS_CLIENTINFOMETHODS_VERSION && + DNS_CLIENTINFOMETHODS_VERSION <= methods->version) + { + methods->sourceip(clientinfo, &src); + fmt_address(src, addrbuf, sizeof(addrbuf)); + } + + loginfo("dlz_example: dlz_findzonedb called with name '%s' " + "in zone DB '%s' from %s", + name, state->zone_name, addrbuf); + + /* + * Returning ISC_R_NOTFOUND will cause the query logic to + * check the database for parent names, looking for zone cuts. + * + * Returning ISC_R_NOMORE prevents the query logic from doing + * this; it will move onto the next database after a single query. + */ + if (strcasecmp(name, "test.example.com") == 0) { + return ISC_R_NOMORE; + } + + /* + * For example.net, only return ISC_R_NOMORE when queried + * from 10.53.0.1. + */ + if (strcasecmp(name, "test.example.net") == 0 && + strncmp(addrbuf, "10.53.0.1", 9) == 0) + { + return ISC_R_NOMORE; + } + + /* + * For bigcname.domain, return success so it appears to be + * the zone origin; this regression tests a bug in which + * zone origin nodes could fail to return SERVFAIL to the client. + */ + if (strcasecmp(name, "bigcname.domain") == 0) { + return ISC_R_SUCCESS; + } + + /* + * Return success if we have an exact match between the + * zone name and the qname + */ + if (strcasecmp(state->zone_name, name) == 0) { + return ISC_R_SUCCESS; + } + + snprintf(absolute, sizeof(absolute), "%s.", name); + if (strcasecmp(state->zone_name, absolute) == 0) { + return ISC_R_SUCCESS; + } + + return ISC_R_NOTFOUND; +} + +/* + * Look up one record in the sample database. + * + * If the queryname is "source-addr", send back a TXT record containing + * the address of the client, to test the use of 'methods' and 'clientinfo' + * + * If the queryname is "too-long", send back a TXT record that's too long + * to process; this should result in a SERVFAIL when queried. + */ +isc_result_t +dlz_lookup(const char *zone, const char *name, void *dbdata, + dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + isc_result_t result; + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + bool found = false; + void *dbversion = NULL; + isc_sockaddr_t *src; + char full_name[256]; + char buf[512]; + static char last[256]; + static int count = 0; + int i, size; + + UNUSED(zone); + + if (state->putrr == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + if (strcmp(name, "@") == 0) { + size = snprintf(full_name, sizeof(full_name), "%s", + state->zone_name); + } else if (strcmp(state->zone_name, ".") == 0) { + size = snprintf(full_name, sizeof(full_name), "%s.", name); + } else { + size = snprintf(full_name, sizeof(full_name), "%s.%s", name, + state->zone_name); + } + + if (size < 0 || (size_t)size >= sizeof(full_name) || + (size_t)size >= sizeof(last)) + { + return ISC_R_NOSPACE; + } + + /* + * For test purposes, log all calls to dlz_lookup() + */ + if (strcasecmp(full_name, last) == 0) { + count++; + } else { + count = 1; + memcpy(last, full_name, size + 1); + } + loginfo("lookup #%d for %s", count, full_name); + + /* + * If we need to know the database version (as set in + * the 'newversion' dlz function) we can pick it up from the + * clientinfo. + * + * This allows a lookup to query the correct version of the DNS + * data, if the DLZ can differentiate between versions. + * + * For example, if a new database transaction is created by + * 'newversion', the lookup should query within the same + * transaction scope if it can. + * + * If the DLZ only operates on 'live' data, then version + * wouldn't necessarily be needed. + */ + if (clientinfo != NULL && clientinfo->version >= 2) { + dbversion = clientinfo->dbversion; + if (dbversion != NULL && *(bool *)dbversion) { + loginfo("dlz_example: lookup against live transaction"); + } + } + + if (strcmp(name, "source-addr") == 0) { + char ecsbuf[DNS_ECS_FORMATSIZE] = "not supported"; + strncpy(buf, "unknown", sizeof(buf)); + if (methods != NULL && methods->sourceip != NULL && + (methods->version - methods->age <= + DNS_CLIENTINFOMETHODS_VERSION) && + DNS_CLIENTINFOMETHODS_VERSION <= methods->version) + { + methods->sourceip(clientinfo, &src); + fmt_address(src, buf, sizeof(buf)); + } + if (clientinfo != NULL && clientinfo->version >= 3) { + if (clientinfo->ecs.addr.family != AF_UNSPEC) { + dns_ecs_format(&clientinfo->ecs, ecsbuf, + sizeof(ecsbuf)); + } else { + snprintf(ecsbuf, sizeof(ecsbuf), "%s", + "not present"); + } + } + i = strlen(buf); + snprintf(buf + i, sizeof(buf) - i - 1, " ECS %s", ecsbuf); + + loginfo("dlz_example: lookup connection from %s", buf); + + found = true; + result = state->putrr(lookup, "TXT", 0, buf); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + if (strcmp(name, "too-long") == 0 || + strcmp(zone, "bigcname.domain") == 0) + { + for (i = 0; i < 511; i++) { + buf[i] = 'x'; + } + buf[i] = '\0'; + found = true; + result = state->putrr(lookup, "TXT", 0, buf); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + /* Tests for DLZ redirection zones */ + if (strcmp(name, "*") == 0 && strcmp(zone, ".") == 0) { + result = state->putrr(lookup, "A", 0, "100.100.100.2"); + found = true; + if (result != ISC_R_SUCCESS) { + return result; + } + } + + if (strcmp(name, "long.name.is.not.there") == 0 && + strcmp(zone, ".") == 0) + { + result = state->putrr(lookup, "A", 0, "100.100.100.3"); + found = true; + if (result != ISC_R_SUCCESS) { + return result; + } + } + + /* Answer from current records */ + for (i = 0; i < MAX_RECORDS; i++) { + if (strcasecmp(state->current[i].name, full_name) == 0) { + found = true; + result = state->putrr(lookup, state->current[i].type, + state->current[i].ttl, + state->current[i].data); + if (result != ISC_R_SUCCESS) { + return result; + } + } + } + + if (!found) { + return ISC_R_NOTFOUND; + } + + return ISC_R_SUCCESS; +} + +/* + * See if a zone transfer is allowed + */ +isc_result_t +dlz_allowzonexfr(void *dbdata, const char *name, const char *client) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + isc_result_t result; + + loginfo("dlz_example: dlz_allowzonexfr called for %s", name); + + result = dlz_findzonedb(dbdata, name, NULL, NULL); + if (result != ISC_R_SUCCESS) { + loginfo("dlz_example: findzonedb returned %s", + isc_result_totext(result)); + return result; + } + + /* + * Exception for "example.org" so we can test the use of + * the view ACL. + */ + if (strcmp(name, "example.org") == 0) { + loginfo("dlz_example: use view ACL for example.org"); + return ISC_R_DEFAULT; + } + + /* + * Exception for 10.53.0.5 so we can test that allow-transfer + * is effective. + */ + if (strcmp(client, "10.53.0.5") == 0) { + loginfo("dlz_example: disallow transfer to 10.53.0.5"); + return ISC_R_NOPERM; + } + + loginfo("dlz_example: transfer allowed for %s", name); + + return ISC_R_SUCCESS; +} + +/* + * Perform a zone transfer + */ +isc_result_t +dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + int i; + + UNUSED(zone); + + if (state->putnamedrr == NULL) { + return ISC_R_NOTIMPLEMENTED; + } + + for (i = 0; i < MAX_RECORDS; i++) { + isc_result_t result; + if (strlen(state->current[i].name) == 0U) { + continue; + } + result = state->putnamedrr(allnodes, state->current[i].name, + state->current[i].type, + state->current[i].ttl, + state->current[i].data); + if (result != ISC_R_SUCCESS) { + return result; + } + } + + return ISC_R_SUCCESS; +} + +/* + * Start a transaction + */ +isc_result_t +dlz_newversion(const char *zone, void *dbdata, void **versionp) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (state->transaction_started) { + loginfo("dlz_example: transaction already started for zone %s", + zone); + return ISC_R_FAILURE; + } + + state->transaction_started = true; + *versionp = (void *)&state->transaction_started; + + return ISC_R_SUCCESS; +} + +/* + * End a transaction + */ +void +dlz_closeversion(const char *zone, bool commit, void *dbdata, void **versionp) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (!state->transaction_started) { + loginfo("dlz_example: transaction not started for zone %s", + zone); + *versionp = NULL; + return; + } + + state->transaction_started = false; + + *versionp = NULL; + + if (commit) { + int i; + loginfo("dlz_example: committing transaction on zone %s", zone); + for (i = 0; i < MAX_RECORDS; i++) { + if (strlen(state->deletes[i].name) > 0U) { + (void)del_name(state, &state->current[0], + state->deletes[i].name, + state->deletes[i].type, + state->deletes[i].ttl, + state->deletes[i].data); + } + } + for (i = 0; i < MAX_RECORDS; i++) { + if (strlen(state->adds[i].name) > 0U) { + (void)add_name(state, &state->current[0], + state->adds[i].name, + state->adds[i].type, + state->adds[i].ttl, + state->adds[i].data); + } + } + } else { + loginfo("dlz_example: cancelling transaction on zone %s", zone); + } + memset(state->adds, 0, sizeof(state->adds)); + memset(state->deletes, 0, sizeof(state->deletes)); +} + +/* + * Configure a writeable zone + */ +isc_result_t +dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + isc_result_t result; + + loginfo("dlz_example: starting configure"); + + if (state->writeable_zone == NULL) { + loginfo("dlz_example: no writeable_zone method available"); + return ISC_R_FAILURE; + } + + result = state->writeable_zone(view, dlzdb, state->zone_name); + if (result != ISC_R_SUCCESS) { + loginfo("dlz_example: failed to configure zone %s", + state->zone_name); + return result; + } + + loginfo("dlz_example: configured writeable zone %s", state->zone_name); + return ISC_R_SUCCESS; +} + +/* + * Authorize a zone update + */ +bool +dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, + unsigned char *keydata, void *dbdata) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + UNUSED(tcpaddr); + UNUSED(type); + UNUSED(key); + UNUSED(keydatalen); + UNUSED(keydata); + + if (strncmp(name, "deny.", 5) == 0) { + loginfo("dlz_example: denying update of name=%s by %s", name, + signer); + return false; + } + loginfo("dlz_example: allowing update of name=%s by %s", name, signer); + return true; +} + +static isc_result_t +modrdataset(struct dlz_example_data *state, const char *name, + const char *rdatastr, struct record *list) { + char *full_name, *dclass, *type, *data, *ttlstr, *buf; + char absolute[1024]; + isc_result_t result; + char *saveptr = NULL; + + buf = strdup(rdatastr); + if (buf == NULL) { + return ISC_R_FAILURE; + } + + /* + * The format is: + * FULLNAME\tTTL\tDCLASS\tTYPE\tDATA + * + * The DATA field is space separated, and is in the data format + * for the type used by dig + */ + + full_name = strtok_r(buf, "\t", &saveptr); + if (full_name == NULL) { + goto error; + } + + ttlstr = strtok_r(NULL, "\t", &saveptr); + if (ttlstr == NULL) { + goto error; + } + + dclass = strtok_r(NULL, "\t", &saveptr); + if (dclass == NULL) { + goto error; + } + + type = strtok_r(NULL, "\t", &saveptr); + if (type == NULL) { + goto error; + } + + data = strtok_r(NULL, "\t", &saveptr); + if (data == NULL) { + goto error; + } + + if (name[strlen(name) - 1] != '.') { + snprintf(absolute, sizeof(absolute), "%s.", name); + name = absolute; + } + + result = add_name(state, list, name, type, strtoul(ttlstr, NULL, 10), + data); + free(buf); + return result; + +error: + free(buf); + return ISC_R_FAILURE; +} + +isc_result_t +dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, + void *version) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *)&state->transaction_started) { + return ISC_R_FAILURE; + } + + loginfo("dlz_example: adding rdataset %s '%s'", name, rdatastr); + + return modrdataset(state, name, rdatastr, &state->adds[0]); +} + +isc_result_t +dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, + void *version) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *)&state->transaction_started) { + return ISC_R_FAILURE; + } + + loginfo("dlz_example: subtracting rdataset %s '%s'", name, rdatastr); + + return modrdataset(state, name, rdatastr, &state->deletes[0]); +} + +isc_result_t +dlz_delrdataset(const char *name, const char *type, void *dbdata, + void *version) { + struct dlz_example_data *state = (struct dlz_example_data *)dbdata; + + if (version != (void *)&state->transaction_started) { + return ISC_R_FAILURE; + } + + loginfo("dlz_example: deleting rdataset %s of type %s", name, type); + + return ISC_R_SUCCESS; +} diff --git a/bin/tests/system/dlzexternal/driver/driver.h b/bin/tests/system/dlzexternal/driver/driver.h new file mode 100644 index 0000000..2c1a594 --- /dev/null +++ b/bin/tests/system/dlzexternal/driver/driver.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include + +/* + * This header includes the declarations of entry points. + */ + +dlz_dlopen_version_t dlz_version; +dlz_dlopen_create_t dlz_create; +dlz_dlopen_destroy_t dlz_destroy; +dlz_dlopen_findzonedb_t dlz_findzonedb; +dlz_dlopen_lookup_t dlz_lookup; +dlz_dlopen_allowzonexfr_t dlz_allowzonexfr; +dlz_dlopen_allnodes_t dlz_allnodes; +dlz_dlopen_newversion_t dlz_newversion; +dlz_dlopen_closeversion_t dlz_closeversion; +dlz_dlopen_configure_t dlz_configure; +dlz_dlopen_ssumatch_t dlz_ssumatch; +dlz_dlopen_addrdataset_t dlz_addrdataset; +dlz_dlopen_subrdataset_t dlz_subrdataset; +dlz_dlopen_delrdataset_t dlz_delrdataset; diff --git a/bin/tests/system/dlzexternal/ns1/named.conf.in b/bin/tests/system/dlzexternal/ns1/named.conf.in new file mode 100644 index 0000000..f8b36e9 --- /dev/null +++ b/bin/tests/system/dlzexternal/ns1/named.conf.in @@ -0,0 +1,85 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.1; 127.0.0.1; }; + listen-on-v6 { none; }; + allow-transfer { !10.53.0.1; any; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +include "ddns.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dlz "example one" { + database "dlopen ../driver/.libs/dlzexternal.so example.nil"; +}; + +dlz "example two" { + database "dlopen ../driver/.libs/dlzexternal.so alternate.nil"; +}; + +dlz "example three" { + database "dlopen ../driver/.libs/dlzexternal.so example.org"; +}; + +dlz "example four" { + // Long zone name to trigger ISC_R_NOSPACE in dns_sdlz_putrr. + database "dlopen ../driver/.libs/dlzexternal.so 123456789.123456789.123456789.123456789.123456789.example.foo"; +}; + +dlz "unsearched1" { + database "dlopen ../driver/.libs/dlzexternal.so other.nil"; + search no; +}; + +dlz "unsearched2" { + database "dlopen ../driver/.libs/dlzexternal.so zone.nil"; + search no; +}; + +dlz redzone { + database "dlopen ../driver/.libs/dlzexternal.so ."; + search no; +}; + +zone zone.nil { + type primary; + dlz unsearched2; +}; + +zone "." { + type redirect; + dlz redzone; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/dlzexternal/ns1/root.db b/bin/tests/system/dlzexternal/ns1/root.db new file mode 100644 index 0000000..6cbe579 --- /dev/null +++ b/bin/tests/system/dlzexternal/ns1/root.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns1.example. +ns1.example. A 10.53.0.1 + +exists. A 10.10.10.10 diff --git a/bin/tests/system/dlzexternal/prereq.sh b/bin/tests/system/dlzexternal/prereq.sh new file mode 100644 index 0000000..f7591d7 --- /dev/null +++ b/bin/tests/system/dlzexternal/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --tsan && { + echo_i "TSAN - skipping dlzexternal test" + exit 255 +} + +exit 0 diff --git a/bin/tests/system/dlzexternal/setup.sh b/bin/tests/system/dlzexternal/setup.sh new file mode 100644 index 0000000..2dfa3d6 --- /dev/null +++ b/bin/tests/system/dlzexternal/setup.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$TSIGKEYGEN ddns-key.example.nil >ns1/ddns.key + +copy_setports ns1/named.conf.in ns1/named.conf diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh new file mode 100644 index 0000000..031f76a --- /dev/null +++ b/bin/tests/system/dlzexternal/tests.sh @@ -0,0 +1,231 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +DIGOPTS="@10.53.0.1 -p ${PORT} +nocookie" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +newtest() { + n=$((n + 1)) + echo_i "${1} (${n})" + ret=0 +} + +test_update() { + host="$1" + type="$2" + cmd="$3" + digout="$4" + should_fail="$5" + + cat <ns1/update.txt +server 10.53.0.1 ${PORT} +update add $host $cmd +send +EOF + + newtest "testing update for $host $type $cmd${comment:+ }$comment" + $NSUPDATE -k ns1/ddns.key ns1/update.txt >/dev/null 2>&1 || { + [ "$should_fail" ] \ + || echo_i "update failed for $host $type $cmd" + return 1 + } + + out=$($DIG $DIGOPTS -t $type -q $host | grep -E "^$host") + lines=$(echo "$out" | grep "$digout" | wc -l) + [ $lines -eq 1 ] || { + [ "$should_fail" ] \ + || echo_i "dig output incorrect for $host $type $cmd: $out" + return 1 + } + return 0 +} + +test_update testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1 +status=$((status + ret)) + +test_update testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || ret=1 +status=$((status + ret)) + +test_update testdc3.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1 +status=$((status + ret)) + +test_update deny.example.nil. TXT "86400 TXT helloworld" "helloworld" should_fail && ret=1 +status=$((status + ret)) + +newtest "testing nxrrset" +$DIG $DIGOPTS testdc1.example.nil AAAA >dig.out.$n || ret=1 +grep "status: NOERROR" dig.out.$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.$n >/dev/null || ret=1 +status=$((status + ret)) + +newtest "testing prerequisites are checked correctly" +cat >ns1/update.txt </dev/null 2>&1 && ret=1 +out=$($DIG $DIGOPTS +short a testdc3.example.nil) +[ "$out" = "10.53.0.12" ] && ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing passing client info into DLZ driver" +out=$($DIG $DIGOPTS +short -t txt -q source-addr.example.nil | grep -v '^;') +addr=$(eval echo "$out" | cut -f1 -d'#') +[ "$addr" = "10.53.0.1" ] || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing DLZ driver is cleaned up on reload" +rndc_reload ns1 10.53.0.1 +for i in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + grep 'dlz_example: shutting down zone example.nil' ns1/named.run >/dev/null 2>&1 || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing multiple DLZ drivers" +test_update testdc1.alternate.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1 +status=$((status + ret)) + +newtest "testing AXFR from DLZ drivers" +$DIG $DIGOPTS +noall +answer axfr example.nil >dig.out.example.ns1.test$n || ret=1 +lines=$(cat dig.out.example.ns1.test$n | wc -l) +[ ${lines:-0} -eq 4 ] || ret=1 +$DIG $DIGOPTS +noall +answer axfr alternate.nil >dig.out.alternate.ns1.test$n || ret=1 +lines=$(cat dig.out.alternate.ns1.test$n | wc -l) +[ ${lines:-0} -eq 5 ] || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing AXFR denied from DLZ drivers" +$DIG $DIGOPTS -b 10.53.0.5 +noall +answer axfr example.nil >dig.out.example.ns1.test$n || ret=1 +grep "; Transfer failed" dig.out.example.ns1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS -b 10.53.0.5 +noall +answer axfr alternate.nil >dig.out.alternate.ns1.test$n || ret=1 +grep "; Transfer failed" dig.out.alternate.ns1.test$n >/dev/null || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing AXFR denied based on view ACL" +# 10.53.0.1 should be disallowed +$DIG $DIGOPTS -b 10.53.0.1 +noall +answer axfr example.org >dig.out.example.ns1.test$n.1 || ret=1 +grep "; Transfer failed" dig.out.example.ns1.test$n.1 >/dev/null || ret=1 +# 10.53.0.2 should be allowed +$DIG $DIGOPTS -b 10.53.0.2 +noall +answer axfr example.org >dig.out.example.ns1.test$n.2 || ret=1 +grep "; Transfer failed" dig.out.example.ns1.test$n.2 >/dev/null && ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing unsearched/unregistered DLZ zone is not found" +$DIG $DIGOPTS +noall +answer ns other.nil >dig.out.ns1.test$n || ret=1 +grep "3600.IN.NS.other.nil." dig.out.ns1.test$n >/dev/null && ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing unsearched/registered DLZ zone is found" +$DIG $DIGOPTS +noall +answer ns zone.nil >dig.out.ns1.test$n || ret=1 +grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n >/dev/null || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing unsearched/registered DLZ zone is found" +$DIG $DIGOPTS +noall +answer ns zone.nil >dig.out.ns1.test$n || ret=1 +grep "3600.IN.NS.zone.nil." dig.out.ns1.test$n >/dev/null || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing correct behavior with findzone returning ISC_R_NOMORE" +$DIG $DIGOPTS +noall a test.example.com >/dev/null 2>&1 || ret=1 +# we should only find one logged lookup per searched DLZ database +lines=$(grep "dlz_findzonedb.*test\.example\.com.*example.nil" ns1/named.run | wc -l) +[ $lines -eq 1 ] || ret=1 +lines=$(grep "dlz_findzonedb.*test\.example\.com.*alternate.nil" ns1/named.run | wc -l) +[ $lines -eq 1 ] || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing findzone can return different results per client" +$DIG $DIGOPTS -b 10.53.0.1 +noall a test.example.net >/dev/null 2>&1 || ret=1 +# we should only find one logged lookup per searched DLZ database +lines=$(grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l) +[ $lines -eq 1 ] || ret=1 +lines=$(grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l) +[ $lines -eq 1 ] || ret=1 +$DIG $DIGOPTS -b 10.53.0.2 +noall a test.example.net >/dev/null 2>&1 || ret=1 +# we should find several logged lookups this time +lines=$(grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l) +[ $lines -gt 2 ] || ret=1 +lines=$(grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l) +[ $lines -gt 2 ] || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing zone returning oversized data" +$DIG $DIGOPTS txt too-long.example.nil >dig.out.ns1.test$n 2>&1 || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test$n >/dev/null || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "testing zone returning oversized data at zone origin" +$DIG $DIGOPTS txt bigcname.domain >dig.out.ns1.test$n 2>&1 || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test$n >/dev/null || ret=1 +[ "$ret" -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +newtest "checking redirected lookup for nonexistent name" +$DIG $DIGOPTS @10.53.0.1 unexists a >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "^unexists.*A.*100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1 +grep "flags:[^;]* aa[ ;]" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "checking no redirected lookup for nonexistent type" +$DIG $DIGOPTS @10.53.0.1 exists aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "checking redirected lookup for a long nonexistent name" +$DIG $DIGOPTS @10.53.0.1 long.name.is.not.there a >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "^long.name.*A.*100.100.100.3" dig.out.ns1.test$n >/dev/null || ret=1 +grep "flags:[^;]* aa[ ;]" dig.out.ns1.test$n >/dev/null || ret=1 +lookups=$(grep "lookup #.*\.not\.there" ns1/named.run | wc -l) +[ "$lookups" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "checking ECS data is passed to driver in clientinfo" +$DIG $DIGOPTS +short +subnet=192.0/16 source-addr.example.nil txt >dig.out.ns1.test$n.1 || ret=1 +grep "192.0.0.0/16/0" dig.out.ns1.test$n.1 >/dev/null || ret=1 +$DIG $DIGOPTS +short source-addr.example.nil txt >dig.out.ns1.test$n.2 || ret=1 +grep "not.*present" dig.out.ns1.test$n.2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py b/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py new file mode 100644 index 0000000..e64ecda --- /dev/null +++ b/bin/tests/system/dlzexternal/tests_sh_dlzexternal.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns1/ddns.key", + "ns1/update.txt", + ] +) + + +def test_dlzexternal(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/dns64/conf/bad1.conf b/bin/tests/system/dns64/conf/bad1.conf new file mode 100644 index 0000000..a4b7e7f --- /dev/null +++ b/bin/tests/system/dns64/conf/bad1.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/0 { }; +}; diff --git a/bin/tests/system/dns64/conf/bad10.conf b/bin/tests/system/dns64/conf/bad10.conf new file mode 100644 index 0000000..21855f6 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad10.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:0100:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad11.conf b/bin/tests/system/dns64/conf/bad11.conf new file mode 100644 index 0000000..c3bdd92 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad11.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:0200:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad12.conf b/bin/tests/system/dns64/conf/bad12.conf new file mode 100644 index 0000000..6ffe720 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad12.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:0400:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad13.conf b/bin/tests/system/dns64/conf/bad13.conf new file mode 100644 index 0000000..dc6c064 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad13.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:0800:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad14.conf b/bin/tests/system/dns64/conf/bad14.conf new file mode 100644 index 0000000..985101a --- /dev/null +++ b/bin/tests/system/dns64/conf/bad14.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:1000:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad15.conf b/bin/tests/system/dns64/conf/bad15.conf new file mode 100644 index 0000000..0931a55 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad15.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:2000:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad16.conf b/bin/tests/system/dns64/conf/bad16.conf new file mode 100644 index 0000000..3a8b962 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad16.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:4000:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad17.conf b/bin/tests/system/dns64/conf/bad17.conf new file mode 100644 index 0000000..6c9079b --- /dev/null +++ b/bin/tests/system/dns64/conf/bad17.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 0000:0000:0000:0000:8000:000f::/96 { }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad18.conf b/bin/tests/system/dns64/conf/bad18.conf new file mode 100644 index 0000000..566e177 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad18.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/32 { suffix ::8000:0000:0000:0000; }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad19.conf b/bin/tests/system/dns64/conf/bad19.conf new file mode 100644 index 0000000..8a9fb76 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad19.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/32 { suffix ::0100:0000:0000:0000; }; /* bits [64..71] MBZ */ +}; diff --git a/bin/tests/system/dns64/conf/bad2.conf b/bin/tests/system/dns64/conf/bad2.conf new file mode 100644 index 0000000..d275998 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/96 { suffix ::1; }; +}; diff --git a/bin/tests/system/dns64/conf/bad3.conf b/bin/tests/system/dns64/conf/bad3.conf new file mode 100644 index 0000000..24971b3 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad3.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/96 { suffix 127.0.0.1; }; +}; diff --git a/bin/tests/system/dns64/conf/bad4.conf b/bin/tests/system/dns64/conf/bad4.conf new file mode 100644 index 0000000..bc73ca5 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad4.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/129 { }; +}; diff --git a/bin/tests/system/dns64/conf/bad5.conf b/bin/tests/system/dns64/conf/bad5.conf new file mode 100644 index 0000000..bc73ca5 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad5.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 ::/129 { }; +}; diff --git a/bin/tests/system/dns64/conf/bad6.conf b/bin/tests/system/dns64/conf/bad6.conf new file mode 100644 index 0000000..1d85ab9 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad6.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 :: { }; +}; diff --git a/bin/tests/system/dns64/conf/bad7.conf b/bin/tests/system/dns64/conf/bad7.conf new file mode 100644 index 0000000..afbf437 --- /dev/null +++ b/bin/tests/system/dns64/conf/bad7.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 FC36:EAFE:F993::/64 { + exclude { bogusacl; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/bad8.conf b/bin/tests/system/dns64/conf/bad8.conf new file mode 100644 index 0000000..9aa423f --- /dev/null +++ b/bin/tests/system/dns64/conf/bad8.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 FC36:EAFE:F993::/64 { + clients { bogusacl; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/bad9.conf b/bin/tests/system/dns64/conf/bad9.conf new file mode 100644 index 0000000..b74204c --- /dev/null +++ b/bin/tests/system/dns64/conf/bad9.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dns64 FC36:EAFE:F993::/64 { + mapped { bogusacl; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/good1.conf b/bin/tests/system/dns64/conf/good1.conf new file mode 100644 index 0000000..d84733e --- /dev/null +++ b/bin/tests/system/dns64/conf/good1.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; +options { + /* Well Known Prefix */ + dns64 64:FF9B::/96 { + clients { any; }; + mapped { !rfc1918; any; }; + exclude { ::ffff:0:0/96; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/good2.conf b/bin/tests/system/dns64/conf/good2.conf new file mode 100644 index 0000000..41b5730 --- /dev/null +++ b/bin/tests/system/dns64/conf/good2.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; +options { + /* Well Known Prefix */ + dns64 64:FF9B::/96 { + mapped { !rfc1918; any; }; + exclude { ::ffff:0:0/96; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/good3.conf b/bin/tests/system/dns64/conf/good3.conf new file mode 100644 index 0000000..450b2e0 --- /dev/null +++ b/bin/tests/system/dns64/conf/good3.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; +options { + /* Well Known Prefix */ + dns64 64:FF9B::/96 { + clients { any; }; + exclude { ::ffff:0:0/96; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/good4.conf b/bin/tests/system/dns64/conf/good4.conf new file mode 100644 index 0000000..2c57f23 --- /dev/null +++ b/bin/tests/system/dns64/conf/good4.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; +options { + /* Well Known Prefix */ + dns64 64:FF9B::/96 { + clients { any; }; + mapped { !rfc1918; any; }; + }; +}; diff --git a/bin/tests/system/dns64/conf/good5.conf b/bin/tests/system/dns64/conf/good5.conf new file mode 100644 index 0000000..f6027a4 --- /dev/null +++ b/bin/tests/system/dns64/conf/good5.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; +options { + /* Well Known Prefix */ + dns64 64:FF9B::/96 { }; +}; diff --git a/bin/tests/system/dns64/ns1/example.db b/bin/tests/system/dns64/ns1/example.db new file mode 100644 index 0000000..8253f1d --- /dev/null +++ b/bin/tests/system/dns64/ns1/example.db @@ -0,0 +1,56 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns1 marka.isc.org. 0 0 0 0 1200 +@ NS ns1 +ns1 A 10.53.0.1 +excluded-good-a AAAA 2001:eeee::1 + A 1.2.3.4 +excluded-bad-a AAAA 2001:eeee::2 + A 10.0.0.1 +excluded-only AAAA 2001:eeee::3 +partially-excluded-good-a AAAA 2001:eeee::1 + AAAA 2001::1 + A 1.2.3.4 +partially-excluded-bad-a AAAA 2001:eeee::2 + AAAA 2001::2 + A 10.0.0.1 +partially-excluded-only AAAA 2001:eeee::3 + AAAA 2001::3 +a-only A 1.2.3.5 +a-and-aaaa AAAA 2001::1 + A 1.2.3.6 +aaaa-only AAAA 2001::2 +a-not-mapped A 10.0.0.2 +a-and-mapped AAAA ::ffff:1.2.3.4 + A 1.2.3.5 +a-and-aaaa-and-mapped AAAA 2001:eeee::4 +a-and-aaaa-and-mapped AAAA ::ffff:1.2.3.4 +a-and-aaaa-and-mapped A 1.2.3.5 +mx-only MX 10 ns.example. +cname-excluded-good-a CNAME excluded-good-a +cname-excluded-bad-a CNAME excluded-bad-a +cname-excluded-only CNAME excluded-only +cname-partial-excluded-good-a CNAME partial-excluded-good-a +cname-partial-excluded-bad-a CNAME partial-excluded-bad-a +cname-partial-excluded-only CNAME partial-excluded-only +cname-a-only CNAME a-only +cname-a-and-aaaa CNAME a-and-aaaa +cname-aaaa-only CNAME aaaa-only +cname-a-not-mapped CNAME a-not-mapped +cname-mx-only CNAME mx-only +cname-non-existent CNAME non-existent +ttl-less-than-600 500 A 5.6.7.8 +ttl-more-than-600 700 A 5.6.7.8 +ttl-less-than-minimum 1100 A 5.6.7.8 +ttl-more-than-minimum 1300 A 5.6.7.8 +rpz 1500 A 99.99.99.99 diff --git a/bin/tests/system/dns64/ns1/ipv4only.arpa.db b/bin/tests/system/dns64/ns1/ipv4only.arpa.db new file mode 100644 index 0000000..9e0726d --- /dev/null +++ b/bin/tests/system/dns64/ns1/ipv4only.arpa.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +ipv4only.arpa. 3600 IN SOA . . 2018112766 7200 3600 604800 3600 +ipv4only.arpa. 3600 IN NS . +ipv4only.arpa. 3600 IN A 192.0.0.170 +ipv4only.arpa. 3600 IN A 192.0.0.171 diff --git a/bin/tests/system/dns64/ns1/named.conf1.in b/bin/tests/system/dns64/ns1/named.conf1.in new file mode 100644 index 0000000..bc6c2d2 --- /dev/null +++ b/bin/tests/system/dns64/ns1/named.conf1.in @@ -0,0 +1,65 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-recursion { 10.53.0.1; }; + notify yes; + dnssec-validation yes; + + dns64 2001:bbbb::/96 { + clients { any; }; + mapped { !rfc1918; any; }; + exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; }; + suffix ::; + recursive-only yes; + }; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "signed" { + type primary; + file "signed.db.signed"; +}; + +zone "ipv4only.arpa" { + type primary; + file "ipv4only.arpa.db"; +}; diff --git a/bin/tests/system/dns64/ns1/named.conf2.in b/bin/tests/system/dns64/ns1/named.conf2.in new file mode 100644 index 0000000..d7a6d1f --- /dev/null +++ b/bin/tests/system/dns64/ns1/named.conf2.in @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-recursion { 10.53.0.1; }; + notify yes; + dnssec-validation yes; + + dns64 2001:bbbb::/96 { + clients { any; }; + mapped { !rfc1918; any; }; + exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; }; + suffix ::; + recursive-only yes; + }; + dns64 2001:aaaa::/64 { + mapped { !rfc1918; any; }; + }; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "signed" { + type primary; + file "signed.db.signed"; +}; + +zone "ipv4only.arpa" { + type primary; + file "ipv4only.arpa.db"; +}; diff --git a/bin/tests/system/dns64/ns1/named.conf3.in b/bin/tests/system/dns64/ns1/named.conf3.in new file mode 100644 index 0000000..393e623 --- /dev/null +++ b/bin/tests/system/dns64/ns1/named.conf3.in @@ -0,0 +1,57 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-recursion { 10.53.0.1; }; + notify yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "signed" { + type primary; + file "signed.db.signed"; +}; + +zone "ipv4only.arpa" { + type primary; + file "ipv4only.arpa.db"; +}; diff --git a/bin/tests/system/dns64/ns1/root.db b/bin/tests/system/dns64/ns1/root.db new file mode 100644 index 0000000..0e3bbee --- /dev/null +++ b/bin/tests/system/dns64/ns1/root.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +example NS ns1.example. +ns1.example. A 10.53.0.1 +signed NS ns1.example. +ns1.signed. A 10.53.0.1 diff --git a/bin/tests/system/dns64/ns1/sign.sh b/bin/tests/system/dns64/ns1/sign.sh new file mode 100644 index 0000000..1a0acfd --- /dev/null +++ b/bin/tests/system/dns64/ns1/sign.sh @@ -0,0 +1,25 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=signed +infile=example.db +zonefile=signed.db + +key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM $zone) +key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null diff --git a/bin/tests/system/dns64/ns2/named.conf.in b/bin/tests/system/dns64/ns2/named.conf.in new file mode 100644 index 0000000..49299aa --- /dev/null +++ b/bin/tests/system/dns64/ns2/named.conf.in @@ -0,0 +1,73 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + + dns64 2001:aaaa::/96 { + clients { 10.53.0.2; }; + mapped { !rfc1918; any; }; + exclude { 2001:eeee::/32; 64:FF9B::/96; ::ffff:0000:0000/96; }; + suffix ::; + }; + + dns64 64:FF9B::/96 { + clients { 10.53.0.1; }; + mapped { !192.228.79.201; !rfc1918; any; }; + exclude { 64:FF9B::/96; ::ffff:0000:0000/96; }; + suffix ::; + }; + + dns64 2001:bbbb::/96 { + clients { 10.53.0.4; }; + mapped { !rfc1918; any; }; + suffix ::; + }; + + dns64-server "dns64.example.net."; + dns64-contact "hostmaster.example.net."; + dns64 2001:32::/32 { clients { 10.53.0.6; }; }; + dns64 2001:40::/40 { clients { 10.53.0.6; }; }; + dns64 2001:48::/48 { clients { 10.53.0.6; }; }; + dns64 2001:56::/56 { clients { 10.53.0.6; }; }; + dns64 2001:64::/64 { clients { 10.53.0.6; }; }; + + dns64 2001:96::/96 { clients { 10.53.0.7; }; }; + + response-policy { zone "rpz"; }; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "rpz" { + type primary; + file "rpz.db"; +}; diff --git a/bin/tests/system/dns64/ns2/rpz.db b/bin/tests/system/dns64/ns2/rpz.db new file mode 100644 index 0000000..014cbf0 --- /dev/null +++ b/bin/tests/system/dns64/ns2/rpz.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 ; 1 day +@ IN SOA rpz. noc.rpz. ( + 1 ; serial + 86400 ; refresh (1 day) + 3600 ; retry (1 hour) + 2592000 ; expire (4 weeks 2 days) + 25200 ; minimum (7 hours) + ) + NS @ + IN A 10.53.0.2 + +rpz.example IN A 10.10.10.10 diff --git a/bin/tests/system/dns64/ns3/hints b/bin/tests/system/dns64/ns3/hints new file mode 100644 index 0000000..3685f54 --- /dev/null +++ b/bin/tests/system/dns64/ns3/hints @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.4 diff --git a/bin/tests/system/dns64/ns3/named.conf.in b/bin/tests/system/dns64/ns3/named.conf.in new file mode 100644 index 0000000..a86686b --- /dev/null +++ b/bin/tests/system/dns64/ns3/named.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +// NS3 + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.3; + query-source-v6 address fd92:7065:b8e:ffff::3; + notify-source 10.53.0.3; + notify-source-v6 fd92:7065:b8e:ffff::3; + transfer-source 10.53.0.3; + transfer-source-v6 fd92:7065:b8e:ffff::3; + port @EXTRAPORT1@; + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.3; }; // for start.pl + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + notify yes; + dnssec-validation yes; + allow-recursion { any; }; + resolver-use-dns64 yes; + + dns64 fd92:7065:b8e:fffe::/96 { + clients { any; }; + mapped { 10.53.0.4; !rfc1918; any; }; + suffix ::; + }; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "hints"; +}; diff --git a/bin/tests/system/dns64/ns4/named.conf.in b/bin/tests/system/dns64/ns4/named.conf.in new file mode 100644 index 0000000..485cdc8 --- /dev/null +++ b/bin/tests/system/dns64/ns4/named.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +// NS4 + +options { + query-source address 10.53.0.4; + query-source-v6 address fd92:7065:b8e:fffe::10.53.0.4; + notify-source 10.53.0.4; + notify-source-v6 fd92:7065:b8e:fffe::10.53.0.4; + transfer-source 10.53.0.4; + transfer-source-v6 fd92:7065:b8e:fffe::10.53.0.4; + port @EXTRAPORT1@; + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.4; }; // for start.pl + listen-on-v6 { fd92:7065:b8e:fffe::10.53.0.4; }; + notify yes; + dnssec-validation yes; + recursion no; +}; + +trust-anchors { }; + +zone "." { + type master; + file "root.db"; +}; diff --git a/bin/tests/system/dns64/ns4/root.db b/bin/tests/system/dns64/ns4/root.db new file mode 100644 index 0000000..afa7c8a --- /dev/null +++ b/bin/tests/system/dns64/ns4/root.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN SOA a.root-servers.nil. . 0 0 0 0 0 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.4 +no-aaaa IN A 1.2.3.4 +have-aaaa IN AAAA 2002::1 diff --git a/bin/tests/system/dns64/setup.sh b/bin/tests/system/dns64/setup.sh new file mode 100644 index 0000000..e6df4d0 --- /dev/null +++ b/bin/tests/system/dns64/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf1.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +cd ns1 && $SHELL sign.sh diff --git a/bin/tests/system/dns64/tests.sh b/bin/tests/system/dns64/tests.sh new file mode 100644 index 0000000..df6e05b --- /dev/null +++ b/bin/tests/system/dns64/tests.sh @@ -0,0 +1,1465 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}" + +for conf in conf/good*.conf; do + echo_i "checking that $conf is accepted ($n)" + ret=0 + $CHECKCONF "$conf" || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for conf in conf/bad*.conf; do + echo_i "checking that $conf is rejected ($n)" + ret=0 + $CHECKCONF "$conf" >/dev/null && ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +# Check the example. domain + +echo_i "checking non-excluded AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking default exclude acl ignores mapped A records (all mapped) ($n)" +ret=0 +$DIG $DIGOPTS a-and-mapped.example. @10.53.0.2 -b 10.53.0.4 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::1.2.3.5" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking default exclude acl ignores mapped A records (some mapped) ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa-and-mapped.example. @10.53.0.2 -b 10.53.0.4 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::4" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::ffff:1.2.3.4" dig.out.ns2.test$n >/dev/null && ret=1 +grep "::ffff:1.2.3.5" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking default exclude acl works with AAAA only ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.4 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking default exclude acl A only lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.4 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially excluded only AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded AAAA and non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded only AAAA and mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA lookup works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::1.2.3.4" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the example. domain recursive only + +echo_i "checking non-excluded AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::1.2.3.4" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially excluded only AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded AAAA and non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded only AAAA and mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::102:304" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:bbbb::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME lookup works, recursive only ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the example. domain recursive only w/o recursion + +echo_i "checking non-excluded AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially excluded only AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded AAAA and non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking partially-excluded only AAAA and mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec partially-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee:" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-bad-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-excluded-good-a.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-aaaa-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-only.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-and-aaaa.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-a-not-mapped.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-mx-only.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME lookup works, recursive only +norec ($n)" +ret=0 +$DIG $DIGOPTS +norec cname-non-existent.example. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the example. domain from non client + +echo_i "checking non-excluded AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.example." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME from non-client lookup works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.example. @10.53.0.2 -b 10.53.0.3 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the signed. domain + +echo_i "checking non-excluded AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:304" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:304" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.signed." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME lookup is signed zone works ($n)" +ret=0 +$DIG $DIGOPTS cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the signed. domain +echo_i "checking non-excluded AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-excluded AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded AAAA and non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-bad-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking excluded only AAAA and mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-excluded-good-a.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:eeee::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA only via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-aaaa-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::2" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A only via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:aaaa::102:305" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A and AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-and-aaaa.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001::1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-mapped A via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-a-not-mapped.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2" dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME a-not-mapped.signed." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NODATA AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-mx-only.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +grep "CNAME mx-only.signed." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking non-existent AAAA via CNAME lookup is signed zone works with +dnssec ($n)" +ret=0 +$DIG $DIGOPTS +dnssec cname-non-existent.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking reverse mapping ($n)" +ret=0 +$DIG $DIGOPTS -x 2001:aaaa::10.0.0.1 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep -i "CNAME.1.0.0.10.IN-ADDR.ARPA.$" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +list=$($DIG $DIGOPTS -b 10.53.0.6 @10.53.0.2 +short aaaa a-only.example | sort) +for a in $list; do + ret=0 + echo_i "checking reverse mapping of $a ($n)" + $DIG $DIGOPTS -x $a @10.53.0.2 >dig.out.ns2.test$n || ret=1 + grep -i "CNAME.5.3.2.1.IN-ADDR.ARPA." dig.out.ns2.test$n >/dev/null || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +rev=$($ARPANAME 2001:aaaa::10.0.0.1) +regex='..\(.*.IP6.ARPA\)' +rev=$(expr "${rev}" : "${regex}") +fin=$(expr "${rev}" : "............${regex}") +while test "${rev}" != "${fin}"; do + ret=0 + echo_i "checking $rev ($n)" + $DIG $DIGOPTS $rev ptr @10.53.0.2 >dig.out.ns2.test$n || ret=1 + grep -i "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 + grep -i "ANSWER: 0," dig.out.ns2.test$n >/dev/null || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + rev=$(expr "${rev}" : "${regex}") +done + +echo_i "checking dns64-server and dns64-contact ($n)" +ret=0 +$DIG $DIGOPTS soa 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.a.a.a.1.0.0.2.ip6.arpa @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "SOA.dns64.example.net..hostmaster.example.net." dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL less than 600 from zone ($n)" +ret=0 +#expect 500 +$DIG $DIGOPTS aaaa ttl-less-than-600.example +rec @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep -i "ttl-less-than-600.example..500.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL more than 600 from zone ($n)" +ret=0 +#expect 700 +$DIG $DIGOPTS aaaa ttl-more-than-600.example +rec @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep -i "ttl-more-than-600.example..700.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL less than minimum from zone ($n)" +ret=0 +#expect 1100 +$DIG $DIGOPTS aaaa ttl-less-than-minimum.example +rec @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep -i "ttl-less-than-minimum.example..1100.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL limited to minimum from zone ($n)" +ret=0 +#expect 1200 +$DIG $DIGOPTS aaaa ttl-more-than-minimum.example +rec @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep -i "ttl-more-than-minimum.example..1200.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL less than 600 via cache ($n)" +ret=0 +#expect 500 +$DIG $DIGOPTS aaaa ttl-less-than-600.example +rec -b 10.53.0.2 @10.53.0.2 >dig.out.ns1.test$n || ret=1 +grep -i "ttl-less-than-600.example..500.IN.AAAA" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL more than 600 via cache ($n)" +ret=0 +#expect 700 +$DIG $DIGOPTS aaaa ttl-more-than-600.example +rec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep -i "ttl-more-than-600.example..700.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL less than minimum via cache ($n)" +ret=0 +#expect 1100 +$DIG $DIGOPTS aaaa ttl-less-than-minimum.example +rec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep -i "ttl-less-than-minimum.example..1100.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TTL limited to minimum via cache ($n)" +ret=0 +#expect 1200 +$DIG $DIGOPTS aaaa ttl-more-than-minimum.example +rec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep -i "ttl-more-than-minimum.example..1200.IN.AAAA" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking synthesis of AAAA from RPZ-remapped A ($n)" +ret=0 +$DIG $DIGOPTS aaaa rpz.example +rec -b 10.53.0.7 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep -i 'rpz.example.*IN.AAAA.2001:96::a0a:a0a' dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking 'dig +dns64prefix' ($n)" +$DIG $DIGOPTS +dns64prefix @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep '^2001:bbbb::/96$' dig.out.ns1.test$n >/dev/null || ret=1 +test $(wc -l dig.out.ns1.test$n || ret=1 +grep '^2001:bbbb::/96$' dig.out.ns1.test$n >/dev/null || ret=1 +grep '2001:aaaa::/64' dig.out.ns1.test$n >/dev/null || ret=1 +test $(wc -l dig.out.ns1.test$n || ret=1 +test $(wc -l dig.out.ns2.test$n || ret=1 +grep -i 'ipv4only.arpa.*IN.AAAA.2001:96::c000:aa' dig.out.ns2.test$n >/dev/null || ret=1 +grep -i 'ipv4only.arpa.*IN.AAAA.2001:96::c000:ab' dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking reverse of dns64 mapped ipv4only.arpa addresses returns ipv4only.arpa ($n)" +ret=0 +$DIG $DIGOPTS ptr -x 2001:96::192.0.0.170 -b 10.53.0.7 @10.53.0.2 >dig.out.170.ns2.test$n || ret=1 +$DIG $DIGOPTS ptr -x 2001:96::192.0.0.171 -b 10.53.0.7 @10.53.0.2 >dig.out.171.ns2.test$n || ret=1 +grep "ip6\.arpa\..*PTR.*ipv4only\.arpa\." dig.out.170.ns2.test$n >/dev/null || ret=1 +grep "ip6\.arpa\..*PTR.*ipv4only\.arpa\." dig.out.171.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if $PERL ../testsock6.pl fd92:7065:b8e:fffe::10.53.0.4 2>/dev/null; then + echo_i "checking resolver-use-dns64 ($n)" + ret=0 + $DIG $DIGOPTS @10.53.0.3 no-aaaa aaaa >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "fd92:7065:b8e:fffe::102:304" dig.out.ns3.test$n >/dev/null || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped use-dns64 test - fd92:7065:b8e:fffe::10.53.0.4 not configured ($n)" +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dns64/tests_sh_dns64.py b/bin/tests/system/dns64/tests_sh_dns64.py new file mode 100644 index 0000000..a7af9cf --- /dev/null +++ b/bin/tests/system/dns64/tests_sh_dns64.py @@ -0,0 +1,25 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns1/K*", + "ns1/dsset-signed.", + "ns1/signed.db*", + ] +) + + +def test_dns64(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/dnssec/README b/bin/tests/system/dnssec/README new file mode 100644 index 0000000..fcaa3b6 --- /dev/null +++ b/bin/tests/system/dnssec/README @@ -0,0 +1,32 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The test setup for the DNSSEC tests has a secure root. + +ns1 is the root server. + +ns2 and ns3 are authoritative servers for the various test domains. + +ns4 is a caching-only server, configured with the correct trusted key +for the root. + +ns5 is a caching-only server, configured with the an incorrect trusted +key for the root. It is used for testing failure cases. + +ns6 is an caching and authoritative server used for testing unusual +server behaviors such as disabled DNSSEC algorithms. + +ns7 is used for checking non-cacheable answers. + +ns8 is a caching-only server, configured with unsupported and disabled +algorithms. It is used for testing failure cases. + +ns9 is a forwarding-only server. diff --git a/bin/tests/system/dnssec/ans10/ans.py b/bin/tests/system/dnssec/ans10/ans.py new file mode 100644 index 0000000..84bf0a2 --- /dev/null +++ b/bin/tests/system/dnssec/ans10/ans.py @@ -0,0 +1,164 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns, dns.message, dns.query, dns.flags +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + + +############################################################################ +# Respond to a DNS query. +# SOA gets a unsigned response. +# NS gets a unsigned response. +# DNSKEY get a unsigned NODATA response. +# A gets a signed response. +# TXT gets a signed NODATA response without RRSIG. +# All other types get a unsigned NODATA response. +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, qname)) + print("%s %s" % (typename, qname), end=" ") + + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + if rrtype == A: + now = datetime.today() + expire = now + timedelta(days=30) + inception = now - timedelta(days=1) + rrsig = ( + "A 13 2 60 " + + expire.strftime("%Y%m%d%H%M%S") + + " " + + inception.strftime("%Y%m%d%H%M%S") + + " 12345 " + + qname + + " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl" + + "y2Qs7y5VCjSMOGn85bnaMoAc7w==" + ) + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + r.answer.append(dns.rrset.from_text(qname, 1, IN, RRSIG, rrsig)) + elif rrtype == NS: + r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, ".")) + elif rrtype == SOA: + r.answer.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0")) + elif rrtype == TXT: + r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0")) + r.authority.append( + dns.rrset.from_text(qname, 1, IN, NSEC, qname + " A NS SOA RRSIG NSEC") + ) + else: + r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0")) + r.flags |= dns.flags.AA + return r + + +def sigterm(signum, frame): + print("Shutting down now...") + os.remove("ans.pid") + running = False + sys.exit(0) + + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.10" +ip6 = "fd92:7065:b8e:ffff::10" + +try: + port = int(os.environ["PORT"]) +except: + port = 5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False +signal.signal(signal.SIGTERM, sigterm) + +f = open("ans.pid", "w") +pid = os.getpid() +print(pid, file=f) +f.close() + +running = True + +print("Listening on %s port %d" % (ip4, port)) +if havev6: + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket] +else: + input = [query4_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_socket or s == query6_socket: + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE") + if not running: + break diff --git a/bin/tests/system/dnssec/dnssec_update_test.pl b/bin/tests/system/dnssec/dnssec_update_test.pl new file mode 100644 index 0000000..a06c563 --- /dev/null +++ b/bin/tests/system/dnssec/dnssec_update_test.pl @@ -0,0 +1,99 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# DNSSEC Dynamic update test suite. +# +# Usage: +# +# perl update_test.pl [-s server] [-p port] zone +# +# The server defaults to 127.0.0.1. +# The port defaults to 53. +# +# Installation notes: +# +# This program uses the Net::DNS::Resolver module. +# You can install it by saying +# +# perl -MCPAN -e "install Net::DNS" +# + +use Getopt::Std; +use Net::DNS; +use Net::DNS::Update; +use Net::DNS::Resolver; + +$opt_s = "127.0.0.1"; +$opt_p = 53; + +getopt('s:p:'); + +$res = new Net::DNS::Resolver; +$res->nameservers($opt_s); +$res->port($opt_p); +$res->defnames(0); # Do not append default domain. + +@ARGV == 1 or die + "usage: perl update_test.pl [-s server] [-p port] zone\n"; + +$zone = shift @ARGV; + +my $failures = 0; + +sub assert { + my ($cond, $explanation) = @_; + if (!$cond) { + print "Test Failed: $explanation ***\n"; + $failures++ + } +} + +sub test { + my ($expected, @records) = @_; + + my $update = new Net::DNS::Update("$zone"); + + foreach $rec (@records) { + $update->push(@$rec); + } + + $reply = $res->send($update); + + # Did it work? + if (defined $reply) { + my $rcode = $reply->header->rcode; + assert($rcode eq $expected, "expected $expected, got $rcode"); + } else { + print "Update failed: ", $res->errorstring, "\n"; + } +} + +sub section { + my ($msg) = @_; + print "$msg\n"; +} + +section("Add a name"); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); + +section("Delete the name"); +test("NOERROR", ["update", rr_del("a.$zone")]); + +if ($failures) { + print "$failures update tests failed.\n"; +} else { + print "All update tests successful.\n"; +} + +exit $failures; diff --git a/bin/tests/system/dnssec/ns1/named.conf.in b/bin/tests/system/dnssec/ns1/named.conf.in new file mode 100644 index 0000000..bd1ccc4 --- /dev/null +++ b/bin/tests/system/dnssec/ns1/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; + /* test that we can turn off trust-anchor-telemetry */ + trust-anchor-telemetry no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns1/root.db.in b/bin/tests/system/dnssec/ns1/root.db.in new file mode 100644 index 0000000..1e7a5c7 --- /dev/null +++ b/bin/tests/system/dnssec/ns1/root.db.in @@ -0,0 +1,47 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +algroll. NS ns2.algroll. +ns2.algroll. A 10.53.0.2 +managed. NS ns2.managed. +ns2.managed. A 10.53.0.2 +trusted. NS ns2.trusted. +ns2.trusted. A 10.53.0.2 +lazy-ksk. NS ns2.lazy-ksk. +ns2.lazy-ksk. A 10.53.0.2 +optout-tld NS ns6.optout-tld. +ns6.optout-tld. A 10.53.0.6 +in-addr.arpa. NS ns2.example. +inprogress. NS ns10.inprogress. +ns10.inprogress. A 10.53.0.10 +too-many-iterations. NS ns2.too-many-iterations. +ns2.too-many-iterations. A 10.53.0.2 +dnskey-rrsigs-stripped. NS ns2.dnskey-rrsigs-stripped. +ns2.dnskey-rrsigs-stripped. A 10.53.0.2 +ds-rrsigs-stripped. NS ns2.ds-rrsigs-stripped. +ns2.ds-rrsigs-stripped. A 10.53.0.2 +inconsistent. NS ns2.inconsistent. +ns2.inconsistent. A 10.53.0.2 +nsec-rrsigs-stripped. NS ns10.nsec-rrsigs-stripped. +ns10.nsec-rrsigs-stripped. A 10.53.0.10 diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh new file mode 100644 index 0000000..62331d6 --- /dev/null +++ b/bin/tests/system/dnssec/ns1/sign.sh @@ -0,0 +1,66 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +zone=. +infile=root.db.in +zonefile=root.db + +(cd ../ns2 && $SHELL sign.sh) +(cd ../ns6 && $SHELL sign.sh) +(cd ../ns7 && $SHELL sign.sh) + +echo_i "ns1/sign.sh" + +cp "../ns2/dsset-example." . +cp "../ns2/dsset-in-addr.arpa." . +cp "../ns2/dsset-too-many-iterations." . +cp "../ns2/dsset-lazy-ksk." . +cp "../ns2/dsset-dnskey-rrsigs-stripped." . +cp "../ns2/dsset-ds-rrsigs-stripped." . +cp "../ns2/dsset-inconsistent." . + +grep "$DEFAULT_ALGORITHM_NUMBER [12] " "../ns2/dsset-algroll." >"dsset-algroll." +cp "../ns6/dsset-optout-tld." . + +ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" + +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# Configure the resolving server with a staitc key. +keyfile_to_static_ds "$ksk" >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns4/trusted.conf +cp trusted.conf ../ns6/trusted.conf +cp trusted.conf ../ns7/trusted.conf +cp trusted.conf ../ns9/trusted.conf + +keyfile_to_trusted_keys "$ksk" >trusted.keys + +# ...or with an initializing key. +keyfile_to_initial_ds "$ksk" >managed.conf +cp managed.conf ../ns4/managed.conf + +# +# Save keyid for managed key id test. +# + +keyfile_to_key_id "$ksk" >managed.key.id diff --git a/bin/tests/system/dnssec/ns2/algroll.db.in b/bin/tests/system/dnssec/ns2/algroll.db.in new file mode 100644 index 0000000..6f66fc9 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/algroll.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns2/badparam.db.in b/bin/tests/system/dnssec/ns2/badparam.db.in new file mode 100644 index 0000000..b18d186 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/badparam.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2010081000 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cdnskey-auto.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cdnskey-update.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in b/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cdnskey.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in b/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cds-auto.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/cds-update.secure.db.in b/bin/tests/system/dnssec/ns2/cds-update.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cds-update.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/cds.secure.db.in b/bin/tests/system/dnssec/ns2/cds.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/cds.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/child.ds-rrsigs-stripped.db.in b/bin/tests/system/dnssec/ns2/child.ds-rrsigs-stripped.db.in new file mode 100644 index 0000000..5fcc74d --- /dev/null +++ b/bin/tests/system/dnssec/ns2/child.ds-rrsigs-stripped.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns2/child.nsec3.example.db b/bin/tests/system/dnssec/ns2/child.nsec3.example.db new file mode 100644 index 0000000..8fc3bc8 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/child.nsec3.example.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2006081400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ IN NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/child.optout.example.db b/bin/tests/system/dnssec/ns2/child.optout.example.db new file mode 100644 index 0000000..8fc3bc8 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/child.optout.example.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2006081400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ IN NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/corp.db b/bin/tests/system/dnssec/ns2/corp.db new file mode 100644 index 0000000..b2912bc --- /dev/null +++ b/bin/tests/system/dnssec/ns2/corp.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +www A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns2/dnskey-rrsigs-stripped.db.in b/bin/tests/system/dnssec/ns2/dnskey-rrsigs-stripped.db.in new file mode 100644 index 0000000..5fcc74d --- /dev/null +++ b/bin/tests/system/dnssec/ns2/dnskey-rrsigs-stripped.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns2/ds-rrsigs-stripped.db.in b/bin/tests/system/dnssec/ns2/ds-rrsigs-stripped.db.in new file mode 100644 index 0000000..7b1a7a5 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/ds-rrsigs-stripped.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +child NS ns2.child +ns2.child A 10.53.0.2 +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns2/dst.example.db.in b/bin/tests/system/dnssec/ns2/dst.example.db.in new file mode 100644 index 0000000..0039484 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/dst.example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2.example. +a A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in new file mode 100644 index 0000000..72e3c1f --- /dev/null +++ b/bin/tests/system/dnssec/ns2/example.db.in @@ -0,0 +1,183 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +bad-cname CNAME a +bad-dname DNAME @ + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns3.secure +ns3.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A second insecure subdomain +insecure2 NS ns.insecure2 +ns.insecure2 A 10.53.0.3 + +; A secure subdomain we're going to inject bogus data into +bogus NS ns.bogus +ns.bogus A 10.53.0.3 + +; A subdomain with a corrupt DS +badds NS ns.badds +ns.badds A 10.53.0.3 + +; A dynamic secure subdomain +dynamic NS dynamic +dynamic A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +; A subdomain with expired signatures +expired NS ns.expired +ns.expired A 10.53.0.3 + +; A rfc2535 signed zone w/ CNAME +rfc2535 NS ns.rfc2535 +ns.rfc2535 A 10.53.0.3 + +z A 10.0.0.26 + +keyless NS ns.keyless +ns.keyless A 10.53.0.3 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +dnskey-unknown NS ns.dnskey-unknown +ns.dnskey-unknown A 10.53.0.3 + +dnskey-unsupported NS ns.dnskey-unsupported +ns.dnskey-unsupported A 10.53.0.3 + +ds-unsupported NS ns.ds-unsupported +ns.ds-unsupported A 10.53.0.3 + +digest-alg-unsupported NS ns.digest-alg-unsupported +ns.digest-alg-unsupported A 10.53.0.3 + +dnskey-nsec3-unknown NS ns.dnskey-nsec3-unknown +ns.dnskey-nsec3-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +*.wild A 10.0.0.27 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 + +kskonly NS ns.kskonly +ns.kskonly A 10.53.0.3 + +update-nsec3 NS ns.update-nsec3 +ns.update-nsec3 A 10.53.0.3 + +auto-nsec NS ns.auto-nsec +ns.auto-nsec A 10.53.0.3 + +auto-nsec3 NS ns.auto-nsec3 +ns.auto-nsec3 A 10.53.0.3 + + +below-cname CNAME some.where.else. + +insecure.below-cname NS ns.insecure.below-cname +ns.insecure.below-cname A 10.53.0.3 + +secure.below-cname NS ns.secure.below-cname +ns.secure.below-cname A 10.53.0.3 + +ttlpatch NS ns.ttlpatch +ns.ttlpatch A 10.53.0.3 + +split-dnssec NS ns.split-dnssec +ns.split-dnssec A 10.53.0.3 + +split-smart NS ns.split-smart +ns.split-smart A 10.53.0.3 + +upper NS ns.upper +ns.upper A 10.53.0.3 + +LOWER NS NS.LOWER +NS.LOWER A 10.53.0.3 + +expiring NS ns.expiring +ns.expiring A 10.53.0.3 + +future NS ns.future +ns.future A 10.53.0.3 + +managed-future NS ns.managed-future +ns.managed-future A 10.53.0.3 + +revkey NS ns.revkey +ns.revkey A 10.53.0.3 + +rsasha1 NS ns.rsasha1 +ns.rsasha1 A 10.53.0.3 + +rsasha1-1024 NS ns.rsasha1-1024 +ns.rsasha1-1024 A 10.53.0.3 + +dname-at-apex-nsec3 NS ns3 diff --git a/bin/tests/system/dnssec/ns2/hours-vs-days.db.in b/bin/tests/system/dnssec/ns2/hours-vs-days.db.in new file mode 100644 index 0000000..5ec8801 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/hours-vs-days.db.in @@ -0,0 +1,167 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +bad-cname CNAME a +bad-dname DNAME @ + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns3.secure +ns3.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A secure subdomain we're going to inject bogus data into +bogus NS ns.bogus +ns.bogus A 10.53.0.3 + +; A subdomain with a corrupt DS +badds NS ns.badds +ns.badds A 10.53.0.3 + +; A dynamic secure subdomain +dynamic NS dynamic +dynamic A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +; A subdomain with expired signatures +expired NS ns.expired +ns.expired A 10.53.0.3 + +; A rfc2535 signed zone w/ CNAME +rfc2535 NS ns.rfc2535 +ns.rfc2535 A 10.53.0.3 + +z A 10.0.0.26 + +keyless NS ns.keyless +ns.keyless A 10.53.0.3 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +dnskey-unknown NS ns.dnskey-unknown +ns.dnskey-unknown A 10.53.0.3 + +dnskey-unsupported NS ns.dnskey-unsupported +ns.dnskey-unsupported A 10.53.0.3 + +dnskey-nsec3-unknown NS ns.dnskey-nsec3-unknown +ns.dnskey-nsec3-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +*.wild A 10.0.0.27 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 + +kskonly NS ns.kskonly +ns.kskonly A 10.53.0.3 + +update-nsec3 NS ns.update-nsec3 +ns.update-nsec3 A 10.53.0.3 + +auto-nsec NS ns.auto-nsec +ns.auto-nsec A 10.53.0.3 + +auto-nsec3 NS ns.auto-nsec3 +ns.auto-nsec3 A 10.53.0.3 + + +below-cname CNAME some.where.else. + +insecure.below-cname NS ns.insecure.below-cname +ns.insecure.below-cname A 10.53.0.3 + +secure.below-cname NS ns.secure.below-cname +ns.secure.below-cname A 10.53.0.3 + +ttlpatch NS ns.ttlpatch +ns.ttlpatch A 10.53.0.3 + +split-dnssec NS ns.split-dnssec +ns.split-dnssec A 10.53.0.3 + +split-smart NS ns.split-smart +ns.split-smart A 10.53.0.3 + +upper NS ns.upper +ns.upper A 10.53.0.3 + +LOWER NS NS.LOWER +NS.LOWER A 10.53.0.3 + +expiring NS ns.expiring +ns.expiring A 10.53.0.3 + +future NS ns.future +ns.future A 10.53.0.3 + +managed-future NS ns.managed-future +ns.managed-future A 10.53.0.3 + +revkey NS ns.revkey +ns.revkey A 10.53.0.3 + +dname-at-apex-nsec3 NS ns3 diff --git a/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in b/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in new file mode 100644 index 0000000..874b915 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/in-addr.arpa.db.in @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. +; +; As we are testing empty zone behaviour ns3 doesn't need to be +; configured to serve 10.in-addr.arpa. +; +10 NS ns3.example. diff --git a/bin/tests/system/dnssec/ns2/inconsistent.db.in b/bin/tests/system/dnssec/ns2/inconsistent.db.in new file mode 100644 index 0000000..0f9c211 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/inconsistent.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns2.example. . ( + 2010042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2.example. + NS ns3.example. + A 10.53.0.1 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns2/insecure.secure.example.db b/bin/tests/system/dnssec/ns2/insecure.secure.example.db new file mode 100644 index 0000000..62862f5 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/insecure.secure.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns2/key.db.in b/bin/tests/system/dnssec/ns2/key.db.in new file mode 100644 index 0000000..2ff5df4 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/key.db.in @@ -0,0 +1,45 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; A secure subdomain +secure NS ns3.secure +ns3.secure A 10.53.0.3 + +; A subdomain that is signed with an unsupported algorithm +unsupported NS ns3.unsupported +ns3.unsupported A 10.53.0.3 + +; A secure subdomain with a disabled algorithm +disabled NS ns3.disabled +ns3.disabled A 10.53.0.3 + +; A secure subdomain with a disabled algorithm, but not in bailiwick +enabled NS ns3.enabled +ns3.enabled A 10.53.0.3 + +; A secure subdomain with a revoked trust anchor +revoked NS ns3.revoked +ns3.revoked A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns2/lazy-ksk.db.in b/bin/tests/system/dnssec/ns2/lazy-ksk.db.in new file mode 100644 index 0000000..1527e07 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/lazy-ksk.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +*.a A 10.0.0.3 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns2/named.conf.in b/bin/tests/system/dnssec/ns2/named.conf.in new file mode 100644 index 0000000..1eb3b59 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/named.conf.in @@ -0,0 +1,237 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; + notify-delay 1; + minimal-responses no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "dnssec" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "kskonly" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + signatures-validity 10d; + signatures-validity-dnskey 40d; +}; + +dnssec-policy "not-enough-hours-in-day" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + /* validity 500 days, with one 1 day jitter (resign in 499 days) */ + signatures-jitter 1d; + signatures-validity-dnskey 500d; + signatures-validity 500d; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "trusted" { + type primary; + file "trusted.db.signed"; +}; + +zone "managed" { + type primary; + file "managed.db.signed"; +}; + +zone "example" { + type primary; + file "example.db.signed"; + allow-update { any; }; +}; + +zone "insecure.secure.example" { + type primary; + file "insecure.secure.example.db"; + allow-update { any; }; +}; + +zone "rfc2335.example" { + type primary; + file "rfc2335.example.db"; +}; + +zone "child.nsec3.example" { + type primary; + file "child.nsec3.example.db"; + allow-update { none; }; +}; + +zone "child.optout.example" { + type primary; + file "child.optout.example.db"; + allow-update { none; }; +}; + +zone "badparam" { + type primary; + file "badparam.db.bad"; +}; + +zone "single-nsec3" { + type primary; + file "single-nsec3.db.signed"; +}; + +zone "algroll" { + type primary; + file "algroll.db.signed"; +}; + +zone "nsec3chain-test" { + type primary; + file "nsec3chain-test.db.signed"; + allow-update {any;}; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.arpa.db.signed"; +}; + +zone "cds.secure" { + type primary; + file "cds.secure.db.signed"; +}; + +zone "cds-x.secure" { + type primary; + file "cds-x.secure.db.signed"; +}; + +zone "cds-update.secure" { + type primary; + file "cds-update.secure.db.signed"; + allow-update { any; }; +}; + +zone "cds-auto.secure" { + type primary; + file "cds-auto.secure.db.signed"; + dnssec-policy dnssec; + allow-update { any; }; +}; + +zone "cdnskey.secure" { + type primary; + file "cdnskey.secure.db.signed"; +}; + +zone "cdnskey-x.secure" { + type primary; + file "cdnskey-x.secure.db.signed"; +}; + +zone "cdnskey-update.secure" { + type primary; + file "cdnskey-update.secure.db.signed"; + allow-update { any; }; +}; + +zone "cdnskey-auto.secure" { + type primary; + file "cdnskey-auto.secure.db.signed"; + dnssec-policy dnssec; + allow-update { any; }; +}; + +zone "updatecheck-kskonly.secure" { + type primary; + file "updatecheck-kskonly.secure.db.signed"; + dnssec-policy kskonly; + allow-update { any; }; +}; + +zone "corp" { + type primary; + file "corp.db"; +}; + +zone "hours-vs-days" { + type primary; + file "hours-vs-days.db.signed"; + dnssec-policy not-enough-hours-in-day; + allow-update { any; }; +}; + +zone "too-many-iterations" { + type primary; + file "too-many-iterations.db.signed"; +}; + +zone "inconsistent" { + type primary; + file "inconsistent.db.signed"; +}; + +zone "lazy-ksk" { + type primary; + file "lazy-ksk.db"; + dnssec-policy "dnssec"; + allow-update { any; }; +}; + +zone "dnskey-rrsigs-stripped" { + type primary; + file "dnskey-rrsigs-stripped.db.signed"; +}; + +zone "ds-rrsigs-stripped" { + type primary; + file "ds-rrsigs-stripped.db.signed"; +}; + +zone "child.ds-rrsigs-stripped" { + type primary; + file "child.ds-rrsigs-stripped.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns2/private.secure.example.db.in b/bin/tests/system/dnssec/ns2/private.secure.example.db.in new file mode 100644 index 0000000..94042ae --- /dev/null +++ b/bin/tests/system/dnssec/ns2/private.secure.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +private2secure-nxdomain CNAME r.example. +*.wild CNAME s.example. diff --git a/bin/tests/system/dnssec/ns2/rfc2335.example.db b/bin/tests/system/dnssec/ns2/rfc2335.example.db new file mode 100644 index 0000000..78e9326 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/rfc2335.example.db @@ -0,0 +1,114 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; File written on Fri Apr 30 12:19:15 2004 +; dnssec_signzone version 9.2.4rc3 +rfc2335.example. 300 IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + 300 SIG SOA 1 2 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + nGPJKIzF7X/hMJbZURRz59UeEi/6HRxCn9Er + GqSnpw0Ea9Yx5Axu6sLKnF7jXlkZ6NHMCIpJ + +Lv+FDHXTs/dQg== ) + 300 NS ns.rfc2335.example. + 300 SIG NS 1 2 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + Q234AL9dJYMvxdWG33lpww6AJ3GplKp+ace7 + MUaj0oqDdkx4DtJF2XaP2xcqq7kTOObdQ8ES + vVxNThqOx7LFzg== ) + 300 KEY 256 3 1 ( + AQPZhzXIabI8y5ihWUw7F0WxN2MabnYWkOcV + Fn11NgaGSdjBSYPRMMwMCasD5N2KYPRUP83W + y8mj+ofcoW1FurcZ + ) ; key id = 47799 + 300 NXT a.rfc2335.example. NS SOA SIG KEY NXT + 300 SIG NXT 1 2 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + Y587mqNy6pBEfbsU6+weM2XRSqLwLwRT9Sl7 + oNuOK9kV3TR4R2M54m2S0MgJCXbRAwU+fF8Q + UbZkSTVe2N8Nyg== ) +a.rfc2335.example. 300 IN A 10.0.0.1 + 300 SIG A 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + FnfWrcw5ire8ut25504zti5l///BdDMUAkJZ + UCLFiTW4lBGMcq1pqz64zltDZXCgJ3xUeQ2i + nRt19/ZxO6Z1KA== ) + 300 NXT b.rfc2335.example. A SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + R6SpC3ndMVg4u/eZaaUsXSuMHV/hZXeaM/Op + bJLAe3KxMiOHfb6XgLy7wflAiC1xt6A9bWpy + kTc5T5gfic33kA== ) +b.rfc2335.example. 300 IN A 10.0.0.2 + 300 SIG A 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + zjRsYXMGyhDI6ipDtu8YXC9XPN+3hGamzzxL + 8uPE/LPo+x19MNdbzEgWzlajAf1/mkSGr2jN + BDMVBA5NMKpwAA== ) + 300 NXT d.rfc2335.example. A SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + aV87iZCYsC5Tqop827Zzb18TNqopGt0QynkR + gIF/lIHqZasNFRfaS1/nTnXdDKD8JS5IqxKb + oTJr5zswDAtCEw== ) +d.rfc2335.example. 300 IN A 10.0.0.4 + 300 SIG A 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + NsKyvhUYZxTbOTBX4YwxTxevI5iGBpULKwmt + +D4l00ME4XRygOVmiqVDTT9dF1EgjDxOdfMT + hSjtCh5M1b2f6g== ) + 300 NXT ns.rfc2335.example. A SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + OGqlvSDZIZdHYigh4UAFzXfPze7vcQfgj7sN + +cAeoh4BL1gpa00DqANCxowNCYluDk3ZCDwt + UHZEJa8ZjNvv4g== ) +ns.rfc2335.example. 300 IN A 10.53.0.3 + 300 SIG A 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + T6ZGeUWflLTku8jO23x/TeAPeUl8t0I18FCh + qHUZaHomLQasQ2jlZQn6cLpFd2uFJkBNxZ0G + I39aG7G1bObXdA== ) + 300 NXT x.rfc2335.example. A SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + l46mrf3/Ii5iRm3AiDjYeMg4ZXBgitHxXA2y + e/NhKpkxRRpCs7UQ94wT/RiSCjjK49E5FBe6 + 5bRxtWq0GI7zlg== ) +x.rfc2335.example. 300 IN CNAME a.rfc2335.example. + 300 SIG CNAME 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + L3IOluq+kboBd2gR2Mu54uJKCUzfmyHRiWKl + kfx+vuFr0I8mEHQRmJtouxNDrBzmzGp5vybK + SdabLWw0n6uQEA== ) + 300 NXT z.rfc2335.example. CNAME SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + CBKoJSkZzdpwiON7JS4yPFY5VVeBjfT19x/O + vx+5UK1JZUNKhTXWWgW1er+JlLzNf4Ot40+l + z9HUTyaeS0eWyw== ) +z.rfc2335.example. 300 IN A 10.0.0.26 + 300 SIG A 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + ccqjVHnehvVwlNNd4+7n/GzGlRjj+ul0gCT3 + X3950LTccxHsOFyjNNm8v/Ho/aurSYdqXEjY + jwmjC6elwkzB7A== ) + 300 NXT rfc2335.example. A SIG NXT + 300 SIG NXT 1 3 300 20040530021915 ( + 20040430021915 47799 rfc2335.example. + W42WoFyd9erysv8HjKo+CpHIH1x6+pAKwCDO + /hHnkEpQI3brewxl7cWOPYeA92Ns80Ody/ui + m2E28A5gnmWqPw== ) diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh new file mode 100644 index 0000000..501d6a3 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/sign.sh @@ -0,0 +1,412 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +# Sign child zones (served by ns3). +(cd ../ns3 && $SHELL sign.sh) + +echo_i "ns2/sign.sh" + +# Get the DS records for the "trusted." and "managed." zones. +for subdomain in secure unsupported disabled enabled; do + cp "../ns3/dsset-$subdomain.managed." . + cp "../ns3/dsset-$subdomain.trusted." . +done + +# Sign the "trusted." and "managed." zones. +zone=managed. +infile=key.db.in +zonefile=managed.db + +keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +zone=trusted. +infile=key.db.in +zonefile=trusted.db + +keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +# The "example." zone. +zone=example. +infile=example.db.in +zonefile=example.db + +# Get the DS records for the "example." zone. +for subdomain in digest-alg-unsupported ds-unsupported secure badds \ + bogus dynamic keyless nsec3 optout \ + nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \ + kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \ + ttlpatch split-dnssec split-smart expired expiring upper lower \ + dnskey-unknown dnskey-unsupported dnskey-unsupported-2 \ + dnskey-nsec3-unknown managed-future future revkey \ + dname-at-apex-nsec3 occluded rsasha1 rsasha1-1024; do + cp "../ns3/dsset-$subdomain.example." . +done + +# Sign the "example." zone. +keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +# +# lower/uppercase the signature bits with the exception of the last characters +# changing the last 4 characters will lead to a bad base64 encoding. +# + +zonefiletmp=$(mktemp "$zonefile.XXXXXX") || exit 1 +"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" \ + | awk ' +tolower($1) == "bad-cname.example." && $4 == "RRSIG" && $5 == "CNAME" { + for (i = 1; i <= NF; i++ ) { + if (i <= 12) { + printf("%s ", $i); + continue; + } + prefix = substr($i, 1, length($i) - 4); + suffix = substr($i, length($i) - 4, 4); + if (i > 12 && tolower(prefix) != prefix) + printf("%s%s", tolower(prefix), suffix); + else if (i > 12 && toupper(prefix) != prefix) + printf("%s%s", toupper(prefix), suffix); + else + printf("%s%s ", prefix, suffix); + } + printf("\n"); + next; +} + +tolower($1) == "bad-dname.example." && $4 == "RRSIG" && $5 == "DNAME" { + for (i = 1; i <= NF; i++ ) { + if (i <= 12) { + printf("%s ", $i); + continue; + } + prefix = substr($i, 1, length($i) - 4); + suffix = substr($i, length($i) - 4, 4); + if (i > 12 && tolower(prefix) != prefix) + printf("%s%s", tolower(prefix), suffix); + else if (i > 12 && toupper(prefix) != prefix) + printf("%s%s", toupper(prefix), suffix); + else + printf("%s%s ", prefix, suffix); + } + printf("\n"); + next; +} + +{ print; }' >"$zonefiletmp" && mv "$zonefiletmp" "$zonefile.signed" + +# +# signed in-addr.arpa w/ a delegation for 10.in-addr.arpa which is unsigned. +# +zone=in-addr.arpa. +infile=in-addr.arpa.db.in +zonefile=in-addr.arpa.db + +keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" +"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +# Sign the badparam secure file + +zone=badparam. +infile=badparam.db.in +zonefile=badparam.db + +keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -3 - -H 1 -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +sed -e 's/IN NSEC3 1 0 1 /IN NSEC3 1 0 10 /' "$zonefile.signed" >"$zonefile.bad" + +# Sign the single-nsec3 secure zone with optout + +zone=single-nsec3. +infile=single-nsec3.db.in +zonefile=single-nsec3.db + +keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -3 - -A -H 1 -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 + +# +# algroll has just has the old DNSKEY records removed and is waiting +# for them to be flushed from caches. We still need to generate +# RRSIGs for the old DNSKEY. +# +zone=algroll. +infile=algroll.db.in +zonefile=algroll.db + +keyold1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone -f KSK "$zone") +keyold2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -n zone "$zone") +keynew1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +keynew2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keynew1.key" "$keynew2.key" >"$zonefile" + +"$SIGNER" -o "$zone" -k "$keyold1" -k "$keynew1" "$zonefile" "$keyold1" "$keyold2" "$keynew1" "$keynew2" >/dev/null 2>&1 + +# +# Make a zone big enough that it takes several seconds to generate a new +# nsec3 chain. +# +zone=nsec3chain-test +zonefile=nsec3chain-test.db +cat >"$zonefile" <>"$zonefile" +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$key1.key" "$key2.key" >>"$zonefile" +"$SIGNER" -3 - -A -H 1 -g -o "$zone" -k "$key1" "$zonefile" "$key2" >/dev/null 2>&1 + +zone=cds.secure +infile=cds.secure.db.in +zonefile=cds.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +"$DSFROMKEY" -C "$key1.key" >"$key1.cds" +cat "$infile" "$key1.key" "$key2.key" "$key1.cds" >$zonefile +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +zone=cds-x.secure +infile=cds.secure.db.in +zonefile=cds-x.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +"$DSFROMKEY" -C "$key2.key" >"$key2.cds" +cat "$infile" "$key1.key" "$key2.key" "$key3.key" "$key2.cds" >"$zonefile" +"$SIGNER" -g -x -o "$zone" "$zonefile" >/dev/null 2>&1 + +zone=cds-update.secure +infile=cds-update.secure.db.in +zonefile=cds-update.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$key1.key" "$key2.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 +keyfile_to_key_id "$key1" >cds-update.secure.id + +zone=cds-auto.secure +infile=cds-auto.secure.db.in +zonefile=cds-auto.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +$SETTIME -P sync now "$key1" >/dev/null +cat "$infile" >"$zonefile.signed" + +zone=cdnskey.secure +infile=cdnskey.secure.db.in +zonefile=cdnskey.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +sed 's/DNSKEY/CDNSKEY/' "$key1.key" >"$key1.cds" +cat "$infile" "$key1.key" "$key2.key" "$key1.cds" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +zone=cdnskey-x.secure +infile=cdnskey.secure.db.in +zonefile=cdnskey-x.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +sed 's/DNSKEY/CDNSKEY/' "$key1.key" >"$key1.cds" +cat "$infile" "$key1.key" "$key2.key" "$key3.key" "$key1.cds" >"$zonefile" +"$SIGNER" -g -x -o "$zone" "$zonefile" >/dev/null 2>&1 + +zone=cdnskey-update.secure +infile=cdnskey-update.secure.db.in +zonefile=cdnskey-update.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$key1.key" "$key2.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 +keyfile_to_key_id "$key1" >cdnskey-update.secure.id + +zone=cdnskey-auto.secure +infile=cdnskey-auto.secure.db.in +zonefile=cdnskey-auto.secure.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +$SETTIME -P sync now "$key1" >/dev/null +cat "$infile" >"$zonefile.signed" + +zone=updatecheck-kskonly.secure +infile=template.secure.db.in +zonefile=${zone}.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +# Save key id's for checking active key usage +keyfile_to_key_id "$key1" >$zone.ksk.id +keyfile_to_key_id "$key2" >$zone.zsk.id +echo "${key1}" >$zone.ksk.key +echo "${key2}" >$zone.zsk.key +# Make sure dnssec-policy adds CDS and CDNSKEY records +$SETTIME -s -g OMNIPRESENT -k OMNIPRESENT now -r OMNIPRESENT now -d RUMOURED now $key1 >settime.out.$zone.ksk 2>&1 +$SETTIME -s -g OMNIPRESENT -k OMNIPRESENT now -z OMNIPRESENT now $key2 >settime.out.$zone.zsk 2>&1 +# Don't sign, let dnssec-policy maintain do it. +cat "$infile" "$key1.key" "$key2.key" >"$zonefile" +mv $zonefile "$zonefile.signed" + +zone=hours-vs-days +infile=hours-vs-days.db.in +zonefile=hours-vs-days.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +$SETTIME -P sync now "$key1" >/dev/null +cat "$infile" >"$zonefile.signed" + +# +# Negative result from this zone should come back as insecure. +# +zone=too-many-iterations +infile=too-many-iterations.db.in +zonefile=too-many-iterations.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$key1.key" "$key2.key" >"$zonefile" +"$SIGNER" -P -3 - -H too-many -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# +# A zone with a secure chain of trust of two KSKs, only one KSK is not signing. +# +zone=lazy-ksk +infile=lazy-ksk.db.in +zonefile=lazy-ksk.db +ksk1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +ksk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +ksk3=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$ksk1.key" "$ksk2.key" "$ksk3.key" "$zsk.key" >"$zonefile" +$DSFROMKEY "$ksk1.key" >"dsset-$zone." +$DSFROMKEY "$ksk2.key" >>"dsset-$zone." +$DSFROMKEY "$ksk3.key" >>"dsset-$zone." +# Keep the KSK with the highest key tag +id1=$(keyfile_to_key_id "$ksk1") +id2=$(keyfile_to_key_id "$ksk2") +id3=$(keyfile_to_key_id "$ksk3") +if [ $id1 -gt $id2 ]; then + if [ $id1 -gt $id3 ]; then + rm1="$ksk2" + rm2="$ksk3" + else # id3 -gt $id1 + rm1="$ksk2" + rm2="$ksk1" + fi +else # $id2 -gt $id1 + if [ $id2 -gt $id3 ]; then + rm1="$ksk1" + rm2="$ksk3" + else #id3 -gt $id2 + rm1="$ksk2" + rm2="$ksk1" + fi +fi + +rm "$rm1.key" +rm "$rm1.private" +rm "$rm2.key" +rm "$rm2.private" + +# +# A zone with the DNSKEY RRSIGS stripped +# +zone=dnskey-rrsigs-stripped +infile=dnskey-rrsigs-stripped.db.in +zonefile=dnskey-rrsigs-stripped.db +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 +"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" \ + | awk '$4 == "RRSIG" && $5 == "DNSKEY" { next } { print }' >"$zonefile.stripped" +"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" \ + | awk '$4 == "SOA" { $7 = $7 + 1; print; next } { print }' >"$zonefile.next" +"$SIGNER" -g -o "$zone" -f "$zonefile.next" "$zonefile.next" >/dev/null 2>&1 +cp "$zonefile.stripped" "$zonefile.signed" + +# +# A child zone for the stripped DS RRSIGs test +# +zone=child.ds-rrsigs-stripped +infile=child.ds-rrsigs-stripped.db.in +zonefile=child.ds-rrsigs-stripped.db +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# +# A zone with the DNSKEY RRSIGS stripped +# +zone=ds-rrsigs-stripped +infile=ds-rrsigs-stripped.db.in +zonefile=ds-rrsigs-stripped.db +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 +"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" \ + | awk '$4 == "RRSIG" && $5 == "DS" { next } { print }' >"$zonefile.stripped" +"$CHECKZONE" -D -q -i local "$zone" "$zonefile.signed" \ + | awk '$4 == "SOA" { $7 = $7 + 1; print; next } { print }' >"$zonefile.next" +"$SIGNER" -g -o "$zone" -f "$zonefile.next" "$zonefile.next" >/dev/null 2>&1 +cp "$zonefile.stripped" "$zonefile.signed" + +# +# Inconsistent NS RRset between parent and child +# +zone=inconsistent +infile=inconsistent.db.in +zonefile=inconsistent.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$key1.key" "$key2.key" >"$zonefile" +"$SIGNER" -3 - -g -o "$zone" "$zonefile" >/dev/null 2>&1 diff --git a/bin/tests/system/dnssec/ns2/single-nsec3.db.in b/bin/tests/system/dnssec/ns2/single-nsec3.db.in new file mode 100644 index 0000000..b2e3c13 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/single-nsec3.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns2.example. . ( + 2010042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2.example. +delegation NS ns3.example. diff --git a/bin/tests/system/dnssec/ns2/template.secure.db.in b/bin/tests/system/dnssec/ns2/template.secure.db.in new file mode 100644 index 0000000..aa3aaab --- /dev/null +++ b/bin/tests/system/dnssec/ns2/template.secure.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. . 1 3600 1200 86400 1200 +@ NS ns2.example. diff --git a/bin/tests/system/dnssec/ns2/too-many-iterations.db.in b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in new file mode 100644 index 0000000..1527e07 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +*.a A 10.0.0.3 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in new file mode 100644 index 0000000..a7792fd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + +nosoa NS ns.nosoa +ns.nosoa A 10.53.0.7 + +normalthenrrsig A 10.0.0.28 +rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in new file mode 100644 index 0000000..a7792fd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + +nosoa NS ns.nosoa +ns.nosoa A 10.53.0.7 + +normalthenrrsig A 10.0.0.28 +rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/bogus.example.db.in b/bin/tests/system/dnssec/ns3/bogus.example.db.in new file mode 100644 index 0000000..0feb441 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/bogus.example.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/digest-alg-unsupported.example.db.in b/bin/tests/system/dnssec/ns3/digest-alg-unsupported.example.db.in new file mode 100644 index 0000000..94fa465 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/digest-alg-unsupported.example.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 +a A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in new file mode 100644 index 0000000..e758cdd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dname-at-apex-nsec3.example.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns3.example. . 1 1200 1200 1814400 3600 +@ NS ns3.example. +@ DNAME example. diff --git a/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dnskey-nsec3-unknown.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dnskey-unknown.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dnskey-unsupported-2.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in b/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dnskey-unsupported.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/ds-unsupported.example.db.in b/bin/tests/system/dnssec/ns3/ds-unsupported.example.db.in new file mode 100644 index 0000000..94fa465 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/ds-unsupported.example.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 +a A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns3/dynamic.example.db.in b/bin/tests/system/dnssec/ns3/dynamic.example.db.in new file mode 100644 index 0000000..babf54c --- /dev/null +++ b/bin/tests/system/dnssec/ns3/dynamic.example.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This has the NS and glue at the apex because testing RT #2399 +; requires we have only one name in the zone at a certain point +; during the test. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS @ +@ A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns3/expired.example.db.in b/bin/tests/system/dnssec/ns3/expired.example.db.in new file mode 100644 index 0000000..b7706d3 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/expired.example.db.in @@ -0,0 +1,44 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns + MX 10 mx +ns A 10.53.0.3 +mx A 10.0.0.30 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + +nosoa NS ns.nosoa +ns.nosoa A 10.53.0.7 + +normalthenrrsig A 10.0.0.28 +rrsigonly A 10.0.0.29 + + diff --git a/bin/tests/system/dnssec/ns3/expiring.example.db.in b/bin/tests/system/dnssec/ns3/expiring.example.db.in new file mode 100644 index 0000000..8acf7b1 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/expiring.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns + MX 10 mx +ns A 10.53.0.3 +mx A 10.0.0.30 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/dnssec/ns3/future.example.db.in b/bin/tests/system/dnssec/ns3/future.example.db.in new file mode 100644 index 0000000..20c19c5 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/future.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +child NS ns2.example. +insecure.empty NS ns.insecure.empty +ns.insecure.empty A 10.53.0.3 +foo.*.empty-wild NS ns diff --git a/bin/tests/system/dnssec/ns3/generic.example.db.in b/bin/tests/system/dnssec/ns3/generic.example.db.in new file mode 100644 index 0000000..5cc3ecc --- /dev/null +++ b/bin/tests/system/dnssec/ns3/generic.example.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a.b A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns3/inline.example.db b/bin/tests/system/dnssec/ns3/inline.example.db new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/inline.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db b/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/insecure.below-cname.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/insecure.example.db b/bin/tests/system/dnssec/ns3/insecure.example.db new file mode 100644 index 0000000..76e3f47 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/insecure.example.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x DNSKEY 258 3 5 Cg== +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/insecure.optout.example.db b/bin/tests/system/dnssec/ns3/insecure.optout.example.db new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/insecure.optout.example.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/insecure2.example.db b/bin/tests/system/dnssec/ns3/insecure2.example.db new file mode 100644 index 0000000..76e3f47 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/insecure2.example.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x DNSKEY 258 3 5 Cg== +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/key.db.in b/bin/tests/system/dnssec/ns3/key.db.in new file mode 100644 index 0000000..0165e3f --- /dev/null +++ b/bin/tests/system/dnssec/ns3/key.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/dnssec/ns3/kskonly.example.db.in b/bin/tests/system/dnssec/ns3/kskonly.example.db.in new file mode 100644 index 0000000..0b11a00 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/kskonly.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +x CNAME a diff --git a/bin/tests/system/dnssec/ns3/lower.example.db.in b/bin/tests/system/dnssec/ns3/lower.example.db.in new file mode 100644 index 0000000..a04793e --- /dev/null +++ b/bin/tests/system/dnssec/ns3/lower.example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA MNAME1. . ( + 2012042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS NS +NS A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns3/managed-future.example.db.in b/bin/tests/system/dnssec/ns3/managed-future.example.db.in new file mode 100644 index 0000000..20c19c5 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/managed-future.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +child NS ns2.example. +insecure.empty NS ns.insecure.empty +ns.insecure.empty A 10.53.0.3 +foo.*.empty-wild NS ns diff --git a/bin/tests/system/dnssec/ns3/multiple.example.db.in b/bin/tests/system/dnssec/ns3/multiple.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/multiple.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/named.conf.in b/bin/tests/system/dnssec/ns3/named.conf.in new file mode 100644 index 0000000..293ff2d --- /dev/null +++ b/bin/tests/system/dnssec/ns3/named.conf.in @@ -0,0 +1,450 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; + session-keyfile "session.key"; + minimal-responses no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "dnssec" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 0; +}; + +dnssec-policy "autonsec" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + }; +}; + +dnssec-policy "autonsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + }; + + nsec3param iterations 0 optout no salt-length 0; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.2; }; + file "example.bk"; +}; + +zone "secure.example" { + type primary; + file "secure.example.db.signed"; + allow-update { any; }; +}; + +zone "bogus.example" { + type primary; + file "bogus.example.db.signed"; + allow-update { any; }; +}; + +zone "badds.example" { + type primary; + file "badds.example.db.signed"; + allow-update { any; }; +}; + +zone "dynamic.example" { + type primary; + file "dynamic.example.db.signed"; + allow-update { any; }; +}; + +zone "insecure.example" { + type primary; + file "insecure.example.db"; + allow-update { any; }; +}; + +zone "insecure2.example" { + type primary; + file "insecure2.example.db"; + allow-update { any; }; +}; + +zone "insecure.nsec3.example" { + type primary; + file "insecure.nsec3.example.db"; + allow-update { any; }; +}; + +zone "insecure.optout.example" { + type primary; + file "insecure.optout.example.db"; + allow-update { any; }; +}; + +zone "keyless.example" { + type primary; + file "keyless.example.db.signed"; +}; + +zone "nsec3.example" { + type primary; + file "nsec3.example.db.signed"; +}; + +zone "optout.nsec3.example" { + type primary; + file "optout.nsec3.example.db.signed"; +}; + +zone "nsec3.nsec3.example" { + type primary; + file "nsec3.nsec3.example.db.signed"; +}; + +zone "secure.nsec3.example" { + type primary; + file "secure.nsec3.example.db.signed"; +}; + +zone "optout.example" { + type primary; + file "optout.example.db.signed"; +}; + +zone "secure.optout.example" { + type primary; + file "secure.optout.example.db.signed"; +}; + +zone "nsec3.optout.example" { + type primary; + file "nsec3.optout.example.db.signed"; +}; + +zone "optout.optout.example" { + type primary; + file "optout.optout.example.db.signed"; +}; + +zone "nsec3-unknown.example" { + type primary; + nsec3-test-zone yes; + file "nsec3-unknown.example.db.signed"; +}; + +zone "optout-unknown.example" { + type primary; + nsec3-test-zone yes; + file "optout-unknown.example.db.signed"; +}; + +zone "dnskey-unknown.example" { + type primary; + file "dnskey-unknown.example.db.signed"; +}; + +zone "digest-alg-unsupported.example" { + type primary; + file "digest-alg-unsupported.example.db.signed"; + allow-update { any; }; +}; + +zone "ds-unsupported.example" { + type primary; + file "ds-unsupported.example.db.signed"; + allow-update { any; }; +}; + +zone "dnskey-unsupported.example" { + type primary; + file "dnskey-unsupported.example.db.signed"; +}; + +zone "dnskey-unsupported-2.example" { + type primary; + file "dnskey-unsupported-2.example.db.signed"; +}; + +zone "dnskey-nsec3-unknown.example" { + type primary; + nsec3-test-zone yes; + file "dnskey-nsec3-unknown.example.db.signed"; +}; + +zone "multiple.example" { + type primary; + file "multiple.example.db.signed"; + allow-update { any; }; +}; + +zone "rfc2335.example" { + type secondary; + primaries { 10.53.0.2; }; + file "rfc2335.example.bk"; +}; + +zone "rsasha256.example" { + type primary; + file "rsasha256.example.db.signed"; +}; + +zone "rsasha512.example" { + type primary; + file "rsasha512.example.db.signed"; +}; + +zone "kskonly.example" { + type primary; + file "kskonly.example.db.signed"; +}; + +zone "expired.example" { + type primary; + allow-update { none; }; + file "expired.example.db.signed"; +}; + +zone "update-nsec3.example" { + type primary; + dnssec-policy nsec3; + allow-update { any; }; + file "update-nsec3.example.db.signed"; +}; + +zone "auto-nsec.example" { + type primary; + dnssec-policy autonsec; + allow-update { !0.0.0.0; }; + file "auto-nsec.example.db.signed"; +}; + +zone "auto-nsec3.example" { + type primary; + dnssec-policy autonsec3; + allow-update { !0.0.0.0; }; + file "auto-nsec3.example.db.signed"; +}; + +zone "insecure.below-cname.example" { + type primary; + file "insecure.below-cname.example.db"; +}; + +zone "secure.below-cname.example" { + type primary; + file "secure.below-cname.example.db.signed"; +}; + +zone "ttlpatch.example" { + type primary; + file "ttlpatch.example.db.patched"; +}; + +zone "split-dnssec.example" { + type primary; + file "split-dnssec.example.db"; +}; + +zone "split-smart.example" { + type primary; + file "split-smart.example.db"; +}; + +zone "nsec3chain-test" { + type secondary; + file "nsec3chain-test.bk"; + primaries { 10.53.0.2; }; +}; + +zone "expiring.example" { + type primary; + allow-update { any; }; + file "expiring.example.db.signed"; +}; + +zone "upper.example" { + type primary; + file "upper.example.db.signed"; +}; + +zone "LOWER.EXAMPLE" { + type primary; + file "lower.example.db.signed"; +}; + +zone "inline.example" { + type primary; + file "inline.example.db"; + inline-signing yes; + dnssec-policy dnssec; +}; + +zone "future.example" { + type primary; + file "future.example.db.signed"; +}; + +zone "managed-future.example" { + type primary; + file "managed-future.example.db.signed"; + allow-update { any; }; +}; + +zone "revkey.example" { + type primary; + file "revkey.example.db.signed"; +}; + +zone "dname-at-apex-nsec3.example" { + type primary; + file "dname-at-apex-nsec3.example.db.signed"; +}; + +zone "occluded.example" { + type primary; + file "occluded.example.db.signed"; +}; + +zone "secure.managed" { + type primary; + file "secure.managed.db.signed"; +}; + +zone "disabled.managed" { + type primary; + file "disabled.managed.db.signed"; +}; + +zone "enabled.managed" { + type primary; + file "enabled.managed.db.signed"; +}; + +zone "unsupported.managed" { + type primary; + file "unsupported.managed.db.signed"; +}; + +zone "revoked.managed" { + type primary; + file "revoked.managed.db.signed"; +}; + +zone "secure.trusted" { + type primary; + file "secure.trusted.db.signed"; +}; + +zone "disabled.trusted" { + type primary; + file "disabled.trusted.db.signed"; +}; + +zone "enabled.trusted" { + type primary; + file "enabled.trusted.db.signed"; +}; + +zone "unsupported.trusted" { + type primary; + file "unsupported.trusted.db.signed"; +}; + +zone "revoked.trusted" { + type primary; + file "revoked.trusted.db.signed"; +}; + +zone "too-many-iterations" { + type secondary; + primaries { 10.53.0.2; }; + file "too-many-iterations.bk"; +}; + +zone "rsasha1.example" { + type primary; + file "rsasha1.example.db"; +}; + +zone "rsasha1-1024.example" { + type primary; + file "rsasha1-1024.example.db"; +}; + +dnssec-policy "siginterval1" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + signatures-validity 1d; + signatures-refresh 21h; + signatures-validity-dnskey 90d; +}; + +dnssec-policy "siginterval2" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + signatures-validity 35d; + signatures-refresh 28d; + signatures-validity-dnskey 90d; +}; + +include "siginterval.conf"; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns3/nosign.example.db.in b/bin/tests/system/dnssec/ns3/nosign.example.db.in new file mode 100644 index 0000000..2be8a28 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nosign.example.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 diff --git a/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.example.db.in new file mode 100644 index 0000000..55b3877 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nsec3.example.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/occluded.example.db.in b/bin/tests/system/dnssec/ns3/occluded.example.db.in new file mode 100644 index 0000000..ee9c900 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/occluded.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a.b A 10.0.0.1 +delegation NS ns + A 10.53.0.3 + AAAA 2002:: diff --git a/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in new file mode 100644 index 0000000..f37dd75 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.e A 10.0.0.6 +child NS ns2.example. diff --git a/bin/tests/system/dnssec/ns3/optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.example.db.in new file mode 100644 index 0000000..20c19c5 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/optout.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +child NS ns2.example. +insecure.empty NS ns.insecure.empty +ns.insecure.empty A 10.53.0.3 +foo.*.empty-wild NS ns diff --git a/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/optout.optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db b/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db new file mode 100644 index 0000000..d51672c --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db @@ -0,0 +1,63 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; File written on Tue Jan 11 18:07:57 2022 +; dnssec_signzone version 9.17.21 +rsasha1-1024.example. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600 +rsasha1-1024.example. 300 IN RRSIG SOA 5 2 300 20900129082204 20220111060757 22290 rsasha1-1024.example. kM6ztqAaLkxcRxYWrw2oe3qofzoIRjDv/tLD/A5edreqzzwj7H6Ihm0s JHfzqVOWBTwYzX0XgD0PXCqMdkXP7QlcWGYK7uCWnisayZIwNCdkywPC sS2ky1d0eK1A7kJ9nEH/eOgLba5uFZcAo8+9dD/6o6Rt1jTeTQkL4RHI UC8= +; resign=20900129082204 +rsasha1-1024.example. 300 IN NS ns.rsasha1-1024.example. +rsasha1-1024.example. 300 IN RRSIG NS 5 2 300 20900129082204 20220111060757 22290 rsasha1-1024.example. jxbsZlgK4B6IkCrZuNDVv/EIqgCU8pTOyWEt2DqvzRI8AeL3I+U9Nbcz 9gmQRaNEtffLVR/sfht6v1ms4AFJKd0xLSZj9ywsZKCmG12UxfNIoZ49 4d1ono8hGYU8xr1Qh1BU2HwgGY1JF4OyO28cgrkT2F9dAvG8MSMEW5Sg 9A8= +; resign=20900129082204 +rsasha1-1024.example. 300 IN NSEC a.rsasha1-1024.example. NS SOA RRSIG NSEC DNSKEY +rsasha1-1024.example. 300 IN RRSIG NSEC 5 2 300 20900129082204 20220111060757 22290 rsasha1-1024.example. AfEX9beXrft4d1moQD1VP3Em9cMgJmx2EYBKMlW5e5XFNk2Z5Wj1N//3 sBuUPNppxUilUEydqH5psVw7IMhrz8Q1+bhABNV7cPm1EOuq0NuQJ2LN JNlTnjfaRT6IAtY7d+NOCO2eKlDzMC/q8t2oaB+iHhgO7yc5+fxMGyQ/ PVc= +; resign=20900129082204 +rsasha1-1024.example. 300 IN DNSKEY 256 3 5 AwEAAaYD3SqsLtFHSfDhA8HhNKQJOToRptRmFhsYbqre+lq/BLpLQNkA 7Kq+chsUhOe+8OHMfkNXfr3XFyuUA3rBg15kq57NZ5gLzkHyeGqB9Ths M5pdwDCqPjJKP43W2+EXXHWsg5P94yldWcvMx1v80vrxGvUimfiQSznE hok/6oqR +rsasha1-1024.example. 300 IN DNSKEY 257 3 5 AwEAAeEe/ohrvXtDqYgrz5Q1WAKRstnnH0xi/4Mne49PLO56TcVPf6sg xpv/SaHSlQGJnVbQBLebPemKDAC1vVOUqdTDxHJbLuO28brIWMzf0pc1 5G2RNtrQf44E4yaibSROhyBmWoerUHTPGJw6BGDI4fb/CVWujFQ1ieBy WC0p1NWH +rsasha1-1024.example. 300 IN RRSIG DNSKEY 5 2 300 20900129082204 20220111060757 22290 rsasha1-1024.example. nBLPJfoZe4G3wOe17bBSMooRZHe523pjdaTAK2PmXEa8exXH+OWCHh7f Jnh/SI89Hp9a2ru1Skze3FcUcTj/SlwtEuWpxOs9B1R29P1xVPCwkAfb xsmtmE6u5+oeLGrt88zA/kpjx6t0sFbU7A8/qxlpuoH+hdAu1jI2tlP4 d30= +rsasha1-1024.example. 300 IN RRSIG DNSKEY 5 2 300 20900129082204 20220111060757 1151 rsasha1-1024.example. 0oNrcBsFySVjBT60SX3m7cKIPmuCOUH0ZFucrmEVXJLGpNOXe37aXbnC Iz+NHcaaeZQP/w4aYSTyQvZs6Vl5Tufeic3SWalzTGv0f01mIIk24v1a h4ePUB8w0b0+/qq89zl6Ccr2/PgTaLvjuSGYcgX15cigqPRcKQNYCwO1 Vsk= +; resign=20900129082204 +z.rsasha1-1024.example. 300 IN A 10.0.0.26 +z.rsasha1-1024.example. 300 IN RRSIG A 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. Zf/ynA7APXpNjcMPusIjRan0/ITLmeeY7GJfhCLeD3lEjnAd7dWRl7sC N5sBzUG78Mtgm39Ov/Kj2EwQjFcwcMUmppan3NzS+1YtYuZqlN9iAW+b UUfv8UQUHvM3x/hW4kNCPd2PHIzV2uedIp7VG3Lz72FvjHxECbI7g79V 18c= +; resign=20900129082204 +z.rsasha1-1024.example. 300 IN NSEC rsasha1-1024.example. A RRSIG NSEC +z.rsasha1-1024.example. 300 IN RRSIG NSEC 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. FPlYMJ41r79tkhIkDTX9/uVtcKXfHa+5oXb8fdo7/2CugjBfp5uihn57 3gMmY7Mi2aVsW64hRkehPJr+sTUOk5+ILhO2Qhjdrm2DpHgeSK29BTQr Okn9ruvpLhRFHwI/DllnKvBOyCmKSzJZE7PDOrqouGclNue07IXz+K2R bME= +; resign=20900129082204 +b.rsasha1-1024.example. 300 IN A 10.0.0.2 +b.rsasha1-1024.example. 300 IN RRSIG A 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. gQmhCIwai57iscF2s5CJ5DbSy0Z9TiOWYGeFeZITxQ/koFOOjyuZXAZn 6f7mTUcFPhNm4AT/PJAs/L/tzcE16pcVwwDnHszdY28XwEU6OqaXUB3E T/Qu4Sh0BWet9U6JcSSqLG5317qJxqSGfnIJOXMucYi3MH3W8uSpapr+ 4Qk= +; resign=20900129082204 +b.rsasha1-1024.example. 300 IN NSEC d.rsasha1-1024.example. A RRSIG NSEC +b.rsasha1-1024.example. 300 IN RRSIG NSEC 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. Do6VghMEcHk35Q7fI2VrrQBYhChT4pnw791qUFhHZeol5fIKtEnrlviA RN2fbEY+7OrQQXo7Ywxo7nTD9sYsFgOwGKqKJ+yLNPcr++0csbkgt5rU ch1Lv+t7jOUuUX8IzgjOoCH5j9eoU5QtGkEBxf6z0nvlsLJaTWwTqvbr 7aU= +; resign=20900129082204 +a.rsasha1-1024.example. 300 IN A 10.0.0.1 +a.rsasha1-1024.example. 300 IN RRSIG A 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. CaPXSTPLNeQ4MyRylYP/Ztb6kRT9/QdgpTnZxUHCjSdWEBXsrkEr55/z dBSQ8zGGOfCxlOkmgH/UrR7JmHTQrIqsb/iVq+6D0mfvNJDyNpT92bo8 r+C62/9NXLlkS5zcpyNG8Ls66EQ7dcFa6SxwdxF1qaoeBjJvkrGUMnzP UFo= +; resign=20900129082204 +a.rsasha1-1024.example. 300 IN NSEC b.rsasha1-1024.example. A RRSIG NSEC +a.rsasha1-1024.example. 300 IN RRSIG NSEC 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. DJlfCVMSPZ6KUIUhWUBt7LOCB8vBbxOFaR4PoHs/fLpGBWrQj46sjLKO W/TImquBg3ygYTOIyWEzVb177HryRmx65AKnfGLbzaTdTgHzcELwg88t EYFT4ODalqTn68o2RfWtNl95FNqJR/kguxxzFVgpN4zfGKXdhTWAA4JW zG0= +; resign=20900129082204 +a.a.a.a.a.a.a.a.a.a.e.rsasha1-1024.example. 300 IN A 10.0.0.27 +a.a.a.a.a.a.a.a.a.a.e.rsasha1-1024.example. 300 IN RRSIG A 5 13 300 20900129082204 20220111060757 22290 rsasha1-1024.example. PVFCHIXgDCZOHsTsr3G9wMnPPmiY4CfOXC3b1ZF2qEDqloIT+YX5oKKE uiT6fCBteS6Cq8XTXdezXjqTqxrdY4qMMOBDnIZhf8eOxjFzMEUKKZuH 9c5rt8u35TihuIdKv9OPXdWuTJ4dVSEZjNNxvh3VoMW6XFagYmu3f8Gr 0rg= +; resign=20900129082204 +a.a.a.a.a.a.a.a.a.a.e.rsasha1-1024.example. 300 IN NSEC ns.rsasha1-1024.example. A RRSIG NSEC +a.a.a.a.a.a.a.a.a.a.e.rsasha1-1024.example. 300 IN RRSIG NSEC 5 13 300 20900129082204 20220111060757 22290 rsasha1-1024.example. VOOEksRwMWNO2ESMrcMyPFAHuXyYgeLVODy46DwDx8PTli3/UwOH1e3l qd3Poh2K/OFP2v8TuzkXXnPW48Lg90haHtG9yLr5UUNoKntmBC9PFeqt P/qdOBiHszvcyyjJ4gabEX2gn+o/sL/klQV4m3mB4Vf5sg2dfX8Qyuw6 nDQ= +; resign=20900129082204 +d.rsasha1-1024.example. 300 IN A 10.0.0.4 +d.rsasha1-1024.example. 300 IN RRSIG A 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. XcxbM4wA+yTOAwPePwRIg6E58HuMr5qIkdghNn/R5ck1JdirLbMB/Wpp Si+5a4q9F02Bs8uZv2YXtXRIa32i1/L6OPeU3RFQfvkpHbQNTvPtsuAL bmFGB/zdR6XQpqC6G+ip9qY+mk2hXwCZZ24NW90O9qYlE8Rp145/dIVM DPo= +; resign=20900129082204 +d.rsasha1-1024.example. 300 IN NSEC a.a.a.a.a.a.a.a.a.a.e.rsasha1-1024.example. A RRSIG NSEC +d.rsasha1-1024.example. 300 IN RRSIG NSEC 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. fmBjPGTNWOXAs51XO1fIRCKAbf9TLTV04TmlgLm50oOouEXsXpwKo6tb MbCGI2f+u986mtzLW4gWY+rcAPrMCndu5BPIYPk/Ngd6zqylWJzAfKyg PIqO0lf6jg0J3FfP39fw9bf+xB+AI1PWBrVZ55LotBYgIBZYhQ1LKPZ2 iyU= +; resign=20900129082204 +ns.rsasha1-1024.example. 300 IN A 10.53.0.3 +ns.rsasha1-1024.example. 300 IN RRSIG A 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. beHl0WxLgPYkzKs/tdQnphXDzHx6FqdQRlVtJIYHGoWmWe4X6JWg4ENB a0xPeOGFQPBMgNuKbwyjAVmX0B3Su4LiBM7GcmfJbd4YRNCa4hQvhDpG o5A54Pxo2Qdo9Cffhzva5z4iO+DNnmBsfKGPna4sO2lRNfIxXlxCTbnE zps= +; resign=20900129082204 +ns.rsasha1-1024.example. 300 IN NSEC z.rsasha1-1024.example. A RRSIG NSEC +ns.rsasha1-1024.example. 300 IN RRSIG NSEC 5 3 300 20900129082204 20220111060757 22290 rsasha1-1024.example. aZTImJ5QFufIQEIuX+5ZYVW2Yq4ctxeX9zm9yrQaUODvVRm3X3WjncrU hkgDaW3a/j8RRG0cdAnzSWCzIMz0Yv4kWxrxCEJyIgmVUQ3fzxzpGwMF ZwCtNb9aWmImcAugTnjocn5+iCiyTEVipZmTASEyN0Bgp5Q4oFChnzIj kjk= +; resign=20900129082204 diff --git a/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db.in b/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db.in new file mode 100644 index 0000000..b2e7e21 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha1-1024.example.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 diff --git a/bin/tests/system/dnssec/ns3/rsasha1.example.db b/bin/tests/system/dnssec/ns3/rsasha1.example.db new file mode 100644 index 0000000..2d16e50 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha1.example.db @@ -0,0 +1,63 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; File written on Tue Jan 4 17:29:34 2022 +; dnssec_signzone version 9.17.20 +rsasha1.example. 300 IN SOA mname1. . 2000042407 20 20 1814400 3600 +rsasha1.example. 300 IN RRSIG SOA 5 2 300 20900122074341 20220104052934 30286 rsasha1.example. wg8k4y/Cs/+u2QfUnBURhD4isSFTzCofpdhMzVJEUfBqu1DBVO+FECQ4 U80NCg9iksxm7xsWAZiQx6Rzvh1rUqEA7OhCy7XiPuz+jR1TYHXJhRMu t9gu7aCdTkcXYCMtppd49/2vT+WPKB98QIKD6wgl4LFFhwbUCoXavin4 babUiJrJeAnuxmIeD5HtM5a+++p0F8QemdP5FkX3WCRBHNFGnoVYJjc7 PZ+L8ZpKElah47XzJwAYWDr34TwqU9llCOcXlXYKBqDKO9fEtJJ1hyk9 Sf4fGOdzZD9Pj4Zz83UlHumeZPfIC1N0xVBYvGPu8LU41WZ4BgZfKSoS UIpbPQ== +; resign=20900122074341 +rsasha1.example. 300 IN NS ns.rsasha1.example. +rsasha1.example. 300 IN RRSIG NS 5 2 300 20900122074341 20220104052934 30286 rsasha1.example. VqOKkNo7CRH2uquL/46cIVoIPvFYT2WrpwpG6ienlJoLF/mZn0ReoMaK G29R8Q0tklalk14CGShiD409lXDRynyHgmLGIFjkXMd6aNRQOdD1O+7C wEhAj4/FEz+qpk/xRGMslxCCF1P7DxpX5ZPI9DuPVVvTRk4131CALaFQ EPblDzEgd7JeoO0tKnPjpzXLdr86NDeDVZXonimjEhQNrvrrurQ5/u2F x7jVmovN47Z06+XCbleC2ag8ZazNkYfU8GlFvkozZMGZtnpja1/SllNJ ZdURisd3JFMw/xsZd1v2MspKYcZePTfzyk/keXSJ0AlO7TA1X2sjiFOo 1fhSnQ== +; resign=20900122074341 +rsasha1.example. 300 IN NSEC a.rsasha1.example. NS SOA RRSIG NSEC DNSKEY +rsasha1.example. 300 IN RRSIG NSEC 5 2 300 20900122074341 20220104052934 30286 rsasha1.example. U7SEGuJ95CKk6+sWNCNHfPuvjJ2KChhutImWmSTc9lgb3uSfptzwbYnP UZ3xG0IqkayRJhBSizLb5kntvBZbcz4pEWZ+o7ZJdiBHcCARj82OJaLF d147VB3XJa6rIi+o/Zm8SIbxU7gugqRds7KfSTxAIjHzLpCcu12hlgfc Qso1LYiVeU5GVnmfuNJQL7QvS3BQuTylTI1+HQpiY6W8Bzev/TcbhoDJ Ywp4hvgF4VGCvrO2glSO4VycLjluawKSlrNaLbAtWIYYUSPbvtktM8tQ GBqOij4l7eMCTGRCoExWEnr+CzWAauoemhLDh27Bq6VNjD5iIvjzt3Ym uGDQUg== +; resign=20900122074341 +rsasha1.example. 300 IN DNSKEY 256 3 5 AwEAAe31msH3kL5cIQ6C1vTnB8GvbFDm0t/j5XWnLonaKDSUoHtKLlRq pBPuwlORRUZxRSs7VDAaKE0YGky/YklSCqvo8gBD4dkNjWD/6XGkmtEq DOL8XCz1KO+djs7WLCuCyGIkG282+sntuZJj4IMd+ZDW1urCwaP94t3u W9N+PgrSacK9Ff1bwLR9KIgkRFpJ+JxPeaFYnVEyB4ZaZ8DgPWYNJ+aC awL0nATybC8asPeCGvft3lSS99z55IMfkpjF1rwHIVybqhiukRighazQ ljjVQdlXj3YxFgD0fpscJ6yN0QXdseagxiT4PahnwaHYHUhgGm+HB1zA pA49L9dg2RE= +rsasha1.example. 300 IN DNSKEY 257 3 5 AwEAAcQdnpcda8XlNxllEGbWy9EGkD5TtHEbxThaB9c6ZNQPTf3gJw0A LpIZ787sepWND7vPcq6Qb/xZEmC6ER5OfaYbDznUh8q5NaaTbSwv0tng gE8KPwtvlgH+4eUmOcEkGrfR9G6J9S8JTT5bUWKTUbprxE65/8xcY33S cEeOpi34DLR9GLNvPLTSLuWQcYrq1YZFHbivQ45oFD9PvWPJWOoAN68N T28e0ZV8QHuXqW0IEheeW+AEemywupdaxun6Cvvolfz2EMYFnYX8YycE 0qUoDC4W9w3xB4nOllWQfJzgQkSTr/I4XCgepFunBeuAHZhCoQHPt9fK IfPUYxQzaa8= +rsasha1.example. 300 IN RRSIG DNSKEY 5 2 300 20900122074341 20220104052934 30286 rsasha1.example. tODh3LiRuG/ao3ZtJSLBPCy74pkfHXMPRUgFP7MhNR3X6gq75daTVHLi ApTesgAXPAbHI404ps/8M2Z84dkMKBhRDdp1e9OwR8IB4Iw0IOGp2rV7 oZSYNzgnlwRfQ2G75G3xbCjiQhY0H+7IlSiys3sAaI67plvI3nDC3C/r zyDKiY90pK31e+q72SSK+1t/MlsRm0nAYHyUZGLuBMoXYHwonLImeH9Q jwy+cXLwhzOfPfm97ailNifEk38+P+H+Yq35Cp1ezpMzxAi67AcY83sR XB7RVRCf/4uUErh5rYcl6EcnHFh1xA9oSHsaPQbd39PO2fNanyvdPH+p b0ey0A== +rsasha1.example. 300 IN RRSIG DNSKEY 5 2 300 20900122074341 20220104052934 9662 rsasha1.example. Ksyrf1lseBMSQGyPWrSve/X09Nb1CWB//Yvjw9HAEBwna9wseI6cH6mi B1G2JyFmTFzxGgVmf0wB+oec2w7nt5/uUJbyVfLQvCs9RXBGEpKAwhVf GKIwcSF1VTyVfx+PYPHvCpeN01Qm3C/5pJ28dkT65Hry2a7f39kk/8YZ 4zVM1nYaTsBUQdQWvR5UlSm0S3SUMBc2MIEUGUFBhtBJ10W8VkIfNzma ONjMHthu8vLAfwuBYX8zzJIVB31XvnxZDa4LSM4PesyPZ+KVR27o5dlL gQS62u3PWJDgEhUNFIa8A+5kDENC24p7DSfG+Aipe3upefBpBAW3VEdN A/nwQQ== +; resign=20900122074341 +b.rsasha1.example. 300 IN A 10.0.0.2 +b.rsasha1.example. 300 IN RRSIG A 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. ivXu+xAyZThIsY2T1c1wczdeeIG/37z+nO9sbUOzcUyf4+T9lX+6rU0D gxQTxHVdcsw3ge/C+dU2qcrs3EHHW4JcpT1yZMbXcyo+w5ocj5oHGYD2 L3iKLCEZrzdkIwmY4GXNyTznk0X5GKuaP7P6PeNrwWEBficB6xLSiLm7 tsswVcc4XyHa+zKBbxevIt2bKvRUfruyztgENZXJ5125Kx1Ee70Hwvgw bNc2J7lqpJw5c5O8yUaXq5gsxcaLBuONbQ4ANL5PtFQJJY7B5GhqlRTy gVrThJsoZj66pfa8gK92yn8uRG6sFpAbtPrTMQaReiExOhCUdBZRBmA+ RWUTKQ== +; resign=20900122074341 +b.rsasha1.example. 300 IN NSEC d.rsasha1.example. A RRSIG NSEC +b.rsasha1.example. 300 IN RRSIG NSEC 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. hHtS5Bev1RkOJhsz4QnWJzzn/BBRLJil1l1RCbX+nbVbPE93l/2aDi12 jgctWKIfAiVfdFn93uno11+7Lq+bJaiMvaozJ+f7XWMAPsITOlKGNtiw l9kqZJExugH3q0RC1W0xxnb6HlIbwYGn6refUexaZKjgBsUg302pY7bh 6z4WuPakuxAqsaI6KLxLAlm7CWmdXvpFMCc1dnIVDplxOAvEINTrEesY sffjfmRbP3YAXC6/xvu0WVlikgklJjjiRqdeiSqPLGlnb79OAF5whHSL nYvWscX00/f+SOiniFoAFH2KeSb7VdJ2jvpTaqWjrYxxvwuZMsKNzwRI 4pnH/w== +; resign=20900122074341 +a.a.a.a.a.a.a.a.a.a.e.rsasha1.example. 300 IN A 10.0.0.27 +a.a.a.a.a.a.a.a.a.a.e.rsasha1.example. 300 IN RRSIG A 5 13 300 20900122074341 20220104052934 30286 rsasha1.example. BQT+sZ6SJUbGDJ0eG6WBM19+UoBGZEie96E7EXaeS4It3M+EaMkIWIGD hp0MwiC0yW8u0zWjlA57t3yRpVhvCic8kl4SPs5tOmDXyy5RRJ7YOHNx 3PCuAbkoTfoLt5ReVtGcs5LTz+lmPUKZw/dwols5x8v1PIC2O/Ud6Yep TE9Qeymj1/C3GxxLVPLxXQhirkhT6LfMmFH6fNwec6U7bVRyMo3twcvK TDxkEZu5qA0+6bSrLC/xdyZYE38RQOlicmmGfYAIkDWKDdDXYbfBeJq6 zP8aFvdqOckDBvXQcnP9Cq+IvQX1noO90ePYf5AzNxAEQFJ4S1LUm/0q mQqNLA== +; resign=20900122074341 +a.a.a.a.a.a.a.a.a.a.e.rsasha1.example. 300 IN NSEC ns.rsasha1.example. A RRSIG NSEC +a.a.a.a.a.a.a.a.a.a.e.rsasha1.example. 300 IN RRSIG NSEC 5 13 300 20900122074341 20220104052934 30286 rsasha1.example. jvJup/Pg4BpAjh+eLMKEYFkpK/iOVt3QggGL7CRMxzxkYYMJNPwXqdAt 5MovIAFjFKBQm0RDe8/tqav/zdOZrDTyRZ2Zsh9qOp7hlOhy4oqQF+4n Wqg3x8v9gSgrzSAsiJAhb3fbbfdAb3Esc1R0Ec/RcLYEUXiD1eLTG0cB qtVmX3McwXTmu0OGpn0Dsg8CTSuQnrvo24bvsah5SEL1/NVkPtEE7KDT Q8orR7LNM0EeIL1CHxT5dqCAo5MvUm9L8GL/YIOZgtifD/uL23T0ej4j 0JYN7EYoDyFT0fyGeBoS2jkCZTsQZivfnkE5J4Ch1nAU5bUmSeX1eZHK nvce9Q== +; resign=20900122074341 +d.rsasha1.example. 300 IN A 10.0.0.4 +d.rsasha1.example. 300 IN RRSIG A 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. 1mZnG0HsIygSfEue9vMlqWpIQ59EmrktvFrGBzNUEDQDjsoGHv+syMFi A8BtRPkrHZzGaYTqy4L8ZL6V5vZPN1icETNVebx7teBTNFIwlvubdKoQ Zg/37W8gW6U1PN4khQlfX7W5XMFifF4qfCfI3XhkPgKacVaucHQhvGth ZzgCbhCQBVMooRb+v+nzknin0qpIWm7pVPh94BaajxQJ0mNwVQ8hjdJP jy16PH4z/aQ6oPjPKMbnMwTQOdWVUKsZtEkBGcAjJWLFmUJYpR5PPdRB /VsEtjexNKZtDwn0/QUIqUi4GcSp0ISTDBTNDjImJhWVJUoFh6S6zuRW tPYZGA== +; resign=20900122074341 +d.rsasha1.example. 300 IN NSEC a.a.a.a.a.a.a.a.a.a.e.rsasha1.example. A RRSIG NSEC +d.rsasha1.example. 300 IN RRSIG NSEC 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. oWJRAhXbXUA84Nc56NyMocBq93bn3k4uGeqv+XL2L5l6yjxQYxKzjqq1 O5m72K6GiIjoIeun5TxJlEI7/o1EivTxdGYVP4Fsb//Wrv422QcHwS27 xNsFhLMFQglBCOaZzj1v3G2nXRRjP8x81ysg048THlhH5Jm7cW3aUmuS P6kXebWVwIc2nywLHVr/U4dCT2sHOk2gkUuaj8p6rMLVYwj/5dBRijVl Wm131ZeimetxrrRVxXtOfof7W4pqx3bpYRqb/Exdh035Hen+QesxRYTA zcxY7CywJY59afc9/abQBWGkPLfF7rgfJjPIc3MpJlP4SPf0SV4bTNUU nptZ/A== +; resign=20900122074341 +ns.rsasha1.example. 300 IN A 10.53.0.3 +ns.rsasha1.example. 300 IN RRSIG A 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. ONQph6nkFWSS6dqe/agbVnbjwTtA8ZZATpTCqoRJp2QoEgIjZ/0Yh7Fl Axz4PnpMYsEoie0IZ0/g+xTH7nXYphZzzzgedK8WK0vdTW3Pspyoiek/ tWjiGshqq1atHgi+jjRiuhnEvkaX0UDipMCQvI7oFHMOJxmnwZBCNWMc kBu9vbqtr/+HM4y+jGywg5l2XVkmHC5RZv1CoYc5PhfvV4zMI2RCb/Km i5eNCrUZefRfAq4fK9M67Jh/WnfRWfnHZKZN3O0yiRdnKOh2tOQP3X46 fIuNldCeg1PPnkbs4R+ekqJYhpEydNuWKEoKw2ZgeIrmbcRqepD6y3SZ UP/TAw== +; resign=20900122074341 +ns.rsasha1.example. 300 IN NSEC z.rsasha1.example. A RRSIG NSEC +ns.rsasha1.example. 300 IN RRSIG NSEC 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. s7P7k9FDJrO1JhUVjgVUDQXNXfNOJrYVt44OoD45e7w4Q7QkyeZe+6z1 Arj9tW1bI9nIVNo63DT51bsJmj4vPf4SuJgHO05ElkLFSvHn17qMdw8Q Kpx8MQa7plAISqzl9hJip0exMuV+1IHujO9VGE42CxKl0q6l2b/x3+Il afx47bcEePkdhHXyhOSdrtxFTayzjMd/7uSy6p1jFSEVrheejQ/r44t3 9uxEc4EYfiP+HVfnjJ178j2Xa4dZyi3ljhJjaH5oleiy5c2Y5kXRIuXH OcIQ2axO7LT/yupRcBPlo7ulwI9iEVd2Q2gueMqaJ9YEWlcoOSFu1H75 7IRAbA== +; resign=20900122074341 +z.rsasha1.example. 300 IN A 10.0.0.26 +z.rsasha1.example. 300 IN RRSIG A 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. nuqG+ILECKKCQockETu4yLRKZzv9qjXJpfD0/yw5Cw7nSrZFvAjpkQR2 f+xmzbcxP4xiYqs1I+nz8cnHs6NNkJA8vcmk9dnzRu78X0x8MFFV0Yha jQKK/cSzhEhys7GMYv3Jz6lKfmFOAoq1et9PaQT6w8zQD8Q5vBzKrvZm pg+QzZvvgToZfj4e5J7nrhnyOVo7Jec5l/aBCGJbgRMDxjyyC0ufOjnm POvsTZk+wM3+wuN6zYwDpproPiH/6vC/yPlDHeh6kDt971dMsdvRv+kS KAzPyN8rweptJ/HRprb9x6zcAJOrK0T1sJ+EhMbYMgC/py6aAn+T7G5D FGY1tg== +; resign=20900122074341 +z.rsasha1.example. 300 IN NSEC rsasha1.example. A RRSIG NSEC +z.rsasha1.example. 300 IN RRSIG NSEC 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. Wj5DkrGppeMFn8bWLUMfFPCzDAO2HeabbEIMaAHBH/g0hdn+2PPkQc8D D6WCSc4q5gyGNRSXj2Kik2TojD9n/5WuwDAA3W2AOso+4d616lSy9pyj x+e4WZ6y6tAYRRIGIVTdDEOxrZ8KspclWk7H6OAAPIYvgZeYjox21qXN BknpIifVoaYUoxi3e81k25erm/Xww4uU2SMQgvq3sBrs0YGANembfxas BRVmSmBykpugHgS1/Fl19Hp40y/JTBzqOLrHgPgHO4aH89dgta0WlMhb 8uCUOjHNjcR+KO3KUpKDZkH8IuJHWWFd0TabdV0KBhpInQh6Yorhpjg7 qNBbgA== +; resign=20900122074341 +a.rsasha1.example. 300 IN A 10.0.0.1 +a.rsasha1.example. 300 IN RRSIG A 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. eJyAqMArSagK54kSFvJxE5qYXFSDYxj6Vt8l4gi58BQigO7p5v0BUWcS icToRx3a9+rSdhnBuGbOWGNlrKFfCKrLmqYrlI9GFSAFLAFj7DETSKDJ X5dQ0KnpyGL3SneQsDWAvAof0y9B17dnBHQMSjeVqqQLjYEnq3ZIdT3c b6emCGMhcbfIAOYWt7t9nk/J2tsTsdoKtTCHP1SHjn5sE++BPXOce49X gFnNMD+pOcoLH8Z07RcTQ8IeNIa9hO8UaypyicaHQ2F0JtsiL1pqREXf QsBeLC12Gbi0rxJX3gdj0LXsmSerVl6BgaNjPTp3840WKrW3nTG/8Lre bxgkow== +; resign=20900122074341 +a.rsasha1.example. 300 IN NSEC b.rsasha1.example. A RRSIG NSEC +a.rsasha1.example. 300 IN RRSIG NSEC 5 3 300 20900122074341 20220104052934 30286 rsasha1.example. 6fZ5/GXrFAc9lEspMNlPa40F8O/tGq1oaSZXVstwLH124TNWxRK+i8eT H77Kq80vZkDus8rkLr4fiLP3ApXVBffCRHZWecGrYaPGDbQXALQEktld NhmLr9Nf30Jq7KvVV9Qf4daPC7ZwkB8EsikJxjpQ/paHlU/Pua7ZonnH /x9HHRJBLWb/PPQWEc++8SSjA79+HZVbB8rBwXyxHO1tFBCbBpK/JNwu KpRqNp/mwxPpSaJGZIuhHlzfbLsS4WoXjdG+fob4RqsPPwrf/uAAzKM2 dHVuqZ1erH3ryb4JdRo+MhqD0+vC/7+eNccEXraBsE5xGw4M62Se37WC kyQDQA== +; resign=20900122074341 diff --git a/bin/tests/system/dnssec/ns3/rsasha1.example.db.in b/bin/tests/system/dnssec/ns3/rsasha1.example.db.in new file mode 100644 index 0000000..b2e7e21 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha1.example.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 diff --git a/bin/tests/system/dnssec/ns3/rsasha256.example.db.in b/bin/tests/system/dnssec/ns3/rsasha256.example.db.in new file mode 100644 index 0000000..f6c4fab --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha256.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a diff --git a/bin/tests/system/dnssec/ns3/rsasha512.example.db.in b/bin/tests/system/dnssec/ns3/rsasha512.example.db.in new file mode 100644 index 0000000..f6c4fab --- /dev/null +++ b/bin/tests/system/dnssec/ns3/rsasha512.example.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2009102722 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a diff --git a/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in b/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/secure.below-cname.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in new file mode 100644 index 0000000..9aebd98 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/secure.example.db.in @@ -0,0 +1,54 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 +e A 10.0.0.5 +f A 10.0.0.6 +g A 10.0.0.7 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a +badalg A 10.53.0.4 + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns2.insecure +ns2.insecure A 10.53.0.2 + +nosoa NS ns.nosoa +ns.nosoa A 10.53.0.7 + +normalthenrrsig A 10.0.0.28 +rrsigonly A 10.0.0.29 + +cnameandkey CNAME @ +cnamenokey CNAME @ +dnameandkey DNAME @ + +mixedcase A 10.0.0.30 +mixedCASE TXT "mixed case" +MIXEDcase AAAA 2002:: +mIxEdCaSe LOC 37 52 56.788 N 121 54 55.02 W 1120m 10m 100m 10m diff --git a/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/secure.optout.example.db.in b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in new file mode 100644 index 0000000..15fe621 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + diff --git a/bin/tests/system/dnssec/ns3/siginterval.example.db.in b/bin/tests/system/dnssec/ns3/siginterval.example.db.in new file mode 100644 index 0000000..ec6603a --- /dev/null +++ b/bin/tests/system/dnssec/ns3/siginterval.example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2012042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS ns +ns A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns3/siginterval1.conf b/bin/tests/system/dnssec/ns3/siginterval1.conf new file mode 100644 index 0000000..1d82f68 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/siginterval1.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "siginterval.example" { + type primary; + allow-update { any; }; + dnssec-policy siginterval1; + file "siginterval.example.db"; +}; diff --git a/bin/tests/system/dnssec/ns3/siginterval2.conf b/bin/tests/system/dnssec/ns3/siginterval2.conf new file mode 100644 index 0000000..fa9c626 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/siginterval2.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "siginterval.example" { + type primary; + allow-update { any; }; + dnssec-policy siginterval2; + file "siginterval.example.db"; +}; diff --git a/bin/tests/system/dnssec/ns3/sign-rsasha1-1024.sh b/bin/tests/system/dnssec/ns3/sign-rsasha1-1024.sh new file mode 100644 index 0000000..20e4bc5 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/sign-rsasha1-1024.sh @@ -0,0 +1,27 @@ +#!/bin/sh -ef + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# RSASHA1 is validate only in FIPS mode so we need to have a pre-signed +# version of the zone to test with in FIPS mode. This requires a non +# FIPS build which supports RSASHA1 to be used to generate it. + +. ../../conf.sh + +zone=rsasha1-1024.example +k1=$("$KEYGEN" -a rsasha1 -b 1024 $zone) +k2=$("$KEYGEN" -a rsasha1 -b 1024 -f KSK $zone) +cat $zone.db.in $k1.key $k2.key >$zone.tmp +# use maximum expirey period (-e 2^31-1-3600) +# use output format full for easy extraction of KSK (-O full) +"$SIGNER" -e +2147480047 -o $zone -f $zone.db -O full $zone.tmp +rm -f $k1.key $k1.private $k2.key $k2.private $zone.tmp diff --git a/bin/tests/system/dnssec/ns3/sign-rsasha1.sh b/bin/tests/system/dnssec/ns3/sign-rsasha1.sh new file mode 100644 index 0000000..c62f3fe --- /dev/null +++ b/bin/tests/system/dnssec/ns3/sign-rsasha1.sh @@ -0,0 +1,27 @@ +#!/bin/sh -ef + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# RSASHA1 is validate only in FIPS mode so we need to have a pre-signed +# version of the zone to test with in FIPS mode. This requires a non +# FIPS build which supports RSASHA1 to be used to generate it. + +. ../../conf.sh + +zone=rsasha1.example +k1=$("$KEYGEN" -a rsasha1 $zone) +k2=$("$KEYGEN" -a rsasha1 -f KSK $zone) +cat $zone.db.in $k1.key $k2.key >$zone.tmp +# use maximum expirey period (-e 2^31-1-3600) +# use output format full for easy extraction of KSK (-O full) +"$SIGNER" +2147480047 -o $zone -f $zone.db -O full $zone.tmp +rm -f $k1.key $k1.private $k2.key $k2.private $zone.tmp diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh new file mode 100644 index 0000000..f61ea28 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -0,0 +1,703 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +echo_i "ns3/sign.sh" + +infile=key.db.in +for tld in managed trusted; do + # A secure zone to test. + zone=secure.${tld} + zonefile=${zone}.db + + keyname1=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + cat "$infile" "$keyname1.key" >"$zonefile" + "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" >/dev/null + + # Zone to test trust anchor that matches disabled algorithm. + zone=disabled.${tld} + zonefile=${zone}.db + + keyname2=$("$KEYGEN" -f KSK -q -a "$DISABLED_ALGORITHM" -b "$DISABLED_BITS" -n zone "$zone") + cat "$infile" "$keyname2.key" >"$zonefile" + "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" >/dev/null + + # Zone to test trust anchor that has disabled algorithm for other domain. + zone=enabled.${tld} + zonefile=${zone}.db + + keyname3=$("$KEYGEN" -f KSK -q -a "$DISABLED_ALGORITHM" -b "$DISABLED_BITS" -n zone "$zone") + cat "$infile" "$keyname3.key" >"$zonefile" + "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" >/dev/null + + # Zone to test trust anchor with unsupported algorithm. + zone=unsupported.${tld} + zonefile=${zone}.db + + keyname4=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + cat "$infile" "$keyname4.key" >"$zonefile" + "$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" >/dev/null + awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefile}.tmp >${zonefile}.signed + + # Make trusted-keys and managed keys conf sections for ns8. + mv ${keyname4}.key ${keyname4}.tmp + awk '$1 == "unsupported.'"${tld}"'." { $6 = 255 } { print }' ${keyname4}.tmp >${keyname4}.key + + # Zone to test trust anchor that is revoked. + zone=revoked.${tld} + zonefile=${zone}.db + + keyname5=$("$KEYGEN" -f KSK -f REVOKE -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + cat "$infile" "$keyname5.key" >"$zonefile" + "$SIGNER" -z -P -3 - -o "$zone" -O full -f ${zonefile}.signed "$zonefile" >/dev/null + + case $tld in + "managed") + keyfile_to_initial_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns8/managed.conf + ;; + "trusted") + keyfile_to_static_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns8/trusted.conf + ;; + esac +done + +echo_i "ns3/sign.sh: example zones" + +zone=secure.example. +infile=secure.example.db.in +zonefile=secure.example.db + +cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone") +dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone") +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null +cat "$zonefile" "$zonefile".signed >"$zonefile".tmp +mv "$zonefile".tmp "$zonefile".signed + +zone=bogus.example. +infile=bogus.example.db.in +zonefile=bogus.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null + +zone=dynamic.example. +infile=dynamic.example.db.in +zonefile=dynamic.example.db + +keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -o "$zone" "$zonefile" >/dev/null + +zone=keyless.example. +infile=generic.example.db.in +zonefile=keyless.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null + +# Change the signer field of the a.b.keyless.example RRSIG A +# to point to a provably nonexistent DNSKEY record. +zonefiletmp=$(mktemp "$zonefile.XXXXXX") || exit 1 +mv "$zonefile.signed" "$zonefiletmp" +"$PERL" <"$zonefiletmp" -p -e 's/ keyless.example/ b.keyless.example/ + if /^a.b.keyless.example/../A RRSIG NSEC/;' >"$zonefile.signed" +rm -f "$zonefiletmp" + +# +# NSEC3/NSEC test zone +# +zone=secure.nsec3.example. +infile=secure.nsec3.example.db.in +zonefile=secure.nsec3.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null + +# +# NSEC3/NSEC3 test zone +# +zone=nsec3.nsec3.example. +infile=nsec3.nsec3.example.db.in +zonefile=nsec3.nsec3.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -o "$zone" "$zonefile" >/dev/null + +# +# OPTOUT/NSEC3 test zone +# +zone=optout.nsec3.example. +infile=optout.nsec3.example.db.in +zonefile=optout.nsec3.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" >/dev/null + +# +# A nsec3 zone (non-optout). +# +zone=nsec3.example. +infile=nsec3.example.db.in +zonefile=nsec3.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -g -3 - -o "$zone" "$zonefile" >/dev/null + +# +# OPTOUT/NSEC test zone +# +zone=secure.optout.example. +infile=secure.optout.example.db.in +zonefile=secure.optout.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null + +# +# OPTOUT/NSEC3 test zone +# +zone=nsec3.optout.example. +infile=nsec3.optout.example.db.in +zonefile=nsec3.optout.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -o "$zone" "$zonefile" >/dev/null + +# +# OPTOUT/OPTOUT test zone +# +zone=optout.optout.example. +infile=optout.optout.example.db.in +zonefile=optout.optout.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" >/dev/null + +# +# A optout nsec3 zone. +# +zone=optout.example. +infile=optout.example.db.in +zonefile=optout.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -g -3 - -A -o "$zone" "$zonefile" >/dev/null + +# +# A nsec3 zone (non-optout) with unknown nsec3 hash algorithm (-U). +# +zone=nsec3-unknown.example. +infile=nsec3-unknown.example.db.in +zonefile=nsec3-unknown.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -PU -o "$zone" "$zonefile" >/dev/null + +# +# A optout nsec3 zone with a unknown nsec3 hash algorithm (-U). +# +zone=optout-unknown.example. +infile=optout-unknown.example.db.in +zonefile=optout-unknown.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -PU -A -o "$zone" "$zonefile" >/dev/null + +# +# A zone that is signed with an unknown DNSKEY algorithm. +# Algorithm 7 is replaced by 100 in the zone and dsset. +# +zone=dnskey-unknown.example +infile=dnskey-unknown.example.db.in +zonefile=dnskey-unknown.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" >/dev/null + +awk '$4 == "DNSKEY" { $7 = 100 } $4 == "RRSIG" { $6 = 100 } { print }' ${zonefile}.tmp >${zonefile}.signed + +DSFILE="dsset-${zone}." +$DSFROMKEY -A -f ${zonefile}.signed "$zone" >"$DSFILE" + +# +# A zone that is signed with an unsupported DNSKEY algorithm (3). +# Algorithm 7 is replaced by 255 in the zone and dsset. +# +zone=dnskey-unsupported.example +infile=dnskey-unsupported.example.db.in +zonefile=dnskey-unsupported.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" >/dev/null + +awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefile}.tmp >${zonefile}.signed + +DSFILE="dsset-${zone}." +$DSFROMKEY -A -f ${zonefile}.signed "$zone" >"$DSFILE" + +# +# A zone which uses an unsupported algorithm for a DNSKEY and an unsupported +# digest for another DNSKEY +# +zone=digest-alg-unsupported.example. +infile=digest-alg-unsupported.example.db.in +zonefile=digest-alg-unsupported.example.db + +cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone") +dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone") +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +keyname2=$("$KEYGEN" -q -a ECDSAP384SHA384 -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null +cat "$zonefile" "$zonefile".signed >"$zonefile".tmp +mv "$zonefile".tmp "$zonefile".signed + +# override generated DS record file so we can set different digest to each keys +DSFILE="dsset-${zone}" +$DSFROMKEY -a SHA-384 -A -f ${zonefile}.signed "$zone" | head -n 1 >"$DSFILE" +$DSFROMKEY -2 -A -f ${zonefile}.signed "$zone" | tail -1 >>"$DSFILE" + +# +# A zone which is fine by itself (supported algorithm) but that is used +# to mimic unsupported DS digest (see ns8). +# +zone=ds-unsupported.example. +infile=ds-unsupported.example.db.in +zonefile=ds-unsupported.example.db + +cnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "cnameandkey.$zone") +dnameandkey=$("$KEYGEN" -T KEY -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n host "dnameandkey.$zone") +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null +cat "$zonefile" "$zonefile".signed >"$zonefile".tmp +mv "$zonefile".tmp "$zonefile".signed + +# +# A zone with a published unsupported DNSKEY algorithm (Reserved). +# Different from above because this key is not intended for signing. +# +zone=dnskey-unsupported-2.example +infile=dnskey-unsupported-2.example.db.in +zonefile=dnskey-unsupported-2.example.db + +ksk=$("$KEYGEN" -f KSK -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$ksk.key" "$zsk.key" unsupported-algorithm.key >"$zonefile" + +"$SIGNER" -3 - -o "$zone" -f ${zonefile}.signed "$zonefile" >/dev/null + +# +# A zone with a unknown DNSKEY algorithm + unknown NSEC3 hash algorithm (-U). +# Algorithm 7 is replaced by 100 in the zone and dsset. +# +zone=dnskey-nsec3-unknown.example +infile=dnskey-nsec3-unknown.example.db.in +zonefile=dnskey-nsec3-unknown.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -o "$zone" -PU -O full -f ${zonefile}.tmp "$zonefile" >/dev/null + +awk '$4 == "DNSKEY" { $7 = 100; print } $4 == "RRSIG" { $6 = 100; print } { print }' ${zonefile}.tmp >${zonefile}.signed + +DSFILE="dsset-${zone}." +$DSFROMKEY -A -f ${zonefile}.signed "$zone" >"$DSFILE" + +# +# A multiple parameter nsec3 zone. +# +zone=multiple.example. +infile=multiple.example.db.in +zonefile=multiple.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -O full -o "$zone" "$zonefile" >/dev/null +awk '$4 == "NSEC" || ( $4 == "RRSIG" && $5 == "NSEC" ) { print }' "$zonefile".signed >NSEC +"$SIGNER" -z -O full -u3 - -o "$zone" "$zonefile" >/dev/null +awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >NSEC3 +"$SIGNER" -z -O full -u3 AAAA -o "$zone" "$zonefile" >/dev/null +awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >>NSEC3 +"$SIGNER" -z -O full -u3 BBBB -o "$zone" "$zonefile" >/dev/null +awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >>NSEC3 +"$SIGNER" -z -O full -u3 CCCC -o "$zone" "$zonefile" >/dev/null +awk '$4 == "NSEC3" || ( $4 == "RRSIG" && $5 == "NSEC3" ) { print }' "$zonefile".signed >>NSEC3 +"$SIGNER" -z -O full -u3 DDDD -o "$zone" "$zonefile" >/dev/null +cat NSEC NSEC3 >>"$zonefile".signed + +# +# A RSASHA256 zone. +# +zone=rsasha256.example. +infile=rsasha256.example.db.in +zonefile=rsasha256.example.db + +keyname=$("$KEYGEN" -q -a RSASHA256 -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# A RSASHA512 zone. +# +zone=rsasha512.example. +infile=rsasha512.example.db.in +zonefile=rsasha512.example.db + +keyname=$("$KEYGEN" -q -a RSASHA512 -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# A zone with the DNSKEY set only signed by the KSK +# +zone=kskonly.example. +infile=kskonly.example.db.in +zonefile=kskonly.example.db + +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -x -o "$zone" "$zonefile" >/dev/null + +# +# A zone with the expired signatures +# +zone=expired.example. +infile=expired.example.db.in +zonefile=expired.example.db + +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -o "$zone" -s -1d -e +1h "$zonefile" >/dev/null +rm -f "$kskname.*" "$zskname.*" + +# +# A NSEC3 signed zone that will have a DNSKEY added to it via UPDATE. +# +zone=update-nsec3.example. +infile=update-nsec3.example.db.in +zonefile=update-nsec3.example.db + +kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -3 - -o "$zone" "$zonefile" >/dev/null + +# +# A NSEC signed zone that will have dnssec-policy enabled and +# extra keys not in the initial signed zone. +# +zone=auto-nsec.example. +infile=auto-nsec.example.db.in +zonefile=auto-nsec.example.db + +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +"$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -fk "$zone" >/dev/null +"$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" "$zone" >/dev/null +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# A NSEC3 signed zone that will have dnssec-policy enabled and +# extra keys not in the initial signed zone. +# +zone=auto-nsec3.example. +infile=auto-nsec3.example.db.in +zonefile=auto-nsec3.example.db + +kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +"$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -fk "$zone" >/dev/null +"$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" "$zone" >/dev/null +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -3 - -o "$zone" "$zonefile" >/dev/null + +# +# Secure below cname test zone. +# +zone=secure.below-cname.example. +infile=secure.below-cname.example.db.in +zonefile=secure.below-cname.example.db +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$keyname.key" >"$zonefile" +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# Patched TTL test zone. +# +zone=ttlpatch.example. +infile=ttlpatch.example.db.in +zonefile=ttlpatch.example.db +signedfile=ttlpatch.example.db.signed +patchedfile=ttlpatch.example.db.patched + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -P -f $signedfile -o "$zone" "$zonefile" >/dev/null +$CHECKZONE -D -s full "$zone" $signedfile 2>/dev/null \ + | awk '{$2 = "3600"; print}' >$patchedfile + +# +# Separate DNSSEC records. +# +zone=split-dnssec.example. +infile=split-dnssec.example.db.in +zonefile=split-dnssec.example.db +signedfile=split-dnssec.example.db.signed + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$keyname.key" >"$zonefile" +echo "\$INCLUDE \"$signedfile\"" >>"$zonefile" +: >"$signedfile" +"$SIGNER" -P -D -o "$zone" "$zonefile" >/dev/null + +# +# Separate DNSSEC records smart signing. +# +zone=split-smart.example. +infile=split-smart.example.db.in +zonefile=split-smart.example.db +signedfile=split-smart.example.db.signed + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cp "$infile" "$zonefile" +# shellcheck disable=SC2016 +echo "\$INCLUDE \"$signedfile\"" >>"$zonefile" +: >"$signedfile" +"$SIGNER" -P -S -D -o "$zone" "$zonefile" >/dev/null + +# +# Zone with signatures about to expire, but no private key to replace them +# +zone="expiring.example." +infile="expiring.example.db.in" +zonefile="expiring.example.db" +signedfile="expiring.example.db.signed" +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +cp "$infile" "$zonefile" +"$SIGNER" -S -e now+1mi -o "$zone" "$zonefile" >/dev/null +mv -f "${zskname}.private" "${zskname}.private.moved" +mv -f "${kskname}.private" "${kskname}.private.moved" + +# +# A zone where the signer's name has been forced to uppercase. +# +zone="upper.example." +infile="upper.example.db.in" +zonefile="upper.example.db" +lower="upper.example.db.lower" +signedfile="upper.example.db.signed" +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +cp "$infile" "$zonefile" +"$SIGNER" -P -S -o "$zone" -f $lower "$zonefile" >/dev/null +$CHECKZONE -D upper.example $lower 2>/dev/null \ + | sed '/RRSIG/s/ upper.example. / UPPER.EXAMPLE. /' >$signedfile + +# +# Check that the signer's name is in lower case when zone name is in +# upper case. +# +zone="LOWER.EXAMPLE." +infile="lower.example.db.in" +zonefile="lower.example.db" +signedfile="lower.example.db.signed" +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +cp "$infile" "$zonefile" +"$SIGNER" -P -S -o "$zone" "$zonefile" >/dev/null + +# +# An inline signing zone +# +zone=inline.example. +kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") + +# +# A zone which will change its signatures-validity +# +zone=siginterval.example +infile=siginterval.example.db.in +zonefile=siginterval.example.db +kskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -fk "$zone") +zskname=$("$KEYGEN" -q -3 -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cp "$infile" "$zonefile" + +# +# A zone with a bad DS in the parent +# (sourced from bogus.example.db.in) +# +zone=badds.example. +infile=bogus.example.db.in +zonefile=badds.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null +sed -e 's/bogus/badds/g' dsset-badds.example. + +# +# A zone with future signatures. +# +zone=future.example +infile=future.example.db.in +zonefile=future.example.db +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -s +3600 -o "$zone" "$zonefile" >/dev/null +cp -f "$kskname.key" trusted-future.key + +# +# A zone with future signatures. +# +zone=managed-future.example +infile=managed-future.example.db.in +zonefile=managed-future.example.db +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +cat "$infile" "$kskname.key" "$zskname.key" >"$zonefile" +"$SIGNER" -P -s +3600 -o "$zone" "$zonefile" >/dev/null + +# +# A zone with a revoked key +# +zone=revkey.example. +infile=generic.example.db.in +zonefile=revkey.example.db + +ksk1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3fk "$zone") +ksk1=$("$REVOKE" "$ksk1") +ksk2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3fk "$zone") +zsk1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -3 "$zone") + +cat "$infile" "${ksk1}.key" "${ksk2}.key" "${zsk1}.key" >"$zonefile" +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# Check that NSEC3 are correctly signed and returned from below a DNAME +# +zone=dname-at-apex-nsec3.example +infile=dname-at-apex-nsec3.example.db.in +zonefile=dname-at-apex-nsec3.example.db + +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3fk "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -3 "$zone") +cat "$infile" "${kskname}.key" "${zskname}.key" >"$zonefile" +"$SIGNER" -P -3 - -o "$zone" "$zonefile" >/dev/null + +# +# A NSEC zone with occluded data at the delegation +# +zone=occluded.example +infile=occluded.example.db.in +zonefile=occluded.example.db +kskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "$zone") +zskname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" "$zone") +dnskeyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -fk "delegation.$zone") +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -n HOST -T KEY "delegation.$zone") +$DSFROMKEY "$dnskeyname.key" >"dsset-delegation.${zone}." +cat "$infile" "${kskname}.key" "${zskname}.key" "${keyname}.key" \ + "${dnskeyname}.key" "dsset-delegation.${zone}." >"$zonefile" +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null + +# +# Pre-signed zone for FIPS validation of RSASHA1 signed zones +# See sign-rsasha1.sh for how to regenerate rsasha1.example.db +# with non-FIPS compliant instance. +# +# We only need to generate the dsset. +# +zone=rsasha1.example +zonefile=rsasha1.example.db +awk '$4 == "DNSKEY" && $5 == 257 { print }' "$zonefile" \ + | $DSFROMKEY -f - "$zone" >"dsset-${zone}." + +zone=rsasha1-1024.example +zonefile=rsasha1-1024.example.db +awk '$4 == "DNSKEY" && $5 == 257 { print }' "$zonefile" \ + | $DSFROMKEY -f - "$zone" >"dsset-${zone}." diff --git a/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in b/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in new file mode 100644 index 0000000..55b3877 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/split-dnssec.example.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/dnssec/ns3/split-smart.example.db.in b/bin/tests/system/dnssec/ns3/split-smart.example.db.in new file mode 100644 index 0000000..55b3877 --- /dev/null +++ b/bin/tests/system/dnssec/ns3/split-smart.example.db.in @@ -0,0 +1,38 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +child NS ns2.example. +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17 diff --git a/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in b/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in new file mode 100644 index 0000000..14971bd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/ttlpatch.example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/dnssec/ns3/unsupported-algorithm.key b/bin/tests/system/dnssec/ns3/unsupported-algorithm.key new file mode 100644 index 0000000..cc8bb9a --- /dev/null +++ b/bin/tests/system/dnssec/ns3/unsupported-algorithm.key @@ -0,0 +1 @@ +dnskey-unsupported-2.example. IN DNSKEY 257 3 255 BJ0eV4dQC0pihdFXiVdlXjPDkzbv4fC+opEvK0RaDU7LLwFXPAi6DOc6tm7vcSr5Tgdnpoal3S4WqHuVw6I1pzy5mPPIZ3OpLSY/QeOyGc2QRAZtOXxiGxERHRjyAk7emlgGscM0Vty2oJVYRgTPX0lTwKX/V2H+mjEgp7u3tyG3cj5XBUQ8J0KUoqkrn1ZKrizH27aWiDaBUvqxJUcotaDhnydkNtcHoQIedm2b4qbyTQsdRkddJiSWxpveEcj3AMdt2PjU6Q4rgSWOc5ylPnW/O+GqqCEAkalGSF7ud0Nl3FVVR9iGwV/73FHzpBLawfkcHaODFmKRjzGqok8giKCih2vdNsxlx7gdJWJIPYYx/ZqNGc2ewzuAnnleJpZdXFo8uL3HYk6Pl51sSkfVUmcn/SM+ ;{id = 38688 (ksk), size = 768b} diff --git a/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in new file mode 100644 index 0000000..a7792fd --- /dev/null +++ b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in @@ -0,0 +1,40 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 +x CNAME a + +private NS ns.private +ns.private A 10.53.0.2 + +insecure NS ns.insecure +ns.insecure A 10.53.0.2 + +nosoa NS ns.nosoa +ns.nosoa A 10.53.0.7 + +normalthenrrsig A 10.0.0.28 +rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/upper.example.db.in b/bin/tests/system/dnssec/ns3/upper.example.db.in new file mode 100644 index 0000000..ec6603a --- /dev/null +++ b/bin/tests/system/dnssec/ns3/upper.example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2012042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS ns +ns A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns4/managed-keys.bind.in b/bin/tests/system/dnssec/ns4/managed-keys.bind.in new file mode 100644 index 0000000..570669d --- /dev/null +++ b/bin/tests/system/dnssec/ns4/managed-keys.bind.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 0 ; 0 seconds +@ IN SOA . . ( + 2 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + KEYDATA 20221028094934 19700101000000 19700101000000 0 0 0 ; placeholder diff --git a/bin/tests/system/dnssec/ns4/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in new file mode 100644 index 0000000..8e29a45 --- /dev/null +++ b/bin/tests/system/dnssec/ns4/named1.conf.in @@ -0,0 +1,65 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + dnssec-must-be-secure mustbesecure.example yes; + minimal-responses no; + + nta-lifetime 12s; + nta-recheck 9s; + validate-except { corp; }; + + disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; + disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; + disable-ds-digests "ds-unsupported.example." {"SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; + disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; + + # Note: We only reference the bind.keys file here to confirm that it + # is *not* being used. It contains the real root key, and we're + # using a local toy root zone for the tests, so it wouldn't work. + # But since dnssec-validation is set to "yes" not "auto", that + # won't matter. + bindkeys-file "../../../../../bind.keys"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "corp" { + type static-stub; + server-addresses { 10.53.0.2; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns4/named2.conf.in b/bin/tests/system/dnssec/ns4/named2.conf.in new file mode 100644 index 0000000..bf82385 --- /dev/null +++ b/bin/tests/system/dnssec/ns4/named2.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation auto; + bindkeys-file "managed.conf"; + minimal-responses no; + disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; + disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; + disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; + disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/dnssec/ns4/named3.conf.in b/bin/tests/system/dnssec/ns4/named3.conf.in new file mode 100644 index 0000000..d6a44c7 --- /dev/null +++ b/bin/tests/system/dnssec/ns4/named3.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation auto; + bindkeys-file "managed.conf"; + dnssec-accept-expired yes; + minimal-responses no; + servfail-ttl 0; + + disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; + disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384";}; + disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; + disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in new file mode 100644 index 0000000..34f59b4 --- /dev/null +++ b/bin/tests/system/dnssec/ns4/named4.conf.in @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; + disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; + disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; + disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key auth { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +include "trusted.conf"; + +view rec { + match-recursive-only yes; + recursion yes; + dnssec-validation yes; + dnssec-accept-expired yes; + minimal-responses no; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; + + zone insecure.secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; +}; + +view auth { + recursion no; + allow-recursion { none; }; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone secure.example { + type secondary; + primaries { 10.53.0.3; }; + }; + + zone insecure.secure.example { + type secondary; + primaries { 10.53.0.2; }; + }; +}; diff --git a/bin/tests/system/dnssec/ns5/named1.conf.in b/bin/tests/system/dnssec/ns5/named1.conf.in new file mode 100644 index 0000000..ef371e1 --- /dev/null +++ b/bin/tests/system/dnssec/ns5/named1.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns5/named2.conf.in b/bin/tests/system/dnssec/ns5/named2.conf.in new file mode 100644 index 0000000..6d0474b --- /dev/null +++ b/bin/tests/system/dnssec/ns5/named2.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; 127.0.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +view root { + match-destinations { 127.0.0.1; }; + + zone "." { + type primary; + file "root.db.signed"; + }; +}; + +view other { +include "revoked.conf"; + + zone "." { + type static-stub; + server-addresses { 127.0.0.1; }; + }; +}; diff --git a/bin/tests/system/dnssec/ns5/sign.sh b/bin/tests/system/dnssec/ns5/sign.sh new file mode 100644 index 0000000..65105d0 --- /dev/null +++ b/bin/tests/system/dnssec/ns5/sign.sh @@ -0,0 +1,39 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +echo_i "ns5/sign.sh" + +zone=. +infile=../ns1/root.db.in +zonefile=root.db.signed + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") + +# copy the KSK out first, then revoke it +keyfile_to_initial_ds "$keyname" >revoked.conf + +"$SETTIME" -R now "${keyname}.key" >/dev/null + +# create a current set of keys, and sign the root zone +"$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" $zone >/dev/null +"$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK $zone >/dev/null +"$SIGNER" -S -o "$zone" -f "$zonefile" "$infile" >/dev/null 2>&1 + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".") + +keyfile_to_static_ds "$keyname" >trusted.conf diff --git a/bin/tests/system/dnssec/ns6/named.args b/bin/tests/system/dnssec/ns6/named.args new file mode 100644 index 0000000..04d5d1b --- /dev/null +++ b/bin/tests/system/dnssec/ns6/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D dnssec-ns6 -g -T maxcachesize=2097152 -T nonearest -T tat=1 diff --git a/bin/tests/system/dnssec/ns6/named.conf.in b/bin/tests/system/dnssec/ns6/named.conf.in new file mode 100644 index 0000000..2818b79 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/named.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + disable-algorithms . { @ALTERNATIVE_ALGORITHM@; }; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "optout-tld" { + type primary; + file "optout-tld.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns6/optout-tld.db.in b/bin/tests/system/dnssec/ns6/optout-tld.db.in new file mode 100644 index 0000000..b2aa393 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/optout-tld.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +optout-tld. 60 IN SOA example. . 0 0 0 0 0 +optout-tld. 60 IN NS ns6.optout-tld. +ns6.optout-tld. 60 IN A 10.53.0.6 +a 60 PTR example. +b 60 PTR example. +a.b.c.d 60 NS example. +e 60 PTR example. +f 60 PTR example. +g 60 PTR example. +h 60 PTR example. diff --git a/bin/tests/system/dnssec/ns6/sign.sh b/bin/tests/system/dnssec/ns6/sign.sh new file mode 100644 index 0000000..e3ff2d2 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/sign.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +echo_i "ns6/sign.sh" + +zone=optout-tld +infile=optout-tld.db.in +zonefile=optout-tld.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -3 - -A -o "$zone" "$zonefile" >/dev/null 2>&1 diff --git a/bin/tests/system/dnssec/ns7/named.conf.in b/bin/tests/system/dnssec/ns7/named.conf.in new file mode 100644 index 0000000..b352846 --- /dev/null +++ b/bin/tests/system/dnssec/ns7/named.conf.in @@ -0,0 +1,76 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; + minimal-responses yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "nsec3.example" { + type secondary; + primaries { 10.53.0.3; }; + file "nsec3.example.bk"; +}; + +zone "optout.example" { + type secondary; + primaries { 10.53.0.3; }; + file "optout.example.bk"; +}; + +zone "nsec3-unknown.example" { + type secondary; + primaries { 10.53.0.3; }; + file "nsec3-unknown.example.bk"; +}; + +zone "optout-unknown.example" { + type secondary; + primaries { 10.53.0.3; }; + file "optout-unknown.example.bk"; +}; + +zone "multiple.example" { + type secondary; + primaries { 10.53.0.3; }; + file "multiple.example.bk"; +}; + +zone "nosoa.secure.example" { + type primary; + file "nosoa.secure.example.db"; +}; + +zone "split-rrsig" { + type primary; + file "split-rrsig.db.signed"; + allow-update { any; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns7/named.nosoa b/bin/tests/system/dnssec/ns7/named.nosoa new file mode 100644 index 0000000..caefbbb --- /dev/null +++ b/bin/tests/system/dnssec/ns7/named.nosoa @@ -0,0 +1,12 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +Add -T nosoa. diff --git a/bin/tests/system/dnssec/ns7/nosoa.secure.example.db b/bin/tests/system/dnssec/ns7/nosoa.secure.example.db new file mode 100644 index 0000000..d3c9878 --- /dev/null +++ b/bin/tests/system/dnssec/ns7/nosoa.secure.example.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2010062400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ IN NS ns +ns IN A 10.53.0.7 +a IN A 1.2.3.4 diff --git a/bin/tests/system/dnssec/ns7/sign.sh b/bin/tests/system/dnssec/ns7/sign.sh new file mode 100644 index 0000000..5e30050 --- /dev/null +++ b/bin/tests/system/dnssec/ns7/sign.sh @@ -0,0 +1,44 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +echo_i "ns7/sign.sh" + +zone=split-rrsig +infile=split-rrsig.db.in +zonefile=split-rrsig.db + +k1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +k2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$k1.key" "$k2.key" >"$zonefile" + +# The awk script below achieves two goals: +# +# - it puts one of the two RRSIG(SOA) records at the end of the zone file, so +# that these two records (forming a single RRset) are not placed immediately +# next to each other; the test then checks if RRSIG RRsets split this way are +# correctly added to resigning heaps, +# +# - it places a copy of one of the RRSIG(SOA) records somewhere else than at the +# zone apex; the test then checks whether such signatures are automatically +# removed from the zone after it is loaded. +"$SIGNER" -P -3 - -A -o "$zone" -O full -f "$zonefile.unsplit" -e now-3600 -s now-7200 "$zonefile" >/dev/null 2>&1 +awk 'BEGIN { r = ""; } + $4 == "RRSIG" && $5 == "SOA" && r == "" { r = $0; next; } + { print } + END { print r; print "not-at-zone-apex." r; }' "$zonefile.unsplit" >"$zonefile.signed" diff --git a/bin/tests/system/dnssec/ns7/split-rrsig.db.in b/bin/tests/system/dnssec/ns7/split-rrsig.db.in new file mode 100644 index 0000000..48c2f87 --- /dev/null +++ b/bin/tests/system/dnssec/ns7/split-rrsig.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +split-rrsig. 3660 IN SOA . . ( + 1 ; serial + 3600 ; refresh (1 hour) + 3600 ; retry (1 hour) + 3600 ; expire (1 hour) + 3600 ; minimum (1 hour) + ) + 3660 NS ns.example. +a.split-rrsig. 3660 IN A 192.0.2.2 +b.split-rrsig. 3660 IN A 192.0.2.2 diff --git a/bin/tests/system/dnssec/ns8/named.conf.in b/bin/tests/system/dnssec/ns8/named.conf.in new file mode 100644 index 0000000..2590de1 --- /dev/null +++ b/bin/tests/system/dnssec/ns8/named.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS8 + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + minimal-responses no; + disable-algorithms "disabled.managed." { @DISABLED_ALGORITHM@; }; + disable-algorithms "disabled.trusted." { @DISABLED_ALGORITHM@; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "managed.conf"; +include "trusted.conf"; + diff --git a/bin/tests/system/dnssec/ns9/named.conf.in b/bin/tests/system/dnssec/ns9/named.conf.in new file mode 100644 index 0000000..cdbe7ec --- /dev/null +++ b/bin/tests/system/dnssec/ns9/named.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS9 + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + forward only; + forwarders { 10.53.0.4; }; + servfail-ttl 0; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ntadiff.pl b/bin/tests/system/dnssec/ntadiff.pl new file mode 100755 index 0000000..ca80eac --- /dev/null +++ b/bin/tests/system/dnssec/ntadiff.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use Time::Piece; +use Time::Seconds; + +exit 1 if (scalar(@ARGV) != 2); + +my $actual = Time::Piece->strptime($ARGV[0], '%d-%b-%Y %H:%M:%S.000 %z'); +my $expected = Time::Piece->strptime($ARGV[1], '%s') + ONE_WEEK; +my $diff = abs($actual - $expected); + +print($diff . "\n"); diff --git a/bin/tests/system/dnssec/prereq.sh b/bin/tests/system/dnssec/prereq.sh new file mode 100644 index 0000000..32889aa --- /dev/null +++ b/bin/tests/system/dnssec/prereq.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh new file mode 100644 index 0000000..dc53ea8 --- /dev/null +++ b/bin/tests/system/dnssec/setup.sh @@ -0,0 +1,50 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf + +copy_setports ns4/named1.conf.in ns4/named.conf +copy_setports ns5/named1.conf.in ns5/named.conf + +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf + +copy_setports ns9/named.conf.in ns9/named.conf + +( + cd ns1 + $SHELL sign.sh + { + echo "a.bogus.example. A 10.0.0.22" + echo "b.bogus.example. A 10.0.0.23" + echo "c.bogus.example. A 10.0.0.23" + } >>../ns3/bogus.example.db.signed +) + +( + cd ns3 + cp -f siginterval1.conf siginterval.conf +) + +( + cd ns5 + $SHELL sign.sh +) diff --git a/bin/tests/system/dnssec/signer/example.db.in b/bin/tests/system/dnssec/signer/example.db.in new file mode 100644 index 0000000..3ab6aa2 --- /dev/null +++ b/bin/tests/system/dnssec/signer/example.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +example. 60 IN SOA example. . 0 0 0 0 0 +example. 60 IN NS example. +example. 60 IN A 1.2.3.4 +; out of zone record +out-of-zone. 60 IN A 1.2.3.4 diff --git a/bin/tests/system/dnssec/signer/general/K.+013+23640.key b/bin/tests/system/dnssec/signer/general/K.+013+23640.key new file mode 100644 index 0000000..df4ff32 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/K.+013+23640.key @@ -0,0 +1,6 @@ +; This is a key-signing key, keyid 23640, for . +; Created: 20250310185208 (Mon Mar 10 18:52:08 2025) +; Publish: 20250310185208 (Mon Mar 10 18:52:08 2025) +; Activate: 20250310185208 (Mon Mar 10 18:52:08 2025) +; Revoke: 20250310185208 (Mon Mar 10 18:52:08 2025) +. IN DNSKEY 257 3 13 uKwpRtMH+9iuUk/Xj6LciIP5ZckaBtXaUqxUxzJYexXjvxGZGX4470Jv hq2NCI3HBZQNaCCP/h9sluhIzRGPTA== diff --git a/bin/tests/system/dnssec/signer/general/K.+013+23640.private b/bin/tests/system/dnssec/signer/general/K.+013+23640.private new file mode 100644 index 0000000..36f932f --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/K.+013+23640.private @@ -0,0 +1,7 @@ +Private-key-format: v1.3 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: m5udfGNSijISQ8Tfp4kx09O1em4PErLUw/mCj3SKmqw= +Created: 20250310185208 +Publish: 20250310185208 +Activate: 20250310185208 +Revoke: 20250310185208 diff --git a/bin/tests/system/dnssec/signer/general/K.+013+23768.key b/bin/tests/system/dnssec/signer/general/K.+013+23768.key new file mode 100644 index 0000000..85e460a --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/K.+013+23768.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 23768, for . +; Created: 20250310185208 (Mon Mar 10 18:52:08 2025) +; Publish: 20250310185208 (Mon Mar 10 18:52:08 2025) +; Activate: 20250310185208 (Mon Mar 10 18:52:08 2025) +. IN DNSKEY 256 3 13 TFelYtTRBWeA9A307vvuWIcaNwW4txW4RgSELtsi46ZQs24ncRxmxtFf uJuPyVXePNiE4HNI9CIowGUsn5WuBw== diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.key new file mode 100644 index 0000000..104face --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 19857, for example.com. +; Created: 20220902075244 (Fri Sep 2 17:52:44 2022) +; Publish: 20220902075244 (Fri Sep 2 17:52:44 2022) +; Activate: 20220902075244 (Fri Sep 2 17:52:44 2022) +example.com. IN DNSKEY 256 3 5 AwEAAaUr14RTAa2dr/JPoMv5QM32IbLMNUZFPAM9M2Zm6Ef9S3/UsRk9 W+P08Dx5Xte/PMuZK8ejWUyou37LowmVbahkP2kcS7Z552btsLnGK2+5 me5Y/GgnodhMVN7phkEQNPRKSUQQyLdQC6Ltzt0JVp48q4PmgCta22et rgq1YEoj2E8Po53bn5eQXCUsnkBFhkql9/17Ls2ckWNBkHWiItMDaWk7 qkM4ZJu7C/jq3ybBjn0bi4Svlt7PNiuuo3h5WaJYJHXd2M7PIN14rUDE cas/b+iy4eF7VC3CRUgt1spFinW/G4wSro55e6phstc3I1BE6B+pC4pq eGlAfQqWWcs= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.private new file mode 100644 index 0000000..91171b0 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+19857.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 5 (RSASHA1) +Modulus: pSvXhFMBrZ2v8k+gy/lAzfYhssw1RkU8Az0zZmboR/1Lf9SxGT1b4/TwPHle1788y5krx6NZTKi7fsujCZVtqGQ/aRxLtnnnZu2wucYrb7mZ7lj8aCeh2ExU3umGQRA09EpJRBDIt1ALou3O3QlWnjyrg+aAK1rbZ62uCrVgSiPYTw+jndufl5BcJSyeQEWGSqX3/XsuzZyRY0GQdaIi0wNpaTuqQzhkm7sL+OrfJsGOfRuLhK+W3s82K66jeHlZolgkdd3Yzs8g3XitQMRxqz9v6LLh4XtULcJFSC3WykWKdb8bjBKujnl7qmGy1zcjUEToH6kLimp4aUB9CpZZyw== +PublicExponent: AQAB +PrivateExponent: HzQaIgCAd6krnS5X5VDwYjiWgy26/syDmuUL+dOFHFyIz9yBnJAP9Q/H9tTDCyUwuhH0yGFetHHIAhs8cMoPDlnp9NSIpS+AfNx4n5AFkrTQlMuw24hpNfCts/MQDuid6GzETJyTHrZ7jEs64l0qRPiXOnLoUch3XK3eDF3ZlAfFkoPBFA5KIbiK8dcCahUmV4WReyE80X2N2dUloE8vLzy/j7yY2z1/HjhAu74S264wQMxNmJ0MsHeu78y7n8SKEJxncbgAciCNoamiQFiBGYYrs72B6BGHc19fhD5G7ldjpXukes9bHJSgj5ohseRJ27hkK7sKnqzOx/5Se6F5EQ== +Prime1: vNcFqw4Gu/gsEcte00YXSGGkOWlsEAOEARMy+l7yYVC9GMR41YuINydu42Bj+D/Qq1ifYk9ok26VnXsJ6GFWK9DdFFtSElCzq1Crb7/7yuRR86cM9UBr3045g9tvlH6sL+yeH1ESr8vNZtmlytDifw2Xp2kg0xoJnlnV0ZXphOk= +Prime2: 3+nmSodd/lDzVvn3uGMKux2B1mI2iApKM6bbwMwrzobN5bFkLkW1y1PuOYJytX1Sm39ecLCPYEmSf56kCitAquj7B98sblg05Y1QKvTTyX4uUsKFx3YAjvgp+acuI0Rq5J5GeSFCvdttgqAWdvvjoI8ic44K3sT1XTexaoLByJM= +Exponent1: jUmr2gHSlAzonB+3QQfuH5++iZ4Q1iJrP4qn15/2ZU1NThyh89REBFAirUjPQ0wryieyiJG1Qqm4k20dSpqZKItK/hIdY8qxwvnGawQPVgxiLJTOIykiDJ+wdLFX2Ji2J903qWK1QoaPleY+H3MOI9V9pCoJ/yg6DhpU2kz5vRE= +Exponent2: 04rLQ0Y4ivg3rchjPRR1Iupxq/UFx+jQyZOusaszB99bztGU8BJz+jDFNBgF/2jzDm1678Qe8L0RZvidye2rHs0VvQ4fj/BNqUGkp7C+FfLcGNwmP5dAV9Ik9fP4JuGQi4Ts16uQvoX8JBjSoH7BQwN3bOyZYHV7yiG/v/zgz3k= +Coefficient: l8vCrMMiS8eWYQNM/SPa4/swn1/EZtcgPcBqMa3zia+9rOJ4/mzRcQTKz6B7c7Z9BVoTzMWGlgd94PTDeLN9fbTNmRs/8JwwgzJ8FeJeisvZquvarFtq2PdVVZQSxTwt7N6DUMVcA8Vbdq+uGjJghs22/sJ23MS3key+PUHtwFI= +Created: 20220902075244 +Publish: 20220902075244 +Activate: 20220902075244 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.key new file mode 100644 index 0000000..717d65f --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 45884, for example.com. +; Created: 20220902075336 (Fri Sep 2 17:53:36 2022) +; Publish: 20220902075336 (Fri Sep 2 17:53:36 2022) +; Activate: 20220902075336 (Fri Sep 2 17:53:36 2022) +example.com. IN DNSKEY 257 3 5 AwEAAZ6aTwNhgMDJ8AObT38LEX4nZe0CFXKkFv8fzBhEJEWgJRplhEhx laqGc47NoXChBiz5qdX2qAC0zi4CRydmV8TdG9shpED9kapIl7KVM3wj +irX36R9TpFT7Otmvsh7/RbRfpKz4I0pCC01hRHyj7EodMC4j3LMF9sc GWNmiOTQI1PTxbvIEDeDfoTUDMFzvOwVmH1Bq+SzA9Ikm2VADZO4vIIO J/07lWT+LDQ/g1qiCNaSDyNhGfNVf8xYvmB8OXomGFLqDuSpUkwdL5kB 2gGmnUbIH+Pn+pcN9fxVniKH3mzYEGCxIspePbhvwDfB30gTmE8uaFMa 7McouGKW3Ps= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.private new file mode 100644 index 0000000..891c6c3 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+005+45884.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 5 (RSASHA1) +Modulus: nppPA2GAwMnwA5tPfwsRfidl7QIVcqQW/x/MGEQkRaAlGmWESHGVqoZzjs2hcKEGLPmp1faoALTOLgJHJ2ZXxN0b2yGkQP2RqkiXspUzfCP6KtffpH1OkVPs62a+yHv9FtF+krPgjSkILTWFEfKPsSh0wLiPcswX2xwZY2aI5NAjU9PFu8gQN4N+hNQMwXO87BWYfUGr5LMD0iSbZUANk7i8gg4n/TuVZP4sND+DWqII1pIPI2EZ81V/zFi+YHw5eiYYUuoO5KlSTB0vmQHaAaadRsgf4+f6lw31/FWeIofebNgQYLEiyl49uG/AN8HfSBOYTy5oUxrsxyi4Ypbc+w== +PublicExponent: AQAB +PrivateExponent: SSWu0kbaPFAGH4u2NsgSicW+5vfCj4xpRMHT/c8TkX8CDbILN+QW3D5FNnPVBJ5nPD/rGdC3/BdnTeXkDiJP0W4Ohlp2KDkqQMhZGlZgl9z56F+GeBUIstLrnkfVLp6sg6UcBKnsIv5tFHiuBjCCH/kiG64jDpVdXUMQ3HyyHyC67sB1gIqpZdhQxFliVIaebwXHlv4uWi31DxTUj0mmutmpTD1r4z+43DlU3JL07WBBpIoOmG/GoFoDr+JNWWwArnhHDZFl6XL1Z2u5ojdIOcgLTXcU1SdvFwBHIAH9PIwvow0gVcZTIHwDYJ41CL6YExXF8ymVpIPspZPaFwSxvQ== +Prime1: 2iWvbJTRrJuceM1CgOTMMoi/qMN/GtthmbL5V0w+hyFE6UzCWYQXED5YTPtoXk9tZ/YpnD7i5i7ru8VbLx0DAIrLkAFP3Xpxa7dvdRGzyPGuYARsjgNnj57M5Sl1tTTsZpkXaKEeiONCA6+vcSuc2l1NxqdDbhC/TwlpjOAbPRc= +Prime2: uh+ZuRel3T3qvD7acXm2UyF2BdeEEwwIvzqZVi3uxwUTd/TxFA7+3xuX6LNM+HK5fNxuB3exVC8OzALFzUOOJECVFUfhKi/1+VrVfBuJnyLlqQ14RncbZvsn+ScfGZpgYuacvq0zWiP2scxmXSQxchxcFVRCKFRCCVGVuOLzNb0= +Exponent1: coA7TrPiRkY7YBDk6kCtiYzLhKpwaclitkkBpTeozkbBI++dR10UufrvYCDJzE7Gbz3+4zsC360bIKjbTqRcsgkoBcMah3bAV7ilsP4EruFkFJPd4sCYuAKzK0mStfU8bDHI3qtLGrCmMschQDaTEu7MZwveUcRKlhKrqzzqLys= +Exponent2: jlnU7KeViBzvB4La96crN3GEHvuyXA78MaXT2QHQeg770OdZ6wl9DY7BJIzd9bdo/oJo9PUqf0RugMIuHsvoTvnGDDypjeaYrlo2pXE6VKgQFrfioaI/Jwg4jmrJcn+L8JiIkZ1OhUa0S1AVim9AEhJ2qymCX+3xg8cOSBXsBdE= +Coefficient: xotWVi9P/9Xr1FlKANoKVviBZaoT0xqbrVJLdmSLvyca+OipgxDilaPq+To7nAujkwtH/qdR14CHbkFSjxzzEp3jhOOSeh1HysCDlk5N7dCz2X+FHv977IYeC9vuGPG75Vbz18D7FUEy0huXgq003zJdd0e7djNca9a/GAp3gvc= +Created: 20220902075336 +Publish: 20220902075336 +Activate: 20220902075336 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key new file mode 100644 index 0000000..d4b8efb --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 15002, for example.com. +; Created: 20210423012926 (Fri Apr 23 11:29:26 2021) +; Publish: 20210423012926 (Fri Apr 23 11:29:26 2021) +; Activate: 20210423012926 (Fri Apr 23 11:29:26 2021) +example.com. IN DNSKEY 257 3 8 AwEAAdp+oCXl7vpKA3Mmyndx6/iA+wLrtxeMUiWL7uWJ9ZF24EdS8Dye 63p0lGlyvjvM9T5dTiyEpTAdutEBr79H0MlDqIBqpadrCdJRI2S4kC+0 nq5+Aj2CEyiAamPGujwWeXwtfLAvVPfBqs42PBr6wPQIJOByFYDaZBU3 enUEWgHYy/7OnJDrt0QlswKphR6SvYtyuixiUR8J/WouWXglUY5qlC7Z vVDxs9E4q7B1mfKCyoqcFMKPh9lzEBH+IfUZ543xXEYf2BEztKB1SZ2R QnpYedjATGDcgPis46uA2gHMfvDYJTQ5UqTBtveGb3Wsqc0oRXVPMEoY 3WnWhaKDzkk= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private new file mode 100644 index 0000000..72b8e2e --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 2n6gJeXu+koDcybKd3Hr+ID7Auu3F4xSJYvu5Yn1kXbgR1LwPJ7renSUaXK+O8z1Pl1OLISlMB260QGvv0fQyUOogGqlp2sJ0lEjZLiQL7Sern4CPYITKIBqY8a6PBZ5fC18sC9U98GqzjY8GvrA9Agk4HIVgNpkFTd6dQRaAdjL/s6ckOu3RCWzAqmFHpK9i3K6LGJRHwn9ai5ZeCVRjmqULtm9UPGz0TirsHWZ8oLKipwUwo+H2XMQEf4h9RnnjfFcRh/YETO0oHVJnZFCelh52MBMYNyA+Kzjq4DaAcx+8NglNDlSpMG294ZvdaypzShFdU8wShjdadaFooPOSQ== +PublicExponent: AQAB +PrivateExponent: SD4X64/0DTONonRP+2Biej8DP7r6RcHyo1F6QtDzrg4VJ+AHaLPO/iUvsRHsTk99QwqMv3F4QMmDrHmXR3KSWQmS3Crm7M0aaTzErBfOLMfWs7EcQoQQm5KiGq1phFaWAnXzxTlRKb4SIK6T/wOr6sQKlV+DNqB++Pjn92rh67vLM8kZBUzWI14Vl9N0ib+xOOFH1oYFo7ynDgMfJhpnQSkuRfyQls3aD1eKQsNazRtZ7lFi2S0HR/V0AKYH2AQi7SdL5wH6hYba5cHfpKSw7PebI0lYkUJ4PAg3Xw7DPMkg8O0hkpLICpU8x7MPqQQ74eKDaEY+fjbL0KLL0Dy9UQ== +Prime1: /IDRb7WzMY6wp14LqDORULoUnmiQOqkRjOQnCoEXT2KVpYwPmGMG+GR40hrMFgqqAZFVmi56VBoasWpYbSBEqM4aJv1JVimMPREk23v5i+TY93kxICO/ee9/v0hXgLmrKUkS1Kwu4a1PxLX5U/LAzXPR6zF+EHP9OKFjDRWHqN0= +Prime2: 3YU9QdtsXofjNmlDETRwemKv45pa0oVNPmNvS1vtzIpQ3m/QSuhJxzyTgSP9x1XMiIsg63er3LOCtkRifXVE1IBrfIUgchp8YD5LsyesRl2ielE8Hw8PwSA1YjUVu90yRHcVfbZJ8lm2KyRKHgDWXz94t2Xnm/9M5XjUGuNW7l0= +Exponent1: 7KIkpJYZyvW4ZAFk10sMgiUBMbs4f2D2i509YUC9ga4YJD7wVpVncN1nxS9L19RCopl7KbUo+yxDm8TX/dzhu3j7VVLFqbPiM1Cfw/mZUhszoii3ezFFPpbOl4rKRl66I0TSGvEKNoDfYrBPavby7Rf/wHRveifZRXspgpeMvRk= +Exponent2: yvvtjuxW2CRiopg/+YL40lyd2cy2DpRRnKqW8BHzzGquAbWpwwopmOS8MSjewgqv2irK5pmJJTpku0nciiOsB6EJXVfLzGLSt4o96ZOf+/aPDNBla/xsLkaqRCxqlvPwvOX2DnS8O9PS5qNhOy7/QNYzcrJxUfPV7awTh/Pr040= +Coefficient: PHxU1tqPKTpI/8nABvso0SRerc1m+RPWGRk7s/SVcADSBvEW7fUDcwiZeRfK9MdlwPvLiVozbYnRbgRQl8GuKSqAD1+Cnvn2yOQk81AgNKbuKPwF7UvKIdq/c/xnhj2bvZUVSavJ91ux/RlZNP50378Ks8bj5HJl1xzAMVHXB5o= +Created: 20210423012926 +Publish: 20210423012926 +Activate: 20210423012926 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key new file mode 100644 index 0000000..990b837 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 63613, for example.com. +; Created: 20210423012810 (Fri Apr 23 11:28:10 2021) +; Publish: 20210423012810 (Fri Apr 23 11:28:10 2021) +; Activate: 20210423012810 (Fri Apr 23 11:28:10 2021) +example.com. IN DNSKEY 256 3 8 AwEAAZzun7bYfjmGDwUEn4pyJG34vsiawRMW6pEdoNMH87ozxriOzgG6 /4zTjEv8JyYjGQz2k2vcoWWcD+86xD5IUqfa1pdXXUU8bdhG9DBtW/K1 mc4P6g8heU+0f++mq/L4TPlWVZUG8lVH4H8mD6r8PsVK7v/QR7wMeg9b JpCYyxon2A9rZ4zS0J9kX9bfciQVh6ODGVENctwEK5FNp5u0VonPEIx3 5Kj+IVn/mHpfbz4LaC02s7C6Kgvn3ToFFSJczwbOaexl/d+/ai8FLJi7 8UgiAq5/178bcVLItMeY6aD5eQGkRtr2c3JZ/JR4Nf+TQAWFBnl9NSDa RH4Qa55ZNqs= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private new file mode 100644 index 0000000..1765d3f --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: nO6ftth+OYYPBQSfinIkbfi+yJrBExbqkR2g0wfzujPGuI7OAbr/jNOMS/wnJiMZDPaTa9yhZZwP7zrEPkhSp9rWl1ddRTxt2Eb0MG1b8rWZzg/qDyF5T7R/76ar8vhM+VZVlQbyVUfgfyYPqvw+xUru/9BHvAx6D1smkJjLGifYD2tnjNLQn2Rf1t9yJBWHo4MZUQ1y3AQrkU2nm7RWic8QjHfkqP4hWf+Yel9vPgtoLTazsLoqC+fdOgUVIlzPBs5p7GX9379qLwUsmLvxSCICrn/XvxtxUsi0x5jpoPl5AaRG2vZzcln8lHg1/5NABYUGeX01INpEfhBrnlk2qw== +PublicExponent: AQAB +PrivateExponent: N4egcDzO/V/YdLgcFAsrpNY9/BH2e+DCA7NuMv4/WgX0LV4quyYGQzigDksdNzt4I8Qkiig53BCK+uXahwdkaAzhng/F6zfkzoDc6z3nKUzlLasn8U6w9Gk0VAKwGXuPETNheShKG68hWxyGssQrGfjX9SEoIPxxPHnOfZ/zTj95KAnVV5qPz90xVAb0+FUrLXAt72KuRwepOTlsETsMFDKe17uUCqCCdX98Ko0u14wrO6zGRQtNhUsfvNB/pY8fvbHD1GcCTbFSx4FxsUsZMrNtMsvMe3HN9ggC0Y9htbH9HV0hS0w9SKCUyoeOVwf/JZL4hlfoe8+jglsyJpAgoQ== +Prime1: zeXvO3PT4iXv9GlGeebl39pF1sXs8tXY4B9VHUJGGSYlyOlyCEy4URQJIPfuL6VjFKCErSxUJSrGz0HyQuKr8l9qP/0MGxGRH7wxvUR7YTmai84yyQ4fFENRmn8bzxGwj0MVHIW7cKC59j7nWT24gseT21/NP5m8EnPsjz/K40M= +Prime2: wx5vVFSydUfr8HtOHNS1kRrTjhnQOfjmj8SxGi72Hk+mgi9fBCTC5fRLifd80wGbgyFk1vZOXeStOC8L3IlnBGLX0O9MNip+vVX3hRzIRhLwHhL1ygN3xEd04qwVH0XJ8+4A0XCzh/FJgW59F62geN6gwedo7GmZAOSZUBAyRHk= +Exponent1: IlkqeLuQ7Fgx2I87b5iiXp62Keco6TXdkT4I3/GvagCgKw0utc2+rd/uye4ycQZhKg7BM3aCrxScx/STaq8PykY6nmQjgdyDXkzx60YiYwzOCGakuD+/1YyJb4Gm7PthffTN780rgNV/UGIcDBoszrxmoSExR1vpMRbfruIQgas= +Exponent2: or0Os/KUibc79W6Snv9WlLkgPAQRpViQzNaLtD/47R0Xzrs975HNsMgJ/P+bb86Ga1994MC8ahmh1BuBNCax8nmScWQ1V3QoEzjRYoe4DqIa/aposF4mFWJX/fry/wtRPo+CxSzPwJGh8j86PHaHQmjFAhVFcPE+OP1xVdK8alk= +Coefficient: r5wPmPXUF5pVC0Y7La3jVkL4w/3wvq9LBz91tH9gA8OUNLpDDBuFZISiJdhOZ4JVw+qSSoHcEa+3Phd+BqxmXzwZDU1Fqta9mLDDGCqCWjVQOopeeJgrvkv9P0TIzEuoGmW50cQhyqHYCtuUxjOnHfiQSc53p7rfD4Vom1VQ3Ok= +Created: 20210423012810 +Publish: 20210423012810 +Activate: 20210423012810 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key new file mode 100644 index 0000000..47003a4 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 18240, for example.com. +; Created: 20211221062121 (Tue Dec 21 17:21:21 2021) +; Publish: 20211221062121 (Tue Dec 21 17:21:21 2021) +; Activate: 20211221062121 (Tue Dec 21 17:21:21 2021) +example.com. IN DNSKEY 256 3 10 AwEAAe5GunnuJFyzmKiGUknSQY3aPtR5UR8vNLLyMCJswffRzoYwY14/ 60ZTsqzh7N+lJV3KAOraocFSsTnmWIM7D7DPpqtaJMQw90ypBG0cnUP1 wKX9L/gdOH/ITlluBiZpCv9Aux3FRECHBO4Gx8Rse8ST2Vag3UuOPW+q HkLsWQt22K/hYuDhEtUWWx2dTIaXUVXNSNbk2zPL+lhC9PaRV+//1Fjo UX4qXCUuUN4TiqlkK2v4UkcIyld1n2R7qTQAkoN9amGFtPu8z5Zw7CxC San03yUSNuKub3fGys11gQRFuEHRX7FxKxvJjmcngG9qCh8AyfHZ8zYb VstTy1unFoM= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private new file mode 100644 index 0000000..f16b627 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+18240.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 10 (RSASHA512) +Modulus: 7ka6ee4kXLOYqIZSSdJBjdo+1HlRHy80svIwImzB99HOhjBjXj/rRlOyrOHs36UlXcoA6tqhwVKxOeZYgzsPsM+mq1okxDD3TKkEbRydQ/XApf0v+B04f8hOWW4GJmkK/0C7HcVEQIcE7gbHxGx7xJPZVqDdS449b6oeQuxZC3bYr+Fi4OES1RZbHZ1MhpdRVc1I1uTbM8v6WEL09pFX7//UWOhRfipcJS5Q3hOKqWQra/hSRwjKV3WfZHupNACSg31qYYW0+7zPlnDsLEJJqfTfJRI24q5vd8bKzXWBBEW4QdFfsXErG8mOZyeAb2oKHwDJ8dnzNhtWy1PLW6cWgw== +PublicExponent: AQAB +PrivateExponent: U/ipDv9V4TWJvxpXNZzbbVpUehym8g54y/d97yPU17kgxzmWS0jLaWVluneEOuzAVmUyHZIfHzo9KuJ6nwTZar5DRm/mNR3siR+nZ6yF38VjtxubJB1oI+A7fFjB4hdywLHXP46dlv/+RMQu8pIorAZOubDHTDE8hXW2ZG9WkisJ5P7KoaL4KFHHHXi5vsXAMph4Zphd/zPxVL2tHD3l5c3QXRpQWfTNZNQcZ1f/4yVCuMRibg5LCvpia0ZwRrlygfZdAHUUd0VJDfRO45J5nlIJSAHQtjYtVTL+xNISWOHXovVlInkVyluACqfX94I7qPXTu41yg3SxrrtHE6RTwQ== +Prime1: +/YsRxmUxgvHKUh4SxdjzqNDDEi8b2BtM5IpctjVG3oYsL6J9xJB3U5/lbrGEPgl/1ndBUSXMQ6zQ5WcDE1qBAdW8t0eyniyuiexcgQ9f04Ds7p7oUiSHGLRn8YqQOzmiASXoZmkzfJZ+42pGhT3RZ+aYKtWQGMHqXabwV3zZl0= +Prime2: 8hhnKzPzExy6wv/MV0aYKo1g4azrRjug6743/ctTC7zjnMmDW7RMFTXmq5Tu3pFaIL4N4C4m1b7P3abfTrjm+DwHnrlRIvLWS3zJnvUEM22i4BwqqTLRiJpoT5Bfp4pVsdOPT7Iyx1q5UsJZ7Q4qMpg2TFpGiQyieRB5Xwpu4l8= +Exponent1: ZFPx7Z3SD8pA0793pu75Xx7DY/DSl8bdtNtOhdyxfu9vRXGZnjg24diQFR76H2ewOa2exKo7Sd2ApDi+mmd4/4Gsrag+yoClKlsD3VKy6i42ayqmb+Jly8fNkMFnsdKjOSYa+s4jQZ5vFiuiWjBfBeo3nqabAahtNJ12B9lRQkE= +Exponent2: tNz4TnVsFo4zFLVHsrghvECM7WxjBMBNc3FToT6CV1WRcjO1+A/Ve08eenc0kYBjpex2r1GrX6pC3uPpFoXav/8Q7kqiTArBf/nFIwUHU2iH8wf38xntIjHA1hgU7jTR2p0kBrUpbHfh1esuhYQ8kDnY7ufOpFqVEv70vcUsm98= +Coefficient: 3acDCJ9jCnHAP1km7jRO388mOpiI8U6SMv0PBD8l2UoB4CYwujrFxy6PhgUa486bbm5xZEaOwhYZcbw/g1qyC6Qt5kYOb2fVWOob/lEQmyqbDvHMQWTJoIbqaDTKQN/szI4xVdb/xZ6QR4Bq7JgbJpUACgweS540Y7Lf8Dry8C0= +Created: 20211221062121 +Publish: 20211221062121 +Activate: 20211221062121 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key new file mode 100644 index 0000000..37bd259 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 28633, for example.com. +; Created: 20211221062130 (Tue Dec 21 17:21:30 2021) +; Publish: 20211221062130 (Tue Dec 21 17:21:30 2021) +; Activate: 20211221062130 (Tue Dec 21 17:21:30 2021) +example.com. IN DNSKEY 257 3 10 AwEAAc4lt8fDsdCzMCLHxXm8Ok/dw6XDiqx06Rf47LTeLmo6b64xm1Fs 0zloNMrcZDgwS5IxjQ3Breqc5aEc+jehueqCXa/fJXMdIt1VpUG0H7GP 4B+1IVmEiziHfmOozktdkuAyLqcsNhsf+J1+bCoHJSffgz6KbjBks/jR 12uyUnZCDrKGE/KfiR0gpT3watqGqqChO0KXq2N2PsnYfyRDea5FMUjM oPgOOyAT8LIMsM8x4f+EbU6m9Zc3Esafek9iLCS9R1333Pm1EEh5ghQT BsZ7omc5aSvrKUaIneojU3RdofceZouCliIDXmqscfY0y6bivGcmCQI/ LM4XUh7GWlM= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private new file mode 100644 index 0000000..6d7f72e --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+010+28633.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 10 (RSASHA512) +Modulus: ziW3x8Ox0LMwIsfFebw6T93DpcOKrHTpF/jstN4uajpvrjGbUWzTOWg0ytxkODBLkjGNDcGt6pzloRz6N6G56oJdr98lcx0i3VWlQbQfsY/gH7UhWYSLOId+Y6jOS12S4DIupyw2Gx/4nX5sKgclJ9+DPopuMGSz+NHXa7JSdkIOsoYT8p+JHSClPfBq2oaqoKE7QperY3Y+ydh/JEN5rkUxSMyg+A47IBPwsgywzzHh/4RtTqb1lzcSxp96T2IsJL1HXffc+bUQSHmCFBMGxnuiZzlpK+spRoid6iNTdF2h9x5mi4KWIgNeaqxx9jTLpuK8ZyYJAj8szhdSHsZaUw== +PublicExponent: AQAB +PrivateExponent: Wr3fl99cdjFqDuVA18UzJdTIOj9I24Da2eKIz1S9uaTfZB4R8FWm5K4qDuHUe6dGnKOTI2sN0ygdLD5FJhfabo/UDYZ8RZ+dqS/5/mH7UX2zekGQ3Iargcaiq9uycxpNfMKaJpwfdPEtzqXHlvhuMo8AhpcIyeSKFAzKdm2YPtUqIrum4RARHyfRLfLyWlkIotPdyiaKCVGQxiRbFsTcmIB2Bizmt7zRjlB+Hxf8MooXmaKUFRQtMCLnFGK0ecFI1CWAxmLSanvYVKQ0HxcFkFKzRiZAz1au7ZfMgYDZj0jF72WAGU3Edcmdc0QIQRTWjb/3wcBfwlr9s6lKoF3ngQ== +Prime1: 1EIziKhz7dF41rb/hckdr2qeY8eM7tLrT5jIMPLISHCCuKm5IK2u7PY6m6NjMdhx1ilm7K2RGTt+TTFZaqDIEd8qpzRCxAGcfTVOmB9iHwmi9i9RoPSlY6o+iShft68ZnvPiGJWUF2huRYVK2F0cIWErwSqaBGsFd79mXmlkn98= +Prime2: +KEdNtZj9JyCCR2xbLAw3tnAYxHvJ3skVMjxV3cyUupMWi12NWxGhHH1nnetXxDR2LBBuqIl4pE/4MeXe3sClMHTL3Z9XG+pzQAsHS7yvsfZERdyuWZYYy0ya/7XY2auvRVO6LxN7d47VWjYxAGfoCsbCEivgDxmt1dTZhAtRA0= +Exponent1: d5TcZ69PsLoEtCLhDkRh/wO4PEqeMaaOf4d5sWn2QCly3Apyi+CN3l5SYoDIT7q7V4Z3v/uA9ZA49dBJqfLvBHKQGycsPjUSLtAreTSlGQtazguWl3F9BAtTs/4U/u0dKBoKVQNgLVfeWDhiFEdQo9WUyvzvTHHm4LHqQGJsGE0= +Exponent2: EU2dK+DVygNOZXYEkAzfCdNbuUlZPIUsbR4i9bRc8zpNIAWD8YncioEn1+R6U2BnSk5R9LwuKMt1B568YyKXdmTa3rW/WbyHs7WsXEeVK0PbTn40RMTjp9tQZAWzVb6isJQYDsh0H/bUaEhItbNrOYlmczgjxqftehsAudysWc0= +Coefficient: sl2u/8vttxpiTbspGV4SsaDmKUNdzQH7BgJ5rl3mXPp/aUpLw0Sr7FuARy8W8tq3yVNi9qCOnvGwVl6aQzZP7b8N04KiH8gewlAVdSfxG24yFKJIQNbWGKFZYZFYyjtLVlpK6NYF0f0I1KpAjn58XR0qIBvRFZYWBAkggU9C7ro= +Created: 20211221062130 +Publish: 20211221062130 +Activate: 20211221062130 diff --git a/bin/tests/system/dnssec/signer/general/bogus-ksk.key b/bin/tests/system/dnssec/signer/general/bogus-ksk.key new file mode 100644 index 0000000..e468574 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/bogus-ksk.key @@ -0,0 +1,6 @@ +; +; This is a bogus key. It will not have a .private file. +; +; This will be key id 23221 +; +example.com. IN DNSKEY 257 3 10 AwEAAbcyptpM++pVjhpYQW2fVtyOw04IBSw4X0SYi/Ke4wVkmDNW2vBm AFkgiVVKmmNbb0IHDYQiIY7seXk0fjEwjzeY2bmeOAZxDdv2KT9VQpoY Matk2y4NTi6F/V04x0lL/CBvyifTeNbZKvY+S1eKFuWHeS5Ss8tiagz9 zdYWUe/msvmin+Hbs2tlLwXVl4hOmABCL9uK9H8R6GPL5VdEXYyFOh/v 71CNhRU5ufrARti69YYkfzH6NpWhlJWyJvDjqAdt2L3H8V71C2vcXbBu S5NscEYl+8JQfwUvOTN553I5IQrG+NQEusW36UM/Rkad8mMnUVM9Vzqk GH86GHKtLMc= diff --git a/bin/tests/system/dnssec/signer/general/bogus-zsk.key b/bin/tests/system/dnssec/signer/general/bogus-zsk.key new file mode 100644 index 0000000..aa45938 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/bogus-zsk.key @@ -0,0 +1,6 @@ +; +; This is a bogus key. It will not have a .private file. +; +; This will be key id 48930 +; +example.com. IN DNSKEY 256 3 10 AwEAAa/0IcnbGutPVkrz04tw5ZIYx6rU+FprB2rlKS8cTK/wiBOqbOC6 QIDdegDpZG1fOdj04ZQGa3pIizqC2CnlIWfxpfR6W+qSLRBuQ8gmwTmS c/Jy/0vAGB3fv3oVIqKslLNqIXZb3CKNiA2kGcut3aUgfeOW970Jga6z PAGKqPpPZTelW1Qy9N5BO4cRTuYo4uvbZveJv1W/2n5RN+UaeqU0f+AE DP0+wqSWNUfZsi6HygLwk08x3eO8PzTBlqBlAMfvNAygrmXqccMREyyH KEc5dVJ1qOXfj8BAdJUPmunyJhIwC9PxzOW7mn1lW7mZO2D5U/Jaxw2k eX2KblmVk8s= diff --git a/bin/tests/system/dnssec/signer/general/test1.zone b/bin/tests/system/dnssec/signer/general/test1.zone new file mode 100644 index 0000000..98c9f02 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test1.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+18240.key +$include Kexample.com.+010+28633.key diff --git a/bin/tests/system/dnssec/signer/general/test10.zone b/bin/tests/system/dnssec/signer/general/test10.zone new file mode 100644 index 0000000..10a8bc9 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test10.zone @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00100000 1200 3600 604800 300 +extra.example.com. IN A 1.2.3.4 +$include Kexample.com.+008+63613.key +$include Kexample.com.+008+15002.key diff --git a/bin/tests/system/dnssec/signer/general/test11.zone b/bin/tests/system/dnssec/signer/general/test11.zone new file mode 100644 index 0000000..538305f --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test11.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+005+19857.key +$include Kexample.com.+005+45884.key diff --git a/bin/tests/system/dnssec/signer/general/test12.zone b/bin/tests/system/dnssec/signer/general/test12.zone new file mode 100644 index 0000000..4e4c9ba --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test12.zone @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 30 ; 30 seconds +. IN SOA a.root.servers.nil. each.isc.org. ( + 2000042101 ; serial + 600 ; refresh (10 minutes) + 600 ; retry (10 minutes) + 1200 ; expire (20 minutes) + 600 ; minimum (10 minutes) + ) + NS a.root-servers.nil. + DNSKEY 256 3 13 ( + TFelYtTRBWeA9A307vvuWIcaNwW4txW4RgSELtsi46ZQ + s24ncRxmxtFfuJuPyVXePNiE4HNI9CIowGUsn5WuBw== + ) ; ZSK; alg = ECDSAP256SHA256 ; key id = 23768 + DNSKEY 257 3 13 ( + OSmhpULEDCUzHCBeDU5uJXzkCcGuW2qrkQznKRPGhRZN + j7ZUIGInGzM5Um5m02ULWt8tKbi55NJUeifKWegQ0g== + ) ; KSK; alg = ECDSAP256SHA256 ; key id = 22255 + DNSKEY 385 3 13 ( + uKwpRtMH+9iuUk/Xj6LciIP5ZckaBtXaUqxUxzJYexXj + vxGZGX4470Jvhq2NCI3HBZQNaCCP/h9sluhIzRGPTA== + ) ; revoked KSK; alg = ECDSAP256SHA256 ; key id = 23768 +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/dnssec/signer/general/test2.zone b/bin/tests/system/dnssec/signer/general/test2.zone new file mode 100644 index 0000000..97c0d3d --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test2.zone @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has one non-KSK DNSKEY record for which the +; private key file exists. It should be loaded automatically and the zone +; correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+18240.key diff --git a/bin/tests/system/dnssec/signer/general/test3.zone b/bin/tests/system/dnssec/signer/general/test3.zone new file mode 100644 index 0000000..bf9bc66 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test3.zone @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has one KSK DNSKEY record for which the +; private key file exists. It should be loaded automatically. As there +; is no non-KSK DNSKEY the resulting zone should be rejected. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+28633.key diff --git a/bin/tests/system/dnssec/signer/general/test4.zone b/bin/tests/system/dnssec/signer/general/test4.zone new file mode 100644 index 0000000..9f05de5 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test4.zone @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has three DNSKEY records, two (KSK + ZSK) of +; which have existing private key files available. The third is a +; pre-published ZSK. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+18240.key +$include Kexample.com.+010+28633.key +$include bogus-zsk.key diff --git a/bin/tests/system/dnssec/signer/general/test5.zone b/bin/tests/system/dnssec/signer/general/test5.zone new file mode 100644 index 0000000..d61504f --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test5.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has three DNSKEY records, two (KSK +ZSK) of which +; have existing private key files available. The third is a KSK. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+18240.key +$include Kexample.com.+010+28633.key +$include bogus-ksk.key diff --git a/bin/tests/system/dnssec/signer/general/test6.zone b/bin/tests/system/dnssec/signer/general/test6.zone new file mode 100644 index 0000000..fcfb1ec --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test6.zone @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has four DNSKEY records, two (KK + ZSK) of which +; have existing private key files available. There are also a KSK and ZSK +; for which there will be no signatures. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+18240.key +$include Kexample.com.+010+28633.key +$include bogus-ksk.key +$include bogus-zsk.key diff --git a/bin/tests/system/dnssec/signer/general/test7.zone b/bin/tests/system/dnssec/signer/general/test7.zone new file mode 100644 index 0000000..e52c535 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test7.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, none of which have +; existing private key files available. The resulting zone should fail +; the consistency tests. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include bogus-ksk.key +$include bogus-zsk.key diff --git a/bin/tests/system/dnssec/signer/general/test8.zone b/bin/tests/system/dnssec/signer/general/test8.zone new file mode 100644 index 0000000..893d32d --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test8.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, one of which, +; the KSK, has a private key. The resulting zone should be rejected as +; it has no ZSK signatures. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+010+28633.key +$include bogus-zsk.key diff --git a/bin/tests/system/dnssec/signer/general/test9.zone b/bin/tests/system/dnssec/signer/general/test9.zone new file mode 100644 index 0000000..14c47d0 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test9.zone @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+008+63613.key +$include Kexample.com.+008+15002.key diff --git a/bin/tests/system/dnssec/signer/prepub.db.in b/bin/tests/system/dnssec/signer/prepub.db.in new file mode 100644 index 0000000..946aac1 --- /dev/null +++ b/bin/tests/system/dnssec/signer/prepub.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +prepub. 60 IN SOA prepub. . 0 0 0 0 0 +prepub. 60 IN NS prepub. +prepub. 60 IN A 1.2.3.4 +; out of zone record +out-of-zone. 60 IN A 1.2.3.4 diff --git a/bin/tests/system/dnssec/signer/remove.db.in b/bin/tests/system/dnssec/signer/remove.db.in new file mode 100644 index 0000000..5629a42 --- /dev/null +++ b/bin/tests/system/dnssec/signer/remove.db.in @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +remove. 60 IN SOA remove. . 0 0 0 0 0 +remove. 60 IN NS remove. +remove. 60 IN A 1.2.3.4 +remove. 60 IN AAAA ::ffff:1.2.3.4 +remove. 60 IN MX 0 remove. +$INCLUDE remove.db.signed diff --git a/bin/tests/system/dnssec/signer/remove2.db.in b/bin/tests/system/dnssec/signer/remove2.db.in new file mode 100644 index 0000000..b2962b9 --- /dev/null +++ b/bin/tests/system/dnssec/signer/remove2.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +remove. 60 IN SOA remove. . 0 0 0 0 0 +remove. 60 IN NS remove. +remove. 60 IN A 1.2.3.4 +$INCLUDE remove.db.signed diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh new file mode 100644 index 0000000..a365a20 --- /dev/null +++ b/bin/tests/system/dnssec/tests.sh @@ -0,0 +1,4707 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +status=0 +n=1 + +rm -f dig.out.* + +dig_with_opts() { + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" +} + +dig_with_additionalopts() { + "$DIG" +noall +additional +dnssec -p "$PORT" "$@" +} + +dig_with_answeropts() { + "$DIG" +noall +answer +dnssec -p "$PORT" "$@" +} + +delv_with_opts() { + "$DELV" -a ns1/trusted.conf -p "$PORT" "$@" +} + +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +# TODO: Move loadkeys_on to conf.sh.common +dnssec_loadkeys_on() { + nsidx=$1 + zone=$2 + nextpart ns${nsidx}/named.run >/dev/null + rndccmd 10.53.0.${nsidx} loadkeys ${zone} | sed "s/^/ns${nsidx} /" | cat_i + wait_for_log 20 "next key event" ns${nsidx}/named.run || return 1 +} + +# convert private-type records to readable form +showprivate() { + echo "-- $* --" + dig_with_opts +nodnssec +short "@$2" -t type65534 "$1" | cut -f3 -d' ' \ + | while read -r record; do + # shellcheck disable=SC2016 + $PERL -e 'my $rdata = pack("H*", @ARGV[0]); + die "invalid record" unless length($rdata) == 5; + my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata); + my $action = "signing"; + $action = "removing" if $remove; + my $state = " (incomplete)"; + $state = " (complete)" if $complete; + print ("$action: alg: $alg, key: $key$state\n");' "$record" + done +} + +# check that signing records are marked as complete +checkprivate() { + for i in 1 2 3 4 5 6 7 8 9 10; do + showprivate "$@" | grep -q incomplete || return 0 + sleep 1 + done + echo_d "$1 signing incomplete" + return 1 +} + +# check that a zone file is raw format, version 0 +israw0() { + # shellcheck disable=SC2016 + $PERL <"$1" -e 'binmode STDIN; + read(STDIN, $input, 8); + ($style, $version) = unpack("NN", $input); + exit 1 if ($style != 2 || $version != 0);' || return $? +} + +# check that a zone file is raw format, version 1 +israw1() { + # shellcheck disable=SC2016 + $PERL <"$1" -e 'binmode STDIN; + read(STDIN, $input, 8); + ($style, $version) = unpack("NN", $input); + exit 1 if ($style != 2 || $version != 1);' || return $? +} + +# strip NS and RRSIG NS from input +stripns() { + awk '($4 == "NS") || ($4 == "RRSIG" && $5 == "NS") { next} { print }' "$1" +} + +# +# Ensure there is not multiple consecutive blank lines. +# Ensure there is a blank line before "Start view" and +# "Negative trust anchors:". +# Ensure there is not a blank line before "Secure roots:". +# +check_secroots_layout() { + awk '$0 == "" { if (empty) exit(1); empty=1; next } + /Start view/ { if (!empty) exit(1) } + /Secure roots:/ { if (empty) exit(1) } + /Negative trust anchors:/ { if (!empty) exit(1) } + { empty=0 }' $1 || return $? +} + +# Check that for a query against a validating resolver where the +# authoritative zone is unsigned (insecure delegation), glue is returned +# in the additional section +echo_i "checking that additional glue is returned for unsigned delegation ($n)" +ret=0 +$DIG +tcp +dnssec -p "$PORT" a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ns\\.insecure\\.example\\..*A.10\\.53\\.0\\.3" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check the example. domain + +echo_i "checking that zone transfer worked ($n)" +for i in 1 2 3 4 5 6 7 8 9; do + ret=0 + dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 + dig_with_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 + $PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +digcomp dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# test AD bit: +# - dig +adflag asks for authentication (ad in response) +echo_i "checking AD bit asking for validation ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# test AD bit: +# - dig +noadflag +echo_i "checking that AD is not set without +adflag or +dnssec ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking for AD in authoritative answer ($n)" +ret=0 +dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation NSEC ($n)" +ret=0 +dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking recovery from stripped DNSKEY RRSIG ($n)" +ret=0 +# prime cache with DNSKEY without RRSIGs +dig_with_opts +noauth +cd dnskey-rrsigs-stripped. @10.53.0.4 dnskey >dig.out.prime.ns4.test$n || ret=1 +grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "RRSIG.DNSKEY" dig.out.prime.ns4.test$n >/dev/null && ret=1 +# reload server with properly signed zone +cp ns2/dnskey-rrsigs-stripped.db.next ns2/dnskey-rrsigs-stripped.db.signed +nextpart ns2/named.run >/dev/null +rndccmd 10.53.0.2 reload dnskey-rrsigs-stripped | sed 's/^/ns2 /' | cat_i +wait_for_log 5 "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 +dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking recovery from stripped DS RRSIG ($n)" +ret=0 +# prime cache with DS without RRSIGs +dig_with_opts +noauth +cd child.ds-rrsigs-stripped. @10.53.0.4 ds >dig.out.prime.ns4.test$n || ret=1 +grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "RRSIG.DS" dig.out.prime.ns4.test$n >/dev/null && ret=1 +# reload server with properly signed zone +cp ns2/ds-rrsigs-stripped.db.next ns2/ds-rrsigs-stripped.db.signed +nextpart ns2/named.run >/dev/null +rndccmd 10.53.0.2 reload ds-rrsigs-stripped | sed 's/^/ns2 /' | cat_i +wait_for_log 5 "zone ds-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 +dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that 'example/DS' from the referral was used in previous validation ($n)" +ret=0 +grep "query 'example/DS/IN' approved" ns1/named.run >/dev/null && ret=1 +grep "fetch: example/DS" ns4/named.run >/dev/null && ret=1 +grep "validating example/DS: starting" ns4/named.run >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive validation NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.example >delv.out$n || ret=1 + grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + ret=0 + echo_i "checking positive validation NSEC using dns_client (trusted-keys) ($n)" + "$DELV" -a ns1/trusted.keys -p "$PORT" @10.53.0.4 a a.example >delv.out$n || ret=1 + grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking positive validation NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive validation NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1 + grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking positive validation OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +SP="[[:space:]]+" + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive validation OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.optout.example >delv.out$n || ret=1 + grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""A""$SP""10.0.0.1" delv.out$n || ret=1 + grep -Eq "^a\\.optout\\.example\\.""$SP""[0-9]+""$SP""IN""$SP""RRSIG""$SP""A""$SP""$DEFAULT_ALGORITHM_NUMBER""$SP""3""$SP""300" delv.out$n || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking positive wildcard validation NSEC ($n)" +ret=0 +dig_with_opts a.wild.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts a.wild.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n +stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n +digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 +grep "\\*\\.wild\\.example\\..*RRSIG NSEC" dig.out.ns4.test$n >/dev/null || ret=1 +grep "\\*\\.wild\\.example\\..*NSEC z\\.example" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive wildcard validation NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.wild.example >delv.out$n || ret=1 + grep "a.wild.example..*10.0.0.27" delv.out$n >/dev/null || ret=1 + grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 300.*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking positive wildcard answer NSEC3 ($n)" +ret=0 +dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +grep "AUTHORITY: 4," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive wildcard answer NSEC3 ($n)" +ret=0 +dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +grep "AUTHORITY: 4," dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive wildcard validation NSEC3 ($n)" +ret=0 +dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n +stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n +digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.wild.nsec3.example >delv.out$n || ret=1 + grep -E "a.wild.nsec3.example..*10.0.0.6" delv.out$n >/dev/null || ret=1 + grep -E "a.wild.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking positive wildcard validation OPTOUT ($n)" +ret=0 +dig_with_opts a.wild.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts a.wild.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n +stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n +digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.wild.optout.example >delv.out$n || ret=1 + grep "a.wild.optout.example..*10.0.0.6" delv.out$n >/dev/null || ret=1 + grep "a.wild.optout.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative validation NXDOMAIN NSEC ($n)" +ret=0 +dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking RRSIG covered type in negative cache entry ($n)" +ret=0 +rndc_dumpdb ns4 +grep -F '; example. RRSIG NSEC ...' ns4/named_dump.db.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" +ret=0 +dig_with_opts +noauth q.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth q.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.nsec3.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative validation NXDOMAIN OPTOUT ($n)" +ret=0 +dig_with_opts +noauth q.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth q.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.optout.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative validation NODATA NSEC ($n)" +ret=0 +dig_with_opts +noauth a.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth a.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 txt a.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative validation NODATA NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 txt a.nsec3.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative validation NODATA OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 txt a.optout.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative wildcard validation NSEC ($n)" +ret=0 +dig_with_opts b.wild.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +dig_with_opts b.wild.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative wildcard validation NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 txt b.wild.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative wildcard validation NSEC3 ($n)" +ret=0 +dig_with_opts b.wild.nsec3.example. @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +dig_with_opts b.wild.nsec3.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 txt b.wild.nsec3.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking negative wildcard validation OPTOUT ($n)" +ret=0 +dig_with_opts b.wild.optout.example. \ + @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +dig_with_opts b.wild.optout.example. \ + @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 txt b.optout.nsec3.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxrrset" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +# Check the insecure.example domain + +echo_i "checking 1-server insecurity proof NSEC ($n)" +ret=0 +dig_with_opts +noauth a.insecure.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.insecure.example >delv.out$n || ret=1 + grep "a.insecure.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server insecurity proof NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.insecure.nsec3.example >delv.out$n || ret=1 + grep "a.insecure.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server insecurity proof OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.insecure.optout.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.insecure.optout.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 a a.insecure.optout.example >delv.out$n || ret=1 + grep "a.insecure.optout.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server negative insecurity proof NSEC ($n)" +ret=0 +dig_with_opts q.insecure.example. a @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts q.insecure.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.insecure.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server negative insecurity proof NSEC3 ($n)" +ret=0 +dig_with_opts q.insecure.nsec3.example. a @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts q.insecure.nsec3.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.insecure.nsec3.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server negative insecurity proof OPTOUT ($n)" +ret=0 +dig_with_opts q.insecure.optout.example. a @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts q.insecure.optout.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)" + delv_with_opts @10.53.0.4 a q.insecure.optout.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: ncache nxdomain" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)" +ret=0 +dig_with_opts r.insecure.example. soa @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts r.insecure.example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)" +ret=0 +dig_with_opts r.insecure.nsec3.example. soa @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts r.insecure.nsec3.example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)" +ret=0 +dig_with_opts r.insecure.optout.example. soa @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +dig_with_opts r.insecure.optout.example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check the secure.example domain + +echo_i "checking multi-stage positive validation NSEC/NSEC ($n)" +ret=0 +dig_with_opts +noauth a.secure.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.secure.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking mixed-case positive validation ($n)" +ret=0 +for type in a txt aaaa loc; do + dig_with_opts +noauth mixedcase.secure.example. \ + @10.53.0.3 $type >dig.out.$type.ns3.test$n || ret=1 + dig_with_opts +noauth mixedcase.secure.example. \ + @10.53.0.4 $type >dig.out.$type.ns4.test$n || ret=1 + digcomp --lc dig.out.$type.ns3.test$n dig.out.$type.ns4.test$n || ret=1 + grep "status: NOERROR" dig.out.$type.ns4.test$n >/dev/null || ret=1 + grep "flags:.*ad.*QUERY" dig.out.$type.ns4.test$n >/dev/null || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)" +ret=0 +dig_with_opts +noauth a.secure.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.secure.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)" +ret=0 +dig_with_opts +noauth a.secure.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.secure.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking empty NODATA OPTOUT ($n)" +ret=0 +dig_with_opts +noauth empty.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth empty.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check the bogus domain + +echo_i "checking failed validation ($n)" +ret=0 +dig_with_opts a.bogus.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking failed validation using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 a a.bogus.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: RRSIG failed to verify" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +# Try validating with a bad trusted key. +# This should fail. + +echo_i "checking that validation fails with a misconfigured trusted key ($n)" +ret=0 +dig_with_opts example. soa @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that negative validation fails with a misconfigured trusted key ($n)" +ret=0 +dig_with_opts example. ptr @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that insecurity proofs fail with a misconfigured trusted key ($n)" +ret=0 +dig_with_opts a.insecure.example. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation fails when key record is missing ($n)" +ret=0 +dig_with_opts a.b.keyless.example. a @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking that validation fails when key record is missing using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 a a.b.keyless.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: insecurity proof failed" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "checking that validation succeeds when a revoked key is encountered ($n)" +ret=0 +dig_with_opts revkey.example soa @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags: .* ad" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +if [ -x "${DELV}" ]; then + ret=0 + echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 soa revkey.example >delv.out$n 2>&1 || ret=1 + grep "fully validated" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi + +echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)" +ret=0 +#prime +dig_with_opts +cd bad-cname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1 +#check: requery with +CD. pending data should be returned even if it's bogus +expect="a.example. +10.0.0.1" +ans=$(dig_with_opts +cd +nodnssec +short bad-cname.example. @10.53.0.4) || ret=1 +test "$ans" = "$expect" || ret=1 +test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'" +#check: requery without +CD. bogus cached data should be rejected. +dig_with_opts +nodnssec bad-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "Checking that a bad DNAME signature is caught after a +CD query ($n)" +ret=0 +#prime +dig_with_opts +cd a.bad-dname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1 +#check: requery with +CD. pending data should be returned even if it's bogus +expect="example. +a.example. +10.0.0.1" +ans=$(dig_with_opts +cd +nodnssec +short a.bad-dname.example. @10.53.0.4) || ret=1 +test "$ans" = "$expect" || ret=1 +test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'" +#check: requery without +CD. bogus cached data should be rejected. +dig_with_opts +nodnssec a.bad-dname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check the insecure.secure.example domain (insecurity proof) + +echo_i "checking 2-server insecurity proof ($n)" +ret=0 +dig_with_opts +noauth a.insecure.secure.example. @10.53.0.2 a \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth a.insecure.secure.example. @10.53.0.4 a \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check a negative response in insecure.secure.example + +echo_i "checking 2-server insecurity proof with a negative answer ($n)" +ret=0 +dig_with_opts q.insecure.secure.example. @10.53.0.2 a >dig.out.ns2.test$n \ + || ret=1 +dig_with_opts q.insecure.secure.example. @10.53.0.4 a >dig.out.ns4.test$n \ + || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking 2-server insecurity proof with a negative answer and SOA hack ($n)" +ret=0 +dig_with_opts r.insecure.secure.example. @10.53.0.2 soa >dig.out.ns2.test$n \ + || ret=1 +dig_with_opts r.insecure.secure.example. @10.53.0.4 soa >dig.out.ns4.test$n \ + || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check that the query for a security root is successful and has ad set + +echo_i "checking security root query ($n)" +ret=0 +dig_with_opts . @10.53.0.4 key >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check that the setting the cd bit works + +echo_i "checking cd bit on a positive answer ($n)" +ret=0 +dig_with_opts +noauth example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +dig_with_opts +noauth +cdflag example. soa @10.53.0.5 \ + >dig.out.ns5.test$n || ret=1 +digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking cd bit on a negative answer ($n)" +ret=0 +dig_with_opts q.example. soa @10.53.0.4 >dig.out.ns4.test$n || ret=1 +dig_with_opts +cdflag q.example. soa @10.53.0.5 >dig.out.ns5.test$n || ret=1 +digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking insecurity proof works using negative cache ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +dig_with_opts +cd @10.53.0.4 insecure.example. ds >dig.out.ns4.test$n.1 || ret=1 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18; do + dig_with_opts @10.53.0.4 nonexistent.insecure.example. >dig.out.ns4.test$n.2 || ret=1 + if grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null; then + break + fi + sleep 1 +done +grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Should work with FIPS mode as we are only validating +echo_i "checking positive validation RSASHA1 NSEC ($n)" +ret=0 +if $FEATURETEST --rsasha1; then + dig_with_opts +noauth a.rsasha1.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 + dig_with_opts +noauth a.rsasha1.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 + digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 + grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +else + echo_i "skip: RSASHA1 not supported by OS" +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Should work with FIPS mode as we are only validating +echo_i "checking positive validation RSASHA1 (1024 bits) NSEC ($n)" +ret=0 +if $FEATURETEST --rsasha1; then + dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 + dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 + digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 + grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +else + echo_i "skip: RSASHA1 not supported by OS" +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation RSASHA256 NSEC ($n)" +ret=0 +dig_with_opts +noauth a.rsasha256.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.rsasha256.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation RSASHA512 NSEC ($n)" +ret=0 +dig_with_opts +noauth a.rsasha512.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.rsasha512.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation with KSK-only DNSKEY signature ($n)" +ret=0 +dig_with_opts +noauth a.kskonly.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.kskonly.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking cd bit on a query that should fail ($n)" +ret=0 +dig_with_opts a.bogus.example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +dig_with_opts +cdflag a.bogus.example. soa @10.53.0.5 \ + >dig.out.ns5.test$n || ret=1 +digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking cd bit on an insecurity proof ($n)" +ret=0 +dig_with_opts +noauth a.insecure.example. soa @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +dig_with_opts +noauth +cdflag a.insecure.example. soa @10.53.0.5 \ + >dig.out.ns5.test$n || ret=1 +digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - these are looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking cd bit on a negative insecurity proof ($n)" +ret=0 +dig_with_opts q.insecure.example. a @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +dig_with_opts +cdflag q.insecure.example. a @10.53.0.5 \ + >dig.out.ns5.test$n || ret=1 +digcomp dig.out.ns4.test$n dig.out.ns5.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +# Note - these are looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation of an ANY query works ($n)" +ret=0 +dig_with_opts +noauth foo.example. any @10.53.0.2 >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth foo.example. any @10.53.0.4 >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# 2 records in the zone, 1 NXT, 3 SIGs +grep "ANSWER: 6" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation of a query returning a CNAME works ($n)" +ret=0 +dig_with_opts +noauth cname1.example. txt @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth cname1.example. txt @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# the CNAME & its sig, the TXT and its SIG +grep "ANSWER: 4" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation of a query returning a DNAME works ($n)" +ret=0 +dig_with_opts +noauth foo.dname1.example. txt @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth foo.dname1.example. txt @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME. +# It would be nice to test that the CNAME is being synthesized by the +# recursive server and not cached, but I don't know how. +grep "ANSWER: 5" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation of an ANY query returning a CNAME works ($n)" +ret=0 +dig_with_opts +noauth cname2.example. any @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth cname2.example. any @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +# The CNAME, NXT, and their SIGs +grep "ANSWER: 4" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that validation of an ANY query returning a DNAME works ($n)" +ret=0 +dig_with_opts +noauth foo.dname2.example. any @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth foo.dname2.example. any @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that lookups succeed after disabling an algorithm ($n)" +ret=0 +dig_with_opts +noauth example. SOA @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth example. SOA @10.53.0.6 \ + >dig.out.ns6.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1 +# Note - this is looking for failure, hence the && +grep "flags:.*ad.*QUERY" dig.out.ns6.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking a non-cachable NODATA works ($n)" +ret=0 +dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.7 \ + >dig.out.ns7.test$n || ret=1 +grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1 +dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking a non-cachable NXDOMAIN works ($n)" +ret=0 +dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.7 \ + >dig.out.ns7.test$n || ret=1 +grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1 +dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.4 \ + >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that we can load a rfc2535 signed zone ($n)" +ret=0 +dig_with_opts rfc2535.example. SOA @10.53.0.2 \ + >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that we can transfer a rfc2535 signed zone ($n)" +ret=0 +dig_with_opts rfc2535.example. SOA @10.53.0.3 \ + >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "basic dnssec-signzone checks:" +echo_ic "two DNSKEYs ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test1.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "two DNSKEYs, DNSKEY RRset only by KSK ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -s now-1mo -e now+2d -P -x -f signed.zone -O full -o example.com. test1.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "two DNSKEYs, DNSKEY RRset only by KSK, private key missing ($n)" +ret=0 +( + cd signer/general || exit 1 + cp signed.zone signed.expect + grep "example\.com\..*3600.*IN.*RRSIG.*DNSKEY.*10.*2.*3600.*28633.*example\.com\." signed.expect >dnskey.expect || exit 1 + mv Kexample.com.+010+28633.private Kexample.com.+010+28633.offline + $SIGNER -P -x -f signed.zone -O full -o example.com. signed.zone >signer.out.$n + mv Kexample.com.+010+28633.offline Kexample.com.+010+28633.private + grep "$(cat dnskey.expect)" signed.zone >/dev/null || exit 1 +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "one non-KSK DNSKEY ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test2.zone >signer.out.$n + test -f signed.zone +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "one KSK DNSKEY ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test3.zone >signer.out.$n + test -f signed.zone +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "three DNSKEY ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test4.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "three DNSKEY, one private key missing ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test5.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "four DNSKEY ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test6.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "two DNSKEY, both private keys missing ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test7.zone >signer.out.$n + test -f signed.zone +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "two DNSKEY, one private key missing ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -f signed.zone -o example.com. test8.zone >signer.out.$n + test -f signed.zone +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "check that 'dnssec-signzone -F' works with allowed algorithm ($n)" +ret=0 +if $FEATURETEST --fips-provider; then + ( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -F -f signed.zone -o example.com. test1.zone >signer.out.$n + test -f signed.zone + ) || ret=1 +else + echo_i "skipped no FIPS provider available" +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "check that 'dnssec-signzone -F' failed with disallowed algorithm ($n)" +ret=0 +if ! $FEATURETEST --fips-provider; then + echo_i "skipped no FIPS provider available" +elif [ $RSASHA1_SUPPORTED = 0 ]; then + echo_i "skipped: RSASHA1 is not supported" +else + ( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -F -f signed.zone -o example.com. test11.zone >signer.out.$n 2>&1 && exit 1 + grep -F -e "fatal: No signing keys specified or found" \ + -e "fatal: dnskey 'example.com/RSASHA1/19857' failed to sign data" signer.out.$n >/dev/null + ) || ret=1 +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "revoked KSK ID collides with ZSK ($n)" +ret=0 +# signing should fail, but should not coredump +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -S -f signed.zone -o . test12.zone >signer.out.$n +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "check that dnssec-signzone rejects excessive NSEC3 iterations ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $SIGNER -f signed.zone -3 - -H 51 -o example.com. test9.zone >signer.out.$n + test -f signed.zone +) && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "check that dnssec-signzone -J loads journal files ($n)" +ret=0 +( + cd signer/general || exit 0 + rm -f signed.zone + $MAKEJOURNAL example.com. test9.zone test10.zone test9.zone.jnl + $SIGNER -f signed.zone -o example.com. -J test9.zone.jnl test9.zone >signer.out.$n + grep -q extra signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_ic "check that dnssec-signzone accepts maximum NSEC3 iterations ($n)" +ret=0 +( + cd signer/general || exit 1 + rm -f signed.zone + $SIGNER -f signed.zone -3 - -H 50 -o example.com. test9.zone >signer.out.$n + test -f signed.zone +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +get_default_algorithm_key_ids_from_sigs() { + zone=$1 + + awk -v alg=$DEFAULT_ALGORITHM_NUMBER ' + NF < 8 { next } + $(NF-5) != "RRSIG" { next } + $(NF-3) != alg { next } + $NF != "(" { next } + { + getline; + print $3; + } + ' signer/$zone.db.signed | sort -u +} + +# Test dnssec-signzone ZSK prepublish smooth rollover. +echo_i "check dnssec-signzone doesn't sign with prepublished zsk ($n)" +ret=0 +zone=prepub +# Generate keys. +ksk=$("$KEYGEN" -K signer -f KSK -q -a $DEFAULT_ALGORITHM -n zone "$zone") +zsk1=$("$KEYGEN" -K signer -q -a $DEFAULT_ALGORITHM -n zone "$zone") +zsk2=$("$KEYGEN" -K signer -q -a $DEFAULT_ALGORITHM -n zone "$zone") +zskid1=$(keyfile_to_key_id "$zsk1") +zskid2=$(keyfile_to_key_id "$zsk2") +( + cd signer || exit 1 + # Set times such that the current set of keys are introduced 60 days ago and + # start signing now. The successor key is prepublished now and will be active + # next day. + $SETTIME -P now-60d -A now $ksk >/dev/null + $SETTIME -P now-60d -A now -I now+1d -D now+60d $zsk1 >/dev/null + $SETTIME -S $zsk1 -i 1h $zsk2.key >/dev/null + $SETTIME -P now -A now+1d $zsk2.key >/dev/null + # Sign the zone with initial keys and prepublish successor. The zone signatures + # are valid for 30 days and the DNSKEY signature is valid for 60 days. + cp -f $zone.db.in $zone.db + $SIGNER -SDx -e +2592000 -X +5184000 -o $zone $zone.db >/dev/null + echo "\$INCLUDE \"$zone.db.signed\"" >>$zone.db +) +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" >/dev/null || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed: missing signatures from key $zskid1" +status=$((status + ret)) + +echo_i "check dnssec-signzone retains signatures of predecessor zsk ($n)" +ret=0 +zone=prepub +( + cd signer || exit 1 + # Roll the ZSK. The predecessor is inactive from now on and the successor is + # activated. The zone signatures are valid for 30 days and the DNSKEY + # signature is valid for 60 days. Because of the predecessor/successor + # relationship, the signatures of the predecessor are retained and no new + # signatures with the successor should be generated. + $SETTIME -A now-30d -I now -D now+30d $zsk1 >/dev/null + $SETTIME -A now $zsk2 >/dev/null + $SIGNER -SDx -e +2592000 -X +5184000 -o $zone $zone.db >/dev/null +) +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" >/dev/null || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check dnssec-signzone swaps zone signatures after interval ($n)" +ret=0 +zone=prepub +( + cd signer || exit 1 + # After some time the signatures should be replaced. When signing, set the + # interval to 30 days plus one second, meaning all predecessor signatures + # are within the refresh interval and should be replaced with successor + # signatures. + $SETTIME -A now-50d -I now-20d -D now+10d $zsk1 >/dev/null + $SETTIME -A now-20d $zsk2 >/dev/null + $SIGNER -SDx -e +2592000 -X +5184000 -i 2592001 -o $zone $zone.db >/dev/null +) +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid1$" >/dev/null && ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$zskid2$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a key using an unsupported algorithm cannot be generated ($n)" +ret=0 +zone=example +# If dnssec-keygen fails, the test script will exit immediately. Prevent that +# from happening, and also trigger a test failure if dnssec-keygen unexpectedly +# succeeds, by using "&& ret=1". +$KEYGEN -a 255 $zone >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "unsupported algorithm: 255" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a DS record cannot be generated for a key using an unsupported algorithm ($n)" +ret=0 +zone=example +# Fake an unsupported algorithm key +unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key >${unsupportedkey}.tmp +mv ${unsupportedkey}.tmp ${unsupportedkey}.key +# If dnssec-dsfromkey fails, the test script will exit immediately. Prevent +# that from happening, and also trigger a test failure if dnssec-dsfromkey +# unexpectedly succeeds, by using "&& ret=1". +$DSFROMKEY ${unsupportedkey} >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a zone cannot be signed with a key using an unsupported algorithm ($n)" +ret=0 +ret=0 +cat signer/example.db.in "${unsupportedkey}.key" >signer/example.db +# If dnssec-signzone fails, the test script will exit immediately. Prevent that +# from happening, and also trigger a test failure if dnssec-signzone +# unexpectedly succeeds, by using "&& ret=1". +$SIGNER -o example signer/example.db ${unsupportedkey} >dnssectools.out.test$n 2>&1 && ret=1 +grep -q "algorithm is unsupported" dnssectools.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that we can sign a zone with out-of-zone records ($n)" +ret=0 +zone=example +key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone) +( + cd signer || exit 1 + cat example.db.in "$key1.key" "$key2.key" >example.db + $SIGNER -o example -f example.db example.db >/dev/null +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that we can sign a zone (NSEC3) with out-of-zone records ($n)" +ret=0 +zone=example +key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone) +( + cd signer || exit 1 + cat example.db.in "$key1.key" "$key2.key" >example.db + $SIGNER -3 - -H 10 -o example -f example.db example.db >/dev/null + awk '/^IQF9LQTLK/ { + printf("%s", $0); + while (!index($0, ")")) { + if (getline <= 0) + break; + printf (" %s", $0); + } + printf("\n"); + }' example.db | sed 's/[ ][ ]*/ /g' >nsec3param.out + + grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out >/dev/null +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking NSEC3 signing with empty nonterminals above a delegation ($n)" +ret=0 +zone=example +key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone) +( + cd signer || exit 1 + cat example.db.in "$key1.key" "$key2.key" >example3.db + echo "some.empty.nonterminal.nodes.example 60 IN NS ns.example.tld" >>example3.db + $SIGNER -3 - -A -H 10 -o example -f example3.db example3.db >/dev/null + awk '/^IQF9LQTLK/ { + printf("%s", $0); + while (!index($0, ")")) { + if (getline <= 0) + break; + printf (" %s", $0); + } + printf("\n"); + }' example.db | sed 's/[ ][ ]*/ /g' >nsec3param.out + + grep "IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG.example. 0 IN NSEC3 1 0 10 - ( IQF9LQTLKKNFK0KVIFELRAK4IC4QLTMG A NS SOA RRSIG DNSKEY NSEC3PARAM )" nsec3param.out >/dev/null +) || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that dnssec-signzone updates originalttl on ttl changes ($n)" +ret=0 +zone=example +key1=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +key2=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone) +( + cd signer || exit 1 + cat example.db.in "$key1.key" "$key2.key" >example.db + $SIGNER -o example -f example.db.before example.db >/dev/null + sed 's/60.IN.SOA./50 IN SOA /' example.db.before >example.db.changed + $SIGNER -o example -f example.db.after example.db.changed >/dev/null +) +grep "SOA $DEFAULT_ALGORITHM_NUMBER 1 50" signer/example.db.after >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone keeps valid signatures from removed keys ($n)" +ret=0 +zone=example +key1=$($KEYGEN -K signer -q -f KSK -a $DEFAULT_ALGORITHM -n zone $zone) +key2=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +keyid2=$(keyfile_to_key_id "$key2") +key3=$($KEYGEN -K signer -q -a $DEFAULT_ALGORITHM -n zone $zone) +keyid3=$(keyfile_to_key_id "$key3") +( + cd signer || exit 1 + cat example.db.in "$key1.key" "$key2.key" >example.db + $SIGNER -D -o example example.db >/dev/null + + # now switch out key2 for key3 and resign the zone + cat example.db.in "$key1.key" "$key3.key" >example.db + echo "\$INCLUDE \"example.db.signed\"" >>example.db + $SIGNER -D -o example example.db >/dev/null +) || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" >/dev/null || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -R purges signatures from removed keys ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -RD -o example example.db >/dev/null +) || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" >/dev/null && ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone keeps valid signatures from inactive keys ($n)" +ret=0 +zone=example +( + cd signer || exit 1 + cp -f example.db.in example.db + $SIGNER -SD -o example example.db >/dev/null + echo "\$INCLUDE \"example.db.signed\"" >>example.db + # now retire key2 and resign the zone + $SETTIME -I now "$key2" >/dev/null 2>&1 + $SIGNER -SD -o example example.db >/dev/null +) || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" >/dev/null || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -Q purges signatures from inactive keys ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -SDQ -o example example.db >/dev/null +) || ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid2$" >/dev/null && ret=1 +get_default_algorithm_key_ids_from_sigs $zone | grep "^$keyid3$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone retains unexpired signatures ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -Sxt -o example example.db >signer.out.1 + $SIGNER -Sxt -o example -f example.db.signed example.db.signed >signer.out.2 +) || ret=1 +gen1=$(awk '/generated/ {print $3}' signer/signer.out.1) +retain1=$(awk '/retained/ {print $3}' signer/signer.out.1) +gen2=$(awk '/generated/ {print $3}' signer/signer.out.2) +retain2=$(awk '/retained/ {print $3}' signer/signer.out.2) +drop2=$(awk '/dropped/ {print $3}' signer/signer.out.2) +[ "$retain2" -eq $((gen1 + retain1)) ] || ret=1 +[ "$gen2" -eq 0 ] || ret=1 +[ "$drop2" -eq 0 ] || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)" +ret=0 +( + cd signer || exit 1 + # remove NSEC-only keys + rm -f Kexample.+005* + cp -f example.db.in example2.db + cat <>example2.db +sub1.example. IN A 10.53.0.1 +ns.sub2.example. IN A 10.53.0.2 +EOF + echo "\$INCLUDE \"example2.db.signed\"" >>example2.db + touch example2.db.signed + $SIGNER -DS -O full -f example2.db.signed -o example example2.db >/dev/null +) || ret=1 +grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 || ret=1 +grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 || ret=1 +( + cd signer || exit 1 + cp -f example.db.in example2.db + cat <>example2.db +sub1.example. IN NS sub1.example. +sub1.example. IN A 10.53.0.1 +sub2.example. IN NS ns.sub2.example. +ns.sub2.example. IN A 10.53.0.2 +EOF + echo "\$INCLUDE \"example2.db.signed\"" >>example2.db + $SIGNER -DS -O full -f example2.db.signed -o example example2.db >/dev/null +) || ret=1 +grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 && ret=1 +grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)" +ret=0 +( + cd signer || exit 1 + rm -f example2.db.signed + cp -f example.db.in example2.db + cat <>example2.db +sub1.example. IN A 10.53.0.1 +ns.sub2.example. IN A 10.53.0.2 +EOF + echo "\$INCLUDE \"example2.db.signed\"" >>example2.db + touch example2.db.signed + $SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db >/dev/null +) || ret=1 +grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 || ret=1 +grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 || ret=1 +( + cd signer || exit 1 + cp -f example.db.in example2.db + cat <>example2.db +sub1.example. IN NS sub1.example. +sub1.example. IN A 10.53.0.1 +sub2.example. IN NS ns.sub2.example. +ns.sub2.example. IN A 10.53.0.2 +EOF + echo "\$INCLUDE \"example2.db.signed\"" >>example2.db + $SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db >/dev/null +) || ret=1 +grep "^sub1\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 && ret=1 +grep "^ns\\.sub2\\.example\\..*RRSIG[ ]A[ ]" signer/example2.db.signed >/dev/null 2>&1 && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone output format ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -O full -f - -Sxt -o example example.db >signer.out.3 2>/dev/null + $SIGNER -O text -f - -Sxt -o example example.db >signer.out.4 2>/dev/null + $SIGNER -O raw -f signer.out.5 -Sxt -o example example.db >/dev/null + $SIGNER -O raw=0 -f signer.out.6 -Sxt -o example example.db >/dev/null + $SIGNER -O raw -f - -Sxt -o example example.db >signer.out.7 2>/dev/null +) || ret=1 +awk 'BEGIN { found = 0; } + $1 == "example." && $3 == "IN" && $4 == "SOA" { found = 1; if (NF != 11) exit(1); } + END { if (!found) exit(1); }' signer/signer.out.3 || ret=1 +awk 'BEGIN { found = 0; } + $1 == "example." && $3 == "IN" && $4 == "SOA" { found = 1; if (NF != 7) exit(1); } + END { if (!found) exit(1); }' signer/signer.out.4 || ret=1 +israw1 signer/signer.out.5 || ret=1 +israw0 signer/signer.out.6 || ret=1 +israw1 signer/signer.out.7 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking TTLs are capped by dnssec-signzone -M ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -O full -f signer.out.8 -S -M 30 -o example example.db >/dev/null +) || ret=1 +awk '/^;/ { next; } $2 > 30 { exit 1; }' signer/signer.out.8 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -N date ($n)" +ret=0 +( + cd signer || exit 1 + TZ=UTC $SIGNER -O full -f signer.out.9 -S -N date -o example example2.db >/dev/null +) || ret=1 +# shellcheck disable=SC2016 +now=$(TZ=UTC $PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];') +serial=$(awk '/^;/ { next; } $4 == "SOA" { print $7 }' signer/signer.out.9) +[ "$now" -eq "$serial" ] || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G ($n)" +ret=0 +( + cd signer || exit 1 + $SETTIME -P ds now -P sync now "$key1" >/dev/null + $SIGNER -G "cdnskey,cds:sha384" -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (default) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (empty) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "" -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (no CDNSKEY) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cds:sha-256,cds:sha384" -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (no CDS) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey" -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (suppress duplicates) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,cds:sha256,cds:sha256,cdnskey" -O full -S -f signer.out.$n -o example example2.db >/dev/null +) || ret=1 +test $(awk '$4 == "CDNSKEY" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "2" { print }' signer/signer.out.$n | wc -l) -eq 1 || ret=1 +test $(awk '$4 == "CDS" && $7 == "4" { print }' signer/signer.out.$n | wc -l) -eq 0 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (bad argument) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,foobar" -O full -S -f signer.out.$n -o example example2.db 2>signer.err.$n && ret=1 + grep "digest must specify cds:algorithm ('foobar')" signer.err.$n >/dev/null || ret=1 +) +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (bad digest - name) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,cds:foobar" -O full -S -f signer.out.$n -o example example2.db 2>signer.err.$n && ret=1 + grep "bad digest 'cds:foobar'" signer.err.$n >/dev/null || ret=1 +) +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (bad digest - number) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,cds:256" -O full -S -f signer.out.$n -o example example2.db 2>signer.err.$n && ret=1 + grep "bad digest 'cds:256': out of range" signer.err.$n >/dev/null || ret=1 +) +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (unsupported digest - name) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,cds:gost" -O full -S -f signer.out.$n -o example example2.db 2>signer.err.$n && ret=1 + grep "unsupported digest 'cds:gost'" signer.err.$n >/dev/null || ret=1 +) +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone -G (unsupported digest - number) ($n)" +ret=0 +( + cd signer || exit 1 + $SIGNER -G "cdnskey,cds:200" -O full -S -f signer.out.$n -o example example2.db 2>signer.err.$n && ret=1 + grep "unsupported digest 'cds:200'" signer.err.$n >/dev/null || ret=1 +) +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking validated data are not cached longer than originalttl ($n)" +ret=0 +dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +ttl +noauth a.ttlpatch.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +grep "3600.IN" dig.out.ns3.test$n >/dev/null || ret=1 +grep "300.IN" dig.out.ns3.test$n >/dev/null && ret=1 +grep "300.IN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "3600.IN" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Test that "rndc secroots" is able to dump trusted keys +echo_i "checking rndc secroots ($n)" +ret=0 +keyid=$(cat ns1/managed.key.id) +rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i +cp ns4/named.secroots named.secroots.test$n +check_secroots_layout named.secroots.test$n || ret=1 +linecount=$(grep -c "./$DEFAULT_ALGORITHM/$keyid ; static" named.secroots.test$n || true) +[ "$linecount" -eq 1 ] || ret=1 +linecount=$(wc /dev/null || ret=1 +ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1 +expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^A') || ret=1 +test "$ans" = "$expect" || ret=1 +# also check that RA is set +dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1 +grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check direct query for RRSIG: If it's not cached with other records, +# it should result in an empty response. +echo_i "checking RRSIG query not in cache ($n)" +ret=0 +ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1 +test -z "$ans" || ret=1 +# also check that RA is cleared +dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1 +grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# RT21868 regression test. +# +echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)" +ret=0 +dig_with_opts non-exist.badparam. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# RT22007 regression test. +# +echo_i "checking optout NSEC3 referral with only insecure delegations ($n)" +ret=0 +dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)" +ret=0 +dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" + +status=$((status + ret)) +echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)" +ret=0 +dig_with_opts +norec single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)" +ret=0 +dig_with_opts ns algroll. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking validate-except in an insecure local domain ($n)" +ret=0 +dig_with_opts ns www.corp @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive and negative validation with negative trust anchors ($n)" +ret=0 + +# +# check correct initial behavior +# +dig_with_opts a.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null || ret=1 +dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1 +dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1 + +if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi +status=$((status + ret)) +ret=0 + +# +# add negative trust anchors +# +rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i +# reconfig should maintain NTAs +rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 +lines=$(wc -l &1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i +# reload should maintain NTAs +rndc_reload ns4 10.53.0.4 +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2 +lines=$(wc -l dig.out.ns4.test$n.4 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1 +dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 >/dev/null && ret=1 +dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.6 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.6 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 >/dev/null && ret=1 +dig_with_opts a.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.7 || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 >/dev/null && ret=1 +echo_i "dumping secroots" +rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i +cp ns4/named.secroots named.secroots.test$n +check_secroots_layout named.secroots.test$n || ret=1 +grep "bogus.example: expiry" named.secroots.test$n >/dev/null || ret=1 +grep "badds.example: expiry" named.secroots.test$n >/dev/null || ret=1 +grep "secure.example: expiry" named.secroots.test$n >/dev/null || ret=1 +grep "fakenode.secure.example: expiry" named.secroots.test$n >/dev/null || ret=1 + +if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi +status=$((status + ret)) +ret=0 + +echo_i "waiting for NTA rechecks/expirations" + +# +# secure.example and badds.example used default nta-duration +# (configured as 12s in ns4/named1.conf), but nta recheck interval +# is configured to 9s, so at t=10 the NTAs for secure.example and +# fakenode.secure.example should both be lifted, but badds.example +# should still be going. +# +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' +dig_with_opts b.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.8 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.8 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 >/dev/null || ret=1 +dig_with_opts b.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.9 || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n.9 >/dev/null || ret=1 +dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.10 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.10 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 >/dev/null && ret=1 + +if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi +status=$((status + ret)) +ret=0 + +# +# bogus.example was set to expire in 20s, so at t=13 +# it should still be NTA'd, but badds.example used the default +# lifetime of 12s, so it should revert to SERVFAIL now. +# +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' +# check nta table +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n._11 +lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true) +[ "$lines" -le 2 ] || ret=1 +grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null || ret=1 +grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null && ret=1 +dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.11 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.11 >/dev/null && ret=1 +dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.12 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.12 >/dev/null || ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 >/dev/null && ret=1 +dig_with_opts c.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.13 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.13 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 >/dev/null || ret=1 + +if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi +status=$((status + ret)) +ret=0 + +# +# at t=21, all the NTAs should have expired. +# +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' +# check correct behavior after bogus.example expiry +dig_with_opts d.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.14 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.14 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 >/dev/null || ret=1 +dig_with_opts c.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.15 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.15 >/dev/null || ret=1 +# check nta table has been cleaned up now +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 +lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true) +[ "$lines" -eq 0 ] || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi +status=$((status + ret)) +ret=0 + +echo_i "testing NTA removals ($n)" +rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 +grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 >/dev/null || ret=1 +dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null && ret=1 +grep "^a.badds.example." dig.out.ns4.test$n.1 >/dev/null || ret=1 +rndccmd 10.53.0.4 nta -remove badds.example >rndc.out.ns4.test$n.2 +grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 >/dev/null || ret=1 +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 +grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 >/dev/null && ret=1 +dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +ret=0 + +echo_i "remove non-existent NTA three times" +rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.4 2>&1 +rndccmd 10.53.0.4 nta -remove foo >rndc.out.ns4.test$n.5 2>&1 +rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.6 2>&1 +grep "not found" rndc.out.ns4.test$n.6 >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +ret=0 + +n=$((n + 1)) +echo_i "testing NTA with bogus lifetimes ($n)" +echo_i "check with no nta lifetime specified" +rndccmd 10.53.0.4 nta -l "" foo >rndc.out.ns4.test$n.1 2>&1 || true +grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +ret=0 + +echo_i "check with bad nta lifetime" +rndccmd 10.53.0.4 nta -l garbage foo >rndc.out.ns4.test$n.2 2>&1 || true +grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +ret=0 + +echo_i "check with too long nta lifetime" +rndccmd 10.53.0.4 nta -l 7d1h foo >rndc.out.ns4.test$n.3 2>&1 || true +grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +ret=0 + +# +# check NTA persistence across restarts +# +n=$((n + 1)) +echo_i "testing NTA persistence across restarts ($n)" +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 +lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true) +[ "$lines" -eq 0 ] || ret=1 +rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2 +lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true) +[ "$lines" -eq 2 ] || ret=1 +# shellcheck disable=SC2016 +start=$($PERL -e 'print time()."\n";') + +if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi +status=$((status + ret)) +ret=0 + +echo_i "killing ns4 with SIGTERM" +kill -TERM "$(cat ns4/named.pid)" +rm -f ns4/named.pid + +# +# ns4 has now shutdown. wait until t=14 when badds.example's NTA +# (lifetime=10s) would have expired, and then restart ns4. +# +echo_i "waiting till 14s have passed since NTAs were added before restarting ns4" +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' + +if + start_server --noclean --restart --port "$PORT" ns4 +then + echo_i "restarted server ns4" +else + echo_i "could not restart server ns4" + exit 1 +fi + +echo_i "sleeping for an additional 4 seconds for ns4 to fully startup" +sleep 4 + +# +# ns4 should be back up now. The NTA for bogus.example should still be +# valid, whereas badds.example should not have been added during named +# startup (as it had already expired), the fact that it's ignored should +# be logged. +# +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 +lines=$(wc -l /dev/null || ret=1 +dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.4 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1 +dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null || ret=1 +grep "ignoring expired NTA at badds.example" ns4/named.run >/dev/null || ret=1 + +# cleanup +rndccmd 10.53.0.4 nta -remove bogus.example >rndc.out.ns4.test$n.6 + +if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi +status=$((status + ret)) +ret=0 + +# +# check "regular" attribute in NTA file works as expected at named +# startup. +# +n=$((n + 1)) +echo_i "testing loading regular attribute from NTA file ($n)" +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null +lines=$(wc -l dig.out.ns4.test$n.2 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1 + +echo_i "killing ns4 with SIGTERM" +kill -TERM "$(cat ns4/named.pid)" +rm -f ns4/named.pid + +echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" +sleep 4 + +# +# ns4 has now shutdown. add NTA for secure.example. directly into the +# _default.nta file with the regular attribute and some future timestamp. +# +future="$(($(date +%Y) + 20))0101010000" +echo "secure.example. regular $future" >ns4/_default.nta +# shellcheck disable=SC2016 +start=$($PERL -e 'print time()."\n";') + +if + start_server --noclean --restart --port "$PORT" ns4 +then + echo_i "restarted server ns4" +else + echo_i "could not restart server ns4" + exit 1 +fi + +# nta-recheck is configured as 9s, so at t=12 the NTAs for +# secure.example. should be lifted as it is not a forced NTA. +echo_i "waiting till 12s have passed after ns4 was restarted" +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' + +# secure.example. should now return an AD=1 answer (still validates) as +# the NTA has been lifted. +dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1 + +# cleanup +rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null + +if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi +status=$((status + ret)) +ret=0 + +# +# check "forced" attribute in NTA file works as expected at named +# startup. +# +n=$((n + 1)) +echo_i "testing loading forced attribute from NTA file ($n)" +rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null +lines=$(wc -l dig.out.ns4.test$n.2 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1 + +echo_i "killing ns4 with SIGTERM" +kill -TERM "$(cat ns4/named.pid)" +rm -f named.pid + +echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" +sleep 4 + +# +# ns4 has now shutdown. add NTA for secure.example. directly into the +# _default.nta file with the forced attribute and some future timestamp. +# +echo "secure.example. forced $future" >ns4/_default.nta +start=$($PERL -e 'print time()."\n";') + +if + start_server --noclean --restart --port "$PORT" ns4 +then + echo_i "restarted server ns4" +else + echo_i "could not restart server ns4" + exit 1 +fi + +# nta-recheck is configured as 9s, but even at t=12 the NTAs for +# secure.example. should not be lifted as it is a forced NTA. +echo_i "waiting till 12s have passed after ns4 was restarted" +# shellcheck disable=SC2016 +$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' + +# secure.example. should now return an AD=0 answer (non-authenticated) +# as the NTA is still there. +dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 +grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 +grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null && ret=1 + +# cleanup +rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null + +if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi +status=$((status + ret)) +ret=0 + +# +# check that NTA lifetime read from file is clamped to 1 week. +# +n=$((n + 1)) +echo_i "testing loading out of bounds lifetime from NTA file ($n)" + +echo_i "killing ns4 with SIGTERM" +kill -TERM "$(cat ns4/named.pid)" +rm -f ns4/named.pid + +echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" +sleep 4 + +# +# ns4 has now shutdown. add NTA for secure.example. directly into the +# _default.nta file with a lifetime well into the future. +# +echo "secure.example. forced $future" >ns4/_default.nta +added=$($PERL -e 'print time()."\n";') + +if + start_server --noclean --restart --port "$PORT" ns4 +then + echo_i "restarted server ns4" +else + echo_i "could not restart server ns4" + exit 1 +fi + +echo_i "sleeping for an additional 4 seconds for ns4 to fully startup" +sleep 4 + +# dump the NTA to a file (omit validate-except entries) +echo_i "testing 'rndc nta -d' with NTA" +rndccmd 10.53.0.4 nta -d | grep -v ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null +# "corp" is configured as a validate-except domain and thus should be +# removed by the grep -v above. only "secure.example" should appear in +# the dump. +lines=$(wc -l /dev/null || ret=1 +ts=$(awk '{print $3" "$4}' rndc.out.ns4.test$n.2 +echo "ts_with_zone=$ts_with_zone" >>rndc.out.ns4.test$n.2 +echo "added=$added" >>rndc.out.ns4.test$n.2 +if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null; then + # ntadiff.pl computes $ts_with_zone - ($added + 1week) + d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added") + echo "d=$d" >>rndc.out.ns4.test$n.2 + # diff from $added(now) + 1week to the clamped NTA lifetime should be + # less than a few seconds (handle daylight saving changes by adding 3600). + [ "$d" -lt 3610 ] || ret=1 +else + echo_i "skipped ntadiff test; install PERL module Time::Piece" +fi + +echo_i "testing 'rndc nta' lifetime clamping" +rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null +# "corp" is configured as a validate-except domain and thus should be +# the only entry in the dump. +lines=$(wc -l /dev/null || ret=1 + +# cleanup +rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.3 2>/dev/null + +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "testing 'rndc nta -d' displays validate-except entries" +rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null +lines=$(wc -l /dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)" +ret=0 +# Sanity check behavior without an NTA in place. +dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.1 || ret=1 +grep "SERVFAIL" dig.out.ns9.test$n.1 >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns9.test$n.1 >/dev/null || ret=1 +grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 >/dev/null && ret=1 +# Add an NTA, expecting that to cause resolution to succeed. +rndccmd 10.53.0.9 nta badds.example >rndc.out.ns9.test$n.1 2>&1 || ret=1 +dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.2 || ret=1 +grep "NOERROR" dig.out.ns9.test$n.2 >/dev/null || ret=1 +grep "ANSWER: 2" dig.out.ns9.test$n.2 >/dev/null || ret=1 +grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 >/dev/null && ret=1 +# Remove the NTA, expecting that to cause resolution to fail again. +rndccmd 10.53.0.9 nta -remove badds.example >rndc.out.ns9.test$n.2 2>&1 || ret=1 +dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.3 || ret=1 +grep "SERVFAIL" dig.out.ns9.test$n.3 >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns9.test$n.3 >/dev/null || ret=1 +grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 >/dev/null && ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "completed NTA tests" + +# Run a minimal update test if possible. This is really just +# a regression test for RT #2399; more tests should be added. + +if $PERL -e 'use Net::DNS;' 2>/dev/null; then + echo_i "running DNSSEC update test" + ret=0 + { + output=$($PERL dnssec_update_test.pl -s 10.53.0.3 -p "$PORT" dynamic.example.) + rc=$? + } || true + test "$rc" -eq 0 || ret=1 + echo "$output" | cat_i + [ $ret -eq 1 ] && status=1 +else + echo_i "The DNSSEC update test requires the Net::DNS library." >&2 +fi + +n=$((n + 1)) +echo_i "checking managed key maintenance has not started yet ($n)" +ret=0 +[ -f "ns4/managed-keys.bind.jnl" ] && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Reconfigure caching server to use "dnssec-validation auto", and repeat +# some of the DNSSEC validation tests to ensure that it works correctly. +# Also setup a placeholder managed-keys zone to check if named can process it +# correctly. +echo_i "switching to automatic root key configuration" +cp ns4/managed-keys.bind.in ns4/managed-keys.bind +copy_setports ns4/named2.conf.in ns4/named.conf +rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i +sleep 5 + +echo_i "checking managed key maintenance timer has now started ($n)" +ret=0 +[ -f "ns4/managed-keys.bind.jnl" ] || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation NSEC ($n)" +ret=0 +dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation NSEC3 ($n)" +ret=0 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.nsec3.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking positive validation OPTOUT ($n)" +ret=0 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth a.optout.example. \ + @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking negative validation ($n)" +ret=0 +dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that root DS queries validate ($n)" +ret=0 +dig_with_opts +noauth . @10.53.0.1 ds >dig.out.ns1.test$n || ret=1 +dig_with_opts +noauth . @10.53.0.4 ds >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)" +ret=0 +dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1 +dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1 +grep "status: NOERROR" dig.out.ns6.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)" +ret=0 +dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa >dig.out.ns3.test$n || ret=1 +grep "RRSIG.SOA" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" + +status=$((status + ret)) +echo_i "checking expired signatures do not validate ($n)" +ret=0 +dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +grep "expired.example/.*: RRSIG has expired" ns4/named.run >/dev/null || ret=1 +grep "; EDE: 7 (Signature Expired): (expired.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +status=$((status + ret)) +echo_i "checking signatures in the future do not validate ($n)" +ret=0 +dig_with_opts +noauth future.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +grep "future.example/.*: RRSIG validity period has not begun" ns4/named.run >/dev/null || ret=1 +grep "; EDE: 8 (Signature Not Yet Valid): (future.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)" +ret=0 +( + kskname=$($KEYGEN -q -3 -a $DEFAULT_ALGORITHM -fk update-nsec3.example) + ( + echo zone update-nsec3.example + echo server 10.53.0.3 "$PORT" + grep DNSKEY "${kskname}.key" | sed -e 's/^/update add /' -e 's/IN/300 IN/' + echo send + ) | $NSUPDATE +) +dig_with_opts +dnssec a update-nsec3.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +grep "NSEC3 1 0 0 - .*" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that the NSEC record is properly generated when DNSKEY are added by dnssec-policy ($n)" +ret=0 +dig_with_opts +dnssec a auto-nsec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +grep "IN.NSEC[^3].* DNSKEY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added by dnssec-policy ($n)" +ret=0 +dig_with_opts +dnssec a auto-nsec3.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +grep "IN.NSEC3 .* DNSKEY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that signing records have been marked as complete ($n)" +ret=0 +checkprivate dynamic.example 10.53.0.3 || ret=1 +checkprivate auto-nsec3.example 10.53.0.3 || ret=1 +checkprivate expiring.example 10.53.0.3 || ret=1 +checkprivate auto-nsec.example 10.53.0.3 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'rndc signing' without arguments is handled ($n)" +ret=0 +rndccmd 10.53.0.3 signing >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'rndc signing -list' without zone is handled ($n)" +ret=0 +rndccmd 10.53.0.3 signing -list >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)" +ret=0 +rndccmd 10.53.0.3 signing -clear >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'rndc signing -clear all' without zone is handled ($n)" +ret=0 +rndccmd 10.53.0.3 signing -clear all >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check rndc signing -list output ($n)" +ret=0 +{ rndccmd 10.53.0.3 signing -list dynamic.example >signing.out.dynamic.example; } 2>&1 +grep -q "No signing records found" signing.out.dynamic.example || { + ret=1 + sed 's/^/ns3 /' signing.out.dynamic.example | cat_i +} +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a insecure zone beneath a cname resolves ($n)" +ret=0 +dig_with_opts soa insecure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a secure zone beneath a cname resolves ($n)" +ret=0 +dig_with_opts soa secure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +my_dig() { + "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@" +} + +echo_i "checking DNSKEY query with no data still gets put in cache ($n)" +ret=0 +firstVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') +sleep 1 +secondVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') +if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]; then + sleep 1 + thirdVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') + if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]; then + echo_i "cannot confirm query answer still in cache" + ret=1 + fi +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a split dnssec dnssec-signzone work ($n)" +ret=0 +dig_with_opts soa split-dnssec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a smart split dnssec dnssec-signzone work ($n)" +ret=0 +dig_with_opts soa split-smart.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check dnssec-dsfromkey from stdin ($n)" +ret=0 +dig_with_opts dnskey algroll. @10.53.0.2 \ + | $DSFROMKEY -f - algroll. >dig.out.ns2.test$n || ret=1 +NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u) +[ "${NF}" = 7 ] || ret=1 +# make canonical +awk '{ + for (i=1;i<7;i++) printf("%s ", $i); + for (i=7;i<=NF;i++) printf("%s", $i); + printf("\n"); +}' canonical1.$n || ret=1 +awk '{ + for (i=1;i<7;i++) printf("%s ", $i); + for (i=7;i<=NF;i++) printf("%s", $i); + printf("\n"); +}' canonical2.$n || ret=1 +diff -b canonical1.$n canonical2.$n >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Intentionally strip ".key" from keyfile name to ensure the error message +# includes it anyway to avoid confusion (RT #21731) +echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)" +ret=0 +key=$($KEYGEN -a $DEFAULT_ALGORITHM -q example.) || ret=1 +mv "$key.key" "$key" +$DSFROMKEY "$key" >dsfromkey.out.$n 2>&1 && ret=1 +grep "$key.key: file not found" dsfromkey.out.$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check dnssec-dsfromkey with revoked key ($n)" +ret=0 +dig_with_opts revkey.example dnskey @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "DNSKEY.256 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # ZSK +grep "DNSKEY.385 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # revoked KSK +grep "DNSKEY.257 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # KSK +test $(awk '$4 == "DNSKEY" { print }' dig.out.ns4.test$n | wc -l) -eq 3 || ret=1 +$DSFROMKEY -f dig.out.ns4.test$n revkey.example. >dsfromkey.out.test$n || ret=1 +test $(wc -l dig.out.ns3.test$n 2>&1 +# there must be a signature here +[ -s dig.out.ns3.test$n ] || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing legacy upper case signer name validation ($n)" +ret=0 +$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \ + >dig.out.ns4.test$n 2>&1 || ret=1 +grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing that we lower case signer name ($n)" +ret=0 +$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \ + >dig.out.ns4.test$n 2>&1 || ret=1 +grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing TTL is capped at RRSIG expiry time ($n)" +ret=0 +rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i +( + cd ns3 || exit 1 + for file in K*.moved; do + mv "$file" "$(basename "$file" .moved)" + done + $SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db >/dev/null +) || ret=1 +rndc_reload ns3 10.53.0.3 expiring.example + +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n +dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-0}; do + [ "${ttl}" -eq 300 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "${ttl}" -le 60 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +sleep 1 +dig_with_additionalopts +cd expiring.example ns @10.53.0.4 >dig.out.ns4.1.$n +dig_with_additionalopts expiring.example ns @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-300}; do + [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "$ttl" -le 60 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +sleep 1 +dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n +dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-300}; do + [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "$ttl" -le 60 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +copy_setports ns4/named3.conf.in ns4/named.conf +rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i +sleep 3 + +echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n +dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-0}; do + [ "$ttl" -eq 300 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "$ttl" -eq 120 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)" +ret=0 +dig_with_answeropts +cd expired.example soa @10.53.0.4 >dig.out.ns4.1.$n +dig_with_answeropts expired.example soa @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-0}; do + [ "$ttl" -eq 300 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "$ttl" -eq 120 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n +dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n +ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) +ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) +for ttl in ${ttls:-300}; do + [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 +done +for ttl in ${ttls2:-0}; do + [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing DNSKEY lookup via CNAME ($n)" +ret=0 +dig_with_opts +noauth cnameandkey.secure.example. \ + @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth cnameandkey.secure.example. \ + @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing KEY lookup at CNAME (present) ($n)" +ret=0 +dig_with_opts +noauth cnameandkey.secure.example. \ + @10.53.0.3 key >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth cnameandkey.secure.example. \ + @10.53.0.4 key >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing KEY lookup at CNAME (not present) ($n)" +ret=0 +dig_with_opts +noauth cnamenokey.secure.example. \ + @10.53.0.3 key >dig.out.ns3.test$n || ret=1 +dig_with_opts +noauth cnamenokey.secure.example. \ + @10.53.0.4 key >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing DNSKEY lookup via DNAME ($n)" +ret=0 +dig_with_opts a.dnameandkey.secure.example. \ + @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1 +dig_with_opts a.dnameandkey.secure.example. \ + @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1 +grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "testing KEY lookup via DNAME ($n)" +ret=0 +dig_with_opts b.dnameandkey.secure.example. \ + @10.53.0.3 key >dig.out.ns3.test$n || ret=1 +dig_with_opts b.dnameandkey.secure.example. \ + @10.53.0.4 key >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that named doesn't loop when all private keys are not available ($n)" +ret=0 +lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true) +test "${lines:-1000}" -lt 15 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check against against missing nearest provable proof ($n)" +dig_with_opts +norec b.c.d.optout-tld. \ + @10.53.0.6 ds >dig.out.ds.ns6.test$n || ret=1 +nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true) +[ "$nsec3" -eq 2 ] || ret=1 +dig_with_opts +norec b.c.d.optout-tld. \ + @10.53.0.6 A >dig.out.ns6.test$n || ret=1 +nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true) +[ "$nsec3" -eq 1 ] || ret=1 +dig_with_opts optout-tld. \ + @10.53.0.4 SOA >dig.out.soa.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n >/dev/null || ret=1 +dig_with_opts b.c.d.optout-tld. \ + @10.53.0.4 A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that key id are logged when dumping the cache ($n)" +ret=0 +rndc_dumpdb ns4 +grep "; key id = " ns4/named_dump.db.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check KEYDATA records are printed in human readable form in key zone ($n)" +# force the managed-keys zone to be written out +rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i +for i in 1 2 3 4 5 6 7 8 9; do + ret=0 + if test -f ns4/managed-keys.bind; then + grep KEYDATA ns4/managed-keys.bind >/dev/null \ + && grep "next refresh:" ns4/managed-keys.bind >/dev/null \ + && break + fi + ret=1 + sleep 1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check dig's +nocrypto flag ($n)" +ret=0 +dig_with_opts +norec +nocrypto DNSKEY . \ + @10.53.0.1 >dig.out.dnskey.ns1.test$n || ret=1 +grep -E "256 [0-9]+ $DEFAULT_ALGORITHM_NUMBER \\[key id = [1-9][0-9]*]" dig.out.dnskey.ns1.test$n >/dev/null || ret=1 +grep -E "RRSIG.* \\[omitted]" dig.out.dnskey.ns1.test$n >/dev/null || ret=1 +dig_with_opts +norec +nocrypto DS example \ + @10.53.0.1 >dig.out.ds.ns1.test$n || ret=1 +grep -E "DS.* [0-9]+ [12] \[omitted]" dig.out.ds.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that increasing the signatures-validity resigning triggers re-signing ($n)" +ret=0 +before=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA) +cp ns3/siginterval2.conf ns3/siginterval.conf +rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +i=10 +while [ "$i" -ge 0 ]; do + after=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA) + test "$before" != "$after" && break + sleep 1 + i=$((i - 1)) +done +n=$((n + 1)) +if test "$before" = "$after"; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +if [ -x "$PYTHON" ]; then + echo_i "check signatures-validity-dnskey sets longer expiry for DNSKEY ($n)" + ret=0 + rndccmd 10.53.0.3 sign siginterval.example 2>&1 | sed 's/^/ns3 /' | cat_i + # convert expiry date to a comma-separated list of integers python can + # use as input to date(). strip leading 0s in months and days so + # python3 will recognize them as integers. + $DIG +dnssec +short -p "$PORT" @10.53.0.3 soa siginterval.example >dig.out.soa.test$n || ret=1 + soaexpire=$(awk '$1 ~ /SOA/ { print $5 }' dig.out.soa.test$n \ + | sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' \ + | sed 's/ 0/ /g') + $DIG +dnssec +short -p "$PORT" @10.53.0.3 dnskey siginterval.example >dig.out.dnskey.test$n || ret=1 + dnskeyexpire=$(awk '$1 ~ /DNSKEY/ { print $5; exit 0 }' dig.out.dnskey.test$n \ + | sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' \ + | sed 's/ 0/ /g') + $PYTHON >python.out.$n <&1 | sed 's/^/ns4 /' | cat_i +sleep 3 + +echo_i "check insecure delegation between static-stub zones ($n)" +ret=0 +dig_with_opts ns insecure.secure.example \ + @10.53.0.4 >dig.out.ns4.1.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.1.test$n >/dev/null && ret=1 +dig_with_opts ns secure.example \ + @10.53.0.4 >dig.out.ns4.2.test$n || ret=1 +grep "SERVFAIL" dig.out.ns4.2.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check the acceptance of seconds as inception and expiration times ($n)" +ret=0 +in="NSEC 8 0 86400 1390003200 1389394800 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i+UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2rOo=" + +exp="NSEC 8 0 86400 20140118000000 20140110230000 33655 . NYWjZYBV1b+h4j0yu/SmPOOylR8P4IXKDzHX3NwEmU1SUp27aJ91dP+i +UBcnPmBib0hck4DrFVvpflCEpCnVQd2DexcN0GX+3PM7XobxhtDlmnU X1L47zJlbdHNwTqHuPaMM6Xy9HGMXps7O5JVyfggVhTz2C+G5OVxBdb2 rOo=" + +out=$(echo "IN RRSIG $in" | $RRCHECKER -p | sed 's/^IN.RRSIG.//') +[ "$out" = "$exp" ] || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check the correct resigning time is reported in zonestatus ($n)" +ret=0 +rndccmd 10.53.0.3 \ + zonestatus secure.example >rndc.out.ns3.test$n +# next resign node: secure.example/DNSKEY +qname=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,/.*,,') +qtype=$(awk '/next resign node:/ { print $4 }' rndc.out.ns3.test$n | sed 's,.*/,,') +# next resign time: Thu, 24 Apr 2014 10:38:16 GMT +time=$(awk 'BEGIN { m["Jan"] = "01"; m["Feb"] = "02"; m["Mar"] = "03"; + m["Apr"] = "04"; m["May"] = "05"; m["Jun"] = "06"; + m["Jul"] = "07"; m["Aug"] = "08"; m["Sep"] = "09"; + m["Oct"] = "10"; m["Nov"] = "11"; m["Dec"] = "12";} + /next resign time:/ { printf "%d%s%02d%s\n", $7, m[$6], $5, $8 }' rndc.out.ns3.test$n | sed 's/://g') +dig_with_opts +noall +answer "$qname" "$qtype" @10.53.0.3 >dig.out.test$n +expire=$(awk '$4 == "RRSIG" { print $9 }' dig.out.test$n) +inception=$(awk '$4 == "RRSIG" { print $10 }' dig.out.test$n) +$PERL -e 'exit(0) if ("'"$time"'" lt "'"$expire"'" && "'"$time"'" gt "'"$inception"'"); exit(1);' || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that split rrsigs are handled ($n)" +ret=0 +dig_with_opts split-rrsig soa @10.53.0.7 >dig.out.test$n || ret=1 +awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that not-at-zone-apex RRSIG(SOA) RRsets are removed from the zone after load ($n)" +ret=0 +dig_with_opts split-rrsig AXFR @10.53.0.7 >dig.out.test$n || ret=1 +grep -q "not-at-zone-apex.*RRSIG.*SOA" dig.out.test$n && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)" +ret=0 +alg=1 +until test $alg -eq 256; do + zone="keygen-$alg." + case $alg in + 2) # Diffie Helman + alg=$((alg + 1)) + continue + ;; + 157 | 160 | 161 | 162 | 163 | 164 | 165) # private - non standard + alg=$((alg + 1)) + continue + ;; + 1 | 5 | 7 | 8 | 10) # RSA algorithms + key1=$($KEYGEN -a "$alg" -b "2048" -n zone "$zone" 2>"keygen-$alg.err" || true) + ;; + 15 | 16) + key1=$($KEYGEN -a "$alg" -n zone "$zone" 2>"keygen-$alg.err" || true) + ;; + *) + key1=$($KEYGEN -a "$alg" -n zone "$zone" 2>"keygen-$alg.err" || true) + ;; + esac + if grep "unsupported algorithm" "keygen-$alg.err" >/dev/null; then + alg=$((alg + 1)) + continue + fi + if test -z "$key1"; then + echo_i "'$KEYGEN -a $alg': failed" + cat "keygen-$alg.err" + ret=1 + alg=$((alg + 1)) + continue + fi + $SETTIME -I now+4d "$key1.private" >/dev/null + key2=$($KEYGEN -v 10 -i 3d -S "$key1.private" 2>/dev/null) + test -f "$key2.key" -a -f "$key2.private" || { + ret=1 + echo_i "'dnssec-keygen -S' failed for algorithm: $alg" + } + alg=$((alg + 1)) +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'dnssec-keygen -F' disables rsasha1 ($n)" +ret=0 +if $FEATURETEST --have-fips-mode; then + echo_i "skipped: already in FIPS mode" +elif ! $FEATURETEST --fips-provider; then + echo_i "skipped no FIPS provider available" +elif [ $RSASHA1_SUPPORTED = 0 ]; then + echo_i "skipped: RSASHA1 is not supported" +else + $KEYGEN -F -a rsasha1 example.fips 2>keygen.err$n || true + grep -i "unsupported algorithm: RSASHA1" "keygen.err$n" >/dev/null || ret=1 +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that 'dnssec-keygen -F' disables nsec3rsasha1 ($n)" +ret=0 +if $FEATURETEST --have-fips-mode; then + echo_i "skipped: already in FIPS mode" +elif ! $FEATURETEST --fips-provider; then + echo_i "skipped: cannot switch to FIPS mode" +elif [ $RSASHA1_SUPPORTED = 0 ]; then + echo_i "skipped: RSASHA1 is not supported" +else + $KEYGEN -F -a nsec3rsasha1 example.fips 2>keygen.err$n || true + grep -i "unsupported algorithm: NSEC3RSASHA1" "keygen.err$n" >/dev/null || ret=1 +fi +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cds cds.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDS records are not signed using ZSK by dnssec-signzone -x ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cds cds-x.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDS records are signed using KSK by with dnssec-policy ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a CDS deletion record is accepted ($n)" +ret=0 +( + echo zone cds-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cds-update.secure CDS + echo update add cds-update.secure 0 CDS 0 0 0 00 + echo send +) | $NSUPDATE >nsupdate.out.test$n 2>&1 +dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure >dig.out.test$n +lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l) +test "${lines:-10}" -eq 1 || ret=1 +lines=$(awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDS records are signed only using KSK when added by nsupdate ($n)" +ret=0 +keyid=$(cat ns2/cds-update.secure.id) +( + echo zone cds-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cds-update.secure CDS + echo send + dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure \ + | grep "DNSKEY.257" \ + | $DSFROMKEY -12 -C -f - -T 1 cds-update.secure \ + | sed "s/^/update add /" + echo send +) | $NSUPDATE +dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDS deletion records are signed only using KSK when added by nsupdate ($n)" +ret=0 +keyid=$(cat ns2/cds-update.secure.id) +( + echo zone cds-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cds-update.secure CDS + echo update add cds-update.secure 0 CDS 0 0 0 00 + echo send +) | $NSUPDATE +dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDS" && $11 == id {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDS" && $5 == "0" && $6 == "0" && $7 == "0" && $8 == "00" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)" +ret=0 +( + echo zone cds-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cds-update.secure CDS + echo send + dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure \ + | grep "DNSKEY.257" \ + | $DSFROMKEY -12 -C -f - -T 1 cds-update.secure \ + | sed "s/^/update add /" + dig_with_opts +noall +answer @10.53.0.2 dnskey cds-update.secure \ + | grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' \ + | $DSFROMKEY -12 -C -A -f - -T 1 cds-update.secure \ + | sed "s/^/update add /" + echo send +) | $NSUPDATE +dig_with_opts +noall +answer @10.53.0.2 cds cds-update.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDS" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 4 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDNSKEY records are not signed using ZSK by dnssec-signzone -x ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-x.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)" +ret=0 +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that unsupported DNSKEY algorithm validates as insecure ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 dnskey-unsupported.example/SOA)" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking EDE code 2 for unsupported DS digest ($n)" +ret=0 +dig_with_opts @10.53.0.4 a.ds-unsupported.example >dig.out.ns4.test$n || ret=1 +grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-256 ds-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking EDE code 1 for bad alg mnemonic ($n)" +ret=0 +dig_with_opts @10.53.0.4 badalg.secure.example >dig.out.ns4.test$n || ret=1 +grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/A)" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking both EDE code 1 and 2 for unsupported digest on one DNSKEY and alg on the other ($n)" +ret=0 +dig_with_opts @10.53.0.4 a.digest-alg-unsupported.example >dig.out.ns4.test$n || ret=1 +grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP384SHA384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 +grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY >dig.out.test$n +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check that a query for a domain that has a KSK that is not actively signing +# the DNSKEY RRset. This should not result in a broken trust chain if there is +# another KSK that is signing the DNSKEY RRset. +echo_i "checking that a secure chain with one active and one inactive KSK validates as secure ($n)" +ret=0 +dig_with_opts @10.53.0.4 a.lazy-ksk A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# TODO: test case for GL #1689. +# If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5) +# we could write a test that signs a zone with supported and unsupported +# algorithm, apply a fixed rrset order such that the unsupported algorithm +# precedes the supported one in the DNSKEY RRset, and verify the result still +# validates succesfully. + +echo_i "check that a CDNSKEY deletion record is accepted ($n)" +ret=0 +( + echo zone cdnskey-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cdnskey-update.secure CDNSKEY + echo update add cdnskey-update.secure 0 CDNSKEY 0 3 0 AA== + echo send +) | $NSUPDATE >nsupdate.out.test$n 2>&1 +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure >dig.out.test$n +lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "${lines:-10}" -eq 1 || ret=1 +lines=$(awk '$4 == "CDNSKEY" && $5 == "0" && $6 == "3" && $7 == "0" && $8 == "AA==" {print}' dig.out.test$n | wc -l) +test "${lines:-10}" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)" +ret=0 +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A >dig.out.ns3.test$n +dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A >dig.out.ns4.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that CDNSKEY records are signed using KSK only when added by nsupdate ($n)" +ret=0 +keyid=$(cat ns2/cdnskey-update.secure.id) +( + echo zone cdnskey-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cdnskey-update.secure CDNSKEY + dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure \ + | sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p' + echo send +) | $NSUPDATE +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk -v id="${keyid}" '$4 == "RRSIG" && $5 == "CDNSKEY" && $11 == id {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking initialization with a revoked managed key ($n)" +ret=0 +copy_setports ns5/named2.conf.in ns5/named.conf +rndccmd 10.53.0.5 reconfig 2>&1 | sed 's/^/ns5 /' | cat_i +sleep 3 +dig_with_opts +dnssec @10.53.0.5 SOA . >dig.out.ns5.test$n +grep "status: SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a non matching CDNSKEY record is accepted with a matching CDNSKEY record ($n)" +ret=0 +( + echo zone cdnskey-update.secure + echo server 10.53.0.2 "$PORT" + echo update delete cdnskey-update.secure CDNSKEY + dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure \ + | sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p' + dig_with_opts +noall +answer @10.53.0.2 dnskey cdnskey-update.secure \ + | sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p' + echo send +) | $NSUPDATE +dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure >dig.out.test$n +lines=$(awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +lines=$(awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l) +test "$lines" -eq 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that RRSIGs are correctly removed from apex when RRset is removed NSEC ($n)" +ret=0 +# generate signed zone with MX and AAAA records at apex. +( + cd signer || exit 1 + $KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fK remove >/dev/null + $KEYGEN -q -a $DEFAULT_ALGORITHM -33 remove >/dev/null + echo >remove.db.signed + $SIGNER -S -o remove -D -f remove.db.signed remove.db.in >signer.out.1.$n +) +grep "RRSIG MX" signer/remove.db.signed >/dev/null || { + ret=1 + cp signer/remove.db.signed signer/remove.db.signed.pre$n +} +# re-generate signed zone without MX and AAAA records at apex. +( + cd signer || exit 1 + $SIGNER -S -o remove -D -f remove.db.signed remove2.db.in >signer.out.2.$n +) +grep "RRSIG MX" signer/remove.db.signed >/dev/null && { + ret=1 + cp signer/remove.db.signed signer/remove.db.signed.post$n +} +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that RRSIGs are correctly removed from apex when RRset is removed NSEC3 ($n)" +ret=0 +# generate signed zone with MX and AAAA records at apex. +( + cd signer || exit 1 + echo >remove.db.signed + $SIGNER -3 - -S -o remove -D -f remove.db.signed remove.db.in >signer.out.1.$n +) +grep "RRSIG MX" signer/remove.db.signed >/dev/null || { + ret=1 + cp signer/remove.db.signed signer/remove.db.signed.pre$n +} +# re-generate signed zone without MX and AAAA records at apex. +( + cd signer || exit 1 + $SIGNER -3 - -S -o remove -D -f remove.db.signed remove2.db.in >signer.out.2.$n +) +grep "RRSIG MX" signer/remove.db.signed >/dev/null && { + ret=1 + cp signer/remove.db.signed signer/remove.db.signed.post$n +} +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)" +ret=0 +dig_with_opts managed-future.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that trust-anchor-telemetry queries are logged ($n)" +ret=0 +grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns6/named.run >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that _ta-XXXX trust-anchor-telemetry queries are logged ($n)" +ret=0 +grep "trust-anchor-telemetry '_ta-[0-9a-f]*/IN' from" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that _ta-AAAA trust-anchor-telemetry are not sent when disabled ($n)" +ret=0 +grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/IN" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that KEY-TAG trust-anchor-telemetry queries are logged ($n)" +ret=0 +dig_with_opts . dnskey +ednsopt=KEY-TAG:ffff @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "trust-anchor-telemetry './IN' from .* 65535" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that multiple KEY-TAG trust-anchor-telemetry options don't leak memory ($n)" +ret=0 +dig_with_opts . dnskey +ednsopt=KEY-TAG:fffe +ednsopt=KEY-TAG:fffd @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "trust-anchor-telemetry './IN' from .* 65534" ns1/named.run >/dev/null || ret=1 +grep "trust-anchor-telemetry './IN' from .* 65533" ns1/named.run >/dev/null && ret=1 +stop_server ns1 || ret=1 +nextpart ns1/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns1 || ret=1 +n=$(($n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "waiting for root server to finish reloading ($n)" +ret=0 +wait_for_log 20 "all zones loaded" ns1/named.run || ret=1 +n=$(($n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that the view is logged in messages from the validator when using views ($n)" +ret=0 +grep "view rec: *validat" ns4/named.run >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)" +ret=0 +dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "RRSIG.NSEC3 $DEFAULT_ALGORITHM_NUMBER 3 600" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "check that DNSKEY and other occluded data are excluded from the delegating bitmap ($n)" +ret=0 +dig_with_opts axfr occluded.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "^delegation.occluded.example..*NSEC.*NS KEY DS RRSIG NSEC$" dig.out.ns3.test$n >/dev/null || ret=1 +grep "^delegation.occluded.example..*DNSKEY.*" dig.out.ns3.test$n >/dev/null || ret=1 +grep "^delegation.occluded.example..*AAAA.*" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking DNSSEC records are occluded from ANY in an insecure zone ($n)" +ret=0 +dig_with_opts any x.insecure.example. @10.53.0.3 >dig.out.ns3.1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.1.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns3.1.test$n >/dev/null || ret=1 +dig_with_opts any z.secure.example. @10.53.0.3 >dig.out.ns3.2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.2.test$n >/dev/null || ret=1 +# A+RRSIG, NSEC+RRSIG +grep "ANSWER: 4," dig.out.ns3.2.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# DNSSEC tests related to unsupported, disabled and revoked trust anchors. +# + +# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of +# them are good (enabled.managed, enabled.trusted, secure.managed, +# secure.trusted), and some of them are bad (disabled.managed, +# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted, +# unsupported.trusted). Make sure that the bad trust anchors are ignored. +# This is tested by looking for the corresponding lines in the logfile. +echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)" +ret=0 +grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1 +grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1 +grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# The next two tests are fairly normal DNSSEC queries to signed zones with a +# default algorithm. First, a query is made against the server that is +# authoritative for the given zone (ns3). Second, a query is made against a +# resolver with trust anchors for the given zone (ns8). Both are expected to +# return an authentic data positive response. +echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.secure.trusted A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.secure.trusted A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 +grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a managed key using a supported algorithm validates as secure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.secure.managed A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.secure.managed A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 +grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# The next two queries ensure that a zone signed with a DNSKEY with an unsupported +# algorithm will yield insecure positive responses. These trust anchors in ns8 are +# ignored and so this domain is treated as insecure. The AD bit should not be set +# in the response. +echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.unsupported.trusted A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.unsupported.trusted A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.trusted (cached))" dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.unsupported.managed A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.unsupported.managed A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.managed (cached))" dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# The next two queries ensure that a zone signed with a DNSKEY that the nameserver +# has a disabled algorithm match for will yield insecure positive responses. +# These trust anchors in ns8 are ignored and so this domain is treated as insecure. +# The AD bit should not be set in the response. +echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.disabled.trusted A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.disabled.trusted A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.disabled.managed A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.disabled.managed A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# The next two queries ensure that a zone signed with a DNSKEY that the +# nameserver has a disabled algorithm for, but for a different domain, will +# yield secure positive responses. Since "enabled.trusted." and +# "enabled.managed." do not match the "disable-algorithms" option, no +# special rules apply and these zones should validate as secure, with the AD +# bit set. +echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.enabled.trusted A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.enabled.trusted A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.enabled.managed A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.enabled.managed A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# A configured revoked trust anchor is ignored and thus the two queries below +# should result in insecure responses, since no trust points for the +# "revoked.trusted." and "revoked.managed." zones are created. +echo_i "checking that a trusted key that is revoked validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.revoked.trusted A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.revoked.trusted A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that a managed key that is revoked validates as insecure ($n)" +ret=0 +dig_with_opts @10.53.0.3 a.revoked.managed A >dig.out.ns3.test$n +dig_with_opts @10.53.0.8 a.revoked.managed A >dig.out.ns8.test$n +grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 +grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +### +### Additional checks for when the KSK is offline. +### + +# Save some useful information +zone="updatecheck-kskonly.secure" +KSK=$(cat ns2/${zone}.ksk.key) +ZSK=$(cat ns2/${zone}.zsk.key) +KSK_ID=$(cat ns2/${zone}.ksk.id) +ZSK_ID=$(cat ns2/${zone}.zsk.id) +SECTIONS="+answer +noauthority +noadditional" +echo_i "testing zone $zone KSK=$KSK_ID ZSK=$ZSK_ID" + +# Set key state for KSK. The ZSK rollovers below assume that there is a chain +# of trust established, so we tell named that the DS is in omnipresent state. +$SETTIME -s -d OMNIPRESENT now -K ns2 $KSK >/dev/null + +# Print IDs of keys used for generating RRSIG records for RRsets of type $1 +# found in dig output file $2. +get_keys_which_signed() { + qtype=$1 + output=$2 + # The key ID is the 11th column of the RRSIG record line. + awk -v qt="$qtype" '$4 == "RRSIG" && $5 == qt {print $11}' <"$output" +} + +# Basic checks to make sure everything is fine before the KSK is made offline. +for qtype in "DNSKEY" "CDNSKEY" "CDS"; do + echo_i "checking $qtype RRset is signed with KSK only ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +echo_i "checking SOA RRset is signed with ZSK only ($n)" +ret=0 +dig_with_opts $SECTIONS @10.53.0.2 soa $zone >dig.out.test$n +lines=$(get_keys_which_signed "SOA" dig.out.test$n | wc -l) +test "$lines" -eq 1 || ret=1 +get_keys_which_signed "SOA" dig.out.test$n | grep "^$KSK_ID$" >/dev/null && ret=1 +get_keys_which_signed "SOA" dig.out.test$n | grep "^$ZSK_ID$" >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Roll the ZSK. +zsk2=$("$KEYGEN" -q -P none -A none -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone") +keyfile_to_key_id "$zsk2" >ns2/$zone.zsk.id2 +ZSK_ID2=$(cat ns2/$zone.zsk.id2) +ret=0 +echo_i "prepublish new ZSK $ZSK_ID2 for $zone ($n)" +rndccmd 10.53.0.2 dnssec -rollover -key $ZSK_ID $zone 2>&1 | sed 's/^/ns2 /' | cat_i +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +zsk_count_equals() { + expectedzsks=$1 + dig_with_opts @10.53.0.2 DNSKEY $zone >dig.out.test$n + lines=$(cat dig.out.test$n | grep "DNSKEY.*256 3 13" | wc -l) + test "$lines" -eq $expectedzsks || return 1 +} +echo_i "check DNSKEY RRset has successor ZSK $ZSK_ID2 ($n)" +ret=0 +# The expected number of ZSKs is 2. +retry_quiet 5 zsk_count_equals 2 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Make new ZSK active. +echo_i "make ZSK $ZSK_ID inactive and make new ZSK $ZSK_ID2 active for zone $zone ($n)" +ret=0 +$SETTIME -s -I now -K ns2 $ZSK >/dev/null +$SETTIME -s -k OMNIPRESENT now -A now -K ns2 $zsk2 >/dev/null +dnssec_loadkeys_on 2 $zone || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Wait for newest ZSK to become active. +echo_i "wait until new ZSK $ZSK_ID2 active and ZSK $ZSK_ID inactive" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID2 (ZSK) is now active" ns2/named.run >/dev/null || ret=1 + grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID (ZSK) is now inactive" ns2/named.run >/dev/null || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Remove the KSK from disk. +echo_i "remove the KSK $KSK_ID for zone $zone from disk" +mv ns2/$KSK.key ns2/$KSK.key.bak +mv ns2/$KSK.private ns2/$KSK.private.bak + +# Update the zone that requires a resign of the SOA RRset. +echo_i "update the zone with $zone IN TXT nsupdate added me" +( + echo zone $zone + echo server 10.53.0.2 "$PORT" + echo update add $zone. 300 in txt "nsupdate added me" + echo send +) | $NSUPDATE + +# Redo the tests now that the zone is updated and the KSK is offline. +for qtype in "DNSKEY" "CDNSKEY" "CDS"; do + echo_i "checking $qtype RRset is signed with KSK only, KSK offline ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null && ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +for qtype in "SOA" "TXT"; do + echo_i "checking $qtype RRset is signed with new ZSK $ZSK_ID2 only, KSK offline ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +# Put back the KSK. +echo_i "put back the KSK $KSK_ID for zone $zone from disk" +mv ns2/$KSK.key.bak ns2/$KSK.key +mv ns2/$KSK.private.bak ns2/$KSK.private + +# Roll the ZSK again. +zsk3=$("$KEYGEN" -q -P none -A none -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -K ns2 -n zone "$zone") +ret=0 +keyfile_to_key_id "$zsk3" >ns2/$zone.zsk.id3 +ZSK_ID3=$(cat ns2/$zone.zsk.id3) +echo_i "delete old ZSK $ZSK_ID, schedule ZSK $ZSK_ID2 inactive, and pre-publish ZSK $ZSK_ID3 for zone $zone ($n)" +$SETTIME -s -k HIDDEN now -z HIDDEN now -D now -K ns2 $ZSK >/dev/null +$SETTIME -s -k OMNIPRESENT now -z OMNIPRESENT now -K ns2 $zsk2 >/dev/null +dnssec_loadkeys_on 2 $zone || ret=1 +rndccmd 10.53.0.2 dnssec -rollover -key $ZSK_ID2 $zone 2>&1 | sed 's/^/ns2 /' | cat_i +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Wait for newest ZSK to become published. +echo_i "wait until new ZSK $ZSK_ID3 published" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID3 (ZSK) is now published" ns2/named.run >/dev/null || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Remove the KSK from disk. +echo_i "remove the KSK $KSK_ID for zone $zone from disk" +mv ns2/$KSK.key ns2/$KSK.key.bak +mv ns2/$KSK.private ns2/$KSK.private.bak + +# Update the zone that requires a resign of the SOA RRset. +echo_i "update the zone with $zone IN TXT nsupdate added me again" +( + echo zone $zone + echo server 10.53.0.2 "$PORT" + echo update add $zone. 300 in txt "nsupdate added me again" + echo send +) | $NSUPDATE + +# Redo the tests now that the ZSK roll has deleted the old key. +for qtype in "DNSKEY" "CDNSKEY" "CDS"; do + echo_i "checking $qtype RRset is signed with KSK only, old ZSK deleted ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" >/dev/null && ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +for qtype in "SOA" "TXT"; do + echo_i "checking $qtype RRset is signed with ZSK $ZSK_ID2 only, old ZSK deleted ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" >/dev/null && ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +# Put back the KSK. +echo_i "put back the KSK $KSK_ID for zone $zone from disk" +mv ns2/$KSK.key.bak ns2/$KSK.key +mv ns2/$KSK.private.bak ns2/$KSK.private + +# Make the new ZSK (ZSK3) active. +echo_i "make new ZSK $ZSK_ID3 active for zone $zone ($n)" +ret=0 +$SETTIME -s -I now -K ns2 $zsk2 >/dev/null +$SETTIME -s -k OMNIPRESENT now -A now -K ns2 $zsk3 >/dev/null +dnssec_loadkeys_on 2 $zone || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Wait for newest ZSK to become active. +echo_i "wait until new ZSK $ZSK_ID3 active and ZSK $ZSK_ID2 inactive" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID3 (ZSK) is now active" ns2/named.run >/dev/null || ret=1 + grep "DNSKEY $zone/$DEFAULT_ALGORITHM/$ZSK_ID2 (ZSK) is now inactive" ns2/named.run >/dev/null || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Remove the KSK from disk. +echo_i "remove the KSK $KSK_ID for zone $zone from disk" +mv ns2/$KSK.key ns2/$KSK.key.bak +mv ns2/$KSK.private ns2/$KSK.private.bak + +# Update the zone that requires a resign of the SOA RRset. +echo_i "update the zone with $zone IN TXT nsupdate added me one more time" +( + echo zone $zone + echo server 10.53.0.2 "$PORT" + echo update add $zone. 300 in txt "nsupdate added me one more time" + echo send +) | $NSUPDATE +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Redo the tests one more time. +for qtype in "DNSKEY" "CDNSKEY" "CDS"; do + echo_i "checking $qtype RRset is signed with KSK only, new ZSK active ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" >/dev/null && ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +for qtype in "SOA" "TXT"; do + echo_i "checking $qtype RRset is signed with new ZSK $ZSK_ID3 only, new ZSK active ($n)" + ret=0 + dig_with_opts $SECTIONS @10.53.0.2 $qtype $zone >dig.out.test$n + lines=$(get_keys_which_signed $qtype dig.out.test$n | wc -l) + test "$lines" -eq 1 || ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$KSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID2$" >/dev/null && ret=1 + get_keys_which_signed $qtype dig.out.test$n | grep "^$ZSK_ID3$" >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +done + +echo_i "checking secroots output with multiple views ($n)" +ret=0 +rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i +cp ns4/named.secroots named.secroots.test$n +check_secroots_layout named.secroots.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking signatures-validity second field hours vs days ($n)" +ret=0 +# zone configured with 'signatures-validity 500d; signatures-refresh 1d' +# 499 days in the future w/ a 20 minute runtime to now allowance +min=$(TZ=UTC $PERL -e '@lt=localtime(time() + 499*3600*24 - 20*60); printf "%.4d%0.2d%0.2d%0.2d%0.2d%0.2d\n",$lt[5]+1900,$lt[4]+1,$lt[3],$lt[2],$lt[1],$lt[0];') +dig_with_opts @10.53.0.2 hours-vs-days AXFR >dig.out.ns2.test$n +awk -v min=$min '$4 == "RRSIG" { if ($9 < min) { exit(1); } }' dig.out.ns2.test$n || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking validation succeeds during transition to signed ($n)" +ret=0 +dig_with_opts @10.53.0.4 inprogress A >dig.out.ns4.test$n || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep 'A.10\.53\.0\.10' dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking excessive NSEC3 iteration warnings in named.run ($n)" +ret=0 +grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns2/named.run >/dev/null 2>&1 || ret=1 +grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns3/named.run >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check that the validating resolver will fallback to insecure if the answer +# contains NSEC3 records with high iteration count. +echo_i "checking fallback to insecure when NSEC3 iterations is too high (nxdomain) ($n)" +ret=0 +dig_with_opts @10.53.0.2 does-not-exist.too-many-iterations >dig.out.ns2.test$n || ret=1 +dig_with_opts @10.53.0.4 does-not-exist.too-many-iterations >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking fallback to insecure when NSEC3 iterations is too high (nodata) ($n)" +ret=0 +dig_with_opts @10.53.0.2 a.too-many-iterations txt >dig.out.ns2.test$n || ret=1 +dig_with_opts @10.53.0.4 a.too-many-iterations txt >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 4" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard) ($n)" +ret=0 +dig_with_opts @10.53.0.2 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1 +dig_with_opts @10.53.0.4 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep 'wild\.a\.too-many-iterations\..*A.10\.0\.0\.3' dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2, AUTHORITY: 4" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard nodata) ($n)" +ret=0 +dig_with_opts @10.53.0.2 type100 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1 +dig_with_opts @10.53.0.4 type100 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1 +digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Check that a query against a validating resolver succeeds when there is +# a negative cache entry with trust level "pending" for the DS. Prime +# with a +cd DS query to produce the negative cache entry, then send a +# query that uses that entry as part of the validation process. [GL #3279] +echo_i "check that pending negative DS cache entry validates ($n)" +ret=0 +dig_with_opts @10.53.0.4 +cd insecure2.example. ds >dig.out.prime.ns4.test$n || ret=1 +grep "flags: qr rd ra cd;" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 0, AUTHORITY: 4, " dig.out.prime.ns4.test$n >/dev/null || ret=1 +dig_with_opts @10.53.0.4 a.insecure2.example. a >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 1, AUTHORITY: 1, " dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that dnssec-keygen honours key tag ranges ($n)" +ret=0 +zone=settagrange +ksk=$("$KEYGEN" -f KSK -q -a $DEFAULT_ALGORITHM -n zone -M 0:32767 "$zone") +zsk=$("$KEYGEN" -q -a $DEFAULT_ALGORITHM -n zone -M 32768:65535 "$zone") +kid=$(keyfile_to_key_id "$ksk") +zid=$(keyfile_to_key_id "$zsk") +[ $kid -ge 0 -a $kid -le 32767 ] || ret=1 +[ $zid -ge 32768 -a $zid -le 65535 ] || ret=1 +rksk=$($REVOKE -R $ksk) +rzsk=$($REVOKE -R $zsk) +krid=$(keyfile_to_key_id "$rksk") +zrid=$(keyfile_to_key_id "$rzsk") +[ $krid -ge 0 -a $krid -le 32767 ] || ret=1 +[ $zrid -ge 32768 -a $zrid -le 65535 ] || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that records other than DNSKEY are not signed by a revoked key by dnssec-signzone ($n)" +ret=0 +( + cd signer || exit 0 + key1=$(${KEYGEN} -a "${DEFAULT_ALGORITHM}" -f KSK revoke.example) + key2=$(${KEYGEN} -a "${DEFAULT_ALGORITHM}" -f KSK revoke.example) + key3=$(${KEYGEN} -a "${DEFAULT_ALGORITHM}" revoke.example) + rkey=$(${REVOKE} "$key2") + cat >>revoke.example.db <>revoke.example.db + "${SIGNER}" -o revoke.example revoke.example.db >signer.out.$n +) || ret=1 +keycount=$(grep -c "RRSIG.DNSKEY ${DEFAULT_ALGORITHM_NUMBER} " signer/revoke.example.db.signed) +cdscount=$(grep -c "RRSIG.CDS ${DEFAULT_ALGORITHM_NUMBER} " signer/revoke.example.db.signed) +soacount=$(grep -c "RRSIG.SOA ${DEFAULT_ALGORITHM_NUMBER} " signer/revoke.example.db.signed) +[ $keycount -eq 3 ] || ret=1 +[ $cdscount -eq 2 ] || ret=1 +[ $soacount -eq 1 ] || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking validator behavior with mismatching NS ($n)" +ret=0 +rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i +$DIG +tcp +cd -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 +grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.1 >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.1 >/dev/null && ret=1 +$DIG +tcp +cd +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 +grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.2 >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.2 >/dev/null && ret=1 +$DIG +tcp +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 +grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns4.test$n.3 >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.3 >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that a insecure negative response where there is a NSEC without a RRSIG succeeds ($n)" +ret=0 +# check server preconditions +dig_with_opts +notcp @10.53.0.10 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns10.test$n +grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 +grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns10.test$n >/dev/null || ret=1 +grep "IN.RRSIG.NSEC" dig.out.ns10.test$n >/dev/null && ret=1 +# check resolver succeeds +dig_with_opts @10.53.0.4 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns4.test$n +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns4.test$n >/dev/null || ret=1 +grep "IN.RRSIG.NSEC" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NSEC3 nxdomain response closest encloser with 0 ENT ($n)" +ret=0 +dig_with_opts @10.53.0.3 b.b.b.b.b.a.nsec3.example. >dig.out.ns3.test$n +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +pat="^6OVDUHTN094ML2PV8AN90U0DPU823GH2\.nsec3.example\..*NSEC3 1 0 0 - 7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4 A RRSIG\$" +grep "$pat" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NSEC3 nxdomain response closest encloser with 1 ENTs ($n)" +ret=0 +dig_with_opts @10.53.0.3 b.b.b.b.b.a.a.nsec3.example. >dig.out.ns3.test$n +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +pat="^NGCJFSOLJUUE27PFNQNJIME4TQ0OU2DH\.nsec3.example\..*NSEC3 1 0 0 - R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\$" +grep "$pat" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking NSEC3 nxdomain response closest encloser with 2 ENTs ($n)" +ret=0 +dig_with_opts @10.53.0.3 b.b.b.b.b.a.a.a.nsec3.example. >dig.out.ns3.test$n +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +pat="^H7RHPDCHSVVRAND332F878C8AB6IBJQV\.nsec3.example\..*NSEC3 1 0 0 - K8IG76R2UPQ13IKFO49L7IB9JRVB6QJI\$" +grep "$pat" dig.out.ns3.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dnssec/tests_sh_dnssec.py b/bin/tests/system/dnssec/tests_sh_dnssec.py new file mode 100644 index 0000000..c76bc9f --- /dev/null +++ b/bin/tests/system/dnssec/tests_sh_dnssec.py @@ -0,0 +1,174 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "K*", + "canonical*", + "delv.out*", + "dig.out.*", + "dnssectools.out.*", + "dsfromkey.out.*", + "keygen*.err*", + "named.secroots.*", + "nsupdate.out.*", + "python.out.*", + "rndc.out.*", + "signing.out.*", + "*/K*", + "*/dsset-*", + "*/managed.conf", + "*/trusted.conf", + "*/*.bk", + "*/*.jnl", + "*/*.jbk", + "*/*.signed", + "*/*.mkeys*", + "ans*/ans.run", + "ans*/query.log", + "ns1/managed.key.id", + "ns1/root.db", + "ns1/trusted.keys", + "ns2/algroll.db", + "ns2/badparam.db", + "ns2/badparam.db.bad", + "ns2/cdnskey-update.secure.db", + "ns2/cdnskey-update.secure.id", + "ns2/cdnskey-x.secure.db", + "ns2/cdnskey.secure.db", + "ns2/cds-update.secure.db", + "ns2/cds-update.secure.id", + "ns2/cds-x.secure.db", + "ns2/cds.secure.db", + "ns2/dnskey-rrsigs-stripped.db", + "ns2/dnskey-rrsigs-stripped.db.next", + "ns2/dnskey-rrsigs-stripped.db.stripped", + "ns2/child.ds-rrsigs-stripped.db", + "ns2/ds-rrsigs-stripped.db", + "ns2/ds-rrsigs-stripped.db.next", + "ns2/ds-rrsigs-stripped.db.stripped", + "ns2/example.db", + "ns2/in-addr.arpa.db", + "ns2/lazy-ksk.db", + "ns2/managed.db", + "ns2/nsec3chain-test.db", + "ns2/settime.out.updatecheck-kskonly.secure.ksk", + "ns2/settime.out.updatecheck-kskonly.secure.zsk", + "ns2/single-nsec3.db", + "ns2/too-many-iterations.db", + "ns2/inconsistent.db", + "ns2/trusted.db", + "ns2/updatecheck-kskonly.secure.ksk.id", + "ns2/updatecheck-kskonly.secure.ksk.key", + "ns2/updatecheck-kskonly.secure.zsk.id", + "ns2/updatecheck-kskonly.secure.zsk.id2", + "ns2/updatecheck-kskonly.secure.zsk.id3", + "ns2/updatecheck-kskonly.secure.zsk.key", + "ns3/NSEC", + "ns3/NSEC3", + "ns3/auto-nsec.example.db", + "ns3/auto-nsec3.example.db", + "ns3/badds.example.db", + "ns3/bogus.example.db", + "ns3/disabled.managed.db", + "ns3/disabled.trusted.db", + "ns3/dname-at-apex-nsec3.example.db", + "ns3/dnskey-nsec3-unknown.example.db", + "ns3/dnskey-nsec3-unknown.example.db.tmp", + "ns3/dnskey-unknown.example.db", + "ns3/dnskey-unknown.example.db.tmp", + "ns3/dnskey-unsupported-2.example.db", + "ns3/dnskey-unsupported.example.db", + "ns3/dnskey-unsupported.example.db.tmp", + "ns3/dynamic.example.db", + "ns3/digest-alg-unsupported.example.db", + "ns3/enabled.managed.db", + "ns3/enabled.trusted.db", + "ns3/example.bk", + "ns3/expired.example.db", + "ns3/expiring.example.db", + "ns3/future.example.db", + "ns3/keyless.example.db", + "ns3/kskonly.example.db", + "ns3/lower.example.db", + "ns3/managed-future.example.db", + "ns3/multiple.example.db", + "ns3/nsec3-unknown.example.db", + "ns3/nsec3.example.db", + "ns3/nsec3.nsec3.example.db", + "ns3/nsec3.optout.example.db", + "ns3/nsec3chain-test.bk", + "ns3/occluded.example.db", + "ns3/optout-unknown.example.db", + "ns3/optout.example.db", + "ns3/optout.nsec3.example.db", + "ns3/optout.optout.example.db", + "ns3/revkey.example.db", + "ns3/revoked.managed.db", + "ns3/revoked.trusted.db", + "ns3/rfc2335.example.bk", + "ns3/rsasha256.example.db", + "ns3/rsasha512.example.db", + "ns3/secure.below-cname.example.db", + "ns3/secure.example.db", + "ns3/secure.managed.db", + "ns3/secure.nsec3.example.db", + "ns3/secure.optout.example.db", + "ns3/secure.trusted.db", + "ns3/siginterval.conf", + "ns3/siginterval.example.db", + "ns3/split-dnssec.example.db", + "ns3/split-smart.example.db", + "ns3/trusted-future.key", + "ns3/ttlpatch.example.db", + "ns3/ttlpatch.example.db.patched", + "ns3/unsupported.managed.db", + "ns3/unsupported.managed.db.tmp", + "ns3/unsupported.trusted.db", + "ns3/unsupported.trusted.db.tmp", + "ns3/update-nsec3.example.db", + "ns3/update-nsec3.example.db.signed", + "ns3/upper.example.db", + "ns3/upper.example.db.lower", + "ns3/ds-unsupported.example.db", + "ns4/managed.conf", + "ns4/managed-keys.bind", + "ns4/named.secroots", + "ns4/named_dump.db.*", + "ns5/revoked.conf", + "ns5/trusted.conf", + "ns6/optout-tld.db", + "ns7/split-rrsig.db", + "ns7/split-rrsig.db.unsplit", + "signer/example.db", + "signer/example.db.after", + "signer/example.db.before", + "signer/example.db.changed", + "signer/example2.db", + "signer/example3.db", + "signer/general/dnskey.expect", + "signer/general/dsset-*", + "signer/general/signed.expect", + "signer/general/signed.zone", + "signer/general/signer.out.*", + "signer/nsec3param.out", + "signer/prepub.db", + "signer/revoke.example.db", + "signer/signer.err.*", + "signer/signer.out.*", + ] +) + + +def test_dnssec(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/dnstap/README b/bin/tests/system/dnstap/README new file mode 100644 index 0000000..856fe48 --- /dev/null +++ b/bin/tests/system/dnstap/README @@ -0,0 +1,27 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The "large-answer.fstrm" file was generated by configuring a named instance +compiled with --enable-dnstap and --enable-fixed-rrset with the following +directives: + + minimal-responses yes; + rrset-order { order fixed; }; + dnstap { auth response; }; + dnstap-identity none; + dnstap-output file "large-answer.fstrm"; + +The captured RRset from the "example." zone was created using: + + $GENERATE 1-48 @ IN A 127.0.0.$ + +A server instance set up this way was then queried non-recursively (RD=0) for +"example/A". diff --git a/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf b/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf new file mode 100644 index 0000000..fd673d6 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-reopen-interval.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-reopen-interval 1x; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf new file mode 100644 index 0000000..cdab66b --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-max.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-buffer-hint 65537; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf new file mode 100644 index 0000000..c5444e9 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-buffer-hint-min.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-buffer-hint 1023; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf new file mode 100644 index 0000000..05ab1d9 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-max.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-flush-timeout 0; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf new file mode 100644 index 0000000..398b1ab --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-flush-timeout-min.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-flush-timeout 601; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf new file mode 100644 index 0000000..d6c4120 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-max.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-input-queue-size 1; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf new file mode 100644 index 0000000..787f656 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-min.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-input-queue-size 16385; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf new file mode 100644 index 0000000..ae713d3 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-input-queue-size-po2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-input-queue-size 513; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf new file mode 100644 index 0000000..643e2b8 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-output-notify-threshold.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-notify-threshold 0; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf new file mode 100644 index 0000000..853713f --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-max.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + /* + * This value is system dependent and matches IOV_MAX. + */ + fstrm-set-output-queue-size 10000000; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf new file mode 100644 index 0000000..7940c89 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-output-queue-size-min.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-queue-size 1; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf new file mode 100644 index 0000000..9cfa9e3 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-max.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-reopen-interval 601; +}; diff --git a/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf new file mode 100644 index 0000000..be6a640 --- /dev/null +++ b/bin/tests/system/dnstap/bad-fstrm-set-reopen-interval-min.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-reopen-interval 0; +}; diff --git a/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf b/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf new file mode 100644 index 0000000..853da36 --- /dev/null +++ b/bin/tests/system/dnstap/bad-missing-dnstap-output-view.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view "view" { + dnstap { client; auth; }; +}; diff --git a/bin/tests/system/dnstap/bad-missing-dnstap-output.conf b/bin/tests/system/dnstap/bad-missing-dnstap-output.conf new file mode 100644 index 0000000..b5565e2 --- /dev/null +++ b/bin/tests/system/dnstap/bad-missing-dnstap-output.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap { client; auth; }; + recursion yes; +}; diff --git a/bin/tests/system/dnstap/bad-size-version.conf b/bin/tests/system/dnstap/bad-size-version.conf new file mode 100644 index 0000000..8e31528 --- /dev/null +++ b/bin/tests/system/dnstap/bad-size-version.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap-output unix "/tmp/dnstap.sock" size 10k versions 3; +}; diff --git a/bin/tests/system/dnstap/good-dnstap-in-options.conf b/bin/tests/system/dnstap/good-dnstap-in-options.conf new file mode 100644 index 0000000..17feb5e --- /dev/null +++ b/bin/tests/system/dnstap/good-dnstap-in-options.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap-output unix "/var/run/named/dnstap.sock"; + dnstap-identity hostname; + dnstap { client response; }; +}; diff --git a/bin/tests/system/dnstap/good-dnstap-in-view.conf b/bin/tests/system/dnstap/good-dnstap-in-view.conf new file mode 100644 index 0000000..2c17f6c --- /dev/null +++ b/bin/tests/system/dnstap/good-dnstap-in-view.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap-output unix "/var/run/named/dnstap.sock"; + dnstap-identity hostname; +}; + +view "view" { + dnstap { client response; }; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf b/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf new file mode 100644 index 0000000..d525262 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-reopen-interval.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-reopen-interval 5m; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf b/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf new file mode 100644 index 0000000..c550647 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-buffer-hint.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-buffer-hint 8192; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf b/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf new file mode 100644 index 0000000..dd9abf0 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-flush-timeout.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-flush-timeout 1; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf b/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf new file mode 100644 index 0000000..d01b8f8 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-input-queue-size.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-input-queue-size 512; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf b/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf new file mode 100644 index 0000000..2619dc0 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-output-notify-threshold.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-notify-threshold 32; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf new file mode 100644 index 0000000..a81ff7c --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-mpsc.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-queue-model mpsc; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf new file mode 100644 index 0000000..7b394eb --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-model-spsc.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-queue-model spsc; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf b/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf new file mode 100644 index 0000000..87bf028 --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-output-queue-size.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-output-queue-size 64; +}; diff --git a/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf b/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf new file mode 100644 index 0000000..116d3ae --- /dev/null +++ b/bin/tests/system/dnstap/good-fstrm-set-reopen-interval.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + fstrm-set-reopen-interval 5; +}; diff --git a/bin/tests/system/dnstap/good-size-unlimited.conf b/bin/tests/system/dnstap/good-size-unlimited.conf new file mode 100644 index 0000000..8cb9712 --- /dev/null +++ b/bin/tests/system/dnstap/good-size-unlimited.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap-output file "/tmp/dnstap.log" + size unlimited versions unlimited suffix increment; +}; diff --git a/bin/tests/system/dnstap/good-size-version.conf b/bin/tests/system/dnstap/good-size-version.conf new file mode 100644 index 0000000..ca1fba3 --- /dev/null +++ b/bin/tests/system/dnstap/good-size-version.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + dnstap-output file "/tmp/dnstap.log" + size 10k versions 3 suffix timestamp; +}; diff --git a/bin/tests/system/dnstap/large-answer.fstrm b/bin/tests/system/dnstap/large-answer.fstrm new file mode 100644 index 0000000..873b315 Binary files /dev/null and b/bin/tests/system/dnstap/large-answer.fstrm differ diff --git a/bin/tests/system/dnstap/ns1/named.conf.j2 b/bin/tests/system/dnstap/ns1/named.conf.j2 new file mode 100644 index 0000000..daaf887 --- /dev/null +++ b/bin/tests/system/dnstap/ns1/named.conf.j2 @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + statistics-file "named.stats"; + dnstap-identity "ns1"; + dnstap-version "xxx"; + dnstap-output file "dnstap.out" size 30k versions 10; + dnstap { all; }; + send-cookie no; + require-server-cookie no; + dnssec-validation yes; + qname-minimization disabled; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/dnstap/ns1/root.db b/bin/tests/system/dnstap/ns1/root.db new file mode 100644 index 0000000..17780d1 --- /dev/null +++ b/bin/tests/system/dnstap/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/dnstap/ns2/example.db.j2 b/bin/tests/system/dnstap/ns2/example.db.j2 new file mode 100644 index 0000000..7f88dec --- /dev/null +++ b/bin/tests/system/dnstap/ns2/example.db.j2 @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns2.example. +ns2.example. A 10.53.0.2 + +$ORIGIN example. +a A 10.0.0.1 +a A 10.0.0.3 +a A 10.0.0.5 + MX 10 mail.example. + +mail A 10.0.0.2 diff --git a/bin/tests/system/dnstap/ns2/named.conf.j2 b/bin/tests/system/dnstap/ns2/named.conf.j2 new file mode 100644 index 0000000..12ae863 --- /dev/null +++ b/bin/tests/system/dnstap/ns2/named.conf.j2 @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + statistics-file "named.stats"; + dnstap-identity "ns2"; + dnstap-version "xxx"; + dnstap-output file "dnstap.out" size unlimited versions unlimited; + dnstap { all; }; + send-cookie no; + require-server-cookie no; + dnssec-validation yes; + qname-minimization disabled; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/dnstap/ns3/named.args b/bin/tests/system/dnstap/ns3/named.args new file mode 100644 index 0000000..47b682b --- /dev/null +++ b/bin/tests/system/dnstap/ns3/named.args @@ -0,0 +1,2 @@ +# Using "-n 1" allows GL #1795 to be reliably reproduced +-D dnstap-ns3 -m record -c named.conf -d 99 -g -n 1 -T maxcachesize=2097152 diff --git a/bin/tests/system/dnstap/ns3/named.conf.j2 b/bin/tests/system/dnstap/ns3/named.conf.j2 new file mode 100644 index 0000000..d443c38 --- /dev/null +++ b/bin/tests/system/dnstap/ns3/named.conf.j2 @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnstap-identity "ns3"; + dnstap-version "xxx"; + dnstap-output file "dnstap.out"; + dnstap { all; }; + send-cookie no; + require-server-cookie no; + minimal-responses no; + dnssec-validation yes; + qname-minimization disabled; +}; + +trust-anchors { }; + +server 10.53.0.1 { tcp-only yes; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/dnstap/ns4/named.conf.j2 b/bin/tests/system/dnstap/ns4/named.conf.j2 new file mode 100644 index 0000000..18c4da1 --- /dev/null +++ b/bin/tests/system/dnstap/ns4/named.conf.j2 @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnstap-identity "ns4"; + dnstap-version "xxx"; + dnstap-output unix "dnstap.out"; + dnstap { all; }; + send-cookie no; + require-server-cookie no; + dnssec-validation yes; + qname-minimization disabled; +}; + +trust-anchors { }; + +server 10.53.0.1 { tcp-only yes; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/dnstap/prereq.sh b/bin/tests/system/dnstap/prereq.sh new file mode 100644 index 0000000..747f448 --- /dev/null +++ b/bin/tests/system/dnstap/prereq.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --enable-dnstap || { + echo_i "This test requires dnstap support." >&2 + exit 255 +} +exit 0 diff --git a/bin/tests/system/dnstap/tests.sh b/bin/tests/system/dnstap/tests.sh new file mode 100644 index 0000000..261384f --- /dev/null +++ b/bin/tests/system/dnstap/tests.sh @@ -0,0 +1,864 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+short -p ${PORT}" +RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../_common/rndc.conf" + +status=0 + +# dnstap_data_ready +# Flushes capture_file and checks wheter its size is >= min_file_size. +dnstap_data_ready() { + # Process id of running fstrm_capture. + fstrm_capture_pid=$1 + # Output file provided to fstrm_capture via -w switch. + capture_file=$2 + # Minimum expected file size. + min_size_expected=$3 + + kill -HUP $fstrm_capture_pid + file_size=$(wc -c <"$capture_file" | tr -d ' ') + if [ $file_size -lt $min_size_expected ]; then + return 1 + fi +} + +for bad in bad-*.conf; do + ret=0 + echo_i "checking that named-checkconf detects error in $bad" + { + $CHECKCONF $bad >/dev/null 2>&1 + rc=$? + } || true + if [ $rc != 1 ]; then + echo_i "failed" + ret=1 + fi + status=$((status + ret)) +done + +for good in good-*.conf; do + ret=0 + echo_i "checking that named-checkconf detects no error in $good" + { + $CHECKCONF $good >/dev/null 2>&1 + rc=$? + } || true + if [ $rc != 0 ]; then + echo_i "failed" + ret=1 + fi + status=$((status + ret)) +done + +echo_i "wait for servers to finish loading" +ret=0 +wait_for_log 20 "all zones loaded" ns1/named.run || ret=1 +wait_for_log 20 "all zones loaded" ns2/named.run || ret=1 +wait_for_log 20 "all zones loaded" ns3/named.run || ret=1 +wait_for_log 20 "all zones loaded" ns4/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# both the 'a.example/A' lookup and the './NS' lookup to ns1 +# need to complete before reopening/rolling for the counts to +# be correct. + +echo_i "prime cache" +ret=0 +$DIG $DIGOPTS @10.53.0.3 a.example >dig.out || true +wait_for_log 20 "(.): reset client" ns1/named.run || true +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# check three different dnstap reopen/roll methods: +# ns1: dnstap-reopen; ns2: dnstap -reopen; ns3: dnstap -roll +mv ns1/dnstap.out ns1/dnstap.out.save +mv ns2/dnstap.out ns2/dnstap.out.save + +if [ -n "$FSTRM_CAPTURE" ]; then + ret=0 + echo_i "starting fstrm_capture" + $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \ + -w dnstap.out >fstrm_capture.out.1 2>&1 & + fstrm_capture_pid=$! + wait_for_log 10 "socket path ns4/dnstap.out" fstrm_capture.out.1 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "reopen/roll capture streams" +ret=0 +$RNDCCMD -s 10.53.0.1 dnstap-reopen | sed 's/^/ns1 /' | cat_i +$RNDCCMD -s 10.53.0.2 dnstap -reopen | sed 's/^/ns2 /' | cat_i +$RNDCCMD -s 10.53.0.3 dnstap -roll | sed 's/^/ns3 /' | cat_i +$RNDCCMD -s 10.53.0.4 dnstap -reopen | sed 's/^/ns4 /' | cat_i + +echo_i "send test traffic" +ret=0 +$DIG $DIGOPTS @10.53.0.3 a.example >dig.out || ret=1 + +# send an UPDATE to ns2 +$NSUPDATE <<-EOF +server 10.53.0.2 ${PORT} +zone example +update add b.example 3600 in a 10.10.10.10 +send +EOF + +# XXX: file output should be flushed once a second according +# to the libfstrm source, but it doesn't seem to happen until +# enough data has accumulated. to get all the output, we stop +# the name servers, forcing a flush on shutdown. it would be +# nice to find a better way to do this. +$RNDCCMD -s 10.53.0.1 stop | sed 's/^/ns1 /' | cat_i +$RNDCCMD -s 10.53.0.2 stop | sed 's/^/ns2 /' | cat_i +$RNDCCMD -s 10.53.0.3 stop | sed 's/^/ns3 /' | cat_i + +sleep 1 + +echo_i "checking initial message counts" + +udp1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UDP " | wc -l) +tcp1=$($DNSTAPREAD ns1/dnstap.out.save | grep "TCP " | wc -l) +aq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "AQ " | wc -l) +ar1=$($DNSTAPREAD ns1/dnstap.out.save | grep "AR " | wc -l) +cq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "CQ " | wc -l) +cr1=$($DNSTAPREAD ns1/dnstap.out.save | grep "CR " | wc -l) +rq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "RQ " | wc -l) +rr1=$($DNSTAPREAD ns1/dnstap.out.save | grep "RR " | wc -l) +uq1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UQ " | wc -l) +ur1=$($DNSTAPREAD ns1/dnstap.out.save | grep "UR " | wc -l) + +udp2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UDP " | wc -l) +tcp2=$($DNSTAPREAD ns2/dnstap.out.save | grep "TCP " | wc -l) +aq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "AQ " | wc -l) +ar2=$($DNSTAPREAD ns2/dnstap.out.save | grep "AR " | wc -l) +cq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "CQ " | wc -l) +cr2=$($DNSTAPREAD ns2/dnstap.out.save | grep "CR " | wc -l) +rq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "RQ " | wc -l) +rr2=$($DNSTAPREAD ns2/dnstap.out.save | grep "RR " | wc -l) +uq2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UQ " | wc -l) +ur2=$($DNSTAPREAD ns2/dnstap.out.save | grep "UR " | wc -l) + +mv ns3/dnstap.out.0 ns3/dnstap.out.save +udp3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UDP " | wc -l) +tcp3=$($DNSTAPREAD ns3/dnstap.out.save | grep "TCP " | wc -l) +aq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "AQ " | wc -l) +ar3=$($DNSTAPREAD ns3/dnstap.out.save | grep "AR " | wc -l) +cq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "CQ " | wc -l) +cr3=$($DNSTAPREAD ns3/dnstap.out.save | grep "CR " | wc -l) +rq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "RQ " | wc -l) +rr3=$($DNSTAPREAD ns3/dnstap.out.save | grep "RR " | wc -l) +uq3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UQ " | wc -l) +ur3=$($DNSTAPREAD ns3/dnstap.out.save | grep "UR " | wc -l) + +echo_i "checking UDP message counts" +ret=0 +[ $udp1 -eq 0 ] || { + echo_i "ns1 $udp1 expected 0" + ret=1 +} +[ $udp2 -eq 2 ] || { + echo_i "ns2 $udp2 expected 2" + ret=1 +} +[ $udp3 -eq 4 ] || { + echo_i "ns3 $udp3 expected 4" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TCP message counts" +ret=0 +[ $tcp1 -eq 6 ] || { + echo_i "ns1 $tcp1 expected 6" + ret=1 +} +[ $tcp2 -eq 2 ] || { + echo_i "ns2 $tcp2 expected 2" + ret=1 +} +[ $tcp3 -eq 6 ] || { + echo_i "ns3 $tcp3 expected 6" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AUTH_QUERY message counts" +ret=0 +[ $aq1 -eq 3 ] || { + echo_i "ns1 $aq1 exepcted 3" + ret=1 +} +[ $aq2 -eq 2 ] || { + echo_i "ns2 $aq2 expected 2" + ret=1 +} +[ $aq3 -eq 1 ] || { + echo_i "ns3 $aq3 expected 1" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AUTH_RESPONSE message counts" +ret=0 +[ $ar1 -eq 2 ] || { + echo_i "ns1 $ar1 expected 2" + ret=1 +} +[ $ar2 -eq 1 ] || { + echo_i "ns2 $ar2 expected 1" + ret=1 +} +[ $ar3 -eq 0 ] || { + echo_i "ns3 $ar3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking CLIENT_QUERY message counts" +ret=0 +[ $cq1 -eq 0 ] || { + echo_i "ns1 $cq1 expected 0" + ret=1 +} +[ $cq2 -eq 0 ] || { + echo_i "ns2 $cq2 expected 0" + ret=1 +} +[ $cq3 -eq 1 ] || { + echo_i "ns3 $cq3 expected 1" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking CLIENT_RESPONSE message counts" +ret=0 +[ $cr1 -eq 1 ] || { + echo_i "ns1 $cr1 expected 1" + ret=1 +} +[ $cr2 -eq 1 ] || { + echo_i "ns2 $cr2 expected 1" + ret=1 +} +[ $cr3 -eq 2 ] || { + echo_i "ns3 $cr3 expected 2" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking RESOLVER_QUERY message counts" +ret=0 +[ $rq1 -eq 0 ] || { + echo_i "ns1 $rq1 expected 0" + ret=1 +} +[ $rq2 -eq 0 ] || { + echo_i "ns2 $rq2 expected 0" + ret=1 +} +[ $rq3 -eq 3 ] || { + echo_i "ns3 $rq3 expected 3" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking RESOLVER_RESPONSE message counts" +ret=0 +[ $rr1 -eq 0 ] || { + echo_i "ns1 $rr1 expected 0" + ret=1 +} +[ $rr2 -eq 0 ] || { + echo_i "ns2 $rr2 expected 0" + ret=1 +} +[ $rr3 -eq 3 ] || { + echo_i "ns3 $rr3 expected 3" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking UPDATE_QUERY message counts" +ret=0 +[ $uq1 -eq 0 ] || { + echo_i "ns1 $uq1 expected 0" + ret=1 +} +[ $uq2 -eq 0 ] || { + echo_i "ns2 $uq2 expected 0" + ret=1 +} +[ $uq3 -eq 0 ] || { + echo_i "ns3 $uq3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking UPDATE_RESPONSE message counts" +ret=0 +[ $ur1 -eq 0 ] || { + echo_i "ns1 $ur1 expected 0" + ret=1 +} +[ $ur2 -eq 0 ] || { + echo_i "ns2 $ur2 expected 0" + ret=1 +} +[ $ur3 -eq 0 ] || { + echo_i "ns3 $ur3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking reopened message counts" + +udp1=$($DNSTAPREAD ns1/dnstap.out | grep "UDP " | wc -l) +tcp1=$($DNSTAPREAD ns1/dnstap.out | grep "TCP " | wc -l) +aq1=$($DNSTAPREAD ns1/dnstap.out | grep "AQ " | wc -l) +ar1=$($DNSTAPREAD ns1/dnstap.out | grep "AR " | wc -l) +cq1=$($DNSTAPREAD ns1/dnstap.out | grep "CQ " | wc -l) +cr1=$($DNSTAPREAD ns1/dnstap.out | grep "CR " | wc -l) +rq1=$($DNSTAPREAD ns1/dnstap.out | grep "RQ " | wc -l) +rr1=$($DNSTAPREAD ns1/dnstap.out | grep "RR " | wc -l) +uq1=$($DNSTAPREAD ns1/dnstap.out | grep "UQ " | wc -l) +ur1=$($DNSTAPREAD ns1/dnstap.out | grep "UR " | wc -l) + +udp2=$($DNSTAPREAD ns2/dnstap.out | grep "UDP " | wc -l) +tcp2=$($DNSTAPREAD ns2/dnstap.out | grep "TCP " | wc -l) +aq2=$($DNSTAPREAD ns2/dnstap.out | grep "AQ " | wc -l) +ar2=$($DNSTAPREAD ns2/dnstap.out | grep "AR " | wc -l) +cq2=$($DNSTAPREAD ns2/dnstap.out | grep "CQ " | wc -l) +cr2=$($DNSTAPREAD ns2/dnstap.out | grep "CR " | wc -l) +rq2=$($DNSTAPREAD ns2/dnstap.out | grep "RQ " | wc -l) +rr2=$($DNSTAPREAD ns2/dnstap.out | grep "RR " | wc -l) +uq2=$($DNSTAPREAD ns2/dnstap.out | grep "UQ " | wc -l) +ur2=$($DNSTAPREAD ns2/dnstap.out | grep "UR " | wc -l) + +udp3=$($DNSTAPREAD ns3/dnstap.out | grep "UDP " | wc -l) +tcp3=$($DNSTAPREAD ns3/dnstap.out | grep "TCP " | wc -l) +aq3=$($DNSTAPREAD ns3/dnstap.out | grep "AQ " | wc -l) +ar3=$($DNSTAPREAD ns3/dnstap.out | grep "AR " | wc -l) +cq3=$($DNSTAPREAD ns3/dnstap.out | grep "CQ " | wc -l) +cr3=$($DNSTAPREAD ns3/dnstap.out | grep "CR " | wc -l) +rq3=$($DNSTAPREAD ns3/dnstap.out | grep "RQ " | wc -l) +rr3=$($DNSTAPREAD ns3/dnstap.out | grep "RR " | wc -l) +uq3=$($DNSTAPREAD ns3/dnstap.out | grep "UQ " | wc -l) +ur3=$($DNSTAPREAD ns3/dnstap.out | grep "UR " | wc -l) + +echo_i "checking UDP message counts" +ret=0 +[ $udp1 -eq 0 ] || { + echo_i "ns1 $udp1 expected 0" + ret=1 +} +[ $udp2 -eq 2 ] || { + echo_i "ns2 $udp2 expected 2" + ret=1 +} +[ $udp3 -eq 2 ] || { + echo_i "ns3 $udp3 expected 2" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking TCP message counts" +ret=0 +[ $tcp1 -eq 0 ] || { + echo_i "ns1 $tcp1 expected 0" + ret=1 +} +[ $tcp2 -eq 0 ] || { + echo_i "ns2 $tcp2 expected 0" + ret=1 +} +[ $tcp3 -eq 0 ] || { + echo_i "ns3 $tcp3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AUTH_QUERY message counts" +ret=0 +[ $aq1 -eq 0 ] || { + echo_i "ns1 $aq1 exepcted 0" + ret=1 +} +[ $aq2 -eq 0 ] || { + echo_i "ns2 $aq2 expected 0" + ret=1 +} +[ $aq3 -eq 0 ] || { + echo_i "ns3 $aq3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AUTH_RESPONSE message counts" +ret=0 +[ $ar1 -eq 0 ] || { + echo_i "ns1 $ar1 expected 0" + ret=1 +} +[ $ar2 -eq 0 ] || { + echo_i "ns2 $ar2 expected 0" + ret=1 +} +[ $ar3 -eq 0 ] || { + echo_i "ns3 $ar3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking CLIENT_QUERY message counts" +ret=0 +[ $cq1 -eq 0 ] || { + echo_i "ns1 $cq1 expected 0" + ret=1 +} +[ $cq2 -eq 0 ] || { + echo_i "ns2 $cq2 expected 0" + ret=1 +} +[ $cq3 -eq 1 ] || { + echo_i "ns3 $cq3 expected 1" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking CLIENT_RESPONSE message counts" +ret=0 +[ $cr1 -eq 0 ] || { + echo_i "ns1 $cr1 expected 0" + ret=1 +} +[ $cr2 -eq 0 ] || { + echo_i "ns2 $cr2 expected 0" + ret=1 +} +[ $cr3 -eq 1 ] || { + echo_i "ns3 $cr3 expected 1" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking RESOLVER_QUERY message counts" +ret=0 +[ $rq1 -eq 0 ] || { + echo_i "ns1 $rq1 expected 0" + ret=1 +} +[ $rq2 -eq 0 ] || { + echo_i "ns2 $rq2 expected 0" + ret=1 +} +[ $rq3 -eq 0 ] || { + echo_i "ns3 $rq3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking RESOLVER_RESPONSE message counts" +ret=0 +[ $rr1 -eq 0 ] || { + echo_i "ns1 $rr1 expected 0" + ret=1 +} +[ $rr2 -eq 0 ] || { + echo_i "ns2 $rr2 expected 0" + ret=1 +} +[ $rr3 -eq 0 ] || { + echo_i "ns3 $rr3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking UPDATE_QUERY message counts" +ret=0 +[ $uq1 -eq 0 ] || { + echo_i "ns1 $uq1 expected 0" + ret=1 +} +[ $uq2 -eq 1 ] || { + echo_i "ns2 $uq2 expected 1" + ret=1 +} +[ $uq3 -eq 0 ] || { + echo_i "ns3 $uq3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking UPDATE_RESPONSE message counts" +ret=0 +[ $ur1 -eq 0 ] || { + echo_i "ns1 $ur1 expected 0" + ret=1 +} +[ $ur2 -eq 1 ] || { + echo_i "ns2 $ur2 expected 1" + ret=1 +} +[ $ur3 -eq 0 ] || { + echo_i "ns3 $ur3 expected 0" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking whether destination UDP port is logged for client queries" +ret=0 +$DNSTAPREAD ns3/dnstap.out.save | grep -Eq "CQ [0-9:.]+ -> 10.53.0.3:${PORT} UDP" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +HAS_PYYAML=0 +if [ -x "$PYTHON" ]; then + $PYTHON -c "import yaml" 2>/dev/null && HAS_PYYAML=1 +fi + +if [ $HAS_PYYAML -ne 0 ]; then + echo_i "checking dnstap-read YAML output" + ret=0 + { + $PYTHON ydump.py "$DNSTAPREAD" "ns3/dnstap.out.save" >ydump.out || ret=1 + } | cat_i + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "checking dnstap-read hex output" +ret=0 +hex=$($DNSTAPREAD -x ns3/dnstap.out | tail -1) +echo $hex | $WIRETEST >dnstap.hex +grep 'status: NOERROR' dnstap.hex >/dev/null 2>&1 || ret=1 +grep 'ANSWER: 3, AUTHORITY: 1' dnstap.hex >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if [ -n "$FSTRM_CAPTURE" ]; then + $DIG $DIGOPTS @10.53.0.4 a.example >dig.out || ret=1 + + # send an UPDATE to ns4 + $NSUPDATE <<-EOF >nsupdate.out 2>&1 && ret=1 + server 10.53.0.4 ${PORT} + zone example + update add b.example 3600 in a 10.10.10.10 + send +EOF + grep "update failed: NOTAUTH" nsupdate.out >/dev/null || ret=1 + + echo_i "checking unix socket message counts" + sleep 2 + retry_quiet 5 dnstap_data_ready $fstrm_capture_pid dnstap.out 450 || { + echo_i "dnstap output file smaller than expected" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + kill $fstrm_capture_pid + wait + udp4=$($DNSTAPREAD dnstap.out | grep "UDP " | wc -l) + tcp4=$($DNSTAPREAD dnstap.out | grep "TCP " | wc -l) + aq4=$($DNSTAPREAD dnstap.out | grep "AQ " | wc -l) + ar4=$($DNSTAPREAD dnstap.out | grep "AR " | wc -l) + cq4=$($DNSTAPREAD dnstap.out | grep "CQ " | wc -l) + cr4=$($DNSTAPREAD dnstap.out | grep "CR " | wc -l) + rq4=$($DNSTAPREAD dnstap.out | grep "RQ " | wc -l) + rr4=$($DNSTAPREAD dnstap.out | grep "RR " | wc -l) + uq4=$($DNSTAPREAD dnstap.out | grep "UQ " | wc -l) + ur4=$($DNSTAPREAD dnstap.out | grep "UR " | wc -l) + + echo_i "checking UDP message counts" + ret=0 + [ $udp4 -eq 4 ] || { + echo_i "ns4 $udp4 expected 4" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking TCP message counts" + ret=0 + [ $tcp4 -eq 0 ] || { + echo_i "ns4 $tcp4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking AUTH_QUERY message counts" + ret=0 + [ $aq4 -eq 0 ] || { + echo_i "ns4 $aq4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking AUTH_RESPONSE message counts" + ret=0 + [ $ar4 -eq 0 ] || { + echo_i "ns4 $ar4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking CLIENT_QUERY message counts" + ret=0 + [ $cq4 -eq 1 ] || { + echo_i "ns4 $cq4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking CLIENT_RESPONSE message counts" + ret=0 + [ $cr4 -eq 1 ] || { + echo_i "ns4 $cr4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking RESOLVER_QUERY message counts" + ret=0 + [ $rq4 -eq 0 ] || { + echo_i "ns4 $rq4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking RESOLVER_RESPONSE message counts" + ret=0 + [ $rr4 -eq 0 ] || { + echo_i "ns4 $rr4 expected 0" + ret=1 + } + + echo_i "checking UPDATE_QUERY message counts" + ret=0 + [ $uq4 -eq 1 ] || { + echo_i "ns4 $uq4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking UPDATE_RESPONSE message counts" + ret=0 + [ $ur4 -eq 1 ] || { + echo_i "ns4 $ur4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + mv dnstap.out dnstap.out.save + + echo_i "restarting fstrm_capture" + $FSTRM_CAPTURE -t protobuf:dnstap.Dnstap -u ns4/dnstap.out \ + -w dnstap.out >fstrm_capture.out.2 2>&1 & + fstrm_capture_pid=$! + wait_for_log 10 "socket path ns4/dnstap.out" fstrm_capture.out.2 || { + echo_i "failed" + ret=1 + } + $RNDCCMD -s 10.53.0.4 dnstap -reopen | sed 's/^/ns4 /' | cat_i + $DIG $DIGOPTS @10.53.0.4 a.example >dig.out || ret=1 + + echo_i "checking reopened unix socket message counts" + sleep 2 + retry_quiet 5 dnstap_data_ready $fstrm_capture_pid dnstap.out 270 || { + echo_i "dnstap output file smaller than expected" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + kill $fstrm_capture_pid + wait + udp4=$($DNSTAPREAD dnstap.out | grep "UDP " | wc -l) + tcp4=$($DNSTAPREAD dnstap.out | grep "TCP " | wc -l) + aq4=$($DNSTAPREAD dnstap.out | grep "AQ " | wc -l) + ar4=$($DNSTAPREAD dnstap.out | grep "AR " | wc -l) + cq4=$($DNSTAPREAD dnstap.out | grep "CQ " | wc -l) + cr4=$($DNSTAPREAD dnstap.out | grep "CR " | wc -l) + rq4=$($DNSTAPREAD dnstap.out | grep "RQ " | wc -l) + rr4=$($DNSTAPREAD dnstap.out | grep "RR " | wc -l) + uq4=$($DNSTAPREAD dnstap.out | grep "UQ " | wc -l) + ur4=$($DNSTAPREAD dnstap.out | grep "UR " | wc -l) + + echo_i "checking UDP message counts" + ret=0 + [ $udp4 -eq 2 ] || { + echo_i "ns4 $udp4 expected 2" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking TCP message counts" + ret=0 + [ $tcp4 -eq 0 ] || { + echo_i "ns4 $tcp4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking AUTH_QUERY message counts" + ret=0 + [ $aq4 -eq 0 ] || { + echo_i "ns4 $aq4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking AUTH_RESPONSE message counts" + ret=0 + [ $ar4 -eq 0 ] || { + echo_i "ns4 $ar4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking CLIENT_QUERY message counts" + ret=0 + [ $cq4 -eq 1 ] || { + echo_i "ns4 $cq4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking CLIENT_RESPONSE message counts" + ret=0 + [ $cr4 -eq 1 ] || { + echo_i "ns4 $cr4 expected 1" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking RESOLVER_QUERY message counts" + ret=0 + [ $rq4 -eq 0 ] || { + echo_i "ns4 $rq4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking RESOLVER_RESPONSE message counts" + ret=0 + [ $rr4 -eq 0 ] || { + echo_i "ns4 $rr4 expected 0" + ret=1 + } + + echo_i "checking UPDATE_QUERY message counts" + ret=0 + [ $uq4 -eq 0 ] || { + echo_i "ns4 $uq4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + echo_i "checking UPDATE_RESPONSE message counts" + ret=0 + [ $ur4 -eq 0 ] || { + echo_i "ns4 $ur4 expected 0" + ret=1 + } + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +echo_i "checking large packet printing" +ret=0 +# Expect one occurrence of "opcode: QUERY" below "reponse_message_data" and +# another one below "response_message". +lines=$($DNSTAPREAD -y large-answer.fstrm | grep -c "opcode: QUERY") +[ $lines -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +_test_dnstap_roll() ( + ip="$1" + ns="$2" + n="$3" + + $RNDCCMD -s "${ip}" dnstap -roll "${n}" | sed "s/^/${ns} /" | cat_i \ + && files=$(find "$ns" -name "dnstap.out.[0-9]" | wc -l) \ + && test "$files" -eq "${n}" && test "$files" -ge "1" || return 1 +) + +test_dnstap_roll() { + echo_i "checking 'rndc -roll $4' ($1)" + ret=0 + + try=0 + while test $try -lt 12; do + touch "$3/dnstap.out.$try" + try=$((try + 1)) + done + + _repeat 10 _test_dnstap_roll $2 $3 $4 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +} + +start_server --noclean --restart --port "${PORT}" ns3 +test_dnstap_roll "no versions" 10.53.0.3 ns3 6 +test_dnstap_roll "no versions" 10.53.0.3 ns3 3 +test_dnstap_roll "no versions" 10.53.0.3 ns3 1 + +start_server --noclean --restart --port "${PORT}" ns2 +test_dnstap_roll "versions" 10.53.0.2 ns2 6 +test_dnstap_roll "versions" 10.53.0.2 ns2 3 +test_dnstap_roll "versions" 10.53.0.2 ns2 1 + +echo_i "exit status: $status" +[ "$status" -eq 0 ] || exit 1 diff --git a/bin/tests/system/dnstap/tests_dnstap.py b/bin/tests/system/dnstap/tests_dnstap.py new file mode 100644 index 0000000..6326ef0 --- /dev/null +++ b/bin/tests/system/dnstap/tests_dnstap.py @@ -0,0 +1,91 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import re +import subprocess + +import isctest +import pytest + +import dns.message + +pytest.importorskip("dns", minversion="2.0.0") + +pytestmark = pytest.mark.extra_artifacts( + [ + "dnstap.out.*", + "ns*/dnstap.out*", + "ns2/example.db", + ] +) + + +def run_rndc(server, rndc_command): + """ + Send the specified 'rndc_command' to 'server' with a timeout of 10 seconds + """ + rndc = os.getenv("RNDC") + port = os.getenv("CONTROLPORT") + + cmdline = [rndc, "-c", "../_common/rndc.conf", "-p", port, "-s", server] + cmdline.extend(rndc_command) + + subprocess.check_output(cmdline, stderr=subprocess.STDOUT, timeout=10) + + +def test_dnstap_dispatch_socket_addresses(): + # Send some query to ns3 so that it records something in its dnstap file. + msg = dns.message.make_query("mail.example.", "A") + res = isctest.query.tcp(msg, "10.53.0.2", expected_rcode=dns.rcode.NOERROR) + assert res.answer == [ + dns.rrset.from_text("mail.example.", 300, "IN", "A", "10.0.0.2") + ] + + # Before continuing, roll dnstap file to ensure it is flushed to disk. + run_rndc("10.53.0.3", ["dnstap", "-roll", "1"]) + + # Move the dnstap file aside so that it is retained for troubleshooting. + os.rename(os.path.join("ns3", "dnstap.out.0"), "dnstap.out.resolver_addresses") + + # Read the contents of the dnstap file using dnstap-read. + output = subprocess.check_output( + [os.getenv("DNSTAPREAD"), "dnstap.out.resolver_addresses"], encoding="utf-8" + ) + + # Check whether all frames contain the expected addresses. + # + # Expected dnstap-read output format: + # + # 22-Jun-2022 12:09:06.168 RR 10.53.0.3:0 -> 10.53.0.1:7523 TCP ... + # 22-Jun-2022 12:09:06.168 RR 10.53.0.3:0 <- 10.53.0.1:7523 TCP ... + # 22-Jun-2022 12:09:06.168 RQ 10.53.0.3:56306 -> 10.53.0.2:7523 UDP ... + # 22-Jun-2022 12:09:06.168 RQ 10.53.0.3:56306 <- 10.53.0.2:7523 UDP ... + # + bad_frames = [] + inspected_frames = 0 + addr_regex = r"^10\.53\.0\.[0-9]+:[0-9]{1,5}$" + for line in output.splitlines(): + _, _, frame_type, addr1, _, addr2, _ = line.split(" ", 6) + # Only inspect RESOLVER_QUERY and RESOLVER_RESPONSE frames. + if frame_type not in ("RQ", "RR"): + continue + inspected_frames += 1 + if not re.match(addr_regex, addr1) or not re.match(addr_regex, addr2): + bad_frames.append(line) + + assert ( + len(bad_frames) == 0 + ), "{} out of {} inspected frames contain unexpected addresses:\n\n{}".format( + len(bad_frames), inspected_frames, "\n".join(bad_frames) + ) diff --git a/bin/tests/system/dnstap/tests_sh_dnstap.py b/bin/tests/system/dnstap/tests_sh_dnstap.py new file mode 100644 index 0000000..5d4d7a9 --- /dev/null +++ b/bin/tests/system/dnstap/tests_sh_dnstap.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + "dnstap.hex*", + "dnstap.out*", + "fstrm_capture.out.*", + "nsupdate.out*", + "ydump.out*", + "ns*/dnstap.out*", + "ns2/example.db", + "ns2/example.db.jnl", + ] +) + + +def test_dnstap(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py new file mode 100644 index 0000000..ab7e3c9 --- /dev/null +++ b/bin/tests/system/dnstap/ydump.py @@ -0,0 +1,29 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import sys + +try: + import yaml +except (ModuleNotFoundError, ImportError): + print("No python yaml module, skipping") + sys.exit(1) + +import subprocess +import pprint + +DNSTAP_READ = sys.argv[1] +DATAFILE = sys.argv[2] +ARGS = [DNSTAP_READ, "-y", DATAFILE] + +with subprocess.Popen(ARGS, stdout=subprocess.PIPE) as f: + for y in yaml.load_all(f.stdout, Loader=yaml.SafeLoader): + pprint.pprint(y) diff --git a/bin/tests/system/doth/CA/CA.cfg b/bin/tests/system/doth/CA/CA.cfg new file mode 100644 index 0000000..dcdff1f --- /dev/null +++ b/bin/tests/system/doth/CA/CA.cfg @@ -0,0 +1,121 @@ +## How To +# To issue a certificate: +# +# 1. Generate the next certificate serial (if the file does not exist): +# xxd -l 8 -u -ps /dev/urandom > ./serial +# 2. Create the new certificate request (e.g. for foo.example.com): +# openssl req -config ./CA.cfg -new -subj "/CN=foo.example.com" \ +# -addext "subjectAltName=DNS:foo.example.com,IP:X.X.X.X" \ +# -newkey rsa -keyout ./certs/foo.example.com.key \ +# -out ./certs/foo.example.com.csr +# +# The above will generate request for an RSA-based certificate. One +# can issue an ECDSA-based certificate by replacing "-newkey rsa" with +# "-newkey ec -pkeyopt ec_paramgen_curve:secp384r1". +# +# 3. Issue the certificate: +# openssl ca -config ./CA.cfg -in ./certs/foo.example.com.csr \ +# -out ./certs/foo.example.com.pem +# +# To cleanup the internal database from expired certificates: +# +# 1. openssl ca -config ./CA.cfg -updatedb +# +# To revoke a certificate: +# +# 1. Revoke the certificate via file (e.g. for foo.example.com): +# openssl ca -config ./CA.cfg -revoke ./certs/foo.example.com.pem +# 2. Optionally remove the certificate file if you do not need it anymore: +# rm ./certs/foo.example.com.pem +# 3. Generate the certificate revocation list file: CRL (e.g. revoked.crl): +# openssl ca -config ./CA.cfg -gencrl > ./revoked.crl +# +# The key for CA was generated like follows +# openssl genrsa -out ./CA.key 3072 +# openssl req -x509 -new -key ./CA.key -days 10950 -out ./CA.pem +# +# See also: +# +# - https://jamielinux.com/docs/openssl-certificate-authority/index.html +# - https://www.openssl.org/docs/man1.1.1/man1/ca.html +# - https://www.openssl.org/docs/man1.1.1/man1/openssl-req.html +# - https://security.stackexchange.com/questions/74345/provide-subjectaltname-to-openssl-directly-on-the-command-line +# - https://security.stackexchange.com/a/190646 - for ECDSA certificates +# - https://gist.github.com/Soarez/9688998 +# - https://habr.com/ru/post/192446/ - Beware, your screen might "go Cyrillic"! + +# certificate authority configuration +[ca] +default_ca = CA_default # The default ca section + +[CA_default] +dir = . +new_certs_dir = $dir/newcerts # new certs dir (must be created) +certificate = $dir/CA.pem # The CA cert +private_key = $dir/private/CA.key # CA private key + +serial = $dir/serial # serial number file for the next certificate + # Update before issuing it: + # xxd -l 8 -u -ps /dev/urandom > ./serial +database = $dir/index.txt # (must be created manually: touch ./index.txt) + +default_days = 10950 # how long to certify for + +#default_crl_days = 30 # the number of days before the +default_crl_days = 10950 # next CRL is due. That is the + # days from now to place in the + # CRL nextUpdate field. If CRL + # is expired, certificate + # verifications will fail even + # for otherwise valid + # certificates. Clients might + # cache the CRL, so the expiry + # period should normally be + # relatively short (default: + # 30) for production CAs. + +default_md = sha256 # digest to use + +policy = policy_default # default policy +email_in_dn = no # Don't add the email into cert DN + +name_opt = ca_default # Subject name display option +cert_opt = ca_default # Certificate display option + +# We need the following in order to copy Subject Alt Name(s) from a +# request to the certificate. +copy_extensions = copy # copy extensions from request + +[policy_default] +countryName = optional +stateOrProvinceName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# default certificate requests settings +[req] +# Options for the `req` tool (`man req`). +default_bits = 3072 # for RSA only +distinguished_name = req_default +string_mask = utf8only +# SHA-1 is deprecated, so use SHA-256 instead. +default_md = sha256 +# do not encrypt the private key file +encrypt_key = no + +[req_default] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (e.g., city) +0.organizationName = Organization Name (e.g., company) +organizationalUnitName = Organizational Unit Name (e.g. department) +commonName = Common Name (e.g. server FQDN or YOUR name) +emailAddress = Email Address +# defaults +countryName_default = UA +stateOrProvinceName_default = Kharkiv Oblast +localityName_default = Kharkiv +0.organizationName_default = ISC +organizationalUnitName_default = Software Engeneering (BIND 9) diff --git a/bin/tests/system/doth/CA/CA.pem b/bin/tests/system/doth/CA/CA.pem new file mode 100644 index 0000000..1f725db --- /dev/null +++ b/bin/tests/system/doth/CA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE3TCCA0WgAwIBAgIUeZPKrvbGEBZaRc2jNczlIsJXyPYwDQYJKoZIhvcNAQEL +BQAwfTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G +A1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0 +aXVtMRwwGgYDVQQDDBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDEyNDEyNDA1 +NFoYDzIwNTIwMTE3MTI0MDU0WjB9MQswCQYDVQQGEwJVQTEYMBYGA1UECAwPS2hh +cmtpdiBPYmxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5l +dCBTeXN0ZW1zIENvbnNvcnRpdW0xHDAaBgNVBAMME2NhLnRlc3QuZXhhbXBsZS5j +b20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCi6hEegBzpUKbE1NTo +Z7uz7EMUY7TBckkiw/7ydTLKNa8YI4JpBguFvWQsDY0dGFJIoVwyHyNx3seW/LoI +B5zWPZ2xbOvLLceA+t2NZpbc98E7jUOVS123yED+nqlfZjCq9Zt0r/ezwnQtjnFF +ko1mcU4H9Jvg8aIgnU2AxE78zciU9CY8799pFFNThIjbooI8oVbfjbzbpmLzxjA5 +3rDmZBTh+ySTlMa2U2oT4WPjRltZWnJVegRRLpG95GnTbQ1fkJAbj1Iu10XTkCee +wBOqaA1UJem0a6pby5odE414Y7c0ETKcmaJtYENQyO0IJwZWDKtVe5OTIAklakia +eyFTCAw1h5tHCYLaJW/Yu2wlLl5RNQcRZ9+cWXnldTY+TI1iBjfmADjLdKJYUlhX +z7kWJtTi63Sdv6WYcEXxaWpxT+R3e2kaR/R7GOo4gdkWpX1siGlRteHHH2/36CSQ +ZD2etcTUpGW+KDHFR4grnEfL1rt9UgvCjpa4KcssmZtWSSUCAwEAAaNTMFEwHQYD +VR0OBBYEFHyJ6Fzr5R9ySATFj/uSCJz1YCY5MB8GA1UdIwQYMBaAFHyJ6Fzr5R9y +SATFj/uSCJz1YCY5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGB +AF3y0hvzyZWtmuG1JwIcOcc1aPl1KdRy8bao/5iHYGYYrsdDgcO5/e+y9S/izalc +TdW7SKB5iBOCiE8fBNtToCvGP+fxNxHijpAmTr37G5sWuSo1T1VYFizHWL+df/Ig +TcSvDrEjSnAwaEdNJUWtjoIC4VzNKTLtZf16QIATTzTZa3bfgSetpWS7LhLQbHod +CSGI2QB1LRbqGC+a1Y85QxHv81jWzPWPzXYvnOLrDdQyBMOBcxDzrN4b6zg+5Itz +qGYt+IS71jAH0IhxAyD/U5n1jGJv02BnSq0ynLEOD6gsnZjqAwPbt/PM9pGbtbXO +70Q9rxr+vQc1IISKAEiH3txaEPi10wU98d6LbInJvQrmgHo/ntet8skWNYuxlEzS +wvynuE9KvvQtOTodWt5AePtKrhHdxu527a4CHVp59nYUjKSdMKjvmhMRXM1cNjFE +rA/pyyhozR47w3RzHMJVHw2GJ2B/HeqmxpXr1CmJjoRP38QCR7N+mqiZy85Fq2j2 +8Q== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/README b/bin/tests/system/doth/CA/README new file mode 100644 index 0000000..13069ca --- /dev/null +++ b/bin/tests/system/doth/CA/README @@ -0,0 +1,2 @@ +Please take a look at the contents of the CA.cfg file for further +instructions and configurations options. diff --git a/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key new file mode 100644 index 0000000..9da02dd --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCq9Z95YLiCPSevj5Xm +lB/ijFFlZb8AT2bHUyL1fmivBm8JfjSa/j3pZePAF7rltyChZANiAARek2p62nXM +ZAjk+PkvK4U27uHf+s1MYPFEtRZ7+QPPoAhnb64no5WKaB5jq88uIGJS54w+Hu/e +DWlkZbbk3/4aSPhodYSDEfuBWQ7Blkh/JNoR3azLCsUJeCQxOt835rM= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem new file mode 100644 index 0000000..0b4c115 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client01.example.com.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207431 (0x6bb3183cdef52007) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 10 17:44:20 2022 GMT + Not After : Feb 3 17:44:20 2052 GMT + Subject: CN=srv01.client01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:5e:93:6a:7a:da:75:cc:64:08:e4:f8:f9:2f:2b: + 85:36:ee:e1:df:fa:cd:4c:60:f1:44:b5:16:7b:f9: + 03:cf:a0:08:67:6f:ae:27:a3:95:8a:68:1e:63:ab: + cf:2e:20:62:52:e7:8c:3e:1e:ef:de:0d:69:64:65: + b6:e4:df:fe:1a:48:f8:68:75:84:83:11:fb:81:59: + 0e:c1:96:48:7f:24:da:11:dd:ac:cb:0a:c5:09:78: + 24:31:3a:df:37:e6:b3 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client01.example.com + Signature Algorithm: sha256WithRSAEncryption + 82:bd:eb:8f:4e:a5:d2:46:c7:d8:70:3c:34:1d:58:43:1b:81: + 16:5d:c2:b0:76:4b:a9:f2:10:14:23:e4:ef:dc:59:03:b6:7f: + b0:40:34:e5:d0:82:4b:95:a6:07:9a:45:51:94:cf:08:c2:4e: + c9:44:d5:f3:b6:ed:f2:a0:01:94:ad:e0:0e:0f:ab:85:6f:35: + 4b:07:c8:97:25:fb:69:ff:a1:99:bc:ec:70:6c:51:b5:32:95: + e9:c9:45:cf:45:e2:c5:5e:b1:59:a2:e1:f2:83:c8:87:68:c4: + 60:e2:db:50:6c:18:64:1b:9a:9a:cc:7c:e7:fd:d9:f2:b7:d1: + de:1d:ec:29:c9:58:db:7b:9a:a1:06:9a:ce:36:a0:45:10:dc: + 7d:81:24:21:34:30:4c:71:f9:fc:96:37:d6:cf:0d:9d:11:12: + c7:62:bc:19:5b:79:e5:e0:37:e8:17:36:4b:13:af:fa:2c:2e: + 36:d9:be:53:e1:c3:f9:bc:94:a6:7a:97:14:99:36:f9:14:38: + 11:20:3a:2a:9d:fd:64:63:d0:a2:8f:f0:99:a9:02:ca:57:48: + d2:7d:65:44:b6:85:a0:38:ec:e8:19:7e:c2:48:e3:1d:22:53: + cf:3b:d4:0a:98:e1:72:62:ec:8b:01:3f:5a:ea:26:2c:8c:16: + c3:80:5a:c2:5d:40:c5:65:1c:e2:9a:e3:d6:65:16:ee:dc:17: + 30:d8:26:87:92:d0:ef:c7:72:07:99:86:05:9e:49:35:41:33: + b9:bb:cb:1b:25:50:70:85:e3:0f:c7:b9:b2:37:00:1b:87:a2: + 47:97:34:5b:cd:dc:66:22:e5:de:25:ec:57:fe:37:75:2c:03: + 10:f4:d4:a7:cc:f5:4b:0b:ff:eb:d3:a6:78:2e:cd:8f:65:51: + a7:8c:ef:83:67:ec:94:13:c2:1f:74:74:55:7c:a3:0b:b7:2f: + 80:5a:62:04:1d:a2:c0:c1:de:b2:7d:31:3b:a1:fa:f7:40:a7: + bd:12:25:95:5b:8b +-----BEGIN CERTIFICATE----- +MIIDITCCAYmgAwIBAgIIa7MYPN71IAcwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMDE3NDQyMFoYDzIwNTIwMjAz +MTc0NDIwWjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLmNvbTB2 +MBAGByqGSM49AgEGBSuBBAAiA2IABF6TanradcxkCOT4+S8rhTbu4d/6zUxg8US1 +Fnv5A8+gCGdvriejlYpoHmOrzy4gYlLnjD4e794NaWRltuTf/hpI+Gh1hIMR+4FZ +DsGWSH8k2hHdrMsKxQl4JDE63zfms6MpMCcwJQYDVR0RBB4wHIIac3J2MDEuY2xp +ZW50MDEuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggGBAIK9649OpdJGx9hw +PDQdWEMbgRZdwrB2S6nyEBQj5O/cWQO2f7BANOXQgkuVpgeaRVGUzwjCTslE1fO2 +7fKgAZSt4A4Pq4VvNUsHyJcl+2n/oZm87HBsUbUylenJRc9F4sVesVmi4fKDyIdo +xGDi21BsGGQbmprMfOf92fK30d4d7CnJWNt7mqEGms42oEUQ3H2BJCE0MExx+fyW +N9bPDZ0REsdivBlbeeXgN+gXNksTr/osLjbZvlPhw/m8lKZ6lxSZNvkUOBEgOiqd +/WRj0KKP8JmpAspXSNJ9ZUS2haA47OgZfsJI4x0iU8871AqY4XJi7IsBP1rqJiyM +FsOAWsJdQMVlHOKa49ZlFu7cFzDYJoeS0O/HcgeZhgWeSTVBM7m7yxslUHCF4w/H +ubI3ABuHokeXNFvN3GYi5d4l7Ff+N3UsAxD01KfM9UsL/+vTpnguzY9lUaeM74Nn +7JQTwh90dFV8owu3L4BaYgQdosDB3rJ9MTuh+vdAp70SJZVbiw== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key new file mode 100644 index 0000000..91cb6ca --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDD1/sp/yNsAc9Z6TPhm +0xT0ZhSf/9XJD6daSpdUDJ/nEJKa+sBXDWJHuXrbNRqUK2qhZANiAATmRfpXEmxZ +ECOLelx2M+s7Qfq3HJCzLzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XY +z7QpW9xOyOymn1h2JPTF0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuark= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem new file mode 100644 index 0000000..1b43bbd --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client02-ns2.example.com.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207432 (0x6bb3183cdef52008) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 11 13:21:12 2022 GMT + Not After : Feb 4 13:21:12 2052 GMT + Subject: CN=srv01.client02-ns2.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:e6:45:fa:57:12:6c:59:10:23:8b:7a:5c:76:33: + eb:3b:41:fa:b7:1c:90:b3:2f:33:2d:45:7b:e3:e5: + b6:a5:a2:a2:a4:14:f4:50:9d:b0:c6:38:ba:e9:45: + 65:a4:65:b9:10:32:2f:93:9b:d5:d8:cf:b4:29:5b: + dc:4e:c8:ec:a6:9f:58:76:24:f4:c5:d1:48:55:52: + eb:5d:b0:85:93:85:ee:3e:b8:c4:b1:cd:08:59:95: + 12:ff:7b:9b:ee:6a:b9 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client02-ns2.example.com + Signature Algorithm: sha256WithRSAEncryption + 43:ec:0f:62:17:f6:f4:90:3b:7c:36:21:f2:18:94:a6:42:51: + 1e:1d:2a:43:8f:05:b7:8d:3c:ca:f0:20:2f:65:4b:be:48:ad: + 6a:0a:cc:2d:1f:d6:27:1d:af:4a:36:86:ed:0d:03:75:c5:71: + ec:58:9b:ec:f9:0f:e4:83:ef:6f:91:da:20:73:47:ac:e7:c7: + 8b:22:b2:d1:6e:a0:b0:d6:1c:4c:70:1e:74:08:1d:7f:61:06: + e5:be:f3:e8:c4:15:60:e2:b0:02:9b:f0:13:af:76:5b:a8:c7: + 91:2c:10:5f:0d:32:89:51:5a:7f:17:1b:7c:c6:46:97:ee:e7: + bb:8a:48:38:a2:52:d4:ff:3b:1c:ec:4a:a9:8c:a5:23:3a:04: + bb:d7:b8:ad:5b:69:7f:1d:be:ca:96:e0:eb:56:05:43:ee:c8: + ff:2c:48:03:00:c6:c2:ac:fc:4e:15:47:86:c5:33:ed:70:f6: + 98:bc:0b:07:b9:5b:1a:ec:fd:3c:bf:26:61:68:fc:db:02:55: + 07:ae:76:0e:be:ff:c5:b8:56:fb:52:54:a4:b1:2d:64:b4:1d: + 55:02:4f:da:06:bd:26:e4:22:d2:94:1f:7e:29:c4:97:10:d1: + 75:7d:41:53:be:46:52:70:b1:d9:ff:bb:9f:96:19:e3:a0:ba: + d0:4a:5a:8d:da:22:73:89:f0:4c:e6:18:80:53:be:bd:64:56: + 6a:c9:58:71:40:66:9e:4a:3e:31:3b:74:9e:6e:6a:f5:65:ca: + 93:06:52:00:74:65:a0:3a:eb:2e:56:56:d2:a5:4b:0e:85:17: + 25:78:cb:f3:f9:53:7b:85:f9:82:15:87:bc:36:70:b5:69:64: + 48:11:79:b9:2c:2e:cc:09:fd:0f:b0:b7:cd:97:3b:c7:0f:49: + 1a:fc:15:49:d6:1c:a9:dc:14:ff:44:d2:be:5a:36:00:66:0c: + d5:b8:bf:16:9e:60:27:79:c0:f5:b4:ff:2f:af:8c:b2:49:75: + 61:44:05:1a:e8:cd +-----BEGIN CERTIFICATE----- +MIIDKTCCAZGgAwIBAgIIa7MYPN71IAgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMTEzMjExMloYDzIwNTIwMjA0 +MTMyMTEyWjApMScwJQYDVQQDDB5zcnYwMS5jbGllbnQwMi1uczIuZXhhbXBsZS5j +b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATmRfpXEmxZECOLelx2M+s7Qfq3HJCz +LzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XYz7QpW9xOyOymn1h2JPTF +0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuarmjLTArMCkGA1UdEQQiMCCCHnNydjAx +LmNsaWVudDAyLW5zMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAQ+wP +Yhf29JA7fDYh8hiUpkJRHh0qQ48Ft408yvAgL2VLvkitagrMLR/WJx2vSjaG7Q0D +dcVx7Fib7PkP5IPvb5HaIHNHrOfHiyKy0W6gsNYcTHAedAgdf2EG5b7z6MQVYOKw +ApvwE692W6jHkSwQXw0yiVFafxcbfMZGl+7nu4pIOKJS1P87HOxKqYylIzoEu9e4 +rVtpfx2+ypbg61YFQ+7I/yxIAwDGwqz8ThVHhsUz7XD2mLwLB7lbGuz9PL8mYWj8 +2wJVB652Dr7/xbhW+1JUpLEtZLQdVQJP2ga9JuQi0pQffinElxDRdX1BU75GUnCx +2f+7n5YZ46C60Epajdoic4nwTOYYgFO+vWRWaslYcUBmnko+MTt0nm5q9WXKkwZS +AHRloDrrLlZW0qVLDoUXJXjL8/lTe4X5ghWHvDZwtWlkSBF5uSwuzAn9D7C3zZc7 +xw9JGvwVSdYcqdwU/0TSvlo2AGYM1bi/Fp5gJ3nA9bT/L6+Mskl1YUQFGujN +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key new file mode 100644 index 0000000..5d3d283 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCQvnl9FD/mrb+KQaC8 +VMhKW2sxrYFHhZnUYBc3Luz/X3vECNVqLVc5asLu+NrkioyhZANiAAQ4mpvCaoKm +0VCKeHrRvmG+1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry +4GRXGw6e359MezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/A= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem new file mode 100644 index 0000000..99e4a71 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.client03-ns2-expired.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207433 (0x6bb3183cdef52009) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Aug 14 05:00:00 2012 GMT + Not After : Aug 14 06:00:00 2012 GMT + Subject: CN=srv01.client03-ns2-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:38:9a:9b:c2:6a:82:a6:d1:50:8a:78:7a:d1:be: + 61:be:d4:b6:d3:d6:a2:02:97:a4:48:50:c0:c5:1d: + d8:2d:23:19:25:6e:91:02:1d:69:c2:77:d6:f1:a8: + 4f:4a:9a:1d:3c:69:5a:89:41:0a:f2:e0:64:57:1b: + 0e:9e:df:9f:4c:7b:3c:42:dc:21:c8:2c:95:ab:b3: + 4c:5f:56:c4:70:ee:8a:a4:e4:46:c4:9e:98:f5:c8: + 7b:b2:73:d7:45:93:f0 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client03-ns2-expired.example.com + Signature Algorithm: sha256WithRSAEncryption + 38:12:1f:5f:26:b6:8e:9b:3f:77:89:5a:b8:e8:46:78:c3:d6: + f0:0c:67:5f:d5:a3:9c:f6:f2:0a:ae:9c:87:74:9f:a3:5b:8a: + 27:58:47:e5:78:1a:e9:db:b5:cc:28:a7:f8:18:e3:e7:20:43: + cf:82:06:5d:a1:d0:82:ab:15:be:86:46:1e:e6:4d:ad:78:a4: + 16:6c:99:41:3d:29:21:c8:6b:9d:3d:4a:cd:93:37:1f:1c:88: + c7:ae:b6:7c:73:42:57:57:32:9d:e8:c6:e2:3e:da:12:57:3e: + c8:56:4a:bb:d4:01:fc:8e:30:8d:19:fe:61:3d:5e:02:64:65: + a2:46:b3:6e:ea:f9:cb:4e:f0:b9:f6:bc:6b:38:10:19:d0:93: + f8:f7:d9:4c:d2:87:2c:7f:dc:f5:00:c6:29:dd:00:5e:d2:f4: + df:52:fb:7a:5a:ad:98:36:77:72:1f:01:ed:48:91:48:16:2d: + 35:a5:15:21:98:ff:7e:5d:a1:45:c9:5f:9d:c2:3e:e5:98:e2: + ee:ce:4d:18:76:3d:8a:0a:64:9b:f1:19:9d:b6:82:af:1b:15: + d3:48:69:f1:9b:67:76:1b:41:8e:1d:69:d5:31:64:95:01:41: + 73:c1:a9:29:53:6b:f3:29:ad:e0:96:52:8e:3e:8d:c1:8e:d8: + b5:0c:94:5f:a2:6c:3c:0f:3e:5b:10:af:21:00:74:d0:b7:30: + 6c:44:fb:3d:09:46:8d:1d:e6:c2:e4:0a:5b:f4:eb:e1:71:c7: + d5:36:13:90:05:fe:65:16:61:24:b5:41:f2:10:bd:2c:c3:34: + 69:15:25:d1:32:f2:b3:d7:da:23:1b:e9:5b:33:63:43:c8:dc: + 68:f2:31:b5:93:0e:64:ea:9a:45:36:9f:96:44:38:1e:4e:d8: + 45:ba:37:68:06:4d:da:d4:16:d3:3e:77:86:4e:8d:58:d6:06: + a8:60:11:4d:d9:81:f3:85:2b:ee:58:50:6e:ea:2b:f7:84:00: + 9c:ec:a1:90:d4:94 +-----BEGIN CERTIFICATE----- +MIIDNzCCAZ+gAwIBAgIIa7MYPN71IAkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNDA1MDAwMFoXDTEyMDgxNDA2 +MDAwMFowMTEvMC0GA1UEAwwmc3J2MDEuY2xpZW50MDMtbnMyLWV4cGlyZWQuZXhh +bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4mpvCaoKm0VCKeHrRvmG+ +1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry4GRXGw6e359M +ezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/CjNTAzMDEGA1UdEQQqMCiC +JnNydjAxLmNsaWVudDAzLW5zMi1leHBpcmVkLmV4YW1wbGUuY29tMA0GCSqGSIb3 +DQEBCwUAA4IBgQA4Eh9fJraOmz93iVq46EZ4w9bwDGdf1aOc9vIKrpyHdJ+jW4on +WEfleBrp27XMKKf4GOPnIEPPggZdodCCqxW+hkYe5k2teKQWbJlBPSkhyGudPUrN +kzcfHIjHrrZ8c0JXVzKd6MbiPtoSVz7IVkq71AH8jjCNGf5hPV4CZGWiRrNu6vnL +TvC59rxrOBAZ0JP499lM0ocsf9z1AMYp3QBe0vTfUvt6Wq2YNndyHwHtSJFIFi01 +pRUhmP9+XaFFyV+dwj7lmOLuzk0Ydj2KCmSb8RmdtoKvGxXTSGnxm2d2G0GOHWnV +MWSVAUFzwakpU2vzKa3gllKOPo3Bjti1DJRfomw8Dz5bEK8hAHTQtzBsRPs9CUaN +HebC5Apb9OvhccfVNhOQBf5lFmEktUHyEL0swzRpFSXRMvKz19ojG+lbM2NDyNxo +8jG1kw5k6ppFNp+WRDgeTthFujdoBk3a1BbTPneGTo1Y1gaoYBFN2YHzhSvuWFBu +6iv3hACc7KGQ1JQ= +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key new file mode 100644 index 0000000..a4194bd --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB/BdYjkgkVy4gTuXX3 +20DWo80uWsQkKDwMeOoaQ2cYy5Cm2AdTALDdBihGKRfACPqhZANiAAQSoXsPefIp +9Y9qBtAogxRDjxlMKZE2MA8GplbnV5tYLJ78nKNO9uNvkEDVCf2Ulo4UaHRv6Ken +q4w1lvLWj12XXdG5IlvvMRWh4ettb6+xL4Dlpak48m/5ZRRwp6Ws4Ro= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem new file mode 100644 index 0000000..8671dd3 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt01.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207425 (0x6bb3183cdef52001) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:18:52 2022 GMT + Not After : Feb 1 17:18:52 2052 GMT + Subject: CN=srv01.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:12:a1:7b:0f:79:f2:29:f5:8f:6a:06:d0:28:83: + 14:43:8f:19:4c:29:91:36:30:0f:06:a6:56:e7:57: + 9b:58:2c:9e:fc:9c:a3:4e:f6:e3:6f:90:40:d5:09: + fd:94:96:8e:14:68:74:6f:e8:a7:a7:ab:8c:35:96: + f2:d6:8f:5d:97:5d:d1:b9:22:5b:ef:31:15:a1:e1: + eb:6d:6f:af:b1:2f:80:e5:a5:a9:38:f2:6f:f9:65: + 14:70:a7:a5:ac:e1:1a + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt01.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1 + Signature Algorithm: sha256WithRSAEncryption + 79:0f:08:ab:18:cc:f9:7a:bd:47:21:99:a1:a3:76:04:7f:d7: + 08:33:91:49:3d:2d:fc:8d:ff:c5:c1:8d:b8:70:05:65:32:cd: + e2:26:21:49:19:66:a2:94:4f:42:7d:83:3c:4f:ed:c1:87:89: + 5b:73:2c:64:64:67:29:f5:73:83:23:72:b7:a8:2e:d6:9a:de: + 13:0c:ba:35:d3:38:b1:c4:51:7d:81:fc:25:ca:a6:d9:d2:fa: + bb:6d:1f:a4:61:90:50:2d:8a:ed:70:1a:eb:56:2f:fc:7b:f3: + 76:df:68:8d:e8:a4:7d:82:b9:5c:c6:cb:d8:06:f7:78:dc:a7: + 94:35:d4:83:98:28:51:36:1c:73:47:e4:5b:32:d2:cd:de:1c: + 44:f6:de:37:8a:46:d0:14:8d:71:e5:10:22:b1:f9:73:f7:1b: + 4f:82:e1:a1:00:73:18:17:71:a2:bf:a2:0c:59:aa:43:58:46: + 82:f8:38:c4:5a:5a:9f:13:d7:a9:54:1f:58:9b:5d:52:16:d3: + a0:ba:6b:aa:cf:68:3a:d1:12:9c:94:ac:78:6b:7e:bc:69:6c: + 75:07:5d:fb:68:cd:e8:8d:bb:8c:b0:7c:6c:9e:f6:a5:7c:32: + 74:ef:c5:b1:1f:1d:ec:7b:2f:79:c0:3b:52:60:9b:48:89:09: + b4:46:34:69:d3:7b:1b:15:ef:0c:dd:64:1d:58:fe:a7:0b:b1: + 9d:28:1f:1e:9e:3c:c0:b1:a6:38:ab:9d:54:24:0e:75:6c:9e: + 90:13:b9:39:dc:43:fe:37:e3:14:0f:78:7e:2b:56:a2:d2:60: + 51:57:88:3b:4c:cf:24:67:36:77:21:bb:c8:07:eb:48:f7:b0: + 1e:e4:99:61:84:15:bb:61:3a:21:55:df:31:43:67:73:8f:6b: + e9:04:83:be:2d:8b:94:39:89:cf:40:d5:04:f7:6b:c9:c6:8c: + 6e:36:0f:5d:7a:9b:57:86:36:76:2c:75:35:47:50:ed:9a:84: + 7e:37:83:b5:21:a2 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAEwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3MTg1MloYDzIwNTIwMjAx +MTcxODUyWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABBKhew958in1j2oG0CiDFEOPGUwpkTYwDwamVudX +m1gsnvyco07242+QQNUJ/ZSWjhRodG/op6erjDWW8taPXZdd0bkiW+8xFaHh621v +r7EvgOWlqTjyb/llFHCnpazhGqM+MDwwOgYDVR0RBDMwMYIXc3J2MDEuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAGHEP2ScGULjv//AAAAAAAAAAEwDQYJKoZIhvcNAQEL +BQADggGBAHkPCKsYzPl6vUchmaGjdgR/1wgzkUk9LfyN/8XBjbhwBWUyzeImIUkZ +ZqKUT0J9gzxP7cGHiVtzLGRkZyn1c4MjcreoLtaa3hMMujXTOLHEUX2B/CXKptnS ++rttH6RhkFAtiu1wGutWL/x783bfaI3opH2CuVzGy9gG93jcp5Q11IOYKFE2HHNH +5Fsy0s3eHET23jeKRtAUjXHlECKx+XP3G0+C4aEAcxgXcaK/ogxZqkNYRoL4OMRa +Wp8T16lUH1ibXVIW06C6a6rPaDrREpyUrHhrfrxpbHUHXftozeiNu4ywfGye9qV8 +MnTvxbEfHex7L3nAO1Jgm0iJCbRGNGnTexsV7wzdZB1Y/qcLsZ0oHx6ePMCxpjir +nVQkDnVsnpATuTncQ/434xQPeH4rVqLSYFFXiDtMzyRnNnchu8gH60j3sB7kmWGE +FbthOiFV3zFDZ3OPa+kEg74ti5Q5ic9A1QT3a8nGjG42D116m1eGNnYsdTVHUO2a +hH43g7Uhog== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key new file mode 100644 index 0000000..db770c1 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC3sc7RaI9GyH5Z1e0D +WcccNjr43zpavmMqA8bcS9dBBjkiEdvGH47r3EIXTjp0f46hZANiAASjLTP9kpDc +A+82+aSokPFHab7ojmUI2uWzgmMcr5o3tHV8zkb7GRe8kHJPdLZFOfeWs0SFHK1q +26R2hu6OJz33YXjf4QSK65GLAWe2aTJUUBxWhtov7+Q9lLr3WwIUtRM= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem new file mode 100644 index 0000000..65f0f9f --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt02-no-san.example.com.pem @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 7760573232607207426 (0x6bb3183cdef52002) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:21:43 2022 GMT + Not After : Feb 1 17:21:43 2052 GMT + Subject: CN=srv01.crt02-no-san.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:a3:2d:33:fd:92:90:dc:03:ef:36:f9:a4:a8:90: + f1:47:69:be:e8:8e:65:08:da:e5:b3:82:63:1c:af: + 9a:37:b4:75:7c:ce:46:fb:19:17:bc:90:72:4f:74: + b6:45:39:f7:96:b3:44:85:1c:ad:6a:db:a4:76:86: + ee:8e:27:3d:f7:61:78:df:e1:04:8a:eb:91:8b:01: + 67:b6:69:32:54:50:1c:56:86:da:2f:ef:e4:3d:94: + ba:f7:5b:02:14:b5:13 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + Signature Algorithm: sha256WithRSAEncryption + 07:20:2a:a6:7a:52:52:ba:1e:b7:79:cf:e6:11:9c:ca:3f:43: + 2b:f3:d7:2e:74:74:57:81:a1:aa:e6:68:c9:fd:d1:a8:a6:5b: + a2:ff:ea:f7:f0:b7:46:dc:a0:5a:64:5f:ce:e7:0f:76:63:14: + 6d:c2:51:4b:30:ea:51:7e:4a:1b:d3:b2:f8:c2:3d:3f:c1:bf: + ad:db:4d:f8:28:31:e7:75:ae:84:37:90:00:e5:0b:6b:dc:23: + 98:69:d5:ef:ce:e2:0d:e7:19:f1:31:01:1f:2a:6c:23:a3:94: + 62:7a:bf:b3:b0:13:d0:62:fc:a5:a6:0d:52:bb:f4:31:ff:f3: + ce:3a:74:66:30:7f:29:04:8d:34:90:7a:9b:8f:da:82:2e:5c: + 81:dd:af:fa:3a:a1:4e:bb:0a:4c:62:01:40:39:67:9c:29:27: + 6e:2f:76:81:2d:33:68:ee:ee:ed:00:7f:12:7a:af:43:00:7b: + 2d:34:8a:26:9a:66:1c:e5:96:17:7c:f8:6d:1e:8c:17:39:ce: + 4f:0b:9e:40:72:e1:5e:33:3f:9e:84:b5:07:f5:ab:58:d7:37: + ed:d0:29:ad:ce:02:0d:fa:6f:96:a9:0e:6c:6e:32:d2:dc:11: + 23:a3:4a:60:54:b4:98:31:db:8f:4b:4c:58:64:39:4f:ff:27: + d0:02:e5:cc:b2:17:e8:46:dc:aa:cb:dc:3d:ed:14:52:ec:6d: + a6:cd:04:2f:fd:54:16:6c:7e:63:34:17:f1:1d:b8:37:dd:20: + 6c:f6:21:19:6f:bb:62:dd:bc:6c:41:34:ad:b1:90:eb:2a:e0: + 63:ea:70:60:6a:02:e8:fe:46:51:b1:9d:3c:54:54:73:25:b7: + 41:d1:4c:34:aa:88:48:b8:01:21:ae:d8:d3:06:38:05:65:78: + e7:38:f0:f6:e6:2e:61:c0:42:5e:3b:09:59:eb:09:48:4d:55: + 7c:af:f4:de:c1:09:a0:b4:60:f7:9e:a2:d5:46:fc:05:61:69: + e0:c1:2d:26:dc:42 +-----BEGIN CERTIFICATE----- +MIIC9TCCAV0CCGuzGDze9SACMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVB +MRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJraXYxJDAi +BgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UEAwwTY2Eu +dGVzdC5leGFtcGxlLmNvbTAgFw0yMjAyMDgxNzIxNDNaGA8yMDUyMDIwMTE3MjE0 +M1owKTEnMCUGA1UEAwwec3J2MDEuY3J0MDItbm8tc2FuLmV4YW1wbGUuY29tMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEoy0z/ZKQ3APvNvmkqJDxR2m+6I5lCNrls4Jj +HK+aN7R1fM5G+xkXvJByT3S2RTn3lrNEhRytatukdobujic992F43+EEiuuRiwFn +tmkyVFAcVobaL+/kPZS691sCFLUTMA0GCSqGSIb3DQEBCwUAA4IBgQAHICqmelJS +uh63ec/mEZzKP0Mr89cudHRXgaGq5mjJ/dGoplui/+r38LdG3KBaZF/O5w92YxRt +wlFLMOpRfkob07L4wj0/wb+t2034KDHnda6EN5AA5Qtr3COYadXvzuIN5xnxMQEf +Kmwjo5Rier+zsBPQYvylpg1Su/Qx//POOnRmMH8pBI00kHqbj9qCLlyB3a/6OqFO +uwpMYgFAOWecKSduL3aBLTNo7u7tAH8Seq9DAHstNIommmYc5ZYXfPhtHowXOc5P +C55AcuFeMz+ehLUH9atY1zft0CmtzgIN+m+WqQ5sbjLS3BEjo0pgVLSYMduPS0xY +ZDlP/yfQAuXMshfoRtyqy9w97RRS7G2mzQQv/VQWbH5jNBfxHbg33SBs9iEZb7ti +3bxsQTStsZDrKuBj6nBgagLo/kZRsZ08VFRzJbdB0Uw0qohIuAEhrtjTBjgFZXjn +OPD25i5hwEJeOwlZ6wlITVV8r/TewQmgtGD3nqLVRvwFYWngwS0m3EI= +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key new file mode 100644 index 0000000..caef1f0 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAtAQNSdzyxR3sm6gyx +2Ob3SNCsYvdsE6+gobSUJWYbdus0CCFBIN6Qpms9oc0hAgqhZANiAAQf1Xurc7Jw +Ff0zJgJcdhaADHB9V4N1rDy3SgJGNcEbwXq9vvIEmn9pg39UmhsQYtdwve8mkFFQ +EHdWtxovRF6RRjbhLqRMZy5iqH8aFRBEaIsY6s+4lgm/tTrR7xCPn7s= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem new file mode 100644 index 0000000..4befde4 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv01.crt03-expired.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207430 (0x6bb3183cdef52006) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Aug 15 08:00:00 2012 GMT + Not After : Aug 15 09:00:00 2012 GMT + Subject: CN=srv01.crt03-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:1f:d5:7b:ab:73:b2:70:15:fd:33:26:02:5c:76: + 16:80:0c:70:7d:57:83:75:ac:3c:b7:4a:02:46:35: + c1:1b:c1:7a:bd:be:f2:04:9a:7f:69:83:7f:54:9a: + 1b:10:62:d7:70:bd:ef:26:90:51:50:10:77:56:b7: + 1a:2f:44:5e:91:46:36:e1:2e:a4:4c:67:2e:62:a8: + 7f:1a:15:10:44:68:8b:18:ea:cf:b8:96:09:bf:b5: + 3a:d1:ef:10:8f:9f:bb + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt03-expired.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1 + Signature Algorithm: sha256WithRSAEncryption + 25:35:08:f6:e7:f0:83:81:be:65:31:1b:78:a8:04:84:fe:6a: + 2a:1a:5d:c1:73:20:88:08:11:d8:27:be:a5:8e:3c:df:e2:a6: + 19:c5:41:40:ea:01:91:85:99:8d:17:4e:4d:9a:3c:03:f9:78: + 4c:8a:20:41:5e:96:d6:64:83:2f:b2:fe:e7:77:09:f9:91:bd: + 22:1a:57:8b:f6:24:bc:7b:48:2b:2e:14:b7:32:bd:46:91:99: + 5e:21:9a:d3:15:a7:27:e1:c0:3a:c7:f5:f9:94:3f:6d:14:7e: + 0b:02:bf:05:d9:ac:10:8a:7e:b0:37:36:cd:cb:4a:b4:e1:01: + c7:04:8d:83:f3:c6:79:ff:ff:6c:f0:a4:bf:3c:12:61:ea:15: + ac:30:62:26:e3:c3:4e:7d:5c:68:d8:88:de:35:8d:44:75:8c: + a8:c1:0d:07:67:b5:d0:42:43:41:1f:39:a0:47:35:46:d7:0f: + 89:aa:e8:d3:86:45:9a:fb:33:01:06:23:64:53:24:48:5b:69: + fa:cf:d9:81:fb:5e:7e:7b:82:65:56:c6:46:65:5c:e1:4f:f2: + 3c:09:3c:28:5f:c9:e3:a5:24:e3:7b:aa:b5:b1:8a:6a:b2:02: + 32:5f:24:05:f1:67:c8:54:17:0c:cd:ca:3d:e4:44:3e:23:3a: + 7c:63:b6:f9:61:3a:21:e7:8f:27:ad:c3:26:86:39:49:6c:41: + 40:7f:1d:48:69:8d:db:6f:42:e4:09:fe:24:62:bd:8e:2e:54: + 25:f0:14:c2:d8:43:95:09:2e:5f:72:4f:43:b5:9a:8b:bb:8c: + 44:c6:77:c9:05:fb:1a:9f:d7:b6:a6:42:d9:5c:3d:a5:09:0f: + 9e:e0:c7:06:32:f1:ff:c9:53:5e:42:d4:2a:33:ad:06:ea:ec: + b0:26:d3:3c:ef:65:af:15:8e:7b:20:49:ad:f1:56:ef:17:6b: + fc:f4:d8:7c:82:9f:30:19:d0:bc:9c:79:e2:dc:9d:a7:f9:6b: + 6f:65:ae:21:a0:94 +-----BEGIN CERTIFICATE----- +MIIDQTCCAamgAwIBAgIIa7MYPN71IAYwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNTA4MDAwMFoXDTEyMDgxNTA5 +MDAwMFowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDMtZXhwaXJlZC5leGFtcGxlLmNv +bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABB/Ve6tzsnAV/TMmAlx2FoAMcH1Xg3Ws +PLdKAkY1wRvBer2+8gSaf2mDf1SaGxBi13C97yaQUVAQd1a3Gi9EXpFGNuEupExn +LmKofxoVEERoixjqz7iWCb+1OtHvEI+fu6NGMEQwQgYDVR0RBDswOYIfc3J2MDEu +Y3J0MDMtZXhwaXJlZC5leGFtcGxlLmNvbYcECjUAAYcQ/ZJwZQuO//8AAAAAAAAA +ATANBgkqhkiG9w0BAQsFAAOCAYEAJTUI9ufwg4G+ZTEbeKgEhP5qKhpdwXMgiAgR +2Ce+pY483+KmGcVBQOoBkYWZjRdOTZo8A/l4TIogQV6W1mSDL7L+53cJ+ZG9IhpX +i/YkvHtIKy4UtzK9RpGZXiGa0xWnJ+HAOsf1+ZQ/bRR+CwK/BdmsEIp+sDc2zctK +tOEBxwSNg/PGef//bPCkvzwSYeoVrDBiJuPDTn1caNiI3jWNRHWMqMENB2e10EJD +QR85oEc1RtcPiaro04ZFmvszAQYjZFMkSFtp+s/ZgftefnuCZVbGRmVc4U/yPAk8 +KF/J46Uk43uqtbGKarICMl8kBfFnyFQXDM3KPeREPiM6fGO2+WE6IeePJ63DJoY5 +SWxBQH8dSGmN229C5An+JGK9ji5UJfAUwthDlQkuX3JPQ7Wai7uMRMZ3yQX7Gp/X +tqZC2Vw9pQkPnuDHBjLx/8lTXkLUKjOtBurssCbTPO9lrxWOeyBJrfFW7xdr/PTY +fIKfMBnQvJx54tydp/lrb2WuIaCU +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key new file mode 100644 index 0000000..cf495c1 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC/rdGBnhOuZ8hc7fUO +6v0LO2xd2LMjTS0TCb0pVwsccYN/f6OxWJtu0uGSt0DaN6ihZANiAARD1PvMuIhg +lRaqKtAxlss+qFzkdqzBv807ZYW7LMv6w0g8g8gI7txZFZciuEIXjHUJ+T62nPLF +2122impDSAqi3RPCNuRzs2RUebv41H5I9AW+DHdjAf5PMLCqYrzy7fk= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem new file mode 100644 index 0000000..d061c2c --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv02.crt01.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207427 (0x6bb3183cdef52003) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:57:59 2022 GMT + Not After : Feb 1 17:57:59 2052 GMT + Subject: CN=srv02.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:43:d4:fb:cc:b8:88:60:95:16:aa:2a:d0:31:96: + cb:3e:a8:5c:e4:76:ac:c1:bf:cd:3b:65:85:bb:2c: + cb:fa:c3:48:3c:83:c8:08:ee:dc:59:15:97:22:b8: + 42:17:8c:75:09:f9:3e:b6:9c:f2:c5:db:5d:b6:8a: + 6a:43:48:0a:a2:dd:13:c2:36:e4:73:b3:64:54:79: + bb:f8:d4:7e:48:f4:05:be:0c:77:63:01:fe:4f:30: + b0:aa:62:bc:f2:ed:f9 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.com, IP Address:10.53.0.2, IP Address:FD92:7065:B8E:FFFF:0:0:0:2 + Signature Algorithm: sha256WithRSAEncryption + 89:ba:ae:4f:f8:3e:da:48:1f:5c:8f:ff:ee:d8:42:b0:0b:9b: + f1:b5:e2:90:c9:76:40:09:77:a3:31:d5:73:8f:eb:7d:69:94: + 1c:2b:10:31:da:d4:0c:29:e7:80:4e:61:53:ba:15:9d:e1:e8: + 0c:0d:19:77:2b:a8:74:46:e3:03:ae:ab:96:ea:af:80:c3:18: + e0:93:8e:e9:58:0e:79:47:98:a4:06:95:6b:8f:2c:d1:f7:29: + b1:98:85:e8:a4:9c:45:52:ad:c8:60:20:dc:3a:6a:40:78:15: + d1:b4:d0:c3:c5:f3:ac:fe:ec:d3:94:ef:66:0b:d7:8c:46:f3: + 62:30:c4:c2:78:65:de:40:4e:d8:26:84:8e:18:a7:71:f2:b7: + 65:d8:d0:c2:c8:e6:a0:fb:ea:01:de:2f:03:8a:50:3d:f6:6c: + 0b:ef:ce:f5:25:1f:80:54:3e:c2:6d:2c:d3:2b:bd:23:b7:3b: + 82:6b:91:7f:ea:ff:e6:11:37:d3:f0:d4:db:9f:32:ac:12:cc: + ec:25:25:81:58:16:18:90:73:c3:ad:7c:09:a7:08:99:16:ce: + e8:6c:4b:9a:e6:09:96:11:c2:f1:cf:19:43:a6:a6:81:f2:57: + 21:fa:b1:91:58:39:76:17:89:32:4c:4b:df:fa:59:03:b2:32: + b4:b3:95:89:af:f4:5e:94:b1:df:e9:bf:21:73:14:06:5d:08: + 1e:0f:d2:84:14:44:20:91:19:72:b9:38:0b:3c:2e:4f:ea:3a: + 9b:ef:93:61:e7:36:82:df:49:e2:d7:45:ea:87:45:1d:74:36: + 18:f4:aa:30:d5:65:da:1f:c7:98:61:ab:64:2a:49:98:64:a1: + 8c:33:3a:a5:97:4a:69:a6:9d:6f:00:b9:6b:81:8d:09:0f:98: + 63:0f:85:ae:e4:21:70:a3:da:5a:27:eb:df:6d:82:ac:bb:48: + 6b:01:4e:36:95:5a:d3:f0:b9:30:43:72:87:af:41:7a:30:13: + f2:92:15:f1:69:e7 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAMwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTc1OVoYDzIwNTIwMjAx +MTc1NzU5WjAiMSAwHgYDVQQDDBdzcnYwMi5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEPU+8y4iGCVFqoq0DGWyz6oXOR2rMG/zTtlhbss +y/rDSDyDyAju3FkVlyK4QheMdQn5Prac8sXbXbaKakNICqLdE8I25HOzZFR5u/jU +fkj0Bb4Md2MB/k8wsKpivPLt+aM+MDwwOgYDVR0RBDMwMYIXc3J2MDIuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAKHEP2ScGULjv//AAAAAAAAAAIwDQYJKoZIhvcNAQEL +BQADggGBAIm6rk/4PtpIH1yP/+7YQrALm/G14pDJdkAJd6Mx1XOP631plBwrEDHa +1Awp54BOYVO6FZ3h6AwNGXcrqHRG4wOuq5bqr4DDGOCTjulYDnlHmKQGlWuPLNH3 +KbGYheiknEVSrchgINw6akB4FdG00MPF86z+7NOU72YL14xG82IwxMJ4Zd5ATtgm +hI4Yp3Hyt2XY0MLI5qD76gHeLwOKUD32bAvvzvUlH4BUPsJtLNMrvSO3O4JrkX/q +/+YRN9Pw1NufMqwSzOwlJYFYFhiQc8OtfAmnCJkWzuhsS5rmCZYRwvHPGUOmpoHy +VyH6sZFYOXYXiTJMS9/6WQOyMrSzlYmv9F6Usd/pvyFzFAZdCB4P0oQURCCRGXK5 +OAs8Lk/qOpvvk2HnNoLfSeLXReqHRR10Nhj0qjDVZdofx5hhq2QqSZhkoYwzOqWX +SmmmnW8AuWuBjQkPmGMPha7kIXCj2lon699tgqy7SGsBTjaVWtPwuTBDcoevQXow +E/KSFfFp5w== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key new file mode 100644 index 0000000..72f8a40 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBMJxQaJB76ywjBuhZI +LUz05LQuwmDBAFeZFqe10HG+r0cZvVw4Cr5M7jr2RVLqKRChZANiAARF27kbN2W/ +saGKWjkAjUoVO0OauC//qH2Zg6ic3LbCqp/4UaEOLpcPkBMiTIvx/zxr65EpfUzf +fAXdrepKTK0K1m+OUbCIWEKILBbURx24j7NODRLfTBT2JyA/lJojgUg= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem new file mode 100644 index 0000000..39b48ee --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv03.crt01.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207428 (0x6bb3183cdef52004) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:58:15 2022 GMT + Not After : Feb 1 17:58:15 2052 GMT + Subject: CN=srv03.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:45:db:b9:1b:37:65:bf:b1:a1:8a:5a:39:00:8d: + 4a:15:3b:43:9a:b8:2f:ff:a8:7d:99:83:a8:9c:dc: + b6:c2:aa:9f:f8:51:a1:0e:2e:97:0f:90:13:22:4c: + 8b:f1:ff:3c:6b:eb:91:29:7d:4c:df:7c:05:dd:ad: + ea:4a:4c:ad:0a:d6:6f:8e:51:b0:88:58:42:88:2c: + 16:d4:47:1d:b8:8f:b3:4e:0d:12:df:4c:14:f6:27: + 20:3f:94:9a:23:81:48 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv03.crt01.example.com, IP Address:10.53.0.3, IP Address:FD92:7065:B8E:FFFF:0:0:0:3 + Signature Algorithm: sha256WithRSAEncryption + 8f:96:88:82:94:76:8e:97:b6:75:8b:e9:2b:4f:f3:8f:14:5c: + 50:00:ca:67:96:9e:2e:bd:53:25:25:40:6d:c5:56:e6:1a:f6: + cb:fb:58:fc:b3:56:9d:fc:0b:e2:8e:99:7e:e8:e6:ad:b6:e7: + e6:3e:8a:59:ef:3e:76:a4:ed:7b:58:fd:a3:4b:aa:4e:11:e1: + 57:bf:b1:23:a5:a1:00:f8:95:07:c8:7d:ee:ac:a7:c8:24:ee: + cf:e8:c5:a4:9f:96:27:c9:47:c1:7d:11:de:66:d0:6d:d1:8d: + e7:8f:a0:0f:46:d9:2e:70:f3:9f:ac:6a:b0:3f:5a:dc:70:d4: + b9:a5:f3:ff:5c:21:50:5d:c2:a2:46:26:25:2a:2f:8a:aa:7a: + fd:76:31:5f:e0:25:a3:ee:df:36:f0:ab:05:a1:5d:0d:3c:6b: + 2c:1d:d5:c5:73:9c:a0:57:1f:c4:26:e6:dc:a1:7c:25:08:21: + 61:28:e2:b3:f5:51:83:20:73:14:19:8f:47:79:69:bc:2b:22: + f2:17:62:1d:83:f7:4f:a9:c4:51:68:e0:a9:d7:9f:17:6a:d2: + fd:f7:04:ce:a4:f5:8e:eb:31:b4:bf:c6:2d:da:0c:70:6e:0c: + a5:75:21:54:3c:f6:3d:36:b8:8a:d8:b6:7b:77:7e:54:1d:9f: + 91:8f:02:a6:d1:2c:a7:30:d1:cc:e6:d9:6b:76:80:15:4b:ba: + fd:55:20:cc:b2:99:85:57:60:11:97:c5:e7:28:50:a6:17:af: + d2:bd:1b:7e:06:48:7f:63:dc:70:f8:3f:22:9f:41:a1:66:f5: + a7:81:99:cb:07:0e:8a:9a:bb:12:f6:c0:fe:59:0c:00:37:15: + b2:9d:f0:f9:93:d1:1a:b6:f8:0a:6b:bd:9e:92:32:45:f5:a2: + 44:f0:45:8d:1a:d0:10:b2:db:98:c4:c7:5e:c1:e8:f3:94:33: + 6c:06:f5:1a:cc:51:23:72:ae:37:2f:57:d4:f8:ac:1f:25:b4: + d3:bf:99:9b:ac:fc +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAQwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTgxNVoYDzIwNTIwMjAx +MTc1ODE1WjAiMSAwHgYDVQQDDBdzcnYwMy5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEXbuRs3Zb+xoYpaOQCNShU7Q5q4L/+ofZmDqJzc +tsKqn/hRoQ4ulw+QEyJMi/H/PGvrkSl9TN98Bd2t6kpMrQrWb45RsIhYQogsFtRH +HbiPs04NEt9MFPYnID+UmiOBSKM+MDwwOgYDVR0RBDMwMYIXc3J2MDMuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAOHEP2ScGULjv//AAAAAAAAAAMwDQYJKoZIhvcNAQEL +BQADggGBAI+WiIKUdo6XtnWL6StP848UXFAAymeWni69UyUlQG3FVuYa9sv7WPyz +Vp38C+KOmX7o5q225+Y+ilnvPnak7XtY/aNLqk4R4Ve/sSOloQD4lQfIfe6sp8gk +7s/oxaSflifJR8F9Ed5m0G3RjeePoA9G2S5w85+sarA/Wtxw1Lml8/9cIVBdwqJG +JiUqL4qqev12MV/gJaPu3zbwqwWhXQ08aywd1cVznKBXH8Qm5tyhfCUIIWEo4rP1 +UYMgcxQZj0d5abwrIvIXYh2D90+pxFFo4KnXnxdq0v33BM6k9Y7rMbS/xi3aDHBu +DKV1IVQ89j02uIrYtnt3flQdn5GPAqbRLKcw0czm2Wt2gBVLuv1VIMyymYVXYBGX +xecoUKYXr9K9G34GSH9j3HD4PyKfQaFm9aeBmcsHDoqauxL2wP5ZDAA3FbKd8PmT +0Rq2+AprvZ6SMkX1okTwRY0a0BCy25jEx17B6POUM2wG9RrMUSNyrjcvV9T4rB8l +tNO/mZus/A== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key new file mode 100644 index 0000000..5356fc1 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDq5a0oiMxJiOdwaSmk +U2NPPJXOWPZVWpIGxB0kczGcCS6Xq0VinNqLe5YI9M1YwXehZANiAASeQ9fMKeGO +SzWhj7ePMA9Ws1t/wGKbIyFwsSvnc/nqOAFmS1JDMc8QaRW/awjzaQc/mbu4cNA7 +iSId8iVCWj5VkcP8tL7HLYZRFMSr/nxUNGfHXtuGhMxm61SvnX3czhg= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem new file mode 100644 index 0000000..b4e2d22 --- /dev/null +++ b/bin/tests/system/doth/CA/certs/srv04.crt01.example.com.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207429 (0x6bb3183cdef52005) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:59:14 2022 GMT + Not After : Feb 1 17:59:14 2052 GMT + Subject: CN=srv04.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:9e:43:d7:cc:29:e1:8e:4b:35:a1:8f:b7:8f:30: + 0f:56:b3:5b:7f:c0:62:9b:23:21:70:b1:2b:e7:73: + f9:ea:38:01:66:4b:52:43:31:cf:10:69:15:bf:6b: + 08:f3:69:07:3f:99:bb:b8:70:d0:3b:89:22:1d:f2: + 25:42:5a:3e:55:91:c3:fc:b4:be:c7:2d:86:51:14: + c4:ab:fe:7c:54:34:67:c7:5e:db:86:84:cc:66:eb: + 54:af:9d:7d:dc:ce:18 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv04.crt01.example.com, IP Address:10.53.0.4, IP Address:FD92:7065:B8E:FFFF:0:0:0:4 + Signature Algorithm: sha256WithRSAEncryption + 48:b5:38:59:79:e6:51:a6:ea:80:d7:d1:3c:29:03:70:31:e4: + 43:b4:e3:09:e7:e1:37:8c:d0:0f:2a:19:7a:f2:5a:6d:76:cd: + 17:7a:66:1c:3e:74:56:24:b8:29:06:55:b2:1c:af:9a:42:05: + 93:a4:70:cb:a5:68:85:ab:71:53:da:d9:29:a3:f4:2a:1e:df: + 0c:ec:7d:52:55:fa:9b:e6:a0:18:d5:4c:da:e6:d2:60:da:bc: + 09:5b:13:53:6d:c7:d2:30:b9:a8:a5:02:7f:a3:66:28:34:93: + de:55:a0:de:b5:c8:dc:43:7b:b9:03:06:1f:ce:8c:5f:82:d8: + af:40:56:ce:f8:b9:d4:73:1c:ae:c9:cb:1d:0f:a2:52:71:9b: + 8b:05:f4:d6:0b:1e:a8:db:0f:29:a0:43:b5:2f:56:09:d8:68: + 58:9c:e5:6a:df:38:91:56:9d:44:e5:d2:ca:9a:b1:41:a1:01: + 0c:68:a0:f5:0a:f7:98:4f:d5:a0:6f:99:59:a0:e0:cb:49:57: + 26:20:09:5a:fa:c2:75:40:f6:1b:6a:ac:55:47:50:8d:38:81: + 61:79:44:e7:d5:d1:b3:c7:3b:db:ec:44:59:ef:e1:82:31:a3: + 38:4c:de:40:11:31:52:8b:bb:1c:af:be:ce:c5:2b:f5:0d:c0: + 60:13:fb:7e:da:22:41:d4:85:5e:4d:ba:db:f8:f7:26:61:32: + 26:fe:fe:9e:37:a3:cc:25:3b:3c:c8:b5:a7:a5:5c:d9:4d:8f: + a8:f2:86:98:79:b3:00:08:0f:f2:c9:1f:c6:3f:07:ad:e4:a7: + 8d:86:3d:15:fa:5b:1a:0f:96:67:b6:0a:78:0a:bb:6e:05:a6: + 54:29:48:b4:f9:48:0d:7f:f0:13:65:32:2f:c5:ee:ab:b8:e8: + 0d:b2:f9:c9:96:d2:cf:51:a2:64:3c:58:0f:65:6f:c6:99:93: + 76:2c:42:08:d9:f3:f3:13:cd:41:b6:67:8f:1d:9a:2f:da:93: + 3d:26:4c:9a:11:c1 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAUwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTkxNFoYDzIwNTIwMjAx +MTc1OTE0WjAiMSAwHgYDVQQDDBdzcnYwNC5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABJ5D18wp4Y5LNaGPt48wD1azW3/AYpsjIXCxK+dz ++eo4AWZLUkMxzxBpFb9rCPNpBz+Zu7hw0DuJIh3yJUJaPlWRw/y0vscthlEUxKv+ +fFQ0Z8de24aEzGbrVK+dfdzOGKM+MDwwOgYDVR0RBDMwMYIXc3J2MDQuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AASHEP2ScGULjv//AAAAAAAAAAQwDQYJKoZIhvcNAQEL +BQADggGBAEi1OFl55lGm6oDX0TwpA3Ax5EO04wnn4TeM0A8qGXryWm12zRd6Zhw+ +dFYkuCkGVbIcr5pCBZOkcMulaIWrcVPa2Smj9Coe3wzsfVJV+pvmoBjVTNrm0mDa +vAlbE1Ntx9IwuailAn+jZig0k95VoN61yNxDe7kDBh/OjF+C2K9AVs74udRzHK7J +yx0PolJxm4sF9NYLHqjbDymgQ7UvVgnYaFic5WrfOJFWnUTl0sqasUGhAQxooPUK +95hP1aBvmVmg4MtJVyYgCVr6wnVA9htqrFVHUI04gWF5ROfV0bPHO9vsRFnv4YIx +ozhM3kARMVKLuxyvvs7FK/UNwGAT+37aIkHUhV5Nutv49yZhMib+/p43o8wlOzzI +taelXNlNj6jyhph5swAID/LJH8Y/B63kp42GPRX6WxoPlme2CngKu24FplQpSLT5 +SA1/8BNlMi/F7qu46A2y+cmW0s9RomQ8WA9lb8aZk3YsQgjZ8/MTzUG2Z48dmi/a +kz0mTJoRwQ== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/index.txt b/bin/tests/system/doth/CA/index.txt new file mode 100644 index 0000000..230127d --- /dev/null +++ b/bin/tests/system/doth/CA/index.txt @@ -0,0 +1,9 @@ +V 20520201171852Z 6BB3183CDEF52001 unknown /CN=srv01.crt01.example.com +V 20520201172143Z 6BB3183CDEF52002 unknown /CN=srv01.crt02-no-san.example.com +V 20520201175759Z 6BB3183CDEF52003 unknown /CN=srv02.crt01.example.com +V 20520201175815Z 6BB3183CDEF52004 unknown /CN=srv03.crt01.example.com +V 20520201175914Z 6BB3183CDEF52005 unknown /CN=srv04.crt01.example.com +V 120815090000Z 6BB3183CDEF52006 unknown /CN=srv01.crt03-expired.example.com +V 20520203174420Z 6BB3183CDEF52007 unknown /CN=srv01.client01.example.com +V 20520204132112Z 6BB3183CDEF52008 unknown /CN=srv01.client02-ns2.example.com +V 120814060000Z 6BB3183CDEF52009 unknown /CN=srv01.client03-ns2-expired.example.com diff --git a/bin/tests/system/doth/CA/index.txt.attr b/bin/tests/system/doth/CA/index.txt.attr new file mode 100644 index 0000000..8f7e63a --- /dev/null +++ b/bin/tests/system/doth/CA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem new file mode 100644 index 0000000..8671dd3 --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52001.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207425 (0x6bb3183cdef52001) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:18:52 2022 GMT + Not After : Feb 1 17:18:52 2052 GMT + Subject: CN=srv01.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:12:a1:7b:0f:79:f2:29:f5:8f:6a:06:d0:28:83: + 14:43:8f:19:4c:29:91:36:30:0f:06:a6:56:e7:57: + 9b:58:2c:9e:fc:9c:a3:4e:f6:e3:6f:90:40:d5:09: + fd:94:96:8e:14:68:74:6f:e8:a7:a7:ab:8c:35:96: + f2:d6:8f:5d:97:5d:d1:b9:22:5b:ef:31:15:a1:e1: + eb:6d:6f:af:b1:2f:80:e5:a5:a9:38:f2:6f:f9:65: + 14:70:a7:a5:ac:e1:1a + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt01.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1 + Signature Algorithm: sha256WithRSAEncryption + 79:0f:08:ab:18:cc:f9:7a:bd:47:21:99:a1:a3:76:04:7f:d7: + 08:33:91:49:3d:2d:fc:8d:ff:c5:c1:8d:b8:70:05:65:32:cd: + e2:26:21:49:19:66:a2:94:4f:42:7d:83:3c:4f:ed:c1:87:89: + 5b:73:2c:64:64:67:29:f5:73:83:23:72:b7:a8:2e:d6:9a:de: + 13:0c:ba:35:d3:38:b1:c4:51:7d:81:fc:25:ca:a6:d9:d2:fa: + bb:6d:1f:a4:61:90:50:2d:8a:ed:70:1a:eb:56:2f:fc:7b:f3: + 76:df:68:8d:e8:a4:7d:82:b9:5c:c6:cb:d8:06:f7:78:dc:a7: + 94:35:d4:83:98:28:51:36:1c:73:47:e4:5b:32:d2:cd:de:1c: + 44:f6:de:37:8a:46:d0:14:8d:71:e5:10:22:b1:f9:73:f7:1b: + 4f:82:e1:a1:00:73:18:17:71:a2:bf:a2:0c:59:aa:43:58:46: + 82:f8:38:c4:5a:5a:9f:13:d7:a9:54:1f:58:9b:5d:52:16:d3: + a0:ba:6b:aa:cf:68:3a:d1:12:9c:94:ac:78:6b:7e:bc:69:6c: + 75:07:5d:fb:68:cd:e8:8d:bb:8c:b0:7c:6c:9e:f6:a5:7c:32: + 74:ef:c5:b1:1f:1d:ec:7b:2f:79:c0:3b:52:60:9b:48:89:09: + b4:46:34:69:d3:7b:1b:15:ef:0c:dd:64:1d:58:fe:a7:0b:b1: + 9d:28:1f:1e:9e:3c:c0:b1:a6:38:ab:9d:54:24:0e:75:6c:9e: + 90:13:b9:39:dc:43:fe:37:e3:14:0f:78:7e:2b:56:a2:d2:60: + 51:57:88:3b:4c:cf:24:67:36:77:21:bb:c8:07:eb:48:f7:b0: + 1e:e4:99:61:84:15:bb:61:3a:21:55:df:31:43:67:73:8f:6b: + e9:04:83:be:2d:8b:94:39:89:cf:40:d5:04:f7:6b:c9:c6:8c: + 6e:36:0f:5d:7a:9b:57:86:36:76:2c:75:35:47:50:ed:9a:84: + 7e:37:83:b5:21:a2 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAEwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3MTg1MloYDzIwNTIwMjAx +MTcxODUyWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABBKhew958in1j2oG0CiDFEOPGUwpkTYwDwamVudX +m1gsnvyco07242+QQNUJ/ZSWjhRodG/op6erjDWW8taPXZdd0bkiW+8xFaHh621v +r7EvgOWlqTjyb/llFHCnpazhGqM+MDwwOgYDVR0RBDMwMYIXc3J2MDEuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAGHEP2ScGULjv//AAAAAAAAAAEwDQYJKoZIhvcNAQEL +BQADggGBAHkPCKsYzPl6vUchmaGjdgR/1wgzkUk9LfyN/8XBjbhwBWUyzeImIUkZ +ZqKUT0J9gzxP7cGHiVtzLGRkZyn1c4MjcreoLtaa3hMMujXTOLHEUX2B/CXKptnS ++rttH6RhkFAtiu1wGutWL/x783bfaI3opH2CuVzGy9gG93jcp5Q11IOYKFE2HHNH +5Fsy0s3eHET23jeKRtAUjXHlECKx+XP3G0+C4aEAcxgXcaK/ogxZqkNYRoL4OMRa +Wp8T16lUH1ibXVIW06C6a6rPaDrREpyUrHhrfrxpbHUHXftozeiNu4ywfGye9qV8 +MnTvxbEfHex7L3nAO1Jgm0iJCbRGNGnTexsV7wzdZB1Y/qcLsZ0oHx6ePMCxpjir +nVQkDnVsnpATuTncQ/434xQPeH4rVqLSYFFXiDtMzyRnNnchu8gH60j3sB7kmWGE +FbthOiFV3zFDZ3OPa+kEg74ti5Q5ic9A1QT3a8nGjG42D116m1eGNnYsdTVHUO2a +hH43g7Uhog== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem new file mode 100644 index 0000000..65f0f9f --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52002.pem @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 7760573232607207426 (0x6bb3183cdef52002) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:21:43 2022 GMT + Not After : Feb 1 17:21:43 2052 GMT + Subject: CN=srv01.crt02-no-san.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:a3:2d:33:fd:92:90:dc:03:ef:36:f9:a4:a8:90: + f1:47:69:be:e8:8e:65:08:da:e5:b3:82:63:1c:af: + 9a:37:b4:75:7c:ce:46:fb:19:17:bc:90:72:4f:74: + b6:45:39:f7:96:b3:44:85:1c:ad:6a:db:a4:76:86: + ee:8e:27:3d:f7:61:78:df:e1:04:8a:eb:91:8b:01: + 67:b6:69:32:54:50:1c:56:86:da:2f:ef:e4:3d:94: + ba:f7:5b:02:14:b5:13 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + Signature Algorithm: sha256WithRSAEncryption + 07:20:2a:a6:7a:52:52:ba:1e:b7:79:cf:e6:11:9c:ca:3f:43: + 2b:f3:d7:2e:74:74:57:81:a1:aa:e6:68:c9:fd:d1:a8:a6:5b: + a2:ff:ea:f7:f0:b7:46:dc:a0:5a:64:5f:ce:e7:0f:76:63:14: + 6d:c2:51:4b:30:ea:51:7e:4a:1b:d3:b2:f8:c2:3d:3f:c1:bf: + ad:db:4d:f8:28:31:e7:75:ae:84:37:90:00:e5:0b:6b:dc:23: + 98:69:d5:ef:ce:e2:0d:e7:19:f1:31:01:1f:2a:6c:23:a3:94: + 62:7a:bf:b3:b0:13:d0:62:fc:a5:a6:0d:52:bb:f4:31:ff:f3: + ce:3a:74:66:30:7f:29:04:8d:34:90:7a:9b:8f:da:82:2e:5c: + 81:dd:af:fa:3a:a1:4e:bb:0a:4c:62:01:40:39:67:9c:29:27: + 6e:2f:76:81:2d:33:68:ee:ee:ed:00:7f:12:7a:af:43:00:7b: + 2d:34:8a:26:9a:66:1c:e5:96:17:7c:f8:6d:1e:8c:17:39:ce: + 4f:0b:9e:40:72:e1:5e:33:3f:9e:84:b5:07:f5:ab:58:d7:37: + ed:d0:29:ad:ce:02:0d:fa:6f:96:a9:0e:6c:6e:32:d2:dc:11: + 23:a3:4a:60:54:b4:98:31:db:8f:4b:4c:58:64:39:4f:ff:27: + d0:02:e5:cc:b2:17:e8:46:dc:aa:cb:dc:3d:ed:14:52:ec:6d: + a6:cd:04:2f:fd:54:16:6c:7e:63:34:17:f1:1d:b8:37:dd:20: + 6c:f6:21:19:6f:bb:62:dd:bc:6c:41:34:ad:b1:90:eb:2a:e0: + 63:ea:70:60:6a:02:e8:fe:46:51:b1:9d:3c:54:54:73:25:b7: + 41:d1:4c:34:aa:88:48:b8:01:21:ae:d8:d3:06:38:05:65:78: + e7:38:f0:f6:e6:2e:61:c0:42:5e:3b:09:59:eb:09:48:4d:55: + 7c:af:f4:de:c1:09:a0:b4:60:f7:9e:a2:d5:46:fc:05:61:69: + e0:c1:2d:26:dc:42 +-----BEGIN CERTIFICATE----- +MIIC9TCCAV0CCGuzGDze9SACMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVB +MRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJraXYxJDAi +BgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UEAwwTY2Eu +dGVzdC5leGFtcGxlLmNvbTAgFw0yMjAyMDgxNzIxNDNaGA8yMDUyMDIwMTE3MjE0 +M1owKTEnMCUGA1UEAwwec3J2MDEuY3J0MDItbm8tc2FuLmV4YW1wbGUuY29tMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEoy0z/ZKQ3APvNvmkqJDxR2m+6I5lCNrls4Jj +HK+aN7R1fM5G+xkXvJByT3S2RTn3lrNEhRytatukdobujic992F43+EEiuuRiwFn +tmkyVFAcVobaL+/kPZS691sCFLUTMA0GCSqGSIb3DQEBCwUAA4IBgQAHICqmelJS +uh63ec/mEZzKP0Mr89cudHRXgaGq5mjJ/dGoplui/+r38LdG3KBaZF/O5w92YxRt +wlFLMOpRfkob07L4wj0/wb+t2034KDHnda6EN5AA5Qtr3COYadXvzuIN5xnxMQEf +Kmwjo5Rier+zsBPQYvylpg1Su/Qx//POOnRmMH8pBI00kHqbj9qCLlyB3a/6OqFO +uwpMYgFAOWecKSduL3aBLTNo7u7tAH8Seq9DAHstNIommmYc5ZYXfPhtHowXOc5P +C55AcuFeMz+ehLUH9atY1zft0CmtzgIN+m+WqQ5sbjLS3BEjo0pgVLSYMduPS0xY +ZDlP/yfQAuXMshfoRtyqy9w97RRS7G2mzQQv/VQWbH5jNBfxHbg33SBs9iEZb7ti +3bxsQTStsZDrKuBj6nBgagLo/kZRsZ08VFRzJbdB0Uw0qohIuAEhrtjTBjgFZXjn +OPD25i5hwEJeOwlZ6wlITVV8r/TewQmgtGD3nqLVRvwFYWngwS0m3EI= +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem new file mode 100644 index 0000000..d061c2c --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52003.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207427 (0x6bb3183cdef52003) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:57:59 2022 GMT + Not After : Feb 1 17:57:59 2052 GMT + Subject: CN=srv02.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:43:d4:fb:cc:b8:88:60:95:16:aa:2a:d0:31:96: + cb:3e:a8:5c:e4:76:ac:c1:bf:cd:3b:65:85:bb:2c: + cb:fa:c3:48:3c:83:c8:08:ee:dc:59:15:97:22:b8: + 42:17:8c:75:09:f9:3e:b6:9c:f2:c5:db:5d:b6:8a: + 6a:43:48:0a:a2:dd:13:c2:36:e4:73:b3:64:54:79: + bb:f8:d4:7e:48:f4:05:be:0c:77:63:01:fe:4f:30: + b0:aa:62:bc:f2:ed:f9 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.com, IP Address:10.53.0.2, IP Address:FD92:7065:B8E:FFFF:0:0:0:2 + Signature Algorithm: sha256WithRSAEncryption + 89:ba:ae:4f:f8:3e:da:48:1f:5c:8f:ff:ee:d8:42:b0:0b:9b: + f1:b5:e2:90:c9:76:40:09:77:a3:31:d5:73:8f:eb:7d:69:94: + 1c:2b:10:31:da:d4:0c:29:e7:80:4e:61:53:ba:15:9d:e1:e8: + 0c:0d:19:77:2b:a8:74:46:e3:03:ae:ab:96:ea:af:80:c3:18: + e0:93:8e:e9:58:0e:79:47:98:a4:06:95:6b:8f:2c:d1:f7:29: + b1:98:85:e8:a4:9c:45:52:ad:c8:60:20:dc:3a:6a:40:78:15: + d1:b4:d0:c3:c5:f3:ac:fe:ec:d3:94:ef:66:0b:d7:8c:46:f3: + 62:30:c4:c2:78:65:de:40:4e:d8:26:84:8e:18:a7:71:f2:b7: + 65:d8:d0:c2:c8:e6:a0:fb:ea:01:de:2f:03:8a:50:3d:f6:6c: + 0b:ef:ce:f5:25:1f:80:54:3e:c2:6d:2c:d3:2b:bd:23:b7:3b: + 82:6b:91:7f:ea:ff:e6:11:37:d3:f0:d4:db:9f:32:ac:12:cc: + ec:25:25:81:58:16:18:90:73:c3:ad:7c:09:a7:08:99:16:ce: + e8:6c:4b:9a:e6:09:96:11:c2:f1:cf:19:43:a6:a6:81:f2:57: + 21:fa:b1:91:58:39:76:17:89:32:4c:4b:df:fa:59:03:b2:32: + b4:b3:95:89:af:f4:5e:94:b1:df:e9:bf:21:73:14:06:5d:08: + 1e:0f:d2:84:14:44:20:91:19:72:b9:38:0b:3c:2e:4f:ea:3a: + 9b:ef:93:61:e7:36:82:df:49:e2:d7:45:ea:87:45:1d:74:36: + 18:f4:aa:30:d5:65:da:1f:c7:98:61:ab:64:2a:49:98:64:a1: + 8c:33:3a:a5:97:4a:69:a6:9d:6f:00:b9:6b:81:8d:09:0f:98: + 63:0f:85:ae:e4:21:70:a3:da:5a:27:eb:df:6d:82:ac:bb:48: + 6b:01:4e:36:95:5a:d3:f0:b9:30:43:72:87:af:41:7a:30:13: + f2:92:15:f1:69:e7 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAMwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTc1OVoYDzIwNTIwMjAx +MTc1NzU5WjAiMSAwHgYDVQQDDBdzcnYwMi5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEPU+8y4iGCVFqoq0DGWyz6oXOR2rMG/zTtlhbss +y/rDSDyDyAju3FkVlyK4QheMdQn5Prac8sXbXbaKakNICqLdE8I25HOzZFR5u/jU +fkj0Bb4Md2MB/k8wsKpivPLt+aM+MDwwOgYDVR0RBDMwMYIXc3J2MDIuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAKHEP2ScGULjv//AAAAAAAAAAIwDQYJKoZIhvcNAQEL +BQADggGBAIm6rk/4PtpIH1yP/+7YQrALm/G14pDJdkAJd6Mx1XOP631plBwrEDHa +1Awp54BOYVO6FZ3h6AwNGXcrqHRG4wOuq5bqr4DDGOCTjulYDnlHmKQGlWuPLNH3 +KbGYheiknEVSrchgINw6akB4FdG00MPF86z+7NOU72YL14xG82IwxMJ4Zd5ATtgm +hI4Yp3Hyt2XY0MLI5qD76gHeLwOKUD32bAvvzvUlH4BUPsJtLNMrvSO3O4JrkX/q +/+YRN9Pw1NufMqwSzOwlJYFYFhiQc8OtfAmnCJkWzuhsS5rmCZYRwvHPGUOmpoHy +VyH6sZFYOXYXiTJMS9/6WQOyMrSzlYmv9F6Usd/pvyFzFAZdCB4P0oQURCCRGXK5 +OAs8Lk/qOpvvk2HnNoLfSeLXReqHRR10Nhj0qjDVZdofx5hhq2QqSZhkoYwzOqWX +SmmmnW8AuWuBjQkPmGMPha7kIXCj2lon699tgqy7SGsBTjaVWtPwuTBDcoevQXow +E/KSFfFp5w== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem new file mode 100644 index 0000000..39b48ee --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52004.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207428 (0x6bb3183cdef52004) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:58:15 2022 GMT + Not After : Feb 1 17:58:15 2052 GMT + Subject: CN=srv03.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:45:db:b9:1b:37:65:bf:b1:a1:8a:5a:39:00:8d: + 4a:15:3b:43:9a:b8:2f:ff:a8:7d:99:83:a8:9c:dc: + b6:c2:aa:9f:f8:51:a1:0e:2e:97:0f:90:13:22:4c: + 8b:f1:ff:3c:6b:eb:91:29:7d:4c:df:7c:05:dd:ad: + ea:4a:4c:ad:0a:d6:6f:8e:51:b0:88:58:42:88:2c: + 16:d4:47:1d:b8:8f:b3:4e:0d:12:df:4c:14:f6:27: + 20:3f:94:9a:23:81:48 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv03.crt01.example.com, IP Address:10.53.0.3, IP Address:FD92:7065:B8E:FFFF:0:0:0:3 + Signature Algorithm: sha256WithRSAEncryption + 8f:96:88:82:94:76:8e:97:b6:75:8b:e9:2b:4f:f3:8f:14:5c: + 50:00:ca:67:96:9e:2e:bd:53:25:25:40:6d:c5:56:e6:1a:f6: + cb:fb:58:fc:b3:56:9d:fc:0b:e2:8e:99:7e:e8:e6:ad:b6:e7: + e6:3e:8a:59:ef:3e:76:a4:ed:7b:58:fd:a3:4b:aa:4e:11:e1: + 57:bf:b1:23:a5:a1:00:f8:95:07:c8:7d:ee:ac:a7:c8:24:ee: + cf:e8:c5:a4:9f:96:27:c9:47:c1:7d:11:de:66:d0:6d:d1:8d: + e7:8f:a0:0f:46:d9:2e:70:f3:9f:ac:6a:b0:3f:5a:dc:70:d4: + b9:a5:f3:ff:5c:21:50:5d:c2:a2:46:26:25:2a:2f:8a:aa:7a: + fd:76:31:5f:e0:25:a3:ee:df:36:f0:ab:05:a1:5d:0d:3c:6b: + 2c:1d:d5:c5:73:9c:a0:57:1f:c4:26:e6:dc:a1:7c:25:08:21: + 61:28:e2:b3:f5:51:83:20:73:14:19:8f:47:79:69:bc:2b:22: + f2:17:62:1d:83:f7:4f:a9:c4:51:68:e0:a9:d7:9f:17:6a:d2: + fd:f7:04:ce:a4:f5:8e:eb:31:b4:bf:c6:2d:da:0c:70:6e:0c: + a5:75:21:54:3c:f6:3d:36:b8:8a:d8:b6:7b:77:7e:54:1d:9f: + 91:8f:02:a6:d1:2c:a7:30:d1:cc:e6:d9:6b:76:80:15:4b:ba: + fd:55:20:cc:b2:99:85:57:60:11:97:c5:e7:28:50:a6:17:af: + d2:bd:1b:7e:06:48:7f:63:dc:70:f8:3f:22:9f:41:a1:66:f5: + a7:81:99:cb:07:0e:8a:9a:bb:12:f6:c0:fe:59:0c:00:37:15: + b2:9d:f0:f9:93:d1:1a:b6:f8:0a:6b:bd:9e:92:32:45:f5:a2: + 44:f0:45:8d:1a:d0:10:b2:db:98:c4:c7:5e:c1:e8:f3:94:33: + 6c:06:f5:1a:cc:51:23:72:ae:37:2f:57:d4:f8:ac:1f:25:b4: + d3:bf:99:9b:ac:fc +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAQwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTgxNVoYDzIwNTIwMjAx +MTc1ODE1WjAiMSAwHgYDVQQDDBdzcnYwMy5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEXbuRs3Zb+xoYpaOQCNShU7Q5q4L/+ofZmDqJzc +tsKqn/hRoQ4ulw+QEyJMi/H/PGvrkSl9TN98Bd2t6kpMrQrWb45RsIhYQogsFtRH +HbiPs04NEt9MFPYnID+UmiOBSKM+MDwwOgYDVR0RBDMwMYIXc3J2MDMuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AAOHEP2ScGULjv//AAAAAAAAAAMwDQYJKoZIhvcNAQEL +BQADggGBAI+WiIKUdo6XtnWL6StP848UXFAAymeWni69UyUlQG3FVuYa9sv7WPyz +Vp38C+KOmX7o5q225+Y+ilnvPnak7XtY/aNLqk4R4Ve/sSOloQD4lQfIfe6sp8gk +7s/oxaSflifJR8F9Ed5m0G3RjeePoA9G2S5w85+sarA/Wtxw1Lml8/9cIVBdwqJG +JiUqL4qqev12MV/gJaPu3zbwqwWhXQ08aywd1cVznKBXH8Qm5tyhfCUIIWEo4rP1 +UYMgcxQZj0d5abwrIvIXYh2D90+pxFFo4KnXnxdq0v33BM6k9Y7rMbS/xi3aDHBu +DKV1IVQ89j02uIrYtnt3flQdn5GPAqbRLKcw0czm2Wt2gBVLuv1VIMyymYVXYBGX +xecoUKYXr9K9G34GSH9j3HD4PyKfQaFm9aeBmcsHDoqauxL2wP5ZDAA3FbKd8PmT +0Rq2+AprvZ6SMkX1okTwRY0a0BCy25jEx17B6POUM2wG9RrMUSNyrjcvV9T4rB8l +tNO/mZus/A== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem new file mode 100644 index 0000000..b4e2d22 --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52005.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207429 (0x6bb3183cdef52005) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 8 17:59:14 2022 GMT + Not After : Feb 1 17:59:14 2052 GMT + Subject: CN=srv04.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:9e:43:d7:cc:29:e1:8e:4b:35:a1:8f:b7:8f:30: + 0f:56:b3:5b:7f:c0:62:9b:23:21:70:b1:2b:e7:73: + f9:ea:38:01:66:4b:52:43:31:cf:10:69:15:bf:6b: + 08:f3:69:07:3f:99:bb:b8:70:d0:3b:89:22:1d:f2: + 25:42:5a:3e:55:91:c3:fc:b4:be:c7:2d:86:51:14: + c4:ab:fe:7c:54:34:67:c7:5e:db:86:84:cc:66:eb: + 54:af:9d:7d:dc:ce:18 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv04.crt01.example.com, IP Address:10.53.0.4, IP Address:FD92:7065:B8E:FFFF:0:0:0:4 + Signature Algorithm: sha256WithRSAEncryption + 48:b5:38:59:79:e6:51:a6:ea:80:d7:d1:3c:29:03:70:31:e4: + 43:b4:e3:09:e7:e1:37:8c:d0:0f:2a:19:7a:f2:5a:6d:76:cd: + 17:7a:66:1c:3e:74:56:24:b8:29:06:55:b2:1c:af:9a:42:05: + 93:a4:70:cb:a5:68:85:ab:71:53:da:d9:29:a3:f4:2a:1e:df: + 0c:ec:7d:52:55:fa:9b:e6:a0:18:d5:4c:da:e6:d2:60:da:bc: + 09:5b:13:53:6d:c7:d2:30:b9:a8:a5:02:7f:a3:66:28:34:93: + de:55:a0:de:b5:c8:dc:43:7b:b9:03:06:1f:ce:8c:5f:82:d8: + af:40:56:ce:f8:b9:d4:73:1c:ae:c9:cb:1d:0f:a2:52:71:9b: + 8b:05:f4:d6:0b:1e:a8:db:0f:29:a0:43:b5:2f:56:09:d8:68: + 58:9c:e5:6a:df:38:91:56:9d:44:e5:d2:ca:9a:b1:41:a1:01: + 0c:68:a0:f5:0a:f7:98:4f:d5:a0:6f:99:59:a0:e0:cb:49:57: + 26:20:09:5a:fa:c2:75:40:f6:1b:6a:ac:55:47:50:8d:38:81: + 61:79:44:e7:d5:d1:b3:c7:3b:db:ec:44:59:ef:e1:82:31:a3: + 38:4c:de:40:11:31:52:8b:bb:1c:af:be:ce:c5:2b:f5:0d:c0: + 60:13:fb:7e:da:22:41:d4:85:5e:4d:ba:db:f8:f7:26:61:32: + 26:fe:fe:9e:37:a3:cc:25:3b:3c:c8:b5:a7:a5:5c:d9:4d:8f: + a8:f2:86:98:79:b3:00:08:0f:f2:c9:1f:c6:3f:07:ad:e4:a7: + 8d:86:3d:15:fa:5b:1a:0f:96:67:b6:0a:78:0a:bb:6e:05:a6: + 54:29:48:b4:f9:48:0d:7f:f0:13:65:32:2f:c5:ee:ab:b8:e8: + 0d:b2:f9:c9:96:d2:cf:51:a2:64:3c:58:0f:65:6f:c6:99:93: + 76:2c:42:08:d9:f3:f3:13:cd:41:b6:67:8f:1d:9a:2f:da:93: + 3d:26:4c:9a:11:c1 +-----BEGIN CERTIFICATE----- +MIIDMzCCAZugAwIBAgIIa7MYPN71IAUwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIwODE3NTkxNFoYDzIwNTIwMjAx +MTc1OTE0WjAiMSAwHgYDVQQDDBdzcnYwNC5jcnQwMS5leGFtcGxlLmNvbTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABJ5D18wp4Y5LNaGPt48wD1azW3/AYpsjIXCxK+dz ++eo4AWZLUkMxzxBpFb9rCPNpBz+Zu7hw0DuJIh3yJUJaPlWRw/y0vscthlEUxKv+ +fFQ0Z8de24aEzGbrVK+dfdzOGKM+MDwwOgYDVR0RBDMwMYIXc3J2MDQuY3J0MDEu +ZXhhbXBsZS5jb22HBAo1AASHEP2ScGULjv//AAAAAAAAAAQwDQYJKoZIhvcNAQEL +BQADggGBAEi1OFl55lGm6oDX0TwpA3Ax5EO04wnn4TeM0A8qGXryWm12zRd6Zhw+ +dFYkuCkGVbIcr5pCBZOkcMulaIWrcVPa2Smj9Coe3wzsfVJV+pvmoBjVTNrm0mDa +vAlbE1Ntx9IwuailAn+jZig0k95VoN61yNxDe7kDBh/OjF+C2K9AVs74udRzHK7J +yx0PolJxm4sF9NYLHqjbDymgQ7UvVgnYaFic5WrfOJFWnUTl0sqasUGhAQxooPUK +95hP1aBvmVmg4MtJVyYgCVr6wnVA9htqrFVHUI04gWF5ROfV0bPHO9vsRFnv4YIx +ozhM3kARMVKLuxyvvs7FK/UNwGAT+37aIkHUhV5Nutv49yZhMib+/p43o8wlOzzI +taelXNlNj6jyhph5swAID/LJH8Y/B63kp42GPRX6WxoPlme2CngKu24FplQpSLT5 +SA1/8BNlMi/F7qu46A2y+cmW0s9RomQ8WA9lb8aZk3YsQgjZ8/MTzUG2Z48dmi/a +kz0mTJoRwQ== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem new file mode 100644 index 0000000..4befde4 --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52006.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207430 (0x6bb3183cdef52006) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Aug 15 08:00:00 2012 GMT + Not After : Aug 15 09:00:00 2012 GMT + Subject: CN=srv01.crt03-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:1f:d5:7b:ab:73:b2:70:15:fd:33:26:02:5c:76: + 16:80:0c:70:7d:57:83:75:ac:3c:b7:4a:02:46:35: + c1:1b:c1:7a:bd:be:f2:04:9a:7f:69:83:7f:54:9a: + 1b:10:62:d7:70:bd:ef:26:90:51:50:10:77:56:b7: + 1a:2f:44:5e:91:46:36:e1:2e:a4:4c:67:2e:62:a8: + 7f:1a:15:10:44:68:8b:18:ea:cf:b8:96:09:bf:b5: + 3a:d1:ef:10:8f:9f:bb + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt03-expired.example.com, IP Address:10.53.0.1, IP Address:FD92:7065:B8E:FFFF:0:0:0:1 + Signature Algorithm: sha256WithRSAEncryption + 25:35:08:f6:e7:f0:83:81:be:65:31:1b:78:a8:04:84:fe:6a: + 2a:1a:5d:c1:73:20:88:08:11:d8:27:be:a5:8e:3c:df:e2:a6: + 19:c5:41:40:ea:01:91:85:99:8d:17:4e:4d:9a:3c:03:f9:78: + 4c:8a:20:41:5e:96:d6:64:83:2f:b2:fe:e7:77:09:f9:91:bd: + 22:1a:57:8b:f6:24:bc:7b:48:2b:2e:14:b7:32:bd:46:91:99: + 5e:21:9a:d3:15:a7:27:e1:c0:3a:c7:f5:f9:94:3f:6d:14:7e: + 0b:02:bf:05:d9:ac:10:8a:7e:b0:37:36:cd:cb:4a:b4:e1:01: + c7:04:8d:83:f3:c6:79:ff:ff:6c:f0:a4:bf:3c:12:61:ea:15: + ac:30:62:26:e3:c3:4e:7d:5c:68:d8:88:de:35:8d:44:75:8c: + a8:c1:0d:07:67:b5:d0:42:43:41:1f:39:a0:47:35:46:d7:0f: + 89:aa:e8:d3:86:45:9a:fb:33:01:06:23:64:53:24:48:5b:69: + fa:cf:d9:81:fb:5e:7e:7b:82:65:56:c6:46:65:5c:e1:4f:f2: + 3c:09:3c:28:5f:c9:e3:a5:24:e3:7b:aa:b5:b1:8a:6a:b2:02: + 32:5f:24:05:f1:67:c8:54:17:0c:cd:ca:3d:e4:44:3e:23:3a: + 7c:63:b6:f9:61:3a:21:e7:8f:27:ad:c3:26:86:39:49:6c:41: + 40:7f:1d:48:69:8d:db:6f:42:e4:09:fe:24:62:bd:8e:2e:54: + 25:f0:14:c2:d8:43:95:09:2e:5f:72:4f:43:b5:9a:8b:bb:8c: + 44:c6:77:c9:05:fb:1a:9f:d7:b6:a6:42:d9:5c:3d:a5:09:0f: + 9e:e0:c7:06:32:f1:ff:c9:53:5e:42:d4:2a:33:ad:06:ea:ec: + b0:26:d3:3c:ef:65:af:15:8e:7b:20:49:ad:f1:56:ef:17:6b: + fc:f4:d8:7c:82:9f:30:19:d0:bc:9c:79:e2:dc:9d:a7:f9:6b: + 6f:65:ae:21:a0:94 +-----BEGIN CERTIFICATE----- +MIIDQTCCAamgAwIBAgIIa7MYPN71IAYwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNTA4MDAwMFoXDTEyMDgxNTA5 +MDAwMFowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDMtZXhwaXJlZC5leGFtcGxlLmNv +bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABB/Ve6tzsnAV/TMmAlx2FoAMcH1Xg3Ws +PLdKAkY1wRvBer2+8gSaf2mDf1SaGxBi13C97yaQUVAQd1a3Gi9EXpFGNuEupExn +LmKofxoVEERoixjqz7iWCb+1OtHvEI+fu6NGMEQwQgYDVR0RBDswOYIfc3J2MDEu +Y3J0MDMtZXhwaXJlZC5leGFtcGxlLmNvbYcECjUAAYcQ/ZJwZQuO//8AAAAAAAAA +ATANBgkqhkiG9w0BAQsFAAOCAYEAJTUI9ufwg4G+ZTEbeKgEhP5qKhpdwXMgiAgR +2Ce+pY483+KmGcVBQOoBkYWZjRdOTZo8A/l4TIogQV6W1mSDL7L+53cJ+ZG9IhpX +i/YkvHtIKy4UtzK9RpGZXiGa0xWnJ+HAOsf1+ZQ/bRR+CwK/BdmsEIp+sDc2zctK +tOEBxwSNg/PGef//bPCkvzwSYeoVrDBiJuPDTn1caNiI3jWNRHWMqMENB2e10EJD +QR85oEc1RtcPiaro04ZFmvszAQYjZFMkSFtp+s/ZgftefnuCZVbGRmVc4U/yPAk8 +KF/J46Uk43uqtbGKarICMl8kBfFnyFQXDM3KPeREPiM6fGO2+WE6IeePJ63DJoY5 +SWxBQH8dSGmN229C5An+JGK9ji5UJfAUwthDlQkuX3JPQ7Wai7uMRMZ3yQX7Gp/X +tqZC2Vw9pQkPnuDHBjLx/8lTXkLUKjOtBurssCbTPO9lrxWOeyBJrfFW7xdr/PTY +fIKfMBnQvJx54tydp/lrb2WuIaCU +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem new file mode 100644 index 0000000..0b4c115 --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52007.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207431 (0x6bb3183cdef52007) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 10 17:44:20 2022 GMT + Not After : Feb 3 17:44:20 2052 GMT + Subject: CN=srv01.client01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:5e:93:6a:7a:da:75:cc:64:08:e4:f8:f9:2f:2b: + 85:36:ee:e1:df:fa:cd:4c:60:f1:44:b5:16:7b:f9: + 03:cf:a0:08:67:6f:ae:27:a3:95:8a:68:1e:63:ab: + cf:2e:20:62:52:e7:8c:3e:1e:ef:de:0d:69:64:65: + b6:e4:df:fe:1a:48:f8:68:75:84:83:11:fb:81:59: + 0e:c1:96:48:7f:24:da:11:dd:ac:cb:0a:c5:09:78: + 24:31:3a:df:37:e6:b3 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client01.example.com + Signature Algorithm: sha256WithRSAEncryption + 82:bd:eb:8f:4e:a5:d2:46:c7:d8:70:3c:34:1d:58:43:1b:81: + 16:5d:c2:b0:76:4b:a9:f2:10:14:23:e4:ef:dc:59:03:b6:7f: + b0:40:34:e5:d0:82:4b:95:a6:07:9a:45:51:94:cf:08:c2:4e: + c9:44:d5:f3:b6:ed:f2:a0:01:94:ad:e0:0e:0f:ab:85:6f:35: + 4b:07:c8:97:25:fb:69:ff:a1:99:bc:ec:70:6c:51:b5:32:95: + e9:c9:45:cf:45:e2:c5:5e:b1:59:a2:e1:f2:83:c8:87:68:c4: + 60:e2:db:50:6c:18:64:1b:9a:9a:cc:7c:e7:fd:d9:f2:b7:d1: + de:1d:ec:29:c9:58:db:7b:9a:a1:06:9a:ce:36:a0:45:10:dc: + 7d:81:24:21:34:30:4c:71:f9:fc:96:37:d6:cf:0d:9d:11:12: + c7:62:bc:19:5b:79:e5:e0:37:e8:17:36:4b:13:af:fa:2c:2e: + 36:d9:be:53:e1:c3:f9:bc:94:a6:7a:97:14:99:36:f9:14:38: + 11:20:3a:2a:9d:fd:64:63:d0:a2:8f:f0:99:a9:02:ca:57:48: + d2:7d:65:44:b6:85:a0:38:ec:e8:19:7e:c2:48:e3:1d:22:53: + cf:3b:d4:0a:98:e1:72:62:ec:8b:01:3f:5a:ea:26:2c:8c:16: + c3:80:5a:c2:5d:40:c5:65:1c:e2:9a:e3:d6:65:16:ee:dc:17: + 30:d8:26:87:92:d0:ef:c7:72:07:99:86:05:9e:49:35:41:33: + b9:bb:cb:1b:25:50:70:85:e3:0f:c7:b9:b2:37:00:1b:87:a2: + 47:97:34:5b:cd:dc:66:22:e5:de:25:ec:57:fe:37:75:2c:03: + 10:f4:d4:a7:cc:f5:4b:0b:ff:eb:d3:a6:78:2e:cd:8f:65:51: + a7:8c:ef:83:67:ec:94:13:c2:1f:74:74:55:7c:a3:0b:b7:2f: + 80:5a:62:04:1d:a2:c0:c1:de:b2:7d:31:3b:a1:fa:f7:40:a7: + bd:12:25:95:5b:8b +-----BEGIN CERTIFICATE----- +MIIDITCCAYmgAwIBAgIIa7MYPN71IAcwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMDE3NDQyMFoYDzIwNTIwMjAz +MTc0NDIwWjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLmNvbTB2 +MBAGByqGSM49AgEGBSuBBAAiA2IABF6TanradcxkCOT4+S8rhTbu4d/6zUxg8US1 +Fnv5A8+gCGdvriejlYpoHmOrzy4gYlLnjD4e794NaWRltuTf/hpI+Gh1hIMR+4FZ +DsGWSH8k2hHdrMsKxQl4JDE63zfms6MpMCcwJQYDVR0RBB4wHIIac3J2MDEuY2xp +ZW50MDEuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggGBAIK9649OpdJGx9hw +PDQdWEMbgRZdwrB2S6nyEBQj5O/cWQO2f7BANOXQgkuVpgeaRVGUzwjCTslE1fO2 +7fKgAZSt4A4Pq4VvNUsHyJcl+2n/oZm87HBsUbUylenJRc9F4sVesVmi4fKDyIdo +xGDi21BsGGQbmprMfOf92fK30d4d7CnJWNt7mqEGms42oEUQ3H2BJCE0MExx+fyW +N9bPDZ0REsdivBlbeeXgN+gXNksTr/osLjbZvlPhw/m8lKZ6lxSZNvkUOBEgOiqd +/WRj0KKP8JmpAspXSNJ9ZUS2haA47OgZfsJI4x0iU8871AqY4XJi7IsBP1rqJiyM +FsOAWsJdQMVlHOKa49ZlFu7cFzDYJoeS0O/HcgeZhgWeSTVBM7m7yxslUHCF4w/H +ubI3ABuHokeXNFvN3GYi5d4l7Ff+N3UsAxD01KfM9UsL/+vTpnguzY9lUaeM74Nn +7JQTwh90dFV8owu3L4BaYgQdosDB3rJ9MTuh+vdAp70SJZVbiw== +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem new file mode 100644 index 0000000..1b43bbd --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52008.pem @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207432 (0x6bb3183cdef52008) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Feb 11 13:21:12 2022 GMT + Not After : Feb 4 13:21:12 2052 GMT + Subject: CN=srv01.client02-ns2.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:e6:45:fa:57:12:6c:59:10:23:8b:7a:5c:76:33: + eb:3b:41:fa:b7:1c:90:b3:2f:33:2d:45:7b:e3:e5: + b6:a5:a2:a2:a4:14:f4:50:9d:b0:c6:38:ba:e9:45: + 65:a4:65:b9:10:32:2f:93:9b:d5:d8:cf:b4:29:5b: + dc:4e:c8:ec:a6:9f:58:76:24:f4:c5:d1:48:55:52: + eb:5d:b0:85:93:85:ee:3e:b8:c4:b1:cd:08:59:95: + 12:ff:7b:9b:ee:6a:b9 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client02-ns2.example.com + Signature Algorithm: sha256WithRSAEncryption + 43:ec:0f:62:17:f6:f4:90:3b:7c:36:21:f2:18:94:a6:42:51: + 1e:1d:2a:43:8f:05:b7:8d:3c:ca:f0:20:2f:65:4b:be:48:ad: + 6a:0a:cc:2d:1f:d6:27:1d:af:4a:36:86:ed:0d:03:75:c5:71: + ec:58:9b:ec:f9:0f:e4:83:ef:6f:91:da:20:73:47:ac:e7:c7: + 8b:22:b2:d1:6e:a0:b0:d6:1c:4c:70:1e:74:08:1d:7f:61:06: + e5:be:f3:e8:c4:15:60:e2:b0:02:9b:f0:13:af:76:5b:a8:c7: + 91:2c:10:5f:0d:32:89:51:5a:7f:17:1b:7c:c6:46:97:ee:e7: + bb:8a:48:38:a2:52:d4:ff:3b:1c:ec:4a:a9:8c:a5:23:3a:04: + bb:d7:b8:ad:5b:69:7f:1d:be:ca:96:e0:eb:56:05:43:ee:c8: + ff:2c:48:03:00:c6:c2:ac:fc:4e:15:47:86:c5:33:ed:70:f6: + 98:bc:0b:07:b9:5b:1a:ec:fd:3c:bf:26:61:68:fc:db:02:55: + 07:ae:76:0e:be:ff:c5:b8:56:fb:52:54:a4:b1:2d:64:b4:1d: + 55:02:4f:da:06:bd:26:e4:22:d2:94:1f:7e:29:c4:97:10:d1: + 75:7d:41:53:be:46:52:70:b1:d9:ff:bb:9f:96:19:e3:a0:ba: + d0:4a:5a:8d:da:22:73:89:f0:4c:e6:18:80:53:be:bd:64:56: + 6a:c9:58:71:40:66:9e:4a:3e:31:3b:74:9e:6e:6a:f5:65:ca: + 93:06:52:00:74:65:a0:3a:eb:2e:56:56:d2:a5:4b:0e:85:17: + 25:78:cb:f3:f9:53:7b:85:f9:82:15:87:bc:36:70:b5:69:64: + 48:11:79:b9:2c:2e:cc:09:fd:0f:b0:b7:cd:97:3b:c7:0f:49: + 1a:fc:15:49:d6:1c:a9:dc:14:ff:44:d2:be:5a:36:00:66:0c: + d5:b8:bf:16:9e:60:27:79:c0:f5:b4:ff:2f:af:8c:b2:49:75: + 61:44:05:1a:e8:cd +-----BEGIN CERTIFICATE----- +MIIDKTCCAZGgAwIBAgIIa7MYPN71IAgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDIxMTEzMjExMloYDzIwNTIwMjA0 +MTMyMTEyWjApMScwJQYDVQQDDB5zcnYwMS5jbGllbnQwMi1uczIuZXhhbXBsZS5j +b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATmRfpXEmxZECOLelx2M+s7Qfq3HJCz +LzMtRXvj5baloqKkFPRQnbDGOLrpRWWkZbkQMi+Tm9XYz7QpW9xOyOymn1h2JPTF +0UhVUutdsIWThe4+uMSxzQhZlRL/e5vuarmjLTArMCkGA1UdEQQiMCCCHnNydjAx +LmNsaWVudDAyLW5zMi5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAQ+wP +Yhf29JA7fDYh8hiUpkJRHh0qQ48Ft408yvAgL2VLvkitagrMLR/WJx2vSjaG7Q0D +dcVx7Fib7PkP5IPvb5HaIHNHrOfHiyKy0W6gsNYcTHAedAgdf2EG5b7z6MQVYOKw +ApvwE692W6jHkSwQXw0yiVFafxcbfMZGl+7nu4pIOKJS1P87HOxKqYylIzoEu9e4 +rVtpfx2+ypbg61YFQ+7I/yxIAwDGwqz8ThVHhsUz7XD2mLwLB7lbGuz9PL8mYWj8 +2wJVB652Dr7/xbhW+1JUpLEtZLQdVQJP2ga9JuQi0pQffinElxDRdX1BU75GUnCx +2f+7n5YZ46C60Epajdoic4nwTOYYgFO+vWRWaslYcUBmnko+MTt0nm5q9WXKkwZS +AHRloDrrLlZW0qVLDoUXJXjL8/lTe4X5ghWHvDZwtWlkSBF5uSwuzAn9D7C3zZc7 +xw9JGvwVSdYcqdwU/0TSvlo2AGYM1bi/Fp5gJ3nA9bT/L6+Mskl1YUQFGujN +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem new file mode 100644 index 0000000..99e4a71 --- /dev/null +++ b/bin/tests/system/doth/CA/newcerts/6BB3183CDEF52009.pem @@ -0,0 +1,69 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 7760573232607207433 (0x6bb3183cdef52009) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Aug 14 05:00:00 2012 GMT + Not After : Aug 14 06:00:00 2012 GMT + Subject: CN=srv01.client03-ns2-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:38:9a:9b:c2:6a:82:a6:d1:50:8a:78:7a:d1:be: + 61:be:d4:b6:d3:d6:a2:02:97:a4:48:50:c0:c5:1d: + d8:2d:23:19:25:6e:91:02:1d:69:c2:77:d6:f1:a8: + 4f:4a:9a:1d:3c:69:5a:89:41:0a:f2:e0:64:57:1b: + 0e:9e:df:9f:4c:7b:3c:42:dc:21:c8:2c:95:ab:b3: + 4c:5f:56:c4:70:ee:8a:a4:e4:46:c4:9e:98:f5:c8: + 7b:b2:73:d7:45:93:f0 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client03-ns2-expired.example.com + Signature Algorithm: sha256WithRSAEncryption + 38:12:1f:5f:26:b6:8e:9b:3f:77:89:5a:b8:e8:46:78:c3:d6: + f0:0c:67:5f:d5:a3:9c:f6:f2:0a:ae:9c:87:74:9f:a3:5b:8a: + 27:58:47:e5:78:1a:e9:db:b5:cc:28:a7:f8:18:e3:e7:20:43: + cf:82:06:5d:a1:d0:82:ab:15:be:86:46:1e:e6:4d:ad:78:a4: + 16:6c:99:41:3d:29:21:c8:6b:9d:3d:4a:cd:93:37:1f:1c:88: + c7:ae:b6:7c:73:42:57:57:32:9d:e8:c6:e2:3e:da:12:57:3e: + c8:56:4a:bb:d4:01:fc:8e:30:8d:19:fe:61:3d:5e:02:64:65: + a2:46:b3:6e:ea:f9:cb:4e:f0:b9:f6:bc:6b:38:10:19:d0:93: + f8:f7:d9:4c:d2:87:2c:7f:dc:f5:00:c6:29:dd:00:5e:d2:f4: + df:52:fb:7a:5a:ad:98:36:77:72:1f:01:ed:48:91:48:16:2d: + 35:a5:15:21:98:ff:7e:5d:a1:45:c9:5f:9d:c2:3e:e5:98:e2: + ee:ce:4d:18:76:3d:8a:0a:64:9b:f1:19:9d:b6:82:af:1b:15: + d3:48:69:f1:9b:67:76:1b:41:8e:1d:69:d5:31:64:95:01:41: + 73:c1:a9:29:53:6b:f3:29:ad:e0:96:52:8e:3e:8d:c1:8e:d8: + b5:0c:94:5f:a2:6c:3c:0f:3e:5b:10:af:21:00:74:d0:b7:30: + 6c:44:fb:3d:09:46:8d:1d:e6:c2:e4:0a:5b:f4:eb:e1:71:c7: + d5:36:13:90:05:fe:65:16:61:24:b5:41:f2:10:bd:2c:c3:34: + 69:15:25:d1:32:f2:b3:d7:da:23:1b:e9:5b:33:63:43:c8:dc: + 68:f2:31:b5:93:0e:64:ea:9a:45:36:9f:96:44:38:1e:4e:d8: + 45:ba:37:68:06:4d:da:d4:16:d3:3e:77:86:4e:8d:58:d6:06: + a8:60:11:4d:d9:81:f3:85:2b:ee:58:50:6e:ea:2b:f7:84:00: + 9c:ec:a1:90:d4:94 +-----BEGIN CERTIFICATE----- +MIIDNzCCAZ+gAwIBAgIIa7MYPN71IAkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTEyMDgxNDA1MDAwMFoXDTEyMDgxNDA2 +MDAwMFowMTEvMC0GA1UEAwwmc3J2MDEuY2xpZW50MDMtbnMyLWV4cGlyZWQuZXhh +bXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ4mpvCaoKm0VCKeHrRvmG+ +1LbT1qICl6RIUMDFHdgtIxklbpECHWnCd9bxqE9Kmh08aVqJQQry4GRXGw6e359M +ezxC3CHILJWrs0xfVsRw7oqk5EbEnpj1yHuyc9dFk/CjNTAzMDEGA1UdEQQqMCiC +JnNydjAxLmNsaWVudDAzLW5zMi1leHBpcmVkLmV4YW1wbGUuY29tMA0GCSqGSIb3 +DQEBCwUAA4IBgQA4Eh9fJraOmz93iVq46EZ4w9bwDGdf1aOc9vIKrpyHdJ+jW4on +WEfleBrp27XMKKf4GOPnIEPPggZdodCCqxW+hkYe5k2teKQWbJlBPSkhyGudPUrN +kzcfHIjHrrZ8c0JXVzKd6MbiPtoSVz7IVkq71AH8jjCNGf5hPV4CZGWiRrNu6vnL +TvC59rxrOBAZ0JP499lM0ocsf9z1AMYp3QBe0vTfUvt6Wq2YNndyHwHtSJFIFi01 +pRUhmP9+XaFFyV+dwj7lmOLuzk0Ydj2KCmSb8RmdtoKvGxXTSGnxm2d2G0GOHWnV +MWSVAUFzwakpU2vzKa3gllKOPo3Bjti1DJRfomw8Dz5bEK8hAHTQtzBsRPs9CUaN +HebC5Apb9OvhccfVNhOQBf5lFmEktUHyEL0swzRpFSXRMvKz19ojG+lbM2NDyNxo +8jG1kw5k6ppFNp+WRDgeTthFujdoBk3a1BbTPneGTo1Y1gaoYBFN2YHzhSvuWFBu +6iv3hACc7KGQ1JQ= +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/CA/private/CA.key b/bin/tests/system/doth/CA/private/CA.key new file mode 100644 index 0000000..2d5419d --- /dev/null +++ b/bin/tests/system/doth/CA/private/CA.key @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEAouoRHoAc6VCmxNTU6Ge7s+xDFGO0wXJJIsP+8nUyyjWvGCOC +aQYLhb1kLA2NHRhSSKFcMh8jcd7Hlvy6CAec1j2dsWzryy3HgPrdjWaW3PfBO41D +lUtdt8hA/p6pX2YwqvWbdK/3s8J0LY5xRZKNZnFOB/Sb4PGiIJ1NgMRO/M3IlPQm +PO/faRRTU4SI26KCPKFW342826Zi88YwOd6w5mQU4fskk5TGtlNqE+Fj40ZbWVpy +VXoEUS6RveRp020NX5CQG49SLtdF05AnnsATqmgNVCXptGuqW8uaHRONeGO3NBEy +nJmibWBDUMjtCCcGVgyrVXuTkyAJJWpImnshUwgMNYebRwmC2iVv2LtsJS5eUTUH +EWffnFl55XU2PkyNYgY35gA4y3SiWFJYV8+5FibU4ut0nb+lmHBF8WlqcU/kd3tp +Gkf0exjqOIHZFqV9bIhpUbXhxx9v9+gkkGQ9nrXE1KRlvigxxUeIK5xHy9a7fVIL +wo6WuCnLLJmbVkklAgMBAAECggGBAI5ZV3v/FUQIZK+4CBDKEwizeClotZgR9DWc +bDgOj8KABe5hmKGL1qWVRuH3NUYm6j7sP1LMQnxM3LjhOuupOzE3xYIyWhW+eoQI +r23OJiQNl5ohZNweblUXdTMGD5h8AipfUOY0m4tGbZ0gyXixBTxt5HCvG0UB3VgC +GqZY4Wujo5ADhSXZsqxuRiDDvZGr/YBcuTu87Tg/ulam5ZyrKIcnC9gpSVxqsva9 +DAMy/cSoxUjd7ukhJISK3G3AF3fV4GSslQcJTlyJ2D3+LnqPuHJKYTI4hc46lN3x +E2g24GdSCPYf6SoEPwACXtbavV8TXwQPJrHN+f+0/ePCI4jkYe5NoA3gwVgMb/WB +wFchxzVh3V4e8tPGiG+ofKl81DSAW8VZCJLUIbTEce9oxafPT78WJxdC0wWbh5S8 +V/qN6sW/yWnK3oY9SilWhJGRwKOZ+8xtStaDeCzyCaOqEcWi8ZR0QfC33UozlhdC +SrMKnOXmn/rUuXGrVR56IzIl0M7YAQKBwQDM3GJDdlFuHn6L0syKYdHDS8gXD9ke +s+ochIP6jvkEPcayaEoZGl8s7RT3iztqXod7wLaZdotktxfDAZnJfeuOcVrCu+Bx +HLytnBvV6czMfp3REGgQAJQeusSgtlBCTHHVOsDzIjdnkY3WBa7IiFYWO5wnYrGx +r3ucnwnHaUVDMj1r4YI7mYIpCuYQl6eGyW7mhWewyhVwoQXKbifdrXxjvOigL0Cp +tgsoU9pql3hpphOaYMX6hLOincTfaMxfnCECgcEAy5UXp3dA0OwK+4iDGKr+cUpk +AtGTheiE+8zEVh2KYFLt921mW/QZiB1+xtnkknp3c7u07Ugk8jAEXzCkwMnN5ZCx +LrJ72fC+cLIAbRm6/vMMP8iz83wyttao4qNMeoOBBfE9rEiP+lrugpv282V3ZHYa +IUZWTeugJbckUHTbD3RZQExmQcRVG3m/TzonBfoZ8HoRj/n3d7V2T911cHUhi8Xn +RQIi2m63VofOIep86LgartlKneMWnL0oOPq4RKyFAoHAZUzpDkD4nUJZAx025Yrf +ZfoYNEcy7vq6XmWsuX5vZoiBs4DcezNOMvH9NzdTJxMdXbV61cIHxcK/7j7hZABv +NZ2Z6sdqgaRbLGIQZaPaEJjfwxygyKDwnY1vY6UjZNVWSMFn3hJiYUVZZKakuiao +ow/Q9KzZ/2ot7tG5zTCh/ktekfUOKBiNg2wPPc8wGPeMblMzZflXxrzpFyOHdRev +dcZZJbSX/hO1yrhEPgculNd5xBHsdCegiF4JlwvEW9bhAoHAZQQiy5bx03j8bhkr +q6bVQFPAUmG5iL16lxLg7TYVPnyH1bk0DDaQIKk6CeN+dmxML2IZgY/FvWK0GKOj +bIH2J43nTRuFNvwtEvBQI9KbpfvlvRSSriOXaoATJvoObdAoylEM4BrVTk2mgapw +HA/h8Thk+NPU6S8ctPouC7ogJIf/7Va7erC35j0//0kEqgOSsW9wnXdUItMo1LI3 +nsiQD7Hwcp5/utErKcWTM+MNfdA0dUQesT9ILhfyCGvn2TOdAoHBAKldZkDyRcu9 +r9uDF1bhUEnpV2k4hgvTuCvQ3rzyx3WrVT8ChEmePC8Ke5A54ffu/YdbpDLbdf2c +j4n5CQhHbMIZs3P2hB3WqDCImApCfMbXaltfBbaT0j7uLJPMp+2+f/wWYpc3R+bn +HVnaRI2PoXXmG9OjQSQdVZ5gNpkEuemAo3dJOSS6BMqQaSxUynGy7o/a/d4izBjd +B58Fwq3sZI/Xv90Se9+b6ICST3YJ3p0vn8RKzmlCQjLg/xynpCByiw== +-----END RSA PRIVATE KEY----- diff --git a/bin/tests/system/doth/CA/serial b/bin/tests/system/doth/CA/serial new file mode 100644 index 0000000..a20b068 --- /dev/null +++ b/bin/tests/system/doth/CA/serial @@ -0,0 +1 @@ +6BB3183CDEF5200A diff --git a/bin/tests/system/doth/README.curl b/bin/tests/system/doth/README.curl new file mode 100644 index 0000000..475f20f --- /dev/null +++ b/bin/tests/system/doth/README.curl @@ -0,0 +1,38 @@ + + +DoH query values that can be passed on the command line for testing +with curl can be obtained by encoding binary DNS messages into +base64url, with trailing '='s removed. + +For example: + +$ perl bin/tests/system/fromhex.pl << EOF | base64url + # Transaction ID + 0001 + # Standard query + 0000 + # Questions: 1, Additional: 0 + 0001 0000 0000 0000 + # QNAME: example + 07 6578616d706c65 00 + # Type: SOA + 0006 + Class: IN + 0001 +EOF + +This produces the string "AAEAAAABAAAAAAAAB2V4YW1wbGUAAAbFrMonAAE=". With +the trailing '=' removed, this can then be passed to curl: + +curl "https:///dns-query?dns=AAEAAAABAAAAAAAAB2V4YW1wbGUAAAbFrMonAAE" diff --git a/bin/tests/system/doth/conftest.py b/bin/tests/system/doth/conftest.py new file mode 100644 index 0000000..27dca7e --- /dev/null +++ b/bin/tests/system/doth/conftest.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import shutil + +import pytest +import isctest + + +@pytest.fixture +def gnutls_cli_executable(): + # Ensure gnutls-cli is available. + executable = shutil.which("gnutls-cli") + if not executable: + pytest.skip("gnutls-cli not found in PATH") + + # Ensure gnutls-cli supports the --logfile command-line option. + output = isctest.run.cmd( + [executable, "--logfile=/dev/null"], log_stderr=False, raise_on_exception=False + ).stdout + if b"illegal option" in output: + pytest.skip("gnutls-cli does not support the --logfile option") + + return executable + + +@pytest.fixture +def sslyze_executable(): + # Check whether sslyze is available. + executable = shutil.which("sslyze") + if not executable: + pytest.skip("sslyze not found in PATH") + + return executable diff --git a/bin/tests/system/doth/dhparam3072.pem b/bin/tests/system/doth/dhparam3072.pem new file mode 100644 index 0000000..fb31ccd --- /dev/null +++ b/bin/tests/system/doth/dhparam3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 +7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 +nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu +N///////////AgEC +-----END DH PARAMETERS----- diff --git a/bin/tests/system/doth/example.axfr.good b/bin/tests/system/doth/example.axfr.good new file mode 100644 index 0000000..a5ec1f2 --- /dev/null +++ b/bin/tests/system/doth/example.axfr.good @@ -0,0 +1,2681 @@ +example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600 +example. 3600 IN NS ns2.example. +example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +a01.example. 3600 IN A 0.0.0.0 +a02.example. 3600 IN A 255.255.255.255 +a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo. +a601.example. 3600 IN A6 127 ::1 foo. +a601.example. 3600 IN A6 128 . +aaaa01.example. 3600 IN AAAA ::1 +aaaa02.example. 3600 IN AAAA fd92:7065:b8e:ffff::5 +afsdb01.example. 3600 IN AFSDB 0 hostname.example. +afsdb02.example. 3600 IN AFSDB 65535 . +amtrelay01.example. 3600 IN AMTRELAY 0 0 0 +amtrelay02.example. 3600 IN AMTRELAY 0 1 0 +amtrelay03.example. 3600 IN AMTRELAY 0 0 1 0.0.0.0 +amtrelay04.example. 3600 IN AMTRELAY 0 0 2 :: +amtrelay05.example. 3600 IN AMTRELAY 0 0 3 example.net. +amtrelay06.example. 3600 IN AMTRELAY \# 2 0004 +apl01.example. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24 +apl02.example. 3600 IN APL +atma01.example. 3600 IN ATMA +61200000000 +atma02.example. 3600 IN ATMA +61200000000 +atma03.example. 3600 IN ATMA 1234567890abcdef +atma04.example. 3600 IN ATMA fedcba0987654321 +avc.example. 3600 IN AVC "foo:bar" +biganswer.example. 3600 IN A 10.10.1.1 +biganswer.example. 3600 IN A 10.10.1.2 +biganswer.example. 3600 IN A 10.10.1.3 +biganswer.example. 3600 IN A 10.10.1.4 +biganswer.example. 3600 IN A 10.10.1.5 +biganswer.example. 3600 IN A 10.10.1.6 +biganswer.example. 3600 IN A 10.10.1.7 +biganswer.example. 3600 IN A 10.10.1.8 +biganswer.example. 3600 IN A 10.10.1.9 +biganswer.example. 3600 IN A 10.10.1.10 +biganswer.example. 3600 IN A 10.10.1.11 +biganswer.example. 3600 IN A 10.10.1.12 +biganswer.example. 3600 IN A 10.10.1.13 +biganswer.example. 3600 IN A 10.10.1.14 +biganswer.example. 3600 IN A 10.10.1.15 +biganswer.example. 3600 IN A 10.10.1.16 +biganswer.example. 3600 IN A 10.10.1.17 +biganswer.example. 3600 IN A 10.10.1.18 +biganswer.example. 3600 IN A 10.10.1.19 +biganswer.example. 3600 IN A 10.10.1.20 +biganswer.example. 3600 IN A 10.10.1.21 +biganswer.example. 3600 IN A 10.10.1.22 +biganswer.example. 3600 IN A 10.10.1.23 +biganswer.example. 3600 IN A 10.10.1.24 +biganswer.example. 3600 IN A 10.10.1.25 +biganswer.example. 3600 IN A 10.10.1.26 +biganswer.example. 3600 IN A 10.10.1.27 +biganswer.example. 3600 IN A 10.10.1.28 +biganswer.example. 3600 IN A 10.10.1.29 +biganswer.example. 3600 IN A 10.10.1.30 +biganswer.example. 3600 IN A 10.10.1.31 +biganswer.example. 3600 IN A 10.10.1.32 +biganswer.example. 3600 IN A 10.10.1.33 +biganswer.example. 3600 IN A 10.10.1.34 +biganswer.example. 3600 IN A 10.10.1.35 +biganswer.example. 3600 IN A 10.10.1.36 +biganswer.example. 3600 IN A 10.10.1.37 +biganswer.example. 3600 IN A 10.10.1.38 +biganswer.example. 3600 IN A 10.10.1.39 +biganswer.example. 3600 IN A 10.10.1.40 +biganswer.example. 3600 IN A 10.10.1.41 +biganswer.example. 3600 IN A 10.10.1.42 +biganswer.example. 3600 IN A 10.10.1.43 +biganswer.example. 3600 IN A 10.10.1.44 +biganswer.example. 3600 IN A 10.10.1.45 +biganswer.example. 3600 IN A 10.10.1.46 +biganswer.example. 3600 IN A 10.10.1.47 +biganswer.example. 3600 IN A 10.10.1.48 +biganswer.example. 3600 IN A 10.10.1.49 +biganswer.example. 3600 IN A 10.10.1.50 +biganswer.example. 3600 IN A 10.10.2.1 +biganswer.example. 3600 IN A 10.10.2.2 +biganswer.example. 3600 IN A 10.10.2.3 +biganswer.example. 3600 IN A 10.10.2.4 +biganswer.example. 3600 IN A 10.10.2.5 +biganswer.example. 3600 IN A 10.10.2.6 +biganswer.example. 3600 IN A 10.10.2.7 +biganswer.example. 3600 IN A 10.10.2.8 +biganswer.example. 3600 IN A 10.10.2.9 +biganswer.example. 3600 IN A 10.10.2.10 +biganswer.example. 3600 IN A 10.10.2.11 +biganswer.example. 3600 IN A 10.10.2.12 +biganswer.example. 3600 IN A 10.10.2.13 +biganswer.example. 3600 IN A 10.10.2.14 +biganswer.example. 3600 IN A 10.10.2.15 +biganswer.example. 3600 IN A 10.10.2.16 +biganswer.example. 3600 IN A 10.10.2.17 +biganswer.example. 3600 IN A 10.10.2.18 +biganswer.example. 3600 IN A 10.10.2.19 +biganswer.example. 3600 IN A 10.10.2.20 +biganswer.example. 3600 IN A 10.10.2.21 +biganswer.example. 3600 IN A 10.10.2.22 +biganswer.example. 3600 IN A 10.10.2.23 +biganswer.example. 3600 IN A 10.10.2.24 +biganswer.example. 3600 IN A 10.10.2.25 +biganswer.example. 3600 IN A 10.10.2.26 +biganswer.example. 3600 IN A 10.10.2.27 +biganswer.example. 3600 IN A 10.10.2.28 +biganswer.example. 3600 IN A 10.10.2.29 +biganswer.example. 3600 IN A 10.10.2.30 +biganswer.example. 3600 IN A 10.10.2.31 +biganswer.example. 3600 IN A 10.10.2.32 +biganswer.example. 3600 IN A 10.10.2.33 +biganswer.example. 3600 IN A 10.10.2.34 +biganswer.example. 3600 IN A 10.10.2.35 +biganswer.example. 3600 IN A 10.10.2.36 +biganswer.example. 3600 IN A 10.10.2.37 +biganswer.example. 3600 IN A 10.10.2.38 +biganswer.example. 3600 IN A 10.10.2.39 +biganswer.example. 3600 IN A 10.10.2.40 +biganswer.example. 3600 IN A 10.10.2.41 +biganswer.example. 3600 IN A 10.10.2.42 +biganswer.example. 3600 IN A 10.10.2.43 +biganswer.example. 3600 IN A 10.10.2.44 +biganswer.example. 3600 IN A 10.10.2.45 +biganswer.example. 3600 IN A 10.10.2.46 +biganswer.example. 3600 IN A 10.10.2.47 +biganswer.example. 3600 IN A 10.10.2.48 +biganswer.example. 3600 IN A 10.10.2.49 +biganswer.example. 3600 IN A 10.10.2.50 +biganswer.example. 3600 IN A 10.10.3.1 +biganswer.example. 3600 IN A 10.10.3.2 +biganswer.example. 3600 IN A 10.10.3.3 +biganswer.example. 3600 IN A 10.10.3.4 +biganswer.example. 3600 IN A 10.10.3.5 +biganswer.example. 3600 IN A 10.10.3.6 +biganswer.example. 3600 IN A 10.10.3.7 +biganswer.example. 3600 IN A 10.10.3.8 +biganswer.example. 3600 IN A 10.10.3.9 +biganswer.example. 3600 IN A 10.10.3.10 +biganswer.example. 3600 IN A 10.10.3.11 +biganswer.example. 3600 IN A 10.10.3.12 +biganswer.example. 3600 IN A 10.10.3.13 +biganswer.example. 3600 IN A 10.10.3.14 +biganswer.example. 3600 IN A 10.10.3.15 +biganswer.example. 3600 IN A 10.10.3.16 +biganswer.example. 3600 IN A 10.10.3.17 +biganswer.example. 3600 IN A 10.10.3.18 +biganswer.example. 3600 IN A 10.10.3.19 +biganswer.example. 3600 IN A 10.10.3.20 +biganswer.example. 3600 IN A 10.10.3.21 +biganswer.example. 3600 IN A 10.10.3.22 +biganswer.example. 3600 IN A 10.10.3.23 +biganswer.example. 3600 IN A 10.10.3.24 +biganswer.example. 3600 IN A 10.10.3.25 +biganswer.example. 3600 IN A 10.10.3.26 +biganswer.example. 3600 IN A 10.10.3.27 +biganswer.example. 3600 IN A 10.10.3.28 +biganswer.example. 3600 IN A 10.10.3.29 +biganswer.example. 3600 IN A 10.10.3.30 +biganswer.example. 3600 IN A 10.10.3.31 +biganswer.example. 3600 IN A 10.10.3.32 +biganswer.example. 3600 IN A 10.10.3.33 +biganswer.example. 3600 IN A 10.10.3.34 +biganswer.example. 3600 IN A 10.10.3.35 +biganswer.example. 3600 IN A 10.10.3.36 +biganswer.example. 3600 IN A 10.10.3.37 +biganswer.example. 3600 IN A 10.10.3.38 +biganswer.example. 3600 IN A 10.10.3.39 +biganswer.example. 3600 IN A 10.10.3.40 +biganswer.example. 3600 IN A 10.10.3.41 +biganswer.example. 3600 IN A 10.10.3.42 +biganswer.example. 3600 IN A 10.10.3.43 +biganswer.example. 3600 IN A 10.10.3.44 +biganswer.example. 3600 IN A 10.10.3.45 +biganswer.example. 3600 IN A 10.10.3.46 +biganswer.example. 3600 IN A 10.10.3.47 +biganswer.example. 3600 IN A 10.10.3.48 +biganswer.example. 3600 IN A 10.10.3.49 +biganswer.example. 3600 IN A 10.10.3.50 +biganswer.example. 3600 IN A 10.10.4.1 +biganswer.example. 3600 IN A 10.10.4.2 +biganswer.example. 3600 IN A 10.10.4.3 +biganswer.example. 3600 IN A 10.10.4.4 +biganswer.example. 3600 IN A 10.10.4.5 +biganswer.example. 3600 IN A 10.10.4.6 +biganswer.example. 3600 IN A 10.10.4.7 +biganswer.example. 3600 IN A 10.10.4.8 +biganswer.example. 3600 IN A 10.10.4.9 +biganswer.example. 3600 IN A 10.10.4.10 +biganswer.example. 3600 IN A 10.10.4.11 +biganswer.example. 3600 IN A 10.10.4.12 +biganswer.example. 3600 IN A 10.10.4.13 +biganswer.example. 3600 IN A 10.10.4.14 +biganswer.example. 3600 IN A 10.10.4.15 +biganswer.example. 3600 IN A 10.10.4.16 +biganswer.example. 3600 IN A 10.10.4.17 +biganswer.example. 3600 IN A 10.10.4.18 +biganswer.example. 3600 IN A 10.10.4.19 +biganswer.example. 3600 IN A 10.10.4.20 +biganswer.example. 3600 IN A 10.10.4.21 +biganswer.example. 3600 IN A 10.10.4.22 +biganswer.example. 3600 IN A 10.10.4.23 +biganswer.example. 3600 IN A 10.10.4.24 +biganswer.example. 3600 IN A 10.10.4.25 +biganswer.example. 3600 IN A 10.10.4.26 +biganswer.example. 3600 IN A 10.10.4.27 +biganswer.example. 3600 IN A 10.10.4.28 +biganswer.example. 3600 IN A 10.10.4.29 +biganswer.example. 3600 IN A 10.10.4.30 +biganswer.example. 3600 IN A 10.10.4.31 +biganswer.example. 3600 IN A 10.10.4.32 +biganswer.example. 3600 IN A 10.10.4.33 +biganswer.example. 3600 IN A 10.10.4.34 +biganswer.example. 3600 IN A 10.10.4.35 +biganswer.example. 3600 IN A 10.10.4.36 +biganswer.example. 3600 IN A 10.10.4.37 +biganswer.example. 3600 IN A 10.10.4.38 +biganswer.example. 3600 IN A 10.10.4.39 +biganswer.example. 3600 IN A 10.10.4.40 +biganswer.example. 3600 IN A 10.10.4.41 +biganswer.example. 3600 IN A 10.10.4.42 +biganswer.example. 3600 IN A 10.10.4.43 +biganswer.example. 3600 IN A 10.10.4.44 +biganswer.example. 3600 IN A 10.10.4.45 +biganswer.example. 3600 IN A 10.10.4.46 +biganswer.example. 3600 IN A 10.10.4.47 +biganswer.example. 3600 IN A 10.10.4.48 +biganswer.example. 3600 IN A 10.10.4.49 +biganswer.example. 3600 IN A 10.10.4.50 +biganswer.example. 3600 IN A 10.10.5.1 +biganswer.example. 3600 IN A 10.10.5.2 +biganswer.example. 3600 IN A 10.10.5.3 +biganswer.example. 3600 IN A 10.10.5.4 +biganswer.example. 3600 IN A 10.10.5.5 +biganswer.example. 3600 IN A 10.10.5.6 +biganswer.example. 3600 IN A 10.10.5.7 +biganswer.example. 3600 IN A 10.10.5.8 +biganswer.example. 3600 IN A 10.10.5.9 +biganswer.example. 3600 IN A 10.10.5.10 +biganswer.example. 3600 IN A 10.10.5.11 +biganswer.example. 3600 IN A 10.10.5.12 +biganswer.example. 3600 IN A 10.10.5.13 +biganswer.example. 3600 IN A 10.10.5.14 +biganswer.example. 3600 IN A 10.10.5.15 +biganswer.example. 3600 IN A 10.10.5.16 +biganswer.example. 3600 IN A 10.10.5.17 +biganswer.example. 3600 IN A 10.10.5.18 +biganswer.example. 3600 IN A 10.10.5.19 +biganswer.example. 3600 IN A 10.10.5.20 +biganswer.example. 3600 IN A 10.10.5.21 +biganswer.example. 3600 IN A 10.10.5.22 +biganswer.example. 3600 IN A 10.10.5.23 +biganswer.example. 3600 IN A 10.10.5.24 +biganswer.example. 3600 IN A 10.10.5.25 +biganswer.example. 3600 IN A 10.10.5.26 +biganswer.example. 3600 IN A 10.10.5.27 +biganswer.example. 3600 IN A 10.10.5.28 +biganswer.example. 3600 IN A 10.10.5.29 +biganswer.example. 3600 IN A 10.10.5.30 +biganswer.example. 3600 IN A 10.10.5.31 +biganswer.example. 3600 IN A 10.10.5.32 +biganswer.example. 3600 IN A 10.10.5.33 +biganswer.example. 3600 IN A 10.10.5.34 +biganswer.example. 3600 IN A 10.10.5.35 +biganswer.example. 3600 IN A 10.10.5.36 +biganswer.example. 3600 IN A 10.10.5.37 +biganswer.example. 3600 IN A 10.10.5.38 +biganswer.example. 3600 IN A 10.10.5.39 +biganswer.example. 3600 IN A 10.10.5.40 +biganswer.example. 3600 IN A 10.10.5.41 +biganswer.example. 3600 IN A 10.10.5.42 +biganswer.example. 3600 IN A 10.10.5.43 +biganswer.example. 3600 IN A 10.10.5.44 +biganswer.example. 3600 IN A 10.10.5.45 +biganswer.example. 3600 IN A 10.10.5.46 +biganswer.example. 3600 IN A 10.10.5.47 +biganswer.example. 3600 IN A 10.10.5.48 +biganswer.example. 3600 IN A 10.10.5.49 +biganswer.example. 3600 IN A 10.10.5.50 +biganswer.example. 3600 IN A 10.10.6.1 +biganswer.example. 3600 IN A 10.10.6.2 +biganswer.example. 3600 IN A 10.10.6.3 +biganswer.example. 3600 IN A 10.10.6.4 +biganswer.example. 3600 IN A 10.10.6.5 +biganswer.example. 3600 IN A 10.10.6.6 +biganswer.example. 3600 IN A 10.10.6.7 +biganswer.example. 3600 IN A 10.10.6.8 +biganswer.example. 3600 IN A 10.10.6.9 +biganswer.example. 3600 IN A 10.10.6.10 +biganswer.example. 3600 IN A 10.10.6.11 +biganswer.example. 3600 IN A 10.10.6.12 +biganswer.example. 3600 IN A 10.10.6.13 +biganswer.example. 3600 IN A 10.10.6.14 +biganswer.example. 3600 IN A 10.10.6.15 +biganswer.example. 3600 IN A 10.10.6.16 +biganswer.example. 3600 IN A 10.10.6.17 +biganswer.example. 3600 IN A 10.10.6.18 +biganswer.example. 3600 IN A 10.10.6.19 +biganswer.example. 3600 IN A 10.10.6.20 +biganswer.example. 3600 IN A 10.10.6.21 +biganswer.example. 3600 IN A 10.10.6.22 +biganswer.example. 3600 IN A 10.10.6.23 +biganswer.example. 3600 IN A 10.10.6.24 +biganswer.example. 3600 IN A 10.10.6.25 +biganswer.example. 3600 IN A 10.10.6.26 +biganswer.example. 3600 IN A 10.10.6.27 +biganswer.example. 3600 IN A 10.10.6.28 +biganswer.example. 3600 IN A 10.10.6.29 +biganswer.example. 3600 IN A 10.10.6.30 +biganswer.example. 3600 IN A 10.10.6.31 +biganswer.example. 3600 IN A 10.10.6.32 +biganswer.example. 3600 IN A 10.10.6.33 +biganswer.example. 3600 IN A 10.10.6.34 +biganswer.example. 3600 IN A 10.10.6.35 +biganswer.example. 3600 IN A 10.10.6.36 +biganswer.example. 3600 IN A 10.10.6.37 +biganswer.example. 3600 IN A 10.10.6.38 +biganswer.example. 3600 IN A 10.10.6.39 +biganswer.example. 3600 IN A 10.10.6.40 +biganswer.example. 3600 IN A 10.10.6.41 +biganswer.example. 3600 IN A 10.10.6.42 +biganswer.example. 3600 IN A 10.10.6.43 +biganswer.example. 3600 IN A 10.10.6.44 +biganswer.example. 3600 IN A 10.10.6.45 +biganswer.example. 3600 IN A 10.10.6.46 +biganswer.example. 3600 IN A 10.10.6.47 +biganswer.example. 3600 IN A 10.10.6.48 +biganswer.example. 3600 IN A 10.10.6.49 +biganswer.example. 3600 IN A 10.10.6.50 +biganswer.example. 3600 IN A 10.10.7.1 +biganswer.example. 3600 IN A 10.10.7.2 +biganswer.example. 3600 IN A 10.10.7.3 +biganswer.example. 3600 IN A 10.10.7.4 +biganswer.example. 3600 IN A 10.10.7.5 +biganswer.example. 3600 IN A 10.10.7.6 +biganswer.example. 3600 IN A 10.10.7.7 +biganswer.example. 3600 IN A 10.10.7.8 +biganswer.example. 3600 IN A 10.10.7.9 +biganswer.example. 3600 IN A 10.10.7.10 +biganswer.example. 3600 IN A 10.10.7.11 +biganswer.example. 3600 IN A 10.10.7.12 +biganswer.example. 3600 IN A 10.10.7.13 +biganswer.example. 3600 IN A 10.10.7.14 +biganswer.example. 3600 IN A 10.10.7.15 +biganswer.example. 3600 IN A 10.10.7.16 +biganswer.example. 3600 IN A 10.10.7.17 +biganswer.example. 3600 IN A 10.10.7.18 +biganswer.example. 3600 IN A 10.10.7.19 +biganswer.example. 3600 IN A 10.10.7.20 +biganswer.example. 3600 IN A 10.10.7.21 +biganswer.example. 3600 IN A 10.10.7.22 +biganswer.example. 3600 IN A 10.10.7.23 +biganswer.example. 3600 IN A 10.10.7.24 +biganswer.example. 3600 IN A 10.10.7.25 +biganswer.example. 3600 IN A 10.10.7.26 +biganswer.example. 3600 IN A 10.10.7.27 +biganswer.example. 3600 IN A 10.10.7.28 +biganswer.example. 3600 IN A 10.10.7.29 +biganswer.example. 3600 IN A 10.10.7.30 +biganswer.example. 3600 IN A 10.10.7.31 +biganswer.example. 3600 IN A 10.10.7.32 +biganswer.example. 3600 IN A 10.10.7.33 +biganswer.example. 3600 IN A 10.10.7.34 +biganswer.example. 3600 IN A 10.10.7.35 +biganswer.example. 3600 IN A 10.10.7.36 +biganswer.example. 3600 IN A 10.10.7.37 +biganswer.example. 3600 IN A 10.10.7.38 +biganswer.example. 3600 IN A 10.10.7.39 +biganswer.example. 3600 IN A 10.10.7.40 +biganswer.example. 3600 IN A 10.10.7.41 +biganswer.example. 3600 IN A 10.10.7.42 +biganswer.example. 3600 IN A 10.10.7.43 +biganswer.example. 3600 IN A 10.10.7.44 +biganswer.example. 3600 IN A 10.10.7.45 +biganswer.example. 3600 IN A 10.10.7.46 +biganswer.example. 3600 IN A 10.10.7.47 +biganswer.example. 3600 IN A 10.10.7.48 +biganswer.example. 3600 IN A 10.10.7.49 +biganswer.example. 3600 IN A 10.10.7.50 +biganswer.example. 3600 IN A 10.10.8.1 +biganswer.example. 3600 IN A 10.10.8.2 +biganswer.example. 3600 IN A 10.10.8.3 +biganswer.example. 3600 IN A 10.10.8.4 +biganswer.example. 3600 IN A 10.10.8.5 +biganswer.example. 3600 IN A 10.10.8.6 +biganswer.example. 3600 IN A 10.10.8.7 +biganswer.example. 3600 IN A 10.10.8.8 +biganswer.example. 3600 IN A 10.10.8.9 +biganswer.example. 3600 IN A 10.10.8.10 +biganswer.example. 3600 IN A 10.10.8.11 +biganswer.example. 3600 IN A 10.10.8.12 +biganswer.example. 3600 IN A 10.10.8.13 +biganswer.example. 3600 IN A 10.10.8.14 +biganswer.example. 3600 IN A 10.10.8.15 +biganswer.example. 3600 IN A 10.10.8.16 +biganswer.example. 3600 IN A 10.10.8.17 +biganswer.example. 3600 IN A 10.10.8.18 +biganswer.example. 3600 IN A 10.10.8.19 +biganswer.example. 3600 IN A 10.10.8.20 +biganswer.example. 3600 IN A 10.10.8.21 +biganswer.example. 3600 IN A 10.10.8.22 +biganswer.example. 3600 IN A 10.10.8.23 +biganswer.example. 3600 IN A 10.10.8.24 +biganswer.example. 3600 IN A 10.10.8.25 +biganswer.example. 3600 IN A 10.10.8.26 +biganswer.example. 3600 IN A 10.10.8.27 +biganswer.example. 3600 IN A 10.10.8.28 +biganswer.example. 3600 IN A 10.10.8.29 +biganswer.example. 3600 IN A 10.10.8.30 +biganswer.example. 3600 IN A 10.10.8.31 +biganswer.example. 3600 IN A 10.10.8.32 +biganswer.example. 3600 IN A 10.10.8.33 +biganswer.example. 3600 IN A 10.10.8.34 +biganswer.example. 3600 IN A 10.10.8.35 +biganswer.example. 3600 IN A 10.10.8.36 +biganswer.example. 3600 IN A 10.10.8.37 +biganswer.example. 3600 IN A 10.10.8.38 +biganswer.example. 3600 IN A 10.10.8.39 +biganswer.example. 3600 IN A 10.10.8.40 +biganswer.example. 3600 IN A 10.10.8.41 +biganswer.example. 3600 IN A 10.10.8.42 +biganswer.example. 3600 IN A 10.10.8.43 +biganswer.example. 3600 IN A 10.10.8.44 +biganswer.example. 3600 IN A 10.10.8.45 +biganswer.example. 3600 IN A 10.10.8.46 +biganswer.example. 3600 IN A 10.10.8.47 +biganswer.example. 3600 IN A 10.10.8.48 +biganswer.example. 3600 IN A 10.10.8.49 +biganswer.example. 3600 IN A 10.10.8.50 +biganswer.example. 3600 IN A 10.10.9.1 +biganswer.example. 3600 IN A 10.10.9.2 +biganswer.example. 3600 IN A 10.10.9.3 +biganswer.example. 3600 IN A 10.10.9.4 +biganswer.example. 3600 IN A 10.10.9.5 +biganswer.example. 3600 IN A 10.10.9.6 +biganswer.example. 3600 IN A 10.10.9.7 +biganswer.example. 3600 IN A 10.10.9.8 +biganswer.example. 3600 IN A 10.10.9.9 +biganswer.example. 3600 IN A 10.10.9.10 +biganswer.example. 3600 IN A 10.10.9.11 +biganswer.example. 3600 IN A 10.10.9.12 +biganswer.example. 3600 IN A 10.10.9.13 +biganswer.example. 3600 IN A 10.10.9.14 +biganswer.example. 3600 IN A 10.10.9.15 +biganswer.example. 3600 IN A 10.10.9.16 +biganswer.example. 3600 IN A 10.10.9.17 +biganswer.example. 3600 IN A 10.10.9.18 +biganswer.example. 3600 IN A 10.10.9.19 +biganswer.example. 3600 IN A 10.10.9.20 +biganswer.example. 3600 IN A 10.10.9.21 +biganswer.example. 3600 IN A 10.10.9.22 +biganswer.example. 3600 IN A 10.10.9.23 +biganswer.example. 3600 IN A 10.10.9.24 +biganswer.example. 3600 IN A 10.10.9.25 +biganswer.example. 3600 IN A 10.10.9.26 +biganswer.example. 3600 IN A 10.10.9.27 +biganswer.example. 3600 IN A 10.10.9.28 +biganswer.example. 3600 IN A 10.10.9.29 +biganswer.example. 3600 IN A 10.10.9.30 +biganswer.example. 3600 IN A 10.10.9.31 +biganswer.example. 3600 IN A 10.10.9.32 +biganswer.example. 3600 IN A 10.10.9.33 +biganswer.example. 3600 IN A 10.10.9.34 +biganswer.example. 3600 IN A 10.10.9.35 +biganswer.example. 3600 IN A 10.10.9.36 +biganswer.example. 3600 IN A 10.10.9.37 +biganswer.example. 3600 IN A 10.10.9.38 +biganswer.example. 3600 IN A 10.10.9.39 +biganswer.example. 3600 IN A 10.10.9.40 +biganswer.example. 3600 IN A 10.10.9.41 +biganswer.example. 3600 IN A 10.10.9.42 +biganswer.example. 3600 IN A 10.10.9.43 +biganswer.example. 3600 IN A 10.10.9.44 +biganswer.example. 3600 IN A 10.10.9.45 +biganswer.example. 3600 IN A 10.10.9.46 +biganswer.example. 3600 IN A 10.10.9.47 +biganswer.example. 3600 IN A 10.10.9.48 +biganswer.example. 3600 IN A 10.10.9.49 +biganswer.example. 3600 IN A 10.10.9.50 +biganswer.example. 3600 IN A 10.10.10.1 +biganswer.example. 3600 IN A 10.10.10.2 +biganswer.example. 3600 IN A 10.10.10.3 +biganswer.example. 3600 IN A 10.10.10.4 +biganswer.example. 3600 IN A 10.10.10.5 +biganswer.example. 3600 IN A 10.10.10.6 +biganswer.example. 3600 IN A 10.10.10.7 +biganswer.example. 3600 IN A 10.10.10.8 +biganswer.example. 3600 IN A 10.10.10.9 +biganswer.example. 3600 IN A 10.10.10.10 +biganswer.example. 3600 IN A 10.10.10.11 +biganswer.example. 3600 IN A 10.10.10.12 +biganswer.example. 3600 IN A 10.10.10.13 +biganswer.example. 3600 IN A 10.10.10.14 +biganswer.example. 3600 IN A 10.10.10.15 +biganswer.example. 3600 IN A 10.10.10.16 +biganswer.example. 3600 IN A 10.10.10.17 +biganswer.example. 3600 IN A 10.10.10.18 +biganswer.example. 3600 IN A 10.10.10.19 +biganswer.example. 3600 IN A 10.10.10.20 +biganswer.example. 3600 IN A 10.10.10.21 +biganswer.example. 3600 IN A 10.10.10.22 +biganswer.example. 3600 IN A 10.10.10.23 +biganswer.example. 3600 IN A 10.10.10.24 +biganswer.example. 3600 IN A 10.10.10.25 +biganswer.example. 3600 IN A 10.10.10.26 +biganswer.example. 3600 IN A 10.10.10.27 +biganswer.example. 3600 IN A 10.10.10.28 +biganswer.example. 3600 IN A 10.10.10.29 +biganswer.example. 3600 IN A 10.10.10.30 +biganswer.example. 3600 IN A 10.10.10.31 +biganswer.example. 3600 IN A 10.10.10.32 +biganswer.example. 3600 IN A 10.10.10.33 +biganswer.example. 3600 IN A 10.10.10.34 +biganswer.example. 3600 IN A 10.10.10.35 +biganswer.example. 3600 IN A 10.10.10.36 +biganswer.example. 3600 IN A 10.10.10.37 +biganswer.example. 3600 IN A 10.10.10.38 +biganswer.example. 3600 IN A 10.10.10.39 +biganswer.example. 3600 IN A 10.10.10.40 +biganswer.example. 3600 IN A 10.10.10.41 +biganswer.example. 3600 IN A 10.10.10.42 +biganswer.example. 3600 IN A 10.10.10.43 +biganswer.example. 3600 IN A 10.10.10.44 +biganswer.example. 3600 IN A 10.10.10.45 +biganswer.example. 3600 IN A 10.10.10.46 +biganswer.example. 3600 IN A 10.10.10.47 +biganswer.example. 3600 IN A 10.10.10.48 +biganswer.example. 3600 IN A 10.10.10.49 +biganswer.example. 3600 IN A 10.10.10.50 +biganswer.example. 3600 IN A 10.10.11.1 +biganswer.example. 3600 IN A 10.10.11.2 +biganswer.example. 3600 IN A 10.10.11.3 +biganswer.example. 3600 IN A 10.10.11.4 +biganswer.example. 3600 IN A 10.10.11.5 +biganswer.example. 3600 IN A 10.10.11.6 +biganswer.example. 3600 IN A 10.10.11.7 +biganswer.example. 3600 IN A 10.10.11.8 +biganswer.example. 3600 IN A 10.10.11.9 +biganswer.example. 3600 IN A 10.10.11.10 +biganswer.example. 3600 IN A 10.10.11.11 +biganswer.example. 3600 IN A 10.10.11.12 +biganswer.example. 3600 IN A 10.10.11.13 +biganswer.example. 3600 IN A 10.10.11.14 +biganswer.example. 3600 IN A 10.10.11.15 +biganswer.example. 3600 IN A 10.10.11.16 +biganswer.example. 3600 IN A 10.10.11.17 +biganswer.example. 3600 IN A 10.10.11.18 +biganswer.example. 3600 IN A 10.10.11.19 +biganswer.example. 3600 IN A 10.10.11.20 +biganswer.example. 3600 IN A 10.10.11.21 +biganswer.example. 3600 IN A 10.10.11.22 +biganswer.example. 3600 IN A 10.10.11.23 +biganswer.example. 3600 IN A 10.10.11.24 +biganswer.example. 3600 IN A 10.10.11.25 +biganswer.example. 3600 IN A 10.10.11.26 +biganswer.example. 3600 IN A 10.10.11.27 +biganswer.example. 3600 IN A 10.10.11.28 +biganswer.example. 3600 IN A 10.10.11.29 +biganswer.example. 3600 IN A 10.10.11.30 +biganswer.example. 3600 IN A 10.10.11.31 +biganswer.example. 3600 IN A 10.10.11.32 +biganswer.example. 3600 IN A 10.10.11.33 +biganswer.example. 3600 IN A 10.10.11.34 +biganswer.example. 3600 IN A 10.10.11.35 +biganswer.example. 3600 IN A 10.10.11.36 +biganswer.example. 3600 IN A 10.10.11.37 +biganswer.example. 3600 IN A 10.10.11.38 +biganswer.example. 3600 IN A 10.10.11.39 +biganswer.example. 3600 IN A 10.10.11.40 +biganswer.example. 3600 IN A 10.10.11.41 +biganswer.example. 3600 IN A 10.10.11.42 +biganswer.example. 3600 IN A 10.10.11.43 +biganswer.example. 3600 IN A 10.10.11.44 +biganswer.example. 3600 IN A 10.10.11.45 +biganswer.example. 3600 IN A 10.10.11.46 +biganswer.example. 3600 IN A 10.10.11.47 +biganswer.example. 3600 IN A 10.10.11.48 +biganswer.example. 3600 IN A 10.10.11.49 +biganswer.example. 3600 IN A 10.10.11.50 +biganswer.example. 3600 IN A 10.10.12.1 +biganswer.example. 3600 IN A 10.10.12.2 +biganswer.example. 3600 IN A 10.10.12.3 +biganswer.example. 3600 IN A 10.10.12.4 +biganswer.example. 3600 IN A 10.10.12.5 +biganswer.example. 3600 IN A 10.10.12.6 +biganswer.example. 3600 IN A 10.10.12.7 +biganswer.example. 3600 IN A 10.10.12.8 +biganswer.example. 3600 IN A 10.10.12.9 +biganswer.example. 3600 IN A 10.10.12.10 +biganswer.example. 3600 IN A 10.10.12.11 +biganswer.example. 3600 IN A 10.10.12.12 +biganswer.example. 3600 IN A 10.10.12.13 +biganswer.example. 3600 IN A 10.10.12.14 +biganswer.example. 3600 IN A 10.10.12.15 +biganswer.example. 3600 IN A 10.10.12.16 +biganswer.example. 3600 IN A 10.10.12.17 +biganswer.example. 3600 IN A 10.10.12.18 +biganswer.example. 3600 IN A 10.10.12.19 +biganswer.example. 3600 IN A 10.10.12.20 +biganswer.example. 3600 IN A 10.10.12.21 +biganswer.example. 3600 IN A 10.10.12.22 +biganswer.example. 3600 IN A 10.10.12.23 +biganswer.example. 3600 IN A 10.10.12.24 +biganswer.example. 3600 IN A 10.10.12.25 +biganswer.example. 3600 IN A 10.10.12.26 +biganswer.example. 3600 IN A 10.10.12.27 +biganswer.example. 3600 IN A 10.10.12.28 +biganswer.example. 3600 IN A 10.10.12.29 +biganswer.example. 3600 IN A 10.10.12.30 +biganswer.example. 3600 IN A 10.10.12.31 +biganswer.example. 3600 IN A 10.10.12.32 +biganswer.example. 3600 IN A 10.10.12.33 +biganswer.example. 3600 IN A 10.10.12.34 +biganswer.example. 3600 IN A 10.10.12.35 +biganswer.example. 3600 IN A 10.10.12.36 +biganswer.example. 3600 IN A 10.10.12.37 +biganswer.example. 3600 IN A 10.10.12.38 +biganswer.example. 3600 IN A 10.10.12.39 +biganswer.example. 3600 IN A 10.10.12.40 +biganswer.example. 3600 IN A 10.10.12.41 +biganswer.example. 3600 IN A 10.10.12.42 +biganswer.example. 3600 IN A 10.10.12.43 +biganswer.example. 3600 IN A 10.10.12.44 +biganswer.example. 3600 IN A 10.10.12.45 +biganswer.example. 3600 IN A 10.10.12.46 +biganswer.example. 3600 IN A 10.10.12.47 +biganswer.example. 3600 IN A 10.10.12.48 +biganswer.example. 3600 IN A 10.10.12.49 +biganswer.example. 3600 IN A 10.10.12.50 +biganswer.example. 3600 IN A 10.10.13.1 +biganswer.example. 3600 IN A 10.10.13.2 +biganswer.example. 3600 IN A 10.10.13.3 +biganswer.example. 3600 IN A 10.10.13.4 +biganswer.example. 3600 IN A 10.10.13.5 +biganswer.example. 3600 IN A 10.10.13.6 +biganswer.example. 3600 IN A 10.10.13.7 +biganswer.example. 3600 IN A 10.10.13.8 +biganswer.example. 3600 IN A 10.10.13.9 +biganswer.example. 3600 IN A 10.10.13.10 +biganswer.example. 3600 IN A 10.10.13.11 +biganswer.example. 3600 IN A 10.10.13.12 +biganswer.example. 3600 IN A 10.10.13.13 +biganswer.example. 3600 IN A 10.10.13.14 +biganswer.example. 3600 IN A 10.10.13.15 +biganswer.example. 3600 IN A 10.10.13.16 +biganswer.example. 3600 IN A 10.10.13.17 +biganswer.example. 3600 IN A 10.10.13.18 +biganswer.example. 3600 IN A 10.10.13.19 +biganswer.example. 3600 IN A 10.10.13.20 +biganswer.example. 3600 IN A 10.10.13.21 +biganswer.example. 3600 IN A 10.10.13.22 +biganswer.example. 3600 IN A 10.10.13.23 +biganswer.example. 3600 IN A 10.10.13.24 +biganswer.example. 3600 IN A 10.10.13.25 +biganswer.example. 3600 IN A 10.10.13.26 +biganswer.example. 3600 IN A 10.10.13.27 +biganswer.example. 3600 IN A 10.10.13.28 +biganswer.example. 3600 IN A 10.10.13.29 +biganswer.example. 3600 IN A 10.10.13.30 +biganswer.example. 3600 IN A 10.10.13.31 +biganswer.example. 3600 IN A 10.10.13.32 +biganswer.example. 3600 IN A 10.10.13.33 +biganswer.example. 3600 IN A 10.10.13.34 +biganswer.example. 3600 IN A 10.10.13.35 +biganswer.example. 3600 IN A 10.10.13.36 +biganswer.example. 3600 IN A 10.10.13.37 +biganswer.example. 3600 IN A 10.10.13.38 +biganswer.example. 3600 IN A 10.10.13.39 +biganswer.example. 3600 IN A 10.10.13.40 +biganswer.example. 3600 IN A 10.10.13.41 +biganswer.example. 3600 IN A 10.10.13.42 +biganswer.example. 3600 IN A 10.10.13.43 +biganswer.example. 3600 IN A 10.10.13.44 +biganswer.example. 3600 IN A 10.10.13.45 +biganswer.example. 3600 IN A 10.10.13.46 +biganswer.example. 3600 IN A 10.10.13.47 +biganswer.example. 3600 IN A 10.10.13.48 +biganswer.example. 3600 IN A 10.10.13.49 +biganswer.example. 3600 IN A 10.10.13.50 +biganswer.example. 3600 IN A 10.10.14.1 +biganswer.example. 3600 IN A 10.10.14.2 +biganswer.example. 3600 IN A 10.10.14.3 +biganswer.example. 3600 IN A 10.10.14.4 +biganswer.example. 3600 IN A 10.10.14.5 +biganswer.example. 3600 IN A 10.10.14.6 +biganswer.example. 3600 IN A 10.10.14.7 +biganswer.example. 3600 IN A 10.10.14.8 +biganswer.example. 3600 IN A 10.10.14.9 +biganswer.example. 3600 IN A 10.10.14.10 +biganswer.example. 3600 IN A 10.10.14.11 +biganswer.example. 3600 IN A 10.10.14.12 +biganswer.example. 3600 IN A 10.10.14.13 +biganswer.example. 3600 IN A 10.10.14.14 +biganswer.example. 3600 IN A 10.10.14.15 +biganswer.example. 3600 IN A 10.10.14.16 +biganswer.example. 3600 IN A 10.10.14.17 +biganswer.example. 3600 IN A 10.10.14.18 +biganswer.example. 3600 IN A 10.10.14.19 +biganswer.example. 3600 IN A 10.10.14.20 +biganswer.example. 3600 IN A 10.10.14.21 +biganswer.example. 3600 IN A 10.10.14.22 +biganswer.example. 3600 IN A 10.10.14.23 +biganswer.example. 3600 IN A 10.10.14.24 +biganswer.example. 3600 IN A 10.10.14.25 +biganswer.example. 3600 IN A 10.10.14.26 +biganswer.example. 3600 IN A 10.10.14.27 +biganswer.example. 3600 IN A 10.10.14.28 +biganswer.example. 3600 IN A 10.10.14.29 +biganswer.example. 3600 IN A 10.10.14.30 +biganswer.example. 3600 IN A 10.10.14.31 +biganswer.example. 3600 IN A 10.10.14.32 +biganswer.example. 3600 IN A 10.10.14.33 +biganswer.example. 3600 IN A 10.10.14.34 +biganswer.example. 3600 IN A 10.10.14.35 +biganswer.example. 3600 IN A 10.10.14.36 +biganswer.example. 3600 IN A 10.10.14.37 +biganswer.example. 3600 IN A 10.10.14.38 +biganswer.example. 3600 IN A 10.10.14.39 +biganswer.example. 3600 IN A 10.10.14.40 +biganswer.example. 3600 IN A 10.10.14.41 +biganswer.example. 3600 IN A 10.10.14.42 +biganswer.example. 3600 IN A 10.10.14.43 +biganswer.example. 3600 IN A 10.10.14.44 +biganswer.example. 3600 IN A 10.10.14.45 +biganswer.example. 3600 IN A 10.10.14.46 +biganswer.example. 3600 IN A 10.10.14.47 +biganswer.example. 3600 IN A 10.10.14.48 +biganswer.example. 3600 IN A 10.10.14.49 +biganswer.example. 3600 IN A 10.10.14.50 +biganswer.example. 3600 IN A 10.10.15.1 +biganswer.example. 3600 IN A 10.10.15.2 +biganswer.example. 3600 IN A 10.10.15.3 +biganswer.example. 3600 IN A 10.10.15.4 +biganswer.example. 3600 IN A 10.10.15.5 +biganswer.example. 3600 IN A 10.10.15.6 +biganswer.example. 3600 IN A 10.10.15.7 +biganswer.example. 3600 IN A 10.10.15.8 +biganswer.example. 3600 IN A 10.10.15.9 +biganswer.example. 3600 IN A 10.10.15.10 +biganswer.example. 3600 IN A 10.10.15.11 +biganswer.example. 3600 IN A 10.10.15.12 +biganswer.example. 3600 IN A 10.10.15.13 +biganswer.example. 3600 IN A 10.10.15.14 +biganswer.example. 3600 IN A 10.10.15.15 +biganswer.example. 3600 IN A 10.10.15.16 +biganswer.example. 3600 IN A 10.10.15.17 +biganswer.example. 3600 IN A 10.10.15.18 +biganswer.example. 3600 IN A 10.10.15.19 +biganswer.example. 3600 IN A 10.10.15.20 +biganswer.example. 3600 IN A 10.10.15.21 +biganswer.example. 3600 IN A 10.10.15.22 +biganswer.example. 3600 IN A 10.10.15.23 +biganswer.example. 3600 IN A 10.10.15.24 +biganswer.example. 3600 IN A 10.10.15.25 +biganswer.example. 3600 IN A 10.10.15.26 +biganswer.example. 3600 IN A 10.10.15.27 +biganswer.example. 3600 IN A 10.10.15.28 +biganswer.example. 3600 IN A 10.10.15.29 +biganswer.example. 3600 IN A 10.10.15.30 +biganswer.example. 3600 IN A 10.10.15.31 +biganswer.example. 3600 IN A 10.10.15.32 +biganswer.example. 3600 IN A 10.10.15.33 +biganswer.example. 3600 IN A 10.10.15.34 +biganswer.example. 3600 IN A 10.10.15.35 +biganswer.example. 3600 IN A 10.10.15.36 +biganswer.example. 3600 IN A 10.10.15.37 +biganswer.example. 3600 IN A 10.10.15.38 +biganswer.example. 3600 IN A 10.10.15.39 +biganswer.example. 3600 IN A 10.10.15.40 +biganswer.example. 3600 IN A 10.10.15.41 +biganswer.example. 3600 IN A 10.10.15.42 +biganswer.example. 3600 IN A 10.10.15.43 +biganswer.example. 3600 IN A 10.10.15.44 +biganswer.example. 3600 IN A 10.10.15.45 +biganswer.example. 3600 IN A 10.10.15.46 +biganswer.example. 3600 IN A 10.10.15.47 +biganswer.example. 3600 IN A 10.10.15.48 +biganswer.example. 3600 IN A 10.10.15.49 +biganswer.example. 3600 IN A 10.10.15.50 +biganswer.example. 3600 IN A 10.10.16.1 +biganswer.example. 3600 IN A 10.10.16.2 +biganswer.example. 3600 IN A 10.10.16.3 +biganswer.example. 3600 IN A 10.10.16.4 +biganswer.example. 3600 IN A 10.10.16.5 +biganswer.example. 3600 IN A 10.10.16.6 +biganswer.example. 3600 IN A 10.10.16.7 +biganswer.example. 3600 IN A 10.10.16.8 +biganswer.example. 3600 IN A 10.10.16.9 +biganswer.example. 3600 IN A 10.10.16.10 +biganswer.example. 3600 IN A 10.10.16.11 +biganswer.example. 3600 IN A 10.10.16.12 +biganswer.example. 3600 IN A 10.10.16.13 +biganswer.example. 3600 IN A 10.10.16.14 +biganswer.example. 3600 IN A 10.10.16.15 +biganswer.example. 3600 IN A 10.10.16.16 +biganswer.example. 3600 IN A 10.10.16.17 +biganswer.example. 3600 IN A 10.10.16.18 +biganswer.example. 3600 IN A 10.10.16.19 +biganswer.example. 3600 IN A 10.10.16.20 +biganswer.example. 3600 IN A 10.10.16.21 +biganswer.example. 3600 IN A 10.10.16.22 +biganswer.example. 3600 IN A 10.10.16.23 +biganswer.example. 3600 IN A 10.10.16.24 +biganswer.example. 3600 IN A 10.10.16.25 +biganswer.example. 3600 IN A 10.10.16.26 +biganswer.example. 3600 IN A 10.10.16.27 +biganswer.example. 3600 IN A 10.10.16.28 +biganswer.example. 3600 IN A 10.10.16.29 +biganswer.example. 3600 IN A 10.10.16.30 +biganswer.example. 3600 IN A 10.10.16.31 +biganswer.example. 3600 IN A 10.10.16.32 +biganswer.example. 3600 IN A 10.10.16.33 +biganswer.example. 3600 IN A 10.10.16.34 +biganswer.example. 3600 IN A 10.10.16.35 +biganswer.example. 3600 IN A 10.10.16.36 +biganswer.example. 3600 IN A 10.10.16.37 +biganswer.example. 3600 IN A 10.10.16.38 +biganswer.example. 3600 IN A 10.10.16.39 +biganswer.example. 3600 IN A 10.10.16.40 +biganswer.example. 3600 IN A 10.10.16.41 +biganswer.example. 3600 IN A 10.10.16.42 +biganswer.example. 3600 IN A 10.10.16.43 +biganswer.example. 3600 IN A 10.10.16.44 +biganswer.example. 3600 IN A 10.10.16.45 +biganswer.example. 3600 IN A 10.10.16.46 +biganswer.example. 3600 IN A 10.10.16.47 +biganswer.example. 3600 IN A 10.10.16.48 +biganswer.example. 3600 IN A 10.10.16.49 +biganswer.example. 3600 IN A 10.10.16.50 +biganswer.example. 3600 IN A 10.10.17.1 +biganswer.example. 3600 IN A 10.10.17.2 +biganswer.example. 3600 IN A 10.10.17.3 +biganswer.example. 3600 IN A 10.10.17.4 +biganswer.example. 3600 IN A 10.10.17.5 +biganswer.example. 3600 IN A 10.10.17.6 +biganswer.example. 3600 IN A 10.10.17.7 +biganswer.example. 3600 IN A 10.10.17.8 +biganswer.example. 3600 IN A 10.10.17.9 +biganswer.example. 3600 IN A 10.10.17.10 +biganswer.example. 3600 IN A 10.10.17.11 +biganswer.example. 3600 IN A 10.10.17.12 +biganswer.example. 3600 IN A 10.10.17.13 +biganswer.example. 3600 IN A 10.10.17.14 +biganswer.example. 3600 IN A 10.10.17.15 +biganswer.example. 3600 IN A 10.10.17.16 +biganswer.example. 3600 IN A 10.10.17.17 +biganswer.example. 3600 IN A 10.10.17.18 +biganswer.example. 3600 IN A 10.10.17.19 +biganswer.example. 3600 IN A 10.10.17.20 +biganswer.example. 3600 IN A 10.10.17.21 +biganswer.example. 3600 IN A 10.10.17.22 +biganswer.example. 3600 IN A 10.10.17.23 +biganswer.example. 3600 IN A 10.10.17.24 +biganswer.example. 3600 IN A 10.10.17.25 +biganswer.example. 3600 IN A 10.10.17.26 +biganswer.example. 3600 IN A 10.10.17.27 +biganswer.example. 3600 IN A 10.10.17.28 +biganswer.example. 3600 IN A 10.10.17.29 +biganswer.example. 3600 IN A 10.10.17.30 +biganswer.example. 3600 IN A 10.10.17.31 +biganswer.example. 3600 IN A 10.10.17.32 +biganswer.example. 3600 IN A 10.10.17.33 +biganswer.example. 3600 IN A 10.10.17.34 +biganswer.example. 3600 IN A 10.10.17.35 +biganswer.example. 3600 IN A 10.10.17.36 +biganswer.example. 3600 IN A 10.10.17.37 +biganswer.example. 3600 IN A 10.10.17.38 +biganswer.example. 3600 IN A 10.10.17.39 +biganswer.example. 3600 IN A 10.10.17.40 +biganswer.example. 3600 IN A 10.10.17.41 +biganswer.example. 3600 IN A 10.10.17.42 +biganswer.example. 3600 IN A 10.10.17.43 +biganswer.example. 3600 IN A 10.10.17.44 +biganswer.example. 3600 IN A 10.10.17.45 +biganswer.example. 3600 IN A 10.10.17.46 +biganswer.example. 3600 IN A 10.10.17.47 +biganswer.example. 3600 IN A 10.10.17.48 +biganswer.example. 3600 IN A 10.10.17.49 +biganswer.example. 3600 IN A 10.10.17.50 +biganswer.example. 3600 IN A 10.10.18.1 +biganswer.example. 3600 IN A 10.10.18.2 +biganswer.example. 3600 IN A 10.10.18.3 +biganswer.example. 3600 IN A 10.10.18.4 +biganswer.example. 3600 IN A 10.10.18.5 +biganswer.example. 3600 IN A 10.10.18.6 +biganswer.example. 3600 IN A 10.10.18.7 +biganswer.example. 3600 IN A 10.10.18.8 +biganswer.example. 3600 IN A 10.10.18.9 +biganswer.example. 3600 IN A 10.10.18.10 +biganswer.example. 3600 IN A 10.10.18.11 +biganswer.example. 3600 IN A 10.10.18.12 +biganswer.example. 3600 IN A 10.10.18.13 +biganswer.example. 3600 IN A 10.10.18.14 +biganswer.example. 3600 IN A 10.10.18.15 +biganswer.example. 3600 IN A 10.10.18.16 +biganswer.example. 3600 IN A 10.10.18.17 +biganswer.example. 3600 IN A 10.10.18.18 +biganswer.example. 3600 IN A 10.10.18.19 +biganswer.example. 3600 IN A 10.10.18.20 +biganswer.example. 3600 IN A 10.10.18.21 +biganswer.example. 3600 IN A 10.10.18.22 +biganswer.example. 3600 IN A 10.10.18.23 +biganswer.example. 3600 IN A 10.10.18.24 +biganswer.example. 3600 IN A 10.10.18.25 +biganswer.example. 3600 IN A 10.10.18.26 +biganswer.example. 3600 IN A 10.10.18.27 +biganswer.example. 3600 IN A 10.10.18.28 +biganswer.example. 3600 IN A 10.10.18.29 +biganswer.example. 3600 IN A 10.10.18.30 +biganswer.example. 3600 IN A 10.10.18.31 +biganswer.example. 3600 IN A 10.10.18.32 +biganswer.example. 3600 IN A 10.10.18.33 +biganswer.example. 3600 IN A 10.10.18.34 +biganswer.example. 3600 IN A 10.10.18.35 +biganswer.example. 3600 IN A 10.10.18.36 +biganswer.example. 3600 IN A 10.10.18.37 +biganswer.example. 3600 IN A 10.10.18.38 +biganswer.example. 3600 IN A 10.10.18.39 +biganswer.example. 3600 IN A 10.10.18.40 +biganswer.example. 3600 IN A 10.10.18.41 +biganswer.example. 3600 IN A 10.10.18.42 +biganswer.example. 3600 IN A 10.10.18.43 +biganswer.example. 3600 IN A 10.10.18.44 +biganswer.example. 3600 IN A 10.10.18.45 +biganswer.example. 3600 IN A 10.10.18.46 +biganswer.example. 3600 IN A 10.10.18.47 +biganswer.example. 3600 IN A 10.10.18.48 +biganswer.example. 3600 IN A 10.10.18.49 +biganswer.example. 3600 IN A 10.10.18.50 +biganswer.example. 3600 IN A 10.10.19.1 +biganswer.example. 3600 IN A 10.10.19.2 +biganswer.example. 3600 IN A 10.10.19.3 +biganswer.example. 3600 IN A 10.10.19.4 +biganswer.example. 3600 IN A 10.10.19.5 +biganswer.example. 3600 IN A 10.10.19.6 +biganswer.example. 3600 IN A 10.10.19.7 +biganswer.example. 3600 IN A 10.10.19.8 +biganswer.example. 3600 IN A 10.10.19.9 +biganswer.example. 3600 IN A 10.10.19.10 +biganswer.example. 3600 IN A 10.10.19.11 +biganswer.example. 3600 IN A 10.10.19.12 +biganswer.example. 3600 IN A 10.10.19.13 +biganswer.example. 3600 IN A 10.10.19.14 +biganswer.example. 3600 IN A 10.10.19.15 +biganswer.example. 3600 IN A 10.10.19.16 +biganswer.example. 3600 IN A 10.10.19.17 +biganswer.example. 3600 IN A 10.10.19.18 +biganswer.example. 3600 IN A 10.10.19.19 +biganswer.example. 3600 IN A 10.10.19.20 +biganswer.example. 3600 IN A 10.10.19.21 +biganswer.example. 3600 IN A 10.10.19.22 +biganswer.example. 3600 IN A 10.10.19.23 +biganswer.example. 3600 IN A 10.10.19.24 +biganswer.example. 3600 IN A 10.10.19.25 +biganswer.example. 3600 IN A 10.10.19.26 +biganswer.example. 3600 IN A 10.10.19.27 +biganswer.example. 3600 IN A 10.10.19.28 +biganswer.example. 3600 IN A 10.10.19.29 +biganswer.example. 3600 IN A 10.10.19.30 +biganswer.example. 3600 IN A 10.10.19.31 +biganswer.example. 3600 IN A 10.10.19.32 +biganswer.example. 3600 IN A 10.10.19.33 +biganswer.example. 3600 IN A 10.10.19.34 +biganswer.example. 3600 IN A 10.10.19.35 +biganswer.example. 3600 IN A 10.10.19.36 +biganswer.example. 3600 IN A 10.10.19.37 +biganswer.example. 3600 IN A 10.10.19.38 +biganswer.example. 3600 IN A 10.10.19.39 +biganswer.example. 3600 IN A 10.10.19.40 +biganswer.example. 3600 IN A 10.10.19.41 +biganswer.example. 3600 IN A 10.10.19.42 +biganswer.example. 3600 IN A 10.10.19.43 +biganswer.example. 3600 IN A 10.10.19.44 +biganswer.example. 3600 IN A 10.10.19.45 +biganswer.example. 3600 IN A 10.10.19.46 +biganswer.example. 3600 IN A 10.10.19.47 +biganswer.example. 3600 IN A 10.10.19.48 +biganswer.example. 3600 IN A 10.10.19.49 +biganswer.example. 3600 IN A 10.10.19.50 +biganswer.example. 3600 IN A 10.10.20.1 +biganswer.example. 3600 IN A 10.10.20.2 +biganswer.example. 3600 IN A 10.10.20.3 +biganswer.example. 3600 IN A 10.10.20.4 +biganswer.example. 3600 IN A 10.10.20.5 +biganswer.example. 3600 IN A 10.10.20.6 +biganswer.example. 3600 IN A 10.10.20.7 +biganswer.example. 3600 IN A 10.10.20.8 +biganswer.example. 3600 IN A 10.10.20.9 +biganswer.example. 3600 IN A 10.10.20.10 +biganswer.example. 3600 IN A 10.10.20.11 +biganswer.example. 3600 IN A 10.10.20.12 +biganswer.example. 3600 IN A 10.10.20.13 +biganswer.example. 3600 IN A 10.10.20.14 +biganswer.example. 3600 IN A 10.10.20.15 +biganswer.example. 3600 IN A 10.10.20.16 +biganswer.example. 3600 IN A 10.10.20.17 +biganswer.example. 3600 IN A 10.10.20.18 +biganswer.example. 3600 IN A 10.10.20.19 +biganswer.example. 3600 IN A 10.10.20.20 +biganswer.example. 3600 IN A 10.10.20.21 +biganswer.example. 3600 IN A 10.10.20.22 +biganswer.example. 3600 IN A 10.10.20.23 +biganswer.example. 3600 IN A 10.10.20.24 +biganswer.example. 3600 IN A 10.10.20.25 +biganswer.example. 3600 IN A 10.10.20.26 +biganswer.example. 3600 IN A 10.10.20.27 +biganswer.example. 3600 IN A 10.10.20.28 +biganswer.example. 3600 IN A 10.10.20.29 +biganswer.example. 3600 IN A 10.10.20.30 +biganswer.example. 3600 IN A 10.10.20.31 +biganswer.example. 3600 IN A 10.10.20.32 +biganswer.example. 3600 IN A 10.10.20.33 +biganswer.example. 3600 IN A 10.10.20.34 +biganswer.example. 3600 IN A 10.10.20.35 +biganswer.example. 3600 IN A 10.10.20.36 +biganswer.example. 3600 IN A 10.10.20.37 +biganswer.example. 3600 IN A 10.10.20.38 +biganswer.example. 3600 IN A 10.10.20.39 +biganswer.example. 3600 IN A 10.10.20.40 +biganswer.example. 3600 IN A 10.10.20.41 +biganswer.example. 3600 IN A 10.10.20.42 +biganswer.example. 3600 IN A 10.10.20.43 +biganswer.example. 3600 IN A 10.10.20.44 +biganswer.example. 3600 IN A 10.10.20.45 +biganswer.example. 3600 IN A 10.10.20.46 +biganswer.example. 3600 IN A 10.10.20.47 +biganswer.example. 3600 IN A 10.10.20.48 +biganswer.example. 3600 IN A 10.10.20.49 +biganswer.example. 3600 IN A 10.10.20.50 +biganswer.example. 3600 IN A 10.10.21.1 +biganswer.example. 3600 IN A 10.10.21.2 +biganswer.example. 3600 IN A 10.10.21.3 +biganswer.example. 3600 IN A 10.10.21.4 +biganswer.example. 3600 IN A 10.10.21.5 +biganswer.example. 3600 IN A 10.10.21.6 +biganswer.example. 3600 IN A 10.10.21.7 +biganswer.example. 3600 IN A 10.10.21.8 +biganswer.example. 3600 IN A 10.10.21.9 +biganswer.example. 3600 IN A 10.10.21.10 +biganswer.example. 3600 IN A 10.10.21.11 +biganswer.example. 3600 IN A 10.10.21.12 +biganswer.example. 3600 IN A 10.10.21.13 +biganswer.example. 3600 IN A 10.10.21.14 +biganswer.example. 3600 IN A 10.10.21.15 +biganswer.example. 3600 IN A 10.10.21.16 +biganswer.example. 3600 IN A 10.10.21.17 +biganswer.example. 3600 IN A 10.10.21.18 +biganswer.example. 3600 IN A 10.10.21.19 +biganswer.example. 3600 IN A 10.10.21.20 +biganswer.example. 3600 IN A 10.10.21.21 +biganswer.example. 3600 IN A 10.10.21.22 +biganswer.example. 3600 IN A 10.10.21.23 +biganswer.example. 3600 IN A 10.10.21.24 +biganswer.example. 3600 IN A 10.10.21.25 +biganswer.example. 3600 IN A 10.10.21.26 +biganswer.example. 3600 IN A 10.10.21.27 +biganswer.example. 3600 IN A 10.10.21.28 +biganswer.example. 3600 IN A 10.10.21.29 +biganswer.example. 3600 IN A 10.10.21.30 +biganswer.example. 3600 IN A 10.10.21.31 +biganswer.example. 3600 IN A 10.10.21.32 +biganswer.example. 3600 IN A 10.10.21.33 +biganswer.example. 3600 IN A 10.10.21.34 +biganswer.example. 3600 IN A 10.10.21.35 +biganswer.example. 3600 IN A 10.10.21.36 +biganswer.example. 3600 IN A 10.10.21.37 +biganswer.example. 3600 IN A 10.10.21.38 +biganswer.example. 3600 IN A 10.10.21.39 +biganswer.example. 3600 IN A 10.10.21.40 +biganswer.example. 3600 IN A 10.10.21.41 +biganswer.example. 3600 IN A 10.10.21.42 +biganswer.example. 3600 IN A 10.10.21.43 +biganswer.example. 3600 IN A 10.10.21.44 +biganswer.example. 3600 IN A 10.10.21.45 +biganswer.example. 3600 IN A 10.10.21.46 +biganswer.example. 3600 IN A 10.10.21.47 +biganswer.example. 3600 IN A 10.10.21.48 +biganswer.example. 3600 IN A 10.10.21.49 +biganswer.example. 3600 IN A 10.10.21.50 +biganswer.example. 3600 IN A 10.10.22.1 +biganswer.example. 3600 IN A 10.10.22.2 +biganswer.example. 3600 IN A 10.10.22.3 +biganswer.example. 3600 IN A 10.10.22.4 +biganswer.example. 3600 IN A 10.10.22.5 +biganswer.example. 3600 IN A 10.10.22.6 +biganswer.example. 3600 IN A 10.10.22.7 +biganswer.example. 3600 IN A 10.10.22.8 +biganswer.example. 3600 IN A 10.10.22.9 +biganswer.example. 3600 IN A 10.10.22.10 +biganswer.example. 3600 IN A 10.10.22.11 +biganswer.example. 3600 IN A 10.10.22.12 +biganswer.example. 3600 IN A 10.10.22.13 +biganswer.example. 3600 IN A 10.10.22.14 +biganswer.example. 3600 IN A 10.10.22.15 +biganswer.example. 3600 IN A 10.10.22.16 +biganswer.example. 3600 IN A 10.10.22.17 +biganswer.example. 3600 IN A 10.10.22.18 +biganswer.example. 3600 IN A 10.10.22.19 +biganswer.example. 3600 IN A 10.10.22.20 +biganswer.example. 3600 IN A 10.10.22.21 +biganswer.example. 3600 IN A 10.10.22.22 +biganswer.example. 3600 IN A 10.10.22.23 +biganswer.example. 3600 IN A 10.10.22.24 +biganswer.example. 3600 IN A 10.10.22.25 +biganswer.example. 3600 IN A 10.10.22.26 +biganswer.example. 3600 IN A 10.10.22.27 +biganswer.example. 3600 IN A 10.10.22.28 +biganswer.example. 3600 IN A 10.10.22.29 +biganswer.example. 3600 IN A 10.10.22.30 +biganswer.example. 3600 IN A 10.10.22.31 +biganswer.example. 3600 IN A 10.10.22.32 +biganswer.example. 3600 IN A 10.10.22.33 +biganswer.example. 3600 IN A 10.10.22.34 +biganswer.example. 3600 IN A 10.10.22.35 +biganswer.example. 3600 IN A 10.10.22.36 +biganswer.example. 3600 IN A 10.10.22.37 +biganswer.example. 3600 IN A 10.10.22.38 +biganswer.example. 3600 IN A 10.10.22.39 +biganswer.example. 3600 IN A 10.10.22.40 +biganswer.example. 3600 IN A 10.10.22.41 +biganswer.example. 3600 IN A 10.10.22.42 +biganswer.example. 3600 IN A 10.10.22.43 +biganswer.example. 3600 IN A 10.10.22.44 +biganswer.example. 3600 IN A 10.10.22.45 +biganswer.example. 3600 IN A 10.10.22.46 +biganswer.example. 3600 IN A 10.10.22.47 +biganswer.example. 3600 IN A 10.10.22.48 +biganswer.example. 3600 IN A 10.10.22.49 +biganswer.example. 3600 IN A 10.10.22.50 +biganswer.example. 3600 IN A 10.10.23.1 +biganswer.example. 3600 IN A 10.10.23.2 +biganswer.example. 3600 IN A 10.10.23.3 +biganswer.example. 3600 IN A 10.10.23.4 +biganswer.example. 3600 IN A 10.10.23.5 +biganswer.example. 3600 IN A 10.10.23.6 +biganswer.example. 3600 IN A 10.10.23.7 +biganswer.example. 3600 IN A 10.10.23.8 +biganswer.example. 3600 IN A 10.10.23.9 +biganswer.example. 3600 IN A 10.10.23.10 +biganswer.example. 3600 IN A 10.10.23.11 +biganswer.example. 3600 IN A 10.10.23.12 +biganswer.example. 3600 IN A 10.10.23.13 +biganswer.example. 3600 IN A 10.10.23.14 +biganswer.example. 3600 IN A 10.10.23.15 +biganswer.example. 3600 IN A 10.10.23.16 +biganswer.example. 3600 IN A 10.10.23.17 +biganswer.example. 3600 IN A 10.10.23.18 +biganswer.example. 3600 IN A 10.10.23.19 +biganswer.example. 3600 IN A 10.10.23.20 +biganswer.example. 3600 IN A 10.10.23.21 +biganswer.example. 3600 IN A 10.10.23.22 +biganswer.example. 3600 IN A 10.10.23.23 +biganswer.example. 3600 IN A 10.10.23.24 +biganswer.example. 3600 IN A 10.10.23.25 +biganswer.example. 3600 IN A 10.10.23.26 +biganswer.example. 3600 IN A 10.10.23.27 +biganswer.example. 3600 IN A 10.10.23.28 +biganswer.example. 3600 IN A 10.10.23.29 +biganswer.example. 3600 IN A 10.10.23.30 +biganswer.example. 3600 IN A 10.10.23.31 +biganswer.example. 3600 IN A 10.10.23.32 +biganswer.example. 3600 IN A 10.10.23.33 +biganswer.example. 3600 IN A 10.10.23.34 +biganswer.example. 3600 IN A 10.10.23.35 +biganswer.example. 3600 IN A 10.10.23.36 +biganswer.example. 3600 IN A 10.10.23.37 +biganswer.example. 3600 IN A 10.10.23.38 +biganswer.example. 3600 IN A 10.10.23.39 +biganswer.example. 3600 IN A 10.10.23.40 +biganswer.example. 3600 IN A 10.10.23.41 +biganswer.example. 3600 IN A 10.10.23.42 +biganswer.example. 3600 IN A 10.10.23.43 +biganswer.example. 3600 IN A 10.10.23.44 +biganswer.example. 3600 IN A 10.10.23.45 +biganswer.example. 3600 IN A 10.10.23.46 +biganswer.example. 3600 IN A 10.10.23.47 +biganswer.example. 3600 IN A 10.10.23.48 +biganswer.example. 3600 IN A 10.10.23.49 +biganswer.example. 3600 IN A 10.10.23.50 +biganswer.example. 3600 IN A 10.10.24.1 +biganswer.example. 3600 IN A 10.10.24.2 +biganswer.example. 3600 IN A 10.10.24.3 +biganswer.example. 3600 IN A 10.10.24.4 +biganswer.example. 3600 IN A 10.10.24.5 +biganswer.example. 3600 IN A 10.10.24.6 +biganswer.example. 3600 IN A 10.10.24.7 +biganswer.example. 3600 IN A 10.10.24.8 +biganswer.example. 3600 IN A 10.10.24.9 +biganswer.example. 3600 IN A 10.10.24.10 +biganswer.example. 3600 IN A 10.10.24.11 +biganswer.example. 3600 IN A 10.10.24.12 +biganswer.example. 3600 IN A 10.10.24.13 +biganswer.example. 3600 IN A 10.10.24.14 +biganswer.example. 3600 IN A 10.10.24.15 +biganswer.example. 3600 IN A 10.10.24.16 +biganswer.example. 3600 IN A 10.10.24.17 +biganswer.example. 3600 IN A 10.10.24.18 +biganswer.example. 3600 IN A 10.10.24.19 +biganswer.example. 3600 IN A 10.10.24.20 +biganswer.example. 3600 IN A 10.10.24.21 +biganswer.example. 3600 IN A 10.10.24.22 +biganswer.example. 3600 IN A 10.10.24.23 +biganswer.example. 3600 IN A 10.10.24.24 +biganswer.example. 3600 IN A 10.10.24.25 +biganswer.example. 3600 IN A 10.10.24.26 +biganswer.example. 3600 IN A 10.10.24.27 +biganswer.example. 3600 IN A 10.10.24.28 +biganswer.example. 3600 IN A 10.10.24.29 +biganswer.example. 3600 IN A 10.10.24.30 +biganswer.example. 3600 IN A 10.10.24.31 +biganswer.example. 3600 IN A 10.10.24.32 +biganswer.example. 3600 IN A 10.10.24.33 +biganswer.example. 3600 IN A 10.10.24.34 +biganswer.example. 3600 IN A 10.10.24.35 +biganswer.example. 3600 IN A 10.10.24.36 +biganswer.example. 3600 IN A 10.10.24.37 +biganswer.example. 3600 IN A 10.10.24.38 +biganswer.example. 3600 IN A 10.10.24.39 +biganswer.example. 3600 IN A 10.10.24.40 +biganswer.example. 3600 IN A 10.10.24.41 +biganswer.example. 3600 IN A 10.10.24.42 +biganswer.example. 3600 IN A 10.10.24.43 +biganswer.example. 3600 IN A 10.10.24.44 +biganswer.example. 3600 IN A 10.10.24.45 +biganswer.example. 3600 IN A 10.10.24.46 +biganswer.example. 3600 IN A 10.10.24.47 +biganswer.example. 3600 IN A 10.10.24.48 +biganswer.example. 3600 IN A 10.10.24.49 +biganswer.example. 3600 IN A 10.10.24.50 +biganswer.example. 3600 IN A 10.10.25.1 +biganswer.example. 3600 IN A 10.10.25.2 +biganswer.example. 3600 IN A 10.10.25.3 +biganswer.example. 3600 IN A 10.10.25.4 +biganswer.example. 3600 IN A 10.10.25.5 +biganswer.example. 3600 IN A 10.10.25.6 +biganswer.example. 3600 IN A 10.10.25.7 +biganswer.example. 3600 IN A 10.10.25.8 +biganswer.example. 3600 IN A 10.10.25.9 +biganswer.example. 3600 IN A 10.10.25.10 +biganswer.example. 3600 IN A 10.10.25.11 +biganswer.example. 3600 IN A 10.10.25.12 +biganswer.example. 3600 IN A 10.10.25.13 +biganswer.example. 3600 IN A 10.10.25.14 +biganswer.example. 3600 IN A 10.10.25.15 +biganswer.example. 3600 IN A 10.10.25.16 +biganswer.example. 3600 IN A 10.10.25.17 +biganswer.example. 3600 IN A 10.10.25.18 +biganswer.example. 3600 IN A 10.10.25.19 +biganswer.example. 3600 IN A 10.10.25.20 +biganswer.example. 3600 IN A 10.10.25.21 +biganswer.example. 3600 IN A 10.10.25.22 +biganswer.example. 3600 IN A 10.10.25.23 +biganswer.example. 3600 IN A 10.10.25.24 +biganswer.example. 3600 IN A 10.10.25.25 +biganswer.example. 3600 IN A 10.10.25.26 +biganswer.example. 3600 IN A 10.10.25.27 +biganswer.example. 3600 IN A 10.10.25.28 +biganswer.example. 3600 IN A 10.10.25.29 +biganswer.example. 3600 IN A 10.10.25.30 +biganswer.example. 3600 IN A 10.10.25.31 +biganswer.example. 3600 IN A 10.10.25.32 +biganswer.example. 3600 IN A 10.10.25.33 +biganswer.example. 3600 IN A 10.10.25.34 +biganswer.example. 3600 IN A 10.10.25.35 +biganswer.example. 3600 IN A 10.10.25.36 +biganswer.example. 3600 IN A 10.10.25.37 +biganswer.example. 3600 IN A 10.10.25.38 +biganswer.example. 3600 IN A 10.10.25.39 +biganswer.example. 3600 IN A 10.10.25.40 +biganswer.example. 3600 IN A 10.10.25.41 +biganswer.example. 3600 IN A 10.10.25.42 +biganswer.example. 3600 IN A 10.10.25.43 +biganswer.example. 3600 IN A 10.10.25.44 +biganswer.example. 3600 IN A 10.10.25.45 +biganswer.example. 3600 IN A 10.10.25.46 +biganswer.example. 3600 IN A 10.10.25.47 +biganswer.example. 3600 IN A 10.10.25.48 +biganswer.example. 3600 IN A 10.10.25.49 +biganswer.example. 3600 IN A 10.10.25.50 +biganswer.example. 3600 IN A 10.10.26.1 +biganswer.example. 3600 IN A 10.10.26.2 +biganswer.example. 3600 IN A 10.10.26.3 +biganswer.example. 3600 IN A 10.10.26.4 +biganswer.example. 3600 IN A 10.10.26.5 +biganswer.example. 3600 IN A 10.10.26.6 +biganswer.example. 3600 IN A 10.10.26.7 +biganswer.example. 3600 IN A 10.10.26.8 +biganswer.example. 3600 IN A 10.10.26.9 +biganswer.example. 3600 IN A 10.10.26.10 +biganswer.example. 3600 IN A 10.10.26.11 +biganswer.example. 3600 IN A 10.10.26.12 +biganswer.example. 3600 IN A 10.10.26.13 +biganswer.example. 3600 IN A 10.10.26.14 +biganswer.example. 3600 IN A 10.10.26.15 +biganswer.example. 3600 IN A 10.10.26.16 +biganswer.example. 3600 IN A 10.10.26.17 +biganswer.example. 3600 IN A 10.10.26.18 +biganswer.example. 3600 IN A 10.10.26.19 +biganswer.example. 3600 IN A 10.10.26.20 +biganswer.example. 3600 IN A 10.10.26.21 +biganswer.example. 3600 IN A 10.10.26.22 +biganswer.example. 3600 IN A 10.10.26.23 +biganswer.example. 3600 IN A 10.10.26.24 +biganswer.example. 3600 IN A 10.10.26.25 +biganswer.example. 3600 IN A 10.10.26.26 +biganswer.example. 3600 IN A 10.10.26.27 +biganswer.example. 3600 IN A 10.10.26.28 +biganswer.example. 3600 IN A 10.10.26.29 +biganswer.example. 3600 IN A 10.10.26.30 +biganswer.example. 3600 IN A 10.10.26.31 +biganswer.example. 3600 IN A 10.10.26.32 +biganswer.example. 3600 IN A 10.10.26.33 +biganswer.example. 3600 IN A 10.10.26.34 +biganswer.example. 3600 IN A 10.10.26.35 +biganswer.example. 3600 IN A 10.10.26.36 +biganswer.example. 3600 IN A 10.10.26.37 +biganswer.example. 3600 IN A 10.10.26.38 +biganswer.example. 3600 IN A 10.10.26.39 +biganswer.example. 3600 IN A 10.10.26.40 +biganswer.example. 3600 IN A 10.10.26.41 +biganswer.example. 3600 IN A 10.10.26.42 +biganswer.example. 3600 IN A 10.10.26.43 +biganswer.example. 3600 IN A 10.10.26.44 +biganswer.example. 3600 IN A 10.10.26.45 +biganswer.example. 3600 IN A 10.10.26.46 +biganswer.example. 3600 IN A 10.10.26.47 +biganswer.example. 3600 IN A 10.10.26.48 +biganswer.example. 3600 IN A 10.10.26.49 +biganswer.example. 3600 IN A 10.10.26.50 +biganswer.example. 3600 IN A 10.10.27.1 +biganswer.example. 3600 IN A 10.10.27.2 +biganswer.example. 3600 IN A 10.10.27.3 +biganswer.example. 3600 IN A 10.10.27.4 +biganswer.example. 3600 IN A 10.10.27.5 +biganswer.example. 3600 IN A 10.10.27.6 +biganswer.example. 3600 IN A 10.10.27.7 +biganswer.example. 3600 IN A 10.10.27.8 +biganswer.example. 3600 IN A 10.10.27.9 +biganswer.example. 3600 IN A 10.10.27.10 +biganswer.example. 3600 IN A 10.10.27.11 +biganswer.example. 3600 IN A 10.10.27.12 +biganswer.example. 3600 IN A 10.10.27.13 +biganswer.example. 3600 IN A 10.10.27.14 +biganswer.example. 3600 IN A 10.10.27.15 +biganswer.example. 3600 IN A 10.10.27.16 +biganswer.example. 3600 IN A 10.10.27.17 +biganswer.example. 3600 IN A 10.10.27.18 +biganswer.example. 3600 IN A 10.10.27.19 +biganswer.example. 3600 IN A 10.10.27.20 +biganswer.example. 3600 IN A 10.10.27.21 +biganswer.example. 3600 IN A 10.10.27.22 +biganswer.example. 3600 IN A 10.10.27.23 +biganswer.example. 3600 IN A 10.10.27.24 +biganswer.example. 3600 IN A 10.10.27.25 +biganswer.example. 3600 IN A 10.10.27.26 +biganswer.example. 3600 IN A 10.10.27.27 +biganswer.example. 3600 IN A 10.10.27.28 +biganswer.example. 3600 IN A 10.10.27.29 +biganswer.example. 3600 IN A 10.10.27.30 +biganswer.example. 3600 IN A 10.10.27.31 +biganswer.example. 3600 IN A 10.10.27.32 +biganswer.example. 3600 IN A 10.10.27.33 +biganswer.example. 3600 IN A 10.10.27.34 +biganswer.example. 3600 IN A 10.10.27.35 +biganswer.example. 3600 IN A 10.10.27.36 +biganswer.example. 3600 IN A 10.10.27.37 +biganswer.example. 3600 IN A 10.10.27.38 +biganswer.example. 3600 IN A 10.10.27.39 +biganswer.example. 3600 IN A 10.10.27.40 +biganswer.example. 3600 IN A 10.10.27.41 +biganswer.example. 3600 IN A 10.10.27.42 +biganswer.example. 3600 IN A 10.10.27.43 +biganswer.example. 3600 IN A 10.10.27.44 +biganswer.example. 3600 IN A 10.10.27.45 +biganswer.example. 3600 IN A 10.10.27.46 +biganswer.example. 3600 IN A 10.10.27.47 +biganswer.example. 3600 IN A 10.10.27.48 +biganswer.example. 3600 IN A 10.10.27.49 +biganswer.example. 3600 IN A 10.10.27.50 +biganswer.example. 3600 IN A 10.10.28.1 +biganswer.example. 3600 IN A 10.10.28.2 +biganswer.example. 3600 IN A 10.10.28.3 +biganswer.example. 3600 IN A 10.10.28.4 +biganswer.example. 3600 IN A 10.10.28.5 +biganswer.example. 3600 IN A 10.10.28.6 +biganswer.example. 3600 IN A 10.10.28.7 +biganswer.example. 3600 IN A 10.10.28.8 +biganswer.example. 3600 IN A 10.10.28.9 +biganswer.example. 3600 IN A 10.10.28.10 +biganswer.example. 3600 IN A 10.10.28.11 +biganswer.example. 3600 IN A 10.10.28.12 +biganswer.example. 3600 IN A 10.10.28.13 +biganswer.example. 3600 IN A 10.10.28.14 +biganswer.example. 3600 IN A 10.10.28.15 +biganswer.example. 3600 IN A 10.10.28.16 +biganswer.example. 3600 IN A 10.10.28.17 +biganswer.example. 3600 IN A 10.10.28.18 +biganswer.example. 3600 IN A 10.10.28.19 +biganswer.example. 3600 IN A 10.10.28.20 +biganswer.example. 3600 IN A 10.10.28.21 +biganswer.example. 3600 IN A 10.10.28.22 +biganswer.example. 3600 IN A 10.10.28.23 +biganswer.example. 3600 IN A 10.10.28.24 +biganswer.example. 3600 IN A 10.10.28.25 +biganswer.example. 3600 IN A 10.10.28.26 +biganswer.example. 3600 IN A 10.10.28.27 +biganswer.example. 3600 IN A 10.10.28.28 +biganswer.example. 3600 IN A 10.10.28.29 +biganswer.example. 3600 IN A 10.10.28.30 +biganswer.example. 3600 IN A 10.10.28.31 +biganswer.example. 3600 IN A 10.10.28.32 +biganswer.example. 3600 IN A 10.10.28.33 +biganswer.example. 3600 IN A 10.10.28.34 +biganswer.example. 3600 IN A 10.10.28.35 +biganswer.example. 3600 IN A 10.10.28.36 +biganswer.example. 3600 IN A 10.10.28.37 +biganswer.example. 3600 IN A 10.10.28.38 +biganswer.example. 3600 IN A 10.10.28.39 +biganswer.example. 3600 IN A 10.10.28.40 +biganswer.example. 3600 IN A 10.10.28.41 +biganswer.example. 3600 IN A 10.10.28.42 +biganswer.example. 3600 IN A 10.10.28.43 +biganswer.example. 3600 IN A 10.10.28.44 +biganswer.example. 3600 IN A 10.10.28.45 +biganswer.example. 3600 IN A 10.10.28.46 +biganswer.example. 3600 IN A 10.10.28.47 +biganswer.example. 3600 IN A 10.10.28.48 +biganswer.example. 3600 IN A 10.10.28.49 +biganswer.example. 3600 IN A 10.10.28.50 +biganswer.example. 3600 IN A 10.10.29.1 +biganswer.example. 3600 IN A 10.10.29.2 +biganswer.example. 3600 IN A 10.10.29.3 +biganswer.example. 3600 IN A 10.10.29.4 +biganswer.example. 3600 IN A 10.10.29.5 +biganswer.example. 3600 IN A 10.10.29.6 +biganswer.example. 3600 IN A 10.10.29.7 +biganswer.example. 3600 IN A 10.10.29.8 +biganswer.example. 3600 IN A 10.10.29.9 +biganswer.example. 3600 IN A 10.10.29.10 +biganswer.example. 3600 IN A 10.10.29.11 +biganswer.example. 3600 IN A 10.10.29.12 +biganswer.example. 3600 IN A 10.10.29.13 +biganswer.example. 3600 IN A 10.10.29.14 +biganswer.example. 3600 IN A 10.10.29.15 +biganswer.example. 3600 IN A 10.10.29.16 +biganswer.example. 3600 IN A 10.10.29.17 +biganswer.example. 3600 IN A 10.10.29.18 +biganswer.example. 3600 IN A 10.10.29.19 +biganswer.example. 3600 IN A 10.10.29.20 +biganswer.example. 3600 IN A 10.10.29.21 +biganswer.example. 3600 IN A 10.10.29.22 +biganswer.example. 3600 IN A 10.10.29.23 +biganswer.example. 3600 IN A 10.10.29.24 +biganswer.example. 3600 IN A 10.10.29.25 +biganswer.example. 3600 IN A 10.10.29.26 +biganswer.example. 3600 IN A 10.10.29.27 +biganswer.example. 3600 IN A 10.10.29.28 +biganswer.example. 3600 IN A 10.10.29.29 +biganswer.example. 3600 IN A 10.10.29.30 +biganswer.example. 3600 IN A 10.10.29.31 +biganswer.example. 3600 IN A 10.10.29.32 +biganswer.example. 3600 IN A 10.10.29.33 +biganswer.example. 3600 IN A 10.10.29.34 +biganswer.example. 3600 IN A 10.10.29.35 +biganswer.example. 3600 IN A 10.10.29.36 +biganswer.example. 3600 IN A 10.10.29.37 +biganswer.example. 3600 IN A 10.10.29.38 +biganswer.example. 3600 IN A 10.10.29.39 +biganswer.example. 3600 IN A 10.10.29.40 +biganswer.example. 3600 IN A 10.10.29.41 +biganswer.example. 3600 IN A 10.10.29.42 +biganswer.example. 3600 IN A 10.10.29.43 +biganswer.example. 3600 IN A 10.10.29.44 +biganswer.example. 3600 IN A 10.10.29.45 +biganswer.example. 3600 IN A 10.10.29.46 +biganswer.example. 3600 IN A 10.10.29.47 +biganswer.example. 3600 IN A 10.10.29.48 +biganswer.example. 3600 IN A 10.10.29.49 +biganswer.example. 3600 IN A 10.10.29.50 +biganswer.example. 3600 IN A 10.10.30.1 +biganswer.example. 3600 IN A 10.10.30.2 +biganswer.example. 3600 IN A 10.10.30.3 +biganswer.example. 3600 IN A 10.10.30.4 +biganswer.example. 3600 IN A 10.10.30.5 +biganswer.example. 3600 IN A 10.10.30.6 +biganswer.example. 3600 IN A 10.10.30.7 +biganswer.example. 3600 IN A 10.10.30.8 +biganswer.example. 3600 IN A 10.10.30.9 +biganswer.example. 3600 IN A 10.10.30.10 +biganswer.example. 3600 IN A 10.10.30.11 +biganswer.example. 3600 IN A 10.10.30.12 +biganswer.example. 3600 IN A 10.10.30.13 +biganswer.example. 3600 IN A 10.10.30.14 +biganswer.example. 3600 IN A 10.10.30.15 +biganswer.example. 3600 IN A 10.10.30.16 +biganswer.example. 3600 IN A 10.10.30.17 +biganswer.example. 3600 IN A 10.10.30.18 +biganswer.example. 3600 IN A 10.10.30.19 +biganswer.example. 3600 IN A 10.10.30.20 +biganswer.example. 3600 IN A 10.10.30.21 +biganswer.example. 3600 IN A 10.10.30.22 +biganswer.example. 3600 IN A 10.10.30.23 +biganswer.example. 3600 IN A 10.10.30.24 +biganswer.example. 3600 IN A 10.10.30.25 +biganswer.example. 3600 IN A 10.10.30.26 +biganswer.example. 3600 IN A 10.10.30.27 +biganswer.example. 3600 IN A 10.10.30.28 +biganswer.example. 3600 IN A 10.10.30.29 +biganswer.example. 3600 IN A 10.10.30.30 +biganswer.example. 3600 IN A 10.10.30.31 +biganswer.example. 3600 IN A 10.10.30.32 +biganswer.example. 3600 IN A 10.10.30.33 +biganswer.example. 3600 IN A 10.10.30.34 +biganswer.example. 3600 IN A 10.10.30.35 +biganswer.example. 3600 IN A 10.10.30.36 +biganswer.example. 3600 IN A 10.10.30.37 +biganswer.example. 3600 IN A 10.10.30.38 +biganswer.example. 3600 IN A 10.10.30.39 +biganswer.example. 3600 IN A 10.10.30.40 +biganswer.example. 3600 IN A 10.10.30.41 +biganswer.example. 3600 IN A 10.10.30.42 +biganswer.example. 3600 IN A 10.10.30.43 +biganswer.example. 3600 IN A 10.10.30.44 +biganswer.example. 3600 IN A 10.10.30.45 +biganswer.example. 3600 IN A 10.10.30.46 +biganswer.example. 3600 IN A 10.10.30.47 +biganswer.example. 3600 IN A 10.10.30.48 +biganswer.example. 3600 IN A 10.10.30.49 +biganswer.example. 3600 IN A 10.10.30.50 +biganswer.example. 3600 IN A 10.10.31.1 +biganswer.example. 3600 IN A 10.10.31.2 +biganswer.example. 3600 IN A 10.10.31.3 +biganswer.example. 3600 IN A 10.10.31.4 +biganswer.example. 3600 IN A 10.10.31.5 +biganswer.example. 3600 IN A 10.10.31.6 +biganswer.example. 3600 IN A 10.10.31.7 +biganswer.example. 3600 IN A 10.10.31.8 +biganswer.example. 3600 IN A 10.10.31.9 +biganswer.example. 3600 IN A 10.10.31.10 +biganswer.example. 3600 IN A 10.10.31.11 +biganswer.example. 3600 IN A 10.10.31.12 +biganswer.example. 3600 IN A 10.10.31.13 +biganswer.example. 3600 IN A 10.10.31.14 +biganswer.example. 3600 IN A 10.10.31.15 +biganswer.example. 3600 IN A 10.10.31.16 +biganswer.example. 3600 IN A 10.10.31.17 +biganswer.example. 3600 IN A 10.10.31.18 +biganswer.example. 3600 IN A 10.10.31.19 +biganswer.example. 3600 IN A 10.10.31.20 +biganswer.example. 3600 IN A 10.10.31.21 +biganswer.example. 3600 IN A 10.10.31.22 +biganswer.example. 3600 IN A 10.10.31.23 +biganswer.example. 3600 IN A 10.10.31.24 +biganswer.example. 3600 IN A 10.10.31.25 +biganswer.example. 3600 IN A 10.10.31.26 +biganswer.example. 3600 IN A 10.10.31.27 +biganswer.example. 3600 IN A 10.10.31.28 +biganswer.example. 3600 IN A 10.10.31.29 +biganswer.example. 3600 IN A 10.10.31.30 +biganswer.example. 3600 IN A 10.10.31.31 +biganswer.example. 3600 IN A 10.10.31.32 +biganswer.example. 3600 IN A 10.10.31.33 +biganswer.example. 3600 IN A 10.10.31.34 +biganswer.example. 3600 IN A 10.10.31.35 +biganswer.example. 3600 IN A 10.10.31.36 +biganswer.example. 3600 IN A 10.10.31.37 +biganswer.example. 3600 IN A 10.10.31.38 +biganswer.example. 3600 IN A 10.10.31.39 +biganswer.example. 3600 IN A 10.10.31.40 +biganswer.example. 3600 IN A 10.10.31.41 +biganswer.example. 3600 IN A 10.10.31.42 +biganswer.example. 3600 IN A 10.10.31.43 +biganswer.example. 3600 IN A 10.10.31.44 +biganswer.example. 3600 IN A 10.10.31.45 +biganswer.example. 3600 IN A 10.10.31.46 +biganswer.example. 3600 IN A 10.10.31.47 +biganswer.example. 3600 IN A 10.10.31.48 +biganswer.example. 3600 IN A 10.10.31.49 +biganswer.example. 3600 IN A 10.10.31.50 +biganswer.example. 3600 IN A 10.10.32.1 +biganswer.example. 3600 IN A 10.10.32.2 +biganswer.example. 3600 IN A 10.10.32.3 +biganswer.example. 3600 IN A 10.10.32.4 +biganswer.example. 3600 IN A 10.10.32.5 +biganswer.example. 3600 IN A 10.10.32.6 +biganswer.example. 3600 IN A 10.10.32.7 +biganswer.example. 3600 IN A 10.10.32.8 +biganswer.example. 3600 IN A 10.10.32.9 +biganswer.example. 3600 IN A 10.10.32.10 +biganswer.example. 3600 IN A 10.10.32.11 +biganswer.example. 3600 IN A 10.10.32.12 +biganswer.example. 3600 IN A 10.10.32.13 +biganswer.example. 3600 IN A 10.10.32.14 +biganswer.example. 3600 IN A 10.10.32.15 +biganswer.example. 3600 IN A 10.10.32.16 +biganswer.example. 3600 IN A 10.10.32.17 +biganswer.example. 3600 IN A 10.10.32.18 +biganswer.example. 3600 IN A 10.10.32.19 +biganswer.example. 3600 IN A 10.10.32.20 +biganswer.example. 3600 IN A 10.10.32.21 +biganswer.example. 3600 IN A 10.10.32.22 +biganswer.example. 3600 IN A 10.10.32.23 +biganswer.example. 3600 IN A 10.10.32.24 +biganswer.example. 3600 IN A 10.10.32.25 +biganswer.example. 3600 IN A 10.10.32.26 +biganswer.example. 3600 IN A 10.10.32.27 +biganswer.example. 3600 IN A 10.10.32.28 +biganswer.example. 3600 IN A 10.10.32.29 +biganswer.example. 3600 IN A 10.10.32.30 +biganswer.example. 3600 IN A 10.10.32.31 +biganswer.example. 3600 IN A 10.10.32.32 +biganswer.example. 3600 IN A 10.10.32.33 +biganswer.example. 3600 IN A 10.10.32.34 +biganswer.example. 3600 IN A 10.10.32.35 +biganswer.example. 3600 IN A 10.10.32.36 +biganswer.example. 3600 IN A 10.10.32.37 +biganswer.example. 3600 IN A 10.10.32.38 +biganswer.example. 3600 IN A 10.10.32.39 +biganswer.example. 3600 IN A 10.10.32.40 +biganswer.example. 3600 IN A 10.10.32.41 +biganswer.example. 3600 IN A 10.10.32.42 +biganswer.example. 3600 IN A 10.10.32.43 +biganswer.example. 3600 IN A 10.10.32.44 +biganswer.example. 3600 IN A 10.10.32.45 +biganswer.example. 3600 IN A 10.10.32.46 +biganswer.example. 3600 IN A 10.10.32.47 +biganswer.example. 3600 IN A 10.10.32.48 +biganswer.example. 3600 IN A 10.10.32.49 +biganswer.example. 3600 IN A 10.10.32.50 +biganswer.example. 3600 IN A 10.10.33.1 +biganswer.example. 3600 IN A 10.10.33.2 +biganswer.example. 3600 IN A 10.10.33.3 +biganswer.example. 3600 IN A 10.10.33.4 +biganswer.example. 3600 IN A 10.10.33.5 +biganswer.example. 3600 IN A 10.10.33.6 +biganswer.example. 3600 IN A 10.10.33.7 +biganswer.example. 3600 IN A 10.10.33.8 +biganswer.example. 3600 IN A 10.10.33.9 +biganswer.example. 3600 IN A 10.10.33.10 +biganswer.example. 3600 IN A 10.10.33.11 +biganswer.example. 3600 IN A 10.10.33.12 +biganswer.example. 3600 IN A 10.10.33.13 +biganswer.example. 3600 IN A 10.10.33.14 +biganswer.example. 3600 IN A 10.10.33.15 +biganswer.example. 3600 IN A 10.10.33.16 +biganswer.example. 3600 IN A 10.10.33.17 +biganswer.example. 3600 IN A 10.10.33.18 +biganswer.example. 3600 IN A 10.10.33.19 +biganswer.example. 3600 IN A 10.10.33.20 +biganswer.example. 3600 IN A 10.10.33.21 +biganswer.example. 3600 IN A 10.10.33.22 +biganswer.example. 3600 IN A 10.10.33.23 +biganswer.example. 3600 IN A 10.10.33.24 +biganswer.example. 3600 IN A 10.10.33.25 +biganswer.example. 3600 IN A 10.10.33.26 +biganswer.example. 3600 IN A 10.10.33.27 +biganswer.example. 3600 IN A 10.10.33.28 +biganswer.example. 3600 IN A 10.10.33.29 +biganswer.example. 3600 IN A 10.10.33.30 +biganswer.example. 3600 IN A 10.10.33.31 +biganswer.example. 3600 IN A 10.10.33.32 +biganswer.example. 3600 IN A 10.10.33.33 +biganswer.example. 3600 IN A 10.10.33.34 +biganswer.example. 3600 IN A 10.10.33.35 +biganswer.example. 3600 IN A 10.10.33.36 +biganswer.example. 3600 IN A 10.10.33.37 +biganswer.example. 3600 IN A 10.10.33.38 +biganswer.example. 3600 IN A 10.10.33.39 +biganswer.example. 3600 IN A 10.10.33.40 +biganswer.example. 3600 IN A 10.10.33.41 +biganswer.example. 3600 IN A 10.10.33.42 +biganswer.example. 3600 IN A 10.10.33.43 +biganswer.example. 3600 IN A 10.10.33.44 +biganswer.example. 3600 IN A 10.10.33.45 +biganswer.example. 3600 IN A 10.10.33.46 +biganswer.example. 3600 IN A 10.10.33.47 +biganswer.example. 3600 IN A 10.10.33.48 +biganswer.example. 3600 IN A 10.10.33.49 +biganswer.example. 3600 IN A 10.10.33.50 +biganswer.example. 3600 IN A 10.10.34.1 +biganswer.example. 3600 IN A 10.10.34.2 +biganswer.example. 3600 IN A 10.10.34.3 +biganswer.example. 3600 IN A 10.10.34.4 +biganswer.example. 3600 IN A 10.10.34.5 +biganswer.example. 3600 IN A 10.10.34.6 +biganswer.example. 3600 IN A 10.10.34.7 +biganswer.example. 3600 IN A 10.10.34.8 +biganswer.example. 3600 IN A 10.10.34.9 +biganswer.example. 3600 IN A 10.10.34.10 +biganswer.example. 3600 IN A 10.10.34.11 +biganswer.example. 3600 IN A 10.10.34.12 +biganswer.example. 3600 IN A 10.10.34.13 +biganswer.example. 3600 IN A 10.10.34.14 +biganswer.example. 3600 IN A 10.10.34.15 +biganswer.example. 3600 IN A 10.10.34.16 +biganswer.example. 3600 IN A 10.10.34.17 +biganswer.example. 3600 IN A 10.10.34.18 +biganswer.example. 3600 IN A 10.10.34.19 +biganswer.example. 3600 IN A 10.10.34.20 +biganswer.example. 3600 IN A 10.10.34.21 +biganswer.example. 3600 IN A 10.10.34.22 +biganswer.example. 3600 IN A 10.10.34.23 +biganswer.example. 3600 IN A 10.10.34.24 +biganswer.example. 3600 IN A 10.10.34.25 +biganswer.example. 3600 IN A 10.10.34.26 +biganswer.example. 3600 IN A 10.10.34.27 +biganswer.example. 3600 IN A 10.10.34.28 +biganswer.example. 3600 IN A 10.10.34.29 +biganswer.example. 3600 IN A 10.10.34.30 +biganswer.example. 3600 IN A 10.10.34.31 +biganswer.example. 3600 IN A 10.10.34.32 +biganswer.example. 3600 IN A 10.10.34.33 +biganswer.example. 3600 IN A 10.10.34.34 +biganswer.example. 3600 IN A 10.10.34.35 +biganswer.example. 3600 IN A 10.10.34.36 +biganswer.example. 3600 IN A 10.10.34.37 +biganswer.example. 3600 IN A 10.10.34.38 +biganswer.example. 3600 IN A 10.10.34.39 +biganswer.example. 3600 IN A 10.10.34.40 +biganswer.example. 3600 IN A 10.10.34.41 +biganswer.example. 3600 IN A 10.10.34.42 +biganswer.example. 3600 IN A 10.10.34.43 +biganswer.example. 3600 IN A 10.10.34.44 +biganswer.example. 3600 IN A 10.10.34.45 +biganswer.example. 3600 IN A 10.10.34.46 +biganswer.example. 3600 IN A 10.10.34.47 +biganswer.example. 3600 IN A 10.10.34.48 +biganswer.example. 3600 IN A 10.10.34.49 +biganswer.example. 3600 IN A 10.10.34.50 +biganswer.example. 3600 IN A 10.10.35.1 +biganswer.example. 3600 IN A 10.10.35.2 +biganswer.example. 3600 IN A 10.10.35.3 +biganswer.example. 3600 IN A 10.10.35.4 +biganswer.example. 3600 IN A 10.10.35.5 +biganswer.example. 3600 IN A 10.10.35.6 +biganswer.example. 3600 IN A 10.10.35.7 +biganswer.example. 3600 IN A 10.10.35.8 +biganswer.example. 3600 IN A 10.10.35.9 +biganswer.example. 3600 IN A 10.10.35.10 +biganswer.example. 3600 IN A 10.10.35.11 +biganswer.example. 3600 IN A 10.10.35.12 +biganswer.example. 3600 IN A 10.10.35.13 +biganswer.example. 3600 IN A 10.10.35.14 +biganswer.example. 3600 IN A 10.10.35.15 +biganswer.example. 3600 IN A 10.10.35.16 +biganswer.example. 3600 IN A 10.10.35.17 +biganswer.example. 3600 IN A 10.10.35.18 +biganswer.example. 3600 IN A 10.10.35.19 +biganswer.example. 3600 IN A 10.10.35.20 +biganswer.example. 3600 IN A 10.10.35.21 +biganswer.example. 3600 IN A 10.10.35.22 +biganswer.example. 3600 IN A 10.10.35.23 +biganswer.example. 3600 IN A 10.10.35.24 +biganswer.example. 3600 IN A 10.10.35.25 +biganswer.example. 3600 IN A 10.10.35.26 +biganswer.example. 3600 IN A 10.10.35.27 +biganswer.example. 3600 IN A 10.10.35.28 +biganswer.example. 3600 IN A 10.10.35.29 +biganswer.example. 3600 IN A 10.10.35.30 +biganswer.example. 3600 IN A 10.10.35.31 +biganswer.example. 3600 IN A 10.10.35.32 +biganswer.example. 3600 IN A 10.10.35.33 +biganswer.example. 3600 IN A 10.10.35.34 +biganswer.example. 3600 IN A 10.10.35.35 +biganswer.example. 3600 IN A 10.10.35.36 +biganswer.example. 3600 IN A 10.10.35.37 +biganswer.example. 3600 IN A 10.10.35.38 +biganswer.example. 3600 IN A 10.10.35.39 +biganswer.example. 3600 IN A 10.10.35.40 +biganswer.example. 3600 IN A 10.10.35.41 +biganswer.example. 3600 IN A 10.10.35.42 +biganswer.example. 3600 IN A 10.10.35.43 +biganswer.example. 3600 IN A 10.10.35.44 +biganswer.example. 3600 IN A 10.10.35.45 +biganswer.example. 3600 IN A 10.10.35.46 +biganswer.example. 3600 IN A 10.10.35.47 +biganswer.example. 3600 IN A 10.10.35.48 +biganswer.example. 3600 IN A 10.10.35.49 +biganswer.example. 3600 IN A 10.10.35.50 +biganswer.example. 3600 IN A 10.10.36.1 +biganswer.example. 3600 IN A 10.10.36.2 +biganswer.example. 3600 IN A 10.10.36.3 +biganswer.example. 3600 IN A 10.10.36.4 +biganswer.example. 3600 IN A 10.10.36.5 +biganswer.example. 3600 IN A 10.10.36.6 +biganswer.example. 3600 IN A 10.10.36.7 +biganswer.example. 3600 IN A 10.10.36.8 +biganswer.example. 3600 IN A 10.10.36.9 +biganswer.example. 3600 IN A 10.10.36.10 +biganswer.example. 3600 IN A 10.10.36.11 +biganswer.example. 3600 IN A 10.10.36.12 +biganswer.example. 3600 IN A 10.10.36.13 +biganswer.example. 3600 IN A 10.10.36.14 +biganswer.example. 3600 IN A 10.10.36.15 +biganswer.example. 3600 IN A 10.10.36.16 +biganswer.example. 3600 IN A 10.10.36.17 +biganswer.example. 3600 IN A 10.10.36.18 +biganswer.example. 3600 IN A 10.10.36.19 +biganswer.example. 3600 IN A 10.10.36.20 +biganswer.example. 3600 IN A 10.10.36.21 +biganswer.example. 3600 IN A 10.10.36.22 +biganswer.example. 3600 IN A 10.10.36.23 +biganswer.example. 3600 IN A 10.10.36.24 +biganswer.example. 3600 IN A 10.10.36.25 +biganswer.example. 3600 IN A 10.10.36.26 +biganswer.example. 3600 IN A 10.10.36.27 +biganswer.example. 3600 IN A 10.10.36.28 +biganswer.example. 3600 IN A 10.10.36.29 +biganswer.example. 3600 IN A 10.10.36.30 +biganswer.example. 3600 IN A 10.10.36.31 +biganswer.example. 3600 IN A 10.10.36.32 +biganswer.example. 3600 IN A 10.10.36.33 +biganswer.example. 3600 IN A 10.10.36.34 +biganswer.example. 3600 IN A 10.10.36.35 +biganswer.example. 3600 IN A 10.10.36.36 +biganswer.example. 3600 IN A 10.10.36.37 +biganswer.example. 3600 IN A 10.10.36.38 +biganswer.example. 3600 IN A 10.10.36.39 +biganswer.example. 3600 IN A 10.10.36.40 +biganswer.example. 3600 IN A 10.10.36.41 +biganswer.example. 3600 IN A 10.10.36.42 +biganswer.example. 3600 IN A 10.10.36.43 +biganswer.example. 3600 IN A 10.10.36.44 +biganswer.example. 3600 IN A 10.10.36.45 +biganswer.example. 3600 IN A 10.10.36.46 +biganswer.example. 3600 IN A 10.10.36.47 +biganswer.example. 3600 IN A 10.10.36.48 +biganswer.example. 3600 IN A 10.10.36.49 +biganswer.example. 3600 IN A 10.10.36.50 +biganswer.example. 3600 IN A 10.10.37.1 +biganswer.example. 3600 IN A 10.10.37.2 +biganswer.example. 3600 IN A 10.10.37.3 +biganswer.example. 3600 IN A 10.10.37.4 +biganswer.example. 3600 IN A 10.10.37.5 +biganswer.example. 3600 IN A 10.10.37.6 +biganswer.example. 3600 IN A 10.10.37.7 +biganswer.example. 3600 IN A 10.10.37.8 +biganswer.example. 3600 IN A 10.10.37.9 +biganswer.example. 3600 IN A 10.10.37.10 +biganswer.example. 3600 IN A 10.10.37.11 +biganswer.example. 3600 IN A 10.10.37.12 +biganswer.example. 3600 IN A 10.10.37.13 +biganswer.example. 3600 IN A 10.10.37.14 +biganswer.example. 3600 IN A 10.10.37.15 +biganswer.example. 3600 IN A 10.10.37.16 +biganswer.example. 3600 IN A 10.10.37.17 +biganswer.example. 3600 IN A 10.10.37.18 +biganswer.example. 3600 IN A 10.10.37.19 +biganswer.example. 3600 IN A 10.10.37.20 +biganswer.example. 3600 IN A 10.10.37.21 +biganswer.example. 3600 IN A 10.10.37.22 +biganswer.example. 3600 IN A 10.10.37.23 +biganswer.example. 3600 IN A 10.10.37.24 +biganswer.example. 3600 IN A 10.10.37.25 +biganswer.example. 3600 IN A 10.10.37.26 +biganswer.example. 3600 IN A 10.10.37.27 +biganswer.example. 3600 IN A 10.10.37.28 +biganswer.example. 3600 IN A 10.10.37.29 +biganswer.example. 3600 IN A 10.10.37.30 +biganswer.example. 3600 IN A 10.10.37.31 +biganswer.example. 3600 IN A 10.10.37.32 +biganswer.example. 3600 IN A 10.10.37.33 +biganswer.example. 3600 IN A 10.10.37.34 +biganswer.example. 3600 IN A 10.10.37.35 +biganswer.example. 3600 IN A 10.10.37.36 +biganswer.example. 3600 IN A 10.10.37.37 +biganswer.example. 3600 IN A 10.10.37.38 +biganswer.example. 3600 IN A 10.10.37.39 +biganswer.example. 3600 IN A 10.10.37.40 +biganswer.example. 3600 IN A 10.10.37.41 +biganswer.example. 3600 IN A 10.10.37.42 +biganswer.example. 3600 IN A 10.10.37.43 +biganswer.example. 3600 IN A 10.10.37.44 +biganswer.example. 3600 IN A 10.10.37.45 +biganswer.example. 3600 IN A 10.10.37.46 +biganswer.example. 3600 IN A 10.10.37.47 +biganswer.example. 3600 IN A 10.10.37.48 +biganswer.example. 3600 IN A 10.10.37.49 +biganswer.example. 3600 IN A 10.10.37.50 +biganswer.example. 3600 IN A 10.10.38.1 +biganswer.example. 3600 IN A 10.10.38.2 +biganswer.example. 3600 IN A 10.10.38.3 +biganswer.example. 3600 IN A 10.10.38.4 +biganswer.example. 3600 IN A 10.10.38.5 +biganswer.example. 3600 IN A 10.10.38.6 +biganswer.example. 3600 IN A 10.10.38.7 +biganswer.example. 3600 IN A 10.10.38.8 +biganswer.example. 3600 IN A 10.10.38.9 +biganswer.example. 3600 IN A 10.10.38.10 +biganswer.example. 3600 IN A 10.10.38.11 +biganswer.example. 3600 IN A 10.10.38.12 +biganswer.example. 3600 IN A 10.10.38.13 +biganswer.example. 3600 IN A 10.10.38.14 +biganswer.example. 3600 IN A 10.10.38.15 +biganswer.example. 3600 IN A 10.10.38.16 +biganswer.example. 3600 IN A 10.10.38.17 +biganswer.example. 3600 IN A 10.10.38.18 +biganswer.example. 3600 IN A 10.10.38.19 +biganswer.example. 3600 IN A 10.10.38.20 +biganswer.example. 3600 IN A 10.10.38.21 +biganswer.example. 3600 IN A 10.10.38.22 +biganswer.example. 3600 IN A 10.10.38.23 +biganswer.example. 3600 IN A 10.10.38.24 +biganswer.example. 3600 IN A 10.10.38.25 +biganswer.example. 3600 IN A 10.10.38.26 +biganswer.example. 3600 IN A 10.10.38.27 +biganswer.example. 3600 IN A 10.10.38.28 +biganswer.example. 3600 IN A 10.10.38.29 +biganswer.example. 3600 IN A 10.10.38.30 +biganswer.example. 3600 IN A 10.10.38.31 +biganswer.example. 3600 IN A 10.10.38.32 +biganswer.example. 3600 IN A 10.10.38.33 +biganswer.example. 3600 IN A 10.10.38.34 +biganswer.example. 3600 IN A 10.10.38.35 +biganswer.example. 3600 IN A 10.10.38.36 +biganswer.example. 3600 IN A 10.10.38.37 +biganswer.example. 3600 IN A 10.10.38.38 +biganswer.example. 3600 IN A 10.10.38.39 +biganswer.example. 3600 IN A 10.10.38.40 +biganswer.example. 3600 IN A 10.10.38.41 +biganswer.example. 3600 IN A 10.10.38.42 +biganswer.example. 3600 IN A 10.10.38.43 +biganswer.example. 3600 IN A 10.10.38.44 +biganswer.example. 3600 IN A 10.10.38.45 +biganswer.example. 3600 IN A 10.10.38.46 +biganswer.example. 3600 IN A 10.10.38.47 +biganswer.example. 3600 IN A 10.10.38.48 +biganswer.example. 3600 IN A 10.10.38.49 +biganswer.example. 3600 IN A 10.10.38.50 +biganswer.example. 3600 IN A 10.10.39.1 +biganswer.example. 3600 IN A 10.10.39.2 +biganswer.example. 3600 IN A 10.10.39.3 +biganswer.example. 3600 IN A 10.10.39.4 +biganswer.example. 3600 IN A 10.10.39.5 +biganswer.example. 3600 IN A 10.10.39.6 +biganswer.example. 3600 IN A 10.10.39.7 +biganswer.example. 3600 IN A 10.10.39.8 +biganswer.example. 3600 IN A 10.10.39.9 +biganswer.example. 3600 IN A 10.10.39.10 +biganswer.example. 3600 IN A 10.10.39.11 +biganswer.example. 3600 IN A 10.10.39.12 +biganswer.example. 3600 IN A 10.10.39.13 +biganswer.example. 3600 IN A 10.10.39.14 +biganswer.example. 3600 IN A 10.10.39.15 +biganswer.example. 3600 IN A 10.10.39.16 +biganswer.example. 3600 IN A 10.10.39.17 +biganswer.example. 3600 IN A 10.10.39.18 +biganswer.example. 3600 IN A 10.10.39.19 +biganswer.example. 3600 IN A 10.10.39.20 +biganswer.example. 3600 IN A 10.10.39.21 +biganswer.example. 3600 IN A 10.10.39.22 +biganswer.example. 3600 IN A 10.10.39.23 +biganswer.example. 3600 IN A 10.10.39.24 +biganswer.example. 3600 IN A 10.10.39.25 +biganswer.example. 3600 IN A 10.10.39.26 +biganswer.example. 3600 IN A 10.10.39.27 +biganswer.example. 3600 IN A 10.10.39.28 +biganswer.example. 3600 IN A 10.10.39.29 +biganswer.example. 3600 IN A 10.10.39.30 +biganswer.example. 3600 IN A 10.10.39.31 +biganswer.example. 3600 IN A 10.10.39.32 +biganswer.example. 3600 IN A 10.10.39.33 +biganswer.example. 3600 IN A 10.10.39.34 +biganswer.example. 3600 IN A 10.10.39.35 +biganswer.example. 3600 IN A 10.10.39.36 +biganswer.example. 3600 IN A 10.10.39.37 +biganswer.example. 3600 IN A 10.10.39.38 +biganswer.example. 3600 IN A 10.10.39.39 +biganswer.example. 3600 IN A 10.10.39.40 +biganswer.example. 3600 IN A 10.10.39.41 +biganswer.example. 3600 IN A 10.10.39.42 +biganswer.example. 3600 IN A 10.10.39.43 +biganswer.example. 3600 IN A 10.10.39.44 +biganswer.example. 3600 IN A 10.10.39.45 +biganswer.example. 3600 IN A 10.10.39.46 +biganswer.example. 3600 IN A 10.10.39.47 +biganswer.example. 3600 IN A 10.10.39.48 +biganswer.example. 3600 IN A 10.10.39.49 +biganswer.example. 3600 IN A 10.10.39.50 +biganswer.example. 3600 IN A 10.10.40.1 +biganswer.example. 3600 IN A 10.10.40.2 +biganswer.example. 3600 IN A 10.10.40.3 +biganswer.example. 3600 IN A 10.10.40.4 +biganswer.example. 3600 IN A 10.10.40.5 +biganswer.example. 3600 IN A 10.10.40.6 +biganswer.example. 3600 IN A 10.10.40.7 +biganswer.example. 3600 IN A 10.10.40.8 +biganswer.example. 3600 IN A 10.10.40.9 +biganswer.example. 3600 IN A 10.10.40.10 +biganswer.example. 3600 IN A 10.10.40.11 +biganswer.example. 3600 IN A 10.10.40.12 +biganswer.example. 3600 IN A 10.10.40.13 +biganswer.example. 3600 IN A 10.10.40.14 +biganswer.example. 3600 IN A 10.10.40.15 +biganswer.example. 3600 IN A 10.10.40.16 +biganswer.example. 3600 IN A 10.10.40.17 +biganswer.example. 3600 IN A 10.10.40.18 +biganswer.example. 3600 IN A 10.10.40.19 +biganswer.example. 3600 IN A 10.10.40.20 +biganswer.example. 3600 IN A 10.10.40.21 +biganswer.example. 3600 IN A 10.10.40.22 +biganswer.example. 3600 IN A 10.10.40.23 +biganswer.example. 3600 IN A 10.10.40.24 +biganswer.example. 3600 IN A 10.10.40.25 +biganswer.example. 3600 IN A 10.10.40.26 +biganswer.example. 3600 IN A 10.10.40.27 +biganswer.example. 3600 IN A 10.10.40.28 +biganswer.example. 3600 IN A 10.10.40.29 +biganswer.example. 3600 IN A 10.10.40.30 +biganswer.example. 3600 IN A 10.10.40.31 +biganswer.example. 3600 IN A 10.10.40.32 +biganswer.example. 3600 IN A 10.10.40.33 +biganswer.example. 3600 IN A 10.10.40.34 +biganswer.example. 3600 IN A 10.10.40.35 +biganswer.example. 3600 IN A 10.10.40.36 +biganswer.example. 3600 IN A 10.10.40.37 +biganswer.example. 3600 IN A 10.10.40.38 +biganswer.example. 3600 IN A 10.10.40.39 +biganswer.example. 3600 IN A 10.10.40.40 +biganswer.example. 3600 IN A 10.10.40.41 +biganswer.example. 3600 IN A 10.10.40.42 +biganswer.example. 3600 IN A 10.10.40.43 +biganswer.example. 3600 IN A 10.10.40.44 +biganswer.example. 3600 IN A 10.10.40.45 +biganswer.example. 3600 IN A 10.10.40.46 +biganswer.example. 3600 IN A 10.10.40.47 +biganswer.example. 3600 IN A 10.10.40.48 +biganswer.example. 3600 IN A 10.10.40.49 +biganswer.example. 3600 IN A 10.10.40.50 +biganswer.example. 3600 IN A 10.10.41.1 +biganswer.example. 3600 IN A 10.10.41.2 +biganswer.example. 3600 IN A 10.10.41.3 +biganswer.example. 3600 IN A 10.10.41.4 +biganswer.example. 3600 IN A 10.10.41.5 +biganswer.example. 3600 IN A 10.10.41.6 +biganswer.example. 3600 IN A 10.10.41.7 +biganswer.example. 3600 IN A 10.10.41.8 +biganswer.example. 3600 IN A 10.10.41.9 +biganswer.example. 3600 IN A 10.10.41.10 +biganswer.example. 3600 IN A 10.10.41.11 +biganswer.example. 3600 IN A 10.10.41.12 +biganswer.example. 3600 IN A 10.10.41.13 +biganswer.example. 3600 IN A 10.10.41.14 +biganswer.example. 3600 IN A 10.10.41.15 +biganswer.example. 3600 IN A 10.10.41.16 +biganswer.example. 3600 IN A 10.10.41.17 +biganswer.example. 3600 IN A 10.10.41.18 +biganswer.example. 3600 IN A 10.10.41.19 +biganswer.example. 3600 IN A 10.10.41.20 +biganswer.example. 3600 IN A 10.10.41.21 +biganswer.example. 3600 IN A 10.10.41.22 +biganswer.example. 3600 IN A 10.10.41.23 +biganswer.example. 3600 IN A 10.10.41.24 +biganswer.example. 3600 IN A 10.10.41.25 +biganswer.example. 3600 IN A 10.10.41.26 +biganswer.example. 3600 IN A 10.10.41.27 +biganswer.example. 3600 IN A 10.10.41.28 +biganswer.example. 3600 IN A 10.10.41.29 +biganswer.example. 3600 IN A 10.10.41.30 +biganswer.example. 3600 IN A 10.10.41.31 +biganswer.example. 3600 IN A 10.10.41.32 +biganswer.example. 3600 IN A 10.10.41.33 +biganswer.example. 3600 IN A 10.10.41.34 +biganswer.example. 3600 IN A 10.10.41.35 +biganswer.example. 3600 IN A 10.10.41.36 +biganswer.example. 3600 IN A 10.10.41.37 +biganswer.example. 3600 IN A 10.10.41.38 +biganswer.example. 3600 IN A 10.10.41.39 +biganswer.example. 3600 IN A 10.10.41.40 +biganswer.example. 3600 IN A 10.10.41.41 +biganswer.example. 3600 IN A 10.10.41.42 +biganswer.example. 3600 IN A 10.10.41.43 +biganswer.example. 3600 IN A 10.10.41.44 +biganswer.example. 3600 IN A 10.10.41.45 +biganswer.example. 3600 IN A 10.10.41.46 +biganswer.example. 3600 IN A 10.10.41.47 +biganswer.example. 3600 IN A 10.10.41.48 +biganswer.example. 3600 IN A 10.10.41.49 +biganswer.example. 3600 IN A 10.10.41.50 +biganswer.example. 3600 IN A 10.10.42.1 +biganswer.example. 3600 IN A 10.10.42.2 +biganswer.example. 3600 IN A 10.10.42.3 +biganswer.example. 3600 IN A 10.10.42.4 +biganswer.example. 3600 IN A 10.10.42.5 +biganswer.example. 3600 IN A 10.10.42.6 +biganswer.example. 3600 IN A 10.10.42.7 +biganswer.example. 3600 IN A 10.10.42.8 +biganswer.example. 3600 IN A 10.10.42.9 +biganswer.example. 3600 IN A 10.10.42.10 +biganswer.example. 3600 IN A 10.10.42.11 +biganswer.example. 3600 IN A 10.10.42.12 +biganswer.example. 3600 IN A 10.10.42.13 +biganswer.example. 3600 IN A 10.10.42.14 +biganswer.example. 3600 IN A 10.10.42.15 +biganswer.example. 3600 IN A 10.10.42.16 +biganswer.example. 3600 IN A 10.10.42.17 +biganswer.example. 3600 IN A 10.10.42.18 +biganswer.example. 3600 IN A 10.10.42.19 +biganswer.example. 3600 IN A 10.10.42.20 +biganswer.example. 3600 IN A 10.10.42.21 +biganswer.example. 3600 IN A 10.10.42.22 +biganswer.example. 3600 IN A 10.10.42.23 +biganswer.example. 3600 IN A 10.10.42.24 +biganswer.example. 3600 IN A 10.10.42.25 +biganswer.example. 3600 IN A 10.10.42.26 +biganswer.example. 3600 IN A 10.10.42.27 +biganswer.example. 3600 IN A 10.10.42.28 +biganswer.example. 3600 IN A 10.10.42.29 +biganswer.example. 3600 IN A 10.10.42.30 +biganswer.example. 3600 IN A 10.10.42.31 +biganswer.example. 3600 IN A 10.10.42.32 +biganswer.example. 3600 IN A 10.10.42.33 +biganswer.example. 3600 IN A 10.10.42.34 +biganswer.example. 3600 IN A 10.10.42.35 +biganswer.example. 3600 IN A 10.10.42.36 +biganswer.example. 3600 IN A 10.10.42.37 +biganswer.example. 3600 IN A 10.10.42.38 +biganswer.example. 3600 IN A 10.10.42.39 +biganswer.example. 3600 IN A 10.10.42.40 +biganswer.example. 3600 IN A 10.10.42.41 +biganswer.example. 3600 IN A 10.10.42.42 +biganswer.example. 3600 IN A 10.10.42.43 +biganswer.example. 3600 IN A 10.10.42.44 +biganswer.example. 3600 IN A 10.10.42.45 +biganswer.example. 3600 IN A 10.10.42.46 +biganswer.example. 3600 IN A 10.10.42.47 +biganswer.example. 3600 IN A 10.10.42.48 +biganswer.example. 3600 IN A 10.10.42.49 +biganswer.example. 3600 IN A 10.10.42.50 +biganswer.example. 3600 IN A 10.10.43.1 +biganswer.example. 3600 IN A 10.10.43.2 +biganswer.example. 3600 IN A 10.10.43.3 +biganswer.example. 3600 IN A 10.10.43.4 +biganswer.example. 3600 IN A 10.10.43.5 +biganswer.example. 3600 IN A 10.10.43.6 +biganswer.example. 3600 IN A 10.10.43.7 +biganswer.example. 3600 IN A 10.10.43.8 +biganswer.example. 3600 IN A 10.10.43.9 +biganswer.example. 3600 IN A 10.10.43.10 +biganswer.example. 3600 IN A 10.10.43.11 +biganswer.example. 3600 IN A 10.10.43.12 +biganswer.example. 3600 IN A 10.10.43.13 +biganswer.example. 3600 IN A 10.10.43.14 +biganswer.example. 3600 IN A 10.10.43.15 +biganswer.example. 3600 IN A 10.10.43.16 +biganswer.example. 3600 IN A 10.10.43.17 +biganswer.example. 3600 IN A 10.10.43.18 +biganswer.example. 3600 IN A 10.10.43.19 +biganswer.example. 3600 IN A 10.10.43.20 +biganswer.example. 3600 IN A 10.10.43.21 +biganswer.example. 3600 IN A 10.10.43.22 +biganswer.example. 3600 IN A 10.10.43.23 +biganswer.example. 3600 IN A 10.10.43.24 +biganswer.example. 3600 IN A 10.10.43.25 +biganswer.example. 3600 IN A 10.10.43.26 +biganswer.example. 3600 IN A 10.10.43.27 +biganswer.example. 3600 IN A 10.10.43.28 +biganswer.example. 3600 IN A 10.10.43.29 +biganswer.example. 3600 IN A 10.10.43.30 +biganswer.example. 3600 IN A 10.10.43.31 +biganswer.example. 3600 IN A 10.10.43.32 +biganswer.example. 3600 IN A 10.10.43.33 +biganswer.example. 3600 IN A 10.10.43.34 +biganswer.example. 3600 IN A 10.10.43.35 +biganswer.example. 3600 IN A 10.10.43.36 +biganswer.example. 3600 IN A 10.10.43.37 +biganswer.example. 3600 IN A 10.10.43.38 +biganswer.example. 3600 IN A 10.10.43.39 +biganswer.example. 3600 IN A 10.10.43.40 +biganswer.example. 3600 IN A 10.10.43.41 +biganswer.example. 3600 IN A 10.10.43.42 +biganswer.example. 3600 IN A 10.10.43.43 +biganswer.example. 3600 IN A 10.10.43.44 +biganswer.example. 3600 IN A 10.10.43.45 +biganswer.example. 3600 IN A 10.10.43.46 +biganswer.example. 3600 IN A 10.10.43.47 +biganswer.example. 3600 IN A 10.10.43.48 +biganswer.example. 3600 IN A 10.10.43.49 +biganswer.example. 3600 IN A 10.10.43.50 +biganswer.example. 3600 IN A 10.10.44.1 +biganswer.example. 3600 IN A 10.10.44.2 +biganswer.example. 3600 IN A 10.10.44.3 +biganswer.example. 3600 IN A 10.10.44.4 +biganswer.example. 3600 IN A 10.10.44.5 +biganswer.example. 3600 IN A 10.10.44.6 +biganswer.example. 3600 IN A 10.10.44.7 +biganswer.example. 3600 IN A 10.10.44.8 +biganswer.example. 3600 IN A 10.10.44.9 +biganswer.example. 3600 IN A 10.10.44.10 +biganswer.example. 3600 IN A 10.10.44.11 +biganswer.example. 3600 IN A 10.10.44.12 +biganswer.example. 3600 IN A 10.10.44.13 +biganswer.example. 3600 IN A 10.10.44.14 +biganswer.example. 3600 IN A 10.10.44.15 +biganswer.example. 3600 IN A 10.10.44.16 +biganswer.example. 3600 IN A 10.10.44.17 +biganswer.example. 3600 IN A 10.10.44.18 +biganswer.example. 3600 IN A 10.10.44.19 +biganswer.example. 3600 IN A 10.10.44.20 +biganswer.example. 3600 IN A 10.10.44.21 +biganswer.example. 3600 IN A 10.10.44.22 +biganswer.example. 3600 IN A 10.10.44.23 +biganswer.example. 3600 IN A 10.10.44.24 +biganswer.example. 3600 IN A 10.10.44.25 +biganswer.example. 3600 IN A 10.10.44.26 +biganswer.example. 3600 IN A 10.10.44.27 +biganswer.example. 3600 IN A 10.10.44.28 +biganswer.example. 3600 IN A 10.10.44.29 +biganswer.example. 3600 IN A 10.10.44.30 +biganswer.example. 3600 IN A 10.10.44.31 +biganswer.example. 3600 IN A 10.10.44.32 +biganswer.example. 3600 IN A 10.10.44.33 +biganswer.example. 3600 IN A 10.10.44.34 +biganswer.example. 3600 IN A 10.10.44.35 +biganswer.example. 3600 IN A 10.10.44.36 +biganswer.example. 3600 IN A 10.10.44.37 +biganswer.example. 3600 IN A 10.10.44.38 +biganswer.example. 3600 IN A 10.10.44.39 +biganswer.example. 3600 IN A 10.10.44.40 +biganswer.example. 3600 IN A 10.10.44.41 +biganswer.example. 3600 IN A 10.10.44.42 +biganswer.example. 3600 IN A 10.10.44.43 +biganswer.example. 3600 IN A 10.10.44.44 +biganswer.example. 3600 IN A 10.10.44.45 +biganswer.example. 3600 IN A 10.10.44.46 +biganswer.example. 3600 IN A 10.10.44.47 +biganswer.example. 3600 IN A 10.10.44.48 +biganswer.example. 3600 IN A 10.10.44.49 +biganswer.example. 3600 IN A 10.10.44.50 +biganswer.example. 3600 IN A 10.10.45.1 +biganswer.example. 3600 IN A 10.10.45.2 +biganswer.example. 3600 IN A 10.10.45.3 +biganswer.example. 3600 IN A 10.10.45.4 +biganswer.example. 3600 IN A 10.10.45.5 +biganswer.example. 3600 IN A 10.10.45.6 +biganswer.example. 3600 IN A 10.10.45.7 +biganswer.example. 3600 IN A 10.10.45.8 +biganswer.example. 3600 IN A 10.10.45.9 +biganswer.example. 3600 IN A 10.10.45.10 +biganswer.example. 3600 IN A 10.10.45.11 +biganswer.example. 3600 IN A 10.10.45.12 +biganswer.example. 3600 IN A 10.10.45.13 +biganswer.example. 3600 IN A 10.10.45.14 +biganswer.example. 3600 IN A 10.10.45.15 +biganswer.example. 3600 IN A 10.10.45.16 +biganswer.example. 3600 IN A 10.10.45.17 +biganswer.example. 3600 IN A 10.10.45.18 +biganswer.example. 3600 IN A 10.10.45.19 +biganswer.example. 3600 IN A 10.10.45.20 +biganswer.example. 3600 IN A 10.10.45.21 +biganswer.example. 3600 IN A 10.10.45.22 +biganswer.example. 3600 IN A 10.10.45.23 +biganswer.example. 3600 IN A 10.10.45.24 +biganswer.example. 3600 IN A 10.10.45.25 +biganswer.example. 3600 IN A 10.10.45.26 +biganswer.example. 3600 IN A 10.10.45.27 +biganswer.example. 3600 IN A 10.10.45.28 +biganswer.example. 3600 IN A 10.10.45.29 +biganswer.example. 3600 IN A 10.10.45.30 +biganswer.example. 3600 IN A 10.10.45.31 +biganswer.example. 3600 IN A 10.10.45.32 +biganswer.example. 3600 IN A 10.10.45.33 +biganswer.example. 3600 IN A 10.10.45.34 +biganswer.example. 3600 IN A 10.10.45.35 +biganswer.example. 3600 IN A 10.10.45.36 +biganswer.example. 3600 IN A 10.10.45.37 +biganswer.example. 3600 IN A 10.10.45.38 +biganswer.example. 3600 IN A 10.10.45.39 +biganswer.example. 3600 IN A 10.10.45.40 +biganswer.example. 3600 IN A 10.10.45.41 +biganswer.example. 3600 IN A 10.10.45.42 +biganswer.example. 3600 IN A 10.10.45.43 +biganswer.example. 3600 IN A 10.10.45.44 +biganswer.example. 3600 IN A 10.10.45.45 +biganswer.example. 3600 IN A 10.10.45.46 +biganswer.example. 3600 IN A 10.10.45.47 +biganswer.example. 3600 IN A 10.10.45.48 +biganswer.example. 3600 IN A 10.10.45.49 +biganswer.example. 3600 IN A 10.10.45.50 +biganswer.example. 3600 IN A 10.10.46.1 +biganswer.example. 3600 IN A 10.10.46.2 +biganswer.example. 3600 IN A 10.10.46.3 +biganswer.example. 3600 IN A 10.10.46.4 +biganswer.example. 3600 IN A 10.10.46.5 +biganswer.example. 3600 IN A 10.10.46.6 +biganswer.example. 3600 IN A 10.10.46.7 +biganswer.example. 3600 IN A 10.10.46.8 +biganswer.example. 3600 IN A 10.10.46.9 +biganswer.example. 3600 IN A 10.10.46.10 +biganswer.example. 3600 IN A 10.10.46.11 +biganswer.example. 3600 IN A 10.10.46.12 +biganswer.example. 3600 IN A 10.10.46.13 +biganswer.example. 3600 IN A 10.10.46.14 +biganswer.example. 3600 IN A 10.10.46.15 +biganswer.example. 3600 IN A 10.10.46.16 +biganswer.example. 3600 IN A 10.10.46.17 +biganswer.example. 3600 IN A 10.10.46.18 +biganswer.example. 3600 IN A 10.10.46.19 +biganswer.example. 3600 IN A 10.10.46.20 +biganswer.example. 3600 IN A 10.10.46.21 +biganswer.example. 3600 IN A 10.10.46.22 +biganswer.example. 3600 IN A 10.10.46.23 +biganswer.example. 3600 IN A 10.10.46.24 +biganswer.example. 3600 IN A 10.10.46.25 +biganswer.example. 3600 IN A 10.10.46.26 +biganswer.example. 3600 IN A 10.10.46.27 +biganswer.example. 3600 IN A 10.10.46.28 +biganswer.example. 3600 IN A 10.10.46.29 +biganswer.example. 3600 IN A 10.10.46.30 +biganswer.example. 3600 IN A 10.10.46.31 +biganswer.example. 3600 IN A 10.10.46.32 +biganswer.example. 3600 IN A 10.10.46.33 +biganswer.example. 3600 IN A 10.10.46.34 +biganswer.example. 3600 IN A 10.10.46.35 +biganswer.example. 3600 IN A 10.10.46.36 +biganswer.example. 3600 IN A 10.10.46.37 +biganswer.example. 3600 IN A 10.10.46.38 +biganswer.example. 3600 IN A 10.10.46.39 +biganswer.example. 3600 IN A 10.10.46.40 +biganswer.example. 3600 IN A 10.10.46.41 +biganswer.example. 3600 IN A 10.10.46.42 +biganswer.example. 3600 IN A 10.10.46.43 +biganswer.example. 3600 IN A 10.10.46.44 +biganswer.example. 3600 IN A 10.10.46.45 +biganswer.example. 3600 IN A 10.10.46.46 +biganswer.example. 3600 IN A 10.10.46.47 +biganswer.example. 3600 IN A 10.10.46.48 +biganswer.example. 3600 IN A 10.10.46.49 +biganswer.example. 3600 IN A 10.10.46.50 +biganswer.example. 3600 IN A 10.10.47.1 +biganswer.example. 3600 IN A 10.10.47.2 +biganswer.example. 3600 IN A 10.10.47.3 +biganswer.example. 3600 IN A 10.10.47.4 +biganswer.example. 3600 IN A 10.10.47.5 +biganswer.example. 3600 IN A 10.10.47.6 +biganswer.example. 3600 IN A 10.10.47.7 +biganswer.example. 3600 IN A 10.10.47.8 +biganswer.example. 3600 IN A 10.10.47.9 +biganswer.example. 3600 IN A 10.10.47.10 +biganswer.example. 3600 IN A 10.10.47.11 +biganswer.example. 3600 IN A 10.10.47.12 +biganswer.example. 3600 IN A 10.10.47.13 +biganswer.example. 3600 IN A 10.10.47.14 +biganswer.example. 3600 IN A 10.10.47.15 +biganswer.example. 3600 IN A 10.10.47.16 +biganswer.example. 3600 IN A 10.10.47.17 +biganswer.example. 3600 IN A 10.10.47.18 +biganswer.example. 3600 IN A 10.10.47.19 +biganswer.example. 3600 IN A 10.10.47.20 +biganswer.example. 3600 IN A 10.10.47.21 +biganswer.example. 3600 IN A 10.10.47.22 +biganswer.example. 3600 IN A 10.10.47.23 +biganswer.example. 3600 IN A 10.10.47.24 +biganswer.example. 3600 IN A 10.10.47.25 +biganswer.example. 3600 IN A 10.10.47.26 +biganswer.example. 3600 IN A 10.10.47.27 +biganswer.example. 3600 IN A 10.10.47.28 +biganswer.example. 3600 IN A 10.10.47.29 +biganswer.example. 3600 IN A 10.10.47.30 +biganswer.example. 3600 IN A 10.10.47.31 +biganswer.example. 3600 IN A 10.10.47.32 +biganswer.example. 3600 IN A 10.10.47.33 +biganswer.example. 3600 IN A 10.10.47.34 +biganswer.example. 3600 IN A 10.10.47.35 +biganswer.example. 3600 IN A 10.10.47.36 +biganswer.example. 3600 IN A 10.10.47.37 +biganswer.example. 3600 IN A 10.10.47.38 +biganswer.example. 3600 IN A 10.10.47.39 +biganswer.example. 3600 IN A 10.10.47.40 +biganswer.example. 3600 IN A 10.10.47.41 +biganswer.example. 3600 IN A 10.10.47.42 +biganswer.example. 3600 IN A 10.10.47.43 +biganswer.example. 3600 IN A 10.10.47.44 +biganswer.example. 3600 IN A 10.10.47.45 +biganswer.example. 3600 IN A 10.10.47.46 +biganswer.example. 3600 IN A 10.10.47.47 +biganswer.example. 3600 IN A 10.10.47.48 +biganswer.example. 3600 IN A 10.10.47.49 +biganswer.example. 3600 IN A 10.10.47.50 +biganswer.example. 3600 IN A 10.10.48.1 +biganswer.example. 3600 IN A 10.10.48.2 +biganswer.example. 3600 IN A 10.10.48.3 +biganswer.example. 3600 IN A 10.10.48.4 +biganswer.example. 3600 IN A 10.10.48.5 +biganswer.example. 3600 IN A 10.10.48.6 +biganswer.example. 3600 IN A 10.10.48.7 +biganswer.example. 3600 IN A 10.10.48.8 +biganswer.example. 3600 IN A 10.10.48.9 +biganswer.example. 3600 IN A 10.10.48.10 +biganswer.example. 3600 IN A 10.10.48.11 +biganswer.example. 3600 IN A 10.10.48.12 +biganswer.example. 3600 IN A 10.10.48.13 +biganswer.example. 3600 IN A 10.10.48.14 +biganswer.example. 3600 IN A 10.10.48.15 +biganswer.example. 3600 IN A 10.10.48.16 +biganswer.example. 3600 IN A 10.10.48.17 +biganswer.example. 3600 IN A 10.10.48.18 +biganswer.example. 3600 IN A 10.10.48.19 +biganswer.example. 3600 IN A 10.10.48.20 +biganswer.example. 3600 IN A 10.10.48.21 +biganswer.example. 3600 IN A 10.10.48.22 +biganswer.example. 3600 IN A 10.10.48.23 +biganswer.example. 3600 IN A 10.10.48.24 +biganswer.example. 3600 IN A 10.10.48.25 +biganswer.example. 3600 IN A 10.10.48.26 +biganswer.example. 3600 IN A 10.10.48.27 +biganswer.example. 3600 IN A 10.10.48.28 +biganswer.example. 3600 IN A 10.10.48.29 +biganswer.example. 3600 IN A 10.10.48.30 +biganswer.example. 3600 IN A 10.10.48.31 +biganswer.example. 3600 IN A 10.10.48.32 +biganswer.example. 3600 IN A 10.10.48.33 +biganswer.example. 3600 IN A 10.10.48.34 +biganswer.example. 3600 IN A 10.10.48.35 +biganswer.example. 3600 IN A 10.10.48.36 +biganswer.example. 3600 IN A 10.10.48.37 +biganswer.example. 3600 IN A 10.10.48.38 +biganswer.example. 3600 IN A 10.10.48.39 +biganswer.example. 3600 IN A 10.10.48.40 +biganswer.example. 3600 IN A 10.10.48.41 +biganswer.example. 3600 IN A 10.10.48.42 +biganswer.example. 3600 IN A 10.10.48.43 +biganswer.example. 3600 IN A 10.10.48.44 +biganswer.example. 3600 IN A 10.10.48.45 +biganswer.example. 3600 IN A 10.10.48.46 +biganswer.example. 3600 IN A 10.10.48.47 +biganswer.example. 3600 IN A 10.10.48.48 +biganswer.example. 3600 IN A 10.10.48.49 +biganswer.example. 3600 IN A 10.10.48.50 +biganswer.example. 3600 IN A 10.10.49.1 +biganswer.example. 3600 IN A 10.10.49.2 +biganswer.example. 3600 IN A 10.10.49.3 +biganswer.example. 3600 IN A 10.10.49.4 +biganswer.example. 3600 IN A 10.10.49.5 +biganswer.example. 3600 IN A 10.10.49.6 +biganswer.example. 3600 IN A 10.10.49.7 +biganswer.example. 3600 IN A 10.10.49.8 +biganswer.example. 3600 IN A 10.10.49.9 +biganswer.example. 3600 IN A 10.10.49.10 +biganswer.example. 3600 IN A 10.10.49.11 +biganswer.example. 3600 IN A 10.10.49.12 +biganswer.example. 3600 IN A 10.10.49.13 +biganswer.example. 3600 IN A 10.10.49.14 +biganswer.example. 3600 IN A 10.10.49.15 +biganswer.example. 3600 IN A 10.10.49.16 +biganswer.example. 3600 IN A 10.10.49.17 +biganswer.example. 3600 IN A 10.10.49.18 +biganswer.example. 3600 IN A 10.10.49.19 +biganswer.example. 3600 IN A 10.10.49.20 +biganswer.example. 3600 IN A 10.10.49.21 +biganswer.example. 3600 IN A 10.10.49.22 +biganswer.example. 3600 IN A 10.10.49.23 +biganswer.example. 3600 IN A 10.10.49.24 +biganswer.example. 3600 IN A 10.10.49.25 +biganswer.example. 3600 IN A 10.10.49.26 +biganswer.example. 3600 IN A 10.10.49.27 +biganswer.example. 3600 IN A 10.10.49.28 +biganswer.example. 3600 IN A 10.10.49.29 +biganswer.example. 3600 IN A 10.10.49.30 +biganswer.example. 3600 IN A 10.10.49.31 +biganswer.example. 3600 IN A 10.10.49.32 +biganswer.example. 3600 IN A 10.10.49.33 +biganswer.example. 3600 IN A 10.10.49.34 +biganswer.example. 3600 IN A 10.10.49.35 +biganswer.example. 3600 IN A 10.10.49.36 +biganswer.example. 3600 IN A 10.10.49.37 +biganswer.example. 3600 IN A 10.10.49.38 +biganswer.example. 3600 IN A 10.10.49.39 +biganswer.example. 3600 IN A 10.10.49.40 +biganswer.example. 3600 IN A 10.10.49.41 +biganswer.example. 3600 IN A 10.10.49.42 +biganswer.example. 3600 IN A 10.10.49.43 +biganswer.example. 3600 IN A 10.10.49.44 +biganswer.example. 3600 IN A 10.10.49.45 +biganswer.example. 3600 IN A 10.10.49.46 +biganswer.example. 3600 IN A 10.10.49.47 +biganswer.example. 3600 IN A 10.10.49.48 +biganswer.example. 3600 IN A 10.10.49.49 +biganswer.example. 3600 IN A 10.10.49.50 +biganswer.example. 3600 IN A 10.10.50.1 +biganswer.example. 3600 IN A 10.10.50.2 +biganswer.example. 3600 IN A 10.10.50.3 +biganswer.example. 3600 IN A 10.10.50.4 +biganswer.example. 3600 IN A 10.10.50.5 +biganswer.example. 3600 IN A 10.10.50.6 +biganswer.example. 3600 IN A 10.10.50.7 +biganswer.example. 3600 IN A 10.10.50.8 +biganswer.example. 3600 IN A 10.10.50.9 +biganswer.example. 3600 IN A 10.10.50.10 +biganswer.example. 3600 IN A 10.10.50.11 +biganswer.example. 3600 IN A 10.10.50.12 +biganswer.example. 3600 IN A 10.10.50.13 +biganswer.example. 3600 IN A 10.10.50.14 +biganswer.example. 3600 IN A 10.10.50.15 +biganswer.example. 3600 IN A 10.10.50.16 +biganswer.example. 3600 IN A 10.10.50.17 +biganswer.example. 3600 IN A 10.10.50.18 +biganswer.example. 3600 IN A 10.10.50.19 +biganswer.example. 3600 IN A 10.10.50.20 +biganswer.example. 3600 IN A 10.10.50.21 +biganswer.example. 3600 IN A 10.10.50.22 +biganswer.example. 3600 IN A 10.10.50.23 +biganswer.example. 3600 IN A 10.10.50.24 +biganswer.example. 3600 IN A 10.10.50.25 +biganswer.example. 3600 IN A 10.10.50.26 +biganswer.example. 3600 IN A 10.10.50.27 +biganswer.example. 3600 IN A 10.10.50.28 +biganswer.example. 3600 IN A 10.10.50.29 +biganswer.example. 3600 IN A 10.10.50.30 +biganswer.example. 3600 IN A 10.10.50.31 +biganswer.example. 3600 IN A 10.10.50.32 +biganswer.example. 3600 IN A 10.10.50.33 +biganswer.example. 3600 IN A 10.10.50.34 +biganswer.example. 3600 IN A 10.10.50.35 +biganswer.example. 3600 IN A 10.10.50.36 +biganswer.example. 3600 IN A 10.10.50.37 +biganswer.example. 3600 IN A 10.10.50.38 +biganswer.example. 3600 IN A 10.10.50.39 +biganswer.example. 3600 IN A 10.10.50.40 +biganswer.example. 3600 IN A 10.10.50.41 +biganswer.example. 3600 IN A 10.10.50.42 +biganswer.example. 3600 IN A 10.10.50.43 +biganswer.example. 3600 IN A 10.10.50.44 +biganswer.example. 3600 IN A 10.10.50.45 +biganswer.example. 3600 IN A 10.10.50.46 +biganswer.example. 3600 IN A 10.10.50.47 +biganswer.example. 3600 IN A 10.10.50.48 +biganswer.example. 3600 IN A 10.10.50.49 +biganswer.example. 3600 IN A 10.10.50.50 +caa01.example. 3600 IN CAA 0 issue "ca.example.net; policy=ev" +caa02.example. 3600 IN CAA 128 tbs "Unknown" +caa03.example. 3600 IN CAA 128 tbs "" +cdnskey01.example. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +cds01.example. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +cname01.example. 3600 IN CNAME cname-target. +cname02.example. 3600 IN CNAME cname-target.example. +cname03.example. 3600 IN CNAME . +csync01.example. 3600 IN CSYNC 0 0 A NS AAAA +csync02.example. 3600 IN CSYNC 0 0 +dhcid01.example. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA= +dhcid02.example. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No= +dhcid03.example. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY= +dlv.example. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +dname01.example. 3600 IN DNAME dname-target. +dname02.example. 3600 IN DNAME dname-target.example. +dname03.example. 3600 IN DNAME . +doa01.example. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7 +doa02.example. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8= +ds01.example. 3600 IN NS ns42.example. +ds01.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13 +ds02.example. 3600 IN NS ns43.example. +ds02.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 +eid01.example. 3600 IN EID 1289AB +eui48.example. 3600 IN EUI48 01-23-45-67-89-ab +eui64.example. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef +gid01.example. 3600 IN GID \# 1 03 +gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0" +gpos02.example. 3600 IN GPOS "" "" "" +hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02.example. 3600 IN HINFO "PC" "NetBSD" +hip1.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip2.example. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +https0.example. 3600 IN HTTPS 0 example.net. +https1.example. 3600 IN HTTPS 1 . port=60 +ipseckey01.example. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey02.example. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey03.example. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey04.example. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey05.example. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +isdn01.example. 3600 IN ISDN "isdn-address" +isdn02.example. 3600 IN ISDN "isdn-address" "subaddress" +isdn03.example. 3600 IN ISDN "isdn-address" +isdn04.example. 3600 IN ISDN "isdn-address" "subaddress" +keydata.example. 3600 IN TYPE65533 \# 0 +keydata.example. 3600 IN TYPE65533 \# 6 010203040506 +keydata.example. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506 +kx01.example. 3600 IN KX 10 kdc.example. +kx02.example. 3600 IN KX 10 . +l32.example. 3600 IN L32 10 1.2.3.4 +l64.example. 3600 IN L64 10 14:4fff:ff20:ee64 +loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +lp.example. 3600 IN LP 10 example.net. +mb01.example. 3600 IN MG madname.example. +mb02.example. 3600 IN MG . +mg01.example. 3600 IN MG mgmname.example. +mg02.example. 3600 IN MG . +minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example. +minfo02.example. 3600 IN MINFO . . +mr01.example. 3600 IN MR mrname.example. +mr02.example. 3600 IN MR . +mx01.example. 3600 IN MX 10 mail.example. +mx02.example. 3600 IN MX 10 . +naptr01.example. 3600 IN NAPTR 0 0 "" "" "" . +naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nid.example. 3600 IN NID 10 14:4fff:ff20:ee64 +nimloc01.example. 3600 IN NIMLOC 1289AB +ninfo01.example. 3600 IN NINFO "foo" +ninfo02.example. 3600 IN NINFO "foo" "bar" +ninfo03.example. 3600 IN NINFO "foo" +ninfo04.example. 3600 IN NINFO "foo" "bar" +ninfo05.example. 3600 IN NINFO "foo bar" +ninfo06.example. 3600 IN NINFO "foo bar" +ninfo07.example. 3600 IN NINFO "foo bar" +ninfo08.example. 3600 IN NINFO "foo\010bar" +ninfo09.example. 3600 IN NINFO "foo\010bar" +ninfo10.example. 3600 IN NINFO "foo bar" +ninfo11.example. 3600 IN NINFO "\"foo\"" +ninfo12.example. 3600 IN NINFO "\"foo\"" +ninfo13.example. 3600 IN NINFO "foo;" +ninfo14.example. 3600 IN NINFO "foo;" +ninfo15.example. 3600 IN NINFO "bar\\;" +ns2.example. 3600 IN A 10.53.0.2 +nsap-ptr01.example. 3600 IN NSAP-PTR foo. +nsap-ptr01.example. 3600 IN NSAP-PTR . +nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY +nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC +nsec03.example. 3600 IN NSEC . A +nsec04.example. 3600 IN NSEC . TYPE127 +openpgpkey.example. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +ptr01.example. 3600 IN PTR example. +px01.example. 3600 IN PX 65535 foo. bar. +px02.example. 3600 IN PX 65535 . . +resinfo.example. 3600 IN RESINFO "qnamemin" "exterr=15,16,17" "infourl=https://resolver.example.com/guide" +rkey01.example. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example. +rp02.example. 3600 IN RP . . +rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +rt01.example. 3600 IN RT 0 intermediate-host.example. +rt02.example. 3600 IN RT 65535 . +sink01.example. 3600 IN SINK 1 0 0 +sink02.example. 3600 IN SINK 8 0 2 l4ik +smimea.example. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC +spf01.example. 3600 IN SPF "v=spf1 -all" +spf02.example. 3600 IN SPF "v=spf1" " -all" +srv01.example. 3600 IN SRV 0 0 0 . +srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example. +sshfp01.example. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83 +sshfp02.example. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC +svcb0.example. 3600 IN SVCB 0 example.net. +svcb1.example. 3600 IN SVCB 1 . port=60 +ta.example. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +talink0.example. 3600 IN TALINK . talink1.example. +talink1.example. 3600 IN TALINK talink0.example. talink2.example. +talink2.example. 3600 IN TALINK talink2.example. . +tlsa.example. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC +txt01.example. 3600 IN TXT "foo" +txt02.example. 3600 IN TXT "foo" "bar" +txt03.example. 3600 IN TXT "foo" +txt04.example. 3600 IN TXT "foo" "bar" +txt05.example. 3600 IN TXT "foo bar" +txt06.example. 3600 IN TXT "foo bar" +txt07.example. 3600 IN TXT "foo bar" +txt08.example. 3600 IN TXT "foo\010bar" +txt09.example. 3600 IN TXT "foo\010bar" +txt10.example. 3600 IN TXT "foo bar" +txt11.example. 3600 IN TXT "\"foo\"" +txt12.example. 3600 IN TXT "\"foo\"" +txt13.example. 3600 IN TXT "foo;" +txt14.example. 3600 IN TXT "foo;" +txt15.example. 3600 IN TXT "bar\\;" +uid01.example. 3600 IN UID \# 1 02 +uinfo01.example. 3600 IN UINFO \# 1 01 +unspec01.example. 3600 IN UNSPEC \# 1 04 +uri01.example. 3600 IN URI 10 20 "https://www.isc.org/" +uri02.example. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/" +uri03.example. 3600 IN URI 30 40 "" +wallet.example. 3600 IN WALLET "currency-identifer" "wallet-identifier" +wallet-multiple.example. 3600 IN WALLET "currency-identifer1" "wallet-identifier1" +wallet-multiple.example. 3600 IN WALLET "currency-identifer1" "wallet-identifier2" +wallet-multiple.example. 3600 IN WALLET "currency-identifer2" "wallet-identifier3" +wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03.example. 3600 IN WKS 10.0.0.2 6 65535 +x2501.example. 3600 IN X25 "123456789" +zonemd01.example. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB +zonemd02.example. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27 +8f1tmio9avcom2k0frp92lgcumak0cad.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM +kcd3juae64f9c5csl1kif1htaui7un0g.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E +mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG +example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600 diff --git a/bin/tests/system/doth/example8.axfr.good b/bin/tests/system/doth/example8.axfr.good new file mode 100644 index 0000000..39d70e2 --- /dev/null +++ b/bin/tests/system/doth/example8.axfr.good @@ -0,0 +1,2681 @@ +example8. 86400 IN SOA ns2.example8. hostmaster.example8. 1397051952 5 5 1814400 3600 +example8. 3600 IN NS ns2.example8. +example8. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +a01.example8. 3600 IN A 0.0.0.0 +a02.example8. 3600 IN A 255.255.255.255 +a601.example8. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +a601.example8. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo. +a601.example8. 3600 IN A6 127 ::1 foo. +a601.example8. 3600 IN A6 128 . +aaaa01.example8. 3600 IN AAAA ::1 +aaaa02.example8. 3600 IN AAAA fd92:7065:b8e:ffff::5 +afsdb01.example8. 3600 IN AFSDB 0 hostname.example8. +afsdb02.example8. 3600 IN AFSDB 65535 . +amtrelay01.example8. 3600 IN AMTRELAY 0 0 0 +amtrelay02.example8. 3600 IN AMTRELAY 0 1 0 +amtrelay03.example8. 3600 IN AMTRELAY 0 0 1 0.0.0.0 +amtrelay04.example8. 3600 IN AMTRELAY 0 0 2 :: +amtrelay05.example8. 3600 IN AMTRELAY 0 0 3 example.net. +amtrelay06.example8. 3600 IN AMTRELAY \# 2 0004 +apl01.example8. 3600 IN APL !1:10.0.0.1/32 1:10.0.0.0/24 +apl02.example8. 3600 IN APL +atma01.example8. 3600 IN ATMA +61200000000 +atma02.example8. 3600 IN ATMA +61200000000 +atma03.example8. 3600 IN ATMA 1234567890abcdef +atma04.example8. 3600 IN ATMA fedcba0987654321 +avc.example8. 3600 IN AVC "foo:bar" +biganswer.example8. 3600 IN A 10.10.1.1 +biganswer.example8. 3600 IN A 10.10.1.2 +biganswer.example8. 3600 IN A 10.10.1.3 +biganswer.example8. 3600 IN A 10.10.1.4 +biganswer.example8. 3600 IN A 10.10.1.5 +biganswer.example8. 3600 IN A 10.10.1.6 +biganswer.example8. 3600 IN A 10.10.1.7 +biganswer.example8. 3600 IN A 10.10.1.8 +biganswer.example8. 3600 IN A 10.10.1.9 +biganswer.example8. 3600 IN A 10.10.1.10 +biganswer.example8. 3600 IN A 10.10.1.11 +biganswer.example8. 3600 IN A 10.10.1.12 +biganswer.example8. 3600 IN A 10.10.1.13 +biganswer.example8. 3600 IN A 10.10.1.14 +biganswer.example8. 3600 IN A 10.10.1.15 +biganswer.example8. 3600 IN A 10.10.1.16 +biganswer.example8. 3600 IN A 10.10.1.17 +biganswer.example8. 3600 IN A 10.10.1.18 +biganswer.example8. 3600 IN A 10.10.1.19 +biganswer.example8. 3600 IN A 10.10.1.20 +biganswer.example8. 3600 IN A 10.10.1.21 +biganswer.example8. 3600 IN A 10.10.1.22 +biganswer.example8. 3600 IN A 10.10.1.23 +biganswer.example8. 3600 IN A 10.10.1.24 +biganswer.example8. 3600 IN A 10.10.1.25 +biganswer.example8. 3600 IN A 10.10.1.26 +biganswer.example8. 3600 IN A 10.10.1.27 +biganswer.example8. 3600 IN A 10.10.1.28 +biganswer.example8. 3600 IN A 10.10.1.29 +biganswer.example8. 3600 IN A 10.10.1.30 +biganswer.example8. 3600 IN A 10.10.1.31 +biganswer.example8. 3600 IN A 10.10.1.32 +biganswer.example8. 3600 IN A 10.10.1.33 +biganswer.example8. 3600 IN A 10.10.1.34 +biganswer.example8. 3600 IN A 10.10.1.35 +biganswer.example8. 3600 IN A 10.10.1.36 +biganswer.example8. 3600 IN A 10.10.1.37 +biganswer.example8. 3600 IN A 10.10.1.38 +biganswer.example8. 3600 IN A 10.10.1.39 +biganswer.example8. 3600 IN A 10.10.1.40 +biganswer.example8. 3600 IN A 10.10.1.41 +biganswer.example8. 3600 IN A 10.10.1.42 +biganswer.example8. 3600 IN A 10.10.1.43 +biganswer.example8. 3600 IN A 10.10.1.44 +biganswer.example8. 3600 IN A 10.10.1.45 +biganswer.example8. 3600 IN A 10.10.1.46 +biganswer.example8. 3600 IN A 10.10.1.47 +biganswer.example8. 3600 IN A 10.10.1.48 +biganswer.example8. 3600 IN A 10.10.1.49 +biganswer.example8. 3600 IN A 10.10.1.50 +biganswer.example8. 3600 IN A 10.10.2.1 +biganswer.example8. 3600 IN A 10.10.2.2 +biganswer.example8. 3600 IN A 10.10.2.3 +biganswer.example8. 3600 IN A 10.10.2.4 +biganswer.example8. 3600 IN A 10.10.2.5 +biganswer.example8. 3600 IN A 10.10.2.6 +biganswer.example8. 3600 IN A 10.10.2.7 +biganswer.example8. 3600 IN A 10.10.2.8 +biganswer.example8. 3600 IN A 10.10.2.9 +biganswer.example8. 3600 IN A 10.10.2.10 +biganswer.example8. 3600 IN A 10.10.2.11 +biganswer.example8. 3600 IN A 10.10.2.12 +biganswer.example8. 3600 IN A 10.10.2.13 +biganswer.example8. 3600 IN A 10.10.2.14 +biganswer.example8. 3600 IN A 10.10.2.15 +biganswer.example8. 3600 IN A 10.10.2.16 +biganswer.example8. 3600 IN A 10.10.2.17 +biganswer.example8. 3600 IN A 10.10.2.18 +biganswer.example8. 3600 IN A 10.10.2.19 +biganswer.example8. 3600 IN A 10.10.2.20 +biganswer.example8. 3600 IN A 10.10.2.21 +biganswer.example8. 3600 IN A 10.10.2.22 +biganswer.example8. 3600 IN A 10.10.2.23 +biganswer.example8. 3600 IN A 10.10.2.24 +biganswer.example8. 3600 IN A 10.10.2.25 +biganswer.example8. 3600 IN A 10.10.2.26 +biganswer.example8. 3600 IN A 10.10.2.27 +biganswer.example8. 3600 IN A 10.10.2.28 +biganswer.example8. 3600 IN A 10.10.2.29 +biganswer.example8. 3600 IN A 10.10.2.30 +biganswer.example8. 3600 IN A 10.10.2.31 +biganswer.example8. 3600 IN A 10.10.2.32 +biganswer.example8. 3600 IN A 10.10.2.33 +biganswer.example8. 3600 IN A 10.10.2.34 +biganswer.example8. 3600 IN A 10.10.2.35 +biganswer.example8. 3600 IN A 10.10.2.36 +biganswer.example8. 3600 IN A 10.10.2.37 +biganswer.example8. 3600 IN A 10.10.2.38 +biganswer.example8. 3600 IN A 10.10.2.39 +biganswer.example8. 3600 IN A 10.10.2.40 +biganswer.example8. 3600 IN A 10.10.2.41 +biganswer.example8. 3600 IN A 10.10.2.42 +biganswer.example8. 3600 IN A 10.10.2.43 +biganswer.example8. 3600 IN A 10.10.2.44 +biganswer.example8. 3600 IN A 10.10.2.45 +biganswer.example8. 3600 IN A 10.10.2.46 +biganswer.example8. 3600 IN A 10.10.2.47 +biganswer.example8. 3600 IN A 10.10.2.48 +biganswer.example8. 3600 IN A 10.10.2.49 +biganswer.example8. 3600 IN A 10.10.2.50 +biganswer.example8. 3600 IN A 10.10.3.1 +biganswer.example8. 3600 IN A 10.10.3.2 +biganswer.example8. 3600 IN A 10.10.3.3 +biganswer.example8. 3600 IN A 10.10.3.4 +biganswer.example8. 3600 IN A 10.10.3.5 +biganswer.example8. 3600 IN A 10.10.3.6 +biganswer.example8. 3600 IN A 10.10.3.7 +biganswer.example8. 3600 IN A 10.10.3.8 +biganswer.example8. 3600 IN A 10.10.3.9 +biganswer.example8. 3600 IN A 10.10.3.10 +biganswer.example8. 3600 IN A 10.10.3.11 +biganswer.example8. 3600 IN A 10.10.3.12 +biganswer.example8. 3600 IN A 10.10.3.13 +biganswer.example8. 3600 IN A 10.10.3.14 +biganswer.example8. 3600 IN A 10.10.3.15 +biganswer.example8. 3600 IN A 10.10.3.16 +biganswer.example8. 3600 IN A 10.10.3.17 +biganswer.example8. 3600 IN A 10.10.3.18 +biganswer.example8. 3600 IN A 10.10.3.19 +biganswer.example8. 3600 IN A 10.10.3.20 +biganswer.example8. 3600 IN A 10.10.3.21 +biganswer.example8. 3600 IN A 10.10.3.22 +biganswer.example8. 3600 IN A 10.10.3.23 +biganswer.example8. 3600 IN A 10.10.3.24 +biganswer.example8. 3600 IN A 10.10.3.25 +biganswer.example8. 3600 IN A 10.10.3.26 +biganswer.example8. 3600 IN A 10.10.3.27 +biganswer.example8. 3600 IN A 10.10.3.28 +biganswer.example8. 3600 IN A 10.10.3.29 +biganswer.example8. 3600 IN A 10.10.3.30 +biganswer.example8. 3600 IN A 10.10.3.31 +biganswer.example8. 3600 IN A 10.10.3.32 +biganswer.example8. 3600 IN A 10.10.3.33 +biganswer.example8. 3600 IN A 10.10.3.34 +biganswer.example8. 3600 IN A 10.10.3.35 +biganswer.example8. 3600 IN A 10.10.3.36 +biganswer.example8. 3600 IN A 10.10.3.37 +biganswer.example8. 3600 IN A 10.10.3.38 +biganswer.example8. 3600 IN A 10.10.3.39 +biganswer.example8. 3600 IN A 10.10.3.40 +biganswer.example8. 3600 IN A 10.10.3.41 +biganswer.example8. 3600 IN A 10.10.3.42 +biganswer.example8. 3600 IN A 10.10.3.43 +biganswer.example8. 3600 IN A 10.10.3.44 +biganswer.example8. 3600 IN A 10.10.3.45 +biganswer.example8. 3600 IN A 10.10.3.46 +biganswer.example8. 3600 IN A 10.10.3.47 +biganswer.example8. 3600 IN A 10.10.3.48 +biganswer.example8. 3600 IN A 10.10.3.49 +biganswer.example8. 3600 IN A 10.10.3.50 +biganswer.example8. 3600 IN A 10.10.4.1 +biganswer.example8. 3600 IN A 10.10.4.2 +biganswer.example8. 3600 IN A 10.10.4.3 +biganswer.example8. 3600 IN A 10.10.4.4 +biganswer.example8. 3600 IN A 10.10.4.5 +biganswer.example8. 3600 IN A 10.10.4.6 +biganswer.example8. 3600 IN A 10.10.4.7 +biganswer.example8. 3600 IN A 10.10.4.8 +biganswer.example8. 3600 IN A 10.10.4.9 +biganswer.example8. 3600 IN A 10.10.4.10 +biganswer.example8. 3600 IN A 10.10.4.11 +biganswer.example8. 3600 IN A 10.10.4.12 +biganswer.example8. 3600 IN A 10.10.4.13 +biganswer.example8. 3600 IN A 10.10.4.14 +biganswer.example8. 3600 IN A 10.10.4.15 +biganswer.example8. 3600 IN A 10.10.4.16 +biganswer.example8. 3600 IN A 10.10.4.17 +biganswer.example8. 3600 IN A 10.10.4.18 +biganswer.example8. 3600 IN A 10.10.4.19 +biganswer.example8. 3600 IN A 10.10.4.20 +biganswer.example8. 3600 IN A 10.10.4.21 +biganswer.example8. 3600 IN A 10.10.4.22 +biganswer.example8. 3600 IN A 10.10.4.23 +biganswer.example8. 3600 IN A 10.10.4.24 +biganswer.example8. 3600 IN A 10.10.4.25 +biganswer.example8. 3600 IN A 10.10.4.26 +biganswer.example8. 3600 IN A 10.10.4.27 +biganswer.example8. 3600 IN A 10.10.4.28 +biganswer.example8. 3600 IN A 10.10.4.29 +biganswer.example8. 3600 IN A 10.10.4.30 +biganswer.example8. 3600 IN A 10.10.4.31 +biganswer.example8. 3600 IN A 10.10.4.32 +biganswer.example8. 3600 IN A 10.10.4.33 +biganswer.example8. 3600 IN A 10.10.4.34 +biganswer.example8. 3600 IN A 10.10.4.35 +biganswer.example8. 3600 IN A 10.10.4.36 +biganswer.example8. 3600 IN A 10.10.4.37 +biganswer.example8. 3600 IN A 10.10.4.38 +biganswer.example8. 3600 IN A 10.10.4.39 +biganswer.example8. 3600 IN A 10.10.4.40 +biganswer.example8. 3600 IN A 10.10.4.41 +biganswer.example8. 3600 IN A 10.10.4.42 +biganswer.example8. 3600 IN A 10.10.4.43 +biganswer.example8. 3600 IN A 10.10.4.44 +biganswer.example8. 3600 IN A 10.10.4.45 +biganswer.example8. 3600 IN A 10.10.4.46 +biganswer.example8. 3600 IN A 10.10.4.47 +biganswer.example8. 3600 IN A 10.10.4.48 +biganswer.example8. 3600 IN A 10.10.4.49 +biganswer.example8. 3600 IN A 10.10.4.50 +biganswer.example8. 3600 IN A 10.10.5.1 +biganswer.example8. 3600 IN A 10.10.5.2 +biganswer.example8. 3600 IN A 10.10.5.3 +biganswer.example8. 3600 IN A 10.10.5.4 +biganswer.example8. 3600 IN A 10.10.5.5 +biganswer.example8. 3600 IN A 10.10.5.6 +biganswer.example8. 3600 IN A 10.10.5.7 +biganswer.example8. 3600 IN A 10.10.5.8 +biganswer.example8. 3600 IN A 10.10.5.9 +biganswer.example8. 3600 IN A 10.10.5.10 +biganswer.example8. 3600 IN A 10.10.5.11 +biganswer.example8. 3600 IN A 10.10.5.12 +biganswer.example8. 3600 IN A 10.10.5.13 +biganswer.example8. 3600 IN A 10.10.5.14 +biganswer.example8. 3600 IN A 10.10.5.15 +biganswer.example8. 3600 IN A 10.10.5.16 +biganswer.example8. 3600 IN A 10.10.5.17 +biganswer.example8. 3600 IN A 10.10.5.18 +biganswer.example8. 3600 IN A 10.10.5.19 +biganswer.example8. 3600 IN A 10.10.5.20 +biganswer.example8. 3600 IN A 10.10.5.21 +biganswer.example8. 3600 IN A 10.10.5.22 +biganswer.example8. 3600 IN A 10.10.5.23 +biganswer.example8. 3600 IN A 10.10.5.24 +biganswer.example8. 3600 IN A 10.10.5.25 +biganswer.example8. 3600 IN A 10.10.5.26 +biganswer.example8. 3600 IN A 10.10.5.27 +biganswer.example8. 3600 IN A 10.10.5.28 +biganswer.example8. 3600 IN A 10.10.5.29 +biganswer.example8. 3600 IN A 10.10.5.30 +biganswer.example8. 3600 IN A 10.10.5.31 +biganswer.example8. 3600 IN A 10.10.5.32 +biganswer.example8. 3600 IN A 10.10.5.33 +biganswer.example8. 3600 IN A 10.10.5.34 +biganswer.example8. 3600 IN A 10.10.5.35 +biganswer.example8. 3600 IN A 10.10.5.36 +biganswer.example8. 3600 IN A 10.10.5.37 +biganswer.example8. 3600 IN A 10.10.5.38 +biganswer.example8. 3600 IN A 10.10.5.39 +biganswer.example8. 3600 IN A 10.10.5.40 +biganswer.example8. 3600 IN A 10.10.5.41 +biganswer.example8. 3600 IN A 10.10.5.42 +biganswer.example8. 3600 IN A 10.10.5.43 +biganswer.example8. 3600 IN A 10.10.5.44 +biganswer.example8. 3600 IN A 10.10.5.45 +biganswer.example8. 3600 IN A 10.10.5.46 +biganswer.example8. 3600 IN A 10.10.5.47 +biganswer.example8. 3600 IN A 10.10.5.48 +biganswer.example8. 3600 IN A 10.10.5.49 +biganswer.example8. 3600 IN A 10.10.5.50 +biganswer.example8. 3600 IN A 10.10.6.1 +biganswer.example8. 3600 IN A 10.10.6.2 +biganswer.example8. 3600 IN A 10.10.6.3 +biganswer.example8. 3600 IN A 10.10.6.4 +biganswer.example8. 3600 IN A 10.10.6.5 +biganswer.example8. 3600 IN A 10.10.6.6 +biganswer.example8. 3600 IN A 10.10.6.7 +biganswer.example8. 3600 IN A 10.10.6.8 +biganswer.example8. 3600 IN A 10.10.6.9 +biganswer.example8. 3600 IN A 10.10.6.10 +biganswer.example8. 3600 IN A 10.10.6.11 +biganswer.example8. 3600 IN A 10.10.6.12 +biganswer.example8. 3600 IN A 10.10.6.13 +biganswer.example8. 3600 IN A 10.10.6.14 +biganswer.example8. 3600 IN A 10.10.6.15 +biganswer.example8. 3600 IN A 10.10.6.16 +biganswer.example8. 3600 IN A 10.10.6.17 +biganswer.example8. 3600 IN A 10.10.6.18 +biganswer.example8. 3600 IN A 10.10.6.19 +biganswer.example8. 3600 IN A 10.10.6.20 +biganswer.example8. 3600 IN A 10.10.6.21 +biganswer.example8. 3600 IN A 10.10.6.22 +biganswer.example8. 3600 IN A 10.10.6.23 +biganswer.example8. 3600 IN A 10.10.6.24 +biganswer.example8. 3600 IN A 10.10.6.25 +biganswer.example8. 3600 IN A 10.10.6.26 +biganswer.example8. 3600 IN A 10.10.6.27 +biganswer.example8. 3600 IN A 10.10.6.28 +biganswer.example8. 3600 IN A 10.10.6.29 +biganswer.example8. 3600 IN A 10.10.6.30 +biganswer.example8. 3600 IN A 10.10.6.31 +biganswer.example8. 3600 IN A 10.10.6.32 +biganswer.example8. 3600 IN A 10.10.6.33 +biganswer.example8. 3600 IN A 10.10.6.34 +biganswer.example8. 3600 IN A 10.10.6.35 +biganswer.example8. 3600 IN A 10.10.6.36 +biganswer.example8. 3600 IN A 10.10.6.37 +biganswer.example8. 3600 IN A 10.10.6.38 +biganswer.example8. 3600 IN A 10.10.6.39 +biganswer.example8. 3600 IN A 10.10.6.40 +biganswer.example8. 3600 IN A 10.10.6.41 +biganswer.example8. 3600 IN A 10.10.6.42 +biganswer.example8. 3600 IN A 10.10.6.43 +biganswer.example8. 3600 IN A 10.10.6.44 +biganswer.example8. 3600 IN A 10.10.6.45 +biganswer.example8. 3600 IN A 10.10.6.46 +biganswer.example8. 3600 IN A 10.10.6.47 +biganswer.example8. 3600 IN A 10.10.6.48 +biganswer.example8. 3600 IN A 10.10.6.49 +biganswer.example8. 3600 IN A 10.10.6.50 +biganswer.example8. 3600 IN A 10.10.7.1 +biganswer.example8. 3600 IN A 10.10.7.2 +biganswer.example8. 3600 IN A 10.10.7.3 +biganswer.example8. 3600 IN A 10.10.7.4 +biganswer.example8. 3600 IN A 10.10.7.5 +biganswer.example8. 3600 IN A 10.10.7.6 +biganswer.example8. 3600 IN A 10.10.7.7 +biganswer.example8. 3600 IN A 10.10.7.8 +biganswer.example8. 3600 IN A 10.10.7.9 +biganswer.example8. 3600 IN A 10.10.7.10 +biganswer.example8. 3600 IN A 10.10.7.11 +biganswer.example8. 3600 IN A 10.10.7.12 +biganswer.example8. 3600 IN A 10.10.7.13 +biganswer.example8. 3600 IN A 10.10.7.14 +biganswer.example8. 3600 IN A 10.10.7.15 +biganswer.example8. 3600 IN A 10.10.7.16 +biganswer.example8. 3600 IN A 10.10.7.17 +biganswer.example8. 3600 IN A 10.10.7.18 +biganswer.example8. 3600 IN A 10.10.7.19 +biganswer.example8. 3600 IN A 10.10.7.20 +biganswer.example8. 3600 IN A 10.10.7.21 +biganswer.example8. 3600 IN A 10.10.7.22 +biganswer.example8. 3600 IN A 10.10.7.23 +biganswer.example8. 3600 IN A 10.10.7.24 +biganswer.example8. 3600 IN A 10.10.7.25 +biganswer.example8. 3600 IN A 10.10.7.26 +biganswer.example8. 3600 IN A 10.10.7.27 +biganswer.example8. 3600 IN A 10.10.7.28 +biganswer.example8. 3600 IN A 10.10.7.29 +biganswer.example8. 3600 IN A 10.10.7.30 +biganswer.example8. 3600 IN A 10.10.7.31 +biganswer.example8. 3600 IN A 10.10.7.32 +biganswer.example8. 3600 IN A 10.10.7.33 +biganswer.example8. 3600 IN A 10.10.7.34 +biganswer.example8. 3600 IN A 10.10.7.35 +biganswer.example8. 3600 IN A 10.10.7.36 +biganswer.example8. 3600 IN A 10.10.7.37 +biganswer.example8. 3600 IN A 10.10.7.38 +biganswer.example8. 3600 IN A 10.10.7.39 +biganswer.example8. 3600 IN A 10.10.7.40 +biganswer.example8. 3600 IN A 10.10.7.41 +biganswer.example8. 3600 IN A 10.10.7.42 +biganswer.example8. 3600 IN A 10.10.7.43 +biganswer.example8. 3600 IN A 10.10.7.44 +biganswer.example8. 3600 IN A 10.10.7.45 +biganswer.example8. 3600 IN A 10.10.7.46 +biganswer.example8. 3600 IN A 10.10.7.47 +biganswer.example8. 3600 IN A 10.10.7.48 +biganswer.example8. 3600 IN A 10.10.7.49 +biganswer.example8. 3600 IN A 10.10.7.50 +biganswer.example8. 3600 IN A 10.10.8.1 +biganswer.example8. 3600 IN A 10.10.8.2 +biganswer.example8. 3600 IN A 10.10.8.3 +biganswer.example8. 3600 IN A 10.10.8.4 +biganswer.example8. 3600 IN A 10.10.8.5 +biganswer.example8. 3600 IN A 10.10.8.6 +biganswer.example8. 3600 IN A 10.10.8.7 +biganswer.example8. 3600 IN A 10.10.8.8 +biganswer.example8. 3600 IN A 10.10.8.9 +biganswer.example8. 3600 IN A 10.10.8.10 +biganswer.example8. 3600 IN A 10.10.8.11 +biganswer.example8. 3600 IN A 10.10.8.12 +biganswer.example8. 3600 IN A 10.10.8.13 +biganswer.example8. 3600 IN A 10.10.8.14 +biganswer.example8. 3600 IN A 10.10.8.15 +biganswer.example8. 3600 IN A 10.10.8.16 +biganswer.example8. 3600 IN A 10.10.8.17 +biganswer.example8. 3600 IN A 10.10.8.18 +biganswer.example8. 3600 IN A 10.10.8.19 +biganswer.example8. 3600 IN A 10.10.8.20 +biganswer.example8. 3600 IN A 10.10.8.21 +biganswer.example8. 3600 IN A 10.10.8.22 +biganswer.example8. 3600 IN A 10.10.8.23 +biganswer.example8. 3600 IN A 10.10.8.24 +biganswer.example8. 3600 IN A 10.10.8.25 +biganswer.example8. 3600 IN A 10.10.8.26 +biganswer.example8. 3600 IN A 10.10.8.27 +biganswer.example8. 3600 IN A 10.10.8.28 +biganswer.example8. 3600 IN A 10.10.8.29 +biganswer.example8. 3600 IN A 10.10.8.30 +biganswer.example8. 3600 IN A 10.10.8.31 +biganswer.example8. 3600 IN A 10.10.8.32 +biganswer.example8. 3600 IN A 10.10.8.33 +biganswer.example8. 3600 IN A 10.10.8.34 +biganswer.example8. 3600 IN A 10.10.8.35 +biganswer.example8. 3600 IN A 10.10.8.36 +biganswer.example8. 3600 IN A 10.10.8.37 +biganswer.example8. 3600 IN A 10.10.8.38 +biganswer.example8. 3600 IN A 10.10.8.39 +biganswer.example8. 3600 IN A 10.10.8.40 +biganswer.example8. 3600 IN A 10.10.8.41 +biganswer.example8. 3600 IN A 10.10.8.42 +biganswer.example8. 3600 IN A 10.10.8.43 +biganswer.example8. 3600 IN A 10.10.8.44 +biganswer.example8. 3600 IN A 10.10.8.45 +biganswer.example8. 3600 IN A 10.10.8.46 +biganswer.example8. 3600 IN A 10.10.8.47 +biganswer.example8. 3600 IN A 10.10.8.48 +biganswer.example8. 3600 IN A 10.10.8.49 +biganswer.example8. 3600 IN A 10.10.8.50 +biganswer.example8. 3600 IN A 10.10.9.1 +biganswer.example8. 3600 IN A 10.10.9.2 +biganswer.example8. 3600 IN A 10.10.9.3 +biganswer.example8. 3600 IN A 10.10.9.4 +biganswer.example8. 3600 IN A 10.10.9.5 +biganswer.example8. 3600 IN A 10.10.9.6 +biganswer.example8. 3600 IN A 10.10.9.7 +biganswer.example8. 3600 IN A 10.10.9.8 +biganswer.example8. 3600 IN A 10.10.9.9 +biganswer.example8. 3600 IN A 10.10.9.10 +biganswer.example8. 3600 IN A 10.10.9.11 +biganswer.example8. 3600 IN A 10.10.9.12 +biganswer.example8. 3600 IN A 10.10.9.13 +biganswer.example8. 3600 IN A 10.10.9.14 +biganswer.example8. 3600 IN A 10.10.9.15 +biganswer.example8. 3600 IN A 10.10.9.16 +biganswer.example8. 3600 IN A 10.10.9.17 +biganswer.example8. 3600 IN A 10.10.9.18 +biganswer.example8. 3600 IN A 10.10.9.19 +biganswer.example8. 3600 IN A 10.10.9.20 +biganswer.example8. 3600 IN A 10.10.9.21 +biganswer.example8. 3600 IN A 10.10.9.22 +biganswer.example8. 3600 IN A 10.10.9.23 +biganswer.example8. 3600 IN A 10.10.9.24 +biganswer.example8. 3600 IN A 10.10.9.25 +biganswer.example8. 3600 IN A 10.10.9.26 +biganswer.example8. 3600 IN A 10.10.9.27 +biganswer.example8. 3600 IN A 10.10.9.28 +biganswer.example8. 3600 IN A 10.10.9.29 +biganswer.example8. 3600 IN A 10.10.9.30 +biganswer.example8. 3600 IN A 10.10.9.31 +biganswer.example8. 3600 IN A 10.10.9.32 +biganswer.example8. 3600 IN A 10.10.9.33 +biganswer.example8. 3600 IN A 10.10.9.34 +biganswer.example8. 3600 IN A 10.10.9.35 +biganswer.example8. 3600 IN A 10.10.9.36 +biganswer.example8. 3600 IN A 10.10.9.37 +biganswer.example8. 3600 IN A 10.10.9.38 +biganswer.example8. 3600 IN A 10.10.9.39 +biganswer.example8. 3600 IN A 10.10.9.40 +biganswer.example8. 3600 IN A 10.10.9.41 +biganswer.example8. 3600 IN A 10.10.9.42 +biganswer.example8. 3600 IN A 10.10.9.43 +biganswer.example8. 3600 IN A 10.10.9.44 +biganswer.example8. 3600 IN A 10.10.9.45 +biganswer.example8. 3600 IN A 10.10.9.46 +biganswer.example8. 3600 IN A 10.10.9.47 +biganswer.example8. 3600 IN A 10.10.9.48 +biganswer.example8. 3600 IN A 10.10.9.49 +biganswer.example8. 3600 IN A 10.10.9.50 +biganswer.example8. 3600 IN A 10.10.10.1 +biganswer.example8. 3600 IN A 10.10.10.2 +biganswer.example8. 3600 IN A 10.10.10.3 +biganswer.example8. 3600 IN A 10.10.10.4 +biganswer.example8. 3600 IN A 10.10.10.5 +biganswer.example8. 3600 IN A 10.10.10.6 +biganswer.example8. 3600 IN A 10.10.10.7 +biganswer.example8. 3600 IN A 10.10.10.8 +biganswer.example8. 3600 IN A 10.10.10.9 +biganswer.example8. 3600 IN A 10.10.10.10 +biganswer.example8. 3600 IN A 10.10.10.11 +biganswer.example8. 3600 IN A 10.10.10.12 +biganswer.example8. 3600 IN A 10.10.10.13 +biganswer.example8. 3600 IN A 10.10.10.14 +biganswer.example8. 3600 IN A 10.10.10.15 +biganswer.example8. 3600 IN A 10.10.10.16 +biganswer.example8. 3600 IN A 10.10.10.17 +biganswer.example8. 3600 IN A 10.10.10.18 +biganswer.example8. 3600 IN A 10.10.10.19 +biganswer.example8. 3600 IN A 10.10.10.20 +biganswer.example8. 3600 IN A 10.10.10.21 +biganswer.example8. 3600 IN A 10.10.10.22 +biganswer.example8. 3600 IN A 10.10.10.23 +biganswer.example8. 3600 IN A 10.10.10.24 +biganswer.example8. 3600 IN A 10.10.10.25 +biganswer.example8. 3600 IN A 10.10.10.26 +biganswer.example8. 3600 IN A 10.10.10.27 +biganswer.example8. 3600 IN A 10.10.10.28 +biganswer.example8. 3600 IN A 10.10.10.29 +biganswer.example8. 3600 IN A 10.10.10.30 +biganswer.example8. 3600 IN A 10.10.10.31 +biganswer.example8. 3600 IN A 10.10.10.32 +biganswer.example8. 3600 IN A 10.10.10.33 +biganswer.example8. 3600 IN A 10.10.10.34 +biganswer.example8. 3600 IN A 10.10.10.35 +biganswer.example8. 3600 IN A 10.10.10.36 +biganswer.example8. 3600 IN A 10.10.10.37 +biganswer.example8. 3600 IN A 10.10.10.38 +biganswer.example8. 3600 IN A 10.10.10.39 +biganswer.example8. 3600 IN A 10.10.10.40 +biganswer.example8. 3600 IN A 10.10.10.41 +biganswer.example8. 3600 IN A 10.10.10.42 +biganswer.example8. 3600 IN A 10.10.10.43 +biganswer.example8. 3600 IN A 10.10.10.44 +biganswer.example8. 3600 IN A 10.10.10.45 +biganswer.example8. 3600 IN A 10.10.10.46 +biganswer.example8. 3600 IN A 10.10.10.47 +biganswer.example8. 3600 IN A 10.10.10.48 +biganswer.example8. 3600 IN A 10.10.10.49 +biganswer.example8. 3600 IN A 10.10.10.50 +biganswer.example8. 3600 IN A 10.10.11.1 +biganswer.example8. 3600 IN A 10.10.11.2 +biganswer.example8. 3600 IN A 10.10.11.3 +biganswer.example8. 3600 IN A 10.10.11.4 +biganswer.example8. 3600 IN A 10.10.11.5 +biganswer.example8. 3600 IN A 10.10.11.6 +biganswer.example8. 3600 IN A 10.10.11.7 +biganswer.example8. 3600 IN A 10.10.11.8 +biganswer.example8. 3600 IN A 10.10.11.9 +biganswer.example8. 3600 IN A 10.10.11.10 +biganswer.example8. 3600 IN A 10.10.11.11 +biganswer.example8. 3600 IN A 10.10.11.12 +biganswer.example8. 3600 IN A 10.10.11.13 +biganswer.example8. 3600 IN A 10.10.11.14 +biganswer.example8. 3600 IN A 10.10.11.15 +biganswer.example8. 3600 IN A 10.10.11.16 +biganswer.example8. 3600 IN A 10.10.11.17 +biganswer.example8. 3600 IN A 10.10.11.18 +biganswer.example8. 3600 IN A 10.10.11.19 +biganswer.example8. 3600 IN A 10.10.11.20 +biganswer.example8. 3600 IN A 10.10.11.21 +biganswer.example8. 3600 IN A 10.10.11.22 +biganswer.example8. 3600 IN A 10.10.11.23 +biganswer.example8. 3600 IN A 10.10.11.24 +biganswer.example8. 3600 IN A 10.10.11.25 +biganswer.example8. 3600 IN A 10.10.11.26 +biganswer.example8. 3600 IN A 10.10.11.27 +biganswer.example8. 3600 IN A 10.10.11.28 +biganswer.example8. 3600 IN A 10.10.11.29 +biganswer.example8. 3600 IN A 10.10.11.30 +biganswer.example8. 3600 IN A 10.10.11.31 +biganswer.example8. 3600 IN A 10.10.11.32 +biganswer.example8. 3600 IN A 10.10.11.33 +biganswer.example8. 3600 IN A 10.10.11.34 +biganswer.example8. 3600 IN A 10.10.11.35 +biganswer.example8. 3600 IN A 10.10.11.36 +biganswer.example8. 3600 IN A 10.10.11.37 +biganswer.example8. 3600 IN A 10.10.11.38 +biganswer.example8. 3600 IN A 10.10.11.39 +biganswer.example8. 3600 IN A 10.10.11.40 +biganswer.example8. 3600 IN A 10.10.11.41 +biganswer.example8. 3600 IN A 10.10.11.42 +biganswer.example8. 3600 IN A 10.10.11.43 +biganswer.example8. 3600 IN A 10.10.11.44 +biganswer.example8. 3600 IN A 10.10.11.45 +biganswer.example8. 3600 IN A 10.10.11.46 +biganswer.example8. 3600 IN A 10.10.11.47 +biganswer.example8. 3600 IN A 10.10.11.48 +biganswer.example8. 3600 IN A 10.10.11.49 +biganswer.example8. 3600 IN A 10.10.11.50 +biganswer.example8. 3600 IN A 10.10.12.1 +biganswer.example8. 3600 IN A 10.10.12.2 +biganswer.example8. 3600 IN A 10.10.12.3 +biganswer.example8. 3600 IN A 10.10.12.4 +biganswer.example8. 3600 IN A 10.10.12.5 +biganswer.example8. 3600 IN A 10.10.12.6 +biganswer.example8. 3600 IN A 10.10.12.7 +biganswer.example8. 3600 IN A 10.10.12.8 +biganswer.example8. 3600 IN A 10.10.12.9 +biganswer.example8. 3600 IN A 10.10.12.10 +biganswer.example8. 3600 IN A 10.10.12.11 +biganswer.example8. 3600 IN A 10.10.12.12 +biganswer.example8. 3600 IN A 10.10.12.13 +biganswer.example8. 3600 IN A 10.10.12.14 +biganswer.example8. 3600 IN A 10.10.12.15 +biganswer.example8. 3600 IN A 10.10.12.16 +biganswer.example8. 3600 IN A 10.10.12.17 +biganswer.example8. 3600 IN A 10.10.12.18 +biganswer.example8. 3600 IN A 10.10.12.19 +biganswer.example8. 3600 IN A 10.10.12.20 +biganswer.example8. 3600 IN A 10.10.12.21 +biganswer.example8. 3600 IN A 10.10.12.22 +biganswer.example8. 3600 IN A 10.10.12.23 +biganswer.example8. 3600 IN A 10.10.12.24 +biganswer.example8. 3600 IN A 10.10.12.25 +biganswer.example8. 3600 IN A 10.10.12.26 +biganswer.example8. 3600 IN A 10.10.12.27 +biganswer.example8. 3600 IN A 10.10.12.28 +biganswer.example8. 3600 IN A 10.10.12.29 +biganswer.example8. 3600 IN A 10.10.12.30 +biganswer.example8. 3600 IN A 10.10.12.31 +biganswer.example8. 3600 IN A 10.10.12.32 +biganswer.example8. 3600 IN A 10.10.12.33 +biganswer.example8. 3600 IN A 10.10.12.34 +biganswer.example8. 3600 IN A 10.10.12.35 +biganswer.example8. 3600 IN A 10.10.12.36 +biganswer.example8. 3600 IN A 10.10.12.37 +biganswer.example8. 3600 IN A 10.10.12.38 +biganswer.example8. 3600 IN A 10.10.12.39 +biganswer.example8. 3600 IN A 10.10.12.40 +biganswer.example8. 3600 IN A 10.10.12.41 +biganswer.example8. 3600 IN A 10.10.12.42 +biganswer.example8. 3600 IN A 10.10.12.43 +biganswer.example8. 3600 IN A 10.10.12.44 +biganswer.example8. 3600 IN A 10.10.12.45 +biganswer.example8. 3600 IN A 10.10.12.46 +biganswer.example8. 3600 IN A 10.10.12.47 +biganswer.example8. 3600 IN A 10.10.12.48 +biganswer.example8. 3600 IN A 10.10.12.49 +biganswer.example8. 3600 IN A 10.10.12.50 +biganswer.example8. 3600 IN A 10.10.13.1 +biganswer.example8. 3600 IN A 10.10.13.2 +biganswer.example8. 3600 IN A 10.10.13.3 +biganswer.example8. 3600 IN A 10.10.13.4 +biganswer.example8. 3600 IN A 10.10.13.5 +biganswer.example8. 3600 IN A 10.10.13.6 +biganswer.example8. 3600 IN A 10.10.13.7 +biganswer.example8. 3600 IN A 10.10.13.8 +biganswer.example8. 3600 IN A 10.10.13.9 +biganswer.example8. 3600 IN A 10.10.13.10 +biganswer.example8. 3600 IN A 10.10.13.11 +biganswer.example8. 3600 IN A 10.10.13.12 +biganswer.example8. 3600 IN A 10.10.13.13 +biganswer.example8. 3600 IN A 10.10.13.14 +biganswer.example8. 3600 IN A 10.10.13.15 +biganswer.example8. 3600 IN A 10.10.13.16 +biganswer.example8. 3600 IN A 10.10.13.17 +biganswer.example8. 3600 IN A 10.10.13.18 +biganswer.example8. 3600 IN A 10.10.13.19 +biganswer.example8. 3600 IN A 10.10.13.20 +biganswer.example8. 3600 IN A 10.10.13.21 +biganswer.example8. 3600 IN A 10.10.13.22 +biganswer.example8. 3600 IN A 10.10.13.23 +biganswer.example8. 3600 IN A 10.10.13.24 +biganswer.example8. 3600 IN A 10.10.13.25 +biganswer.example8. 3600 IN A 10.10.13.26 +biganswer.example8. 3600 IN A 10.10.13.27 +biganswer.example8. 3600 IN A 10.10.13.28 +biganswer.example8. 3600 IN A 10.10.13.29 +biganswer.example8. 3600 IN A 10.10.13.30 +biganswer.example8. 3600 IN A 10.10.13.31 +biganswer.example8. 3600 IN A 10.10.13.32 +biganswer.example8. 3600 IN A 10.10.13.33 +biganswer.example8. 3600 IN A 10.10.13.34 +biganswer.example8. 3600 IN A 10.10.13.35 +biganswer.example8. 3600 IN A 10.10.13.36 +biganswer.example8. 3600 IN A 10.10.13.37 +biganswer.example8. 3600 IN A 10.10.13.38 +biganswer.example8. 3600 IN A 10.10.13.39 +biganswer.example8. 3600 IN A 10.10.13.40 +biganswer.example8. 3600 IN A 10.10.13.41 +biganswer.example8. 3600 IN A 10.10.13.42 +biganswer.example8. 3600 IN A 10.10.13.43 +biganswer.example8. 3600 IN A 10.10.13.44 +biganswer.example8. 3600 IN A 10.10.13.45 +biganswer.example8. 3600 IN A 10.10.13.46 +biganswer.example8. 3600 IN A 10.10.13.47 +biganswer.example8. 3600 IN A 10.10.13.48 +biganswer.example8. 3600 IN A 10.10.13.49 +biganswer.example8. 3600 IN A 10.10.13.50 +biganswer.example8. 3600 IN A 10.10.14.1 +biganswer.example8. 3600 IN A 10.10.14.2 +biganswer.example8. 3600 IN A 10.10.14.3 +biganswer.example8. 3600 IN A 10.10.14.4 +biganswer.example8. 3600 IN A 10.10.14.5 +biganswer.example8. 3600 IN A 10.10.14.6 +biganswer.example8. 3600 IN A 10.10.14.7 +biganswer.example8. 3600 IN A 10.10.14.8 +biganswer.example8. 3600 IN A 10.10.14.9 +biganswer.example8. 3600 IN A 10.10.14.10 +biganswer.example8. 3600 IN A 10.10.14.11 +biganswer.example8. 3600 IN A 10.10.14.12 +biganswer.example8. 3600 IN A 10.10.14.13 +biganswer.example8. 3600 IN A 10.10.14.14 +biganswer.example8. 3600 IN A 10.10.14.15 +biganswer.example8. 3600 IN A 10.10.14.16 +biganswer.example8. 3600 IN A 10.10.14.17 +biganswer.example8. 3600 IN A 10.10.14.18 +biganswer.example8. 3600 IN A 10.10.14.19 +biganswer.example8. 3600 IN A 10.10.14.20 +biganswer.example8. 3600 IN A 10.10.14.21 +biganswer.example8. 3600 IN A 10.10.14.22 +biganswer.example8. 3600 IN A 10.10.14.23 +biganswer.example8. 3600 IN A 10.10.14.24 +biganswer.example8. 3600 IN A 10.10.14.25 +biganswer.example8. 3600 IN A 10.10.14.26 +biganswer.example8. 3600 IN A 10.10.14.27 +biganswer.example8. 3600 IN A 10.10.14.28 +biganswer.example8. 3600 IN A 10.10.14.29 +biganswer.example8. 3600 IN A 10.10.14.30 +biganswer.example8. 3600 IN A 10.10.14.31 +biganswer.example8. 3600 IN A 10.10.14.32 +biganswer.example8. 3600 IN A 10.10.14.33 +biganswer.example8. 3600 IN A 10.10.14.34 +biganswer.example8. 3600 IN A 10.10.14.35 +biganswer.example8. 3600 IN A 10.10.14.36 +biganswer.example8. 3600 IN A 10.10.14.37 +biganswer.example8. 3600 IN A 10.10.14.38 +biganswer.example8. 3600 IN A 10.10.14.39 +biganswer.example8. 3600 IN A 10.10.14.40 +biganswer.example8. 3600 IN A 10.10.14.41 +biganswer.example8. 3600 IN A 10.10.14.42 +biganswer.example8. 3600 IN A 10.10.14.43 +biganswer.example8. 3600 IN A 10.10.14.44 +biganswer.example8. 3600 IN A 10.10.14.45 +biganswer.example8. 3600 IN A 10.10.14.46 +biganswer.example8. 3600 IN A 10.10.14.47 +biganswer.example8. 3600 IN A 10.10.14.48 +biganswer.example8. 3600 IN A 10.10.14.49 +biganswer.example8. 3600 IN A 10.10.14.50 +biganswer.example8. 3600 IN A 10.10.15.1 +biganswer.example8. 3600 IN A 10.10.15.2 +biganswer.example8. 3600 IN A 10.10.15.3 +biganswer.example8. 3600 IN A 10.10.15.4 +biganswer.example8. 3600 IN A 10.10.15.5 +biganswer.example8. 3600 IN A 10.10.15.6 +biganswer.example8. 3600 IN A 10.10.15.7 +biganswer.example8. 3600 IN A 10.10.15.8 +biganswer.example8. 3600 IN A 10.10.15.9 +biganswer.example8. 3600 IN A 10.10.15.10 +biganswer.example8. 3600 IN A 10.10.15.11 +biganswer.example8. 3600 IN A 10.10.15.12 +biganswer.example8. 3600 IN A 10.10.15.13 +biganswer.example8. 3600 IN A 10.10.15.14 +biganswer.example8. 3600 IN A 10.10.15.15 +biganswer.example8. 3600 IN A 10.10.15.16 +biganswer.example8. 3600 IN A 10.10.15.17 +biganswer.example8. 3600 IN A 10.10.15.18 +biganswer.example8. 3600 IN A 10.10.15.19 +biganswer.example8. 3600 IN A 10.10.15.20 +biganswer.example8. 3600 IN A 10.10.15.21 +biganswer.example8. 3600 IN A 10.10.15.22 +biganswer.example8. 3600 IN A 10.10.15.23 +biganswer.example8. 3600 IN A 10.10.15.24 +biganswer.example8. 3600 IN A 10.10.15.25 +biganswer.example8. 3600 IN A 10.10.15.26 +biganswer.example8. 3600 IN A 10.10.15.27 +biganswer.example8. 3600 IN A 10.10.15.28 +biganswer.example8. 3600 IN A 10.10.15.29 +biganswer.example8. 3600 IN A 10.10.15.30 +biganswer.example8. 3600 IN A 10.10.15.31 +biganswer.example8. 3600 IN A 10.10.15.32 +biganswer.example8. 3600 IN A 10.10.15.33 +biganswer.example8. 3600 IN A 10.10.15.34 +biganswer.example8. 3600 IN A 10.10.15.35 +biganswer.example8. 3600 IN A 10.10.15.36 +biganswer.example8. 3600 IN A 10.10.15.37 +biganswer.example8. 3600 IN A 10.10.15.38 +biganswer.example8. 3600 IN A 10.10.15.39 +biganswer.example8. 3600 IN A 10.10.15.40 +biganswer.example8. 3600 IN A 10.10.15.41 +biganswer.example8. 3600 IN A 10.10.15.42 +biganswer.example8. 3600 IN A 10.10.15.43 +biganswer.example8. 3600 IN A 10.10.15.44 +biganswer.example8. 3600 IN A 10.10.15.45 +biganswer.example8. 3600 IN A 10.10.15.46 +biganswer.example8. 3600 IN A 10.10.15.47 +biganswer.example8. 3600 IN A 10.10.15.48 +biganswer.example8. 3600 IN A 10.10.15.49 +biganswer.example8. 3600 IN A 10.10.15.50 +biganswer.example8. 3600 IN A 10.10.16.1 +biganswer.example8. 3600 IN A 10.10.16.2 +biganswer.example8. 3600 IN A 10.10.16.3 +biganswer.example8. 3600 IN A 10.10.16.4 +biganswer.example8. 3600 IN A 10.10.16.5 +biganswer.example8. 3600 IN A 10.10.16.6 +biganswer.example8. 3600 IN A 10.10.16.7 +biganswer.example8. 3600 IN A 10.10.16.8 +biganswer.example8. 3600 IN A 10.10.16.9 +biganswer.example8. 3600 IN A 10.10.16.10 +biganswer.example8. 3600 IN A 10.10.16.11 +biganswer.example8. 3600 IN A 10.10.16.12 +biganswer.example8. 3600 IN A 10.10.16.13 +biganswer.example8. 3600 IN A 10.10.16.14 +biganswer.example8. 3600 IN A 10.10.16.15 +biganswer.example8. 3600 IN A 10.10.16.16 +biganswer.example8. 3600 IN A 10.10.16.17 +biganswer.example8. 3600 IN A 10.10.16.18 +biganswer.example8. 3600 IN A 10.10.16.19 +biganswer.example8. 3600 IN A 10.10.16.20 +biganswer.example8. 3600 IN A 10.10.16.21 +biganswer.example8. 3600 IN A 10.10.16.22 +biganswer.example8. 3600 IN A 10.10.16.23 +biganswer.example8. 3600 IN A 10.10.16.24 +biganswer.example8. 3600 IN A 10.10.16.25 +biganswer.example8. 3600 IN A 10.10.16.26 +biganswer.example8. 3600 IN A 10.10.16.27 +biganswer.example8. 3600 IN A 10.10.16.28 +biganswer.example8. 3600 IN A 10.10.16.29 +biganswer.example8. 3600 IN A 10.10.16.30 +biganswer.example8. 3600 IN A 10.10.16.31 +biganswer.example8. 3600 IN A 10.10.16.32 +biganswer.example8. 3600 IN A 10.10.16.33 +biganswer.example8. 3600 IN A 10.10.16.34 +biganswer.example8. 3600 IN A 10.10.16.35 +biganswer.example8. 3600 IN A 10.10.16.36 +biganswer.example8. 3600 IN A 10.10.16.37 +biganswer.example8. 3600 IN A 10.10.16.38 +biganswer.example8. 3600 IN A 10.10.16.39 +biganswer.example8. 3600 IN A 10.10.16.40 +biganswer.example8. 3600 IN A 10.10.16.41 +biganswer.example8. 3600 IN A 10.10.16.42 +biganswer.example8. 3600 IN A 10.10.16.43 +biganswer.example8. 3600 IN A 10.10.16.44 +biganswer.example8. 3600 IN A 10.10.16.45 +biganswer.example8. 3600 IN A 10.10.16.46 +biganswer.example8. 3600 IN A 10.10.16.47 +biganswer.example8. 3600 IN A 10.10.16.48 +biganswer.example8. 3600 IN A 10.10.16.49 +biganswer.example8. 3600 IN A 10.10.16.50 +biganswer.example8. 3600 IN A 10.10.17.1 +biganswer.example8. 3600 IN A 10.10.17.2 +biganswer.example8. 3600 IN A 10.10.17.3 +biganswer.example8. 3600 IN A 10.10.17.4 +biganswer.example8. 3600 IN A 10.10.17.5 +biganswer.example8. 3600 IN A 10.10.17.6 +biganswer.example8. 3600 IN A 10.10.17.7 +biganswer.example8. 3600 IN A 10.10.17.8 +biganswer.example8. 3600 IN A 10.10.17.9 +biganswer.example8. 3600 IN A 10.10.17.10 +biganswer.example8. 3600 IN A 10.10.17.11 +biganswer.example8. 3600 IN A 10.10.17.12 +biganswer.example8. 3600 IN A 10.10.17.13 +biganswer.example8. 3600 IN A 10.10.17.14 +biganswer.example8. 3600 IN A 10.10.17.15 +biganswer.example8. 3600 IN A 10.10.17.16 +biganswer.example8. 3600 IN A 10.10.17.17 +biganswer.example8. 3600 IN A 10.10.17.18 +biganswer.example8. 3600 IN A 10.10.17.19 +biganswer.example8. 3600 IN A 10.10.17.20 +biganswer.example8. 3600 IN A 10.10.17.21 +biganswer.example8. 3600 IN A 10.10.17.22 +biganswer.example8. 3600 IN A 10.10.17.23 +biganswer.example8. 3600 IN A 10.10.17.24 +biganswer.example8. 3600 IN A 10.10.17.25 +biganswer.example8. 3600 IN A 10.10.17.26 +biganswer.example8. 3600 IN A 10.10.17.27 +biganswer.example8. 3600 IN A 10.10.17.28 +biganswer.example8. 3600 IN A 10.10.17.29 +biganswer.example8. 3600 IN A 10.10.17.30 +biganswer.example8. 3600 IN A 10.10.17.31 +biganswer.example8. 3600 IN A 10.10.17.32 +biganswer.example8. 3600 IN A 10.10.17.33 +biganswer.example8. 3600 IN A 10.10.17.34 +biganswer.example8. 3600 IN A 10.10.17.35 +biganswer.example8. 3600 IN A 10.10.17.36 +biganswer.example8. 3600 IN A 10.10.17.37 +biganswer.example8. 3600 IN A 10.10.17.38 +biganswer.example8. 3600 IN A 10.10.17.39 +biganswer.example8. 3600 IN A 10.10.17.40 +biganswer.example8. 3600 IN A 10.10.17.41 +biganswer.example8. 3600 IN A 10.10.17.42 +biganswer.example8. 3600 IN A 10.10.17.43 +biganswer.example8. 3600 IN A 10.10.17.44 +biganswer.example8. 3600 IN A 10.10.17.45 +biganswer.example8. 3600 IN A 10.10.17.46 +biganswer.example8. 3600 IN A 10.10.17.47 +biganswer.example8. 3600 IN A 10.10.17.48 +biganswer.example8. 3600 IN A 10.10.17.49 +biganswer.example8. 3600 IN A 10.10.17.50 +biganswer.example8. 3600 IN A 10.10.18.1 +biganswer.example8. 3600 IN A 10.10.18.2 +biganswer.example8. 3600 IN A 10.10.18.3 +biganswer.example8. 3600 IN A 10.10.18.4 +biganswer.example8. 3600 IN A 10.10.18.5 +biganswer.example8. 3600 IN A 10.10.18.6 +biganswer.example8. 3600 IN A 10.10.18.7 +biganswer.example8. 3600 IN A 10.10.18.8 +biganswer.example8. 3600 IN A 10.10.18.9 +biganswer.example8. 3600 IN A 10.10.18.10 +biganswer.example8. 3600 IN A 10.10.18.11 +biganswer.example8. 3600 IN A 10.10.18.12 +biganswer.example8. 3600 IN A 10.10.18.13 +biganswer.example8. 3600 IN A 10.10.18.14 +biganswer.example8. 3600 IN A 10.10.18.15 +biganswer.example8. 3600 IN A 10.10.18.16 +biganswer.example8. 3600 IN A 10.10.18.17 +biganswer.example8. 3600 IN A 10.10.18.18 +biganswer.example8. 3600 IN A 10.10.18.19 +biganswer.example8. 3600 IN A 10.10.18.20 +biganswer.example8. 3600 IN A 10.10.18.21 +biganswer.example8. 3600 IN A 10.10.18.22 +biganswer.example8. 3600 IN A 10.10.18.23 +biganswer.example8. 3600 IN A 10.10.18.24 +biganswer.example8. 3600 IN A 10.10.18.25 +biganswer.example8. 3600 IN A 10.10.18.26 +biganswer.example8. 3600 IN A 10.10.18.27 +biganswer.example8. 3600 IN A 10.10.18.28 +biganswer.example8. 3600 IN A 10.10.18.29 +biganswer.example8. 3600 IN A 10.10.18.30 +biganswer.example8. 3600 IN A 10.10.18.31 +biganswer.example8. 3600 IN A 10.10.18.32 +biganswer.example8. 3600 IN A 10.10.18.33 +biganswer.example8. 3600 IN A 10.10.18.34 +biganswer.example8. 3600 IN A 10.10.18.35 +biganswer.example8. 3600 IN A 10.10.18.36 +biganswer.example8. 3600 IN A 10.10.18.37 +biganswer.example8. 3600 IN A 10.10.18.38 +biganswer.example8. 3600 IN A 10.10.18.39 +biganswer.example8. 3600 IN A 10.10.18.40 +biganswer.example8. 3600 IN A 10.10.18.41 +biganswer.example8. 3600 IN A 10.10.18.42 +biganswer.example8. 3600 IN A 10.10.18.43 +biganswer.example8. 3600 IN A 10.10.18.44 +biganswer.example8. 3600 IN A 10.10.18.45 +biganswer.example8. 3600 IN A 10.10.18.46 +biganswer.example8. 3600 IN A 10.10.18.47 +biganswer.example8. 3600 IN A 10.10.18.48 +biganswer.example8. 3600 IN A 10.10.18.49 +biganswer.example8. 3600 IN A 10.10.18.50 +biganswer.example8. 3600 IN A 10.10.19.1 +biganswer.example8. 3600 IN A 10.10.19.2 +biganswer.example8. 3600 IN A 10.10.19.3 +biganswer.example8. 3600 IN A 10.10.19.4 +biganswer.example8. 3600 IN A 10.10.19.5 +biganswer.example8. 3600 IN A 10.10.19.6 +biganswer.example8. 3600 IN A 10.10.19.7 +biganswer.example8. 3600 IN A 10.10.19.8 +biganswer.example8. 3600 IN A 10.10.19.9 +biganswer.example8. 3600 IN A 10.10.19.10 +biganswer.example8. 3600 IN A 10.10.19.11 +biganswer.example8. 3600 IN A 10.10.19.12 +biganswer.example8. 3600 IN A 10.10.19.13 +biganswer.example8. 3600 IN A 10.10.19.14 +biganswer.example8. 3600 IN A 10.10.19.15 +biganswer.example8. 3600 IN A 10.10.19.16 +biganswer.example8. 3600 IN A 10.10.19.17 +biganswer.example8. 3600 IN A 10.10.19.18 +biganswer.example8. 3600 IN A 10.10.19.19 +biganswer.example8. 3600 IN A 10.10.19.20 +biganswer.example8. 3600 IN A 10.10.19.21 +biganswer.example8. 3600 IN A 10.10.19.22 +biganswer.example8. 3600 IN A 10.10.19.23 +biganswer.example8. 3600 IN A 10.10.19.24 +biganswer.example8. 3600 IN A 10.10.19.25 +biganswer.example8. 3600 IN A 10.10.19.26 +biganswer.example8. 3600 IN A 10.10.19.27 +biganswer.example8. 3600 IN A 10.10.19.28 +biganswer.example8. 3600 IN A 10.10.19.29 +biganswer.example8. 3600 IN A 10.10.19.30 +biganswer.example8. 3600 IN A 10.10.19.31 +biganswer.example8. 3600 IN A 10.10.19.32 +biganswer.example8. 3600 IN A 10.10.19.33 +biganswer.example8. 3600 IN A 10.10.19.34 +biganswer.example8. 3600 IN A 10.10.19.35 +biganswer.example8. 3600 IN A 10.10.19.36 +biganswer.example8. 3600 IN A 10.10.19.37 +biganswer.example8. 3600 IN A 10.10.19.38 +biganswer.example8. 3600 IN A 10.10.19.39 +biganswer.example8. 3600 IN A 10.10.19.40 +biganswer.example8. 3600 IN A 10.10.19.41 +biganswer.example8. 3600 IN A 10.10.19.42 +biganswer.example8. 3600 IN A 10.10.19.43 +biganswer.example8. 3600 IN A 10.10.19.44 +biganswer.example8. 3600 IN A 10.10.19.45 +biganswer.example8. 3600 IN A 10.10.19.46 +biganswer.example8. 3600 IN A 10.10.19.47 +biganswer.example8. 3600 IN A 10.10.19.48 +biganswer.example8. 3600 IN A 10.10.19.49 +biganswer.example8. 3600 IN A 10.10.19.50 +biganswer.example8. 3600 IN A 10.10.20.1 +biganswer.example8. 3600 IN A 10.10.20.2 +biganswer.example8. 3600 IN A 10.10.20.3 +biganswer.example8. 3600 IN A 10.10.20.4 +biganswer.example8. 3600 IN A 10.10.20.5 +biganswer.example8. 3600 IN A 10.10.20.6 +biganswer.example8. 3600 IN A 10.10.20.7 +biganswer.example8. 3600 IN A 10.10.20.8 +biganswer.example8. 3600 IN A 10.10.20.9 +biganswer.example8. 3600 IN A 10.10.20.10 +biganswer.example8. 3600 IN A 10.10.20.11 +biganswer.example8. 3600 IN A 10.10.20.12 +biganswer.example8. 3600 IN A 10.10.20.13 +biganswer.example8. 3600 IN A 10.10.20.14 +biganswer.example8. 3600 IN A 10.10.20.15 +biganswer.example8. 3600 IN A 10.10.20.16 +biganswer.example8. 3600 IN A 10.10.20.17 +biganswer.example8. 3600 IN A 10.10.20.18 +biganswer.example8. 3600 IN A 10.10.20.19 +biganswer.example8. 3600 IN A 10.10.20.20 +biganswer.example8. 3600 IN A 10.10.20.21 +biganswer.example8. 3600 IN A 10.10.20.22 +biganswer.example8. 3600 IN A 10.10.20.23 +biganswer.example8. 3600 IN A 10.10.20.24 +biganswer.example8. 3600 IN A 10.10.20.25 +biganswer.example8. 3600 IN A 10.10.20.26 +biganswer.example8. 3600 IN A 10.10.20.27 +biganswer.example8. 3600 IN A 10.10.20.28 +biganswer.example8. 3600 IN A 10.10.20.29 +biganswer.example8. 3600 IN A 10.10.20.30 +biganswer.example8. 3600 IN A 10.10.20.31 +biganswer.example8. 3600 IN A 10.10.20.32 +biganswer.example8. 3600 IN A 10.10.20.33 +biganswer.example8. 3600 IN A 10.10.20.34 +biganswer.example8. 3600 IN A 10.10.20.35 +biganswer.example8. 3600 IN A 10.10.20.36 +biganswer.example8. 3600 IN A 10.10.20.37 +biganswer.example8. 3600 IN A 10.10.20.38 +biganswer.example8. 3600 IN A 10.10.20.39 +biganswer.example8. 3600 IN A 10.10.20.40 +biganswer.example8. 3600 IN A 10.10.20.41 +biganswer.example8. 3600 IN A 10.10.20.42 +biganswer.example8. 3600 IN A 10.10.20.43 +biganswer.example8. 3600 IN A 10.10.20.44 +biganswer.example8. 3600 IN A 10.10.20.45 +biganswer.example8. 3600 IN A 10.10.20.46 +biganswer.example8. 3600 IN A 10.10.20.47 +biganswer.example8. 3600 IN A 10.10.20.48 +biganswer.example8. 3600 IN A 10.10.20.49 +biganswer.example8. 3600 IN A 10.10.20.50 +biganswer.example8. 3600 IN A 10.10.21.1 +biganswer.example8. 3600 IN A 10.10.21.2 +biganswer.example8. 3600 IN A 10.10.21.3 +biganswer.example8. 3600 IN A 10.10.21.4 +biganswer.example8. 3600 IN A 10.10.21.5 +biganswer.example8. 3600 IN A 10.10.21.6 +biganswer.example8. 3600 IN A 10.10.21.7 +biganswer.example8. 3600 IN A 10.10.21.8 +biganswer.example8. 3600 IN A 10.10.21.9 +biganswer.example8. 3600 IN A 10.10.21.10 +biganswer.example8. 3600 IN A 10.10.21.11 +biganswer.example8. 3600 IN A 10.10.21.12 +biganswer.example8. 3600 IN A 10.10.21.13 +biganswer.example8. 3600 IN A 10.10.21.14 +biganswer.example8. 3600 IN A 10.10.21.15 +biganswer.example8. 3600 IN A 10.10.21.16 +biganswer.example8. 3600 IN A 10.10.21.17 +biganswer.example8. 3600 IN A 10.10.21.18 +biganswer.example8. 3600 IN A 10.10.21.19 +biganswer.example8. 3600 IN A 10.10.21.20 +biganswer.example8. 3600 IN A 10.10.21.21 +biganswer.example8. 3600 IN A 10.10.21.22 +biganswer.example8. 3600 IN A 10.10.21.23 +biganswer.example8. 3600 IN A 10.10.21.24 +biganswer.example8. 3600 IN A 10.10.21.25 +biganswer.example8. 3600 IN A 10.10.21.26 +biganswer.example8. 3600 IN A 10.10.21.27 +biganswer.example8. 3600 IN A 10.10.21.28 +biganswer.example8. 3600 IN A 10.10.21.29 +biganswer.example8. 3600 IN A 10.10.21.30 +biganswer.example8. 3600 IN A 10.10.21.31 +biganswer.example8. 3600 IN A 10.10.21.32 +biganswer.example8. 3600 IN A 10.10.21.33 +biganswer.example8. 3600 IN A 10.10.21.34 +biganswer.example8. 3600 IN A 10.10.21.35 +biganswer.example8. 3600 IN A 10.10.21.36 +biganswer.example8. 3600 IN A 10.10.21.37 +biganswer.example8. 3600 IN A 10.10.21.38 +biganswer.example8. 3600 IN A 10.10.21.39 +biganswer.example8. 3600 IN A 10.10.21.40 +biganswer.example8. 3600 IN A 10.10.21.41 +biganswer.example8. 3600 IN A 10.10.21.42 +biganswer.example8. 3600 IN A 10.10.21.43 +biganswer.example8. 3600 IN A 10.10.21.44 +biganswer.example8. 3600 IN A 10.10.21.45 +biganswer.example8. 3600 IN A 10.10.21.46 +biganswer.example8. 3600 IN A 10.10.21.47 +biganswer.example8. 3600 IN A 10.10.21.48 +biganswer.example8. 3600 IN A 10.10.21.49 +biganswer.example8. 3600 IN A 10.10.21.50 +biganswer.example8. 3600 IN A 10.10.22.1 +biganswer.example8. 3600 IN A 10.10.22.2 +biganswer.example8. 3600 IN A 10.10.22.3 +biganswer.example8. 3600 IN A 10.10.22.4 +biganswer.example8. 3600 IN A 10.10.22.5 +biganswer.example8. 3600 IN A 10.10.22.6 +biganswer.example8. 3600 IN A 10.10.22.7 +biganswer.example8. 3600 IN A 10.10.22.8 +biganswer.example8. 3600 IN A 10.10.22.9 +biganswer.example8. 3600 IN A 10.10.22.10 +biganswer.example8. 3600 IN A 10.10.22.11 +biganswer.example8. 3600 IN A 10.10.22.12 +biganswer.example8. 3600 IN A 10.10.22.13 +biganswer.example8. 3600 IN A 10.10.22.14 +biganswer.example8. 3600 IN A 10.10.22.15 +biganswer.example8. 3600 IN A 10.10.22.16 +biganswer.example8. 3600 IN A 10.10.22.17 +biganswer.example8. 3600 IN A 10.10.22.18 +biganswer.example8. 3600 IN A 10.10.22.19 +biganswer.example8. 3600 IN A 10.10.22.20 +biganswer.example8. 3600 IN A 10.10.22.21 +biganswer.example8. 3600 IN A 10.10.22.22 +biganswer.example8. 3600 IN A 10.10.22.23 +biganswer.example8. 3600 IN A 10.10.22.24 +biganswer.example8. 3600 IN A 10.10.22.25 +biganswer.example8. 3600 IN A 10.10.22.26 +biganswer.example8. 3600 IN A 10.10.22.27 +biganswer.example8. 3600 IN A 10.10.22.28 +biganswer.example8. 3600 IN A 10.10.22.29 +biganswer.example8. 3600 IN A 10.10.22.30 +biganswer.example8. 3600 IN A 10.10.22.31 +biganswer.example8. 3600 IN A 10.10.22.32 +biganswer.example8. 3600 IN A 10.10.22.33 +biganswer.example8. 3600 IN A 10.10.22.34 +biganswer.example8. 3600 IN A 10.10.22.35 +biganswer.example8. 3600 IN A 10.10.22.36 +biganswer.example8. 3600 IN A 10.10.22.37 +biganswer.example8. 3600 IN A 10.10.22.38 +biganswer.example8. 3600 IN A 10.10.22.39 +biganswer.example8. 3600 IN A 10.10.22.40 +biganswer.example8. 3600 IN A 10.10.22.41 +biganswer.example8. 3600 IN A 10.10.22.42 +biganswer.example8. 3600 IN A 10.10.22.43 +biganswer.example8. 3600 IN A 10.10.22.44 +biganswer.example8. 3600 IN A 10.10.22.45 +biganswer.example8. 3600 IN A 10.10.22.46 +biganswer.example8. 3600 IN A 10.10.22.47 +biganswer.example8. 3600 IN A 10.10.22.48 +biganswer.example8. 3600 IN A 10.10.22.49 +biganswer.example8. 3600 IN A 10.10.22.50 +biganswer.example8. 3600 IN A 10.10.23.1 +biganswer.example8. 3600 IN A 10.10.23.2 +biganswer.example8. 3600 IN A 10.10.23.3 +biganswer.example8. 3600 IN A 10.10.23.4 +biganswer.example8. 3600 IN A 10.10.23.5 +biganswer.example8. 3600 IN A 10.10.23.6 +biganswer.example8. 3600 IN A 10.10.23.7 +biganswer.example8. 3600 IN A 10.10.23.8 +biganswer.example8. 3600 IN A 10.10.23.9 +biganswer.example8. 3600 IN A 10.10.23.10 +biganswer.example8. 3600 IN A 10.10.23.11 +biganswer.example8. 3600 IN A 10.10.23.12 +biganswer.example8. 3600 IN A 10.10.23.13 +biganswer.example8. 3600 IN A 10.10.23.14 +biganswer.example8. 3600 IN A 10.10.23.15 +biganswer.example8. 3600 IN A 10.10.23.16 +biganswer.example8. 3600 IN A 10.10.23.17 +biganswer.example8. 3600 IN A 10.10.23.18 +biganswer.example8. 3600 IN A 10.10.23.19 +biganswer.example8. 3600 IN A 10.10.23.20 +biganswer.example8. 3600 IN A 10.10.23.21 +biganswer.example8. 3600 IN A 10.10.23.22 +biganswer.example8. 3600 IN A 10.10.23.23 +biganswer.example8. 3600 IN A 10.10.23.24 +biganswer.example8. 3600 IN A 10.10.23.25 +biganswer.example8. 3600 IN A 10.10.23.26 +biganswer.example8. 3600 IN A 10.10.23.27 +biganswer.example8. 3600 IN A 10.10.23.28 +biganswer.example8. 3600 IN A 10.10.23.29 +biganswer.example8. 3600 IN A 10.10.23.30 +biganswer.example8. 3600 IN A 10.10.23.31 +biganswer.example8. 3600 IN A 10.10.23.32 +biganswer.example8. 3600 IN A 10.10.23.33 +biganswer.example8. 3600 IN A 10.10.23.34 +biganswer.example8. 3600 IN A 10.10.23.35 +biganswer.example8. 3600 IN A 10.10.23.36 +biganswer.example8. 3600 IN A 10.10.23.37 +biganswer.example8. 3600 IN A 10.10.23.38 +biganswer.example8. 3600 IN A 10.10.23.39 +biganswer.example8. 3600 IN A 10.10.23.40 +biganswer.example8. 3600 IN A 10.10.23.41 +biganswer.example8. 3600 IN A 10.10.23.42 +biganswer.example8. 3600 IN A 10.10.23.43 +biganswer.example8. 3600 IN A 10.10.23.44 +biganswer.example8. 3600 IN A 10.10.23.45 +biganswer.example8. 3600 IN A 10.10.23.46 +biganswer.example8. 3600 IN A 10.10.23.47 +biganswer.example8. 3600 IN A 10.10.23.48 +biganswer.example8. 3600 IN A 10.10.23.49 +biganswer.example8. 3600 IN A 10.10.23.50 +biganswer.example8. 3600 IN A 10.10.24.1 +biganswer.example8. 3600 IN A 10.10.24.2 +biganswer.example8. 3600 IN A 10.10.24.3 +biganswer.example8. 3600 IN A 10.10.24.4 +biganswer.example8. 3600 IN A 10.10.24.5 +biganswer.example8. 3600 IN A 10.10.24.6 +biganswer.example8. 3600 IN A 10.10.24.7 +biganswer.example8. 3600 IN A 10.10.24.8 +biganswer.example8. 3600 IN A 10.10.24.9 +biganswer.example8. 3600 IN A 10.10.24.10 +biganswer.example8. 3600 IN A 10.10.24.11 +biganswer.example8. 3600 IN A 10.10.24.12 +biganswer.example8. 3600 IN A 10.10.24.13 +biganswer.example8. 3600 IN A 10.10.24.14 +biganswer.example8. 3600 IN A 10.10.24.15 +biganswer.example8. 3600 IN A 10.10.24.16 +biganswer.example8. 3600 IN A 10.10.24.17 +biganswer.example8. 3600 IN A 10.10.24.18 +biganswer.example8. 3600 IN A 10.10.24.19 +biganswer.example8. 3600 IN A 10.10.24.20 +biganswer.example8. 3600 IN A 10.10.24.21 +biganswer.example8. 3600 IN A 10.10.24.22 +biganswer.example8. 3600 IN A 10.10.24.23 +biganswer.example8. 3600 IN A 10.10.24.24 +biganswer.example8. 3600 IN A 10.10.24.25 +biganswer.example8. 3600 IN A 10.10.24.26 +biganswer.example8. 3600 IN A 10.10.24.27 +biganswer.example8. 3600 IN A 10.10.24.28 +biganswer.example8. 3600 IN A 10.10.24.29 +biganswer.example8. 3600 IN A 10.10.24.30 +biganswer.example8. 3600 IN A 10.10.24.31 +biganswer.example8. 3600 IN A 10.10.24.32 +biganswer.example8. 3600 IN A 10.10.24.33 +biganswer.example8. 3600 IN A 10.10.24.34 +biganswer.example8. 3600 IN A 10.10.24.35 +biganswer.example8. 3600 IN A 10.10.24.36 +biganswer.example8. 3600 IN A 10.10.24.37 +biganswer.example8. 3600 IN A 10.10.24.38 +biganswer.example8. 3600 IN A 10.10.24.39 +biganswer.example8. 3600 IN A 10.10.24.40 +biganswer.example8. 3600 IN A 10.10.24.41 +biganswer.example8. 3600 IN A 10.10.24.42 +biganswer.example8. 3600 IN A 10.10.24.43 +biganswer.example8. 3600 IN A 10.10.24.44 +biganswer.example8. 3600 IN A 10.10.24.45 +biganswer.example8. 3600 IN A 10.10.24.46 +biganswer.example8. 3600 IN A 10.10.24.47 +biganswer.example8. 3600 IN A 10.10.24.48 +biganswer.example8. 3600 IN A 10.10.24.49 +biganswer.example8. 3600 IN A 10.10.24.50 +biganswer.example8. 3600 IN A 10.10.25.1 +biganswer.example8. 3600 IN A 10.10.25.2 +biganswer.example8. 3600 IN A 10.10.25.3 +biganswer.example8. 3600 IN A 10.10.25.4 +biganswer.example8. 3600 IN A 10.10.25.5 +biganswer.example8. 3600 IN A 10.10.25.6 +biganswer.example8. 3600 IN A 10.10.25.7 +biganswer.example8. 3600 IN A 10.10.25.8 +biganswer.example8. 3600 IN A 10.10.25.9 +biganswer.example8. 3600 IN A 10.10.25.10 +biganswer.example8. 3600 IN A 10.10.25.11 +biganswer.example8. 3600 IN A 10.10.25.12 +biganswer.example8. 3600 IN A 10.10.25.13 +biganswer.example8. 3600 IN A 10.10.25.14 +biganswer.example8. 3600 IN A 10.10.25.15 +biganswer.example8. 3600 IN A 10.10.25.16 +biganswer.example8. 3600 IN A 10.10.25.17 +biganswer.example8. 3600 IN A 10.10.25.18 +biganswer.example8. 3600 IN A 10.10.25.19 +biganswer.example8. 3600 IN A 10.10.25.20 +biganswer.example8. 3600 IN A 10.10.25.21 +biganswer.example8. 3600 IN A 10.10.25.22 +biganswer.example8. 3600 IN A 10.10.25.23 +biganswer.example8. 3600 IN A 10.10.25.24 +biganswer.example8. 3600 IN A 10.10.25.25 +biganswer.example8. 3600 IN A 10.10.25.26 +biganswer.example8. 3600 IN A 10.10.25.27 +biganswer.example8. 3600 IN A 10.10.25.28 +biganswer.example8. 3600 IN A 10.10.25.29 +biganswer.example8. 3600 IN A 10.10.25.30 +biganswer.example8. 3600 IN A 10.10.25.31 +biganswer.example8. 3600 IN A 10.10.25.32 +biganswer.example8. 3600 IN A 10.10.25.33 +biganswer.example8. 3600 IN A 10.10.25.34 +biganswer.example8. 3600 IN A 10.10.25.35 +biganswer.example8. 3600 IN A 10.10.25.36 +biganswer.example8. 3600 IN A 10.10.25.37 +biganswer.example8. 3600 IN A 10.10.25.38 +biganswer.example8. 3600 IN A 10.10.25.39 +biganswer.example8. 3600 IN A 10.10.25.40 +biganswer.example8. 3600 IN A 10.10.25.41 +biganswer.example8. 3600 IN A 10.10.25.42 +biganswer.example8. 3600 IN A 10.10.25.43 +biganswer.example8. 3600 IN A 10.10.25.44 +biganswer.example8. 3600 IN A 10.10.25.45 +biganswer.example8. 3600 IN A 10.10.25.46 +biganswer.example8. 3600 IN A 10.10.25.47 +biganswer.example8. 3600 IN A 10.10.25.48 +biganswer.example8. 3600 IN A 10.10.25.49 +biganswer.example8. 3600 IN A 10.10.25.50 +biganswer.example8. 3600 IN A 10.10.26.1 +biganswer.example8. 3600 IN A 10.10.26.2 +biganswer.example8. 3600 IN A 10.10.26.3 +biganswer.example8. 3600 IN A 10.10.26.4 +biganswer.example8. 3600 IN A 10.10.26.5 +biganswer.example8. 3600 IN A 10.10.26.6 +biganswer.example8. 3600 IN A 10.10.26.7 +biganswer.example8. 3600 IN A 10.10.26.8 +biganswer.example8. 3600 IN A 10.10.26.9 +biganswer.example8. 3600 IN A 10.10.26.10 +biganswer.example8. 3600 IN A 10.10.26.11 +biganswer.example8. 3600 IN A 10.10.26.12 +biganswer.example8. 3600 IN A 10.10.26.13 +biganswer.example8. 3600 IN A 10.10.26.14 +biganswer.example8. 3600 IN A 10.10.26.15 +biganswer.example8. 3600 IN A 10.10.26.16 +biganswer.example8. 3600 IN A 10.10.26.17 +biganswer.example8. 3600 IN A 10.10.26.18 +biganswer.example8. 3600 IN A 10.10.26.19 +biganswer.example8. 3600 IN A 10.10.26.20 +biganswer.example8. 3600 IN A 10.10.26.21 +biganswer.example8. 3600 IN A 10.10.26.22 +biganswer.example8. 3600 IN A 10.10.26.23 +biganswer.example8. 3600 IN A 10.10.26.24 +biganswer.example8. 3600 IN A 10.10.26.25 +biganswer.example8. 3600 IN A 10.10.26.26 +biganswer.example8. 3600 IN A 10.10.26.27 +biganswer.example8. 3600 IN A 10.10.26.28 +biganswer.example8. 3600 IN A 10.10.26.29 +biganswer.example8. 3600 IN A 10.10.26.30 +biganswer.example8. 3600 IN A 10.10.26.31 +biganswer.example8. 3600 IN A 10.10.26.32 +biganswer.example8. 3600 IN A 10.10.26.33 +biganswer.example8. 3600 IN A 10.10.26.34 +biganswer.example8. 3600 IN A 10.10.26.35 +biganswer.example8. 3600 IN A 10.10.26.36 +biganswer.example8. 3600 IN A 10.10.26.37 +biganswer.example8. 3600 IN A 10.10.26.38 +biganswer.example8. 3600 IN A 10.10.26.39 +biganswer.example8. 3600 IN A 10.10.26.40 +biganswer.example8. 3600 IN A 10.10.26.41 +biganswer.example8. 3600 IN A 10.10.26.42 +biganswer.example8. 3600 IN A 10.10.26.43 +biganswer.example8. 3600 IN A 10.10.26.44 +biganswer.example8. 3600 IN A 10.10.26.45 +biganswer.example8. 3600 IN A 10.10.26.46 +biganswer.example8. 3600 IN A 10.10.26.47 +biganswer.example8. 3600 IN A 10.10.26.48 +biganswer.example8. 3600 IN A 10.10.26.49 +biganswer.example8. 3600 IN A 10.10.26.50 +biganswer.example8. 3600 IN A 10.10.27.1 +biganswer.example8. 3600 IN A 10.10.27.2 +biganswer.example8. 3600 IN A 10.10.27.3 +biganswer.example8. 3600 IN A 10.10.27.4 +biganswer.example8. 3600 IN A 10.10.27.5 +biganswer.example8. 3600 IN A 10.10.27.6 +biganswer.example8. 3600 IN A 10.10.27.7 +biganswer.example8. 3600 IN A 10.10.27.8 +biganswer.example8. 3600 IN A 10.10.27.9 +biganswer.example8. 3600 IN A 10.10.27.10 +biganswer.example8. 3600 IN A 10.10.27.11 +biganswer.example8. 3600 IN A 10.10.27.12 +biganswer.example8. 3600 IN A 10.10.27.13 +biganswer.example8. 3600 IN A 10.10.27.14 +biganswer.example8. 3600 IN A 10.10.27.15 +biganswer.example8. 3600 IN A 10.10.27.16 +biganswer.example8. 3600 IN A 10.10.27.17 +biganswer.example8. 3600 IN A 10.10.27.18 +biganswer.example8. 3600 IN A 10.10.27.19 +biganswer.example8. 3600 IN A 10.10.27.20 +biganswer.example8. 3600 IN A 10.10.27.21 +biganswer.example8. 3600 IN A 10.10.27.22 +biganswer.example8. 3600 IN A 10.10.27.23 +biganswer.example8. 3600 IN A 10.10.27.24 +biganswer.example8. 3600 IN A 10.10.27.25 +biganswer.example8. 3600 IN A 10.10.27.26 +biganswer.example8. 3600 IN A 10.10.27.27 +biganswer.example8. 3600 IN A 10.10.27.28 +biganswer.example8. 3600 IN A 10.10.27.29 +biganswer.example8. 3600 IN A 10.10.27.30 +biganswer.example8. 3600 IN A 10.10.27.31 +biganswer.example8. 3600 IN A 10.10.27.32 +biganswer.example8. 3600 IN A 10.10.27.33 +biganswer.example8. 3600 IN A 10.10.27.34 +biganswer.example8. 3600 IN A 10.10.27.35 +biganswer.example8. 3600 IN A 10.10.27.36 +biganswer.example8. 3600 IN A 10.10.27.37 +biganswer.example8. 3600 IN A 10.10.27.38 +biganswer.example8. 3600 IN A 10.10.27.39 +biganswer.example8. 3600 IN A 10.10.27.40 +biganswer.example8. 3600 IN A 10.10.27.41 +biganswer.example8. 3600 IN A 10.10.27.42 +biganswer.example8. 3600 IN A 10.10.27.43 +biganswer.example8. 3600 IN A 10.10.27.44 +biganswer.example8. 3600 IN A 10.10.27.45 +biganswer.example8. 3600 IN A 10.10.27.46 +biganswer.example8. 3600 IN A 10.10.27.47 +biganswer.example8. 3600 IN A 10.10.27.48 +biganswer.example8. 3600 IN A 10.10.27.49 +biganswer.example8. 3600 IN A 10.10.27.50 +biganswer.example8. 3600 IN A 10.10.28.1 +biganswer.example8. 3600 IN A 10.10.28.2 +biganswer.example8. 3600 IN A 10.10.28.3 +biganswer.example8. 3600 IN A 10.10.28.4 +biganswer.example8. 3600 IN A 10.10.28.5 +biganswer.example8. 3600 IN A 10.10.28.6 +biganswer.example8. 3600 IN A 10.10.28.7 +biganswer.example8. 3600 IN A 10.10.28.8 +biganswer.example8. 3600 IN A 10.10.28.9 +biganswer.example8. 3600 IN A 10.10.28.10 +biganswer.example8. 3600 IN A 10.10.28.11 +biganswer.example8. 3600 IN A 10.10.28.12 +biganswer.example8. 3600 IN A 10.10.28.13 +biganswer.example8. 3600 IN A 10.10.28.14 +biganswer.example8. 3600 IN A 10.10.28.15 +biganswer.example8. 3600 IN A 10.10.28.16 +biganswer.example8. 3600 IN A 10.10.28.17 +biganswer.example8. 3600 IN A 10.10.28.18 +biganswer.example8. 3600 IN A 10.10.28.19 +biganswer.example8. 3600 IN A 10.10.28.20 +biganswer.example8. 3600 IN A 10.10.28.21 +biganswer.example8. 3600 IN A 10.10.28.22 +biganswer.example8. 3600 IN A 10.10.28.23 +biganswer.example8. 3600 IN A 10.10.28.24 +biganswer.example8. 3600 IN A 10.10.28.25 +biganswer.example8. 3600 IN A 10.10.28.26 +biganswer.example8. 3600 IN A 10.10.28.27 +biganswer.example8. 3600 IN A 10.10.28.28 +biganswer.example8. 3600 IN A 10.10.28.29 +biganswer.example8. 3600 IN A 10.10.28.30 +biganswer.example8. 3600 IN A 10.10.28.31 +biganswer.example8. 3600 IN A 10.10.28.32 +biganswer.example8. 3600 IN A 10.10.28.33 +biganswer.example8. 3600 IN A 10.10.28.34 +biganswer.example8. 3600 IN A 10.10.28.35 +biganswer.example8. 3600 IN A 10.10.28.36 +biganswer.example8. 3600 IN A 10.10.28.37 +biganswer.example8. 3600 IN A 10.10.28.38 +biganswer.example8. 3600 IN A 10.10.28.39 +biganswer.example8. 3600 IN A 10.10.28.40 +biganswer.example8. 3600 IN A 10.10.28.41 +biganswer.example8. 3600 IN A 10.10.28.42 +biganswer.example8. 3600 IN A 10.10.28.43 +biganswer.example8. 3600 IN A 10.10.28.44 +biganswer.example8. 3600 IN A 10.10.28.45 +biganswer.example8. 3600 IN A 10.10.28.46 +biganswer.example8. 3600 IN A 10.10.28.47 +biganswer.example8. 3600 IN A 10.10.28.48 +biganswer.example8. 3600 IN A 10.10.28.49 +biganswer.example8. 3600 IN A 10.10.28.50 +biganswer.example8. 3600 IN A 10.10.29.1 +biganswer.example8. 3600 IN A 10.10.29.2 +biganswer.example8. 3600 IN A 10.10.29.3 +biganswer.example8. 3600 IN A 10.10.29.4 +biganswer.example8. 3600 IN A 10.10.29.5 +biganswer.example8. 3600 IN A 10.10.29.6 +biganswer.example8. 3600 IN A 10.10.29.7 +biganswer.example8. 3600 IN A 10.10.29.8 +biganswer.example8. 3600 IN A 10.10.29.9 +biganswer.example8. 3600 IN A 10.10.29.10 +biganswer.example8. 3600 IN A 10.10.29.11 +biganswer.example8. 3600 IN A 10.10.29.12 +biganswer.example8. 3600 IN A 10.10.29.13 +biganswer.example8. 3600 IN A 10.10.29.14 +biganswer.example8. 3600 IN A 10.10.29.15 +biganswer.example8. 3600 IN A 10.10.29.16 +biganswer.example8. 3600 IN A 10.10.29.17 +biganswer.example8. 3600 IN A 10.10.29.18 +biganswer.example8. 3600 IN A 10.10.29.19 +biganswer.example8. 3600 IN A 10.10.29.20 +biganswer.example8. 3600 IN A 10.10.29.21 +biganswer.example8. 3600 IN A 10.10.29.22 +biganswer.example8. 3600 IN A 10.10.29.23 +biganswer.example8. 3600 IN A 10.10.29.24 +biganswer.example8. 3600 IN A 10.10.29.25 +biganswer.example8. 3600 IN A 10.10.29.26 +biganswer.example8. 3600 IN A 10.10.29.27 +biganswer.example8. 3600 IN A 10.10.29.28 +biganswer.example8. 3600 IN A 10.10.29.29 +biganswer.example8. 3600 IN A 10.10.29.30 +biganswer.example8. 3600 IN A 10.10.29.31 +biganswer.example8. 3600 IN A 10.10.29.32 +biganswer.example8. 3600 IN A 10.10.29.33 +biganswer.example8. 3600 IN A 10.10.29.34 +biganswer.example8. 3600 IN A 10.10.29.35 +biganswer.example8. 3600 IN A 10.10.29.36 +biganswer.example8. 3600 IN A 10.10.29.37 +biganswer.example8. 3600 IN A 10.10.29.38 +biganswer.example8. 3600 IN A 10.10.29.39 +biganswer.example8. 3600 IN A 10.10.29.40 +biganswer.example8. 3600 IN A 10.10.29.41 +biganswer.example8. 3600 IN A 10.10.29.42 +biganswer.example8. 3600 IN A 10.10.29.43 +biganswer.example8. 3600 IN A 10.10.29.44 +biganswer.example8. 3600 IN A 10.10.29.45 +biganswer.example8. 3600 IN A 10.10.29.46 +biganswer.example8. 3600 IN A 10.10.29.47 +biganswer.example8. 3600 IN A 10.10.29.48 +biganswer.example8. 3600 IN A 10.10.29.49 +biganswer.example8. 3600 IN A 10.10.29.50 +biganswer.example8. 3600 IN A 10.10.30.1 +biganswer.example8. 3600 IN A 10.10.30.2 +biganswer.example8. 3600 IN A 10.10.30.3 +biganswer.example8. 3600 IN A 10.10.30.4 +biganswer.example8. 3600 IN A 10.10.30.5 +biganswer.example8. 3600 IN A 10.10.30.6 +biganswer.example8. 3600 IN A 10.10.30.7 +biganswer.example8. 3600 IN A 10.10.30.8 +biganswer.example8. 3600 IN A 10.10.30.9 +biganswer.example8. 3600 IN A 10.10.30.10 +biganswer.example8. 3600 IN A 10.10.30.11 +biganswer.example8. 3600 IN A 10.10.30.12 +biganswer.example8. 3600 IN A 10.10.30.13 +biganswer.example8. 3600 IN A 10.10.30.14 +biganswer.example8. 3600 IN A 10.10.30.15 +biganswer.example8. 3600 IN A 10.10.30.16 +biganswer.example8. 3600 IN A 10.10.30.17 +biganswer.example8. 3600 IN A 10.10.30.18 +biganswer.example8. 3600 IN A 10.10.30.19 +biganswer.example8. 3600 IN A 10.10.30.20 +biganswer.example8. 3600 IN A 10.10.30.21 +biganswer.example8. 3600 IN A 10.10.30.22 +biganswer.example8. 3600 IN A 10.10.30.23 +biganswer.example8. 3600 IN A 10.10.30.24 +biganswer.example8. 3600 IN A 10.10.30.25 +biganswer.example8. 3600 IN A 10.10.30.26 +biganswer.example8. 3600 IN A 10.10.30.27 +biganswer.example8. 3600 IN A 10.10.30.28 +biganswer.example8. 3600 IN A 10.10.30.29 +biganswer.example8. 3600 IN A 10.10.30.30 +biganswer.example8. 3600 IN A 10.10.30.31 +biganswer.example8. 3600 IN A 10.10.30.32 +biganswer.example8. 3600 IN A 10.10.30.33 +biganswer.example8. 3600 IN A 10.10.30.34 +biganswer.example8. 3600 IN A 10.10.30.35 +biganswer.example8. 3600 IN A 10.10.30.36 +biganswer.example8. 3600 IN A 10.10.30.37 +biganswer.example8. 3600 IN A 10.10.30.38 +biganswer.example8. 3600 IN A 10.10.30.39 +biganswer.example8. 3600 IN A 10.10.30.40 +biganswer.example8. 3600 IN A 10.10.30.41 +biganswer.example8. 3600 IN A 10.10.30.42 +biganswer.example8. 3600 IN A 10.10.30.43 +biganswer.example8. 3600 IN A 10.10.30.44 +biganswer.example8. 3600 IN A 10.10.30.45 +biganswer.example8. 3600 IN A 10.10.30.46 +biganswer.example8. 3600 IN A 10.10.30.47 +biganswer.example8. 3600 IN A 10.10.30.48 +biganswer.example8. 3600 IN A 10.10.30.49 +biganswer.example8. 3600 IN A 10.10.30.50 +biganswer.example8. 3600 IN A 10.10.31.1 +biganswer.example8. 3600 IN A 10.10.31.2 +biganswer.example8. 3600 IN A 10.10.31.3 +biganswer.example8. 3600 IN A 10.10.31.4 +biganswer.example8. 3600 IN A 10.10.31.5 +biganswer.example8. 3600 IN A 10.10.31.6 +biganswer.example8. 3600 IN A 10.10.31.7 +biganswer.example8. 3600 IN A 10.10.31.8 +biganswer.example8. 3600 IN A 10.10.31.9 +biganswer.example8. 3600 IN A 10.10.31.10 +biganswer.example8. 3600 IN A 10.10.31.11 +biganswer.example8. 3600 IN A 10.10.31.12 +biganswer.example8. 3600 IN A 10.10.31.13 +biganswer.example8. 3600 IN A 10.10.31.14 +biganswer.example8. 3600 IN A 10.10.31.15 +biganswer.example8. 3600 IN A 10.10.31.16 +biganswer.example8. 3600 IN A 10.10.31.17 +biganswer.example8. 3600 IN A 10.10.31.18 +biganswer.example8. 3600 IN A 10.10.31.19 +biganswer.example8. 3600 IN A 10.10.31.20 +biganswer.example8. 3600 IN A 10.10.31.21 +biganswer.example8. 3600 IN A 10.10.31.22 +biganswer.example8. 3600 IN A 10.10.31.23 +biganswer.example8. 3600 IN A 10.10.31.24 +biganswer.example8. 3600 IN A 10.10.31.25 +biganswer.example8. 3600 IN A 10.10.31.26 +biganswer.example8. 3600 IN A 10.10.31.27 +biganswer.example8. 3600 IN A 10.10.31.28 +biganswer.example8. 3600 IN A 10.10.31.29 +biganswer.example8. 3600 IN A 10.10.31.30 +biganswer.example8. 3600 IN A 10.10.31.31 +biganswer.example8. 3600 IN A 10.10.31.32 +biganswer.example8. 3600 IN A 10.10.31.33 +biganswer.example8. 3600 IN A 10.10.31.34 +biganswer.example8. 3600 IN A 10.10.31.35 +biganswer.example8. 3600 IN A 10.10.31.36 +biganswer.example8. 3600 IN A 10.10.31.37 +biganswer.example8. 3600 IN A 10.10.31.38 +biganswer.example8. 3600 IN A 10.10.31.39 +biganswer.example8. 3600 IN A 10.10.31.40 +biganswer.example8. 3600 IN A 10.10.31.41 +biganswer.example8. 3600 IN A 10.10.31.42 +biganswer.example8. 3600 IN A 10.10.31.43 +biganswer.example8. 3600 IN A 10.10.31.44 +biganswer.example8. 3600 IN A 10.10.31.45 +biganswer.example8. 3600 IN A 10.10.31.46 +biganswer.example8. 3600 IN A 10.10.31.47 +biganswer.example8. 3600 IN A 10.10.31.48 +biganswer.example8. 3600 IN A 10.10.31.49 +biganswer.example8. 3600 IN A 10.10.31.50 +biganswer.example8. 3600 IN A 10.10.32.1 +biganswer.example8. 3600 IN A 10.10.32.2 +biganswer.example8. 3600 IN A 10.10.32.3 +biganswer.example8. 3600 IN A 10.10.32.4 +biganswer.example8. 3600 IN A 10.10.32.5 +biganswer.example8. 3600 IN A 10.10.32.6 +biganswer.example8. 3600 IN A 10.10.32.7 +biganswer.example8. 3600 IN A 10.10.32.8 +biganswer.example8. 3600 IN A 10.10.32.9 +biganswer.example8. 3600 IN A 10.10.32.10 +biganswer.example8. 3600 IN A 10.10.32.11 +biganswer.example8. 3600 IN A 10.10.32.12 +biganswer.example8. 3600 IN A 10.10.32.13 +biganswer.example8. 3600 IN A 10.10.32.14 +biganswer.example8. 3600 IN A 10.10.32.15 +biganswer.example8. 3600 IN A 10.10.32.16 +biganswer.example8. 3600 IN A 10.10.32.17 +biganswer.example8. 3600 IN A 10.10.32.18 +biganswer.example8. 3600 IN A 10.10.32.19 +biganswer.example8. 3600 IN A 10.10.32.20 +biganswer.example8. 3600 IN A 10.10.32.21 +biganswer.example8. 3600 IN A 10.10.32.22 +biganswer.example8. 3600 IN A 10.10.32.23 +biganswer.example8. 3600 IN A 10.10.32.24 +biganswer.example8. 3600 IN A 10.10.32.25 +biganswer.example8. 3600 IN A 10.10.32.26 +biganswer.example8. 3600 IN A 10.10.32.27 +biganswer.example8. 3600 IN A 10.10.32.28 +biganswer.example8. 3600 IN A 10.10.32.29 +biganswer.example8. 3600 IN A 10.10.32.30 +biganswer.example8. 3600 IN A 10.10.32.31 +biganswer.example8. 3600 IN A 10.10.32.32 +biganswer.example8. 3600 IN A 10.10.32.33 +biganswer.example8. 3600 IN A 10.10.32.34 +biganswer.example8. 3600 IN A 10.10.32.35 +biganswer.example8. 3600 IN A 10.10.32.36 +biganswer.example8. 3600 IN A 10.10.32.37 +biganswer.example8. 3600 IN A 10.10.32.38 +biganswer.example8. 3600 IN A 10.10.32.39 +biganswer.example8. 3600 IN A 10.10.32.40 +biganswer.example8. 3600 IN A 10.10.32.41 +biganswer.example8. 3600 IN A 10.10.32.42 +biganswer.example8. 3600 IN A 10.10.32.43 +biganswer.example8. 3600 IN A 10.10.32.44 +biganswer.example8. 3600 IN A 10.10.32.45 +biganswer.example8. 3600 IN A 10.10.32.46 +biganswer.example8. 3600 IN A 10.10.32.47 +biganswer.example8. 3600 IN A 10.10.32.48 +biganswer.example8. 3600 IN A 10.10.32.49 +biganswer.example8. 3600 IN A 10.10.32.50 +biganswer.example8. 3600 IN A 10.10.33.1 +biganswer.example8. 3600 IN A 10.10.33.2 +biganswer.example8. 3600 IN A 10.10.33.3 +biganswer.example8. 3600 IN A 10.10.33.4 +biganswer.example8. 3600 IN A 10.10.33.5 +biganswer.example8. 3600 IN A 10.10.33.6 +biganswer.example8. 3600 IN A 10.10.33.7 +biganswer.example8. 3600 IN A 10.10.33.8 +biganswer.example8. 3600 IN A 10.10.33.9 +biganswer.example8. 3600 IN A 10.10.33.10 +biganswer.example8. 3600 IN A 10.10.33.11 +biganswer.example8. 3600 IN A 10.10.33.12 +biganswer.example8. 3600 IN A 10.10.33.13 +biganswer.example8. 3600 IN A 10.10.33.14 +biganswer.example8. 3600 IN A 10.10.33.15 +biganswer.example8. 3600 IN A 10.10.33.16 +biganswer.example8. 3600 IN A 10.10.33.17 +biganswer.example8. 3600 IN A 10.10.33.18 +biganswer.example8. 3600 IN A 10.10.33.19 +biganswer.example8. 3600 IN A 10.10.33.20 +biganswer.example8. 3600 IN A 10.10.33.21 +biganswer.example8. 3600 IN A 10.10.33.22 +biganswer.example8. 3600 IN A 10.10.33.23 +biganswer.example8. 3600 IN A 10.10.33.24 +biganswer.example8. 3600 IN A 10.10.33.25 +biganswer.example8. 3600 IN A 10.10.33.26 +biganswer.example8. 3600 IN A 10.10.33.27 +biganswer.example8. 3600 IN A 10.10.33.28 +biganswer.example8. 3600 IN A 10.10.33.29 +biganswer.example8. 3600 IN A 10.10.33.30 +biganswer.example8. 3600 IN A 10.10.33.31 +biganswer.example8. 3600 IN A 10.10.33.32 +biganswer.example8. 3600 IN A 10.10.33.33 +biganswer.example8. 3600 IN A 10.10.33.34 +biganswer.example8. 3600 IN A 10.10.33.35 +biganswer.example8. 3600 IN A 10.10.33.36 +biganswer.example8. 3600 IN A 10.10.33.37 +biganswer.example8. 3600 IN A 10.10.33.38 +biganswer.example8. 3600 IN A 10.10.33.39 +biganswer.example8. 3600 IN A 10.10.33.40 +biganswer.example8. 3600 IN A 10.10.33.41 +biganswer.example8. 3600 IN A 10.10.33.42 +biganswer.example8. 3600 IN A 10.10.33.43 +biganswer.example8. 3600 IN A 10.10.33.44 +biganswer.example8. 3600 IN A 10.10.33.45 +biganswer.example8. 3600 IN A 10.10.33.46 +biganswer.example8. 3600 IN A 10.10.33.47 +biganswer.example8. 3600 IN A 10.10.33.48 +biganswer.example8. 3600 IN A 10.10.33.49 +biganswer.example8. 3600 IN A 10.10.33.50 +biganswer.example8. 3600 IN A 10.10.34.1 +biganswer.example8. 3600 IN A 10.10.34.2 +biganswer.example8. 3600 IN A 10.10.34.3 +biganswer.example8. 3600 IN A 10.10.34.4 +biganswer.example8. 3600 IN A 10.10.34.5 +biganswer.example8. 3600 IN A 10.10.34.6 +biganswer.example8. 3600 IN A 10.10.34.7 +biganswer.example8. 3600 IN A 10.10.34.8 +biganswer.example8. 3600 IN A 10.10.34.9 +biganswer.example8. 3600 IN A 10.10.34.10 +biganswer.example8. 3600 IN A 10.10.34.11 +biganswer.example8. 3600 IN A 10.10.34.12 +biganswer.example8. 3600 IN A 10.10.34.13 +biganswer.example8. 3600 IN A 10.10.34.14 +biganswer.example8. 3600 IN A 10.10.34.15 +biganswer.example8. 3600 IN A 10.10.34.16 +biganswer.example8. 3600 IN A 10.10.34.17 +biganswer.example8. 3600 IN A 10.10.34.18 +biganswer.example8. 3600 IN A 10.10.34.19 +biganswer.example8. 3600 IN A 10.10.34.20 +biganswer.example8. 3600 IN A 10.10.34.21 +biganswer.example8. 3600 IN A 10.10.34.22 +biganswer.example8. 3600 IN A 10.10.34.23 +biganswer.example8. 3600 IN A 10.10.34.24 +biganswer.example8. 3600 IN A 10.10.34.25 +biganswer.example8. 3600 IN A 10.10.34.26 +biganswer.example8. 3600 IN A 10.10.34.27 +biganswer.example8. 3600 IN A 10.10.34.28 +biganswer.example8. 3600 IN A 10.10.34.29 +biganswer.example8. 3600 IN A 10.10.34.30 +biganswer.example8. 3600 IN A 10.10.34.31 +biganswer.example8. 3600 IN A 10.10.34.32 +biganswer.example8. 3600 IN A 10.10.34.33 +biganswer.example8. 3600 IN A 10.10.34.34 +biganswer.example8. 3600 IN A 10.10.34.35 +biganswer.example8. 3600 IN A 10.10.34.36 +biganswer.example8. 3600 IN A 10.10.34.37 +biganswer.example8. 3600 IN A 10.10.34.38 +biganswer.example8. 3600 IN A 10.10.34.39 +biganswer.example8. 3600 IN A 10.10.34.40 +biganswer.example8. 3600 IN A 10.10.34.41 +biganswer.example8. 3600 IN A 10.10.34.42 +biganswer.example8. 3600 IN A 10.10.34.43 +biganswer.example8. 3600 IN A 10.10.34.44 +biganswer.example8. 3600 IN A 10.10.34.45 +biganswer.example8. 3600 IN A 10.10.34.46 +biganswer.example8. 3600 IN A 10.10.34.47 +biganswer.example8. 3600 IN A 10.10.34.48 +biganswer.example8. 3600 IN A 10.10.34.49 +biganswer.example8. 3600 IN A 10.10.34.50 +biganswer.example8. 3600 IN A 10.10.35.1 +biganswer.example8. 3600 IN A 10.10.35.2 +biganswer.example8. 3600 IN A 10.10.35.3 +biganswer.example8. 3600 IN A 10.10.35.4 +biganswer.example8. 3600 IN A 10.10.35.5 +biganswer.example8. 3600 IN A 10.10.35.6 +biganswer.example8. 3600 IN A 10.10.35.7 +biganswer.example8. 3600 IN A 10.10.35.8 +biganswer.example8. 3600 IN A 10.10.35.9 +biganswer.example8. 3600 IN A 10.10.35.10 +biganswer.example8. 3600 IN A 10.10.35.11 +biganswer.example8. 3600 IN A 10.10.35.12 +biganswer.example8. 3600 IN A 10.10.35.13 +biganswer.example8. 3600 IN A 10.10.35.14 +biganswer.example8. 3600 IN A 10.10.35.15 +biganswer.example8. 3600 IN A 10.10.35.16 +biganswer.example8. 3600 IN A 10.10.35.17 +biganswer.example8. 3600 IN A 10.10.35.18 +biganswer.example8. 3600 IN A 10.10.35.19 +biganswer.example8. 3600 IN A 10.10.35.20 +biganswer.example8. 3600 IN A 10.10.35.21 +biganswer.example8. 3600 IN A 10.10.35.22 +biganswer.example8. 3600 IN A 10.10.35.23 +biganswer.example8. 3600 IN A 10.10.35.24 +biganswer.example8. 3600 IN A 10.10.35.25 +biganswer.example8. 3600 IN A 10.10.35.26 +biganswer.example8. 3600 IN A 10.10.35.27 +biganswer.example8. 3600 IN A 10.10.35.28 +biganswer.example8. 3600 IN A 10.10.35.29 +biganswer.example8. 3600 IN A 10.10.35.30 +biganswer.example8. 3600 IN A 10.10.35.31 +biganswer.example8. 3600 IN A 10.10.35.32 +biganswer.example8. 3600 IN A 10.10.35.33 +biganswer.example8. 3600 IN A 10.10.35.34 +biganswer.example8. 3600 IN A 10.10.35.35 +biganswer.example8. 3600 IN A 10.10.35.36 +biganswer.example8. 3600 IN A 10.10.35.37 +biganswer.example8. 3600 IN A 10.10.35.38 +biganswer.example8. 3600 IN A 10.10.35.39 +biganswer.example8. 3600 IN A 10.10.35.40 +biganswer.example8. 3600 IN A 10.10.35.41 +biganswer.example8. 3600 IN A 10.10.35.42 +biganswer.example8. 3600 IN A 10.10.35.43 +biganswer.example8. 3600 IN A 10.10.35.44 +biganswer.example8. 3600 IN A 10.10.35.45 +biganswer.example8. 3600 IN A 10.10.35.46 +biganswer.example8. 3600 IN A 10.10.35.47 +biganswer.example8. 3600 IN A 10.10.35.48 +biganswer.example8. 3600 IN A 10.10.35.49 +biganswer.example8. 3600 IN A 10.10.35.50 +biganswer.example8. 3600 IN A 10.10.36.1 +biganswer.example8. 3600 IN A 10.10.36.2 +biganswer.example8. 3600 IN A 10.10.36.3 +biganswer.example8. 3600 IN A 10.10.36.4 +biganswer.example8. 3600 IN A 10.10.36.5 +biganswer.example8. 3600 IN A 10.10.36.6 +biganswer.example8. 3600 IN A 10.10.36.7 +biganswer.example8. 3600 IN A 10.10.36.8 +biganswer.example8. 3600 IN A 10.10.36.9 +biganswer.example8. 3600 IN A 10.10.36.10 +biganswer.example8. 3600 IN A 10.10.36.11 +biganswer.example8. 3600 IN A 10.10.36.12 +biganswer.example8. 3600 IN A 10.10.36.13 +biganswer.example8. 3600 IN A 10.10.36.14 +biganswer.example8. 3600 IN A 10.10.36.15 +biganswer.example8. 3600 IN A 10.10.36.16 +biganswer.example8. 3600 IN A 10.10.36.17 +biganswer.example8. 3600 IN A 10.10.36.18 +biganswer.example8. 3600 IN A 10.10.36.19 +biganswer.example8. 3600 IN A 10.10.36.20 +biganswer.example8. 3600 IN A 10.10.36.21 +biganswer.example8. 3600 IN A 10.10.36.22 +biganswer.example8. 3600 IN A 10.10.36.23 +biganswer.example8. 3600 IN A 10.10.36.24 +biganswer.example8. 3600 IN A 10.10.36.25 +biganswer.example8. 3600 IN A 10.10.36.26 +biganswer.example8. 3600 IN A 10.10.36.27 +biganswer.example8. 3600 IN A 10.10.36.28 +biganswer.example8. 3600 IN A 10.10.36.29 +biganswer.example8. 3600 IN A 10.10.36.30 +biganswer.example8. 3600 IN A 10.10.36.31 +biganswer.example8. 3600 IN A 10.10.36.32 +biganswer.example8. 3600 IN A 10.10.36.33 +biganswer.example8. 3600 IN A 10.10.36.34 +biganswer.example8. 3600 IN A 10.10.36.35 +biganswer.example8. 3600 IN A 10.10.36.36 +biganswer.example8. 3600 IN A 10.10.36.37 +biganswer.example8. 3600 IN A 10.10.36.38 +biganswer.example8. 3600 IN A 10.10.36.39 +biganswer.example8. 3600 IN A 10.10.36.40 +biganswer.example8. 3600 IN A 10.10.36.41 +biganswer.example8. 3600 IN A 10.10.36.42 +biganswer.example8. 3600 IN A 10.10.36.43 +biganswer.example8. 3600 IN A 10.10.36.44 +biganswer.example8. 3600 IN A 10.10.36.45 +biganswer.example8. 3600 IN A 10.10.36.46 +biganswer.example8. 3600 IN A 10.10.36.47 +biganswer.example8. 3600 IN A 10.10.36.48 +biganswer.example8. 3600 IN A 10.10.36.49 +biganswer.example8. 3600 IN A 10.10.36.50 +biganswer.example8. 3600 IN A 10.10.37.1 +biganswer.example8. 3600 IN A 10.10.37.2 +biganswer.example8. 3600 IN A 10.10.37.3 +biganswer.example8. 3600 IN A 10.10.37.4 +biganswer.example8. 3600 IN A 10.10.37.5 +biganswer.example8. 3600 IN A 10.10.37.6 +biganswer.example8. 3600 IN A 10.10.37.7 +biganswer.example8. 3600 IN A 10.10.37.8 +biganswer.example8. 3600 IN A 10.10.37.9 +biganswer.example8. 3600 IN A 10.10.37.10 +biganswer.example8. 3600 IN A 10.10.37.11 +biganswer.example8. 3600 IN A 10.10.37.12 +biganswer.example8. 3600 IN A 10.10.37.13 +biganswer.example8. 3600 IN A 10.10.37.14 +biganswer.example8. 3600 IN A 10.10.37.15 +biganswer.example8. 3600 IN A 10.10.37.16 +biganswer.example8. 3600 IN A 10.10.37.17 +biganswer.example8. 3600 IN A 10.10.37.18 +biganswer.example8. 3600 IN A 10.10.37.19 +biganswer.example8. 3600 IN A 10.10.37.20 +biganswer.example8. 3600 IN A 10.10.37.21 +biganswer.example8. 3600 IN A 10.10.37.22 +biganswer.example8. 3600 IN A 10.10.37.23 +biganswer.example8. 3600 IN A 10.10.37.24 +biganswer.example8. 3600 IN A 10.10.37.25 +biganswer.example8. 3600 IN A 10.10.37.26 +biganswer.example8. 3600 IN A 10.10.37.27 +biganswer.example8. 3600 IN A 10.10.37.28 +biganswer.example8. 3600 IN A 10.10.37.29 +biganswer.example8. 3600 IN A 10.10.37.30 +biganswer.example8. 3600 IN A 10.10.37.31 +biganswer.example8. 3600 IN A 10.10.37.32 +biganswer.example8. 3600 IN A 10.10.37.33 +biganswer.example8. 3600 IN A 10.10.37.34 +biganswer.example8. 3600 IN A 10.10.37.35 +biganswer.example8. 3600 IN A 10.10.37.36 +biganswer.example8. 3600 IN A 10.10.37.37 +biganswer.example8. 3600 IN A 10.10.37.38 +biganswer.example8. 3600 IN A 10.10.37.39 +biganswer.example8. 3600 IN A 10.10.37.40 +biganswer.example8. 3600 IN A 10.10.37.41 +biganswer.example8. 3600 IN A 10.10.37.42 +biganswer.example8. 3600 IN A 10.10.37.43 +biganswer.example8. 3600 IN A 10.10.37.44 +biganswer.example8. 3600 IN A 10.10.37.45 +biganswer.example8. 3600 IN A 10.10.37.46 +biganswer.example8. 3600 IN A 10.10.37.47 +biganswer.example8. 3600 IN A 10.10.37.48 +biganswer.example8. 3600 IN A 10.10.37.49 +biganswer.example8. 3600 IN A 10.10.37.50 +biganswer.example8. 3600 IN A 10.10.38.1 +biganswer.example8. 3600 IN A 10.10.38.2 +biganswer.example8. 3600 IN A 10.10.38.3 +biganswer.example8. 3600 IN A 10.10.38.4 +biganswer.example8. 3600 IN A 10.10.38.5 +biganswer.example8. 3600 IN A 10.10.38.6 +biganswer.example8. 3600 IN A 10.10.38.7 +biganswer.example8. 3600 IN A 10.10.38.8 +biganswer.example8. 3600 IN A 10.10.38.9 +biganswer.example8. 3600 IN A 10.10.38.10 +biganswer.example8. 3600 IN A 10.10.38.11 +biganswer.example8. 3600 IN A 10.10.38.12 +biganswer.example8. 3600 IN A 10.10.38.13 +biganswer.example8. 3600 IN A 10.10.38.14 +biganswer.example8. 3600 IN A 10.10.38.15 +biganswer.example8. 3600 IN A 10.10.38.16 +biganswer.example8. 3600 IN A 10.10.38.17 +biganswer.example8. 3600 IN A 10.10.38.18 +biganswer.example8. 3600 IN A 10.10.38.19 +biganswer.example8. 3600 IN A 10.10.38.20 +biganswer.example8. 3600 IN A 10.10.38.21 +biganswer.example8. 3600 IN A 10.10.38.22 +biganswer.example8. 3600 IN A 10.10.38.23 +biganswer.example8. 3600 IN A 10.10.38.24 +biganswer.example8. 3600 IN A 10.10.38.25 +biganswer.example8. 3600 IN A 10.10.38.26 +biganswer.example8. 3600 IN A 10.10.38.27 +biganswer.example8. 3600 IN A 10.10.38.28 +biganswer.example8. 3600 IN A 10.10.38.29 +biganswer.example8. 3600 IN A 10.10.38.30 +biganswer.example8. 3600 IN A 10.10.38.31 +biganswer.example8. 3600 IN A 10.10.38.32 +biganswer.example8. 3600 IN A 10.10.38.33 +biganswer.example8. 3600 IN A 10.10.38.34 +biganswer.example8. 3600 IN A 10.10.38.35 +biganswer.example8. 3600 IN A 10.10.38.36 +biganswer.example8. 3600 IN A 10.10.38.37 +biganswer.example8. 3600 IN A 10.10.38.38 +biganswer.example8. 3600 IN A 10.10.38.39 +biganswer.example8. 3600 IN A 10.10.38.40 +biganswer.example8. 3600 IN A 10.10.38.41 +biganswer.example8. 3600 IN A 10.10.38.42 +biganswer.example8. 3600 IN A 10.10.38.43 +biganswer.example8. 3600 IN A 10.10.38.44 +biganswer.example8. 3600 IN A 10.10.38.45 +biganswer.example8. 3600 IN A 10.10.38.46 +biganswer.example8. 3600 IN A 10.10.38.47 +biganswer.example8. 3600 IN A 10.10.38.48 +biganswer.example8. 3600 IN A 10.10.38.49 +biganswer.example8. 3600 IN A 10.10.38.50 +biganswer.example8. 3600 IN A 10.10.39.1 +biganswer.example8. 3600 IN A 10.10.39.2 +biganswer.example8. 3600 IN A 10.10.39.3 +biganswer.example8. 3600 IN A 10.10.39.4 +biganswer.example8. 3600 IN A 10.10.39.5 +biganswer.example8. 3600 IN A 10.10.39.6 +biganswer.example8. 3600 IN A 10.10.39.7 +biganswer.example8. 3600 IN A 10.10.39.8 +biganswer.example8. 3600 IN A 10.10.39.9 +biganswer.example8. 3600 IN A 10.10.39.10 +biganswer.example8. 3600 IN A 10.10.39.11 +biganswer.example8. 3600 IN A 10.10.39.12 +biganswer.example8. 3600 IN A 10.10.39.13 +biganswer.example8. 3600 IN A 10.10.39.14 +biganswer.example8. 3600 IN A 10.10.39.15 +biganswer.example8. 3600 IN A 10.10.39.16 +biganswer.example8. 3600 IN A 10.10.39.17 +biganswer.example8. 3600 IN A 10.10.39.18 +biganswer.example8. 3600 IN A 10.10.39.19 +biganswer.example8. 3600 IN A 10.10.39.20 +biganswer.example8. 3600 IN A 10.10.39.21 +biganswer.example8. 3600 IN A 10.10.39.22 +biganswer.example8. 3600 IN A 10.10.39.23 +biganswer.example8. 3600 IN A 10.10.39.24 +biganswer.example8. 3600 IN A 10.10.39.25 +biganswer.example8. 3600 IN A 10.10.39.26 +biganswer.example8. 3600 IN A 10.10.39.27 +biganswer.example8. 3600 IN A 10.10.39.28 +biganswer.example8. 3600 IN A 10.10.39.29 +biganswer.example8. 3600 IN A 10.10.39.30 +biganswer.example8. 3600 IN A 10.10.39.31 +biganswer.example8. 3600 IN A 10.10.39.32 +biganswer.example8. 3600 IN A 10.10.39.33 +biganswer.example8. 3600 IN A 10.10.39.34 +biganswer.example8. 3600 IN A 10.10.39.35 +biganswer.example8. 3600 IN A 10.10.39.36 +biganswer.example8. 3600 IN A 10.10.39.37 +biganswer.example8. 3600 IN A 10.10.39.38 +biganswer.example8. 3600 IN A 10.10.39.39 +biganswer.example8. 3600 IN A 10.10.39.40 +biganswer.example8. 3600 IN A 10.10.39.41 +biganswer.example8. 3600 IN A 10.10.39.42 +biganswer.example8. 3600 IN A 10.10.39.43 +biganswer.example8. 3600 IN A 10.10.39.44 +biganswer.example8. 3600 IN A 10.10.39.45 +biganswer.example8. 3600 IN A 10.10.39.46 +biganswer.example8. 3600 IN A 10.10.39.47 +biganswer.example8. 3600 IN A 10.10.39.48 +biganswer.example8. 3600 IN A 10.10.39.49 +biganswer.example8. 3600 IN A 10.10.39.50 +biganswer.example8. 3600 IN A 10.10.40.1 +biganswer.example8. 3600 IN A 10.10.40.2 +biganswer.example8. 3600 IN A 10.10.40.3 +biganswer.example8. 3600 IN A 10.10.40.4 +biganswer.example8. 3600 IN A 10.10.40.5 +biganswer.example8. 3600 IN A 10.10.40.6 +biganswer.example8. 3600 IN A 10.10.40.7 +biganswer.example8. 3600 IN A 10.10.40.8 +biganswer.example8. 3600 IN A 10.10.40.9 +biganswer.example8. 3600 IN A 10.10.40.10 +biganswer.example8. 3600 IN A 10.10.40.11 +biganswer.example8. 3600 IN A 10.10.40.12 +biganswer.example8. 3600 IN A 10.10.40.13 +biganswer.example8. 3600 IN A 10.10.40.14 +biganswer.example8. 3600 IN A 10.10.40.15 +biganswer.example8. 3600 IN A 10.10.40.16 +biganswer.example8. 3600 IN A 10.10.40.17 +biganswer.example8. 3600 IN A 10.10.40.18 +biganswer.example8. 3600 IN A 10.10.40.19 +biganswer.example8. 3600 IN A 10.10.40.20 +biganswer.example8. 3600 IN A 10.10.40.21 +biganswer.example8. 3600 IN A 10.10.40.22 +biganswer.example8. 3600 IN A 10.10.40.23 +biganswer.example8. 3600 IN A 10.10.40.24 +biganswer.example8. 3600 IN A 10.10.40.25 +biganswer.example8. 3600 IN A 10.10.40.26 +biganswer.example8. 3600 IN A 10.10.40.27 +biganswer.example8. 3600 IN A 10.10.40.28 +biganswer.example8. 3600 IN A 10.10.40.29 +biganswer.example8. 3600 IN A 10.10.40.30 +biganswer.example8. 3600 IN A 10.10.40.31 +biganswer.example8. 3600 IN A 10.10.40.32 +biganswer.example8. 3600 IN A 10.10.40.33 +biganswer.example8. 3600 IN A 10.10.40.34 +biganswer.example8. 3600 IN A 10.10.40.35 +biganswer.example8. 3600 IN A 10.10.40.36 +biganswer.example8. 3600 IN A 10.10.40.37 +biganswer.example8. 3600 IN A 10.10.40.38 +biganswer.example8. 3600 IN A 10.10.40.39 +biganswer.example8. 3600 IN A 10.10.40.40 +biganswer.example8. 3600 IN A 10.10.40.41 +biganswer.example8. 3600 IN A 10.10.40.42 +biganswer.example8. 3600 IN A 10.10.40.43 +biganswer.example8. 3600 IN A 10.10.40.44 +biganswer.example8. 3600 IN A 10.10.40.45 +biganswer.example8. 3600 IN A 10.10.40.46 +biganswer.example8. 3600 IN A 10.10.40.47 +biganswer.example8. 3600 IN A 10.10.40.48 +biganswer.example8. 3600 IN A 10.10.40.49 +biganswer.example8. 3600 IN A 10.10.40.50 +biganswer.example8. 3600 IN A 10.10.41.1 +biganswer.example8. 3600 IN A 10.10.41.2 +biganswer.example8. 3600 IN A 10.10.41.3 +biganswer.example8. 3600 IN A 10.10.41.4 +biganswer.example8. 3600 IN A 10.10.41.5 +biganswer.example8. 3600 IN A 10.10.41.6 +biganswer.example8. 3600 IN A 10.10.41.7 +biganswer.example8. 3600 IN A 10.10.41.8 +biganswer.example8. 3600 IN A 10.10.41.9 +biganswer.example8. 3600 IN A 10.10.41.10 +biganswer.example8. 3600 IN A 10.10.41.11 +biganswer.example8. 3600 IN A 10.10.41.12 +biganswer.example8. 3600 IN A 10.10.41.13 +biganswer.example8. 3600 IN A 10.10.41.14 +biganswer.example8. 3600 IN A 10.10.41.15 +biganswer.example8. 3600 IN A 10.10.41.16 +biganswer.example8. 3600 IN A 10.10.41.17 +biganswer.example8. 3600 IN A 10.10.41.18 +biganswer.example8. 3600 IN A 10.10.41.19 +biganswer.example8. 3600 IN A 10.10.41.20 +biganswer.example8. 3600 IN A 10.10.41.21 +biganswer.example8. 3600 IN A 10.10.41.22 +biganswer.example8. 3600 IN A 10.10.41.23 +biganswer.example8. 3600 IN A 10.10.41.24 +biganswer.example8. 3600 IN A 10.10.41.25 +biganswer.example8. 3600 IN A 10.10.41.26 +biganswer.example8. 3600 IN A 10.10.41.27 +biganswer.example8. 3600 IN A 10.10.41.28 +biganswer.example8. 3600 IN A 10.10.41.29 +biganswer.example8. 3600 IN A 10.10.41.30 +biganswer.example8. 3600 IN A 10.10.41.31 +biganswer.example8. 3600 IN A 10.10.41.32 +biganswer.example8. 3600 IN A 10.10.41.33 +biganswer.example8. 3600 IN A 10.10.41.34 +biganswer.example8. 3600 IN A 10.10.41.35 +biganswer.example8. 3600 IN A 10.10.41.36 +biganswer.example8. 3600 IN A 10.10.41.37 +biganswer.example8. 3600 IN A 10.10.41.38 +biganswer.example8. 3600 IN A 10.10.41.39 +biganswer.example8. 3600 IN A 10.10.41.40 +biganswer.example8. 3600 IN A 10.10.41.41 +biganswer.example8. 3600 IN A 10.10.41.42 +biganswer.example8. 3600 IN A 10.10.41.43 +biganswer.example8. 3600 IN A 10.10.41.44 +biganswer.example8. 3600 IN A 10.10.41.45 +biganswer.example8. 3600 IN A 10.10.41.46 +biganswer.example8. 3600 IN A 10.10.41.47 +biganswer.example8. 3600 IN A 10.10.41.48 +biganswer.example8. 3600 IN A 10.10.41.49 +biganswer.example8. 3600 IN A 10.10.41.50 +biganswer.example8. 3600 IN A 10.10.42.1 +biganswer.example8. 3600 IN A 10.10.42.2 +biganswer.example8. 3600 IN A 10.10.42.3 +biganswer.example8. 3600 IN A 10.10.42.4 +biganswer.example8. 3600 IN A 10.10.42.5 +biganswer.example8. 3600 IN A 10.10.42.6 +biganswer.example8. 3600 IN A 10.10.42.7 +biganswer.example8. 3600 IN A 10.10.42.8 +biganswer.example8. 3600 IN A 10.10.42.9 +biganswer.example8. 3600 IN A 10.10.42.10 +biganswer.example8. 3600 IN A 10.10.42.11 +biganswer.example8. 3600 IN A 10.10.42.12 +biganswer.example8. 3600 IN A 10.10.42.13 +biganswer.example8. 3600 IN A 10.10.42.14 +biganswer.example8. 3600 IN A 10.10.42.15 +biganswer.example8. 3600 IN A 10.10.42.16 +biganswer.example8. 3600 IN A 10.10.42.17 +biganswer.example8. 3600 IN A 10.10.42.18 +biganswer.example8. 3600 IN A 10.10.42.19 +biganswer.example8. 3600 IN A 10.10.42.20 +biganswer.example8. 3600 IN A 10.10.42.21 +biganswer.example8. 3600 IN A 10.10.42.22 +biganswer.example8. 3600 IN A 10.10.42.23 +biganswer.example8. 3600 IN A 10.10.42.24 +biganswer.example8. 3600 IN A 10.10.42.25 +biganswer.example8. 3600 IN A 10.10.42.26 +biganswer.example8. 3600 IN A 10.10.42.27 +biganswer.example8. 3600 IN A 10.10.42.28 +biganswer.example8. 3600 IN A 10.10.42.29 +biganswer.example8. 3600 IN A 10.10.42.30 +biganswer.example8. 3600 IN A 10.10.42.31 +biganswer.example8. 3600 IN A 10.10.42.32 +biganswer.example8. 3600 IN A 10.10.42.33 +biganswer.example8. 3600 IN A 10.10.42.34 +biganswer.example8. 3600 IN A 10.10.42.35 +biganswer.example8. 3600 IN A 10.10.42.36 +biganswer.example8. 3600 IN A 10.10.42.37 +biganswer.example8. 3600 IN A 10.10.42.38 +biganswer.example8. 3600 IN A 10.10.42.39 +biganswer.example8. 3600 IN A 10.10.42.40 +biganswer.example8. 3600 IN A 10.10.42.41 +biganswer.example8. 3600 IN A 10.10.42.42 +biganswer.example8. 3600 IN A 10.10.42.43 +biganswer.example8. 3600 IN A 10.10.42.44 +biganswer.example8. 3600 IN A 10.10.42.45 +biganswer.example8. 3600 IN A 10.10.42.46 +biganswer.example8. 3600 IN A 10.10.42.47 +biganswer.example8. 3600 IN A 10.10.42.48 +biganswer.example8. 3600 IN A 10.10.42.49 +biganswer.example8. 3600 IN A 10.10.42.50 +biganswer.example8. 3600 IN A 10.10.43.1 +biganswer.example8. 3600 IN A 10.10.43.2 +biganswer.example8. 3600 IN A 10.10.43.3 +biganswer.example8. 3600 IN A 10.10.43.4 +biganswer.example8. 3600 IN A 10.10.43.5 +biganswer.example8. 3600 IN A 10.10.43.6 +biganswer.example8. 3600 IN A 10.10.43.7 +biganswer.example8. 3600 IN A 10.10.43.8 +biganswer.example8. 3600 IN A 10.10.43.9 +biganswer.example8. 3600 IN A 10.10.43.10 +biganswer.example8. 3600 IN A 10.10.43.11 +biganswer.example8. 3600 IN A 10.10.43.12 +biganswer.example8. 3600 IN A 10.10.43.13 +biganswer.example8. 3600 IN A 10.10.43.14 +biganswer.example8. 3600 IN A 10.10.43.15 +biganswer.example8. 3600 IN A 10.10.43.16 +biganswer.example8. 3600 IN A 10.10.43.17 +biganswer.example8. 3600 IN A 10.10.43.18 +biganswer.example8. 3600 IN A 10.10.43.19 +biganswer.example8. 3600 IN A 10.10.43.20 +biganswer.example8. 3600 IN A 10.10.43.21 +biganswer.example8. 3600 IN A 10.10.43.22 +biganswer.example8. 3600 IN A 10.10.43.23 +biganswer.example8. 3600 IN A 10.10.43.24 +biganswer.example8. 3600 IN A 10.10.43.25 +biganswer.example8. 3600 IN A 10.10.43.26 +biganswer.example8. 3600 IN A 10.10.43.27 +biganswer.example8. 3600 IN A 10.10.43.28 +biganswer.example8. 3600 IN A 10.10.43.29 +biganswer.example8. 3600 IN A 10.10.43.30 +biganswer.example8. 3600 IN A 10.10.43.31 +biganswer.example8. 3600 IN A 10.10.43.32 +biganswer.example8. 3600 IN A 10.10.43.33 +biganswer.example8. 3600 IN A 10.10.43.34 +biganswer.example8. 3600 IN A 10.10.43.35 +biganswer.example8. 3600 IN A 10.10.43.36 +biganswer.example8. 3600 IN A 10.10.43.37 +biganswer.example8. 3600 IN A 10.10.43.38 +biganswer.example8. 3600 IN A 10.10.43.39 +biganswer.example8. 3600 IN A 10.10.43.40 +biganswer.example8. 3600 IN A 10.10.43.41 +biganswer.example8. 3600 IN A 10.10.43.42 +biganswer.example8. 3600 IN A 10.10.43.43 +biganswer.example8. 3600 IN A 10.10.43.44 +biganswer.example8. 3600 IN A 10.10.43.45 +biganswer.example8. 3600 IN A 10.10.43.46 +biganswer.example8. 3600 IN A 10.10.43.47 +biganswer.example8. 3600 IN A 10.10.43.48 +biganswer.example8. 3600 IN A 10.10.43.49 +biganswer.example8. 3600 IN A 10.10.43.50 +biganswer.example8. 3600 IN A 10.10.44.1 +biganswer.example8. 3600 IN A 10.10.44.2 +biganswer.example8. 3600 IN A 10.10.44.3 +biganswer.example8. 3600 IN A 10.10.44.4 +biganswer.example8. 3600 IN A 10.10.44.5 +biganswer.example8. 3600 IN A 10.10.44.6 +biganswer.example8. 3600 IN A 10.10.44.7 +biganswer.example8. 3600 IN A 10.10.44.8 +biganswer.example8. 3600 IN A 10.10.44.9 +biganswer.example8. 3600 IN A 10.10.44.10 +biganswer.example8. 3600 IN A 10.10.44.11 +biganswer.example8. 3600 IN A 10.10.44.12 +biganswer.example8. 3600 IN A 10.10.44.13 +biganswer.example8. 3600 IN A 10.10.44.14 +biganswer.example8. 3600 IN A 10.10.44.15 +biganswer.example8. 3600 IN A 10.10.44.16 +biganswer.example8. 3600 IN A 10.10.44.17 +biganswer.example8. 3600 IN A 10.10.44.18 +biganswer.example8. 3600 IN A 10.10.44.19 +biganswer.example8. 3600 IN A 10.10.44.20 +biganswer.example8. 3600 IN A 10.10.44.21 +biganswer.example8. 3600 IN A 10.10.44.22 +biganswer.example8. 3600 IN A 10.10.44.23 +biganswer.example8. 3600 IN A 10.10.44.24 +biganswer.example8. 3600 IN A 10.10.44.25 +biganswer.example8. 3600 IN A 10.10.44.26 +biganswer.example8. 3600 IN A 10.10.44.27 +biganswer.example8. 3600 IN A 10.10.44.28 +biganswer.example8. 3600 IN A 10.10.44.29 +biganswer.example8. 3600 IN A 10.10.44.30 +biganswer.example8. 3600 IN A 10.10.44.31 +biganswer.example8. 3600 IN A 10.10.44.32 +biganswer.example8. 3600 IN A 10.10.44.33 +biganswer.example8. 3600 IN A 10.10.44.34 +biganswer.example8. 3600 IN A 10.10.44.35 +biganswer.example8. 3600 IN A 10.10.44.36 +biganswer.example8. 3600 IN A 10.10.44.37 +biganswer.example8. 3600 IN A 10.10.44.38 +biganswer.example8. 3600 IN A 10.10.44.39 +biganswer.example8. 3600 IN A 10.10.44.40 +biganswer.example8. 3600 IN A 10.10.44.41 +biganswer.example8. 3600 IN A 10.10.44.42 +biganswer.example8. 3600 IN A 10.10.44.43 +biganswer.example8. 3600 IN A 10.10.44.44 +biganswer.example8. 3600 IN A 10.10.44.45 +biganswer.example8. 3600 IN A 10.10.44.46 +biganswer.example8. 3600 IN A 10.10.44.47 +biganswer.example8. 3600 IN A 10.10.44.48 +biganswer.example8. 3600 IN A 10.10.44.49 +biganswer.example8. 3600 IN A 10.10.44.50 +biganswer.example8. 3600 IN A 10.10.45.1 +biganswer.example8. 3600 IN A 10.10.45.2 +biganswer.example8. 3600 IN A 10.10.45.3 +biganswer.example8. 3600 IN A 10.10.45.4 +biganswer.example8. 3600 IN A 10.10.45.5 +biganswer.example8. 3600 IN A 10.10.45.6 +biganswer.example8. 3600 IN A 10.10.45.7 +biganswer.example8. 3600 IN A 10.10.45.8 +biganswer.example8. 3600 IN A 10.10.45.9 +biganswer.example8. 3600 IN A 10.10.45.10 +biganswer.example8. 3600 IN A 10.10.45.11 +biganswer.example8. 3600 IN A 10.10.45.12 +biganswer.example8. 3600 IN A 10.10.45.13 +biganswer.example8. 3600 IN A 10.10.45.14 +biganswer.example8. 3600 IN A 10.10.45.15 +biganswer.example8. 3600 IN A 10.10.45.16 +biganswer.example8. 3600 IN A 10.10.45.17 +biganswer.example8. 3600 IN A 10.10.45.18 +biganswer.example8. 3600 IN A 10.10.45.19 +biganswer.example8. 3600 IN A 10.10.45.20 +biganswer.example8. 3600 IN A 10.10.45.21 +biganswer.example8. 3600 IN A 10.10.45.22 +biganswer.example8. 3600 IN A 10.10.45.23 +biganswer.example8. 3600 IN A 10.10.45.24 +biganswer.example8. 3600 IN A 10.10.45.25 +biganswer.example8. 3600 IN A 10.10.45.26 +biganswer.example8. 3600 IN A 10.10.45.27 +biganswer.example8. 3600 IN A 10.10.45.28 +biganswer.example8. 3600 IN A 10.10.45.29 +biganswer.example8. 3600 IN A 10.10.45.30 +biganswer.example8. 3600 IN A 10.10.45.31 +biganswer.example8. 3600 IN A 10.10.45.32 +biganswer.example8. 3600 IN A 10.10.45.33 +biganswer.example8. 3600 IN A 10.10.45.34 +biganswer.example8. 3600 IN A 10.10.45.35 +biganswer.example8. 3600 IN A 10.10.45.36 +biganswer.example8. 3600 IN A 10.10.45.37 +biganswer.example8. 3600 IN A 10.10.45.38 +biganswer.example8. 3600 IN A 10.10.45.39 +biganswer.example8. 3600 IN A 10.10.45.40 +biganswer.example8. 3600 IN A 10.10.45.41 +biganswer.example8. 3600 IN A 10.10.45.42 +biganswer.example8. 3600 IN A 10.10.45.43 +biganswer.example8. 3600 IN A 10.10.45.44 +biganswer.example8. 3600 IN A 10.10.45.45 +biganswer.example8. 3600 IN A 10.10.45.46 +biganswer.example8. 3600 IN A 10.10.45.47 +biganswer.example8. 3600 IN A 10.10.45.48 +biganswer.example8. 3600 IN A 10.10.45.49 +biganswer.example8. 3600 IN A 10.10.45.50 +biganswer.example8. 3600 IN A 10.10.46.1 +biganswer.example8. 3600 IN A 10.10.46.2 +biganswer.example8. 3600 IN A 10.10.46.3 +biganswer.example8. 3600 IN A 10.10.46.4 +biganswer.example8. 3600 IN A 10.10.46.5 +biganswer.example8. 3600 IN A 10.10.46.6 +biganswer.example8. 3600 IN A 10.10.46.7 +biganswer.example8. 3600 IN A 10.10.46.8 +biganswer.example8. 3600 IN A 10.10.46.9 +biganswer.example8. 3600 IN A 10.10.46.10 +biganswer.example8. 3600 IN A 10.10.46.11 +biganswer.example8. 3600 IN A 10.10.46.12 +biganswer.example8. 3600 IN A 10.10.46.13 +biganswer.example8. 3600 IN A 10.10.46.14 +biganswer.example8. 3600 IN A 10.10.46.15 +biganswer.example8. 3600 IN A 10.10.46.16 +biganswer.example8. 3600 IN A 10.10.46.17 +biganswer.example8. 3600 IN A 10.10.46.18 +biganswer.example8. 3600 IN A 10.10.46.19 +biganswer.example8. 3600 IN A 10.10.46.20 +biganswer.example8. 3600 IN A 10.10.46.21 +biganswer.example8. 3600 IN A 10.10.46.22 +biganswer.example8. 3600 IN A 10.10.46.23 +biganswer.example8. 3600 IN A 10.10.46.24 +biganswer.example8. 3600 IN A 10.10.46.25 +biganswer.example8. 3600 IN A 10.10.46.26 +biganswer.example8. 3600 IN A 10.10.46.27 +biganswer.example8. 3600 IN A 10.10.46.28 +biganswer.example8. 3600 IN A 10.10.46.29 +biganswer.example8. 3600 IN A 10.10.46.30 +biganswer.example8. 3600 IN A 10.10.46.31 +biganswer.example8. 3600 IN A 10.10.46.32 +biganswer.example8. 3600 IN A 10.10.46.33 +biganswer.example8. 3600 IN A 10.10.46.34 +biganswer.example8. 3600 IN A 10.10.46.35 +biganswer.example8. 3600 IN A 10.10.46.36 +biganswer.example8. 3600 IN A 10.10.46.37 +biganswer.example8. 3600 IN A 10.10.46.38 +biganswer.example8. 3600 IN A 10.10.46.39 +biganswer.example8. 3600 IN A 10.10.46.40 +biganswer.example8. 3600 IN A 10.10.46.41 +biganswer.example8. 3600 IN A 10.10.46.42 +biganswer.example8. 3600 IN A 10.10.46.43 +biganswer.example8. 3600 IN A 10.10.46.44 +biganswer.example8. 3600 IN A 10.10.46.45 +biganswer.example8. 3600 IN A 10.10.46.46 +biganswer.example8. 3600 IN A 10.10.46.47 +biganswer.example8. 3600 IN A 10.10.46.48 +biganswer.example8. 3600 IN A 10.10.46.49 +biganswer.example8. 3600 IN A 10.10.46.50 +biganswer.example8. 3600 IN A 10.10.47.1 +biganswer.example8. 3600 IN A 10.10.47.2 +biganswer.example8. 3600 IN A 10.10.47.3 +biganswer.example8. 3600 IN A 10.10.47.4 +biganswer.example8. 3600 IN A 10.10.47.5 +biganswer.example8. 3600 IN A 10.10.47.6 +biganswer.example8. 3600 IN A 10.10.47.7 +biganswer.example8. 3600 IN A 10.10.47.8 +biganswer.example8. 3600 IN A 10.10.47.9 +biganswer.example8. 3600 IN A 10.10.47.10 +biganswer.example8. 3600 IN A 10.10.47.11 +biganswer.example8. 3600 IN A 10.10.47.12 +biganswer.example8. 3600 IN A 10.10.47.13 +biganswer.example8. 3600 IN A 10.10.47.14 +biganswer.example8. 3600 IN A 10.10.47.15 +biganswer.example8. 3600 IN A 10.10.47.16 +biganswer.example8. 3600 IN A 10.10.47.17 +biganswer.example8. 3600 IN A 10.10.47.18 +biganswer.example8. 3600 IN A 10.10.47.19 +biganswer.example8. 3600 IN A 10.10.47.20 +biganswer.example8. 3600 IN A 10.10.47.21 +biganswer.example8. 3600 IN A 10.10.47.22 +biganswer.example8. 3600 IN A 10.10.47.23 +biganswer.example8. 3600 IN A 10.10.47.24 +biganswer.example8. 3600 IN A 10.10.47.25 +biganswer.example8. 3600 IN A 10.10.47.26 +biganswer.example8. 3600 IN A 10.10.47.27 +biganswer.example8. 3600 IN A 10.10.47.28 +biganswer.example8. 3600 IN A 10.10.47.29 +biganswer.example8. 3600 IN A 10.10.47.30 +biganswer.example8. 3600 IN A 10.10.47.31 +biganswer.example8. 3600 IN A 10.10.47.32 +biganswer.example8. 3600 IN A 10.10.47.33 +biganswer.example8. 3600 IN A 10.10.47.34 +biganswer.example8. 3600 IN A 10.10.47.35 +biganswer.example8. 3600 IN A 10.10.47.36 +biganswer.example8. 3600 IN A 10.10.47.37 +biganswer.example8. 3600 IN A 10.10.47.38 +biganswer.example8. 3600 IN A 10.10.47.39 +biganswer.example8. 3600 IN A 10.10.47.40 +biganswer.example8. 3600 IN A 10.10.47.41 +biganswer.example8. 3600 IN A 10.10.47.42 +biganswer.example8. 3600 IN A 10.10.47.43 +biganswer.example8. 3600 IN A 10.10.47.44 +biganswer.example8. 3600 IN A 10.10.47.45 +biganswer.example8. 3600 IN A 10.10.47.46 +biganswer.example8. 3600 IN A 10.10.47.47 +biganswer.example8. 3600 IN A 10.10.47.48 +biganswer.example8. 3600 IN A 10.10.47.49 +biganswer.example8. 3600 IN A 10.10.47.50 +biganswer.example8. 3600 IN A 10.10.48.1 +biganswer.example8. 3600 IN A 10.10.48.2 +biganswer.example8. 3600 IN A 10.10.48.3 +biganswer.example8. 3600 IN A 10.10.48.4 +biganswer.example8. 3600 IN A 10.10.48.5 +biganswer.example8. 3600 IN A 10.10.48.6 +biganswer.example8. 3600 IN A 10.10.48.7 +biganswer.example8. 3600 IN A 10.10.48.8 +biganswer.example8. 3600 IN A 10.10.48.9 +biganswer.example8. 3600 IN A 10.10.48.10 +biganswer.example8. 3600 IN A 10.10.48.11 +biganswer.example8. 3600 IN A 10.10.48.12 +biganswer.example8. 3600 IN A 10.10.48.13 +biganswer.example8. 3600 IN A 10.10.48.14 +biganswer.example8. 3600 IN A 10.10.48.15 +biganswer.example8. 3600 IN A 10.10.48.16 +biganswer.example8. 3600 IN A 10.10.48.17 +biganswer.example8. 3600 IN A 10.10.48.18 +biganswer.example8. 3600 IN A 10.10.48.19 +biganswer.example8. 3600 IN A 10.10.48.20 +biganswer.example8. 3600 IN A 10.10.48.21 +biganswer.example8. 3600 IN A 10.10.48.22 +biganswer.example8. 3600 IN A 10.10.48.23 +biganswer.example8. 3600 IN A 10.10.48.24 +biganswer.example8. 3600 IN A 10.10.48.25 +biganswer.example8. 3600 IN A 10.10.48.26 +biganswer.example8. 3600 IN A 10.10.48.27 +biganswer.example8. 3600 IN A 10.10.48.28 +biganswer.example8. 3600 IN A 10.10.48.29 +biganswer.example8. 3600 IN A 10.10.48.30 +biganswer.example8. 3600 IN A 10.10.48.31 +biganswer.example8. 3600 IN A 10.10.48.32 +biganswer.example8. 3600 IN A 10.10.48.33 +biganswer.example8. 3600 IN A 10.10.48.34 +biganswer.example8. 3600 IN A 10.10.48.35 +biganswer.example8. 3600 IN A 10.10.48.36 +biganswer.example8. 3600 IN A 10.10.48.37 +biganswer.example8. 3600 IN A 10.10.48.38 +biganswer.example8. 3600 IN A 10.10.48.39 +biganswer.example8. 3600 IN A 10.10.48.40 +biganswer.example8. 3600 IN A 10.10.48.41 +biganswer.example8. 3600 IN A 10.10.48.42 +biganswer.example8. 3600 IN A 10.10.48.43 +biganswer.example8. 3600 IN A 10.10.48.44 +biganswer.example8. 3600 IN A 10.10.48.45 +biganswer.example8. 3600 IN A 10.10.48.46 +biganswer.example8. 3600 IN A 10.10.48.47 +biganswer.example8. 3600 IN A 10.10.48.48 +biganswer.example8. 3600 IN A 10.10.48.49 +biganswer.example8. 3600 IN A 10.10.48.50 +biganswer.example8. 3600 IN A 10.10.49.1 +biganswer.example8. 3600 IN A 10.10.49.2 +biganswer.example8. 3600 IN A 10.10.49.3 +biganswer.example8. 3600 IN A 10.10.49.4 +biganswer.example8. 3600 IN A 10.10.49.5 +biganswer.example8. 3600 IN A 10.10.49.6 +biganswer.example8. 3600 IN A 10.10.49.7 +biganswer.example8. 3600 IN A 10.10.49.8 +biganswer.example8. 3600 IN A 10.10.49.9 +biganswer.example8. 3600 IN A 10.10.49.10 +biganswer.example8. 3600 IN A 10.10.49.11 +biganswer.example8. 3600 IN A 10.10.49.12 +biganswer.example8. 3600 IN A 10.10.49.13 +biganswer.example8. 3600 IN A 10.10.49.14 +biganswer.example8. 3600 IN A 10.10.49.15 +biganswer.example8. 3600 IN A 10.10.49.16 +biganswer.example8. 3600 IN A 10.10.49.17 +biganswer.example8. 3600 IN A 10.10.49.18 +biganswer.example8. 3600 IN A 10.10.49.19 +biganswer.example8. 3600 IN A 10.10.49.20 +biganswer.example8. 3600 IN A 10.10.49.21 +biganswer.example8. 3600 IN A 10.10.49.22 +biganswer.example8. 3600 IN A 10.10.49.23 +biganswer.example8. 3600 IN A 10.10.49.24 +biganswer.example8. 3600 IN A 10.10.49.25 +biganswer.example8. 3600 IN A 10.10.49.26 +biganswer.example8. 3600 IN A 10.10.49.27 +biganswer.example8. 3600 IN A 10.10.49.28 +biganswer.example8. 3600 IN A 10.10.49.29 +biganswer.example8. 3600 IN A 10.10.49.30 +biganswer.example8. 3600 IN A 10.10.49.31 +biganswer.example8. 3600 IN A 10.10.49.32 +biganswer.example8. 3600 IN A 10.10.49.33 +biganswer.example8. 3600 IN A 10.10.49.34 +biganswer.example8. 3600 IN A 10.10.49.35 +biganswer.example8. 3600 IN A 10.10.49.36 +biganswer.example8. 3600 IN A 10.10.49.37 +biganswer.example8. 3600 IN A 10.10.49.38 +biganswer.example8. 3600 IN A 10.10.49.39 +biganswer.example8. 3600 IN A 10.10.49.40 +biganswer.example8. 3600 IN A 10.10.49.41 +biganswer.example8. 3600 IN A 10.10.49.42 +biganswer.example8. 3600 IN A 10.10.49.43 +biganswer.example8. 3600 IN A 10.10.49.44 +biganswer.example8. 3600 IN A 10.10.49.45 +biganswer.example8. 3600 IN A 10.10.49.46 +biganswer.example8. 3600 IN A 10.10.49.47 +biganswer.example8. 3600 IN A 10.10.49.48 +biganswer.example8. 3600 IN A 10.10.49.49 +biganswer.example8. 3600 IN A 10.10.49.50 +biganswer.example8. 3600 IN A 10.10.50.1 +biganswer.example8. 3600 IN A 10.10.50.2 +biganswer.example8. 3600 IN A 10.10.50.3 +biganswer.example8. 3600 IN A 10.10.50.4 +biganswer.example8. 3600 IN A 10.10.50.5 +biganswer.example8. 3600 IN A 10.10.50.6 +biganswer.example8. 3600 IN A 10.10.50.7 +biganswer.example8. 3600 IN A 10.10.50.8 +biganswer.example8. 3600 IN A 10.10.50.9 +biganswer.example8. 3600 IN A 10.10.50.10 +biganswer.example8. 3600 IN A 10.10.50.11 +biganswer.example8. 3600 IN A 10.10.50.12 +biganswer.example8. 3600 IN A 10.10.50.13 +biganswer.example8. 3600 IN A 10.10.50.14 +biganswer.example8. 3600 IN A 10.10.50.15 +biganswer.example8. 3600 IN A 10.10.50.16 +biganswer.example8. 3600 IN A 10.10.50.17 +biganswer.example8. 3600 IN A 10.10.50.18 +biganswer.example8. 3600 IN A 10.10.50.19 +biganswer.example8. 3600 IN A 10.10.50.20 +biganswer.example8. 3600 IN A 10.10.50.21 +biganswer.example8. 3600 IN A 10.10.50.22 +biganswer.example8. 3600 IN A 10.10.50.23 +biganswer.example8. 3600 IN A 10.10.50.24 +biganswer.example8. 3600 IN A 10.10.50.25 +biganswer.example8. 3600 IN A 10.10.50.26 +biganswer.example8. 3600 IN A 10.10.50.27 +biganswer.example8. 3600 IN A 10.10.50.28 +biganswer.example8. 3600 IN A 10.10.50.29 +biganswer.example8. 3600 IN A 10.10.50.30 +biganswer.example8. 3600 IN A 10.10.50.31 +biganswer.example8. 3600 IN A 10.10.50.32 +biganswer.example8. 3600 IN A 10.10.50.33 +biganswer.example8. 3600 IN A 10.10.50.34 +biganswer.example8. 3600 IN A 10.10.50.35 +biganswer.example8. 3600 IN A 10.10.50.36 +biganswer.example8. 3600 IN A 10.10.50.37 +biganswer.example8. 3600 IN A 10.10.50.38 +biganswer.example8. 3600 IN A 10.10.50.39 +biganswer.example8. 3600 IN A 10.10.50.40 +biganswer.example8. 3600 IN A 10.10.50.41 +biganswer.example8. 3600 IN A 10.10.50.42 +biganswer.example8. 3600 IN A 10.10.50.43 +biganswer.example8. 3600 IN A 10.10.50.44 +biganswer.example8. 3600 IN A 10.10.50.45 +biganswer.example8. 3600 IN A 10.10.50.46 +biganswer.example8. 3600 IN A 10.10.50.47 +biganswer.example8. 3600 IN A 10.10.50.48 +biganswer.example8. 3600 IN A 10.10.50.49 +biganswer.example8. 3600 IN A 10.10.50.50 +caa01.example8. 3600 IN CAA 0 issue "ca.example.net; policy=ev" +caa02.example8. 3600 IN CAA 128 tbs "Unknown" +caa03.example8. 3600 IN CAA 128 tbs "" +cdnskey01.example8. 3600 IN CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +cds01.example8. 3600 IN CDS 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +cert01.example8. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +cname01.example8. 3600 IN CNAME cname-target. +cname02.example8. 3600 IN CNAME cname-target.example8. +cname03.example8. 3600 IN CNAME . +csync01.example8. 3600 IN CSYNC 0 0 A NS AAAA +csync02.example8. 3600 IN CSYNC 0 0 +dhcid01.example8. 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA= +dhcid02.example8. 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdWL3b/NaiUDlW2No= +dhcid03.example8. 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6VytcKD//7es/deY= +dlv.example8. 3600 IN DLV 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +dname01.example8. 3600 IN DNAME dname-target. +dname02.example8. 3600 IN DNAME dname-target.example8. +dname03.example8. 3600 IN DNAME . +doa01.example8. 3600 IN DOA 1234567890 1234567890 1 "image/gif" R0lGODlhKAAZAOMCAGZmZgBmmf///zOZzMz//5nM/zNmmWbM/5nMzMzMzACZ/////////////////////yH5BAEKAA8ALAAAAAAoABkAAATH8IFJK5U2a4337F5ogRkpnoCJrly7PrCKyh8c3HgAhzT35MDbbtO7/IJIHbGiOiaTxVTpSVWWLqNq1UVyapNS1wd3OAxug0LhnCubcVhsxysQnOt4ATpvvzHlFzl1AwODhWeFAgRpen5/UhheAYMFdUB4SFcpGEGGdQeCAqBBLTuSk30EeXd9pEsAbKGxjHqDSE0Sp6ixN4N1BJmbc7lIhmsBich1awPAjkY1SZR8bJWrz382SGqIBQQFQd4IsUTaX+ceuudPEQA7 +doa02.example8. 3600 IN DOA 0 1 2 "" aHR0cHM6Ly93d3cuaXNjLm9yZy8= +ds01.example8. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13 +ds01.example8. 3600 IN NS ns42.example8. +ds02.example8. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390 +ds02.example8. 3600 IN NS ns43.example8. +eid01.example8. 3600 IN EID 1289AB +eui48.example8. 3600 IN EUI48 01-23-45-67-89-ab +eui64.example8. 3600 IN EUI64 01-23-45-67-89-ab-cd-ef +gid01.example8. 3600 IN GID \# 1 03 +gpos01.example8. 3600 IN GPOS "-22.6882" "116.8652" "250.0" +gpos02.example8. 3600 IN GPOS "" "" "" +hinfo01.example8. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02.example8. 3600 IN HINFO "PC" "NetBSD" +hip1.example8. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D +hip2.example8. 3600 IN HIP 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs.example.com. +https0.example8. 3600 IN HTTPS 0 example.net. +https1.example8. 3600 IN HTTPS 1 . port=60 +ipseckey01.example8. 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey02.example8. 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey03.example8. 3600 IN IPSECKEY 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey04.example8. 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +ipseckey05.example8. 3600 IN IPSECKEY 10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== +isdn01.example8. 3600 IN ISDN "isdn-address" +isdn02.example8. 3600 IN ISDN "isdn-address" "subaddress" +isdn03.example8. 3600 IN ISDN "isdn-address" +isdn04.example8. 3600 IN ISDN "isdn-address" "subaddress" +keydata.example8. 3600 IN TYPE65533 \# 0 +keydata.example8. 3600 IN TYPE65533 \# 6 010203040506 +keydata.example8. 3600 IN TYPE65533 \# 18 010203040506010203040506010203040506 +kx01.example8. 3600 IN KX 10 kdc.example8. +kx02.example8. 3600 IN KX 10 . +l32.example8. 3600 IN L32 10 1.2.3.4 +l64.example8. 3600 IN L64 10 14:4fff:ff20:ee64 +loc01.example8. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02.example8. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +lp.example8. 3600 IN LP 10 example.net. +mb01.example8. 3600 IN MG madname.example8. +mb02.example8. 3600 IN MG . +mg01.example8. 3600 IN MG mgmname.example8. +mg02.example8. 3600 IN MG . +minfo01.example8. 3600 IN MINFO rmailbx.example8. emailbx.example8. +minfo02.example8. 3600 IN MINFO . . +mr01.example8. 3600 IN MR mrname.example8. +mr02.example8. 3600 IN MR . +mx01.example8. 3600 IN MX 10 mail.example8. +mx02.example8. 3600 IN MX 10 . +naptr01.example8. 3600 IN NAPTR 0 0 "" "" "" . +naptr02.example8. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nid.example8. 3600 IN NID 10 14:4fff:ff20:ee64 +nimloc01.example8. 3600 IN NIMLOC 1289AB +ninfo01.example8. 3600 IN NINFO "foo" +ninfo02.example8. 3600 IN NINFO "foo" "bar" +ninfo03.example8. 3600 IN NINFO "foo" +ninfo04.example8. 3600 IN NINFO "foo" "bar" +ninfo05.example8. 3600 IN NINFO "foo bar" +ninfo06.example8. 3600 IN NINFO "foo bar" +ninfo07.example8. 3600 IN NINFO "foo bar" +ninfo08.example8. 3600 IN NINFO "foo\010bar" +ninfo09.example8. 3600 IN NINFO "foo\010bar" +ninfo10.example8. 3600 IN NINFO "foo bar" +ninfo11.example8. 3600 IN NINFO "\"foo\"" +ninfo12.example8. 3600 IN NINFO "\"foo\"" +ninfo13.example8. 3600 IN NINFO "foo;" +ninfo14.example8. 3600 IN NINFO "foo;" +ninfo15.example8. 3600 IN NINFO "bar\\;" +ns2.example8. 3600 IN A 10.53.0.2 +nsap-ptr01.example8. 3600 IN NSAP-PTR foo. +nsap-ptr01.example8. 3600 IN NSAP-PTR . +nsap01.example8. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02.example8. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsec01.example8. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY +nsec02.example8. 3600 IN NSEC . NSAP-PTR NSEC +nsec03.example8. 3600 IN NSEC . A +nsec04.example8. 3600 IN NSEC . TYPE127 +openpgpkey.example8. 3600 IN OPENPGPKEY AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +ptr01.example8. 3600 IN PTR example8. +px01.example8. 3600 IN PX 65535 foo. bar. +px02.example8. 3600 IN PX 65535 . . +resinfo.example8. 3600 IN RESINFO "qnamemin" "exterr=15,16,17" "infourl=https://resolver.example.com/guide" +rkey01.example8. 3600 IN RKEY 0 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +rp01.example8. 3600 IN RP mbox-dname.example8. txt-dname.example8. +rp02.example8. 3600 IN RP . . +rrsig01.example8. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +rt01.example8. 3600 IN RT 0 intermediate-host.example8. +rt02.example8. 3600 IN RT 65535 . +sink01.example8. 3600 IN SINK 1 0 0 +sink02.example8. 3600 IN SINK 8 0 2 l4ik +smimea.example8. 3600 IN SMIMEA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC +spf01.example8. 3600 IN SPF "v=spf1 -all" +spf02.example8. 3600 IN SPF "v=spf1" " -all" +srv01.example8. 3600 IN SRV 0 0 0 . +srv02.example8. 3600 IN SRV 65535 65535 65535 old-slow-box.example8. +sshfp01.example8. 3600 IN SSHFP 4 2 C76D8329954DA2835751E371544E963EFDA099080D6C58DD2BFD9A31 6E162C83 +sshfp02.example8. 3600 IN SSHFP 1 2 BF29468C83AC58CCF8C85AB7B3BEB054ECF1E38512B8353AB36471FA 88961DCC +svcb0.example8. 3600 IN SVCB 0 example.net. +svcb1.example8. 3600 IN SVCB 1 . port=60 +ta.example8. 3600 IN TA 30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 +talink0.example8. 3600 IN TALINK . talink1.example8. +talink1.example8. 3600 IN TALINK talink0.example8. talink2.example8. +talink2.example8. 3600 IN TALINK talink2.example8. . +tlsa.example8. 3600 IN TLSA 1 1 2 92003BA34942DC74152E2F2C408D29ECA5A520E7F2E06BB944F4DCA3 46BAF63C1B177615D466F6C4B71C216A50292BD58C9EBDD2F74E38FE 51FFD48C43326CBC +txt01.example8. 3600 IN TXT "foo" +txt02.example8. 3600 IN TXT "foo" "bar" +txt03.example8. 3600 IN TXT "foo" +txt04.example8. 3600 IN TXT "foo" "bar" +txt05.example8. 3600 IN TXT "foo bar" +txt06.example8. 3600 IN TXT "foo bar" +txt07.example8. 3600 IN TXT "foo bar" +txt08.example8. 3600 IN TXT "foo\010bar" +txt09.example8. 3600 IN TXT "foo\010bar" +txt10.example8. 3600 IN TXT "foo bar" +txt11.example8. 3600 IN TXT "\"foo\"" +txt12.example8. 3600 IN TXT "\"foo\"" +txt13.example8. 3600 IN TXT "foo;" +txt14.example8. 3600 IN TXT "foo;" +txt15.example8. 3600 IN TXT "bar\\;" +uid01.example8. 3600 IN UID \# 1 02 +uinfo01.example8. 3600 IN UINFO \# 1 01 +unspec01.example8. 3600 IN UNSPEC \# 1 04 +uri01.example8. 3600 IN URI 10 20 "https://www.isc.org/" +uri02.example8. 3600 IN URI 30 40 "https://www.isc.org/HolyCowThisSureIsAVeryLongURIRecordIDontEvenKnowWhatSomeoneWouldEverWantWithSuchAThingButTheSpecificationRequiresThatWesupportItSoHereWeGoTestingItLaLaLaLaLaLaLaSeriouslyThoughWhyWouldYouEvenConsiderUsingAURIThisLongItSeemsLikeASillyIdeaButEnhWhatAreYouGonnaDo/" +uri03.example8. 3600 IN URI 30 40 "" +wallet.example8. 3600 IN WALLET "currency-identifer" "wallet-identifier" +wallet-multiple.example8. 3600 IN WALLET "currency-identifer1" "wallet-identifier1" +wallet-multiple.example8. 3600 IN WALLET "currency-identifer1" "wallet-identifier2" +wallet-multiple.example8. 3600 IN WALLET "currency-identifer2" "wallet-identifier3" +wks01.example8. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02.example8. 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03.example8. 3600 IN WKS 10.0.0.2 6 65535 +x2501.example8. 3600 IN X25 "123456789" +zonemd01.example8. 3600 IN ZONEMD 2019020700 1 1 C220B8A6ED5728A971902F7E3D4FD93ADEEA88B0453C2E8E8C863D46 5AB06CF34EB95B266398C98B59124FA239CB7EEB +zonemd02.example8. 3600 IN ZONEMD 2019020700 1 2 08CFA1115C7B948C4163A901270395EA226A930CD2CBCF2FA9A5E6EB 85F37C8A4E114D884E66F176EAB121CB02DB7D652E0CC4827E7A3204 F166B47E5613FD27 +8f1tmio9avcom2k0frp92lgcumak0cad.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C 8FPNS2UCT7FBS643THP2B77PEQ77K6IU A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM +kcd3juae64f9c5csl1kif1htaui7un0g.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C KD5MN2M20340DGO0BL7NTSB8JP4BSC7E +mr5ukvsk1l37btu4q7b1dfevft4hkqdk.example8. 3600 IN NSEC3 1 0 10 D2CF0294C020CE6C MT38J6VG7S0SN5G17MCUF6IQIKFUAJ05 A AAAA RRSIG +example8. 86400 IN SOA ns2.example8. hostmaster.example8. 1397051952 5 5 1814400 3600 diff --git a/bin/tests/system/doth/get_openssl_version.py b/bin/tests/system/doth/get_openssl_version.py new file mode 100755 index 0000000..94cbf5a --- /dev/null +++ b/bin/tests/system/doth/get_openssl_version.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import ssl + +version = ssl.OPENSSL_VERSION_INFO +print(version[0], version[1], version[2]) diff --git a/bin/tests/system/doth/ns1/named.conf.in b/bin/tests/system/doth/ns1/named.conf.in new file mode 100644 index 0000000..df9a25d --- /dev/null +++ b/bin/tests/system/doth/ns1/named.conf.in @@ -0,0 +1,206 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +http local { + endpoints { "/dns-query"; "/alter"; }; + listener-clients 100; +}; + +tls tls-forward-secrecy { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv01.crt01.example.com.key"; + cert-file "../CA/certs/srv01.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-pfs-aes256 { + protocols { TLSv1.2; }; + ciphers "AES256:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv01.crt01.example.com.key"; + cert-file "../CA/certs/srv01.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-no-subject-alt-name { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv01.crt02-no-san.example.com.key"; + cert-file "../CA/certs/srv01.crt02-no-san.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-expired { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv01.crt03-expired.example.com.key"; + cert-file "../CA/certs/srv01.crt03-expired.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-forward-secrecy-mutual-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv01.crt01.example.com.key"; + cert-file "../CA/certs/srv01.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +options { + port @PORT@; + tls-port @TLSPORT@; + https-port @HTTPSPORT@; + http-port @HTTPPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on tls tls-forward-secrecy { 10.53.0.1; }; // DoT + listen-on-v6 tls tls-forward-secrecy { fd92:7065:b8e:ffff::1;}; + listen-on tls ephemeral http local { 10.53.0.1; }; // DoH + listen-on-v6 tls ephemeral http local { fd92:7065:b8e:ffff::1; }; + listen-on tls none http local { 10.53.0.1; }; // unencrypted DoH + listen-on-v6 tls none http local { fd92:7065:b8e:ffff::1; }; + listen-on-v6 { none; }; + listen-on port @EXTRAPORT1@ tls tls-pfs-aes256 { 10.53.0.1; }; // DoT + listen-on-v6 port @EXTRAPORT1@ tls tls-pfs-aes256 { fd92:7065:b8e:ffff::1;}; + listen-on port @EXTRAPORT2@ tls tls-no-subject-alt-name { 10.53.0.1; }; // DoT + listen-on port @EXTRAPORT3@ tls tls-no-subject-alt-name http local { 10.53.0.1; }; // DoH + listen-on port @EXTRAPORT4@ tls tls-expired { 10.53.0.1; }; // DoT + listen-on port @EXTRAPORT5@ tls tls-forward-secrecy-mutual-tls { 10.53.0.1; }; // DoT + listen-on port @EXTRAPORT6@ tls tls-forward-secrecy-mutual-tls http local { 10.53.0.1; }; // DoH + listen-on port @EXTRAPORT7@ tls tls-forward-secrecy { 10.53.0.1; }; // DoT + recursion no; + notify explicit; + also-notify { 10.53.0.2 port @PORT@; }; + statistics-file "named.stats"; + dnssec-validation yes; + tcp-initial-timeout 1200; + transfers-in 100; + transfers-out 100; + max-records-per-type 0; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; + allow-transfer port @TLSPORT@ transport tls { any; }; +}; + +zone "test.example.com" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example" { + type primary; + file "example.db"; + allow-transfer port @TLSPORT@ transport tls { any; }; +}; + +zone "example2" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT1@ transport tls { any; }; +}; + +zone "example3" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT3@ transport tls { any; }; +}; + +zone "example4" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example5" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example6" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example7" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example8" { + type primary; + file "example.db"; + allow-transfer transport tls { any; }; +}; + +zone "example9" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT5@ transport tls { any; }; +}; + +zone "example10" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT5@ transport tls { any; }; +}; + +zone "example11" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT5@ transport tls { any; }; +}; + +zone "example12" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT7@ transport tls { any; }; +}; + +zone "example13" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT7@ transport tls { any; }; +}; + +zone "example14" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT7@ transport tls { any; }; +}; + +zone "example15" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT7@ transport tls { any; }; +}; diff --git a/bin/tests/system/doth/ns1/root.db b/bin/tests/system/doth/ns1/root.db new file mode 100644 index 0000000..47a18a1 --- /dev/null +++ b/bin/tests/system/doth/ns1/root.db @@ -0,0 +1,10023 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +dom0001. NS a.root-servers.nil. +dom0002. NS a.root-servers.nil. +dom0003. NS a.root-servers.nil. +dom0004. NS a.root-servers.nil. +dom0005. NS a.root-servers.nil. +dom0006. NS a.root-servers.nil. +dom0007. NS a.root-servers.nil. +dom0008. NS a.root-servers.nil. +dom0009. NS a.root-servers.nil. +dom0010. NS a.root-servers.nil. +dom0011. NS a.root-servers.nil. +dom0012. NS a.root-servers.nil. +dom0013. NS a.root-servers.nil. +dom0014. NS a.root-servers.nil. +dom0015. NS a.root-servers.nil. +dom0016. NS a.root-servers.nil. +dom0017. NS a.root-servers.nil. +dom0018. NS a.root-servers.nil. +dom0019. NS a.root-servers.nil. +dom0020. NS a.root-servers.nil. +dom0021. NS a.root-servers.nil. +dom0022. NS a.root-servers.nil. +dom0023. NS a.root-servers.nil. +dom0024. NS a.root-servers.nil. +dom0025. NS a.root-servers.nil. +dom0026. NS a.root-servers.nil. +dom0027. NS a.root-servers.nil. +dom0028. NS a.root-servers.nil. +dom0029. NS a.root-servers.nil. +dom0030. NS a.root-servers.nil. +dom0031. NS a.root-servers.nil. +dom0032. NS a.root-servers.nil. +dom0033. NS a.root-servers.nil. +dom0034. NS a.root-servers.nil. +dom0035. NS a.root-servers.nil. +dom0036. NS a.root-servers.nil. +dom0037. NS a.root-servers.nil. +dom0038. NS a.root-servers.nil. +dom0039. NS a.root-servers.nil. +dom0040. NS a.root-servers.nil. +dom0041. NS a.root-servers.nil. +dom0042. NS a.root-servers.nil. +dom0043. NS a.root-servers.nil. +dom0044. NS a.root-servers.nil. +dom0045. NS a.root-servers.nil. +dom0046. NS a.root-servers.nil. +dom0047. NS a.root-servers.nil. +dom0048. NS a.root-servers.nil. +dom0049. NS a.root-servers.nil. +dom0050. NS a.root-servers.nil. +dom0051. NS a.root-servers.nil. +dom0052. NS a.root-servers.nil. +dom0053. NS a.root-servers.nil. +dom0054. NS a.root-servers.nil. +dom0055. NS a.root-servers.nil. +dom0056. NS a.root-servers.nil. +dom0057. NS a.root-servers.nil. +dom0058. NS a.root-servers.nil. +dom0059. NS a.root-servers.nil. +dom0060. NS a.root-servers.nil. +dom0061. NS a.root-servers.nil. +dom0062. NS a.root-servers.nil. +dom0063. NS a.root-servers.nil. +dom0064. NS a.root-servers.nil. +dom0065. NS a.root-servers.nil. +dom0066. NS a.root-servers.nil. +dom0067. NS a.root-servers.nil. +dom0068. NS a.root-servers.nil. +dom0069. NS a.root-servers.nil. +dom0070. NS a.root-servers.nil. +dom0071. NS a.root-servers.nil. +dom0072. NS a.root-servers.nil. +dom0073. NS a.root-servers.nil. +dom0074. NS a.root-servers.nil. +dom0075. NS a.root-servers.nil. +dom0076. NS a.root-servers.nil. +dom0077. NS a.root-servers.nil. +dom0078. NS a.root-servers.nil. +dom0079. NS a.root-servers.nil. +dom0080. NS a.root-servers.nil. +dom0081. NS a.root-servers.nil. +dom0082. NS a.root-servers.nil. +dom0083. NS a.root-servers.nil. +dom0084. NS a.root-servers.nil. +dom0085. NS a.root-servers.nil. +dom0086. NS a.root-servers.nil. +dom0087. NS a.root-servers.nil. +dom0088. NS a.root-servers.nil. +dom0089. NS a.root-servers.nil. +dom0090. NS a.root-servers.nil. +dom0091. NS a.root-servers.nil. +dom0092. NS a.root-servers.nil. +dom0093. NS a.root-servers.nil. +dom0094. NS a.root-servers.nil. +dom0095. NS a.root-servers.nil. +dom0096. NS a.root-servers.nil. +dom0097. NS a.root-servers.nil. +dom0098. NS a.root-servers.nil. +dom0099. NS a.root-servers.nil. +dom0100. NS a.root-servers.nil. +dom0101. NS a.root-servers.nil. +dom0102. NS a.root-servers.nil. +dom0103. NS a.root-servers.nil. +dom0104. NS a.root-servers.nil. +dom0105. NS a.root-servers.nil. +dom0106. NS a.root-servers.nil. +dom0107. NS a.root-servers.nil. +dom0108. NS a.root-servers.nil. +dom0109. NS a.root-servers.nil. +dom0110. NS a.root-servers.nil. +dom0111. NS a.root-servers.nil. +dom0112. NS a.root-servers.nil. +dom0113. NS a.root-servers.nil. +dom0114. NS a.root-servers.nil. +dom0115. NS a.root-servers.nil. +dom0116. NS a.root-servers.nil. +dom0117. NS a.root-servers.nil. +dom0118. NS a.root-servers.nil. +dom0119. NS a.root-servers.nil. +dom0120. NS a.root-servers.nil. +dom0121. NS a.root-servers.nil. +dom0122. NS a.root-servers.nil. +dom0123. NS a.root-servers.nil. +dom0124. NS a.root-servers.nil. +dom0125. NS a.root-servers.nil. +dom0126. NS a.root-servers.nil. +dom0127. NS a.root-servers.nil. +dom0128. NS a.root-servers.nil. +dom0129. NS a.root-servers.nil. +dom0130. NS a.root-servers.nil. +dom0131. NS a.root-servers.nil. +dom0132. NS a.root-servers.nil. +dom0133. NS a.root-servers.nil. +dom0134. NS a.root-servers.nil. +dom0135. NS a.root-servers.nil. +dom0136. NS a.root-servers.nil. +dom0137. NS a.root-servers.nil. +dom0138. NS a.root-servers.nil. +dom0139. NS a.root-servers.nil. +dom0140. NS a.root-servers.nil. +dom0141. NS a.root-servers.nil. +dom0142. NS a.root-servers.nil. +dom0143. NS a.root-servers.nil. +dom0144. NS a.root-servers.nil. +dom0145. NS a.root-servers.nil. +dom0146. NS a.root-servers.nil. +dom0147. NS a.root-servers.nil. +dom0148. NS a.root-servers.nil. +dom0149. NS a.root-servers.nil. +dom0150. NS a.root-servers.nil. +dom0151. NS a.root-servers.nil. +dom0152. NS a.root-servers.nil. +dom0153. NS a.root-servers.nil. +dom0154. NS a.root-servers.nil. +dom0155. NS a.root-servers.nil. +dom0156. NS a.root-servers.nil. +dom0157. NS a.root-servers.nil. +dom0158. NS a.root-servers.nil. +dom0159. NS a.root-servers.nil. +dom0160. NS a.root-servers.nil. +dom0161. NS a.root-servers.nil. +dom0162. NS a.root-servers.nil. +dom0163. NS a.root-servers.nil. +dom0164. NS a.root-servers.nil. +dom0165. NS a.root-servers.nil. +dom0166. NS a.root-servers.nil. +dom0167. NS a.root-servers.nil. +dom0168. NS a.root-servers.nil. +dom0169. NS a.root-servers.nil. +dom0170. NS a.root-servers.nil. +dom0171. NS a.root-servers.nil. +dom0172. NS a.root-servers.nil. +dom0173. NS a.root-servers.nil. +dom0174. NS a.root-servers.nil. +dom0175. NS a.root-servers.nil. +dom0176. NS a.root-servers.nil. +dom0177. NS a.root-servers.nil. +dom0178. NS a.root-servers.nil. +dom0179. NS a.root-servers.nil. +dom0180. NS a.root-servers.nil. +dom0181. NS a.root-servers.nil. +dom0182. NS a.root-servers.nil. +dom0183. NS a.root-servers.nil. +dom0184. NS a.root-servers.nil. +dom0185. NS a.root-servers.nil. +dom0186. NS a.root-servers.nil. +dom0187. NS a.root-servers.nil. +dom0188. NS a.root-servers.nil. +dom0189. NS a.root-servers.nil. +dom0190. NS a.root-servers.nil. +dom0191. NS a.root-servers.nil. +dom0192. NS a.root-servers.nil. +dom0193. NS a.root-servers.nil. +dom0194. NS a.root-servers.nil. +dom0195. NS a.root-servers.nil. +dom0196. NS a.root-servers.nil. +dom0197. NS a.root-servers.nil. +dom0198. NS a.root-servers.nil. +dom0199. NS a.root-servers.nil. +dom0200. NS a.root-servers.nil. +dom0201. NS a.root-servers.nil. +dom0202. NS a.root-servers.nil. +dom0203. NS a.root-servers.nil. +dom0204. NS a.root-servers.nil. +dom0205. NS a.root-servers.nil. +dom0206. NS a.root-servers.nil. +dom0207. NS a.root-servers.nil. +dom0208. NS a.root-servers.nil. +dom0209. NS a.root-servers.nil. +dom0210. NS a.root-servers.nil. +dom0211. NS a.root-servers.nil. +dom0212. NS a.root-servers.nil. +dom0213. NS a.root-servers.nil. +dom0214. NS a.root-servers.nil. +dom0215. NS a.root-servers.nil. +dom0216. NS a.root-servers.nil. +dom0217. NS a.root-servers.nil. +dom0218. NS a.root-servers.nil. +dom0219. NS a.root-servers.nil. +dom0220. NS a.root-servers.nil. +dom0221. NS a.root-servers.nil. +dom0222. NS a.root-servers.nil. +dom0223. NS a.root-servers.nil. +dom0224. NS a.root-servers.nil. +dom0225. NS a.root-servers.nil. +dom0226. NS a.root-servers.nil. +dom0227. NS a.root-servers.nil. +dom0228. NS a.root-servers.nil. +dom0229. NS a.root-servers.nil. +dom0230. NS a.root-servers.nil. +dom0231. NS a.root-servers.nil. +dom0232. NS a.root-servers.nil. +dom0233. NS a.root-servers.nil. +dom0234. NS a.root-servers.nil. +dom0235. NS a.root-servers.nil. +dom0236. NS a.root-servers.nil. +dom0237. NS a.root-servers.nil. +dom0238. NS a.root-servers.nil. +dom0239. NS a.root-servers.nil. +dom0240. NS a.root-servers.nil. +dom0241. NS a.root-servers.nil. +dom0242. NS a.root-servers.nil. +dom0243. NS a.root-servers.nil. +dom0244. NS a.root-servers.nil. +dom0245. NS a.root-servers.nil. +dom0246. NS a.root-servers.nil. +dom0247. NS a.root-servers.nil. +dom0248. NS a.root-servers.nil. +dom0249. NS a.root-servers.nil. +dom0250. NS a.root-servers.nil. +dom0251. NS a.root-servers.nil. +dom0252. NS a.root-servers.nil. +dom0253. NS a.root-servers.nil. +dom0254. NS a.root-servers.nil. +dom0255. NS a.root-servers.nil. +dom0256. NS a.root-servers.nil. +dom0257. NS a.root-servers.nil. +dom0258. NS a.root-servers.nil. +dom0259. NS a.root-servers.nil. +dom0260. NS a.root-servers.nil. +dom0261. NS a.root-servers.nil. +dom0262. NS a.root-servers.nil. +dom0263. NS a.root-servers.nil. +dom0264. NS a.root-servers.nil. +dom0265. NS a.root-servers.nil. +dom0266. NS a.root-servers.nil. +dom0267. NS a.root-servers.nil. +dom0268. NS a.root-servers.nil. +dom0269. NS a.root-servers.nil. +dom0270. NS a.root-servers.nil. +dom0271. NS a.root-servers.nil. +dom0272. NS a.root-servers.nil. +dom0273. NS a.root-servers.nil. +dom0274. NS a.root-servers.nil. +dom0275. NS a.root-servers.nil. +dom0276. NS a.root-servers.nil. +dom0277. NS a.root-servers.nil. +dom0278. NS a.root-servers.nil. +dom0279. NS a.root-servers.nil. +dom0280. NS a.root-servers.nil. +dom0281. NS a.root-servers.nil. +dom0282. NS a.root-servers.nil. +dom0283. NS a.root-servers.nil. +dom0284. NS a.root-servers.nil. +dom0285. NS a.root-servers.nil. +dom0286. NS a.root-servers.nil. +dom0287. NS a.root-servers.nil. +dom0288. NS a.root-servers.nil. +dom0289. NS a.root-servers.nil. +dom0290. NS a.root-servers.nil. +dom0291. NS a.root-servers.nil. +dom0292. NS a.root-servers.nil. +dom0293. NS a.root-servers.nil. +dom0294. NS a.root-servers.nil. +dom0295. NS a.root-servers.nil. +dom0296. NS a.root-servers.nil. +dom0297. NS a.root-servers.nil. +dom0298. NS a.root-servers.nil. +dom0299. NS a.root-servers.nil. +dom0300. NS a.root-servers.nil. +dom0301. NS a.root-servers.nil. +dom0302. NS a.root-servers.nil. +dom0303. NS a.root-servers.nil. +dom0304. NS a.root-servers.nil. +dom0305. NS a.root-servers.nil. +dom0306. NS a.root-servers.nil. +dom0307. NS a.root-servers.nil. +dom0308. NS a.root-servers.nil. +dom0309. NS a.root-servers.nil. +dom0310. NS a.root-servers.nil. +dom0311. NS a.root-servers.nil. +dom0312. NS a.root-servers.nil. +dom0313. NS a.root-servers.nil. +dom0314. NS a.root-servers.nil. +dom0315. NS a.root-servers.nil. +dom0316. NS a.root-servers.nil. +dom0317. NS a.root-servers.nil. +dom0318. NS a.root-servers.nil. +dom0319. NS a.root-servers.nil. +dom0320. NS a.root-servers.nil. +dom0321. NS a.root-servers.nil. +dom0322. NS a.root-servers.nil. +dom0323. NS a.root-servers.nil. +dom0324. NS a.root-servers.nil. +dom0325. NS a.root-servers.nil. +dom0326. NS a.root-servers.nil. +dom0327. NS a.root-servers.nil. +dom0328. NS a.root-servers.nil. +dom0329. NS a.root-servers.nil. +dom0330. NS a.root-servers.nil. +dom0331. NS a.root-servers.nil. +dom0332. NS a.root-servers.nil. +dom0333. NS a.root-servers.nil. +dom0334. NS a.root-servers.nil. +dom0335. NS a.root-servers.nil. +dom0336. NS a.root-servers.nil. +dom0337. NS a.root-servers.nil. +dom0338. NS a.root-servers.nil. +dom0339. NS a.root-servers.nil. +dom0340. NS a.root-servers.nil. +dom0341. NS a.root-servers.nil. +dom0342. NS a.root-servers.nil. +dom0343. NS a.root-servers.nil. +dom0344. NS a.root-servers.nil. +dom0345. NS a.root-servers.nil. +dom0346. NS a.root-servers.nil. +dom0347. NS a.root-servers.nil. +dom0348. NS a.root-servers.nil. +dom0349. NS a.root-servers.nil. +dom0350. NS a.root-servers.nil. +dom0351. NS a.root-servers.nil. +dom0352. NS a.root-servers.nil. +dom0353. NS a.root-servers.nil. +dom0354. NS a.root-servers.nil. +dom0355. NS a.root-servers.nil. +dom0356. NS a.root-servers.nil. +dom0357. NS a.root-servers.nil. +dom0358. NS a.root-servers.nil. +dom0359. NS a.root-servers.nil. +dom0360. NS a.root-servers.nil. +dom0361. NS a.root-servers.nil. +dom0362. NS a.root-servers.nil. +dom0363. NS a.root-servers.nil. +dom0364. NS a.root-servers.nil. +dom0365. NS a.root-servers.nil. +dom0366. NS a.root-servers.nil. +dom0367. NS a.root-servers.nil. +dom0368. NS a.root-servers.nil. +dom0369. NS a.root-servers.nil. +dom0370. NS a.root-servers.nil. +dom0371. NS a.root-servers.nil. +dom0372. NS a.root-servers.nil. +dom0373. NS a.root-servers.nil. +dom0374. NS a.root-servers.nil. +dom0375. NS a.root-servers.nil. +dom0376. NS a.root-servers.nil. +dom0377. NS a.root-servers.nil. +dom0378. NS a.root-servers.nil. +dom0379. NS a.root-servers.nil. +dom0380. NS a.root-servers.nil. +dom0381. NS a.root-servers.nil. +dom0382. NS a.root-servers.nil. +dom0383. NS a.root-servers.nil. +dom0384. NS a.root-servers.nil. +dom0385. NS a.root-servers.nil. +dom0386. NS a.root-servers.nil. +dom0387. NS a.root-servers.nil. +dom0388. NS a.root-servers.nil. +dom0389. NS a.root-servers.nil. +dom0390. NS a.root-servers.nil. +dom0391. NS a.root-servers.nil. +dom0392. NS a.root-servers.nil. +dom0393. NS a.root-servers.nil. +dom0394. NS a.root-servers.nil. +dom0395. NS a.root-servers.nil. +dom0396. NS a.root-servers.nil. +dom0397. NS a.root-servers.nil. +dom0398. NS a.root-servers.nil. +dom0399. NS a.root-servers.nil. +dom0400. NS a.root-servers.nil. +dom0401. NS a.root-servers.nil. +dom0402. NS a.root-servers.nil. +dom0403. NS a.root-servers.nil. +dom0404. NS a.root-servers.nil. +dom0405. NS a.root-servers.nil. +dom0406. NS a.root-servers.nil. +dom0407. NS a.root-servers.nil. +dom0408. NS a.root-servers.nil. +dom0409. NS a.root-servers.nil. +dom0410. NS a.root-servers.nil. +dom0411. NS a.root-servers.nil. +dom0412. NS a.root-servers.nil. +dom0413. NS a.root-servers.nil. +dom0414. NS a.root-servers.nil. +dom0415. NS a.root-servers.nil. +dom0416. NS a.root-servers.nil. +dom0417. NS a.root-servers.nil. +dom0418. NS a.root-servers.nil. +dom0419. NS a.root-servers.nil. +dom0420. NS a.root-servers.nil. +dom0421. NS a.root-servers.nil. +dom0422. NS a.root-servers.nil. +dom0423. NS a.root-servers.nil. +dom0424. NS a.root-servers.nil. +dom0425. NS a.root-servers.nil. +dom0426. NS a.root-servers.nil. +dom0427. NS a.root-servers.nil. +dom0428. NS a.root-servers.nil. +dom0429. NS a.root-servers.nil. +dom0430. NS a.root-servers.nil. +dom0431. NS a.root-servers.nil. +dom0432. NS a.root-servers.nil. +dom0433. NS a.root-servers.nil. +dom0434. NS a.root-servers.nil. +dom0435. NS a.root-servers.nil. +dom0436. NS a.root-servers.nil. +dom0437. NS a.root-servers.nil. +dom0438. NS a.root-servers.nil. +dom0439. NS a.root-servers.nil. +dom0440. NS a.root-servers.nil. +dom0441. NS a.root-servers.nil. +dom0442. NS a.root-servers.nil. +dom0443. NS a.root-servers.nil. +dom0444. NS a.root-servers.nil. +dom0445. NS a.root-servers.nil. +dom0446. NS a.root-servers.nil. +dom0447. NS a.root-servers.nil. +dom0448. NS a.root-servers.nil. +dom0449. NS a.root-servers.nil. +dom0450. NS a.root-servers.nil. +dom0451. NS a.root-servers.nil. +dom0452. NS a.root-servers.nil. +dom0453. NS a.root-servers.nil. +dom0454. NS a.root-servers.nil. +dom0455. NS a.root-servers.nil. +dom0456. NS a.root-servers.nil. +dom0457. NS a.root-servers.nil. +dom0458. NS a.root-servers.nil. +dom0459. NS a.root-servers.nil. +dom0460. NS a.root-servers.nil. +dom0461. NS a.root-servers.nil. +dom0462. NS a.root-servers.nil. +dom0463. NS a.root-servers.nil. +dom0464. NS a.root-servers.nil. +dom0465. NS a.root-servers.nil. +dom0466. NS a.root-servers.nil. +dom0467. NS a.root-servers.nil. +dom0468. NS a.root-servers.nil. +dom0469. NS a.root-servers.nil. +dom0470. NS a.root-servers.nil. +dom0471. NS a.root-servers.nil. +dom0472. NS a.root-servers.nil. +dom0473. NS a.root-servers.nil. +dom0474. NS a.root-servers.nil. +dom0475. NS a.root-servers.nil. +dom0476. NS a.root-servers.nil. +dom0477. NS a.root-servers.nil. +dom0478. NS a.root-servers.nil. +dom0479. NS a.root-servers.nil. +dom0480. NS a.root-servers.nil. +dom0481. NS a.root-servers.nil. +dom0482. NS a.root-servers.nil. +dom0483. NS a.root-servers.nil. +dom0484. NS a.root-servers.nil. +dom0485. NS a.root-servers.nil. +dom0486. NS a.root-servers.nil. +dom0487. NS a.root-servers.nil. +dom0488. NS a.root-servers.nil. +dom0489. NS a.root-servers.nil. +dom0490. NS a.root-servers.nil. +dom0491. NS a.root-servers.nil. +dom0492. NS a.root-servers.nil. +dom0493. NS a.root-servers.nil. +dom0494. NS a.root-servers.nil. +dom0495. NS a.root-servers.nil. +dom0496. NS a.root-servers.nil. +dom0497. NS a.root-servers.nil. +dom0498. NS a.root-servers.nil. +dom0499. NS a.root-servers.nil. +dom0500. NS a.root-servers.nil. +dom0501. NS a.root-servers.nil. +dom0502. NS a.root-servers.nil. +dom0503. NS a.root-servers.nil. +dom0504. NS a.root-servers.nil. +dom0505. NS a.root-servers.nil. +dom0506. NS a.root-servers.nil. +dom0507. NS a.root-servers.nil. +dom0508. NS a.root-servers.nil. +dom0509. NS a.root-servers.nil. +dom0510. NS a.root-servers.nil. +dom0511. NS a.root-servers.nil. +dom0512. NS a.root-servers.nil. +dom0513. NS a.root-servers.nil. +dom0514. NS a.root-servers.nil. +dom0515. NS a.root-servers.nil. +dom0516. NS a.root-servers.nil. +dom0517. NS a.root-servers.nil. +dom0518. NS a.root-servers.nil. +dom0519. NS a.root-servers.nil. +dom0520. NS a.root-servers.nil. +dom0521. NS a.root-servers.nil. +dom0522. NS a.root-servers.nil. +dom0523. NS a.root-servers.nil. +dom0524. NS a.root-servers.nil. +dom0525. NS a.root-servers.nil. +dom0526. NS a.root-servers.nil. +dom0527. NS a.root-servers.nil. +dom0528. NS a.root-servers.nil. +dom0529. NS a.root-servers.nil. +dom0530. NS a.root-servers.nil. +dom0531. NS a.root-servers.nil. +dom0532. NS a.root-servers.nil. +dom0533. NS a.root-servers.nil. +dom0534. NS a.root-servers.nil. +dom0535. NS a.root-servers.nil. +dom0536. NS a.root-servers.nil. +dom0537. NS a.root-servers.nil. +dom0538. NS a.root-servers.nil. +dom0539. NS a.root-servers.nil. +dom0540. NS a.root-servers.nil. +dom0541. NS a.root-servers.nil. +dom0542. NS a.root-servers.nil. +dom0543. NS a.root-servers.nil. +dom0544. NS a.root-servers.nil. +dom0545. NS a.root-servers.nil. +dom0546. NS a.root-servers.nil. +dom0547. NS a.root-servers.nil. +dom0548. NS a.root-servers.nil. +dom0549. NS a.root-servers.nil. +dom0550. NS a.root-servers.nil. +dom0551. NS a.root-servers.nil. +dom0552. NS a.root-servers.nil. +dom0553. NS a.root-servers.nil. +dom0554. NS a.root-servers.nil. +dom0555. NS a.root-servers.nil. +dom0556. NS a.root-servers.nil. +dom0557. NS a.root-servers.nil. +dom0558. NS a.root-servers.nil. +dom0559. NS a.root-servers.nil. +dom0560. NS a.root-servers.nil. +dom0561. NS a.root-servers.nil. +dom0562. NS a.root-servers.nil. +dom0563. NS a.root-servers.nil. +dom0564. NS a.root-servers.nil. +dom0565. NS a.root-servers.nil. +dom0566. NS a.root-servers.nil. +dom0567. NS a.root-servers.nil. +dom0568. NS a.root-servers.nil. +dom0569. NS a.root-servers.nil. +dom0570. NS a.root-servers.nil. +dom0571. NS a.root-servers.nil. +dom0572. NS a.root-servers.nil. +dom0573. NS a.root-servers.nil. +dom0574. NS a.root-servers.nil. +dom0575. NS a.root-servers.nil. +dom0576. NS a.root-servers.nil. +dom0577. NS a.root-servers.nil. +dom0578. NS a.root-servers.nil. +dom0579. NS a.root-servers.nil. +dom0580. NS a.root-servers.nil. +dom0581. NS a.root-servers.nil. +dom0582. NS a.root-servers.nil. +dom0583. NS a.root-servers.nil. +dom0584. NS a.root-servers.nil. +dom0585. NS a.root-servers.nil. +dom0586. NS a.root-servers.nil. +dom0587. NS a.root-servers.nil. +dom0588. NS a.root-servers.nil. +dom0589. NS a.root-servers.nil. +dom0590. NS a.root-servers.nil. +dom0591. NS a.root-servers.nil. +dom0592. NS a.root-servers.nil. +dom0593. NS a.root-servers.nil. +dom0594. NS a.root-servers.nil. +dom0595. NS a.root-servers.nil. +dom0596. NS a.root-servers.nil. +dom0597. NS a.root-servers.nil. +dom0598. NS a.root-servers.nil. +dom0599. NS a.root-servers.nil. +dom0600. NS a.root-servers.nil. +dom0601. NS a.root-servers.nil. +dom0602. NS a.root-servers.nil. +dom0603. NS a.root-servers.nil. +dom0604. NS a.root-servers.nil. +dom0605. NS a.root-servers.nil. +dom0606. NS a.root-servers.nil. +dom0607. NS a.root-servers.nil. +dom0608. NS a.root-servers.nil. +dom0609. NS a.root-servers.nil. +dom0610. NS a.root-servers.nil. +dom0611. NS a.root-servers.nil. +dom0612. NS a.root-servers.nil. +dom0613. NS a.root-servers.nil. +dom0614. NS a.root-servers.nil. +dom0615. NS a.root-servers.nil. +dom0616. NS a.root-servers.nil. +dom0617. NS a.root-servers.nil. +dom0618. NS a.root-servers.nil. +dom0619. NS a.root-servers.nil. +dom0620. NS a.root-servers.nil. +dom0621. NS a.root-servers.nil. +dom0622. NS a.root-servers.nil. +dom0623. NS a.root-servers.nil. +dom0624. NS a.root-servers.nil. +dom0625. NS a.root-servers.nil. +dom0626. NS a.root-servers.nil. +dom0627. NS a.root-servers.nil. +dom0628. NS a.root-servers.nil. +dom0629. NS a.root-servers.nil. +dom0630. NS a.root-servers.nil. +dom0631. NS a.root-servers.nil. +dom0632. NS a.root-servers.nil. +dom0633. NS a.root-servers.nil. +dom0634. NS a.root-servers.nil. +dom0635. NS a.root-servers.nil. +dom0636. NS a.root-servers.nil. +dom0637. NS a.root-servers.nil. +dom0638. NS a.root-servers.nil. +dom0639. NS a.root-servers.nil. +dom0640. NS a.root-servers.nil. +dom0641. NS a.root-servers.nil. +dom0642. NS a.root-servers.nil. +dom0643. NS a.root-servers.nil. +dom0644. NS a.root-servers.nil. +dom0645. NS a.root-servers.nil. +dom0646. NS a.root-servers.nil. +dom0647. NS a.root-servers.nil. +dom0648. NS a.root-servers.nil. +dom0649. NS a.root-servers.nil. +dom0650. NS a.root-servers.nil. +dom0651. NS a.root-servers.nil. +dom0652. NS a.root-servers.nil. +dom0653. NS a.root-servers.nil. +dom0654. NS a.root-servers.nil. +dom0655. NS a.root-servers.nil. +dom0656. NS a.root-servers.nil. +dom0657. NS a.root-servers.nil. +dom0658. NS a.root-servers.nil. +dom0659. NS a.root-servers.nil. +dom0660. NS a.root-servers.nil. +dom0661. NS a.root-servers.nil. +dom0662. NS a.root-servers.nil. +dom0663. NS a.root-servers.nil. +dom0664. NS a.root-servers.nil. +dom0665. NS a.root-servers.nil. +dom0666. NS a.root-servers.nil. +dom0667. NS a.root-servers.nil. +dom0668. NS a.root-servers.nil. +dom0669. NS a.root-servers.nil. +dom0670. NS a.root-servers.nil. +dom0671. NS a.root-servers.nil. +dom0672. NS a.root-servers.nil. +dom0673. NS a.root-servers.nil. +dom0674. NS a.root-servers.nil. +dom0675. NS a.root-servers.nil. +dom0676. NS a.root-servers.nil. +dom0677. NS a.root-servers.nil. +dom0678. NS a.root-servers.nil. +dom0679. NS a.root-servers.nil. +dom0680. NS a.root-servers.nil. +dom0681. NS a.root-servers.nil. +dom0682. NS a.root-servers.nil. +dom0683. NS a.root-servers.nil. +dom0684. NS a.root-servers.nil. +dom0685. NS a.root-servers.nil. +dom0686. NS a.root-servers.nil. +dom0687. NS a.root-servers.nil. +dom0688. NS a.root-servers.nil. +dom0689. NS a.root-servers.nil. +dom0690. NS a.root-servers.nil. +dom0691. NS a.root-servers.nil. +dom0692. NS a.root-servers.nil. +dom0693. NS a.root-servers.nil. +dom0694. NS a.root-servers.nil. +dom0695. NS a.root-servers.nil. +dom0696. NS a.root-servers.nil. +dom0697. NS a.root-servers.nil. +dom0698. NS a.root-servers.nil. +dom0699. NS a.root-servers.nil. +dom0700. NS a.root-servers.nil. +dom0701. NS a.root-servers.nil. +dom0702. NS a.root-servers.nil. +dom0703. NS a.root-servers.nil. +dom0704. NS a.root-servers.nil. +dom0705. NS a.root-servers.nil. +dom0706. NS a.root-servers.nil. +dom0707. NS a.root-servers.nil. +dom0708. NS a.root-servers.nil. +dom0709. NS a.root-servers.nil. +dom0710. NS a.root-servers.nil. +dom0711. NS a.root-servers.nil. +dom0712. NS a.root-servers.nil. +dom0713. NS a.root-servers.nil. +dom0714. NS a.root-servers.nil. +dom0715. NS a.root-servers.nil. +dom0716. NS a.root-servers.nil. +dom0717. NS a.root-servers.nil. +dom0718. NS a.root-servers.nil. +dom0719. NS a.root-servers.nil. +dom0720. NS a.root-servers.nil. +dom0721. NS a.root-servers.nil. +dom0722. NS a.root-servers.nil. +dom0723. NS a.root-servers.nil. +dom0724. NS a.root-servers.nil. +dom0725. NS a.root-servers.nil. +dom0726. NS a.root-servers.nil. +dom0727. NS a.root-servers.nil. +dom0728. NS a.root-servers.nil. +dom0729. NS a.root-servers.nil. +dom0730. NS a.root-servers.nil. +dom0731. NS a.root-servers.nil. +dom0732. NS a.root-servers.nil. +dom0733. NS a.root-servers.nil. +dom0734. NS a.root-servers.nil. +dom0735. NS a.root-servers.nil. +dom0736. NS a.root-servers.nil. +dom0737. NS a.root-servers.nil. +dom0738. NS a.root-servers.nil. +dom0739. NS a.root-servers.nil. +dom0740. NS a.root-servers.nil. +dom0741. NS a.root-servers.nil. +dom0742. NS a.root-servers.nil. +dom0743. NS a.root-servers.nil. +dom0744. NS a.root-servers.nil. +dom0745. NS a.root-servers.nil. +dom0746. NS a.root-servers.nil. +dom0747. NS a.root-servers.nil. +dom0748. NS a.root-servers.nil. +dom0749. NS a.root-servers.nil. +dom0750. NS a.root-servers.nil. +dom0751. NS a.root-servers.nil. +dom0752. NS a.root-servers.nil. +dom0753. NS a.root-servers.nil. +dom0754. NS a.root-servers.nil. +dom0755. NS a.root-servers.nil. +dom0756. NS a.root-servers.nil. +dom0757. NS a.root-servers.nil. +dom0758. NS a.root-servers.nil. +dom0759. NS a.root-servers.nil. +dom0760. NS a.root-servers.nil. +dom0761. NS a.root-servers.nil. +dom0762. NS a.root-servers.nil. +dom0763. NS a.root-servers.nil. +dom0764. NS a.root-servers.nil. +dom0765. NS a.root-servers.nil. +dom0766. NS a.root-servers.nil. +dom0767. NS a.root-servers.nil. +dom0768. NS a.root-servers.nil. +dom0769. NS a.root-servers.nil. +dom0770. NS a.root-servers.nil. +dom0771. NS a.root-servers.nil. +dom0772. NS a.root-servers.nil. +dom0773. NS a.root-servers.nil. +dom0774. NS a.root-servers.nil. +dom0775. NS a.root-servers.nil. +dom0776. NS a.root-servers.nil. +dom0777. NS a.root-servers.nil. +dom0778. NS a.root-servers.nil. +dom0779. NS a.root-servers.nil. +dom0780. NS a.root-servers.nil. +dom0781. NS a.root-servers.nil. +dom0782. NS a.root-servers.nil. +dom0783. NS a.root-servers.nil. +dom0784. NS a.root-servers.nil. +dom0785. NS a.root-servers.nil. +dom0786. NS a.root-servers.nil. +dom0787. NS a.root-servers.nil. +dom0788. NS a.root-servers.nil. +dom0789. NS a.root-servers.nil. +dom0790. NS a.root-servers.nil. +dom0791. NS a.root-servers.nil. +dom0792. NS a.root-servers.nil. +dom0793. NS a.root-servers.nil. +dom0794. NS a.root-servers.nil. +dom0795. NS a.root-servers.nil. +dom0796. NS a.root-servers.nil. +dom0797. NS a.root-servers.nil. +dom0798. NS a.root-servers.nil. +dom0799. NS a.root-servers.nil. +dom0800. NS a.root-servers.nil. +dom0801. NS a.root-servers.nil. +dom0802. NS a.root-servers.nil. +dom0803. NS a.root-servers.nil. +dom0804. NS a.root-servers.nil. +dom0805. NS a.root-servers.nil. +dom0806. NS a.root-servers.nil. +dom0807. NS a.root-servers.nil. +dom0808. NS a.root-servers.nil. +dom0809. NS a.root-servers.nil. +dom0810. NS a.root-servers.nil. +dom0811. NS a.root-servers.nil. +dom0812. NS a.root-servers.nil. +dom0813. NS a.root-servers.nil. +dom0814. NS a.root-servers.nil. +dom0815. NS a.root-servers.nil. +dom0816. NS a.root-servers.nil. +dom0817. NS a.root-servers.nil. +dom0818. NS a.root-servers.nil. +dom0819. NS a.root-servers.nil. +dom0820. NS a.root-servers.nil. +dom0821. NS a.root-servers.nil. +dom0822. NS a.root-servers.nil. +dom0823. NS a.root-servers.nil. +dom0824. NS a.root-servers.nil. +dom0825. NS a.root-servers.nil. +dom0826. NS a.root-servers.nil. +dom0827. NS a.root-servers.nil. +dom0828. NS a.root-servers.nil. +dom0829. NS a.root-servers.nil. +dom0830. NS a.root-servers.nil. +dom0831. NS a.root-servers.nil. +dom0832. NS a.root-servers.nil. +dom0833. NS a.root-servers.nil. +dom0834. NS a.root-servers.nil. +dom0835. NS a.root-servers.nil. +dom0836. NS a.root-servers.nil. +dom0837. NS a.root-servers.nil. +dom0838. NS a.root-servers.nil. +dom0839. NS a.root-servers.nil. +dom0840. NS a.root-servers.nil. +dom0841. NS a.root-servers.nil. +dom0842. NS a.root-servers.nil. +dom0843. NS a.root-servers.nil. +dom0844. NS a.root-servers.nil. +dom0845. NS a.root-servers.nil. +dom0846. NS a.root-servers.nil. +dom0847. NS a.root-servers.nil. +dom0848. NS a.root-servers.nil. +dom0849. NS a.root-servers.nil. +dom0850. NS a.root-servers.nil. +dom0851. NS a.root-servers.nil. +dom0852. NS a.root-servers.nil. +dom0853. NS a.root-servers.nil. +dom0854. NS a.root-servers.nil. +dom0855. NS a.root-servers.nil. +dom0856. NS a.root-servers.nil. +dom0857. NS a.root-servers.nil. +dom0858. NS a.root-servers.nil. +dom0859. NS a.root-servers.nil. +dom0860. NS a.root-servers.nil. +dom0861. NS a.root-servers.nil. +dom0862. NS a.root-servers.nil. +dom0863. NS a.root-servers.nil. +dom0864. NS a.root-servers.nil. +dom0865. NS a.root-servers.nil. +dom0866. NS a.root-servers.nil. +dom0867. NS a.root-servers.nil. +dom0868. NS a.root-servers.nil. +dom0869. NS a.root-servers.nil. +dom0870. NS a.root-servers.nil. +dom0871. NS a.root-servers.nil. +dom0872. NS a.root-servers.nil. +dom0873. NS a.root-servers.nil. +dom0874. NS a.root-servers.nil. +dom0875. NS a.root-servers.nil. +dom0876. NS a.root-servers.nil. +dom0877. NS a.root-servers.nil. +dom0878. NS a.root-servers.nil. +dom0879. NS a.root-servers.nil. +dom0880. NS a.root-servers.nil. +dom0881. NS a.root-servers.nil. +dom0882. NS a.root-servers.nil. +dom0883. NS a.root-servers.nil. +dom0884. NS a.root-servers.nil. +dom0885. NS a.root-servers.nil. +dom0886. NS a.root-servers.nil. +dom0887. NS a.root-servers.nil. +dom0888. NS a.root-servers.nil. +dom0889. NS a.root-servers.nil. +dom0890. NS a.root-servers.nil. +dom0891. NS a.root-servers.nil. +dom0892. NS a.root-servers.nil. +dom0893. NS a.root-servers.nil. +dom0894. NS a.root-servers.nil. +dom0895. NS a.root-servers.nil. +dom0896. NS a.root-servers.nil. +dom0897. NS a.root-servers.nil. +dom0898. NS a.root-servers.nil. +dom0899. NS a.root-servers.nil. +dom0900. NS a.root-servers.nil. +dom0901. NS a.root-servers.nil. +dom0902. NS a.root-servers.nil. +dom0903. NS a.root-servers.nil. +dom0904. NS a.root-servers.nil. +dom0905. NS a.root-servers.nil. +dom0906. NS a.root-servers.nil. +dom0907. NS a.root-servers.nil. +dom0908. NS a.root-servers.nil. +dom0909. NS a.root-servers.nil. +dom0910. NS a.root-servers.nil. +dom0911. NS a.root-servers.nil. +dom0912. NS a.root-servers.nil. +dom0913. NS a.root-servers.nil. +dom0914. NS a.root-servers.nil. +dom0915. NS a.root-servers.nil. +dom0916. NS a.root-servers.nil. +dom0917. NS a.root-servers.nil. +dom0918. NS a.root-servers.nil. +dom0919. NS a.root-servers.nil. +dom0920. NS a.root-servers.nil. +dom0921. NS a.root-servers.nil. +dom0922. NS a.root-servers.nil. +dom0923. NS a.root-servers.nil. +dom0924. NS a.root-servers.nil. +dom0925. NS a.root-servers.nil. +dom0926. NS a.root-servers.nil. +dom0927. NS a.root-servers.nil. +dom0928. NS a.root-servers.nil. +dom0929. NS a.root-servers.nil. +dom0930. NS a.root-servers.nil. +dom0931. NS a.root-servers.nil. +dom0932. NS a.root-servers.nil. +dom0933. NS a.root-servers.nil. +dom0934. NS a.root-servers.nil. +dom0935. NS a.root-servers.nil. +dom0936. NS a.root-servers.nil. +dom0937. NS a.root-servers.nil. +dom0938. NS a.root-servers.nil. +dom0939. NS a.root-servers.nil. +dom0940. NS a.root-servers.nil. +dom0941. NS a.root-servers.nil. +dom0942. NS a.root-servers.nil. +dom0943. NS a.root-servers.nil. +dom0944. NS a.root-servers.nil. +dom0945. NS a.root-servers.nil. +dom0946. NS a.root-servers.nil. +dom0947. NS a.root-servers.nil. +dom0948. NS a.root-servers.nil. +dom0949. NS a.root-servers.nil. +dom0950. NS a.root-servers.nil. +dom0951. NS a.root-servers.nil. +dom0952. NS a.root-servers.nil. +dom0953. NS a.root-servers.nil. +dom0954. NS a.root-servers.nil. +dom0955. NS a.root-servers.nil. +dom0956. NS a.root-servers.nil. +dom0957. NS a.root-servers.nil. +dom0958. NS a.root-servers.nil. +dom0959. NS a.root-servers.nil. +dom0960. NS a.root-servers.nil. +dom0961. NS a.root-servers.nil. +dom0962. NS a.root-servers.nil. +dom0963. NS a.root-servers.nil. +dom0964. NS a.root-servers.nil. +dom0965. NS a.root-servers.nil. +dom0966. NS a.root-servers.nil. +dom0967. NS a.root-servers.nil. +dom0968. NS a.root-servers.nil. +dom0969. NS a.root-servers.nil. +dom0970. NS a.root-servers.nil. +dom0971. NS a.root-servers.nil. +dom0972. NS a.root-servers.nil. +dom0973. NS a.root-servers.nil. +dom0974. NS a.root-servers.nil. +dom0975. NS a.root-servers.nil. +dom0976. NS a.root-servers.nil. +dom0977. NS a.root-servers.nil. +dom0978. NS a.root-servers.nil. +dom0979. NS a.root-servers.nil. +dom0980. NS a.root-servers.nil. +dom0981. NS a.root-servers.nil. +dom0982. NS a.root-servers.nil. +dom0983. NS a.root-servers.nil. +dom0984. NS a.root-servers.nil. +dom0985. NS a.root-servers.nil. +dom0986. NS a.root-servers.nil. +dom0987. NS a.root-servers.nil. +dom0988. NS a.root-servers.nil. +dom0989. NS a.root-servers.nil. +dom0990. NS a.root-servers.nil. +dom0991. NS a.root-servers.nil. +dom0992. NS a.root-servers.nil. +dom0993. NS a.root-servers.nil. +dom0994. NS a.root-servers.nil. +dom0995. NS a.root-servers.nil. +dom0996. NS a.root-servers.nil. +dom0997. NS a.root-servers.nil. +dom0998. NS a.root-servers.nil. +dom0999. NS a.root-servers.nil. +dom1000. NS a.root-servers.nil. +dom1001. NS a.root-servers.nil. +dom1002. NS a.root-servers.nil. +dom1003. NS a.root-servers.nil. +dom1004. NS a.root-servers.nil. +dom1005. NS a.root-servers.nil. +dom1006. NS a.root-servers.nil. +dom1007. NS a.root-servers.nil. +dom1008. NS a.root-servers.nil. +dom1009. NS a.root-servers.nil. +dom1010. NS a.root-servers.nil. +dom1011. NS a.root-servers.nil. +dom1012. NS a.root-servers.nil. +dom1013. NS a.root-servers.nil. +dom1014. NS a.root-servers.nil. +dom1015. NS a.root-servers.nil. +dom1016. NS a.root-servers.nil. +dom1017. NS a.root-servers.nil. +dom1018. NS a.root-servers.nil. +dom1019. NS a.root-servers.nil. +dom1020. NS a.root-servers.nil. +dom1021. NS a.root-servers.nil. +dom1022. NS a.root-servers.nil. +dom1023. NS a.root-servers.nil. +dom1024. NS a.root-servers.nil. +dom1025. NS a.root-servers.nil. +dom1026. NS a.root-servers.nil. +dom1027. NS a.root-servers.nil. +dom1028. NS a.root-servers.nil. +dom1029. NS a.root-servers.nil. +dom1030. NS a.root-servers.nil. +dom1031. NS a.root-servers.nil. +dom1032. NS a.root-servers.nil. +dom1033. NS a.root-servers.nil. +dom1034. NS a.root-servers.nil. +dom1035. NS a.root-servers.nil. +dom1036. NS a.root-servers.nil. +dom1037. NS a.root-servers.nil. +dom1038. NS a.root-servers.nil. +dom1039. NS a.root-servers.nil. +dom1040. NS a.root-servers.nil. +dom1041. NS a.root-servers.nil. +dom1042. NS a.root-servers.nil. +dom1043. NS a.root-servers.nil. +dom1044. NS a.root-servers.nil. +dom1045. NS a.root-servers.nil. +dom1046. NS a.root-servers.nil. +dom1047. NS a.root-servers.nil. +dom1048. NS a.root-servers.nil. +dom1049. NS a.root-servers.nil. +dom1050. NS a.root-servers.nil. +dom1051. NS a.root-servers.nil. +dom1052. NS a.root-servers.nil. +dom1053. NS a.root-servers.nil. +dom1054. NS a.root-servers.nil. +dom1055. NS a.root-servers.nil. +dom1056. NS a.root-servers.nil. +dom1057. NS a.root-servers.nil. +dom1058. NS a.root-servers.nil. +dom1059. NS a.root-servers.nil. +dom1060. NS a.root-servers.nil. +dom1061. NS a.root-servers.nil. +dom1062. NS a.root-servers.nil. +dom1063. NS a.root-servers.nil. +dom1064. NS a.root-servers.nil. +dom1065. NS a.root-servers.nil. +dom1066. NS a.root-servers.nil. +dom1067. NS a.root-servers.nil. +dom1068. NS a.root-servers.nil. +dom1069. NS a.root-servers.nil. +dom1070. NS a.root-servers.nil. +dom1071. NS a.root-servers.nil. +dom1072. NS a.root-servers.nil. +dom1073. NS a.root-servers.nil. +dom1074. NS a.root-servers.nil. +dom1075. NS a.root-servers.nil. +dom1076. NS a.root-servers.nil. +dom1077. NS a.root-servers.nil. +dom1078. NS a.root-servers.nil. +dom1079. NS a.root-servers.nil. +dom1080. NS a.root-servers.nil. +dom1081. NS a.root-servers.nil. +dom1082. NS a.root-servers.nil. +dom1083. NS a.root-servers.nil. +dom1084. NS a.root-servers.nil. +dom1085. NS a.root-servers.nil. +dom1086. NS a.root-servers.nil. +dom1087. NS a.root-servers.nil. +dom1088. NS a.root-servers.nil. +dom1089. NS a.root-servers.nil. +dom1090. NS a.root-servers.nil. +dom1091. NS a.root-servers.nil. +dom1092. NS a.root-servers.nil. +dom1093. NS a.root-servers.nil. +dom1094. NS a.root-servers.nil. +dom1095. NS a.root-servers.nil. +dom1096. NS a.root-servers.nil. +dom1097. NS a.root-servers.nil. +dom1098. NS a.root-servers.nil. +dom1099. NS a.root-servers.nil. +dom1100. NS a.root-servers.nil. +dom1101. NS a.root-servers.nil. +dom1102. NS a.root-servers.nil. +dom1103. NS a.root-servers.nil. +dom1104. NS a.root-servers.nil. +dom1105. NS a.root-servers.nil. +dom1106. NS a.root-servers.nil. +dom1107. NS a.root-servers.nil. +dom1108. NS a.root-servers.nil. +dom1109. NS a.root-servers.nil. +dom1110. NS a.root-servers.nil. +dom1111. NS a.root-servers.nil. +dom1112. NS a.root-servers.nil. +dom1113. NS a.root-servers.nil. +dom1114. NS a.root-servers.nil. +dom1115. NS a.root-servers.nil. +dom1116. NS a.root-servers.nil. +dom1117. NS a.root-servers.nil. +dom1118. NS a.root-servers.nil. +dom1119. NS a.root-servers.nil. +dom1120. NS a.root-servers.nil. +dom1121. NS a.root-servers.nil. +dom1122. NS a.root-servers.nil. +dom1123. NS a.root-servers.nil. +dom1124. NS a.root-servers.nil. +dom1125. NS a.root-servers.nil. +dom1126. NS a.root-servers.nil. +dom1127. NS a.root-servers.nil. +dom1128. NS a.root-servers.nil. +dom1129. NS a.root-servers.nil. +dom1130. NS a.root-servers.nil. +dom1131. NS a.root-servers.nil. +dom1132. NS a.root-servers.nil. +dom1133. NS a.root-servers.nil. +dom1134. NS a.root-servers.nil. +dom1135. NS a.root-servers.nil. +dom1136. NS a.root-servers.nil. +dom1137. NS a.root-servers.nil. +dom1138. NS a.root-servers.nil. +dom1139. NS a.root-servers.nil. +dom1140. NS a.root-servers.nil. +dom1141. NS a.root-servers.nil. +dom1142. NS a.root-servers.nil. +dom1143. NS a.root-servers.nil. +dom1144. NS a.root-servers.nil. +dom1145. NS a.root-servers.nil. +dom1146. NS a.root-servers.nil. +dom1147. NS a.root-servers.nil. +dom1148. NS a.root-servers.nil. +dom1149. NS a.root-servers.nil. +dom1150. NS a.root-servers.nil. +dom1151. NS a.root-servers.nil. +dom1152. NS a.root-servers.nil. +dom1153. NS a.root-servers.nil. +dom1154. NS a.root-servers.nil. +dom1155. NS a.root-servers.nil. +dom1156. NS a.root-servers.nil. +dom1157. NS a.root-servers.nil. +dom1158. NS a.root-servers.nil. +dom1159. NS a.root-servers.nil. +dom1160. NS a.root-servers.nil. +dom1161. NS a.root-servers.nil. +dom1162. NS a.root-servers.nil. +dom1163. NS a.root-servers.nil. +dom1164. NS a.root-servers.nil. +dom1165. NS a.root-servers.nil. +dom1166. NS a.root-servers.nil. +dom1167. NS a.root-servers.nil. +dom1168. NS a.root-servers.nil. +dom1169. NS a.root-servers.nil. +dom1170. NS a.root-servers.nil. +dom1171. NS a.root-servers.nil. +dom1172. NS a.root-servers.nil. +dom1173. NS a.root-servers.nil. +dom1174. NS a.root-servers.nil. +dom1175. NS a.root-servers.nil. +dom1176. NS a.root-servers.nil. +dom1177. NS a.root-servers.nil. +dom1178. NS a.root-servers.nil. +dom1179. NS a.root-servers.nil. +dom1180. NS a.root-servers.nil. +dom1181. NS a.root-servers.nil. +dom1182. NS a.root-servers.nil. +dom1183. NS a.root-servers.nil. +dom1184. NS a.root-servers.nil. +dom1185. NS a.root-servers.nil. +dom1186. NS a.root-servers.nil. +dom1187. NS a.root-servers.nil. +dom1188. NS a.root-servers.nil. +dom1189. NS a.root-servers.nil. +dom1190. NS a.root-servers.nil. +dom1191. NS a.root-servers.nil. +dom1192. NS a.root-servers.nil. +dom1193. NS a.root-servers.nil. +dom1194. NS a.root-servers.nil. +dom1195. NS a.root-servers.nil. +dom1196. NS a.root-servers.nil. +dom1197. NS a.root-servers.nil. +dom1198. NS a.root-servers.nil. +dom1199. NS a.root-servers.nil. +dom1200. NS a.root-servers.nil. +dom1201. NS a.root-servers.nil. +dom1202. NS a.root-servers.nil. +dom1203. NS a.root-servers.nil. +dom1204. NS a.root-servers.nil. +dom1205. NS a.root-servers.nil. +dom1206. NS a.root-servers.nil. +dom1207. NS a.root-servers.nil. +dom1208. NS a.root-servers.nil. +dom1209. NS a.root-servers.nil. +dom1210. NS a.root-servers.nil. +dom1211. NS a.root-servers.nil. +dom1212. NS a.root-servers.nil. +dom1213. NS a.root-servers.nil. +dom1214. NS a.root-servers.nil. +dom1215. NS a.root-servers.nil. +dom1216. NS a.root-servers.nil. +dom1217. NS a.root-servers.nil. +dom1218. NS a.root-servers.nil. +dom1219. NS a.root-servers.nil. +dom1220. NS a.root-servers.nil. +dom1221. NS a.root-servers.nil. +dom1222. NS a.root-servers.nil. +dom1223. NS a.root-servers.nil. +dom1224. NS a.root-servers.nil. +dom1225. NS a.root-servers.nil. +dom1226. NS a.root-servers.nil. +dom1227. NS a.root-servers.nil. +dom1228. NS a.root-servers.nil. +dom1229. NS a.root-servers.nil. +dom1230. NS a.root-servers.nil. +dom1231. NS a.root-servers.nil. +dom1232. NS a.root-servers.nil. +dom1233. NS a.root-servers.nil. +dom1234. NS a.root-servers.nil. +dom1235. NS a.root-servers.nil. +dom1236. NS a.root-servers.nil. +dom1237. NS a.root-servers.nil. +dom1238. NS a.root-servers.nil. +dom1239. NS a.root-servers.nil. +dom1240. NS a.root-servers.nil. +dom1241. NS a.root-servers.nil. +dom1242. NS a.root-servers.nil. +dom1243. NS a.root-servers.nil. +dom1244. NS a.root-servers.nil. +dom1245. NS a.root-servers.nil. +dom1246. NS a.root-servers.nil. +dom1247. NS a.root-servers.nil. +dom1248. NS a.root-servers.nil. +dom1249. NS a.root-servers.nil. +dom1250. NS a.root-servers.nil. +dom1251. NS a.root-servers.nil. +dom1252. NS a.root-servers.nil. +dom1253. NS a.root-servers.nil. +dom1254. NS a.root-servers.nil. +dom1255. NS a.root-servers.nil. +dom1256. NS a.root-servers.nil. +dom1257. NS a.root-servers.nil. +dom1258. NS a.root-servers.nil. +dom1259. NS a.root-servers.nil. +dom1260. NS a.root-servers.nil. +dom1261. NS a.root-servers.nil. +dom1262. NS a.root-servers.nil. +dom1263. NS a.root-servers.nil. +dom1264. NS a.root-servers.nil. +dom1265. NS a.root-servers.nil. +dom1266. NS a.root-servers.nil. +dom1267. NS a.root-servers.nil. +dom1268. NS a.root-servers.nil. +dom1269. NS a.root-servers.nil. +dom1270. NS a.root-servers.nil. +dom1271. NS a.root-servers.nil. +dom1272. NS a.root-servers.nil. +dom1273. NS a.root-servers.nil. +dom1274. NS a.root-servers.nil. +dom1275. NS a.root-servers.nil. +dom1276. NS a.root-servers.nil. +dom1277. NS a.root-servers.nil. +dom1278. NS a.root-servers.nil. +dom1279. NS a.root-servers.nil. +dom1280. NS a.root-servers.nil. +dom1281. NS a.root-servers.nil. +dom1282. NS a.root-servers.nil. +dom1283. NS a.root-servers.nil. +dom1284. NS a.root-servers.nil. +dom1285. NS a.root-servers.nil. +dom1286. NS a.root-servers.nil. +dom1287. NS a.root-servers.nil. +dom1288. NS a.root-servers.nil. +dom1289. NS a.root-servers.nil. +dom1290. NS a.root-servers.nil. +dom1291. NS a.root-servers.nil. +dom1292. NS a.root-servers.nil. +dom1293. NS a.root-servers.nil. +dom1294. NS a.root-servers.nil. +dom1295. NS a.root-servers.nil. +dom1296. NS a.root-servers.nil. +dom1297. NS a.root-servers.nil. +dom1298. NS a.root-servers.nil. +dom1299. NS a.root-servers.nil. +dom1300. NS a.root-servers.nil. +dom1301. NS a.root-servers.nil. +dom1302. NS a.root-servers.nil. +dom1303. NS a.root-servers.nil. +dom1304. NS a.root-servers.nil. +dom1305. NS a.root-servers.nil. +dom1306. NS a.root-servers.nil. +dom1307. NS a.root-servers.nil. +dom1308. NS a.root-servers.nil. +dom1309. NS a.root-servers.nil. +dom1310. NS a.root-servers.nil. +dom1311. NS a.root-servers.nil. +dom1312. NS a.root-servers.nil. +dom1313. NS a.root-servers.nil. +dom1314. NS a.root-servers.nil. +dom1315. NS a.root-servers.nil. +dom1316. NS a.root-servers.nil. +dom1317. NS a.root-servers.nil. +dom1318. NS a.root-servers.nil. +dom1319. NS a.root-servers.nil. +dom1320. NS a.root-servers.nil. +dom1321. NS a.root-servers.nil. +dom1322. NS a.root-servers.nil. +dom1323. NS a.root-servers.nil. +dom1324. NS a.root-servers.nil. +dom1325. NS a.root-servers.nil. +dom1326. NS a.root-servers.nil. +dom1327. NS a.root-servers.nil. +dom1328. NS a.root-servers.nil. +dom1329. NS a.root-servers.nil. +dom1330. NS a.root-servers.nil. +dom1331. NS a.root-servers.nil. +dom1332. NS a.root-servers.nil. +dom1333. NS a.root-servers.nil. +dom1334. NS a.root-servers.nil. +dom1335. NS a.root-servers.nil. +dom1336. NS a.root-servers.nil. +dom1337. NS a.root-servers.nil. +dom1338. NS a.root-servers.nil. +dom1339. NS a.root-servers.nil. +dom1340. NS a.root-servers.nil. +dom1341. NS a.root-servers.nil. +dom1342. NS a.root-servers.nil. +dom1343. NS a.root-servers.nil. +dom1344. NS a.root-servers.nil. +dom1345. NS a.root-servers.nil. +dom1346. NS a.root-servers.nil. +dom1347. NS a.root-servers.nil. +dom1348. NS a.root-servers.nil. +dom1349. NS a.root-servers.nil. +dom1350. NS a.root-servers.nil. +dom1351. NS a.root-servers.nil. +dom1352. NS a.root-servers.nil. +dom1353. NS a.root-servers.nil. +dom1354. NS a.root-servers.nil. +dom1355. NS a.root-servers.nil. +dom1356. NS a.root-servers.nil. +dom1357. NS a.root-servers.nil. +dom1358. NS a.root-servers.nil. +dom1359. NS a.root-servers.nil. +dom1360. NS a.root-servers.nil. +dom1361. NS a.root-servers.nil. +dom1362. NS a.root-servers.nil. +dom1363. NS a.root-servers.nil. +dom1364. NS a.root-servers.nil. +dom1365. NS a.root-servers.nil. +dom1366. NS a.root-servers.nil. +dom1367. NS a.root-servers.nil. +dom1368. NS a.root-servers.nil. +dom1369. NS a.root-servers.nil. +dom1370. NS a.root-servers.nil. +dom1371. NS a.root-servers.nil. +dom1372. NS a.root-servers.nil. +dom1373. NS a.root-servers.nil. +dom1374. NS a.root-servers.nil. +dom1375. NS a.root-servers.nil. +dom1376. NS a.root-servers.nil. +dom1377. NS a.root-servers.nil. +dom1378. NS a.root-servers.nil. +dom1379. NS a.root-servers.nil. +dom1380. NS a.root-servers.nil. +dom1381. NS a.root-servers.nil. +dom1382. NS a.root-servers.nil. +dom1383. NS a.root-servers.nil. +dom1384. NS a.root-servers.nil. +dom1385. NS a.root-servers.nil. +dom1386. NS a.root-servers.nil. +dom1387. NS a.root-servers.nil. +dom1388. NS a.root-servers.nil. +dom1389. NS a.root-servers.nil. +dom1390. NS a.root-servers.nil. +dom1391. NS a.root-servers.nil. +dom1392. NS a.root-servers.nil. +dom1393. NS a.root-servers.nil. +dom1394. NS a.root-servers.nil. +dom1395. NS a.root-servers.nil. +dom1396. NS a.root-servers.nil. +dom1397. NS a.root-servers.nil. +dom1398. NS a.root-servers.nil. +dom1399. NS a.root-servers.nil. +dom1400. NS a.root-servers.nil. +dom1401. NS a.root-servers.nil. +dom1402. NS a.root-servers.nil. +dom1403. NS a.root-servers.nil. +dom1404. NS a.root-servers.nil. +dom1405. NS a.root-servers.nil. +dom1406. NS a.root-servers.nil. +dom1407. NS a.root-servers.nil. +dom1408. NS a.root-servers.nil. +dom1409. NS a.root-servers.nil. +dom1410. NS a.root-servers.nil. +dom1411. NS a.root-servers.nil. +dom1412. NS a.root-servers.nil. +dom1413. NS a.root-servers.nil. +dom1414. NS a.root-servers.nil. +dom1415. NS a.root-servers.nil. +dom1416. NS a.root-servers.nil. +dom1417. NS a.root-servers.nil. +dom1418. NS a.root-servers.nil. +dom1419. NS a.root-servers.nil. +dom1420. NS a.root-servers.nil. +dom1421. NS a.root-servers.nil. +dom1422. NS a.root-servers.nil. +dom1423. NS a.root-servers.nil. +dom1424. NS a.root-servers.nil. +dom1425. NS a.root-servers.nil. +dom1426. NS a.root-servers.nil. +dom1427. NS a.root-servers.nil. +dom1428. NS a.root-servers.nil. +dom1429. NS a.root-servers.nil. +dom1430. NS a.root-servers.nil. +dom1431. NS a.root-servers.nil. +dom1432. NS a.root-servers.nil. +dom1433. NS a.root-servers.nil. +dom1434. NS a.root-servers.nil. +dom1435. NS a.root-servers.nil. +dom1436. NS a.root-servers.nil. +dom1437. NS a.root-servers.nil. +dom1438. NS a.root-servers.nil. +dom1439. NS a.root-servers.nil. +dom1440. NS a.root-servers.nil. +dom1441. NS a.root-servers.nil. +dom1442. NS a.root-servers.nil. +dom1443. NS a.root-servers.nil. +dom1444. NS a.root-servers.nil. +dom1445. NS a.root-servers.nil. +dom1446. NS a.root-servers.nil. +dom1447. NS a.root-servers.nil. +dom1448. NS a.root-servers.nil. +dom1449. NS a.root-servers.nil. +dom1450. NS a.root-servers.nil. +dom1451. NS a.root-servers.nil. +dom1452. NS a.root-servers.nil. +dom1453. NS a.root-servers.nil. +dom1454. NS a.root-servers.nil. +dom1455. NS a.root-servers.nil. +dom1456. NS a.root-servers.nil. +dom1457. NS a.root-servers.nil. +dom1458. NS a.root-servers.nil. +dom1459. NS a.root-servers.nil. +dom1460. NS a.root-servers.nil. +dom1461. NS a.root-servers.nil. +dom1462. NS a.root-servers.nil. +dom1463. NS a.root-servers.nil. +dom1464. NS a.root-servers.nil. +dom1465. NS a.root-servers.nil. +dom1466. NS a.root-servers.nil. +dom1467. NS a.root-servers.nil. +dom1468. NS a.root-servers.nil. +dom1469. NS a.root-servers.nil. +dom1470. NS a.root-servers.nil. +dom1471. NS a.root-servers.nil. +dom1472. NS a.root-servers.nil. +dom1473. NS a.root-servers.nil. +dom1474. NS a.root-servers.nil. +dom1475. NS a.root-servers.nil. +dom1476. NS a.root-servers.nil. +dom1477. NS a.root-servers.nil. +dom1478. NS a.root-servers.nil. +dom1479. NS a.root-servers.nil. +dom1480. NS a.root-servers.nil. +dom1481. NS a.root-servers.nil. +dom1482. NS a.root-servers.nil. +dom1483. NS a.root-servers.nil. +dom1484. NS a.root-servers.nil. +dom1485. NS a.root-servers.nil. +dom1486. NS a.root-servers.nil. +dom1487. NS a.root-servers.nil. +dom1488. NS a.root-servers.nil. +dom1489. NS a.root-servers.nil. +dom1490. NS a.root-servers.nil. +dom1491. NS a.root-servers.nil. +dom1492. NS a.root-servers.nil. +dom1493. NS a.root-servers.nil. +dom1494. NS a.root-servers.nil. +dom1495. NS a.root-servers.nil. +dom1496. NS a.root-servers.nil. +dom1497. NS a.root-servers.nil. +dom1498. NS a.root-servers.nil. +dom1499. NS a.root-servers.nil. +dom1500. NS a.root-servers.nil. +dom1501. NS a.root-servers.nil. +dom1502. NS a.root-servers.nil. +dom1503. NS a.root-servers.nil. +dom1504. NS a.root-servers.nil. +dom1505. NS a.root-servers.nil. +dom1506. NS a.root-servers.nil. +dom1507. NS a.root-servers.nil. +dom1508. NS a.root-servers.nil. +dom1509. NS a.root-servers.nil. +dom1510. NS a.root-servers.nil. +dom1511. NS a.root-servers.nil. +dom1512. NS a.root-servers.nil. +dom1513. NS a.root-servers.nil. +dom1514. NS a.root-servers.nil. +dom1515. NS a.root-servers.nil. +dom1516. NS a.root-servers.nil. +dom1517. NS a.root-servers.nil. +dom1518. NS a.root-servers.nil. +dom1519. NS a.root-servers.nil. +dom1520. NS a.root-servers.nil. +dom1521. NS a.root-servers.nil. +dom1522. NS a.root-servers.nil. +dom1523. NS a.root-servers.nil. +dom1524. NS a.root-servers.nil. +dom1525. NS a.root-servers.nil. +dom1526. NS a.root-servers.nil. +dom1527. NS a.root-servers.nil. +dom1528. NS a.root-servers.nil. +dom1529. NS a.root-servers.nil. +dom1530. NS a.root-servers.nil. +dom1531. NS a.root-servers.nil. +dom1532. NS a.root-servers.nil. +dom1533. NS a.root-servers.nil. +dom1534. NS a.root-servers.nil. +dom1535. NS a.root-servers.nil. +dom1536. NS a.root-servers.nil. +dom1537. NS a.root-servers.nil. +dom1538. NS a.root-servers.nil. +dom1539. NS a.root-servers.nil. +dom1540. NS a.root-servers.nil. +dom1541. NS a.root-servers.nil. +dom1542. NS a.root-servers.nil. +dom1543. NS a.root-servers.nil. +dom1544. NS a.root-servers.nil. +dom1545. NS a.root-servers.nil. +dom1546. NS a.root-servers.nil. +dom1547. NS a.root-servers.nil. +dom1548. NS a.root-servers.nil. +dom1549. NS a.root-servers.nil. +dom1550. NS a.root-servers.nil. +dom1551. NS a.root-servers.nil. +dom1552. NS a.root-servers.nil. +dom1553. NS a.root-servers.nil. +dom1554. NS a.root-servers.nil. +dom1555. NS a.root-servers.nil. +dom1556. NS a.root-servers.nil. +dom1557. NS a.root-servers.nil. +dom1558. NS a.root-servers.nil. +dom1559. NS a.root-servers.nil. +dom1560. NS a.root-servers.nil. +dom1561. NS a.root-servers.nil. +dom1562. NS a.root-servers.nil. +dom1563. NS a.root-servers.nil. +dom1564. NS a.root-servers.nil. +dom1565. NS a.root-servers.nil. +dom1566. NS a.root-servers.nil. +dom1567. NS a.root-servers.nil. +dom1568. NS a.root-servers.nil. +dom1569. NS a.root-servers.nil. +dom1570. NS a.root-servers.nil. +dom1571. NS a.root-servers.nil. +dom1572. NS a.root-servers.nil. +dom1573. NS a.root-servers.nil. +dom1574. NS a.root-servers.nil. +dom1575. NS a.root-servers.nil. +dom1576. NS a.root-servers.nil. +dom1577. NS a.root-servers.nil. +dom1578. NS a.root-servers.nil. +dom1579. NS a.root-servers.nil. +dom1580. NS a.root-servers.nil. +dom1581. NS a.root-servers.nil. +dom1582. NS a.root-servers.nil. +dom1583. NS a.root-servers.nil. +dom1584. NS a.root-servers.nil. +dom1585. NS a.root-servers.nil. +dom1586. NS a.root-servers.nil. +dom1587. NS a.root-servers.nil. +dom1588. NS a.root-servers.nil. +dom1589. NS a.root-servers.nil. +dom1590. NS a.root-servers.nil. +dom1591. NS a.root-servers.nil. +dom1592. NS a.root-servers.nil. +dom1593. NS a.root-servers.nil. +dom1594. NS a.root-servers.nil. +dom1595. NS a.root-servers.nil. +dom1596. NS a.root-servers.nil. +dom1597. NS a.root-servers.nil. +dom1598. NS a.root-servers.nil. +dom1599. NS a.root-servers.nil. +dom1600. NS a.root-servers.nil. +dom1601. NS a.root-servers.nil. +dom1602. NS a.root-servers.nil. +dom1603. NS a.root-servers.nil. +dom1604. NS a.root-servers.nil. +dom1605. NS a.root-servers.nil. +dom1606. NS a.root-servers.nil. +dom1607. NS a.root-servers.nil. +dom1608. NS a.root-servers.nil. +dom1609. NS a.root-servers.nil. +dom1610. NS a.root-servers.nil. +dom1611. NS a.root-servers.nil. +dom1612. NS a.root-servers.nil. +dom1613. NS a.root-servers.nil. +dom1614. NS a.root-servers.nil. +dom1615. NS a.root-servers.nil. +dom1616. NS a.root-servers.nil. +dom1617. NS a.root-servers.nil. +dom1618. NS a.root-servers.nil. +dom1619. NS a.root-servers.nil. +dom1620. NS a.root-servers.nil. +dom1621. NS a.root-servers.nil. +dom1622. NS a.root-servers.nil. +dom1623. NS a.root-servers.nil. +dom1624. NS a.root-servers.nil. +dom1625. NS a.root-servers.nil. +dom1626. NS a.root-servers.nil. +dom1627. NS a.root-servers.nil. +dom1628. NS a.root-servers.nil. +dom1629. NS a.root-servers.nil. +dom1630. NS a.root-servers.nil. +dom1631. NS a.root-servers.nil. +dom1632. NS a.root-servers.nil. +dom1633. NS a.root-servers.nil. +dom1634. NS a.root-servers.nil. +dom1635. NS a.root-servers.nil. +dom1636. NS a.root-servers.nil. +dom1637. NS a.root-servers.nil. +dom1638. NS a.root-servers.nil. +dom1639. NS a.root-servers.nil. +dom1640. NS a.root-servers.nil. +dom1641. NS a.root-servers.nil. +dom1642. NS a.root-servers.nil. +dom1643. NS a.root-servers.nil. +dom1644. NS a.root-servers.nil. +dom1645. NS a.root-servers.nil. +dom1646. NS a.root-servers.nil. +dom1647. NS a.root-servers.nil. +dom1648. NS a.root-servers.nil. +dom1649. NS a.root-servers.nil. +dom1650. NS a.root-servers.nil. +dom1651. NS a.root-servers.nil. +dom1652. NS a.root-servers.nil. +dom1653. NS a.root-servers.nil. +dom1654. NS a.root-servers.nil. +dom1655. NS a.root-servers.nil. +dom1656. NS a.root-servers.nil. +dom1657. NS a.root-servers.nil. +dom1658. NS a.root-servers.nil. +dom1659. NS a.root-servers.nil. +dom1660. NS a.root-servers.nil. +dom1661. NS a.root-servers.nil. +dom1662. NS a.root-servers.nil. +dom1663. NS a.root-servers.nil. +dom1664. NS a.root-servers.nil. +dom1665. NS a.root-servers.nil. +dom1666. NS a.root-servers.nil. +dom1667. NS a.root-servers.nil. +dom1668. NS a.root-servers.nil. +dom1669. NS a.root-servers.nil. +dom1670. NS a.root-servers.nil. +dom1671. NS a.root-servers.nil. +dom1672. NS a.root-servers.nil. +dom1673. NS a.root-servers.nil. +dom1674. NS a.root-servers.nil. +dom1675. NS a.root-servers.nil. +dom1676. NS a.root-servers.nil. +dom1677. NS a.root-servers.nil. +dom1678. NS a.root-servers.nil. +dom1679. NS a.root-servers.nil. +dom1680. NS a.root-servers.nil. +dom1681. NS a.root-servers.nil. +dom1682. NS a.root-servers.nil. +dom1683. NS a.root-servers.nil. +dom1684. NS a.root-servers.nil. +dom1685. NS a.root-servers.nil. +dom1686. NS a.root-servers.nil. +dom1687. NS a.root-servers.nil. +dom1688. NS a.root-servers.nil. +dom1689. NS a.root-servers.nil. +dom1690. NS a.root-servers.nil. +dom1691. NS a.root-servers.nil. +dom1692. NS a.root-servers.nil. +dom1693. NS a.root-servers.nil. +dom1694. NS a.root-servers.nil. +dom1695. NS a.root-servers.nil. +dom1696. NS a.root-servers.nil. +dom1697. NS a.root-servers.nil. +dom1698. NS a.root-servers.nil. +dom1699. NS a.root-servers.nil. +dom1700. NS a.root-servers.nil. +dom1701. NS a.root-servers.nil. +dom1702. NS a.root-servers.nil. +dom1703. NS a.root-servers.nil. +dom1704. NS a.root-servers.nil. +dom1705. NS a.root-servers.nil. +dom1706. NS a.root-servers.nil. +dom1707. NS a.root-servers.nil. +dom1708. NS a.root-servers.nil. +dom1709. NS a.root-servers.nil. +dom1710. NS a.root-servers.nil. +dom1711. NS a.root-servers.nil. +dom1712. NS a.root-servers.nil. +dom1713. NS a.root-servers.nil. +dom1714. NS a.root-servers.nil. +dom1715. NS a.root-servers.nil. +dom1716. NS a.root-servers.nil. +dom1717. NS a.root-servers.nil. +dom1718. NS a.root-servers.nil. +dom1719. NS a.root-servers.nil. +dom1720. NS a.root-servers.nil. +dom1721. NS a.root-servers.nil. +dom1722. NS a.root-servers.nil. +dom1723. NS a.root-servers.nil. +dom1724. NS a.root-servers.nil. +dom1725. NS a.root-servers.nil. +dom1726. NS a.root-servers.nil. +dom1727. NS a.root-servers.nil. +dom1728. NS a.root-servers.nil. +dom1729. NS a.root-servers.nil. +dom1730. NS a.root-servers.nil. +dom1731. NS a.root-servers.nil. +dom1732. NS a.root-servers.nil. +dom1733. NS a.root-servers.nil. +dom1734. NS a.root-servers.nil. +dom1735. NS a.root-servers.nil. +dom1736. NS a.root-servers.nil. +dom1737. NS a.root-servers.nil. +dom1738. NS a.root-servers.nil. +dom1739. NS a.root-servers.nil. +dom1740. NS a.root-servers.nil. +dom1741. NS a.root-servers.nil. +dom1742. NS a.root-servers.nil. +dom1743. NS a.root-servers.nil. +dom1744. NS a.root-servers.nil. +dom1745. NS a.root-servers.nil. +dom1746. NS a.root-servers.nil. +dom1747. NS a.root-servers.nil. +dom1748. NS a.root-servers.nil. +dom1749. NS a.root-servers.nil. +dom1750. NS a.root-servers.nil. +dom1751. NS a.root-servers.nil. +dom1752. NS a.root-servers.nil. +dom1753. NS a.root-servers.nil. +dom1754. NS a.root-servers.nil. +dom1755. NS a.root-servers.nil. +dom1756. NS a.root-servers.nil. +dom1757. NS a.root-servers.nil. +dom1758. NS a.root-servers.nil. +dom1759. NS a.root-servers.nil. +dom1760. NS a.root-servers.nil. +dom1761. NS a.root-servers.nil. +dom1762. NS a.root-servers.nil. +dom1763. NS a.root-servers.nil. +dom1764. NS a.root-servers.nil. +dom1765. NS a.root-servers.nil. +dom1766. NS a.root-servers.nil. +dom1767. NS a.root-servers.nil. +dom1768. NS a.root-servers.nil. +dom1769. NS a.root-servers.nil. +dom1770. NS a.root-servers.nil. +dom1771. NS a.root-servers.nil. +dom1772. NS a.root-servers.nil. +dom1773. NS a.root-servers.nil. +dom1774. NS a.root-servers.nil. +dom1775. NS a.root-servers.nil. +dom1776. NS a.root-servers.nil. +dom1777. NS a.root-servers.nil. +dom1778. NS a.root-servers.nil. +dom1779. NS a.root-servers.nil. +dom1780. NS a.root-servers.nil. +dom1781. NS a.root-servers.nil. +dom1782. NS a.root-servers.nil. +dom1783. NS a.root-servers.nil. +dom1784. NS a.root-servers.nil. +dom1785. NS a.root-servers.nil. +dom1786. NS a.root-servers.nil. +dom1787. NS a.root-servers.nil. +dom1788. NS a.root-servers.nil. +dom1789. NS a.root-servers.nil. +dom1790. NS a.root-servers.nil. +dom1791. NS a.root-servers.nil. +dom1792. NS a.root-servers.nil. +dom1793. NS a.root-servers.nil. +dom1794. NS a.root-servers.nil. +dom1795. NS a.root-servers.nil. +dom1796. NS a.root-servers.nil. +dom1797. NS a.root-servers.nil. +dom1798. NS a.root-servers.nil. +dom1799. NS a.root-servers.nil. +dom1800. NS a.root-servers.nil. +dom1801. NS a.root-servers.nil. +dom1802. NS a.root-servers.nil. +dom1803. NS a.root-servers.nil. +dom1804. NS a.root-servers.nil. +dom1805. NS a.root-servers.nil. +dom1806. NS a.root-servers.nil. +dom1807. NS a.root-servers.nil. +dom1808. NS a.root-servers.nil. +dom1809. NS a.root-servers.nil. +dom1810. NS a.root-servers.nil. +dom1811. NS a.root-servers.nil. +dom1812. NS a.root-servers.nil. +dom1813. NS a.root-servers.nil. +dom1814. NS a.root-servers.nil. +dom1815. NS a.root-servers.nil. +dom1816. NS a.root-servers.nil. +dom1817. NS a.root-servers.nil. +dom1818. NS a.root-servers.nil. +dom1819. NS a.root-servers.nil. +dom1820. NS a.root-servers.nil. +dom1821. NS a.root-servers.nil. +dom1822. NS a.root-servers.nil. +dom1823. NS a.root-servers.nil. +dom1824. NS a.root-servers.nil. +dom1825. NS a.root-servers.nil. +dom1826. NS a.root-servers.nil. +dom1827. NS a.root-servers.nil. +dom1828. NS a.root-servers.nil. +dom1829. NS a.root-servers.nil. +dom1830. NS a.root-servers.nil. +dom1831. NS a.root-servers.nil. +dom1832. NS a.root-servers.nil. +dom1833. NS a.root-servers.nil. +dom1834. NS a.root-servers.nil. +dom1835. NS a.root-servers.nil. +dom1836. NS a.root-servers.nil. +dom1837. NS a.root-servers.nil. +dom1838. NS a.root-servers.nil. +dom1839. NS a.root-servers.nil. +dom1840. NS a.root-servers.nil. +dom1841. NS a.root-servers.nil. +dom1842. NS a.root-servers.nil. +dom1843. NS a.root-servers.nil. +dom1844. NS a.root-servers.nil. +dom1845. NS a.root-servers.nil. +dom1846. NS a.root-servers.nil. +dom1847. NS a.root-servers.nil. +dom1848. NS a.root-servers.nil. +dom1849. NS a.root-servers.nil. +dom1850. NS a.root-servers.nil. +dom1851. NS a.root-servers.nil. +dom1852. NS a.root-servers.nil. +dom1853. NS a.root-servers.nil. +dom1854. NS a.root-servers.nil. +dom1855. NS a.root-servers.nil. +dom1856. NS a.root-servers.nil. +dom1857. NS a.root-servers.nil. +dom1858. NS a.root-servers.nil. +dom1859. NS a.root-servers.nil. +dom1860. NS a.root-servers.nil. +dom1861. NS a.root-servers.nil. +dom1862. NS a.root-servers.nil. +dom1863. NS a.root-servers.nil. +dom1864. NS a.root-servers.nil. +dom1865. NS a.root-servers.nil. +dom1866. NS a.root-servers.nil. +dom1867. NS a.root-servers.nil. +dom1868. NS a.root-servers.nil. +dom1869. NS a.root-servers.nil. +dom1870. NS a.root-servers.nil. +dom1871. NS a.root-servers.nil. +dom1872. NS a.root-servers.nil. +dom1873. NS a.root-servers.nil. +dom1874. NS a.root-servers.nil. +dom1875. NS a.root-servers.nil. +dom1876. NS a.root-servers.nil. +dom1877. NS a.root-servers.nil. +dom1878. NS a.root-servers.nil. +dom1879. NS a.root-servers.nil. +dom1880. NS a.root-servers.nil. +dom1881. NS a.root-servers.nil. +dom1882. NS a.root-servers.nil. +dom1883. NS a.root-servers.nil. +dom1884. NS a.root-servers.nil. +dom1885. NS a.root-servers.nil. +dom1886. NS a.root-servers.nil. +dom1887. NS a.root-servers.nil. +dom1888. NS a.root-servers.nil. +dom1889. NS a.root-servers.nil. +dom1890. NS a.root-servers.nil. +dom1891. NS a.root-servers.nil. +dom1892. NS a.root-servers.nil. +dom1893. NS a.root-servers.nil. +dom1894. NS a.root-servers.nil. +dom1895. NS a.root-servers.nil. +dom1896. NS a.root-servers.nil. +dom1897. NS a.root-servers.nil. +dom1898. NS a.root-servers.nil. +dom1899. NS a.root-servers.nil. +dom1900. NS a.root-servers.nil. +dom1901. NS a.root-servers.nil. +dom1902. NS a.root-servers.nil. +dom1903. NS a.root-servers.nil. +dom1904. NS a.root-servers.nil. +dom1905. NS a.root-servers.nil. +dom1906. NS a.root-servers.nil. +dom1907. NS a.root-servers.nil. +dom1908. NS a.root-servers.nil. +dom1909. NS a.root-servers.nil. +dom1910. NS a.root-servers.nil. +dom1911. NS a.root-servers.nil. +dom1912. NS a.root-servers.nil. +dom1913. NS a.root-servers.nil. +dom1914. NS a.root-servers.nil. +dom1915. NS a.root-servers.nil. +dom1916. NS a.root-servers.nil. +dom1917. NS a.root-servers.nil. +dom1918. NS a.root-servers.nil. +dom1919. NS a.root-servers.nil. +dom1920. NS a.root-servers.nil. +dom1921. NS a.root-servers.nil. +dom1922. NS a.root-servers.nil. +dom1923. NS a.root-servers.nil. +dom1924. NS a.root-servers.nil. +dom1925. NS a.root-servers.nil. +dom1926. NS a.root-servers.nil. +dom1927. NS a.root-servers.nil. +dom1928. NS a.root-servers.nil. +dom1929. NS a.root-servers.nil. +dom1930. NS a.root-servers.nil. +dom1931. NS a.root-servers.nil. +dom1932. NS a.root-servers.nil. +dom1933. NS a.root-servers.nil. +dom1934. NS a.root-servers.nil. +dom1935. NS a.root-servers.nil. +dom1936. NS a.root-servers.nil. +dom1937. NS a.root-servers.nil. +dom1938. NS a.root-servers.nil. +dom1939. NS a.root-servers.nil. +dom1940. NS a.root-servers.nil. +dom1941. NS a.root-servers.nil. +dom1942. NS a.root-servers.nil. +dom1943. NS a.root-servers.nil. +dom1944. NS a.root-servers.nil. +dom1945. NS a.root-servers.nil. +dom1946. NS a.root-servers.nil. +dom1947. NS a.root-servers.nil. +dom1948. NS a.root-servers.nil. +dom1949. NS a.root-servers.nil. +dom1950. NS a.root-servers.nil. +dom1951. NS a.root-servers.nil. +dom1952. NS a.root-servers.nil. +dom1953. NS a.root-servers.nil. +dom1954. NS a.root-servers.nil. +dom1955. NS a.root-servers.nil. +dom1956. NS a.root-servers.nil. +dom1957. NS a.root-servers.nil. +dom1958. NS a.root-servers.nil. +dom1959. NS a.root-servers.nil. +dom1960. NS a.root-servers.nil. +dom1961. NS a.root-servers.nil. +dom1962. NS a.root-servers.nil. +dom1963. NS a.root-servers.nil. +dom1964. NS a.root-servers.nil. +dom1965. NS a.root-servers.nil. +dom1966. NS a.root-servers.nil. +dom1967. NS a.root-servers.nil. +dom1968. NS a.root-servers.nil. +dom1969. NS a.root-servers.nil. +dom1970. NS a.root-servers.nil. +dom1971. NS a.root-servers.nil. +dom1972. NS a.root-servers.nil. +dom1973. NS a.root-servers.nil. +dom1974. NS a.root-servers.nil. +dom1975. NS a.root-servers.nil. +dom1976. NS a.root-servers.nil. +dom1977. NS a.root-servers.nil. +dom1978. NS a.root-servers.nil. +dom1979. NS a.root-servers.nil. +dom1980. NS a.root-servers.nil. +dom1981. NS a.root-servers.nil. +dom1982. NS a.root-servers.nil. +dom1983. NS a.root-servers.nil. +dom1984. NS a.root-servers.nil. +dom1985. NS a.root-servers.nil. +dom1986. NS a.root-servers.nil. +dom1987. NS a.root-servers.nil. +dom1988. NS a.root-servers.nil. +dom1989. NS a.root-servers.nil. +dom1990. NS a.root-servers.nil. +dom1991. NS a.root-servers.nil. +dom1992. NS a.root-servers.nil. +dom1993. NS a.root-servers.nil. +dom1994. NS a.root-servers.nil. +dom1995. NS a.root-servers.nil. +dom1996. NS a.root-servers.nil. +dom1997. NS a.root-servers.nil. +dom1998. NS a.root-servers.nil. +dom1999. NS a.root-servers.nil. +dom2000. NS a.root-servers.nil. +dom2001. NS a.root-servers.nil. +dom2002. NS a.root-servers.nil. +dom2003. NS a.root-servers.nil. +dom2004. NS a.root-servers.nil. +dom2005. NS a.root-servers.nil. +dom2006. NS a.root-servers.nil. +dom2007. NS a.root-servers.nil. +dom2008. NS a.root-servers.nil. +dom2009. NS a.root-servers.nil. +dom2010. NS a.root-servers.nil. +dom2011. NS a.root-servers.nil. +dom2012. NS a.root-servers.nil. +dom2013. NS a.root-servers.nil. +dom2014. NS a.root-servers.nil. +dom2015. NS a.root-servers.nil. +dom2016. NS a.root-servers.nil. +dom2017. NS a.root-servers.nil. +dom2018. NS a.root-servers.nil. +dom2019. NS a.root-servers.nil. +dom2020. NS a.root-servers.nil. +dom2021. NS a.root-servers.nil. +dom2022. NS a.root-servers.nil. +dom2023. NS a.root-servers.nil. +dom2024. NS a.root-servers.nil. +dom2025. NS a.root-servers.nil. +dom2026. NS a.root-servers.nil. +dom2027. NS a.root-servers.nil. +dom2028. NS a.root-servers.nil. +dom2029. NS a.root-servers.nil. +dom2030. NS a.root-servers.nil. +dom2031. NS a.root-servers.nil. +dom2032. NS a.root-servers.nil. +dom2033. NS a.root-servers.nil. +dom2034. NS a.root-servers.nil. +dom2035. NS a.root-servers.nil. +dom2036. NS a.root-servers.nil. +dom2037. NS a.root-servers.nil. +dom2038. NS a.root-servers.nil. +dom2039. NS a.root-servers.nil. +dom2040. NS a.root-servers.nil. +dom2041. NS a.root-servers.nil. +dom2042. NS a.root-servers.nil. +dom2043. NS a.root-servers.nil. +dom2044. NS a.root-servers.nil. +dom2045. NS a.root-servers.nil. +dom2046. NS a.root-servers.nil. +dom2047. NS a.root-servers.nil. +dom2048. NS a.root-servers.nil. +dom2049. NS a.root-servers.nil. +dom2050. NS a.root-servers.nil. +dom2051. NS a.root-servers.nil. +dom2052. NS a.root-servers.nil. +dom2053. NS a.root-servers.nil. +dom2054. NS a.root-servers.nil. +dom2055. NS a.root-servers.nil. +dom2056. NS a.root-servers.nil. +dom2057. NS a.root-servers.nil. +dom2058. NS a.root-servers.nil. +dom2059. NS a.root-servers.nil. +dom2060. NS a.root-servers.nil. +dom2061. NS a.root-servers.nil. +dom2062. NS a.root-servers.nil. +dom2063. NS a.root-servers.nil. +dom2064. NS a.root-servers.nil. +dom2065. NS a.root-servers.nil. +dom2066. NS a.root-servers.nil. +dom2067. NS a.root-servers.nil. +dom2068. NS a.root-servers.nil. +dom2069. NS a.root-servers.nil. +dom2070. NS a.root-servers.nil. +dom2071. NS a.root-servers.nil. +dom2072. NS a.root-servers.nil. +dom2073. NS a.root-servers.nil. +dom2074. NS a.root-servers.nil. +dom2075. NS a.root-servers.nil. +dom2076. NS a.root-servers.nil. +dom2077. NS a.root-servers.nil. +dom2078. NS a.root-servers.nil. +dom2079. NS a.root-servers.nil. +dom2080. NS a.root-servers.nil. +dom2081. NS a.root-servers.nil. +dom2082. NS a.root-servers.nil. +dom2083. NS a.root-servers.nil. +dom2084. NS a.root-servers.nil. +dom2085. NS a.root-servers.nil. +dom2086. NS a.root-servers.nil. +dom2087. NS a.root-servers.nil. +dom2088. NS a.root-servers.nil. +dom2089. NS a.root-servers.nil. +dom2090. NS a.root-servers.nil. +dom2091. NS a.root-servers.nil. +dom2092. NS a.root-servers.nil. +dom2093. NS a.root-servers.nil. +dom2094. NS a.root-servers.nil. +dom2095. NS a.root-servers.nil. +dom2096. NS a.root-servers.nil. +dom2097. NS a.root-servers.nil. +dom2098. NS a.root-servers.nil. +dom2099. NS a.root-servers.nil. +dom2100. NS a.root-servers.nil. +dom2101. NS a.root-servers.nil. +dom2102. NS a.root-servers.nil. +dom2103. NS a.root-servers.nil. +dom2104. NS a.root-servers.nil. +dom2105. NS a.root-servers.nil. +dom2106. NS a.root-servers.nil. +dom2107. NS a.root-servers.nil. +dom2108. NS a.root-servers.nil. +dom2109. NS a.root-servers.nil. +dom2110. NS a.root-servers.nil. +dom2111. NS a.root-servers.nil. +dom2112. NS a.root-servers.nil. +dom2113. NS a.root-servers.nil. +dom2114. NS a.root-servers.nil. +dom2115. NS a.root-servers.nil. +dom2116. NS a.root-servers.nil. +dom2117. NS a.root-servers.nil. +dom2118. NS a.root-servers.nil. +dom2119. NS a.root-servers.nil. +dom2120. NS a.root-servers.nil. +dom2121. NS a.root-servers.nil. +dom2122. NS a.root-servers.nil. +dom2123. NS a.root-servers.nil. +dom2124. NS a.root-servers.nil. +dom2125. NS a.root-servers.nil. +dom2126. NS a.root-servers.nil. +dom2127. NS a.root-servers.nil. +dom2128. NS a.root-servers.nil. +dom2129. NS a.root-servers.nil. +dom2130. NS a.root-servers.nil. +dom2131. NS a.root-servers.nil. +dom2132. NS a.root-servers.nil. +dom2133. NS a.root-servers.nil. +dom2134. NS a.root-servers.nil. +dom2135. NS a.root-servers.nil. +dom2136. NS a.root-servers.nil. +dom2137. NS a.root-servers.nil. +dom2138. NS a.root-servers.nil. +dom2139. NS a.root-servers.nil. +dom2140. NS a.root-servers.nil. +dom2141. NS a.root-servers.nil. +dom2142. NS a.root-servers.nil. +dom2143. NS a.root-servers.nil. +dom2144. NS a.root-servers.nil. +dom2145. NS a.root-servers.nil. +dom2146. NS a.root-servers.nil. +dom2147. NS a.root-servers.nil. +dom2148. NS a.root-servers.nil. +dom2149. NS a.root-servers.nil. +dom2150. NS a.root-servers.nil. +dom2151. NS a.root-servers.nil. +dom2152. NS a.root-servers.nil. +dom2153. NS a.root-servers.nil. +dom2154. NS a.root-servers.nil. +dom2155. NS a.root-servers.nil. +dom2156. NS a.root-servers.nil. +dom2157. NS a.root-servers.nil. +dom2158. NS a.root-servers.nil. +dom2159. NS a.root-servers.nil. +dom2160. NS a.root-servers.nil. +dom2161. NS a.root-servers.nil. +dom2162. NS a.root-servers.nil. +dom2163. NS a.root-servers.nil. +dom2164. NS a.root-servers.nil. +dom2165. NS a.root-servers.nil. +dom2166. NS a.root-servers.nil. +dom2167. NS a.root-servers.nil. +dom2168. NS a.root-servers.nil. +dom2169. NS a.root-servers.nil. +dom2170. NS a.root-servers.nil. +dom2171. NS a.root-servers.nil. +dom2172. NS a.root-servers.nil. +dom2173. NS a.root-servers.nil. +dom2174. NS a.root-servers.nil. +dom2175. NS a.root-servers.nil. +dom2176. NS a.root-servers.nil. +dom2177. NS a.root-servers.nil. +dom2178. NS a.root-servers.nil. +dom2179. NS a.root-servers.nil. +dom2180. NS a.root-servers.nil. +dom2181. NS a.root-servers.nil. +dom2182. NS a.root-servers.nil. +dom2183. NS a.root-servers.nil. +dom2184. NS a.root-servers.nil. +dom2185. NS a.root-servers.nil. +dom2186. NS a.root-servers.nil. +dom2187. NS a.root-servers.nil. +dom2188. NS a.root-servers.nil. +dom2189. NS a.root-servers.nil. +dom2190. NS a.root-servers.nil. +dom2191. NS a.root-servers.nil. +dom2192. NS a.root-servers.nil. +dom2193. NS a.root-servers.nil. +dom2194. NS a.root-servers.nil. +dom2195. NS a.root-servers.nil. +dom2196. NS a.root-servers.nil. +dom2197. NS a.root-servers.nil. +dom2198. NS a.root-servers.nil. +dom2199. NS a.root-servers.nil. +dom2200. NS a.root-servers.nil. +dom2201. NS a.root-servers.nil. +dom2202. NS a.root-servers.nil. +dom2203. NS a.root-servers.nil. +dom2204. NS a.root-servers.nil. +dom2205. NS a.root-servers.nil. +dom2206. NS a.root-servers.nil. +dom2207. NS a.root-servers.nil. +dom2208. NS a.root-servers.nil. +dom2209. NS a.root-servers.nil. +dom2210. NS a.root-servers.nil. +dom2211. NS a.root-servers.nil. +dom2212. NS a.root-servers.nil. +dom2213. NS a.root-servers.nil. +dom2214. NS a.root-servers.nil. +dom2215. NS a.root-servers.nil. +dom2216. NS a.root-servers.nil. +dom2217. NS a.root-servers.nil. +dom2218. NS a.root-servers.nil. +dom2219. NS a.root-servers.nil. +dom2220. NS a.root-servers.nil. +dom2221. NS a.root-servers.nil. +dom2222. NS a.root-servers.nil. +dom2223. NS a.root-servers.nil. +dom2224. NS a.root-servers.nil. +dom2225. NS a.root-servers.nil. +dom2226. NS a.root-servers.nil. +dom2227. NS a.root-servers.nil. +dom2228. NS a.root-servers.nil. +dom2229. NS a.root-servers.nil. +dom2230. NS a.root-servers.nil. +dom2231. NS a.root-servers.nil. +dom2232. NS a.root-servers.nil. +dom2233. NS a.root-servers.nil. +dom2234. NS a.root-servers.nil. +dom2235. NS a.root-servers.nil. +dom2236. NS a.root-servers.nil. +dom2237. NS a.root-servers.nil. +dom2238. NS a.root-servers.nil. +dom2239. NS a.root-servers.nil. +dom2240. NS a.root-servers.nil. +dom2241. NS a.root-servers.nil. +dom2242. NS a.root-servers.nil. +dom2243. NS a.root-servers.nil. +dom2244. NS a.root-servers.nil. +dom2245. NS a.root-servers.nil. +dom2246. NS a.root-servers.nil. +dom2247. NS a.root-servers.nil. +dom2248. NS a.root-servers.nil. +dom2249. NS a.root-servers.nil. +dom2250. NS a.root-servers.nil. +dom2251. NS a.root-servers.nil. +dom2252. NS a.root-servers.nil. +dom2253. NS a.root-servers.nil. +dom2254. NS a.root-servers.nil. +dom2255. NS a.root-servers.nil. +dom2256. NS a.root-servers.nil. +dom2257. NS a.root-servers.nil. +dom2258. NS a.root-servers.nil. +dom2259. NS a.root-servers.nil. +dom2260. NS a.root-servers.nil. +dom2261. NS a.root-servers.nil. +dom2262. NS a.root-servers.nil. +dom2263. NS a.root-servers.nil. +dom2264. NS a.root-servers.nil. +dom2265. NS a.root-servers.nil. +dom2266. NS a.root-servers.nil. +dom2267. NS a.root-servers.nil. +dom2268. NS a.root-servers.nil. +dom2269. NS a.root-servers.nil. +dom2270. NS a.root-servers.nil. +dom2271. NS a.root-servers.nil. +dom2272. NS a.root-servers.nil. +dom2273. NS a.root-servers.nil. +dom2274. NS a.root-servers.nil. +dom2275. NS a.root-servers.nil. +dom2276. NS a.root-servers.nil. +dom2277. NS a.root-servers.nil. +dom2278. NS a.root-servers.nil. +dom2279. NS a.root-servers.nil. +dom2280. NS a.root-servers.nil. +dom2281. NS a.root-servers.nil. +dom2282. NS a.root-servers.nil. +dom2283. NS a.root-servers.nil. +dom2284. NS a.root-servers.nil. +dom2285. NS a.root-servers.nil. +dom2286. NS a.root-servers.nil. +dom2287. NS a.root-servers.nil. +dom2288. NS a.root-servers.nil. +dom2289. NS a.root-servers.nil. +dom2290. NS a.root-servers.nil. +dom2291. NS a.root-servers.nil. +dom2292. NS a.root-servers.nil. +dom2293. NS a.root-servers.nil. +dom2294. NS a.root-servers.nil. +dom2295. NS a.root-servers.nil. +dom2296. NS a.root-servers.nil. +dom2297. NS a.root-servers.nil. +dom2298. NS a.root-servers.nil. +dom2299. NS a.root-servers.nil. +dom2300. NS a.root-servers.nil. +dom2301. NS a.root-servers.nil. +dom2302. NS a.root-servers.nil. +dom2303. NS a.root-servers.nil. +dom2304. NS a.root-servers.nil. +dom2305. NS a.root-servers.nil. +dom2306. NS a.root-servers.nil. +dom2307. NS a.root-servers.nil. +dom2308. NS a.root-servers.nil. +dom2309. NS a.root-servers.nil. +dom2310. NS a.root-servers.nil. +dom2311. NS a.root-servers.nil. +dom2312. NS a.root-servers.nil. +dom2313. NS a.root-servers.nil. +dom2314. NS a.root-servers.nil. +dom2315. NS a.root-servers.nil. +dom2316. NS a.root-servers.nil. +dom2317. NS a.root-servers.nil. +dom2318. NS a.root-servers.nil. +dom2319. NS a.root-servers.nil. +dom2320. NS a.root-servers.nil. +dom2321. NS a.root-servers.nil. +dom2322. NS a.root-servers.nil. +dom2323. NS a.root-servers.nil. +dom2324. NS a.root-servers.nil. +dom2325. NS a.root-servers.nil. +dom2326. NS a.root-servers.nil. +dom2327. NS a.root-servers.nil. +dom2328. NS a.root-servers.nil. +dom2329. NS a.root-servers.nil. +dom2330. NS a.root-servers.nil. +dom2331. NS a.root-servers.nil. +dom2332. NS a.root-servers.nil. +dom2333. NS a.root-servers.nil. +dom2334. NS a.root-servers.nil. +dom2335. NS a.root-servers.nil. +dom2336. NS a.root-servers.nil. +dom2337. NS a.root-servers.nil. +dom2338. NS a.root-servers.nil. +dom2339. NS a.root-servers.nil. +dom2340. NS a.root-servers.nil. +dom2341. NS a.root-servers.nil. +dom2342. NS a.root-servers.nil. +dom2343. NS a.root-servers.nil. +dom2344. NS a.root-servers.nil. +dom2345. NS a.root-servers.nil. +dom2346. NS a.root-servers.nil. +dom2347. NS a.root-servers.nil. +dom2348. NS a.root-servers.nil. +dom2349. NS a.root-servers.nil. +dom2350. NS a.root-servers.nil. +dom2351. NS a.root-servers.nil. +dom2352. NS a.root-servers.nil. +dom2353. NS a.root-servers.nil. +dom2354. NS a.root-servers.nil. +dom2355. NS a.root-servers.nil. +dom2356. NS a.root-servers.nil. +dom2357. NS a.root-servers.nil. +dom2358. NS a.root-servers.nil. +dom2359. NS a.root-servers.nil. +dom2360. NS a.root-servers.nil. +dom2361. NS a.root-servers.nil. +dom2362. NS a.root-servers.nil. +dom2363. NS a.root-servers.nil. +dom2364. NS a.root-servers.nil. +dom2365. NS a.root-servers.nil. +dom2366. NS a.root-servers.nil. +dom2367. NS a.root-servers.nil. +dom2368. NS a.root-servers.nil. +dom2369. NS a.root-servers.nil. +dom2370. NS a.root-servers.nil. +dom2371. NS a.root-servers.nil. +dom2372. NS a.root-servers.nil. +dom2373. NS a.root-servers.nil. +dom2374. NS a.root-servers.nil. +dom2375. NS a.root-servers.nil. +dom2376. NS a.root-servers.nil. +dom2377. NS a.root-servers.nil. +dom2378. NS a.root-servers.nil. +dom2379. NS a.root-servers.nil. +dom2380. NS a.root-servers.nil. +dom2381. NS a.root-servers.nil. +dom2382. NS a.root-servers.nil. +dom2383. NS a.root-servers.nil. +dom2384. NS a.root-servers.nil. +dom2385. NS a.root-servers.nil. +dom2386. NS a.root-servers.nil. +dom2387. NS a.root-servers.nil. +dom2388. NS a.root-servers.nil. +dom2389. NS a.root-servers.nil. +dom2390. NS a.root-servers.nil. +dom2391. NS a.root-servers.nil. +dom2392. NS a.root-servers.nil. +dom2393. NS a.root-servers.nil. +dom2394. NS a.root-servers.nil. +dom2395. NS a.root-servers.nil. +dom2396. NS a.root-servers.nil. +dom2397. NS a.root-servers.nil. +dom2398. NS a.root-servers.nil. +dom2399. NS a.root-servers.nil. +dom2400. NS a.root-servers.nil. +dom2401. NS a.root-servers.nil. +dom2402. NS a.root-servers.nil. +dom2403. NS a.root-servers.nil. +dom2404. NS a.root-servers.nil. +dom2405. NS a.root-servers.nil. +dom2406. NS a.root-servers.nil. +dom2407. NS a.root-servers.nil. +dom2408. NS a.root-servers.nil. +dom2409. NS a.root-servers.nil. +dom2410. NS a.root-servers.nil. +dom2411. NS a.root-servers.nil. +dom2412. NS a.root-servers.nil. +dom2413. NS a.root-servers.nil. +dom2414. NS a.root-servers.nil. +dom2415. NS a.root-servers.nil. +dom2416. NS a.root-servers.nil. +dom2417. NS a.root-servers.nil. +dom2418. NS a.root-servers.nil. +dom2419. NS a.root-servers.nil. +dom2420. NS a.root-servers.nil. +dom2421. NS a.root-servers.nil. +dom2422. NS a.root-servers.nil. +dom2423. NS a.root-servers.nil. +dom2424. NS a.root-servers.nil. +dom2425. NS a.root-servers.nil. +dom2426. NS a.root-servers.nil. +dom2427. NS a.root-servers.nil. +dom2428. NS a.root-servers.nil. +dom2429. NS a.root-servers.nil. +dom2430. NS a.root-servers.nil. +dom2431. NS a.root-servers.nil. +dom2432. NS a.root-servers.nil. +dom2433. NS a.root-servers.nil. +dom2434. NS a.root-servers.nil. +dom2435. NS a.root-servers.nil. +dom2436. NS a.root-servers.nil. +dom2437. NS a.root-servers.nil. +dom2438. NS a.root-servers.nil. +dom2439. NS a.root-servers.nil. +dom2440. NS a.root-servers.nil. +dom2441. NS a.root-servers.nil. +dom2442. NS a.root-servers.nil. +dom2443. NS a.root-servers.nil. +dom2444. NS a.root-servers.nil. +dom2445. NS a.root-servers.nil. +dom2446. NS a.root-servers.nil. +dom2447. NS a.root-servers.nil. +dom2448. NS a.root-servers.nil. +dom2449. NS a.root-servers.nil. +dom2450. NS a.root-servers.nil. +dom2451. NS a.root-servers.nil. +dom2452. NS a.root-servers.nil. +dom2453. NS a.root-servers.nil. +dom2454. NS a.root-servers.nil. +dom2455. NS a.root-servers.nil. +dom2456. NS a.root-servers.nil. +dom2457. NS a.root-servers.nil. +dom2458. NS a.root-servers.nil. +dom2459. NS a.root-servers.nil. +dom2460. NS a.root-servers.nil. +dom2461. NS a.root-servers.nil. +dom2462. NS a.root-servers.nil. +dom2463. NS a.root-servers.nil. +dom2464. NS a.root-servers.nil. +dom2465. NS a.root-servers.nil. +dom2466. NS a.root-servers.nil. +dom2467. NS a.root-servers.nil. +dom2468. NS a.root-servers.nil. +dom2469. NS a.root-servers.nil. +dom2470. NS a.root-servers.nil. +dom2471. NS a.root-servers.nil. +dom2472. NS a.root-servers.nil. +dom2473. NS a.root-servers.nil. +dom2474. NS a.root-servers.nil. +dom2475. NS a.root-servers.nil. +dom2476. NS a.root-servers.nil. +dom2477. NS a.root-servers.nil. +dom2478. NS a.root-servers.nil. +dom2479. NS a.root-servers.nil. +dom2480. NS a.root-servers.nil. +dom2481. NS a.root-servers.nil. +dom2482. NS a.root-servers.nil. +dom2483. NS a.root-servers.nil. +dom2484. NS a.root-servers.nil. +dom2485. NS a.root-servers.nil. +dom2486. NS a.root-servers.nil. +dom2487. NS a.root-servers.nil. +dom2488. NS a.root-servers.nil. +dom2489. NS a.root-servers.nil. +dom2490. NS a.root-servers.nil. +dom2491. NS a.root-servers.nil. +dom2492. NS a.root-servers.nil. +dom2493. NS a.root-servers.nil. +dom2494. NS a.root-servers.nil. +dom2495. NS a.root-servers.nil. +dom2496. NS a.root-servers.nil. +dom2497. NS a.root-servers.nil. +dom2498. NS a.root-servers.nil. +dom2499. NS a.root-servers.nil. +dom2500. NS a.root-servers.nil. +dom2501. NS a.root-servers.nil. +dom2502. NS a.root-servers.nil. +dom2503. NS a.root-servers.nil. +dom2504. NS a.root-servers.nil. +dom2505. NS a.root-servers.nil. +dom2506. NS a.root-servers.nil. +dom2507. NS a.root-servers.nil. +dom2508. NS a.root-servers.nil. +dom2509. NS a.root-servers.nil. +dom2510. NS a.root-servers.nil. +dom2511. NS a.root-servers.nil. +dom2512. NS a.root-servers.nil. +dom2513. NS a.root-servers.nil. +dom2514. NS a.root-servers.nil. +dom2515. NS a.root-servers.nil. +dom2516. NS a.root-servers.nil. +dom2517. NS a.root-servers.nil. +dom2518. NS a.root-servers.nil. +dom2519. NS a.root-servers.nil. +dom2520. NS a.root-servers.nil. +dom2521. NS a.root-servers.nil. +dom2522. NS a.root-servers.nil. +dom2523. NS a.root-servers.nil. +dom2524. NS a.root-servers.nil. +dom2525. NS a.root-servers.nil. +dom2526. NS a.root-servers.nil. +dom2527. NS a.root-servers.nil. +dom2528. NS a.root-servers.nil. +dom2529. NS a.root-servers.nil. +dom2530. NS a.root-servers.nil. +dom2531. NS a.root-servers.nil. +dom2532. NS a.root-servers.nil. +dom2533. NS a.root-servers.nil. +dom2534. NS a.root-servers.nil. +dom2535. NS a.root-servers.nil. +dom2536. NS a.root-servers.nil. +dom2537. NS a.root-servers.nil. +dom2538. NS a.root-servers.nil. +dom2539. NS a.root-servers.nil. +dom2540. NS a.root-servers.nil. +dom2541. NS a.root-servers.nil. +dom2542. NS a.root-servers.nil. +dom2543. NS a.root-servers.nil. +dom2544. NS a.root-servers.nil. +dom2545. NS a.root-servers.nil. +dom2546. NS a.root-servers.nil. +dom2547. NS a.root-servers.nil. +dom2548. NS a.root-servers.nil. +dom2549. NS a.root-servers.nil. +dom2550. NS a.root-servers.nil. +dom2551. NS a.root-servers.nil. +dom2552. NS a.root-servers.nil. +dom2553. NS a.root-servers.nil. +dom2554. NS a.root-servers.nil. +dom2555. NS a.root-servers.nil. +dom2556. NS a.root-servers.nil. +dom2557. NS a.root-servers.nil. +dom2558. NS a.root-servers.nil. +dom2559. NS a.root-servers.nil. +dom2560. NS a.root-servers.nil. +dom2561. NS a.root-servers.nil. +dom2562. NS a.root-servers.nil. +dom2563. NS a.root-servers.nil. +dom2564. NS a.root-servers.nil. +dom2565. NS a.root-servers.nil. +dom2566. NS a.root-servers.nil. +dom2567. NS a.root-servers.nil. +dom2568. NS a.root-servers.nil. +dom2569. NS a.root-servers.nil. +dom2570. NS a.root-servers.nil. +dom2571. NS a.root-servers.nil. +dom2572. NS a.root-servers.nil. +dom2573. NS a.root-servers.nil. +dom2574. NS a.root-servers.nil. +dom2575. NS a.root-servers.nil. +dom2576. NS a.root-servers.nil. +dom2577. NS a.root-servers.nil. +dom2578. NS a.root-servers.nil. +dom2579. NS a.root-servers.nil. +dom2580. NS a.root-servers.nil. +dom2581. NS a.root-servers.nil. +dom2582. NS a.root-servers.nil. +dom2583. NS a.root-servers.nil. +dom2584. NS a.root-servers.nil. +dom2585. NS a.root-servers.nil. +dom2586. NS a.root-servers.nil. +dom2587. NS a.root-servers.nil. +dom2588. NS a.root-servers.nil. +dom2589. NS a.root-servers.nil. +dom2590. NS a.root-servers.nil. +dom2591. NS a.root-servers.nil. +dom2592. NS a.root-servers.nil. +dom2593. NS a.root-servers.nil. +dom2594. NS a.root-servers.nil. +dom2595. NS a.root-servers.nil. +dom2596. NS a.root-servers.nil. +dom2597. NS a.root-servers.nil. +dom2598. NS a.root-servers.nil. +dom2599. NS a.root-servers.nil. +dom2600. NS a.root-servers.nil. +dom2601. NS a.root-servers.nil. +dom2602. NS a.root-servers.nil. +dom2603. NS a.root-servers.nil. +dom2604. NS a.root-servers.nil. +dom2605. NS a.root-servers.nil. +dom2606. NS a.root-servers.nil. +dom2607. NS a.root-servers.nil. +dom2608. NS a.root-servers.nil. +dom2609. NS a.root-servers.nil. +dom2610. NS a.root-servers.nil. +dom2611. NS a.root-servers.nil. +dom2612. NS a.root-servers.nil. +dom2613. NS a.root-servers.nil. +dom2614. NS a.root-servers.nil. +dom2615. NS a.root-servers.nil. +dom2616. NS a.root-servers.nil. +dom2617. NS a.root-servers.nil. +dom2618. NS a.root-servers.nil. +dom2619. NS a.root-servers.nil. +dom2620. NS a.root-servers.nil. +dom2621. NS a.root-servers.nil. +dom2622. NS a.root-servers.nil. +dom2623. NS a.root-servers.nil. +dom2624. NS a.root-servers.nil. +dom2625. NS a.root-servers.nil. +dom2626. NS a.root-servers.nil. +dom2627. NS a.root-servers.nil. +dom2628. NS a.root-servers.nil. +dom2629. NS a.root-servers.nil. +dom2630. NS a.root-servers.nil. +dom2631. NS a.root-servers.nil. +dom2632. NS a.root-servers.nil. +dom2633. NS a.root-servers.nil. +dom2634. NS a.root-servers.nil. +dom2635. NS a.root-servers.nil. +dom2636. NS a.root-servers.nil. +dom2637. NS a.root-servers.nil. +dom2638. NS a.root-servers.nil. +dom2639. NS a.root-servers.nil. +dom2640. NS a.root-servers.nil. +dom2641. NS a.root-servers.nil. +dom2642. NS a.root-servers.nil. +dom2643. NS a.root-servers.nil. +dom2644. NS a.root-servers.nil. +dom2645. NS a.root-servers.nil. +dom2646. NS a.root-servers.nil. +dom2647. NS a.root-servers.nil. +dom2648. NS a.root-servers.nil. +dom2649. NS a.root-servers.nil. +dom2650. NS a.root-servers.nil. +dom2651. NS a.root-servers.nil. +dom2652. NS a.root-servers.nil. +dom2653. NS a.root-servers.nil. +dom2654. NS a.root-servers.nil. +dom2655. NS a.root-servers.nil. +dom2656. NS a.root-servers.nil. +dom2657. NS a.root-servers.nil. +dom2658. NS a.root-servers.nil. +dom2659. NS a.root-servers.nil. +dom2660. NS a.root-servers.nil. +dom2661. NS a.root-servers.nil. +dom2662. NS a.root-servers.nil. +dom2663. NS a.root-servers.nil. +dom2664. NS a.root-servers.nil. +dom2665. NS a.root-servers.nil. +dom2666. NS a.root-servers.nil. +dom2667. NS a.root-servers.nil. +dom2668. NS a.root-servers.nil. +dom2669. NS a.root-servers.nil. +dom2670. NS a.root-servers.nil. +dom2671. NS a.root-servers.nil. +dom2672. NS a.root-servers.nil. +dom2673. NS a.root-servers.nil. +dom2674. NS a.root-servers.nil. +dom2675. NS a.root-servers.nil. +dom2676. NS a.root-servers.nil. +dom2677. NS a.root-servers.nil. +dom2678. NS a.root-servers.nil. +dom2679. NS a.root-servers.nil. +dom2680. NS a.root-servers.nil. +dom2681. NS a.root-servers.nil. +dom2682. NS a.root-servers.nil. +dom2683. NS a.root-servers.nil. +dom2684. NS a.root-servers.nil. +dom2685. NS a.root-servers.nil. +dom2686. NS a.root-servers.nil. +dom2687. NS a.root-servers.nil. +dom2688. NS a.root-servers.nil. +dom2689. NS a.root-servers.nil. +dom2690. NS a.root-servers.nil. +dom2691. NS a.root-servers.nil. +dom2692. NS a.root-servers.nil. +dom2693. NS a.root-servers.nil. +dom2694. NS a.root-servers.nil. +dom2695. NS a.root-servers.nil. +dom2696. NS a.root-servers.nil. +dom2697. NS a.root-servers.nil. +dom2698. NS a.root-servers.nil. +dom2699. NS a.root-servers.nil. +dom2700. NS a.root-servers.nil. +dom2701. NS a.root-servers.nil. +dom2702. NS a.root-servers.nil. +dom2703. NS a.root-servers.nil. +dom2704. NS a.root-servers.nil. +dom2705. NS a.root-servers.nil. +dom2706. NS a.root-servers.nil. +dom2707. NS a.root-servers.nil. +dom2708. NS a.root-servers.nil. +dom2709. NS a.root-servers.nil. +dom2710. NS a.root-servers.nil. +dom2711. NS a.root-servers.nil. +dom2712. NS a.root-servers.nil. +dom2713. NS a.root-servers.nil. +dom2714. NS a.root-servers.nil. +dom2715. NS a.root-servers.nil. +dom2716. NS a.root-servers.nil. +dom2717. NS a.root-servers.nil. +dom2718. NS a.root-servers.nil. +dom2719. NS a.root-servers.nil. +dom2720. NS a.root-servers.nil. +dom2721. NS a.root-servers.nil. +dom2722. NS a.root-servers.nil. +dom2723. NS a.root-servers.nil. +dom2724. NS a.root-servers.nil. +dom2725. NS a.root-servers.nil. +dom2726. NS a.root-servers.nil. +dom2727. NS a.root-servers.nil. +dom2728. NS a.root-servers.nil. +dom2729. NS a.root-servers.nil. +dom2730. NS a.root-servers.nil. +dom2731. NS a.root-servers.nil. +dom2732. NS a.root-servers.nil. +dom2733. NS a.root-servers.nil. +dom2734. NS a.root-servers.nil. +dom2735. NS a.root-servers.nil. +dom2736. NS a.root-servers.nil. +dom2737. NS a.root-servers.nil. +dom2738. NS a.root-servers.nil. +dom2739. NS a.root-servers.nil. +dom2740. NS a.root-servers.nil. +dom2741. NS a.root-servers.nil. +dom2742. NS a.root-servers.nil. +dom2743. NS a.root-servers.nil. +dom2744. NS a.root-servers.nil. +dom2745. NS a.root-servers.nil. +dom2746. NS a.root-servers.nil. +dom2747. NS a.root-servers.nil. +dom2748. NS a.root-servers.nil. +dom2749. NS a.root-servers.nil. +dom2750. NS a.root-servers.nil. +dom2751. NS a.root-servers.nil. +dom2752. NS a.root-servers.nil. +dom2753. NS a.root-servers.nil. +dom2754. NS a.root-servers.nil. +dom2755. NS a.root-servers.nil. +dom2756. NS a.root-servers.nil. +dom2757. NS a.root-servers.nil. +dom2758. NS a.root-servers.nil. +dom2759. NS a.root-servers.nil. +dom2760. NS a.root-servers.nil. +dom2761. NS a.root-servers.nil. +dom2762. NS a.root-servers.nil. +dom2763. NS a.root-servers.nil. +dom2764. NS a.root-servers.nil. +dom2765. NS a.root-servers.nil. +dom2766. NS a.root-servers.nil. +dom2767. NS a.root-servers.nil. +dom2768. NS a.root-servers.nil. +dom2769. NS a.root-servers.nil. +dom2770. NS a.root-servers.nil. +dom2771. NS a.root-servers.nil. +dom2772. NS a.root-servers.nil. +dom2773. NS a.root-servers.nil. +dom2774. NS a.root-servers.nil. +dom2775. NS a.root-servers.nil. +dom2776. NS a.root-servers.nil. +dom2777. NS a.root-servers.nil. +dom2778. NS a.root-servers.nil. +dom2779. NS a.root-servers.nil. +dom2780. NS a.root-servers.nil. +dom2781. NS a.root-servers.nil. +dom2782. NS a.root-servers.nil. +dom2783. NS a.root-servers.nil. +dom2784. NS a.root-servers.nil. +dom2785. NS a.root-servers.nil. +dom2786. NS a.root-servers.nil. +dom2787. NS a.root-servers.nil. +dom2788. NS a.root-servers.nil. +dom2789. NS a.root-servers.nil. +dom2790. NS a.root-servers.nil. +dom2791. NS a.root-servers.nil. +dom2792. NS a.root-servers.nil. +dom2793. NS a.root-servers.nil. +dom2794. NS a.root-servers.nil. +dom2795. NS a.root-servers.nil. +dom2796. NS a.root-servers.nil. +dom2797. NS a.root-servers.nil. +dom2798. NS a.root-servers.nil. +dom2799. NS a.root-servers.nil. +dom2800. NS a.root-servers.nil. +dom2801. NS a.root-servers.nil. +dom2802. NS a.root-servers.nil. +dom2803. NS a.root-servers.nil. +dom2804. NS a.root-servers.nil. +dom2805. NS a.root-servers.nil. +dom2806. NS a.root-servers.nil. +dom2807. NS a.root-servers.nil. +dom2808. NS a.root-servers.nil. +dom2809. NS a.root-servers.nil. +dom2810. NS a.root-servers.nil. +dom2811. NS a.root-servers.nil. +dom2812. NS a.root-servers.nil. +dom2813. NS a.root-servers.nil. +dom2814. NS a.root-servers.nil. +dom2815. NS a.root-servers.nil. +dom2816. NS a.root-servers.nil. +dom2817. NS a.root-servers.nil. +dom2818. NS a.root-servers.nil. +dom2819. NS a.root-servers.nil. +dom2820. NS a.root-servers.nil. +dom2821. NS a.root-servers.nil. +dom2822. NS a.root-servers.nil. +dom2823. NS a.root-servers.nil. +dom2824. NS a.root-servers.nil. +dom2825. NS a.root-servers.nil. +dom2826. NS a.root-servers.nil. +dom2827. NS a.root-servers.nil. +dom2828. NS a.root-servers.nil. +dom2829. NS a.root-servers.nil. +dom2830. NS a.root-servers.nil. +dom2831. NS a.root-servers.nil. +dom2832. NS a.root-servers.nil. +dom2833. NS a.root-servers.nil. +dom2834. NS a.root-servers.nil. +dom2835. NS a.root-servers.nil. +dom2836. NS a.root-servers.nil. +dom2837. NS a.root-servers.nil. +dom2838. NS a.root-servers.nil. +dom2839. NS a.root-servers.nil. +dom2840. NS a.root-servers.nil. +dom2841. NS a.root-servers.nil. +dom2842. NS a.root-servers.nil. +dom2843. NS a.root-servers.nil. +dom2844. NS a.root-servers.nil. +dom2845. NS a.root-servers.nil. +dom2846. NS a.root-servers.nil. +dom2847. NS a.root-servers.nil. +dom2848. NS a.root-servers.nil. +dom2849. NS a.root-servers.nil. +dom2850. NS a.root-servers.nil. +dom2851. NS a.root-servers.nil. +dom2852. NS a.root-servers.nil. +dom2853. NS a.root-servers.nil. +dom2854. NS a.root-servers.nil. +dom2855. NS a.root-servers.nil. +dom2856. NS a.root-servers.nil. +dom2857. NS a.root-servers.nil. +dom2858. NS a.root-servers.nil. +dom2859. NS a.root-servers.nil. +dom2860. NS a.root-servers.nil. +dom2861. NS a.root-servers.nil. +dom2862. NS a.root-servers.nil. +dom2863. NS a.root-servers.nil. +dom2864. NS a.root-servers.nil. +dom2865. NS a.root-servers.nil. +dom2866. NS a.root-servers.nil. +dom2867. NS a.root-servers.nil. +dom2868. NS a.root-servers.nil. +dom2869. NS a.root-servers.nil. +dom2870. NS a.root-servers.nil. +dom2871. NS a.root-servers.nil. +dom2872. NS a.root-servers.nil. +dom2873. NS a.root-servers.nil. +dom2874. NS a.root-servers.nil. +dom2875. NS a.root-servers.nil. +dom2876. NS a.root-servers.nil. +dom2877. NS a.root-servers.nil. +dom2878. NS a.root-servers.nil. +dom2879. NS a.root-servers.nil. +dom2880. NS a.root-servers.nil. +dom2881. NS a.root-servers.nil. +dom2882. NS a.root-servers.nil. +dom2883. NS a.root-servers.nil. +dom2884. NS a.root-servers.nil. +dom2885. NS a.root-servers.nil. +dom2886. NS a.root-servers.nil. +dom2887. NS a.root-servers.nil. +dom2888. NS a.root-servers.nil. +dom2889. NS a.root-servers.nil. +dom2890. NS a.root-servers.nil. +dom2891. NS a.root-servers.nil. +dom2892. NS a.root-servers.nil. +dom2893. NS a.root-servers.nil. +dom2894. NS a.root-servers.nil. +dom2895. NS a.root-servers.nil. +dom2896. NS a.root-servers.nil. +dom2897. NS a.root-servers.nil. +dom2898. NS a.root-servers.nil. +dom2899. NS a.root-servers.nil. +dom2900. NS a.root-servers.nil. +dom2901. NS a.root-servers.nil. +dom2902. NS a.root-servers.nil. +dom2903. NS a.root-servers.nil. +dom2904. NS a.root-servers.nil. +dom2905. NS a.root-servers.nil. +dom2906. NS a.root-servers.nil. +dom2907. NS a.root-servers.nil. +dom2908. NS a.root-servers.nil. +dom2909. NS a.root-servers.nil. +dom2910. NS a.root-servers.nil. +dom2911. NS a.root-servers.nil. +dom2912. NS a.root-servers.nil. +dom2913. NS a.root-servers.nil. +dom2914. NS a.root-servers.nil. +dom2915. NS a.root-servers.nil. +dom2916. NS a.root-servers.nil. +dom2917. NS a.root-servers.nil. +dom2918. NS a.root-servers.nil. +dom2919. NS a.root-servers.nil. +dom2920. NS a.root-servers.nil. +dom2921. NS a.root-servers.nil. +dom2922. NS a.root-servers.nil. +dom2923. NS a.root-servers.nil. +dom2924. NS a.root-servers.nil. +dom2925. NS a.root-servers.nil. +dom2926. NS a.root-servers.nil. +dom2927. NS a.root-servers.nil. +dom2928. NS a.root-servers.nil. +dom2929. NS a.root-servers.nil. +dom2930. NS a.root-servers.nil. +dom2931. NS a.root-servers.nil. +dom2932. NS a.root-servers.nil. +dom2933. NS a.root-servers.nil. +dom2934. NS a.root-servers.nil. +dom2935. NS a.root-servers.nil. +dom2936. NS a.root-servers.nil. +dom2937. NS a.root-servers.nil. +dom2938. NS a.root-servers.nil. +dom2939. NS a.root-servers.nil. +dom2940. NS a.root-servers.nil. +dom2941. NS a.root-servers.nil. +dom2942. NS a.root-servers.nil. +dom2943. NS a.root-servers.nil. +dom2944. NS a.root-servers.nil. +dom2945. NS a.root-servers.nil. +dom2946. NS a.root-servers.nil. +dom2947. NS a.root-servers.nil. +dom2948. NS a.root-servers.nil. +dom2949. NS a.root-servers.nil. +dom2950. NS a.root-servers.nil. +dom2951. NS a.root-servers.nil. +dom2952. NS a.root-servers.nil. +dom2953. NS a.root-servers.nil. +dom2954. NS a.root-servers.nil. +dom2955. NS a.root-servers.nil. +dom2956. NS a.root-servers.nil. +dom2957. NS a.root-servers.nil. +dom2958. NS a.root-servers.nil. +dom2959. NS a.root-servers.nil. +dom2960. NS a.root-servers.nil. +dom2961. NS a.root-servers.nil. +dom2962. NS a.root-servers.nil. +dom2963. NS a.root-servers.nil. +dom2964. NS a.root-servers.nil. +dom2965. NS a.root-servers.nil. +dom2966. NS a.root-servers.nil. +dom2967. NS a.root-servers.nil. +dom2968. NS a.root-servers.nil. +dom2969. NS a.root-servers.nil. +dom2970. NS a.root-servers.nil. +dom2971. NS a.root-servers.nil. +dom2972. NS a.root-servers.nil. +dom2973. NS a.root-servers.nil. +dom2974. NS a.root-servers.nil. +dom2975. NS a.root-servers.nil. +dom2976. NS a.root-servers.nil. +dom2977. NS a.root-servers.nil. +dom2978. NS a.root-servers.nil. +dom2979. NS a.root-servers.nil. +dom2980. NS a.root-servers.nil. +dom2981. NS a.root-servers.nil. +dom2982. NS a.root-servers.nil. +dom2983. NS a.root-servers.nil. +dom2984. NS a.root-servers.nil. +dom2985. NS a.root-servers.nil. +dom2986. NS a.root-servers.nil. +dom2987. NS a.root-servers.nil. +dom2988. NS a.root-servers.nil. +dom2989. NS a.root-servers.nil. +dom2990. NS a.root-servers.nil. +dom2991. NS a.root-servers.nil. +dom2992. NS a.root-servers.nil. +dom2993. NS a.root-servers.nil. +dom2994. NS a.root-servers.nil. +dom2995. NS a.root-servers.nil. +dom2996. NS a.root-servers.nil. +dom2997. NS a.root-servers.nil. +dom2998. NS a.root-servers.nil. +dom2999. NS a.root-servers.nil. +dom3000. NS a.root-servers.nil. +dom3001. NS a.root-servers.nil. +dom3002. NS a.root-servers.nil. +dom3003. NS a.root-servers.nil. +dom3004. NS a.root-servers.nil. +dom3005. NS a.root-servers.nil. +dom3006. NS a.root-servers.nil. +dom3007. NS a.root-servers.nil. +dom3008. NS a.root-servers.nil. +dom3009. NS a.root-servers.nil. +dom3010. NS a.root-servers.nil. +dom3011. NS a.root-servers.nil. +dom3012. NS a.root-servers.nil. +dom3013. NS a.root-servers.nil. +dom3014. NS a.root-servers.nil. +dom3015. NS a.root-servers.nil. +dom3016. NS a.root-servers.nil. +dom3017. NS a.root-servers.nil. +dom3018. NS a.root-servers.nil. +dom3019. NS a.root-servers.nil. +dom3020. NS a.root-servers.nil. +dom3021. NS a.root-servers.nil. +dom3022. NS a.root-servers.nil. +dom3023. NS a.root-servers.nil. +dom3024. NS a.root-servers.nil. +dom3025. NS a.root-servers.nil. +dom3026. NS a.root-servers.nil. +dom3027. NS a.root-servers.nil. +dom3028. NS a.root-servers.nil. +dom3029. NS a.root-servers.nil. +dom3030. NS a.root-servers.nil. +dom3031. NS a.root-servers.nil. +dom3032. NS a.root-servers.nil. +dom3033. NS a.root-servers.nil. +dom3034. NS a.root-servers.nil. +dom3035. NS a.root-servers.nil. +dom3036. NS a.root-servers.nil. +dom3037. NS a.root-servers.nil. +dom3038. NS a.root-servers.nil. +dom3039. NS a.root-servers.nil. +dom3040. NS a.root-servers.nil. +dom3041. NS a.root-servers.nil. +dom3042. NS a.root-servers.nil. +dom3043. NS a.root-servers.nil. +dom3044. NS a.root-servers.nil. +dom3045. NS a.root-servers.nil. +dom3046. NS a.root-servers.nil. +dom3047. NS a.root-servers.nil. +dom3048. NS a.root-servers.nil. +dom3049. NS a.root-servers.nil. +dom3050. NS a.root-servers.nil. +dom3051. NS a.root-servers.nil. +dom3052. NS a.root-servers.nil. +dom3053. NS a.root-servers.nil. +dom3054. NS a.root-servers.nil. +dom3055. NS a.root-servers.nil. +dom3056. NS a.root-servers.nil. +dom3057. NS a.root-servers.nil. +dom3058. NS a.root-servers.nil. +dom3059. NS a.root-servers.nil. +dom3060. NS a.root-servers.nil. +dom3061. NS a.root-servers.nil. +dom3062. NS a.root-servers.nil. +dom3063. NS a.root-servers.nil. +dom3064. NS a.root-servers.nil. +dom3065. NS a.root-servers.nil. +dom3066. NS a.root-servers.nil. +dom3067. NS a.root-servers.nil. +dom3068. NS a.root-servers.nil. +dom3069. NS a.root-servers.nil. +dom3070. NS a.root-servers.nil. +dom3071. NS a.root-servers.nil. +dom3072. NS a.root-servers.nil. +dom3073. NS a.root-servers.nil. +dom3074. NS a.root-servers.nil. +dom3075. NS a.root-servers.nil. +dom3076. NS a.root-servers.nil. +dom3077. NS a.root-servers.nil. +dom3078. NS a.root-servers.nil. +dom3079. NS a.root-servers.nil. +dom3080. NS a.root-servers.nil. +dom3081. NS a.root-servers.nil. +dom3082. NS a.root-servers.nil. +dom3083. NS a.root-servers.nil. +dom3084. NS a.root-servers.nil. +dom3085. NS a.root-servers.nil. +dom3086. NS a.root-servers.nil. +dom3087. NS a.root-servers.nil. +dom3088. NS a.root-servers.nil. +dom3089. NS a.root-servers.nil. +dom3090. NS a.root-servers.nil. +dom3091. NS a.root-servers.nil. +dom3092. NS a.root-servers.nil. +dom3093. NS a.root-servers.nil. +dom3094. NS a.root-servers.nil. +dom3095. NS a.root-servers.nil. +dom3096. NS a.root-servers.nil. +dom3097. NS a.root-servers.nil. +dom3098. NS a.root-servers.nil. +dom3099. NS a.root-servers.nil. +dom3100. NS a.root-servers.nil. +dom3101. NS a.root-servers.nil. +dom3102. NS a.root-servers.nil. +dom3103. NS a.root-servers.nil. +dom3104. NS a.root-servers.nil. +dom3105. NS a.root-servers.nil. +dom3106. NS a.root-servers.nil. +dom3107. NS a.root-servers.nil. +dom3108. NS a.root-servers.nil. +dom3109. NS a.root-servers.nil. +dom3110. NS a.root-servers.nil. +dom3111. NS a.root-servers.nil. +dom3112. NS a.root-servers.nil. +dom3113. NS a.root-servers.nil. +dom3114. NS a.root-servers.nil. +dom3115. NS a.root-servers.nil. +dom3116. NS a.root-servers.nil. +dom3117. NS a.root-servers.nil. +dom3118. NS a.root-servers.nil. +dom3119. NS a.root-servers.nil. +dom3120. NS a.root-servers.nil. +dom3121. NS a.root-servers.nil. +dom3122. NS a.root-servers.nil. +dom3123. NS a.root-servers.nil. +dom3124. NS a.root-servers.nil. +dom3125. NS a.root-servers.nil. +dom3126. NS a.root-servers.nil. +dom3127. NS a.root-servers.nil. +dom3128. NS a.root-servers.nil. +dom3129. NS a.root-servers.nil. +dom3130. NS a.root-servers.nil. +dom3131. NS a.root-servers.nil. +dom3132. NS a.root-servers.nil. +dom3133. NS a.root-servers.nil. +dom3134. NS a.root-servers.nil. +dom3135. NS a.root-servers.nil. +dom3136. NS a.root-servers.nil. +dom3137. NS a.root-servers.nil. +dom3138. NS a.root-servers.nil. +dom3139. NS a.root-servers.nil. +dom3140. NS a.root-servers.nil. +dom3141. NS a.root-servers.nil. +dom3142. NS a.root-servers.nil. +dom3143. NS a.root-servers.nil. +dom3144. NS a.root-servers.nil. +dom3145. NS a.root-servers.nil. +dom3146. NS a.root-servers.nil. +dom3147. NS a.root-servers.nil. +dom3148. NS a.root-servers.nil. +dom3149. NS a.root-servers.nil. +dom3150. NS a.root-servers.nil. +dom3151. NS a.root-servers.nil. +dom3152. NS a.root-servers.nil. +dom3153. NS a.root-servers.nil. +dom3154. NS a.root-servers.nil. +dom3155. NS a.root-servers.nil. +dom3156. NS a.root-servers.nil. +dom3157. NS a.root-servers.nil. +dom3158. NS a.root-servers.nil. +dom3159. NS a.root-servers.nil. +dom3160. NS a.root-servers.nil. +dom3161. NS a.root-servers.nil. +dom3162. NS a.root-servers.nil. +dom3163. NS a.root-servers.nil. +dom3164. NS a.root-servers.nil. +dom3165. NS a.root-servers.nil. +dom3166. NS a.root-servers.nil. +dom3167. NS a.root-servers.nil. +dom3168. NS a.root-servers.nil. +dom3169. NS a.root-servers.nil. +dom3170. NS a.root-servers.nil. +dom3171. NS a.root-servers.nil. +dom3172. NS a.root-servers.nil. +dom3173. NS a.root-servers.nil. +dom3174. NS a.root-servers.nil. +dom3175. NS a.root-servers.nil. +dom3176. NS a.root-servers.nil. +dom3177. NS a.root-servers.nil. +dom3178. NS a.root-servers.nil. +dom3179. NS a.root-servers.nil. +dom3180. NS a.root-servers.nil. +dom3181. NS a.root-servers.nil. +dom3182. NS a.root-servers.nil. +dom3183. NS a.root-servers.nil. +dom3184. NS a.root-servers.nil. +dom3185. NS a.root-servers.nil. +dom3186. NS a.root-servers.nil. +dom3187. NS a.root-servers.nil. +dom3188. NS a.root-servers.nil. +dom3189. NS a.root-servers.nil. +dom3190. NS a.root-servers.nil. +dom3191. NS a.root-servers.nil. +dom3192. NS a.root-servers.nil. +dom3193. NS a.root-servers.nil. +dom3194. NS a.root-servers.nil. +dom3195. NS a.root-servers.nil. +dom3196. NS a.root-servers.nil. +dom3197. NS a.root-servers.nil. +dom3198. NS a.root-servers.nil. +dom3199. NS a.root-servers.nil. +dom3200. NS a.root-servers.nil. +dom3201. NS a.root-servers.nil. +dom3202. NS a.root-servers.nil. +dom3203. NS a.root-servers.nil. +dom3204. NS a.root-servers.nil. +dom3205. NS a.root-servers.nil. +dom3206. NS a.root-servers.nil. +dom3207. NS a.root-servers.nil. +dom3208. NS a.root-servers.nil. +dom3209. NS a.root-servers.nil. +dom3210. NS a.root-servers.nil. +dom3211. NS a.root-servers.nil. +dom3212. NS a.root-servers.nil. +dom3213. NS a.root-servers.nil. +dom3214. NS a.root-servers.nil. +dom3215. NS a.root-servers.nil. +dom3216. NS a.root-servers.nil. +dom3217. NS a.root-servers.nil. +dom3218. NS a.root-servers.nil. +dom3219. NS a.root-servers.nil. +dom3220. NS a.root-servers.nil. +dom3221. NS a.root-servers.nil. +dom3222. NS a.root-servers.nil. +dom3223. NS a.root-servers.nil. +dom3224. NS a.root-servers.nil. +dom3225. NS a.root-servers.nil. +dom3226. NS a.root-servers.nil. +dom3227. NS a.root-servers.nil. +dom3228. NS a.root-servers.nil. +dom3229. NS a.root-servers.nil. +dom3230. NS a.root-servers.nil. +dom3231. NS a.root-servers.nil. +dom3232. NS a.root-servers.nil. +dom3233. NS a.root-servers.nil. +dom3234. NS a.root-servers.nil. +dom3235. NS a.root-servers.nil. +dom3236. NS a.root-servers.nil. +dom3237. NS a.root-servers.nil. +dom3238. NS a.root-servers.nil. +dom3239. NS a.root-servers.nil. +dom3240. NS a.root-servers.nil. +dom3241. NS a.root-servers.nil. +dom3242. NS a.root-servers.nil. +dom3243. NS a.root-servers.nil. +dom3244. NS a.root-servers.nil. +dom3245. NS a.root-servers.nil. +dom3246. NS a.root-servers.nil. +dom3247. NS a.root-servers.nil. +dom3248. NS a.root-servers.nil. +dom3249. NS a.root-servers.nil. +dom3250. NS a.root-servers.nil. +dom3251. NS a.root-servers.nil. +dom3252. NS a.root-servers.nil. +dom3253. NS a.root-servers.nil. +dom3254. NS a.root-servers.nil. +dom3255. NS a.root-servers.nil. +dom3256. NS a.root-servers.nil. +dom3257. NS a.root-servers.nil. +dom3258. NS a.root-servers.nil. +dom3259. NS a.root-servers.nil. +dom3260. NS a.root-servers.nil. +dom3261. NS a.root-servers.nil. +dom3262. NS a.root-servers.nil. +dom3263. NS a.root-servers.nil. +dom3264. NS a.root-servers.nil. +dom3265. NS a.root-servers.nil. +dom3266. NS a.root-servers.nil. +dom3267. NS a.root-servers.nil. +dom3268. NS a.root-servers.nil. +dom3269. NS a.root-servers.nil. +dom3270. NS a.root-servers.nil. +dom3271. NS a.root-servers.nil. +dom3272. NS a.root-servers.nil. +dom3273. NS a.root-servers.nil. +dom3274. NS a.root-servers.nil. +dom3275. NS a.root-servers.nil. +dom3276. NS a.root-servers.nil. +dom3277. NS a.root-servers.nil. +dom3278. NS a.root-servers.nil. +dom3279. NS a.root-servers.nil. +dom3280. NS a.root-servers.nil. +dom3281. NS a.root-servers.nil. +dom3282. NS a.root-servers.nil. +dom3283. NS a.root-servers.nil. +dom3284. NS a.root-servers.nil. +dom3285. NS a.root-servers.nil. +dom3286. NS a.root-servers.nil. +dom3287. NS a.root-servers.nil. +dom3288. NS a.root-servers.nil. +dom3289. NS a.root-servers.nil. +dom3290. NS a.root-servers.nil. +dom3291. NS a.root-servers.nil. +dom3292. NS a.root-servers.nil. +dom3293. NS a.root-servers.nil. +dom3294. NS a.root-servers.nil. +dom3295. NS a.root-servers.nil. +dom3296. NS a.root-servers.nil. +dom3297. NS a.root-servers.nil. +dom3298. NS a.root-servers.nil. +dom3299. NS a.root-servers.nil. +dom3300. NS a.root-servers.nil. +dom3301. NS a.root-servers.nil. +dom3302. NS a.root-servers.nil. +dom3303. NS a.root-servers.nil. +dom3304. NS a.root-servers.nil. +dom3305. NS a.root-servers.nil. +dom3306. NS a.root-servers.nil. +dom3307. NS a.root-servers.nil. +dom3308. NS a.root-servers.nil. +dom3309. NS a.root-servers.nil. +dom3310. NS a.root-servers.nil. +dom3311. NS a.root-servers.nil. +dom3312. NS a.root-servers.nil. +dom3313. NS a.root-servers.nil. +dom3314. NS a.root-servers.nil. +dom3315. NS a.root-servers.nil. +dom3316. NS a.root-servers.nil. +dom3317. NS a.root-servers.nil. +dom3318. NS a.root-servers.nil. +dom3319. NS a.root-servers.nil. +dom3320. NS a.root-servers.nil. +dom3321. NS a.root-servers.nil. +dom3322. NS a.root-servers.nil. +dom3323. NS a.root-servers.nil. +dom3324. NS a.root-servers.nil. +dom3325. NS a.root-servers.nil. +dom3326. NS a.root-servers.nil. +dom3327. NS a.root-servers.nil. +dom3328. NS a.root-servers.nil. +dom3329. NS a.root-servers.nil. +dom3330. NS a.root-servers.nil. +dom3331. NS a.root-servers.nil. +dom3332. NS a.root-servers.nil. +dom3333. NS a.root-servers.nil. +dom3334. NS a.root-servers.nil. +dom3335. NS a.root-servers.nil. +dom3336. NS a.root-servers.nil. +dom3337. NS a.root-servers.nil. +dom3338. NS a.root-servers.nil. +dom3339. NS a.root-servers.nil. +dom3340. NS a.root-servers.nil. +dom3341. NS a.root-servers.nil. +dom3342. NS a.root-servers.nil. +dom3343. NS a.root-servers.nil. +dom3344. NS a.root-servers.nil. +dom3345. NS a.root-servers.nil. +dom3346. NS a.root-servers.nil. +dom3347. NS a.root-servers.nil. +dom3348. NS a.root-servers.nil. +dom3349. NS a.root-servers.nil. +dom3350. NS a.root-servers.nil. +dom3351. NS a.root-servers.nil. +dom3352. NS a.root-servers.nil. +dom3353. NS a.root-servers.nil. +dom3354. NS a.root-servers.nil. +dom3355. NS a.root-servers.nil. +dom3356. NS a.root-servers.nil. +dom3357. NS a.root-servers.nil. +dom3358. NS a.root-servers.nil. +dom3359. NS a.root-servers.nil. +dom3360. NS a.root-servers.nil. +dom3361. NS a.root-servers.nil. +dom3362. NS a.root-servers.nil. +dom3363. NS a.root-servers.nil. +dom3364. NS a.root-servers.nil. +dom3365. NS a.root-servers.nil. +dom3366. NS a.root-servers.nil. +dom3367. NS a.root-servers.nil. +dom3368. NS a.root-servers.nil. +dom3369. NS a.root-servers.nil. +dom3370. NS a.root-servers.nil. +dom3371. NS a.root-servers.nil. +dom3372. NS a.root-servers.nil. +dom3373. NS a.root-servers.nil. +dom3374. NS a.root-servers.nil. +dom3375. NS a.root-servers.nil. +dom3376. NS a.root-servers.nil. +dom3377. NS a.root-servers.nil. +dom3378. NS a.root-servers.nil. +dom3379. NS a.root-servers.nil. +dom3380. NS a.root-servers.nil. +dom3381. NS a.root-servers.nil. +dom3382. NS a.root-servers.nil. +dom3383. NS a.root-servers.nil. +dom3384. NS a.root-servers.nil. +dom3385. NS a.root-servers.nil. +dom3386. NS a.root-servers.nil. +dom3387. NS a.root-servers.nil. +dom3388. NS a.root-servers.nil. +dom3389. NS a.root-servers.nil. +dom3390. NS a.root-servers.nil. +dom3391. NS a.root-servers.nil. +dom3392. NS a.root-servers.nil. +dom3393. NS a.root-servers.nil. +dom3394. NS a.root-servers.nil. +dom3395. NS a.root-servers.nil. +dom3396. NS a.root-servers.nil. +dom3397. NS a.root-servers.nil. +dom3398. NS a.root-servers.nil. +dom3399. NS a.root-servers.nil. +dom3400. NS a.root-servers.nil. +dom3401. NS a.root-servers.nil. +dom3402. NS a.root-servers.nil. +dom3403. NS a.root-servers.nil. +dom3404. NS a.root-servers.nil. +dom3405. NS a.root-servers.nil. +dom3406. NS a.root-servers.nil. +dom3407. NS a.root-servers.nil. +dom3408. NS a.root-servers.nil. +dom3409. NS a.root-servers.nil. +dom3410. NS a.root-servers.nil. +dom3411. NS a.root-servers.nil. +dom3412. NS a.root-servers.nil. +dom3413. NS a.root-servers.nil. +dom3414. NS a.root-servers.nil. +dom3415. NS a.root-servers.nil. +dom3416. NS a.root-servers.nil. +dom3417. NS a.root-servers.nil. +dom3418. NS a.root-servers.nil. +dom3419. NS a.root-servers.nil. +dom3420. NS a.root-servers.nil. +dom3421. NS a.root-servers.nil. +dom3422. NS a.root-servers.nil. +dom3423. NS a.root-servers.nil. +dom3424. NS a.root-servers.nil. +dom3425. NS a.root-servers.nil. +dom3426. NS a.root-servers.nil. +dom3427. NS a.root-servers.nil. +dom3428. NS a.root-servers.nil. +dom3429. NS a.root-servers.nil. +dom3430. NS a.root-servers.nil. +dom3431. NS a.root-servers.nil. +dom3432. NS a.root-servers.nil. +dom3433. NS a.root-servers.nil. +dom3434. NS a.root-servers.nil. +dom3435. NS a.root-servers.nil. +dom3436. NS a.root-servers.nil. +dom3437. NS a.root-servers.nil. +dom3438. NS a.root-servers.nil. +dom3439. NS a.root-servers.nil. +dom3440. NS a.root-servers.nil. +dom3441. NS a.root-servers.nil. +dom3442. NS a.root-servers.nil. +dom3443. NS a.root-servers.nil. +dom3444. NS a.root-servers.nil. +dom3445. NS a.root-servers.nil. +dom3446. NS a.root-servers.nil. +dom3447. NS a.root-servers.nil. +dom3448. NS a.root-servers.nil. +dom3449. NS a.root-servers.nil. +dom3450. NS a.root-servers.nil. +dom3451. NS a.root-servers.nil. +dom3452. NS a.root-servers.nil. +dom3453. NS a.root-servers.nil. +dom3454. NS a.root-servers.nil. +dom3455. NS a.root-servers.nil. +dom3456. NS a.root-servers.nil. +dom3457. NS a.root-servers.nil. +dom3458. NS a.root-servers.nil. +dom3459. NS a.root-servers.nil. +dom3460. NS a.root-servers.nil. +dom3461. NS a.root-servers.nil. +dom3462. NS a.root-servers.nil. +dom3463. NS a.root-servers.nil. +dom3464. NS a.root-servers.nil. +dom3465. NS a.root-servers.nil. +dom3466. NS a.root-servers.nil. +dom3467. NS a.root-servers.nil. +dom3468. NS a.root-servers.nil. +dom3469. NS a.root-servers.nil. +dom3470. NS a.root-servers.nil. +dom3471. NS a.root-servers.nil. +dom3472. NS a.root-servers.nil. +dom3473. NS a.root-servers.nil. +dom3474. NS a.root-servers.nil. +dom3475. NS a.root-servers.nil. +dom3476. NS a.root-servers.nil. +dom3477. NS a.root-servers.nil. +dom3478. NS a.root-servers.nil. +dom3479. NS a.root-servers.nil. +dom3480. NS a.root-servers.nil. +dom3481. NS a.root-servers.nil. +dom3482. NS a.root-servers.nil. +dom3483. NS a.root-servers.nil. +dom3484. NS a.root-servers.nil. +dom3485. NS a.root-servers.nil. +dom3486. NS a.root-servers.nil. +dom3487. NS a.root-servers.nil. +dom3488. NS a.root-servers.nil. +dom3489. NS a.root-servers.nil. +dom3490. NS a.root-servers.nil. +dom3491. NS a.root-servers.nil. +dom3492. NS a.root-servers.nil. +dom3493. NS a.root-servers.nil. +dom3494. NS a.root-servers.nil. +dom3495. NS a.root-servers.nil. +dom3496. NS a.root-servers.nil. +dom3497. NS a.root-servers.nil. +dom3498. NS a.root-servers.nil. +dom3499. NS a.root-servers.nil. +dom3500. NS a.root-servers.nil. +dom3501. NS a.root-servers.nil. +dom3502. NS a.root-servers.nil. +dom3503. NS a.root-servers.nil. +dom3504. NS a.root-servers.nil. +dom3505. NS a.root-servers.nil. +dom3506. NS a.root-servers.nil. +dom3507. NS a.root-servers.nil. +dom3508. NS a.root-servers.nil. +dom3509. NS a.root-servers.nil. +dom3510. NS a.root-servers.nil. +dom3511. NS a.root-servers.nil. +dom3512. NS a.root-servers.nil. +dom3513. NS a.root-servers.nil. +dom3514. NS a.root-servers.nil. +dom3515. NS a.root-servers.nil. +dom3516. NS a.root-servers.nil. +dom3517. NS a.root-servers.nil. +dom3518. NS a.root-servers.nil. +dom3519. NS a.root-servers.nil. +dom3520. NS a.root-servers.nil. +dom3521. NS a.root-servers.nil. +dom3522. NS a.root-servers.nil. +dom3523. NS a.root-servers.nil. +dom3524. NS a.root-servers.nil. +dom3525. NS a.root-servers.nil. +dom3526. NS a.root-servers.nil. +dom3527. NS a.root-servers.nil. +dom3528. NS a.root-servers.nil. +dom3529. NS a.root-servers.nil. +dom3530. NS a.root-servers.nil. +dom3531. NS a.root-servers.nil. +dom3532. NS a.root-servers.nil. +dom3533. NS a.root-servers.nil. +dom3534. NS a.root-servers.nil. +dom3535. NS a.root-servers.nil. +dom3536. NS a.root-servers.nil. +dom3537. NS a.root-servers.nil. +dom3538. NS a.root-servers.nil. +dom3539. NS a.root-servers.nil. +dom3540. NS a.root-servers.nil. +dom3541. NS a.root-servers.nil. +dom3542. NS a.root-servers.nil. +dom3543. NS a.root-servers.nil. +dom3544. NS a.root-servers.nil. +dom3545. NS a.root-servers.nil. +dom3546. NS a.root-servers.nil. +dom3547. NS a.root-servers.nil. +dom3548. NS a.root-servers.nil. +dom3549. NS a.root-servers.nil. +dom3550. NS a.root-servers.nil. +dom3551. NS a.root-servers.nil. +dom3552. NS a.root-servers.nil. +dom3553. NS a.root-servers.nil. +dom3554. NS a.root-servers.nil. +dom3555. NS a.root-servers.nil. +dom3556. NS a.root-servers.nil. +dom3557. NS a.root-servers.nil. +dom3558. NS a.root-servers.nil. +dom3559. NS a.root-servers.nil. +dom3560. NS a.root-servers.nil. +dom3561. NS a.root-servers.nil. +dom3562. NS a.root-servers.nil. +dom3563. NS a.root-servers.nil. +dom3564. NS a.root-servers.nil. +dom3565. NS a.root-servers.nil. +dom3566. NS a.root-servers.nil. +dom3567. NS a.root-servers.nil. +dom3568. NS a.root-servers.nil. +dom3569. NS a.root-servers.nil. +dom3570. NS a.root-servers.nil. +dom3571. NS a.root-servers.nil. +dom3572. NS a.root-servers.nil. +dom3573. NS a.root-servers.nil. +dom3574. NS a.root-servers.nil. +dom3575. NS a.root-servers.nil. +dom3576. NS a.root-servers.nil. +dom3577. NS a.root-servers.nil. +dom3578. NS a.root-servers.nil. +dom3579. NS a.root-servers.nil. +dom3580. NS a.root-servers.nil. +dom3581. NS a.root-servers.nil. +dom3582. NS a.root-servers.nil. +dom3583. NS a.root-servers.nil. +dom3584. NS a.root-servers.nil. +dom3585. NS a.root-servers.nil. +dom3586. NS a.root-servers.nil. +dom3587. NS a.root-servers.nil. +dom3588. NS a.root-servers.nil. +dom3589. NS a.root-servers.nil. +dom3590. NS a.root-servers.nil. +dom3591. NS a.root-servers.nil. +dom3592. NS a.root-servers.nil. +dom3593. NS a.root-servers.nil. +dom3594. NS a.root-servers.nil. +dom3595. NS a.root-servers.nil. +dom3596. NS a.root-servers.nil. +dom3597. NS a.root-servers.nil. +dom3598. NS a.root-servers.nil. +dom3599. NS a.root-servers.nil. +dom3600. NS a.root-servers.nil. +dom3601. NS a.root-servers.nil. +dom3602. NS a.root-servers.nil. +dom3603. NS a.root-servers.nil. +dom3604. NS a.root-servers.nil. +dom3605. NS a.root-servers.nil. +dom3606. NS a.root-servers.nil. +dom3607. NS a.root-servers.nil. +dom3608. NS a.root-servers.nil. +dom3609. NS a.root-servers.nil. +dom3610. NS a.root-servers.nil. +dom3611. NS a.root-servers.nil. +dom3612. NS a.root-servers.nil. +dom3613. NS a.root-servers.nil. +dom3614. NS a.root-servers.nil. +dom3615. NS a.root-servers.nil. +dom3616. NS a.root-servers.nil. +dom3617. NS a.root-servers.nil. +dom3618. NS a.root-servers.nil. +dom3619. NS a.root-servers.nil. +dom3620. NS a.root-servers.nil. +dom3621. NS a.root-servers.nil. +dom3622. NS a.root-servers.nil. +dom3623. NS a.root-servers.nil. +dom3624. NS a.root-servers.nil. +dom3625. NS a.root-servers.nil. +dom3626. NS a.root-servers.nil. +dom3627. NS a.root-servers.nil. +dom3628. NS a.root-servers.nil. +dom3629. NS a.root-servers.nil. +dom3630. NS a.root-servers.nil. +dom3631. NS a.root-servers.nil. +dom3632. NS a.root-servers.nil. +dom3633. NS a.root-servers.nil. +dom3634. NS a.root-servers.nil. +dom3635. NS a.root-servers.nil. +dom3636. NS a.root-servers.nil. +dom3637. NS a.root-servers.nil. +dom3638. NS a.root-servers.nil. +dom3639. NS a.root-servers.nil. +dom3640. NS a.root-servers.nil. +dom3641. NS a.root-servers.nil. +dom3642. NS a.root-servers.nil. +dom3643. NS a.root-servers.nil. +dom3644. NS a.root-servers.nil. +dom3645. NS a.root-servers.nil. +dom3646. NS a.root-servers.nil. +dom3647. NS a.root-servers.nil. +dom3648. NS a.root-servers.nil. +dom3649. NS a.root-servers.nil. +dom3650. NS a.root-servers.nil. +dom3651. NS a.root-servers.nil. +dom3652. NS a.root-servers.nil. +dom3653. NS a.root-servers.nil. +dom3654. NS a.root-servers.nil. +dom3655. NS a.root-servers.nil. +dom3656. NS a.root-servers.nil. +dom3657. NS a.root-servers.nil. +dom3658. NS a.root-servers.nil. +dom3659. NS a.root-servers.nil. +dom3660. NS a.root-servers.nil. +dom3661. NS a.root-servers.nil. +dom3662. NS a.root-servers.nil. +dom3663. NS a.root-servers.nil. +dom3664. NS a.root-servers.nil. +dom3665. NS a.root-servers.nil. +dom3666. NS a.root-servers.nil. +dom3667. NS a.root-servers.nil. +dom3668. NS a.root-servers.nil. +dom3669. NS a.root-servers.nil. +dom3670. NS a.root-servers.nil. +dom3671. NS a.root-servers.nil. +dom3672. NS a.root-servers.nil. +dom3673. NS a.root-servers.nil. +dom3674. NS a.root-servers.nil. +dom3675. NS a.root-servers.nil. +dom3676. NS a.root-servers.nil. +dom3677. NS a.root-servers.nil. +dom3678. NS a.root-servers.nil. +dom3679. NS a.root-servers.nil. +dom3680. NS a.root-servers.nil. +dom3681. NS a.root-servers.nil. +dom3682. NS a.root-servers.nil. +dom3683. NS a.root-servers.nil. +dom3684. NS a.root-servers.nil. +dom3685. NS a.root-servers.nil. +dom3686. NS a.root-servers.nil. +dom3687. NS a.root-servers.nil. +dom3688. NS a.root-servers.nil. +dom3689. NS a.root-servers.nil. +dom3690. NS a.root-servers.nil. +dom3691. NS a.root-servers.nil. +dom3692. NS a.root-servers.nil. +dom3693. NS a.root-servers.nil. +dom3694. NS a.root-servers.nil. +dom3695. NS a.root-servers.nil. +dom3696. NS a.root-servers.nil. +dom3697. NS a.root-servers.nil. +dom3698. NS a.root-servers.nil. +dom3699. NS a.root-servers.nil. +dom3700. NS a.root-servers.nil. +dom3701. NS a.root-servers.nil. +dom3702. NS a.root-servers.nil. +dom3703. NS a.root-servers.nil. +dom3704. NS a.root-servers.nil. +dom3705. NS a.root-servers.nil. +dom3706. NS a.root-servers.nil. +dom3707. NS a.root-servers.nil. +dom3708. NS a.root-servers.nil. +dom3709. NS a.root-servers.nil. +dom3710. NS a.root-servers.nil. +dom3711. NS a.root-servers.nil. +dom3712. NS a.root-servers.nil. +dom3713. NS a.root-servers.nil. +dom3714. NS a.root-servers.nil. +dom3715. NS a.root-servers.nil. +dom3716. NS a.root-servers.nil. +dom3717. NS a.root-servers.nil. +dom3718. NS a.root-servers.nil. +dom3719. NS a.root-servers.nil. +dom3720. NS a.root-servers.nil. +dom3721. NS a.root-servers.nil. +dom3722. NS a.root-servers.nil. +dom3723. NS a.root-servers.nil. +dom3724. NS a.root-servers.nil. +dom3725. NS a.root-servers.nil. +dom3726. NS a.root-servers.nil. +dom3727. NS a.root-servers.nil. +dom3728. NS a.root-servers.nil. +dom3729. NS a.root-servers.nil. +dom3730. NS a.root-servers.nil. +dom3731. NS a.root-servers.nil. +dom3732. NS a.root-servers.nil. +dom3733. NS a.root-servers.nil. +dom3734. NS a.root-servers.nil. +dom3735. NS a.root-servers.nil. +dom3736. NS a.root-servers.nil. +dom3737. NS a.root-servers.nil. +dom3738. NS a.root-servers.nil. +dom3739. NS a.root-servers.nil. +dom3740. NS a.root-servers.nil. +dom3741. NS a.root-servers.nil. +dom3742. NS a.root-servers.nil. +dom3743. NS a.root-servers.nil. +dom3744. NS a.root-servers.nil. +dom3745. NS a.root-servers.nil. +dom3746. NS a.root-servers.nil. +dom3747. NS a.root-servers.nil. +dom3748. NS a.root-servers.nil. +dom3749. NS a.root-servers.nil. +dom3750. NS a.root-servers.nil. +dom3751. NS a.root-servers.nil. +dom3752. NS a.root-servers.nil. +dom3753. NS a.root-servers.nil. +dom3754. NS a.root-servers.nil. +dom3755. NS a.root-servers.nil. +dom3756. NS a.root-servers.nil. +dom3757. NS a.root-servers.nil. +dom3758. NS a.root-servers.nil. +dom3759. NS a.root-servers.nil. +dom3760. NS a.root-servers.nil. +dom3761. NS a.root-servers.nil. +dom3762. NS a.root-servers.nil. +dom3763. NS a.root-servers.nil. +dom3764. NS a.root-servers.nil. +dom3765. NS a.root-servers.nil. +dom3766. NS a.root-servers.nil. +dom3767. NS a.root-servers.nil. +dom3768. NS a.root-servers.nil. +dom3769. NS a.root-servers.nil. +dom3770. NS a.root-servers.nil. +dom3771. NS a.root-servers.nil. +dom3772. NS a.root-servers.nil. +dom3773. NS a.root-servers.nil. +dom3774. NS a.root-servers.nil. +dom3775. NS a.root-servers.nil. +dom3776. NS a.root-servers.nil. +dom3777. NS a.root-servers.nil. +dom3778. NS a.root-servers.nil. +dom3779. NS a.root-servers.nil. +dom3780. NS a.root-servers.nil. +dom3781. NS a.root-servers.nil. +dom3782. NS a.root-servers.nil. +dom3783. NS a.root-servers.nil. +dom3784. NS a.root-servers.nil. +dom3785. NS a.root-servers.nil. +dom3786. NS a.root-servers.nil. +dom3787. NS a.root-servers.nil. +dom3788. NS a.root-servers.nil. +dom3789. NS a.root-servers.nil. +dom3790. NS a.root-servers.nil. +dom3791. NS a.root-servers.nil. +dom3792. NS a.root-servers.nil. +dom3793. NS a.root-servers.nil. +dom3794. NS a.root-servers.nil. +dom3795. NS a.root-servers.nil. +dom3796. NS a.root-servers.nil. +dom3797. NS a.root-servers.nil. +dom3798. NS a.root-servers.nil. +dom3799. NS a.root-servers.nil. +dom3800. NS a.root-servers.nil. +dom3801. NS a.root-servers.nil. +dom3802. NS a.root-servers.nil. +dom3803. NS a.root-servers.nil. +dom3804. NS a.root-servers.nil. +dom3805. NS a.root-servers.nil. +dom3806. NS a.root-servers.nil. +dom3807. NS a.root-servers.nil. +dom3808. NS a.root-servers.nil. +dom3809. NS a.root-servers.nil. +dom3810. NS a.root-servers.nil. +dom3811. NS a.root-servers.nil. +dom3812. NS a.root-servers.nil. +dom3813. NS a.root-servers.nil. +dom3814. NS a.root-servers.nil. +dom3815. NS a.root-servers.nil. +dom3816. NS a.root-servers.nil. +dom3817. NS a.root-servers.nil. +dom3818. NS a.root-servers.nil. +dom3819. NS a.root-servers.nil. +dom3820. NS a.root-servers.nil. +dom3821. NS a.root-servers.nil. +dom3822. NS a.root-servers.nil. +dom3823. NS a.root-servers.nil. +dom3824. NS a.root-servers.nil. +dom3825. NS a.root-servers.nil. +dom3826. NS a.root-servers.nil. +dom3827. NS a.root-servers.nil. +dom3828. NS a.root-servers.nil. +dom3829. NS a.root-servers.nil. +dom3830. NS a.root-servers.nil. +dom3831. NS a.root-servers.nil. +dom3832. NS a.root-servers.nil. +dom3833. NS a.root-servers.nil. +dom3834. NS a.root-servers.nil. +dom3835. NS a.root-servers.nil. +dom3836. NS a.root-servers.nil. +dom3837. NS a.root-servers.nil. +dom3838. NS a.root-servers.nil. +dom3839. NS a.root-servers.nil. +dom3840. NS a.root-servers.nil. +dom3841. NS a.root-servers.nil. +dom3842. NS a.root-servers.nil. +dom3843. NS a.root-servers.nil. +dom3844. NS a.root-servers.nil. +dom3845. NS a.root-servers.nil. +dom3846. NS a.root-servers.nil. +dom3847. NS a.root-servers.nil. +dom3848. NS a.root-servers.nil. +dom3849. NS a.root-servers.nil. +dom3850. NS a.root-servers.nil. +dom3851. NS a.root-servers.nil. +dom3852. NS a.root-servers.nil. +dom3853. NS a.root-servers.nil. +dom3854. NS a.root-servers.nil. +dom3855. NS a.root-servers.nil. +dom3856. NS a.root-servers.nil. +dom3857. NS a.root-servers.nil. +dom3858. NS a.root-servers.nil. +dom3859. NS a.root-servers.nil. +dom3860. NS a.root-servers.nil. +dom3861. NS a.root-servers.nil. +dom3862. NS a.root-servers.nil. +dom3863. NS a.root-servers.nil. +dom3864. NS a.root-servers.nil. +dom3865. NS a.root-servers.nil. +dom3866. NS a.root-servers.nil. +dom3867. NS a.root-servers.nil. +dom3868. NS a.root-servers.nil. +dom3869. NS a.root-servers.nil. +dom3870. NS a.root-servers.nil. +dom3871. NS a.root-servers.nil. +dom3872. NS a.root-servers.nil. +dom3873. NS a.root-servers.nil. +dom3874. NS a.root-servers.nil. +dom3875. NS a.root-servers.nil. +dom3876. NS a.root-servers.nil. +dom3877. NS a.root-servers.nil. +dom3878. NS a.root-servers.nil. +dom3879. NS a.root-servers.nil. +dom3880. NS a.root-servers.nil. +dom3881. NS a.root-servers.nil. +dom3882. NS a.root-servers.nil. +dom3883. NS a.root-servers.nil. +dom3884. NS a.root-servers.nil. +dom3885. NS a.root-servers.nil. +dom3886. NS a.root-servers.nil. +dom3887. NS a.root-servers.nil. +dom3888. NS a.root-servers.nil. +dom3889. NS a.root-servers.nil. +dom3890. NS a.root-servers.nil. +dom3891. NS a.root-servers.nil. +dom3892. NS a.root-servers.nil. +dom3893. NS a.root-servers.nil. +dom3894. NS a.root-servers.nil. +dom3895. NS a.root-servers.nil. +dom3896. NS a.root-servers.nil. +dom3897. NS a.root-servers.nil. +dom3898. NS a.root-servers.nil. +dom3899. NS a.root-servers.nil. +dom3900. NS a.root-servers.nil. +dom3901. NS a.root-servers.nil. +dom3902. NS a.root-servers.nil. +dom3903. NS a.root-servers.nil. +dom3904. NS a.root-servers.nil. +dom3905. NS a.root-servers.nil. +dom3906. NS a.root-servers.nil. +dom3907. NS a.root-servers.nil. +dom3908. NS a.root-servers.nil. +dom3909. NS a.root-servers.nil. +dom3910. NS a.root-servers.nil. +dom3911. NS a.root-servers.nil. +dom3912. NS a.root-servers.nil. +dom3913. NS a.root-servers.nil. +dom3914. NS a.root-servers.nil. +dom3915. NS a.root-servers.nil. +dom3916. NS a.root-servers.nil. +dom3917. NS a.root-servers.nil. +dom3918. NS a.root-servers.nil. +dom3919. NS a.root-servers.nil. +dom3920. NS a.root-servers.nil. +dom3921. NS a.root-servers.nil. +dom3922. NS a.root-servers.nil. +dom3923. NS a.root-servers.nil. +dom3924. NS a.root-servers.nil. +dom3925. NS a.root-servers.nil. +dom3926. NS a.root-servers.nil. +dom3927. NS a.root-servers.nil. +dom3928. NS a.root-servers.nil. +dom3929. NS a.root-servers.nil. +dom3930. NS a.root-servers.nil. +dom3931. NS a.root-servers.nil. +dom3932. NS a.root-servers.nil. +dom3933. NS a.root-servers.nil. +dom3934. NS a.root-servers.nil. +dom3935. NS a.root-servers.nil. +dom3936. NS a.root-servers.nil. +dom3937. NS a.root-servers.nil. +dom3938. NS a.root-servers.nil. +dom3939. NS a.root-servers.nil. +dom3940. NS a.root-servers.nil. +dom3941. NS a.root-servers.nil. +dom3942. NS a.root-servers.nil. +dom3943. NS a.root-servers.nil. +dom3944. NS a.root-servers.nil. +dom3945. NS a.root-servers.nil. +dom3946. NS a.root-servers.nil. +dom3947. NS a.root-servers.nil. +dom3948. NS a.root-servers.nil. +dom3949. NS a.root-servers.nil. +dom3950. NS a.root-servers.nil. +dom3951. NS a.root-servers.nil. +dom3952. NS a.root-servers.nil. +dom3953. NS a.root-servers.nil. +dom3954. NS a.root-servers.nil. +dom3955. NS a.root-servers.nil. +dom3956. NS a.root-servers.nil. +dom3957. NS a.root-servers.nil. +dom3958. NS a.root-servers.nil. +dom3959. NS a.root-servers.nil. +dom3960. NS a.root-servers.nil. +dom3961. NS a.root-servers.nil. +dom3962. NS a.root-servers.nil. +dom3963. NS a.root-servers.nil. +dom3964. NS a.root-servers.nil. +dom3965. NS a.root-servers.nil. +dom3966. NS a.root-servers.nil. +dom3967. NS a.root-servers.nil. +dom3968. NS a.root-servers.nil. +dom3969. NS a.root-servers.nil. +dom3970. NS a.root-servers.nil. +dom3971. NS a.root-servers.nil. +dom3972. NS a.root-servers.nil. +dom3973. NS a.root-servers.nil. +dom3974. NS a.root-servers.nil. +dom3975. NS a.root-servers.nil. +dom3976. NS a.root-servers.nil. +dom3977. NS a.root-servers.nil. +dom3978. NS a.root-servers.nil. +dom3979. NS a.root-servers.nil. +dom3980. NS a.root-servers.nil. +dom3981. NS a.root-servers.nil. +dom3982. NS a.root-servers.nil. +dom3983. NS a.root-servers.nil. +dom3984. NS a.root-servers.nil. +dom3985. NS a.root-servers.nil. +dom3986. NS a.root-servers.nil. +dom3987. NS a.root-servers.nil. +dom3988. NS a.root-servers.nil. +dom3989. NS a.root-servers.nil. +dom3990. NS a.root-servers.nil. +dom3991. NS a.root-servers.nil. +dom3992. NS a.root-servers.nil. +dom3993. NS a.root-servers.nil. +dom3994. NS a.root-servers.nil. +dom3995. NS a.root-servers.nil. +dom3996. NS a.root-servers.nil. +dom3997. NS a.root-servers.nil. +dom3998. NS a.root-servers.nil. +dom3999. NS a.root-servers.nil. +dom4000. NS a.root-servers.nil. +dom4001. NS a.root-servers.nil. +dom4002. NS a.root-servers.nil. +dom4003. NS a.root-servers.nil. +dom4004. NS a.root-servers.nil. +dom4005. NS a.root-servers.nil. +dom4006. NS a.root-servers.nil. +dom4007. NS a.root-servers.nil. +dom4008. NS a.root-servers.nil. +dom4009. NS a.root-servers.nil. +dom4010. NS a.root-servers.nil. +dom4011. NS a.root-servers.nil. +dom4012. NS a.root-servers.nil. +dom4013. NS a.root-servers.nil. +dom4014. NS a.root-servers.nil. +dom4015. NS a.root-servers.nil. +dom4016. NS a.root-servers.nil. +dom4017. NS a.root-servers.nil. +dom4018. NS a.root-servers.nil. +dom4019. NS a.root-servers.nil. +dom4020. NS a.root-servers.nil. +dom4021. NS a.root-servers.nil. +dom4022. NS a.root-servers.nil. +dom4023. NS a.root-servers.nil. +dom4024. NS a.root-servers.nil. +dom4025. NS a.root-servers.nil. +dom4026. NS a.root-servers.nil. +dom4027. NS a.root-servers.nil. +dom4028. NS a.root-servers.nil. +dom4029. NS a.root-servers.nil. +dom4030. NS a.root-servers.nil. +dom4031. NS a.root-servers.nil. +dom4032. NS a.root-servers.nil. +dom4033. NS a.root-servers.nil. +dom4034. NS a.root-servers.nil. +dom4035. NS a.root-servers.nil. +dom4036. NS a.root-servers.nil. +dom4037. NS a.root-servers.nil. +dom4038. NS a.root-servers.nil. +dom4039. NS a.root-servers.nil. +dom4040. NS a.root-servers.nil. +dom4041. NS a.root-servers.nil. +dom4042. NS a.root-servers.nil. +dom4043. NS a.root-servers.nil. +dom4044. NS a.root-servers.nil. +dom4045. NS a.root-servers.nil. +dom4046. NS a.root-servers.nil. +dom4047. NS a.root-servers.nil. +dom4048. NS a.root-servers.nil. +dom4049. NS a.root-servers.nil. +dom4050. NS a.root-servers.nil. +dom4051. NS a.root-servers.nil. +dom4052. NS a.root-servers.nil. +dom4053. NS a.root-servers.nil. +dom4054. NS a.root-servers.nil. +dom4055. NS a.root-servers.nil. +dom4056. NS a.root-servers.nil. +dom4057. NS a.root-servers.nil. +dom4058. NS a.root-servers.nil. +dom4059. NS a.root-servers.nil. +dom4060. NS a.root-servers.nil. +dom4061. NS a.root-servers.nil. +dom4062. NS a.root-servers.nil. +dom4063. NS a.root-servers.nil. +dom4064. NS a.root-servers.nil. +dom4065. NS a.root-servers.nil. +dom4066. NS a.root-servers.nil. +dom4067. NS a.root-servers.nil. +dom4068. NS a.root-servers.nil. +dom4069. NS a.root-servers.nil. +dom4070. NS a.root-servers.nil. +dom4071. NS a.root-servers.nil. +dom4072. NS a.root-servers.nil. +dom4073. NS a.root-servers.nil. +dom4074. NS a.root-servers.nil. +dom4075. NS a.root-servers.nil. +dom4076. NS a.root-servers.nil. +dom4077. NS a.root-servers.nil. +dom4078. NS a.root-servers.nil. +dom4079. NS a.root-servers.nil. +dom4080. NS a.root-servers.nil. +dom4081. NS a.root-servers.nil. +dom4082. NS a.root-servers.nil. +dom4083. NS a.root-servers.nil. +dom4084. NS a.root-servers.nil. +dom4085. NS a.root-servers.nil. +dom4086. NS a.root-servers.nil. +dom4087. NS a.root-servers.nil. +dom4088. NS a.root-servers.nil. +dom4089. NS a.root-servers.nil. +dom4090. NS a.root-servers.nil. +dom4091. NS a.root-servers.nil. +dom4092. NS a.root-servers.nil. +dom4093. NS a.root-servers.nil. +dom4094. NS a.root-servers.nil. +dom4095. NS a.root-servers.nil. +dom4096. NS a.root-servers.nil. +dom4097. NS a.root-servers.nil. +dom4098. NS a.root-servers.nil. +dom4099. NS a.root-servers.nil. +dom4100. NS a.root-servers.nil. +dom4101. NS a.root-servers.nil. +dom4102. NS a.root-servers.nil. +dom4103. NS a.root-servers.nil. +dom4104. NS a.root-servers.nil. +dom4105. NS a.root-servers.nil. +dom4106. NS a.root-servers.nil. +dom4107. NS a.root-servers.nil. +dom4108. NS a.root-servers.nil. +dom4109. NS a.root-servers.nil. +dom4110. NS a.root-servers.nil. +dom4111. NS a.root-servers.nil. +dom4112. NS a.root-servers.nil. +dom4113. NS a.root-servers.nil. +dom4114. NS a.root-servers.nil. +dom4115. NS a.root-servers.nil. +dom4116. NS a.root-servers.nil. +dom4117. NS a.root-servers.nil. +dom4118. NS a.root-servers.nil. +dom4119. NS a.root-servers.nil. +dom4120. NS a.root-servers.nil. +dom4121. NS a.root-servers.nil. +dom4122. NS a.root-servers.nil. +dom4123. NS a.root-servers.nil. +dom4124. NS a.root-servers.nil. +dom4125. NS a.root-servers.nil. +dom4126. NS a.root-servers.nil. +dom4127. NS a.root-servers.nil. +dom4128. NS a.root-servers.nil. +dom4129. NS a.root-servers.nil. +dom4130. NS a.root-servers.nil. +dom4131. NS a.root-servers.nil. +dom4132. NS a.root-servers.nil. +dom4133. NS a.root-servers.nil. +dom4134. NS a.root-servers.nil. +dom4135. NS a.root-servers.nil. +dom4136. NS a.root-servers.nil. +dom4137. NS a.root-servers.nil. +dom4138. NS a.root-servers.nil. +dom4139. NS a.root-servers.nil. +dom4140. NS a.root-servers.nil. +dom4141. NS a.root-servers.nil. +dom4142. NS a.root-servers.nil. +dom4143. NS a.root-servers.nil. +dom4144. NS a.root-servers.nil. +dom4145. NS a.root-servers.nil. +dom4146. NS a.root-servers.nil. +dom4147. NS a.root-servers.nil. +dom4148. NS a.root-servers.nil. +dom4149. NS a.root-servers.nil. +dom4150. NS a.root-servers.nil. +dom4151. NS a.root-servers.nil. +dom4152. NS a.root-servers.nil. +dom4153. NS a.root-servers.nil. +dom4154. NS a.root-servers.nil. +dom4155. NS a.root-servers.nil. +dom4156. NS a.root-servers.nil. +dom4157. NS a.root-servers.nil. +dom4158. NS a.root-servers.nil. +dom4159. NS a.root-servers.nil. +dom4160. NS a.root-servers.nil. +dom4161. NS a.root-servers.nil. +dom4162. NS a.root-servers.nil. +dom4163. NS a.root-servers.nil. +dom4164. NS a.root-servers.nil. +dom4165. NS a.root-servers.nil. +dom4166. NS a.root-servers.nil. +dom4167. NS a.root-servers.nil. +dom4168. NS a.root-servers.nil. +dom4169. NS a.root-servers.nil. +dom4170. NS a.root-servers.nil. +dom4171. NS a.root-servers.nil. +dom4172. NS a.root-servers.nil. +dom4173. NS a.root-servers.nil. +dom4174. NS a.root-servers.nil. +dom4175. NS a.root-servers.nil. +dom4176. NS a.root-servers.nil. +dom4177. NS a.root-servers.nil. +dom4178. NS a.root-servers.nil. +dom4179. NS a.root-servers.nil. +dom4180. NS a.root-servers.nil. +dom4181. NS a.root-servers.nil. +dom4182. NS a.root-servers.nil. +dom4183. NS a.root-servers.nil. +dom4184. NS a.root-servers.nil. +dom4185. NS a.root-servers.nil. +dom4186. NS a.root-servers.nil. +dom4187. NS a.root-servers.nil. +dom4188. NS a.root-servers.nil. +dom4189. NS a.root-servers.nil. +dom4190. NS a.root-servers.nil. +dom4191. NS a.root-servers.nil. +dom4192. NS a.root-servers.nil. +dom4193. NS a.root-servers.nil. +dom4194. NS a.root-servers.nil. +dom4195. NS a.root-servers.nil. +dom4196. NS a.root-servers.nil. +dom4197. NS a.root-servers.nil. +dom4198. NS a.root-servers.nil. +dom4199. NS a.root-servers.nil. +dom4200. NS a.root-servers.nil. +dom4201. NS a.root-servers.nil. +dom4202. NS a.root-servers.nil. +dom4203. NS a.root-servers.nil. +dom4204. NS a.root-servers.nil. +dom4205. NS a.root-servers.nil. +dom4206. NS a.root-servers.nil. +dom4207. NS a.root-servers.nil. +dom4208. NS a.root-servers.nil. +dom4209. NS a.root-servers.nil. +dom4210. NS a.root-servers.nil. +dom4211. NS a.root-servers.nil. +dom4212. NS a.root-servers.nil. +dom4213. NS a.root-servers.nil. +dom4214. NS a.root-servers.nil. +dom4215. NS a.root-servers.nil. +dom4216. NS a.root-servers.nil. +dom4217. NS a.root-servers.nil. +dom4218. NS a.root-servers.nil. +dom4219. NS a.root-servers.nil. +dom4220. NS a.root-servers.nil. +dom4221. NS a.root-servers.nil. +dom4222. NS a.root-servers.nil. +dom4223. NS a.root-servers.nil. +dom4224. NS a.root-servers.nil. +dom4225. NS a.root-servers.nil. +dom4226. NS a.root-servers.nil. +dom4227. NS a.root-servers.nil. +dom4228. NS a.root-servers.nil. +dom4229. NS a.root-servers.nil. +dom4230. NS a.root-servers.nil. +dom4231. NS a.root-servers.nil. +dom4232. NS a.root-servers.nil. +dom4233. NS a.root-servers.nil. +dom4234. NS a.root-servers.nil. +dom4235. NS a.root-servers.nil. +dom4236. NS a.root-servers.nil. +dom4237. NS a.root-servers.nil. +dom4238. NS a.root-servers.nil. +dom4239. NS a.root-servers.nil. +dom4240. NS a.root-servers.nil. +dom4241. NS a.root-servers.nil. +dom4242. NS a.root-servers.nil. +dom4243. NS a.root-servers.nil. +dom4244. NS a.root-servers.nil. +dom4245. NS a.root-servers.nil. +dom4246. NS a.root-servers.nil. +dom4247. NS a.root-servers.nil. +dom4248. NS a.root-servers.nil. +dom4249. NS a.root-servers.nil. +dom4250. NS a.root-servers.nil. +dom4251. NS a.root-servers.nil. +dom4252. NS a.root-servers.nil. +dom4253. NS a.root-servers.nil. +dom4254. NS a.root-servers.nil. +dom4255. NS a.root-servers.nil. +dom4256. NS a.root-servers.nil. +dom4257. NS a.root-servers.nil. +dom4258. NS a.root-servers.nil. +dom4259. NS a.root-servers.nil. +dom4260. NS a.root-servers.nil. +dom4261. NS a.root-servers.nil. +dom4262. NS a.root-servers.nil. +dom4263. NS a.root-servers.nil. +dom4264. NS a.root-servers.nil. +dom4265. NS a.root-servers.nil. +dom4266. NS a.root-servers.nil. +dom4267. NS a.root-servers.nil. +dom4268. NS a.root-servers.nil. +dom4269. NS a.root-servers.nil. +dom4270. NS a.root-servers.nil. +dom4271. NS a.root-servers.nil. +dom4272. NS a.root-servers.nil. +dom4273. NS a.root-servers.nil. +dom4274. NS a.root-servers.nil. +dom4275. NS a.root-servers.nil. +dom4276. NS a.root-servers.nil. +dom4277. NS a.root-servers.nil. +dom4278. NS a.root-servers.nil. +dom4279. NS a.root-servers.nil. +dom4280. NS a.root-servers.nil. +dom4281. NS a.root-servers.nil. +dom4282. NS a.root-servers.nil. +dom4283. NS a.root-servers.nil. +dom4284. NS a.root-servers.nil. +dom4285. NS a.root-servers.nil. +dom4286. NS a.root-servers.nil. +dom4287. NS a.root-servers.nil. +dom4288. NS a.root-servers.nil. +dom4289. NS a.root-servers.nil. +dom4290. NS a.root-servers.nil. +dom4291. NS a.root-servers.nil. +dom4292. NS a.root-servers.nil. +dom4293. NS a.root-servers.nil. +dom4294. NS a.root-servers.nil. +dom4295. NS a.root-servers.nil. +dom4296. NS a.root-servers.nil. +dom4297. NS a.root-servers.nil. +dom4298. NS a.root-servers.nil. +dom4299. NS a.root-servers.nil. +dom4300. NS a.root-servers.nil. +dom4301. NS a.root-servers.nil. +dom4302. NS a.root-servers.nil. +dom4303. NS a.root-servers.nil. +dom4304. NS a.root-servers.nil. +dom4305. NS a.root-servers.nil. +dom4306. NS a.root-servers.nil. +dom4307. NS a.root-servers.nil. +dom4308. NS a.root-servers.nil. +dom4309. NS a.root-servers.nil. +dom4310. NS a.root-servers.nil. +dom4311. NS a.root-servers.nil. +dom4312. NS a.root-servers.nil. +dom4313. NS a.root-servers.nil. +dom4314. NS a.root-servers.nil. +dom4315. NS a.root-servers.nil. +dom4316. NS a.root-servers.nil. +dom4317. NS a.root-servers.nil. +dom4318. NS a.root-servers.nil. +dom4319. NS a.root-servers.nil. +dom4320. NS a.root-servers.nil. +dom4321. NS a.root-servers.nil. +dom4322. NS a.root-servers.nil. +dom4323. NS a.root-servers.nil. +dom4324. NS a.root-servers.nil. +dom4325. NS a.root-servers.nil. +dom4326. NS a.root-servers.nil. +dom4327. NS a.root-servers.nil. +dom4328. NS a.root-servers.nil. +dom4329. NS a.root-servers.nil. +dom4330. NS a.root-servers.nil. +dom4331. NS a.root-servers.nil. +dom4332. NS a.root-servers.nil. +dom4333. NS a.root-servers.nil. +dom4334. NS a.root-servers.nil. +dom4335. NS a.root-servers.nil. +dom4336. NS a.root-servers.nil. +dom4337. NS a.root-servers.nil. +dom4338. NS a.root-servers.nil. +dom4339. NS a.root-servers.nil. +dom4340. NS a.root-servers.nil. +dom4341. NS a.root-servers.nil. +dom4342. NS a.root-servers.nil. +dom4343. NS a.root-servers.nil. +dom4344. NS a.root-servers.nil. +dom4345. NS a.root-servers.nil. +dom4346. NS a.root-servers.nil. +dom4347. NS a.root-servers.nil. +dom4348. NS a.root-servers.nil. +dom4349. NS a.root-servers.nil. +dom4350. NS a.root-servers.nil. +dom4351. NS a.root-servers.nil. +dom4352. NS a.root-servers.nil. +dom4353. NS a.root-servers.nil. +dom4354. NS a.root-servers.nil. +dom4355. NS a.root-servers.nil. +dom4356. NS a.root-servers.nil. +dom4357. NS a.root-servers.nil. +dom4358. NS a.root-servers.nil. +dom4359. NS a.root-servers.nil. +dom4360. NS a.root-servers.nil. +dom4361. NS a.root-servers.nil. +dom4362. NS a.root-servers.nil. +dom4363. NS a.root-servers.nil. +dom4364. NS a.root-servers.nil. +dom4365. NS a.root-servers.nil. +dom4366. NS a.root-servers.nil. +dom4367. NS a.root-servers.nil. +dom4368. NS a.root-servers.nil. +dom4369. NS a.root-servers.nil. +dom4370. NS a.root-servers.nil. +dom4371. NS a.root-servers.nil. +dom4372. NS a.root-servers.nil. +dom4373. NS a.root-servers.nil. +dom4374. NS a.root-servers.nil. +dom4375. NS a.root-servers.nil. +dom4376. NS a.root-servers.nil. +dom4377. NS a.root-servers.nil. +dom4378. NS a.root-servers.nil. +dom4379. NS a.root-servers.nil. +dom4380. NS a.root-servers.nil. +dom4381. NS a.root-servers.nil. +dom4382. NS a.root-servers.nil. +dom4383. NS a.root-servers.nil. +dom4384. NS a.root-servers.nil. +dom4385. NS a.root-servers.nil. +dom4386. NS a.root-servers.nil. +dom4387. NS a.root-servers.nil. +dom4388. NS a.root-servers.nil. +dom4389. NS a.root-servers.nil. +dom4390. NS a.root-servers.nil. +dom4391. NS a.root-servers.nil. +dom4392. NS a.root-servers.nil. +dom4393. NS a.root-servers.nil. +dom4394. NS a.root-servers.nil. +dom4395. NS a.root-servers.nil. +dom4396. NS a.root-servers.nil. +dom4397. NS a.root-servers.nil. +dom4398. NS a.root-servers.nil. +dom4399. NS a.root-servers.nil. +dom4400. NS a.root-servers.nil. +dom4401. NS a.root-servers.nil. +dom4402. NS a.root-servers.nil. +dom4403. NS a.root-servers.nil. +dom4404. NS a.root-servers.nil. +dom4405. NS a.root-servers.nil. +dom4406. NS a.root-servers.nil. +dom4407. NS a.root-servers.nil. +dom4408. NS a.root-servers.nil. +dom4409. NS a.root-servers.nil. +dom4410. NS a.root-servers.nil. +dom4411. NS a.root-servers.nil. +dom4412. NS a.root-servers.nil. +dom4413. NS a.root-servers.nil. +dom4414. NS a.root-servers.nil. +dom4415. NS a.root-servers.nil. +dom4416. NS a.root-servers.nil. +dom4417. NS a.root-servers.nil. +dom4418. NS a.root-servers.nil. +dom4419. NS a.root-servers.nil. +dom4420. NS a.root-servers.nil. +dom4421. NS a.root-servers.nil. +dom4422. NS a.root-servers.nil. +dom4423. NS a.root-servers.nil. +dom4424. NS a.root-servers.nil. +dom4425. NS a.root-servers.nil. +dom4426. NS a.root-servers.nil. +dom4427. NS a.root-servers.nil. +dom4428. NS a.root-servers.nil. +dom4429. NS a.root-servers.nil. +dom4430. NS a.root-servers.nil. +dom4431. NS a.root-servers.nil. +dom4432. NS a.root-servers.nil. +dom4433. NS a.root-servers.nil. +dom4434. NS a.root-servers.nil. +dom4435. NS a.root-servers.nil. +dom4436. NS a.root-servers.nil. +dom4437. NS a.root-servers.nil. +dom4438. NS a.root-servers.nil. +dom4439. NS a.root-servers.nil. +dom4440. NS a.root-servers.nil. +dom4441. NS a.root-servers.nil. +dom4442. NS a.root-servers.nil. +dom4443. NS a.root-servers.nil. +dom4444. NS a.root-servers.nil. +dom4445. NS a.root-servers.nil. +dom4446. NS a.root-servers.nil. +dom4447. NS a.root-servers.nil. +dom4448. NS a.root-servers.nil. +dom4449. NS a.root-servers.nil. +dom4450. NS a.root-servers.nil. +dom4451. NS a.root-servers.nil. +dom4452. NS a.root-servers.nil. +dom4453. NS a.root-servers.nil. +dom4454. NS a.root-servers.nil. +dom4455. NS a.root-servers.nil. +dom4456. NS a.root-servers.nil. +dom4457. NS a.root-servers.nil. +dom4458. NS a.root-servers.nil. +dom4459. NS a.root-servers.nil. +dom4460. NS a.root-servers.nil. +dom4461. NS a.root-servers.nil. +dom4462. NS a.root-servers.nil. +dom4463. NS a.root-servers.nil. +dom4464. NS a.root-servers.nil. +dom4465. NS a.root-servers.nil. +dom4466. NS a.root-servers.nil. +dom4467. NS a.root-servers.nil. +dom4468. NS a.root-servers.nil. +dom4469. NS a.root-servers.nil. +dom4470. NS a.root-servers.nil. +dom4471. NS a.root-servers.nil. +dom4472. NS a.root-servers.nil. +dom4473. NS a.root-servers.nil. +dom4474. NS a.root-servers.nil. +dom4475. NS a.root-servers.nil. +dom4476. NS a.root-servers.nil. +dom4477. NS a.root-servers.nil. +dom4478. NS a.root-servers.nil. +dom4479. NS a.root-servers.nil. +dom4480. NS a.root-servers.nil. +dom4481. NS a.root-servers.nil. +dom4482. NS a.root-servers.nil. +dom4483. NS a.root-servers.nil. +dom4484. NS a.root-servers.nil. +dom4485. NS a.root-servers.nil. +dom4486. NS a.root-servers.nil. +dom4487. NS a.root-servers.nil. +dom4488. NS a.root-servers.nil. +dom4489. NS a.root-servers.nil. +dom4490. NS a.root-servers.nil. +dom4491. NS a.root-servers.nil. +dom4492. NS a.root-servers.nil. +dom4493. NS a.root-servers.nil. +dom4494. NS a.root-servers.nil. +dom4495. NS a.root-servers.nil. +dom4496. NS a.root-servers.nil. +dom4497. NS a.root-servers.nil. +dom4498. NS a.root-servers.nil. +dom4499. NS a.root-servers.nil. +dom4500. NS a.root-servers.nil. +dom4501. NS a.root-servers.nil. +dom4502. NS a.root-servers.nil. +dom4503. NS a.root-servers.nil. +dom4504. NS a.root-servers.nil. +dom4505. NS a.root-servers.nil. +dom4506. NS a.root-servers.nil. +dom4507. NS a.root-servers.nil. +dom4508. NS a.root-servers.nil. +dom4509. NS a.root-servers.nil. +dom4510. NS a.root-servers.nil. +dom4511. NS a.root-servers.nil. +dom4512. NS a.root-servers.nil. +dom4513. NS a.root-servers.nil. +dom4514. NS a.root-servers.nil. +dom4515. NS a.root-servers.nil. +dom4516. NS a.root-servers.nil. +dom4517. NS a.root-servers.nil. +dom4518. NS a.root-servers.nil. +dom4519. NS a.root-servers.nil. +dom4520. NS a.root-servers.nil. +dom4521. NS a.root-servers.nil. +dom4522. NS a.root-servers.nil. +dom4523. NS a.root-servers.nil. +dom4524. NS a.root-servers.nil. +dom4525. NS a.root-servers.nil. +dom4526. NS a.root-servers.nil. +dom4527. NS a.root-servers.nil. +dom4528. NS a.root-servers.nil. +dom4529. NS a.root-servers.nil. +dom4530. NS a.root-servers.nil. +dom4531. NS a.root-servers.nil. +dom4532. NS a.root-servers.nil. +dom4533. NS a.root-servers.nil. +dom4534. NS a.root-servers.nil. +dom4535. NS a.root-servers.nil. +dom4536. NS a.root-servers.nil. +dom4537. NS a.root-servers.nil. +dom4538. NS a.root-servers.nil. +dom4539. NS a.root-servers.nil. +dom4540. NS a.root-servers.nil. +dom4541. NS a.root-servers.nil. +dom4542. NS a.root-servers.nil. +dom4543. NS a.root-servers.nil. +dom4544. NS a.root-servers.nil. +dom4545. NS a.root-servers.nil. +dom4546. NS a.root-servers.nil. +dom4547. NS a.root-servers.nil. +dom4548. NS a.root-servers.nil. +dom4549. NS a.root-servers.nil. +dom4550. NS a.root-servers.nil. +dom4551. NS a.root-servers.nil. +dom4552. NS a.root-servers.nil. +dom4553. NS a.root-servers.nil. +dom4554. NS a.root-servers.nil. +dom4555. NS a.root-servers.nil. +dom4556. NS a.root-servers.nil. +dom4557. NS a.root-servers.nil. +dom4558. NS a.root-servers.nil. +dom4559. NS a.root-servers.nil. +dom4560. NS a.root-servers.nil. +dom4561. NS a.root-servers.nil. +dom4562. NS a.root-servers.nil. +dom4563. NS a.root-servers.nil. +dom4564. NS a.root-servers.nil. +dom4565. NS a.root-servers.nil. +dom4566. NS a.root-servers.nil. +dom4567. NS a.root-servers.nil. +dom4568. NS a.root-servers.nil. +dom4569. NS a.root-servers.nil. +dom4570. NS a.root-servers.nil. +dom4571. NS a.root-servers.nil. +dom4572. NS a.root-servers.nil. +dom4573. NS a.root-servers.nil. +dom4574. NS a.root-servers.nil. +dom4575. NS a.root-servers.nil. +dom4576. NS a.root-servers.nil. +dom4577. NS a.root-servers.nil. +dom4578. NS a.root-servers.nil. +dom4579. NS a.root-servers.nil. +dom4580. NS a.root-servers.nil. +dom4581. NS a.root-servers.nil. +dom4582. NS a.root-servers.nil. +dom4583. NS a.root-servers.nil. +dom4584. NS a.root-servers.nil. +dom4585. NS a.root-servers.nil. +dom4586. NS a.root-servers.nil. +dom4587. NS a.root-servers.nil. +dom4588. NS a.root-servers.nil. +dom4589. NS a.root-servers.nil. +dom4590. NS a.root-servers.nil. +dom4591. NS a.root-servers.nil. +dom4592. NS a.root-servers.nil. +dom4593. NS a.root-servers.nil. +dom4594. NS a.root-servers.nil. +dom4595. NS a.root-servers.nil. +dom4596. NS a.root-servers.nil. +dom4597. NS a.root-servers.nil. +dom4598. NS a.root-servers.nil. +dom4599. NS a.root-servers.nil. +dom4600. NS a.root-servers.nil. +dom4601. NS a.root-servers.nil. +dom4602. NS a.root-servers.nil. +dom4603. NS a.root-servers.nil. +dom4604. NS a.root-servers.nil. +dom4605. NS a.root-servers.nil. +dom4606. NS a.root-servers.nil. +dom4607. NS a.root-servers.nil. +dom4608. NS a.root-servers.nil. +dom4609. NS a.root-servers.nil. +dom4610. NS a.root-servers.nil. +dom4611. NS a.root-servers.nil. +dom4612. NS a.root-servers.nil. +dom4613. NS a.root-servers.nil. +dom4614. NS a.root-servers.nil. +dom4615. NS a.root-servers.nil. +dom4616. NS a.root-servers.nil. +dom4617. NS a.root-servers.nil. +dom4618. NS a.root-servers.nil. +dom4619. NS a.root-servers.nil. +dom4620. NS a.root-servers.nil. +dom4621. NS a.root-servers.nil. +dom4622. NS a.root-servers.nil. +dom4623. NS a.root-servers.nil. +dom4624. NS a.root-servers.nil. +dom4625. NS a.root-servers.nil. +dom4626. NS a.root-servers.nil. +dom4627. NS a.root-servers.nil. +dom4628. NS a.root-servers.nil. +dom4629. NS a.root-servers.nil. +dom4630. NS a.root-servers.nil. +dom4631. NS a.root-servers.nil. +dom4632. NS a.root-servers.nil. +dom4633. NS a.root-servers.nil. +dom4634. NS a.root-servers.nil. +dom4635. NS a.root-servers.nil. +dom4636. NS a.root-servers.nil. +dom4637. NS a.root-servers.nil. +dom4638. NS a.root-servers.nil. +dom4639. NS a.root-servers.nil. +dom4640. NS a.root-servers.nil. +dom4641. NS a.root-servers.nil. +dom4642. NS a.root-servers.nil. +dom4643. NS a.root-servers.nil. +dom4644. NS a.root-servers.nil. +dom4645. NS a.root-servers.nil. +dom4646. NS a.root-servers.nil. +dom4647. NS a.root-servers.nil. +dom4648. NS a.root-servers.nil. +dom4649. NS a.root-servers.nil. +dom4650. NS a.root-servers.nil. +dom4651. NS a.root-servers.nil. +dom4652. NS a.root-servers.nil. +dom4653. NS a.root-servers.nil. +dom4654. NS a.root-servers.nil. +dom4655. NS a.root-servers.nil. +dom4656. NS a.root-servers.nil. +dom4657. NS a.root-servers.nil. +dom4658. NS a.root-servers.nil. +dom4659. NS a.root-servers.nil. +dom4660. NS a.root-servers.nil. +dom4661. NS a.root-servers.nil. +dom4662. NS a.root-servers.nil. +dom4663. NS a.root-servers.nil. +dom4664. NS a.root-servers.nil. +dom4665. NS a.root-servers.nil. +dom4666. NS a.root-servers.nil. +dom4667. NS a.root-servers.nil. +dom4668. NS a.root-servers.nil. +dom4669. NS a.root-servers.nil. +dom4670. NS a.root-servers.nil. +dom4671. NS a.root-servers.nil. +dom4672. NS a.root-servers.nil. +dom4673. NS a.root-servers.nil. +dom4674. NS a.root-servers.nil. +dom4675. NS a.root-servers.nil. +dom4676. NS a.root-servers.nil. +dom4677. NS a.root-servers.nil. +dom4678. NS a.root-servers.nil. +dom4679. NS a.root-servers.nil. +dom4680. NS a.root-servers.nil. +dom4681. NS a.root-servers.nil. +dom4682. NS a.root-servers.nil. +dom4683. NS a.root-servers.nil. +dom4684. NS a.root-servers.nil. +dom4685. NS a.root-servers.nil. +dom4686. NS a.root-servers.nil. +dom4687. NS a.root-servers.nil. +dom4688. NS a.root-servers.nil. +dom4689. NS a.root-servers.nil. +dom4690. NS a.root-servers.nil. +dom4691. NS a.root-servers.nil. +dom4692. NS a.root-servers.nil. +dom4693. NS a.root-servers.nil. +dom4694. NS a.root-servers.nil. +dom4695. NS a.root-servers.nil. +dom4696. NS a.root-servers.nil. +dom4697. NS a.root-servers.nil. +dom4698. NS a.root-servers.nil. +dom4699. NS a.root-servers.nil. +dom4700. NS a.root-servers.nil. +dom4701. NS a.root-servers.nil. +dom4702. NS a.root-servers.nil. +dom4703. NS a.root-servers.nil. +dom4704. NS a.root-servers.nil. +dom4705. NS a.root-servers.nil. +dom4706. NS a.root-servers.nil. +dom4707. NS a.root-servers.nil. +dom4708. NS a.root-servers.nil. +dom4709. NS a.root-servers.nil. +dom4710. NS a.root-servers.nil. +dom4711. NS a.root-servers.nil. +dom4712. NS a.root-servers.nil. +dom4713. NS a.root-servers.nil. +dom4714. NS a.root-servers.nil. +dom4715. NS a.root-servers.nil. +dom4716. NS a.root-servers.nil. +dom4717. NS a.root-servers.nil. +dom4718. NS a.root-servers.nil. +dom4719. NS a.root-servers.nil. +dom4720. NS a.root-servers.nil. +dom4721. NS a.root-servers.nil. +dom4722. NS a.root-servers.nil. +dom4723. NS a.root-servers.nil. +dom4724. NS a.root-servers.nil. +dom4725. NS a.root-servers.nil. +dom4726. NS a.root-servers.nil. +dom4727. NS a.root-servers.nil. +dom4728. NS a.root-servers.nil. +dom4729. NS a.root-servers.nil. +dom4730. NS a.root-servers.nil. +dom4731. NS a.root-servers.nil. +dom4732. NS a.root-servers.nil. +dom4733. NS a.root-servers.nil. +dom4734. NS a.root-servers.nil. +dom4735. NS a.root-servers.nil. +dom4736. NS a.root-servers.nil. +dom4737. NS a.root-servers.nil. +dom4738. NS a.root-servers.nil. +dom4739. NS a.root-servers.nil. +dom4740. NS a.root-servers.nil. +dom4741. NS a.root-servers.nil. +dom4742. NS a.root-servers.nil. +dom4743. NS a.root-servers.nil. +dom4744. NS a.root-servers.nil. +dom4745. NS a.root-servers.nil. +dom4746. NS a.root-servers.nil. +dom4747. NS a.root-servers.nil. +dom4748. NS a.root-servers.nil. +dom4749. NS a.root-servers.nil. +dom4750. NS a.root-servers.nil. +dom4751. NS a.root-servers.nil. +dom4752. NS a.root-servers.nil. +dom4753. NS a.root-servers.nil. +dom4754. NS a.root-servers.nil. +dom4755. NS a.root-servers.nil. +dom4756. NS a.root-servers.nil. +dom4757. NS a.root-servers.nil. +dom4758. NS a.root-servers.nil. +dom4759. NS a.root-servers.nil. +dom4760. NS a.root-servers.nil. +dom4761. NS a.root-servers.nil. +dom4762. NS a.root-servers.nil. +dom4763. NS a.root-servers.nil. +dom4764. NS a.root-servers.nil. +dom4765. NS a.root-servers.nil. +dom4766. NS a.root-servers.nil. +dom4767. NS a.root-servers.nil. +dom4768. NS a.root-servers.nil. +dom4769. NS a.root-servers.nil. +dom4770. NS a.root-servers.nil. +dom4771. NS a.root-servers.nil. +dom4772. NS a.root-servers.nil. +dom4773. NS a.root-servers.nil. +dom4774. NS a.root-servers.nil. +dom4775. NS a.root-servers.nil. +dom4776. NS a.root-servers.nil. +dom4777. NS a.root-servers.nil. +dom4778. NS a.root-servers.nil. +dom4779. NS a.root-servers.nil. +dom4780. NS a.root-servers.nil. +dom4781. NS a.root-servers.nil. +dom4782. NS a.root-servers.nil. +dom4783. NS a.root-servers.nil. +dom4784. NS a.root-servers.nil. +dom4785. NS a.root-servers.nil. +dom4786. NS a.root-servers.nil. +dom4787. NS a.root-servers.nil. +dom4788. NS a.root-servers.nil. +dom4789. NS a.root-servers.nil. +dom4790. NS a.root-servers.nil. +dom4791. NS a.root-servers.nil. +dom4792. NS a.root-servers.nil. +dom4793. NS a.root-servers.nil. +dom4794. NS a.root-servers.nil. +dom4795. NS a.root-servers.nil. +dom4796. NS a.root-servers.nil. +dom4797. NS a.root-servers.nil. +dom4798. NS a.root-servers.nil. +dom4799. NS a.root-servers.nil. +dom4800. NS a.root-servers.nil. +dom4801. NS a.root-servers.nil. +dom4802. NS a.root-servers.nil. +dom4803. NS a.root-servers.nil. +dom4804. NS a.root-servers.nil. +dom4805. NS a.root-servers.nil. +dom4806. NS a.root-servers.nil. +dom4807. NS a.root-servers.nil. +dom4808. NS a.root-servers.nil. +dom4809. NS a.root-servers.nil. +dom4810. NS a.root-servers.nil. +dom4811. NS a.root-servers.nil. +dom4812. NS a.root-servers.nil. +dom4813. NS a.root-servers.nil. +dom4814. NS a.root-servers.nil. +dom4815. NS a.root-servers.nil. +dom4816. NS a.root-servers.nil. +dom4817. NS a.root-servers.nil. +dom4818. NS a.root-servers.nil. +dom4819. NS a.root-servers.nil. +dom4820. NS a.root-servers.nil. +dom4821. NS a.root-servers.nil. +dom4822. NS a.root-servers.nil. +dom4823. NS a.root-servers.nil. +dom4824. NS a.root-servers.nil. +dom4825. NS a.root-servers.nil. +dom4826. NS a.root-servers.nil. +dom4827. NS a.root-servers.nil. +dom4828. NS a.root-servers.nil. +dom4829. NS a.root-servers.nil. +dom4830. NS a.root-servers.nil. +dom4831. NS a.root-servers.nil. +dom4832. NS a.root-servers.nil. +dom4833. NS a.root-servers.nil. +dom4834. NS a.root-servers.nil. +dom4835. NS a.root-servers.nil. +dom4836. NS a.root-servers.nil. +dom4837. NS a.root-servers.nil. +dom4838. NS a.root-servers.nil. +dom4839. NS a.root-servers.nil. +dom4840. NS a.root-servers.nil. +dom4841. NS a.root-servers.nil. +dom4842. NS a.root-servers.nil. +dom4843. NS a.root-servers.nil. +dom4844. NS a.root-servers.nil. +dom4845. NS a.root-servers.nil. +dom4846. NS a.root-servers.nil. +dom4847. NS a.root-servers.nil. +dom4848. NS a.root-servers.nil. +dom4849. NS a.root-servers.nil. +dom4850. NS a.root-servers.nil. +dom4851. NS a.root-servers.nil. +dom4852. NS a.root-servers.nil. +dom4853. NS a.root-servers.nil. +dom4854. NS a.root-servers.nil. +dom4855. NS a.root-servers.nil. +dom4856. NS a.root-servers.nil. +dom4857. NS a.root-servers.nil. +dom4858. NS a.root-servers.nil. +dom4859. NS a.root-servers.nil. +dom4860. NS a.root-servers.nil. +dom4861. NS a.root-servers.nil. +dom4862. NS a.root-servers.nil. +dom4863. NS a.root-servers.nil. +dom4864. NS a.root-servers.nil. +dom4865. NS a.root-servers.nil. +dom4866. NS a.root-servers.nil. +dom4867. NS a.root-servers.nil. +dom4868. NS a.root-servers.nil. +dom4869. NS a.root-servers.nil. +dom4870. NS a.root-servers.nil. +dom4871. NS a.root-servers.nil. +dom4872. NS a.root-servers.nil. +dom4873. NS a.root-servers.nil. +dom4874. NS a.root-servers.nil. +dom4875. NS a.root-servers.nil. +dom4876. NS a.root-servers.nil. +dom4877. NS a.root-servers.nil. +dom4878. NS a.root-servers.nil. +dom4879. NS a.root-servers.nil. +dom4880. NS a.root-servers.nil. +dom4881. NS a.root-servers.nil. +dom4882. NS a.root-servers.nil. +dom4883. NS a.root-servers.nil. +dom4884. NS a.root-servers.nil. +dom4885. NS a.root-servers.nil. +dom4886. NS a.root-servers.nil. +dom4887. NS a.root-servers.nil. +dom4888. NS a.root-servers.nil. +dom4889. NS a.root-servers.nil. +dom4890. NS a.root-servers.nil. +dom4891. NS a.root-servers.nil. +dom4892. NS a.root-servers.nil. +dom4893. NS a.root-servers.nil. +dom4894. NS a.root-servers.nil. +dom4895. NS a.root-servers.nil. +dom4896. NS a.root-servers.nil. +dom4897. NS a.root-servers.nil. +dom4898. NS a.root-servers.nil. +dom4899. NS a.root-servers.nil. +dom4900. NS a.root-servers.nil. +dom4901. NS a.root-servers.nil. +dom4902. NS a.root-servers.nil. +dom4903. NS a.root-servers.nil. +dom4904. NS a.root-servers.nil. +dom4905. NS a.root-servers.nil. +dom4906. NS a.root-servers.nil. +dom4907. NS a.root-servers.nil. +dom4908. NS a.root-servers.nil. +dom4909. NS a.root-servers.nil. +dom4910. NS a.root-servers.nil. +dom4911. NS a.root-servers.nil. +dom4912. NS a.root-servers.nil. +dom4913. NS a.root-servers.nil. +dom4914. NS a.root-servers.nil. +dom4915. NS a.root-servers.nil. +dom4916. NS a.root-servers.nil. +dom4917. NS a.root-servers.nil. +dom4918. NS a.root-servers.nil. +dom4919. NS a.root-servers.nil. +dom4920. NS a.root-servers.nil. +dom4921. NS a.root-servers.nil. +dom4922. NS a.root-servers.nil. +dom4923. NS a.root-servers.nil. +dom4924. NS a.root-servers.nil. +dom4925. NS a.root-servers.nil. +dom4926. NS a.root-servers.nil. +dom4927. NS a.root-servers.nil. +dom4928. NS a.root-servers.nil. +dom4929. NS a.root-servers.nil. +dom4930. NS a.root-servers.nil. +dom4931. NS a.root-servers.nil. +dom4932. NS a.root-servers.nil. +dom4933. NS a.root-servers.nil. +dom4934. NS a.root-servers.nil. +dom4935. NS a.root-servers.nil. +dom4936. NS a.root-servers.nil. +dom4937. NS a.root-servers.nil. +dom4938. NS a.root-servers.nil. +dom4939. NS a.root-servers.nil. +dom4940. NS a.root-servers.nil. +dom4941. NS a.root-servers.nil. +dom4942. NS a.root-servers.nil. +dom4943. NS a.root-servers.nil. +dom4944. NS a.root-servers.nil. +dom4945. NS a.root-servers.nil. +dom4946. NS a.root-servers.nil. +dom4947. NS a.root-servers.nil. +dom4948. NS a.root-servers.nil. +dom4949. NS a.root-servers.nil. +dom4950. NS a.root-servers.nil. +dom4951. NS a.root-servers.nil. +dom4952. NS a.root-servers.nil. +dom4953. NS a.root-servers.nil. +dom4954. NS a.root-servers.nil. +dom4955. NS a.root-servers.nil. +dom4956. NS a.root-servers.nil. +dom4957. NS a.root-servers.nil. +dom4958. NS a.root-servers.nil. +dom4959. NS a.root-servers.nil. +dom4960. NS a.root-servers.nil. +dom4961. NS a.root-servers.nil. +dom4962. NS a.root-servers.nil. +dom4963. NS a.root-servers.nil. +dom4964. NS a.root-servers.nil. +dom4965. NS a.root-servers.nil. +dom4966. NS a.root-servers.nil. +dom4967. NS a.root-servers.nil. +dom4968. NS a.root-servers.nil. +dom4969. NS a.root-servers.nil. +dom4970. NS a.root-servers.nil. +dom4971. NS a.root-servers.nil. +dom4972. NS a.root-servers.nil. +dom4973. NS a.root-servers.nil. +dom4974. NS a.root-servers.nil. +dom4975. NS a.root-servers.nil. +dom4976. NS a.root-servers.nil. +dom4977. NS a.root-servers.nil. +dom4978. NS a.root-servers.nil. +dom4979. NS a.root-servers.nil. +dom4980. NS a.root-servers.nil. +dom4981. NS a.root-servers.nil. +dom4982. NS a.root-servers.nil. +dom4983. NS a.root-servers.nil. +dom4984. NS a.root-servers.nil. +dom4985. NS a.root-servers.nil. +dom4986. NS a.root-servers.nil. +dom4987. NS a.root-servers.nil. +dom4988. NS a.root-servers.nil. +dom4989. NS a.root-servers.nil. +dom4990. NS a.root-servers.nil. +dom4991. NS a.root-servers.nil. +dom4992. NS a.root-servers.nil. +dom4993. NS a.root-servers.nil. +dom4994. NS a.root-servers.nil. +dom4995. NS a.root-servers.nil. +dom4996. NS a.root-servers.nil. +dom4997. NS a.root-servers.nil. +dom4998. NS a.root-servers.nil. +dom4999. NS a.root-servers.nil. +dom5000. NS a.root-servers.nil. +dom5001. NS a.root-servers.nil. +dom5002. NS a.root-servers.nil. +dom5003. NS a.root-servers.nil. +dom5004. NS a.root-servers.nil. +dom5005. NS a.root-servers.nil. +dom5006. NS a.root-servers.nil. +dom5007. NS a.root-servers.nil. +dom5008. NS a.root-servers.nil. +dom5009. NS a.root-servers.nil. +dom5010. NS a.root-servers.nil. +dom5011. NS a.root-servers.nil. +dom5012. NS a.root-servers.nil. +dom5013. NS a.root-servers.nil. +dom5014. NS a.root-servers.nil. +dom5015. NS a.root-servers.nil. +dom5016. NS a.root-servers.nil. +dom5017. NS a.root-servers.nil. +dom5018. NS a.root-servers.nil. +dom5019. NS a.root-servers.nil. +dom5020. NS a.root-servers.nil. +dom5021. NS a.root-servers.nil. +dom5022. NS a.root-servers.nil. +dom5023. NS a.root-servers.nil. +dom5024. NS a.root-servers.nil. +dom5025. NS a.root-servers.nil. +dom5026. NS a.root-servers.nil. +dom5027. NS a.root-servers.nil. +dom5028. NS a.root-servers.nil. +dom5029. NS a.root-servers.nil. +dom5030. NS a.root-servers.nil. +dom5031. NS a.root-servers.nil. +dom5032. NS a.root-servers.nil. +dom5033. NS a.root-servers.nil. +dom5034. NS a.root-servers.nil. +dom5035. NS a.root-servers.nil. +dom5036. NS a.root-servers.nil. +dom5037. NS a.root-servers.nil. +dom5038. NS a.root-servers.nil. +dom5039. NS a.root-servers.nil. +dom5040. NS a.root-servers.nil. +dom5041. NS a.root-servers.nil. +dom5042. NS a.root-servers.nil. +dom5043. NS a.root-servers.nil. +dom5044. NS a.root-servers.nil. +dom5045. NS a.root-servers.nil. +dom5046. NS a.root-servers.nil. +dom5047. NS a.root-servers.nil. +dom5048. NS a.root-servers.nil. +dom5049. NS a.root-servers.nil. +dom5050. NS a.root-servers.nil. +dom5051. NS a.root-servers.nil. +dom5052. NS a.root-servers.nil. +dom5053. NS a.root-servers.nil. +dom5054. NS a.root-servers.nil. +dom5055. NS a.root-servers.nil. +dom5056. NS a.root-servers.nil. +dom5057. NS a.root-servers.nil. +dom5058. NS a.root-servers.nil. +dom5059. NS a.root-servers.nil. +dom5060. NS a.root-servers.nil. +dom5061. NS a.root-servers.nil. +dom5062. NS a.root-servers.nil. +dom5063. NS a.root-servers.nil. +dom5064. NS a.root-servers.nil. +dom5065. NS a.root-servers.nil. +dom5066. NS a.root-servers.nil. +dom5067. NS a.root-servers.nil. +dom5068. NS a.root-servers.nil. +dom5069. NS a.root-servers.nil. +dom5070. NS a.root-servers.nil. +dom5071. NS a.root-servers.nil. +dom5072. NS a.root-servers.nil. +dom5073. NS a.root-servers.nil. +dom5074. NS a.root-servers.nil. +dom5075. NS a.root-servers.nil. +dom5076. NS a.root-servers.nil. +dom5077. NS a.root-servers.nil. +dom5078. NS a.root-servers.nil. +dom5079. NS a.root-servers.nil. +dom5080. NS a.root-servers.nil. +dom5081. NS a.root-servers.nil. +dom5082. NS a.root-servers.nil. +dom5083. NS a.root-servers.nil. +dom5084. NS a.root-servers.nil. +dom5085. NS a.root-servers.nil. +dom5086. NS a.root-servers.nil. +dom5087. NS a.root-servers.nil. +dom5088. NS a.root-servers.nil. +dom5089. NS a.root-servers.nil. +dom5090. NS a.root-servers.nil. +dom5091. NS a.root-servers.nil. +dom5092. NS a.root-servers.nil. +dom5093. NS a.root-servers.nil. +dom5094. NS a.root-servers.nil. +dom5095. NS a.root-servers.nil. +dom5096. NS a.root-servers.nil. +dom5097. NS a.root-servers.nil. +dom5098. NS a.root-servers.nil. +dom5099. NS a.root-servers.nil. +dom5100. NS a.root-servers.nil. +dom5101. NS a.root-servers.nil. +dom5102. NS a.root-servers.nil. +dom5103. NS a.root-servers.nil. +dom5104. NS a.root-servers.nil. +dom5105. NS a.root-servers.nil. +dom5106. NS a.root-servers.nil. +dom5107. NS a.root-servers.nil. +dom5108. NS a.root-servers.nil. +dom5109. NS a.root-servers.nil. +dom5110. NS a.root-servers.nil. +dom5111. NS a.root-servers.nil. +dom5112. NS a.root-servers.nil. +dom5113. NS a.root-servers.nil. +dom5114. NS a.root-servers.nil. +dom5115. NS a.root-servers.nil. +dom5116. NS a.root-servers.nil. +dom5117. NS a.root-servers.nil. +dom5118. NS a.root-servers.nil. +dom5119. NS a.root-servers.nil. +dom5120. NS a.root-servers.nil. +dom5121. NS a.root-servers.nil. +dom5122. NS a.root-servers.nil. +dom5123. NS a.root-servers.nil. +dom5124. NS a.root-servers.nil. +dom5125. NS a.root-servers.nil. +dom5126. NS a.root-servers.nil. +dom5127. NS a.root-servers.nil. +dom5128. NS a.root-servers.nil. +dom5129. NS a.root-servers.nil. +dom5130. NS a.root-servers.nil. +dom5131. NS a.root-servers.nil. +dom5132. NS a.root-servers.nil. +dom5133. NS a.root-servers.nil. +dom5134. NS a.root-servers.nil. +dom5135. NS a.root-servers.nil. +dom5136. NS a.root-servers.nil. +dom5137. NS a.root-servers.nil. +dom5138. NS a.root-servers.nil. +dom5139. NS a.root-servers.nil. +dom5140. NS a.root-servers.nil. +dom5141. NS a.root-servers.nil. +dom5142. NS a.root-servers.nil. +dom5143. NS a.root-servers.nil. +dom5144. NS a.root-servers.nil. +dom5145. NS a.root-servers.nil. +dom5146. NS a.root-servers.nil. +dom5147. NS a.root-servers.nil. +dom5148. NS a.root-servers.nil. +dom5149. NS a.root-servers.nil. +dom5150. NS a.root-servers.nil. +dom5151. NS a.root-servers.nil. +dom5152. NS a.root-servers.nil. +dom5153. NS a.root-servers.nil. +dom5154. NS a.root-servers.nil. +dom5155. NS a.root-servers.nil. +dom5156. NS a.root-servers.nil. +dom5157. NS a.root-servers.nil. +dom5158. NS a.root-servers.nil. +dom5159. NS a.root-servers.nil. +dom5160. NS a.root-servers.nil. +dom5161. NS a.root-servers.nil. +dom5162. NS a.root-servers.nil. +dom5163. NS a.root-servers.nil. +dom5164. NS a.root-servers.nil. +dom5165. NS a.root-servers.nil. +dom5166. NS a.root-servers.nil. +dom5167. NS a.root-servers.nil. +dom5168. NS a.root-servers.nil. +dom5169. NS a.root-servers.nil. +dom5170. NS a.root-servers.nil. +dom5171. NS a.root-servers.nil. +dom5172. NS a.root-servers.nil. +dom5173. NS a.root-servers.nil. +dom5174. NS a.root-servers.nil. +dom5175. NS a.root-servers.nil. +dom5176. NS a.root-servers.nil. +dom5177. NS a.root-servers.nil. +dom5178. NS a.root-servers.nil. +dom5179. NS a.root-servers.nil. +dom5180. NS a.root-servers.nil. +dom5181. NS a.root-servers.nil. +dom5182. NS a.root-servers.nil. +dom5183. NS a.root-servers.nil. +dom5184. NS a.root-servers.nil. +dom5185. NS a.root-servers.nil. +dom5186. NS a.root-servers.nil. +dom5187. NS a.root-servers.nil. +dom5188. NS a.root-servers.nil. +dom5189. NS a.root-servers.nil. +dom5190. NS a.root-servers.nil. +dom5191. NS a.root-servers.nil. +dom5192. NS a.root-servers.nil. +dom5193. NS a.root-servers.nil. +dom5194. NS a.root-servers.nil. +dom5195. NS a.root-servers.nil. +dom5196. NS a.root-servers.nil. +dom5197. NS a.root-servers.nil. +dom5198. NS a.root-servers.nil. +dom5199. NS a.root-servers.nil. +dom5200. NS a.root-servers.nil. +dom5201. NS a.root-servers.nil. +dom5202. NS a.root-servers.nil. +dom5203. NS a.root-servers.nil. +dom5204. NS a.root-servers.nil. +dom5205. NS a.root-servers.nil. +dom5206. NS a.root-servers.nil. +dom5207. NS a.root-servers.nil. +dom5208. NS a.root-servers.nil. +dom5209. NS a.root-servers.nil. +dom5210. NS a.root-servers.nil. +dom5211. NS a.root-servers.nil. +dom5212. NS a.root-servers.nil. +dom5213. NS a.root-servers.nil. +dom5214. NS a.root-servers.nil. +dom5215. NS a.root-servers.nil. +dom5216. NS a.root-servers.nil. +dom5217. NS a.root-servers.nil. +dom5218. NS a.root-servers.nil. +dom5219. NS a.root-servers.nil. +dom5220. NS a.root-servers.nil. +dom5221. NS a.root-servers.nil. +dom5222. NS a.root-servers.nil. +dom5223. NS a.root-servers.nil. +dom5224. NS a.root-servers.nil. +dom5225. NS a.root-servers.nil. +dom5226. NS a.root-servers.nil. +dom5227. NS a.root-servers.nil. +dom5228. NS a.root-servers.nil. +dom5229. NS a.root-servers.nil. +dom5230. NS a.root-servers.nil. +dom5231. NS a.root-servers.nil. +dom5232. NS a.root-servers.nil. +dom5233. NS a.root-servers.nil. +dom5234. NS a.root-servers.nil. +dom5235. NS a.root-servers.nil. +dom5236. NS a.root-servers.nil. +dom5237. NS a.root-servers.nil. +dom5238. NS a.root-servers.nil. +dom5239. NS a.root-servers.nil. +dom5240. NS a.root-servers.nil. +dom5241. NS a.root-servers.nil. +dom5242. NS a.root-servers.nil. +dom5243. NS a.root-servers.nil. +dom5244. NS a.root-servers.nil. +dom5245. NS a.root-servers.nil. +dom5246. NS a.root-servers.nil. +dom5247. NS a.root-servers.nil. +dom5248. NS a.root-servers.nil. +dom5249. NS a.root-servers.nil. +dom5250. NS a.root-servers.nil. +dom5251. NS a.root-servers.nil. +dom5252. NS a.root-servers.nil. +dom5253. NS a.root-servers.nil. +dom5254. NS a.root-servers.nil. +dom5255. NS a.root-servers.nil. +dom5256. NS a.root-servers.nil. +dom5257. NS a.root-servers.nil. +dom5258. NS a.root-servers.nil. +dom5259. NS a.root-servers.nil. +dom5260. NS a.root-servers.nil. +dom5261. NS a.root-servers.nil. +dom5262. NS a.root-servers.nil. +dom5263. NS a.root-servers.nil. +dom5264. NS a.root-servers.nil. +dom5265. NS a.root-servers.nil. +dom5266. NS a.root-servers.nil. +dom5267. NS a.root-servers.nil. +dom5268. NS a.root-servers.nil. +dom5269. NS a.root-servers.nil. +dom5270. NS a.root-servers.nil. +dom5271. NS a.root-servers.nil. +dom5272. NS a.root-servers.nil. +dom5273. NS a.root-servers.nil. +dom5274. NS a.root-servers.nil. +dom5275. NS a.root-servers.nil. +dom5276. NS a.root-servers.nil. +dom5277. NS a.root-servers.nil. +dom5278. NS a.root-servers.nil. +dom5279. NS a.root-servers.nil. +dom5280. NS a.root-servers.nil. +dom5281. NS a.root-servers.nil. +dom5282. NS a.root-servers.nil. +dom5283. NS a.root-servers.nil. +dom5284. NS a.root-servers.nil. +dom5285. NS a.root-servers.nil. +dom5286. NS a.root-servers.nil. +dom5287. NS a.root-servers.nil. +dom5288. NS a.root-servers.nil. +dom5289. NS a.root-servers.nil. +dom5290. NS a.root-servers.nil. +dom5291. NS a.root-servers.nil. +dom5292. NS a.root-servers.nil. +dom5293. NS a.root-servers.nil. +dom5294. NS a.root-servers.nil. +dom5295. NS a.root-servers.nil. +dom5296. NS a.root-servers.nil. +dom5297. NS a.root-servers.nil. +dom5298. NS a.root-servers.nil. +dom5299. NS a.root-servers.nil. +dom5300. NS a.root-servers.nil. +dom5301. NS a.root-servers.nil. +dom5302. NS a.root-servers.nil. +dom5303. NS a.root-servers.nil. +dom5304. NS a.root-servers.nil. +dom5305. NS a.root-servers.nil. +dom5306. NS a.root-servers.nil. +dom5307. NS a.root-servers.nil. +dom5308. NS a.root-servers.nil. +dom5309. NS a.root-servers.nil. +dom5310. NS a.root-servers.nil. +dom5311. NS a.root-servers.nil. +dom5312. NS a.root-servers.nil. +dom5313. NS a.root-servers.nil. +dom5314. NS a.root-servers.nil. +dom5315. NS a.root-servers.nil. +dom5316. NS a.root-servers.nil. +dom5317. NS a.root-servers.nil. +dom5318. NS a.root-servers.nil. +dom5319. NS a.root-servers.nil. +dom5320. NS a.root-servers.nil. +dom5321. NS a.root-servers.nil. +dom5322. NS a.root-servers.nil. +dom5323. NS a.root-servers.nil. +dom5324. NS a.root-servers.nil. +dom5325. NS a.root-servers.nil. +dom5326. NS a.root-servers.nil. +dom5327. NS a.root-servers.nil. +dom5328. NS a.root-servers.nil. +dom5329. NS a.root-servers.nil. +dom5330. NS a.root-servers.nil. +dom5331. NS a.root-servers.nil. +dom5332. NS a.root-servers.nil. +dom5333. NS a.root-servers.nil. +dom5334. NS a.root-servers.nil. +dom5335. NS a.root-servers.nil. +dom5336. NS a.root-servers.nil. +dom5337. NS a.root-servers.nil. +dom5338. NS a.root-servers.nil. +dom5339. NS a.root-servers.nil. +dom5340. NS a.root-servers.nil. +dom5341. NS a.root-servers.nil. +dom5342. NS a.root-servers.nil. +dom5343. NS a.root-servers.nil. +dom5344. NS a.root-servers.nil. +dom5345. NS a.root-servers.nil. +dom5346. NS a.root-servers.nil. +dom5347. NS a.root-servers.nil. +dom5348. NS a.root-servers.nil. +dom5349. NS a.root-servers.nil. +dom5350. NS a.root-servers.nil. +dom5351. NS a.root-servers.nil. +dom5352. NS a.root-servers.nil. +dom5353. NS a.root-servers.nil. +dom5354. NS a.root-servers.nil. +dom5355. NS a.root-servers.nil. +dom5356. NS a.root-servers.nil. +dom5357. NS a.root-servers.nil. +dom5358. NS a.root-servers.nil. +dom5359. NS a.root-servers.nil. +dom5360. NS a.root-servers.nil. +dom5361. NS a.root-servers.nil. +dom5362. NS a.root-servers.nil. +dom5363. NS a.root-servers.nil. +dom5364. NS a.root-servers.nil. +dom5365. NS a.root-servers.nil. +dom5366. NS a.root-servers.nil. +dom5367. NS a.root-servers.nil. +dom5368. NS a.root-servers.nil. +dom5369. NS a.root-servers.nil. +dom5370. NS a.root-servers.nil. +dom5371. NS a.root-servers.nil. +dom5372. NS a.root-servers.nil. +dom5373. NS a.root-servers.nil. +dom5374. NS a.root-servers.nil. +dom5375. NS a.root-servers.nil. +dom5376. NS a.root-servers.nil. +dom5377. NS a.root-servers.nil. +dom5378. NS a.root-servers.nil. +dom5379. NS a.root-servers.nil. +dom5380. NS a.root-servers.nil. +dom5381. NS a.root-servers.nil. +dom5382. NS a.root-servers.nil. +dom5383. NS a.root-servers.nil. +dom5384. NS a.root-servers.nil. +dom5385. NS a.root-servers.nil. +dom5386. NS a.root-servers.nil. +dom5387. NS a.root-servers.nil. +dom5388. NS a.root-servers.nil. +dom5389. NS a.root-servers.nil. +dom5390. NS a.root-servers.nil. +dom5391. NS a.root-servers.nil. +dom5392. NS a.root-servers.nil. +dom5393. NS a.root-servers.nil. +dom5394. NS a.root-servers.nil. +dom5395. NS a.root-servers.nil. +dom5396. NS a.root-servers.nil. +dom5397. NS a.root-servers.nil. +dom5398. NS a.root-servers.nil. +dom5399. NS a.root-servers.nil. +dom5400. NS a.root-servers.nil. +dom5401. NS a.root-servers.nil. +dom5402. NS a.root-servers.nil. +dom5403. NS a.root-servers.nil. +dom5404. NS a.root-servers.nil. +dom5405. NS a.root-servers.nil. +dom5406. NS a.root-servers.nil. +dom5407. NS a.root-servers.nil. +dom5408. NS a.root-servers.nil. +dom5409. NS a.root-servers.nil. +dom5410. NS a.root-servers.nil. +dom5411. NS a.root-servers.nil. +dom5412. NS a.root-servers.nil. +dom5413. NS a.root-servers.nil. +dom5414. NS a.root-servers.nil. +dom5415. NS a.root-servers.nil. +dom5416. NS a.root-servers.nil. +dom5417. NS a.root-servers.nil. +dom5418. NS a.root-servers.nil. +dom5419. NS a.root-servers.nil. +dom5420. NS a.root-servers.nil. +dom5421. NS a.root-servers.nil. +dom5422. NS a.root-servers.nil. +dom5423. NS a.root-servers.nil. +dom5424. NS a.root-servers.nil. +dom5425. NS a.root-servers.nil. +dom5426. NS a.root-servers.nil. +dom5427. NS a.root-servers.nil. +dom5428. NS a.root-servers.nil. +dom5429. NS a.root-servers.nil. +dom5430. NS a.root-servers.nil. +dom5431. NS a.root-servers.nil. +dom5432. NS a.root-servers.nil. +dom5433. NS a.root-servers.nil. +dom5434. NS a.root-servers.nil. +dom5435. NS a.root-servers.nil. +dom5436. NS a.root-servers.nil. +dom5437. NS a.root-servers.nil. +dom5438. NS a.root-servers.nil. +dom5439. NS a.root-servers.nil. +dom5440. NS a.root-servers.nil. +dom5441. NS a.root-servers.nil. +dom5442. NS a.root-servers.nil. +dom5443. NS a.root-servers.nil. +dom5444. NS a.root-servers.nil. +dom5445. NS a.root-servers.nil. +dom5446. NS a.root-servers.nil. +dom5447. NS a.root-servers.nil. +dom5448. NS a.root-servers.nil. +dom5449. NS a.root-servers.nil. +dom5450. NS a.root-servers.nil. +dom5451. NS a.root-servers.nil. +dom5452. NS a.root-servers.nil. +dom5453. NS a.root-servers.nil. +dom5454. NS a.root-servers.nil. +dom5455. NS a.root-servers.nil. +dom5456. NS a.root-servers.nil. +dom5457. NS a.root-servers.nil. +dom5458. NS a.root-servers.nil. +dom5459. NS a.root-servers.nil. +dom5460. NS a.root-servers.nil. +dom5461. NS a.root-servers.nil. +dom5462. NS a.root-servers.nil. +dom5463. NS a.root-servers.nil. +dom5464. NS a.root-servers.nil. +dom5465. NS a.root-servers.nil. +dom5466. NS a.root-servers.nil. +dom5467. NS a.root-servers.nil. +dom5468. NS a.root-servers.nil. +dom5469. NS a.root-servers.nil. +dom5470. NS a.root-servers.nil. +dom5471. NS a.root-servers.nil. +dom5472. NS a.root-servers.nil. +dom5473. NS a.root-servers.nil. +dom5474. NS a.root-servers.nil. +dom5475. NS a.root-servers.nil. +dom5476. NS a.root-servers.nil. +dom5477. NS a.root-servers.nil. +dom5478. NS a.root-servers.nil. +dom5479. NS a.root-servers.nil. +dom5480. NS a.root-servers.nil. +dom5481. NS a.root-servers.nil. +dom5482. NS a.root-servers.nil. +dom5483. NS a.root-servers.nil. +dom5484. NS a.root-servers.nil. +dom5485. NS a.root-servers.nil. +dom5486. NS a.root-servers.nil. +dom5487. NS a.root-servers.nil. +dom5488. NS a.root-servers.nil. +dom5489. NS a.root-servers.nil. +dom5490. NS a.root-servers.nil. +dom5491. NS a.root-servers.nil. +dom5492. NS a.root-servers.nil. +dom5493. NS a.root-servers.nil. +dom5494. NS a.root-servers.nil. +dom5495. NS a.root-servers.nil. +dom5496. NS a.root-servers.nil. +dom5497. NS a.root-servers.nil. +dom5498. NS a.root-servers.nil. +dom5499. NS a.root-servers.nil. +dom5500. NS a.root-servers.nil. +dom5501. NS a.root-servers.nil. +dom5502. NS a.root-servers.nil. +dom5503. NS a.root-servers.nil. +dom5504. NS a.root-servers.nil. +dom5505. NS a.root-servers.nil. +dom5506. NS a.root-servers.nil. +dom5507. NS a.root-servers.nil. +dom5508. NS a.root-servers.nil. +dom5509. NS a.root-servers.nil. +dom5510. NS a.root-servers.nil. +dom5511. NS a.root-servers.nil. +dom5512. NS a.root-servers.nil. +dom5513. NS a.root-servers.nil. +dom5514. NS a.root-servers.nil. +dom5515. NS a.root-servers.nil. +dom5516. NS a.root-servers.nil. +dom5517. NS a.root-servers.nil. +dom5518. NS a.root-servers.nil. +dom5519. NS a.root-servers.nil. +dom5520. NS a.root-servers.nil. +dom5521. NS a.root-servers.nil. +dom5522. NS a.root-servers.nil. +dom5523. NS a.root-servers.nil. +dom5524. NS a.root-servers.nil. +dom5525. NS a.root-servers.nil. +dom5526. NS a.root-servers.nil. +dom5527. NS a.root-servers.nil. +dom5528. NS a.root-servers.nil. +dom5529. NS a.root-servers.nil. +dom5530. NS a.root-servers.nil. +dom5531. NS a.root-servers.nil. +dom5532. NS a.root-servers.nil. +dom5533. NS a.root-servers.nil. +dom5534. NS a.root-servers.nil. +dom5535. NS a.root-servers.nil. +dom5536. NS a.root-servers.nil. +dom5537. NS a.root-servers.nil. +dom5538. NS a.root-servers.nil. +dom5539. NS a.root-servers.nil. +dom5540. NS a.root-servers.nil. +dom5541. NS a.root-servers.nil. +dom5542. NS a.root-servers.nil. +dom5543. NS a.root-servers.nil. +dom5544. NS a.root-servers.nil. +dom5545. NS a.root-servers.nil. +dom5546. NS a.root-servers.nil. +dom5547. NS a.root-servers.nil. +dom5548. NS a.root-servers.nil. +dom5549. NS a.root-servers.nil. +dom5550. NS a.root-servers.nil. +dom5551. NS a.root-servers.nil. +dom5552. NS a.root-servers.nil. +dom5553. NS a.root-servers.nil. +dom5554. NS a.root-servers.nil. +dom5555. NS a.root-servers.nil. +dom5556. NS a.root-servers.nil. +dom5557. NS a.root-servers.nil. +dom5558. NS a.root-servers.nil. +dom5559. NS a.root-servers.nil. +dom5560. NS a.root-servers.nil. +dom5561. NS a.root-servers.nil. +dom5562. NS a.root-servers.nil. +dom5563. NS a.root-servers.nil. +dom5564. NS a.root-servers.nil. +dom5565. NS a.root-servers.nil. +dom5566. NS a.root-servers.nil. +dom5567. NS a.root-servers.nil. +dom5568. NS a.root-servers.nil. +dom5569. NS a.root-servers.nil. +dom5570. NS a.root-servers.nil. +dom5571. NS a.root-servers.nil. +dom5572. NS a.root-servers.nil. +dom5573. NS a.root-servers.nil. +dom5574. NS a.root-servers.nil. +dom5575. NS a.root-servers.nil. +dom5576. NS a.root-servers.nil. +dom5577. NS a.root-servers.nil. +dom5578. NS a.root-servers.nil. +dom5579. NS a.root-servers.nil. +dom5580. NS a.root-servers.nil. +dom5581. NS a.root-servers.nil. +dom5582. NS a.root-servers.nil. +dom5583. NS a.root-servers.nil. +dom5584. NS a.root-servers.nil. +dom5585. NS a.root-servers.nil. +dom5586. NS a.root-servers.nil. +dom5587. NS a.root-servers.nil. +dom5588. NS a.root-servers.nil. +dom5589. NS a.root-servers.nil. +dom5590. NS a.root-servers.nil. +dom5591. NS a.root-servers.nil. +dom5592. NS a.root-servers.nil. +dom5593. NS a.root-servers.nil. +dom5594. NS a.root-servers.nil. +dom5595. NS a.root-servers.nil. +dom5596. NS a.root-servers.nil. +dom5597. NS a.root-servers.nil. +dom5598. NS a.root-servers.nil. +dom5599. NS a.root-servers.nil. +dom5600. NS a.root-servers.nil. +dom5601. NS a.root-servers.nil. +dom5602. NS a.root-servers.nil. +dom5603. NS a.root-servers.nil. +dom5604. NS a.root-servers.nil. +dom5605. NS a.root-servers.nil. +dom5606. NS a.root-servers.nil. +dom5607. NS a.root-servers.nil. +dom5608. NS a.root-servers.nil. +dom5609. NS a.root-servers.nil. +dom5610. NS a.root-servers.nil. +dom5611. NS a.root-servers.nil. +dom5612. NS a.root-servers.nil. +dom5613. NS a.root-servers.nil. +dom5614. NS a.root-servers.nil. +dom5615. NS a.root-servers.nil. +dom5616. NS a.root-servers.nil. +dom5617. NS a.root-servers.nil. +dom5618. NS a.root-servers.nil. +dom5619. NS a.root-servers.nil. +dom5620. NS a.root-servers.nil. +dom5621. NS a.root-servers.nil. +dom5622. NS a.root-servers.nil. +dom5623. NS a.root-servers.nil. +dom5624. NS a.root-servers.nil. +dom5625. NS a.root-servers.nil. +dom5626. NS a.root-servers.nil. +dom5627. NS a.root-servers.nil. +dom5628. NS a.root-servers.nil. +dom5629. NS a.root-servers.nil. +dom5630. NS a.root-servers.nil. +dom5631. NS a.root-servers.nil. +dom5632. NS a.root-servers.nil. +dom5633. NS a.root-servers.nil. +dom5634. NS a.root-servers.nil. +dom5635. NS a.root-servers.nil. +dom5636. NS a.root-servers.nil. +dom5637. NS a.root-servers.nil. +dom5638. NS a.root-servers.nil. +dom5639. NS a.root-servers.nil. +dom5640. NS a.root-servers.nil. +dom5641. NS a.root-servers.nil. +dom5642. NS a.root-servers.nil. +dom5643. NS a.root-servers.nil. +dom5644. NS a.root-servers.nil. +dom5645. NS a.root-servers.nil. +dom5646. NS a.root-servers.nil. +dom5647. NS a.root-servers.nil. +dom5648. NS a.root-servers.nil. +dom5649. NS a.root-servers.nil. +dom5650. NS a.root-servers.nil. +dom5651. NS a.root-servers.nil. +dom5652. NS a.root-servers.nil. +dom5653. NS a.root-servers.nil. +dom5654. NS a.root-servers.nil. +dom5655. NS a.root-servers.nil. +dom5656. NS a.root-servers.nil. +dom5657. NS a.root-servers.nil. +dom5658. NS a.root-servers.nil. +dom5659. NS a.root-servers.nil. +dom5660. NS a.root-servers.nil. +dom5661. NS a.root-servers.nil. +dom5662. NS a.root-servers.nil. +dom5663. NS a.root-servers.nil. +dom5664. NS a.root-servers.nil. +dom5665. NS a.root-servers.nil. +dom5666. NS a.root-servers.nil. +dom5667. NS a.root-servers.nil. +dom5668. NS a.root-servers.nil. +dom5669. NS a.root-servers.nil. +dom5670. NS a.root-servers.nil. +dom5671. NS a.root-servers.nil. +dom5672. NS a.root-servers.nil. +dom5673. NS a.root-servers.nil. +dom5674. NS a.root-servers.nil. +dom5675. NS a.root-servers.nil. +dom5676. NS a.root-servers.nil. +dom5677. NS a.root-servers.nil. +dom5678. NS a.root-servers.nil. +dom5679. NS a.root-servers.nil. +dom5680. NS a.root-servers.nil. +dom5681. NS a.root-servers.nil. +dom5682. NS a.root-servers.nil. +dom5683. NS a.root-servers.nil. +dom5684. NS a.root-servers.nil. +dom5685. NS a.root-servers.nil. +dom5686. NS a.root-servers.nil. +dom5687. NS a.root-servers.nil. +dom5688. NS a.root-servers.nil. +dom5689. NS a.root-servers.nil. +dom5690. NS a.root-servers.nil. +dom5691. NS a.root-servers.nil. +dom5692. NS a.root-servers.nil. +dom5693. NS a.root-servers.nil. +dom5694. NS a.root-servers.nil. +dom5695. NS a.root-servers.nil. +dom5696. NS a.root-servers.nil. +dom5697. NS a.root-servers.nil. +dom5698. NS a.root-servers.nil. +dom5699. NS a.root-servers.nil. +dom5700. NS a.root-servers.nil. +dom5701. NS a.root-servers.nil. +dom5702. NS a.root-servers.nil. +dom5703. NS a.root-servers.nil. +dom5704. NS a.root-servers.nil. +dom5705. NS a.root-servers.nil. +dom5706. NS a.root-servers.nil. +dom5707. NS a.root-servers.nil. +dom5708. NS a.root-servers.nil. +dom5709. NS a.root-servers.nil. +dom5710. NS a.root-servers.nil. +dom5711. NS a.root-servers.nil. +dom5712. NS a.root-servers.nil. +dom5713. NS a.root-servers.nil. +dom5714. NS a.root-servers.nil. +dom5715. NS a.root-servers.nil. +dom5716. NS a.root-servers.nil. +dom5717. NS a.root-servers.nil. +dom5718. NS a.root-servers.nil. +dom5719. NS a.root-servers.nil. +dom5720. NS a.root-servers.nil. +dom5721. NS a.root-servers.nil. +dom5722. NS a.root-servers.nil. +dom5723. NS a.root-servers.nil. +dom5724. NS a.root-servers.nil. +dom5725. NS a.root-servers.nil. +dom5726. NS a.root-servers.nil. +dom5727. NS a.root-servers.nil. +dom5728. NS a.root-servers.nil. +dom5729. NS a.root-servers.nil. +dom5730. NS a.root-servers.nil. +dom5731. NS a.root-servers.nil. +dom5732. NS a.root-servers.nil. +dom5733. NS a.root-servers.nil. +dom5734. NS a.root-servers.nil. +dom5735. NS a.root-servers.nil. +dom5736. NS a.root-servers.nil. +dom5737. NS a.root-servers.nil. +dom5738. NS a.root-servers.nil. +dom5739. NS a.root-servers.nil. +dom5740. NS a.root-servers.nil. +dom5741. NS a.root-servers.nil. +dom5742. NS a.root-servers.nil. +dom5743. NS a.root-servers.nil. +dom5744. NS a.root-servers.nil. +dom5745. NS a.root-servers.nil. +dom5746. NS a.root-servers.nil. +dom5747. NS a.root-servers.nil. +dom5748. NS a.root-servers.nil. +dom5749. NS a.root-servers.nil. +dom5750. NS a.root-servers.nil. +dom5751. NS a.root-servers.nil. +dom5752. NS a.root-servers.nil. +dom5753. NS a.root-servers.nil. +dom5754. NS a.root-servers.nil. +dom5755. NS a.root-servers.nil. +dom5756. NS a.root-servers.nil. +dom5757. NS a.root-servers.nil. +dom5758. NS a.root-servers.nil. +dom5759. NS a.root-servers.nil. +dom5760. NS a.root-servers.nil. +dom5761. NS a.root-servers.nil. +dom5762. NS a.root-servers.nil. +dom5763. NS a.root-servers.nil. +dom5764. NS a.root-servers.nil. +dom5765. NS a.root-servers.nil. +dom5766. NS a.root-servers.nil. +dom5767. NS a.root-servers.nil. +dom5768. NS a.root-servers.nil. +dom5769. NS a.root-servers.nil. +dom5770. NS a.root-servers.nil. +dom5771. NS a.root-servers.nil. +dom5772. NS a.root-servers.nil. +dom5773. NS a.root-servers.nil. +dom5774. NS a.root-servers.nil. +dom5775. NS a.root-servers.nil. +dom5776. NS a.root-servers.nil. +dom5777. NS a.root-servers.nil. +dom5778. NS a.root-servers.nil. +dom5779. NS a.root-servers.nil. +dom5780. NS a.root-servers.nil. +dom5781. NS a.root-servers.nil. +dom5782. NS a.root-servers.nil. +dom5783. NS a.root-servers.nil. +dom5784. NS a.root-servers.nil. +dom5785. NS a.root-servers.nil. +dom5786. NS a.root-servers.nil. +dom5787. NS a.root-servers.nil. +dom5788. NS a.root-servers.nil. +dom5789. NS a.root-servers.nil. +dom5790. NS a.root-servers.nil. +dom5791. NS a.root-servers.nil. +dom5792. NS a.root-servers.nil. +dom5793. NS a.root-servers.nil. +dom5794. NS a.root-servers.nil. +dom5795. NS a.root-servers.nil. +dom5796. NS a.root-servers.nil. +dom5797. NS a.root-servers.nil. +dom5798. NS a.root-servers.nil. +dom5799. NS a.root-servers.nil. +dom5800. NS a.root-servers.nil. +dom5801. NS a.root-servers.nil. +dom5802. NS a.root-servers.nil. +dom5803. NS a.root-servers.nil. +dom5804. NS a.root-servers.nil. +dom5805. NS a.root-servers.nil. +dom5806. NS a.root-servers.nil. +dom5807. NS a.root-servers.nil. +dom5808. NS a.root-servers.nil. +dom5809. NS a.root-servers.nil. +dom5810. NS a.root-servers.nil. +dom5811. NS a.root-servers.nil. +dom5812. NS a.root-servers.nil. +dom5813. NS a.root-servers.nil. +dom5814. NS a.root-servers.nil. +dom5815. NS a.root-servers.nil. +dom5816. NS a.root-servers.nil. +dom5817. NS a.root-servers.nil. +dom5818. NS a.root-servers.nil. +dom5819. NS a.root-servers.nil. +dom5820. NS a.root-servers.nil. +dom5821. NS a.root-servers.nil. +dom5822. NS a.root-servers.nil. +dom5823. NS a.root-servers.nil. +dom5824. NS a.root-servers.nil. +dom5825. NS a.root-servers.nil. +dom5826. NS a.root-servers.nil. +dom5827. NS a.root-servers.nil. +dom5828. NS a.root-servers.nil. +dom5829. NS a.root-servers.nil. +dom5830. NS a.root-servers.nil. +dom5831. NS a.root-servers.nil. +dom5832. NS a.root-servers.nil. +dom5833. NS a.root-servers.nil. +dom5834. NS a.root-servers.nil. +dom5835. NS a.root-servers.nil. +dom5836. NS a.root-servers.nil. +dom5837. NS a.root-servers.nil. +dom5838. NS a.root-servers.nil. +dom5839. NS a.root-servers.nil. +dom5840. NS a.root-servers.nil. +dom5841. NS a.root-servers.nil. +dom5842. NS a.root-servers.nil. +dom5843. NS a.root-servers.nil. +dom5844. NS a.root-servers.nil. +dom5845. NS a.root-servers.nil. +dom5846. NS a.root-servers.nil. +dom5847. NS a.root-servers.nil. +dom5848. NS a.root-servers.nil. +dom5849. NS a.root-servers.nil. +dom5850. NS a.root-servers.nil. +dom5851. NS a.root-servers.nil. +dom5852. NS a.root-servers.nil. +dom5853. NS a.root-servers.nil. +dom5854. NS a.root-servers.nil. +dom5855. NS a.root-servers.nil. +dom5856. NS a.root-servers.nil. +dom5857. NS a.root-servers.nil. +dom5858. NS a.root-servers.nil. +dom5859. NS a.root-servers.nil. +dom5860. NS a.root-servers.nil. +dom5861. NS a.root-servers.nil. +dom5862. NS a.root-servers.nil. +dom5863. NS a.root-servers.nil. +dom5864. NS a.root-servers.nil. +dom5865. NS a.root-servers.nil. +dom5866. NS a.root-servers.nil. +dom5867. NS a.root-servers.nil. +dom5868. NS a.root-servers.nil. +dom5869. NS a.root-servers.nil. +dom5870. NS a.root-servers.nil. +dom5871. NS a.root-servers.nil. +dom5872. NS a.root-servers.nil. +dom5873. NS a.root-servers.nil. +dom5874. NS a.root-servers.nil. +dom5875. NS a.root-servers.nil. +dom5876. NS a.root-servers.nil. +dom5877. NS a.root-servers.nil. +dom5878. NS a.root-servers.nil. +dom5879. NS a.root-servers.nil. +dom5880. NS a.root-servers.nil. +dom5881. NS a.root-servers.nil. +dom5882. NS a.root-servers.nil. +dom5883. NS a.root-servers.nil. +dom5884. NS a.root-servers.nil. +dom5885. NS a.root-servers.nil. +dom5886. NS a.root-servers.nil. +dom5887. NS a.root-servers.nil. +dom5888. NS a.root-servers.nil. +dom5889. NS a.root-servers.nil. +dom5890. NS a.root-servers.nil. +dom5891. NS a.root-servers.nil. +dom5892. NS a.root-servers.nil. +dom5893. NS a.root-servers.nil. +dom5894. NS a.root-servers.nil. +dom5895. NS a.root-servers.nil. +dom5896. NS a.root-servers.nil. +dom5897. NS a.root-servers.nil. +dom5898. NS a.root-servers.nil. +dom5899. NS a.root-servers.nil. +dom5900. NS a.root-servers.nil. +dom5901. NS a.root-servers.nil. +dom5902. NS a.root-servers.nil. +dom5903. NS a.root-servers.nil. +dom5904. NS a.root-servers.nil. +dom5905. NS a.root-servers.nil. +dom5906. NS a.root-servers.nil. +dom5907. NS a.root-servers.nil. +dom5908. NS a.root-servers.nil. +dom5909. NS a.root-servers.nil. +dom5910. NS a.root-servers.nil. +dom5911. NS a.root-servers.nil. +dom5912. NS a.root-servers.nil. +dom5913. NS a.root-servers.nil. +dom5914. NS a.root-servers.nil. +dom5915. NS a.root-servers.nil. +dom5916. NS a.root-servers.nil. +dom5917. NS a.root-servers.nil. +dom5918. NS a.root-servers.nil. +dom5919. NS a.root-servers.nil. +dom5920. NS a.root-servers.nil. +dom5921. NS a.root-servers.nil. +dom5922. NS a.root-servers.nil. +dom5923. NS a.root-servers.nil. +dom5924. NS a.root-servers.nil. +dom5925. NS a.root-servers.nil. +dom5926. NS a.root-servers.nil. +dom5927. NS a.root-servers.nil. +dom5928. NS a.root-servers.nil. +dom5929. NS a.root-servers.nil. +dom5930. NS a.root-servers.nil. +dom5931. NS a.root-servers.nil. +dom5932. NS a.root-servers.nil. +dom5933. NS a.root-servers.nil. +dom5934. NS a.root-servers.nil. +dom5935. NS a.root-servers.nil. +dom5936. NS a.root-servers.nil. +dom5937. NS a.root-servers.nil. +dom5938. NS a.root-servers.nil. +dom5939. NS a.root-servers.nil. +dom5940. NS a.root-servers.nil. +dom5941. NS a.root-servers.nil. +dom5942. NS a.root-servers.nil. +dom5943. NS a.root-servers.nil. +dom5944. NS a.root-servers.nil. +dom5945. NS a.root-servers.nil. +dom5946. NS a.root-servers.nil. +dom5947. NS a.root-servers.nil. +dom5948. NS a.root-servers.nil. +dom5949. NS a.root-servers.nil. +dom5950. NS a.root-servers.nil. +dom5951. NS a.root-servers.nil. +dom5952. NS a.root-servers.nil. +dom5953. NS a.root-servers.nil. +dom5954. NS a.root-servers.nil. +dom5955. NS a.root-servers.nil. +dom5956. NS a.root-servers.nil. +dom5957. NS a.root-servers.nil. +dom5958. NS a.root-servers.nil. +dom5959. NS a.root-servers.nil. +dom5960. NS a.root-servers.nil. +dom5961. NS a.root-servers.nil. +dom5962. NS a.root-servers.nil. +dom5963. NS a.root-servers.nil. +dom5964. NS a.root-servers.nil. +dom5965. NS a.root-servers.nil. +dom5966. NS a.root-servers.nil. +dom5967. NS a.root-servers.nil. +dom5968. NS a.root-servers.nil. +dom5969. NS a.root-servers.nil. +dom5970. NS a.root-servers.nil. +dom5971. NS a.root-servers.nil. +dom5972. NS a.root-servers.nil. +dom5973. NS a.root-servers.nil. +dom5974. NS a.root-servers.nil. +dom5975. NS a.root-servers.nil. +dom5976. NS a.root-servers.nil. +dom5977. NS a.root-servers.nil. +dom5978. NS a.root-servers.nil. +dom5979. NS a.root-servers.nil. +dom5980. NS a.root-servers.nil. +dom5981. NS a.root-servers.nil. +dom5982. NS a.root-servers.nil. +dom5983. NS a.root-servers.nil. +dom5984. NS a.root-servers.nil. +dom5985. NS a.root-servers.nil. +dom5986. NS a.root-servers.nil. +dom5987. NS a.root-servers.nil. +dom5988. NS a.root-servers.nil. +dom5989. NS a.root-servers.nil. +dom5990. NS a.root-servers.nil. +dom5991. NS a.root-servers.nil. +dom5992. NS a.root-servers.nil. +dom5993. NS a.root-servers.nil. +dom5994. NS a.root-servers.nil. +dom5995. NS a.root-servers.nil. +dom5996. NS a.root-servers.nil. +dom5997. NS a.root-servers.nil. +dom5998. NS a.root-servers.nil. +dom5999. NS a.root-servers.nil. +dom6000. NS a.root-servers.nil. +dom6001. NS a.root-servers.nil. +dom6002. NS a.root-servers.nil. +dom6003. NS a.root-servers.nil. +dom6004. NS a.root-servers.nil. +dom6005. NS a.root-servers.nil. +dom6006. NS a.root-servers.nil. +dom6007. NS a.root-servers.nil. +dom6008. NS a.root-servers.nil. +dom6009. NS a.root-servers.nil. +dom6010. NS a.root-servers.nil. +dom6011. NS a.root-servers.nil. +dom6012. NS a.root-servers.nil. +dom6013. NS a.root-servers.nil. +dom6014. NS a.root-servers.nil. +dom6015. NS a.root-servers.nil. +dom6016. NS a.root-servers.nil. +dom6017. NS a.root-servers.nil. +dom6018. NS a.root-servers.nil. +dom6019. NS a.root-servers.nil. +dom6020. NS a.root-servers.nil. +dom6021. NS a.root-servers.nil. +dom6022. NS a.root-servers.nil. +dom6023. NS a.root-servers.nil. +dom6024. NS a.root-servers.nil. +dom6025. NS a.root-servers.nil. +dom6026. NS a.root-servers.nil. +dom6027. NS a.root-servers.nil. +dom6028. NS a.root-servers.nil. +dom6029. NS a.root-servers.nil. +dom6030. NS a.root-servers.nil. +dom6031. NS a.root-servers.nil. +dom6032. NS a.root-servers.nil. +dom6033. NS a.root-servers.nil. +dom6034. NS a.root-servers.nil. +dom6035. NS a.root-servers.nil. +dom6036. NS a.root-servers.nil. +dom6037. NS a.root-servers.nil. +dom6038. NS a.root-servers.nil. +dom6039. NS a.root-servers.nil. +dom6040. NS a.root-servers.nil. +dom6041. NS a.root-servers.nil. +dom6042. NS a.root-servers.nil. +dom6043. NS a.root-servers.nil. +dom6044. NS a.root-servers.nil. +dom6045. NS a.root-servers.nil. +dom6046. NS a.root-servers.nil. +dom6047. NS a.root-servers.nil. +dom6048. NS a.root-servers.nil. +dom6049. NS a.root-servers.nil. +dom6050. NS a.root-servers.nil. +dom6051. NS a.root-servers.nil. +dom6052. NS a.root-servers.nil. +dom6053. NS a.root-servers.nil. +dom6054. NS a.root-servers.nil. +dom6055. NS a.root-servers.nil. +dom6056. NS a.root-servers.nil. +dom6057. NS a.root-servers.nil. +dom6058. NS a.root-servers.nil. +dom6059. NS a.root-servers.nil. +dom6060. NS a.root-servers.nil. +dom6061. NS a.root-servers.nil. +dom6062. NS a.root-servers.nil. +dom6063. NS a.root-servers.nil. +dom6064. NS a.root-servers.nil. +dom6065. NS a.root-servers.nil. +dom6066. NS a.root-servers.nil. +dom6067. NS a.root-servers.nil. +dom6068. NS a.root-servers.nil. +dom6069. NS a.root-servers.nil. +dom6070. NS a.root-servers.nil. +dom6071. NS a.root-servers.nil. +dom6072. NS a.root-servers.nil. +dom6073. NS a.root-servers.nil. +dom6074. NS a.root-servers.nil. +dom6075. NS a.root-servers.nil. +dom6076. NS a.root-servers.nil. +dom6077. NS a.root-servers.nil. +dom6078. NS a.root-servers.nil. +dom6079. NS a.root-servers.nil. +dom6080. NS a.root-servers.nil. +dom6081. NS a.root-servers.nil. +dom6082. NS a.root-servers.nil. +dom6083. NS a.root-servers.nil. +dom6084. NS a.root-servers.nil. +dom6085. NS a.root-servers.nil. +dom6086. NS a.root-servers.nil. +dom6087. NS a.root-servers.nil. +dom6088. NS a.root-servers.nil. +dom6089. NS a.root-servers.nil. +dom6090. NS a.root-servers.nil. +dom6091. NS a.root-servers.nil. +dom6092. NS a.root-servers.nil. +dom6093. NS a.root-servers.nil. +dom6094. NS a.root-servers.nil. +dom6095. NS a.root-servers.nil. +dom6096. NS a.root-servers.nil. +dom6097. NS a.root-servers.nil. +dom6098. NS a.root-servers.nil. +dom6099. NS a.root-servers.nil. +dom6100. NS a.root-servers.nil. +dom6101. NS a.root-servers.nil. +dom6102. NS a.root-servers.nil. +dom6103. NS a.root-servers.nil. +dom6104. NS a.root-servers.nil. +dom6105. NS a.root-servers.nil. +dom6106. NS a.root-servers.nil. +dom6107. NS a.root-servers.nil. +dom6108. NS a.root-servers.nil. +dom6109. NS a.root-servers.nil. +dom6110. NS a.root-servers.nil. +dom6111. NS a.root-servers.nil. +dom6112. NS a.root-servers.nil. +dom6113. NS a.root-servers.nil. +dom6114. NS a.root-servers.nil. +dom6115. NS a.root-servers.nil. +dom6116. NS a.root-servers.nil. +dom6117. NS a.root-servers.nil. +dom6118. NS a.root-servers.nil. +dom6119. NS a.root-servers.nil. +dom6120. NS a.root-servers.nil. +dom6121. NS a.root-servers.nil. +dom6122. NS a.root-servers.nil. +dom6123. NS a.root-servers.nil. +dom6124. NS a.root-servers.nil. +dom6125. NS a.root-servers.nil. +dom6126. NS a.root-servers.nil. +dom6127. NS a.root-servers.nil. +dom6128. NS a.root-servers.nil. +dom6129. NS a.root-servers.nil. +dom6130. NS a.root-servers.nil. +dom6131. NS a.root-servers.nil. +dom6132. NS a.root-servers.nil. +dom6133. NS a.root-servers.nil. +dom6134. NS a.root-servers.nil. +dom6135. NS a.root-servers.nil. +dom6136. NS a.root-servers.nil. +dom6137. NS a.root-servers.nil. +dom6138. NS a.root-servers.nil. +dom6139. NS a.root-servers.nil. +dom6140. NS a.root-servers.nil. +dom6141. NS a.root-servers.nil. +dom6142. NS a.root-servers.nil. +dom6143. NS a.root-servers.nil. +dom6144. NS a.root-servers.nil. +dom6145. NS a.root-servers.nil. +dom6146. NS a.root-servers.nil. +dom6147. NS a.root-servers.nil. +dom6148. NS a.root-servers.nil. +dom6149. NS a.root-servers.nil. +dom6150. NS a.root-servers.nil. +dom6151. NS a.root-servers.nil. +dom6152. NS a.root-servers.nil. +dom6153. NS a.root-servers.nil. +dom6154. NS a.root-servers.nil. +dom6155. NS a.root-servers.nil. +dom6156. NS a.root-servers.nil. +dom6157. NS a.root-servers.nil. +dom6158. NS a.root-servers.nil. +dom6159. NS a.root-servers.nil. +dom6160. NS a.root-servers.nil. +dom6161. NS a.root-servers.nil. +dom6162. NS a.root-servers.nil. +dom6163. NS a.root-servers.nil. +dom6164. NS a.root-servers.nil. +dom6165. NS a.root-servers.nil. +dom6166. NS a.root-servers.nil. +dom6167. NS a.root-servers.nil. +dom6168. NS a.root-servers.nil. +dom6169. NS a.root-servers.nil. +dom6170. NS a.root-servers.nil. +dom6171. NS a.root-servers.nil. +dom6172. NS a.root-servers.nil. +dom6173. NS a.root-servers.nil. +dom6174. NS a.root-servers.nil. +dom6175. NS a.root-servers.nil. +dom6176. NS a.root-servers.nil. +dom6177. NS a.root-servers.nil. +dom6178. NS a.root-servers.nil. +dom6179. NS a.root-servers.nil. +dom6180. NS a.root-servers.nil. +dom6181. NS a.root-servers.nil. +dom6182. NS a.root-servers.nil. +dom6183. NS a.root-servers.nil. +dom6184. NS a.root-servers.nil. +dom6185. NS a.root-servers.nil. +dom6186. NS a.root-servers.nil. +dom6187. NS a.root-servers.nil. +dom6188. NS a.root-servers.nil. +dom6189. NS a.root-servers.nil. +dom6190. NS a.root-servers.nil. +dom6191. NS a.root-servers.nil. +dom6192. NS a.root-servers.nil. +dom6193. NS a.root-servers.nil. +dom6194. NS a.root-servers.nil. +dom6195. NS a.root-servers.nil. +dom6196. NS a.root-servers.nil. +dom6197. NS a.root-servers.nil. +dom6198. NS a.root-servers.nil. +dom6199. NS a.root-servers.nil. +dom6200. NS a.root-servers.nil. +dom6201. NS a.root-servers.nil. +dom6202. NS a.root-servers.nil. +dom6203. NS a.root-servers.nil. +dom6204. NS a.root-servers.nil. +dom6205. NS a.root-servers.nil. +dom6206. NS a.root-servers.nil. +dom6207. NS a.root-servers.nil. +dom6208. NS a.root-servers.nil. +dom6209. NS a.root-servers.nil. +dom6210. NS a.root-servers.nil. +dom6211. NS a.root-servers.nil. +dom6212. NS a.root-servers.nil. +dom6213. NS a.root-servers.nil. +dom6214. NS a.root-servers.nil. +dom6215. NS a.root-servers.nil. +dom6216. NS a.root-servers.nil. +dom6217. NS a.root-servers.nil. +dom6218. NS a.root-servers.nil. +dom6219. NS a.root-servers.nil. +dom6220. NS a.root-servers.nil. +dom6221. NS a.root-servers.nil. +dom6222. NS a.root-servers.nil. +dom6223. NS a.root-servers.nil. +dom6224. NS a.root-servers.nil. +dom6225. NS a.root-servers.nil. +dom6226. NS a.root-servers.nil. +dom6227. NS a.root-servers.nil. +dom6228. NS a.root-servers.nil. +dom6229. NS a.root-servers.nil. +dom6230. NS a.root-servers.nil. +dom6231. NS a.root-servers.nil. +dom6232. NS a.root-servers.nil. +dom6233. NS a.root-servers.nil. +dom6234. NS a.root-servers.nil. +dom6235. NS a.root-servers.nil. +dom6236. NS a.root-servers.nil. +dom6237. NS a.root-servers.nil. +dom6238. NS a.root-servers.nil. +dom6239. NS a.root-servers.nil. +dom6240. NS a.root-servers.nil. +dom6241. NS a.root-servers.nil. +dom6242. NS a.root-servers.nil. +dom6243. NS a.root-servers.nil. +dom6244. NS a.root-servers.nil. +dom6245. NS a.root-servers.nil. +dom6246. NS a.root-servers.nil. +dom6247. NS a.root-servers.nil. +dom6248. NS a.root-servers.nil. +dom6249. NS a.root-servers.nil. +dom6250. NS a.root-servers.nil. +dom6251. NS a.root-servers.nil. +dom6252. NS a.root-servers.nil. +dom6253. NS a.root-servers.nil. +dom6254. NS a.root-servers.nil. +dom6255. NS a.root-servers.nil. +dom6256. NS a.root-servers.nil. +dom6257. NS a.root-servers.nil. +dom6258. NS a.root-servers.nil. +dom6259. NS a.root-servers.nil. +dom6260. NS a.root-servers.nil. +dom6261. NS a.root-servers.nil. +dom6262. NS a.root-servers.nil. +dom6263. NS a.root-servers.nil. +dom6264. NS a.root-servers.nil. +dom6265. NS a.root-servers.nil. +dom6266. NS a.root-servers.nil. +dom6267. NS a.root-servers.nil. +dom6268. NS a.root-servers.nil. +dom6269. NS a.root-servers.nil. +dom6270. NS a.root-servers.nil. +dom6271. NS a.root-servers.nil. +dom6272. NS a.root-servers.nil. +dom6273. NS a.root-servers.nil. +dom6274. NS a.root-servers.nil. +dom6275. NS a.root-servers.nil. +dom6276. NS a.root-servers.nil. +dom6277. NS a.root-servers.nil. +dom6278. NS a.root-servers.nil. +dom6279. NS a.root-servers.nil. +dom6280. NS a.root-servers.nil. +dom6281. NS a.root-servers.nil. +dom6282. NS a.root-servers.nil. +dom6283. NS a.root-servers.nil. +dom6284. NS a.root-servers.nil. +dom6285. NS a.root-servers.nil. +dom6286. NS a.root-servers.nil. +dom6287. NS a.root-servers.nil. +dom6288. NS a.root-servers.nil. +dom6289. NS a.root-servers.nil. +dom6290. NS a.root-servers.nil. +dom6291. NS a.root-servers.nil. +dom6292. NS a.root-servers.nil. +dom6293. NS a.root-servers.nil. +dom6294. NS a.root-servers.nil. +dom6295. NS a.root-servers.nil. +dom6296. NS a.root-servers.nil. +dom6297. NS a.root-servers.nil. +dom6298. NS a.root-servers.nil. +dom6299. NS a.root-servers.nil. +dom6300. NS a.root-servers.nil. +dom6301. NS a.root-servers.nil. +dom6302. NS a.root-servers.nil. +dom6303. NS a.root-servers.nil. +dom6304. NS a.root-servers.nil. +dom6305. NS a.root-servers.nil. +dom6306. NS a.root-servers.nil. +dom6307. NS a.root-servers.nil. +dom6308. NS a.root-servers.nil. +dom6309. NS a.root-servers.nil. +dom6310. NS a.root-servers.nil. +dom6311. NS a.root-servers.nil. +dom6312. NS a.root-servers.nil. +dom6313. NS a.root-servers.nil. +dom6314. NS a.root-servers.nil. +dom6315. NS a.root-servers.nil. +dom6316. NS a.root-servers.nil. +dom6317. NS a.root-servers.nil. +dom6318. NS a.root-servers.nil. +dom6319. NS a.root-servers.nil. +dom6320. NS a.root-servers.nil. +dom6321. NS a.root-servers.nil. +dom6322. NS a.root-servers.nil. +dom6323. NS a.root-servers.nil. +dom6324. NS a.root-servers.nil. +dom6325. NS a.root-servers.nil. +dom6326. NS a.root-servers.nil. +dom6327. NS a.root-servers.nil. +dom6328. NS a.root-servers.nil. +dom6329. NS a.root-servers.nil. +dom6330. NS a.root-servers.nil. +dom6331. NS a.root-servers.nil. +dom6332. NS a.root-servers.nil. +dom6333. NS a.root-servers.nil. +dom6334. NS a.root-servers.nil. +dom6335. NS a.root-servers.nil. +dom6336. NS a.root-servers.nil. +dom6337. NS a.root-servers.nil. +dom6338. NS a.root-servers.nil. +dom6339. NS a.root-servers.nil. +dom6340. NS a.root-servers.nil. +dom6341. NS a.root-servers.nil. +dom6342. NS a.root-servers.nil. +dom6343. NS a.root-servers.nil. +dom6344. NS a.root-servers.nil. +dom6345. NS a.root-servers.nil. +dom6346. NS a.root-servers.nil. +dom6347. NS a.root-servers.nil. +dom6348. NS a.root-servers.nil. +dom6349. NS a.root-servers.nil. +dom6350. NS a.root-servers.nil. +dom6351. NS a.root-servers.nil. +dom6352. NS a.root-servers.nil. +dom6353. NS a.root-servers.nil. +dom6354. NS a.root-servers.nil. +dom6355. NS a.root-servers.nil. +dom6356. NS a.root-servers.nil. +dom6357. NS a.root-servers.nil. +dom6358. NS a.root-servers.nil. +dom6359. NS a.root-servers.nil. +dom6360. NS a.root-servers.nil. +dom6361. NS a.root-servers.nil. +dom6362. NS a.root-servers.nil. +dom6363. NS a.root-servers.nil. +dom6364. NS a.root-servers.nil. +dom6365. NS a.root-servers.nil. +dom6366. NS a.root-servers.nil. +dom6367. NS a.root-servers.nil. +dom6368. NS a.root-servers.nil. +dom6369. NS a.root-servers.nil. +dom6370. NS a.root-servers.nil. +dom6371. NS a.root-servers.nil. +dom6372. NS a.root-servers.nil. +dom6373. NS a.root-servers.nil. +dom6374. NS a.root-servers.nil. +dom6375. NS a.root-servers.nil. +dom6376. NS a.root-servers.nil. +dom6377. NS a.root-servers.nil. +dom6378. NS a.root-servers.nil. +dom6379. NS a.root-servers.nil. +dom6380. NS a.root-servers.nil. +dom6381. NS a.root-servers.nil. +dom6382. NS a.root-servers.nil. +dom6383. NS a.root-servers.nil. +dom6384. NS a.root-servers.nil. +dom6385. NS a.root-servers.nil. +dom6386. NS a.root-servers.nil. +dom6387. NS a.root-servers.nil. +dom6388. NS a.root-servers.nil. +dom6389. NS a.root-servers.nil. +dom6390. NS a.root-servers.nil. +dom6391. NS a.root-servers.nil. +dom6392. NS a.root-servers.nil. +dom6393. NS a.root-servers.nil. +dom6394. NS a.root-servers.nil. +dom6395. NS a.root-servers.nil. +dom6396. NS a.root-servers.nil. +dom6397. NS a.root-servers.nil. +dom6398. NS a.root-servers.nil. +dom6399. NS a.root-servers.nil. +dom6400. NS a.root-servers.nil. +dom6401. NS a.root-servers.nil. +dom6402. NS a.root-servers.nil. +dom6403. NS a.root-servers.nil. +dom6404. NS a.root-servers.nil. +dom6405. NS a.root-servers.nil. +dom6406. NS a.root-servers.nil. +dom6407. NS a.root-servers.nil. +dom6408. NS a.root-servers.nil. +dom6409. NS a.root-servers.nil. +dom6410. NS a.root-servers.nil. +dom6411. NS a.root-servers.nil. +dom6412. NS a.root-servers.nil. +dom6413. NS a.root-servers.nil. +dom6414. NS a.root-servers.nil. +dom6415. NS a.root-servers.nil. +dom6416. NS a.root-servers.nil. +dom6417. NS a.root-servers.nil. +dom6418. NS a.root-servers.nil. +dom6419. NS a.root-servers.nil. +dom6420. NS a.root-servers.nil. +dom6421. NS a.root-servers.nil. +dom6422. NS a.root-servers.nil. +dom6423. NS a.root-servers.nil. +dom6424. NS a.root-servers.nil. +dom6425. NS a.root-servers.nil. +dom6426. NS a.root-servers.nil. +dom6427. NS a.root-servers.nil. +dom6428. NS a.root-servers.nil. +dom6429. NS a.root-servers.nil. +dom6430. NS a.root-servers.nil. +dom6431. NS a.root-servers.nil. +dom6432. NS a.root-servers.nil. +dom6433. NS a.root-servers.nil. +dom6434. NS a.root-servers.nil. +dom6435. NS a.root-servers.nil. +dom6436. NS a.root-servers.nil. +dom6437. NS a.root-servers.nil. +dom6438. NS a.root-servers.nil. +dom6439. NS a.root-servers.nil. +dom6440. NS a.root-servers.nil. +dom6441. NS a.root-servers.nil. +dom6442. NS a.root-servers.nil. +dom6443. NS a.root-servers.nil. +dom6444. NS a.root-servers.nil. +dom6445. NS a.root-servers.nil. +dom6446. NS a.root-servers.nil. +dom6447. NS a.root-servers.nil. +dom6448. NS a.root-servers.nil. +dom6449. NS a.root-servers.nil. +dom6450. NS a.root-servers.nil. +dom6451. NS a.root-servers.nil. +dom6452. NS a.root-servers.nil. +dom6453. NS a.root-servers.nil. +dom6454. NS a.root-servers.nil. +dom6455. NS a.root-servers.nil. +dom6456. NS a.root-servers.nil. +dom6457. NS a.root-servers.nil. +dom6458. NS a.root-servers.nil. +dom6459. NS a.root-servers.nil. +dom6460. NS a.root-servers.nil. +dom6461. NS a.root-servers.nil. +dom6462. NS a.root-servers.nil. +dom6463. NS a.root-servers.nil. +dom6464. NS a.root-servers.nil. +dom6465. NS a.root-servers.nil. +dom6466. NS a.root-servers.nil. +dom6467. NS a.root-servers.nil. +dom6468. NS a.root-servers.nil. +dom6469. NS a.root-servers.nil. +dom6470. NS a.root-servers.nil. +dom6471. NS a.root-servers.nil. +dom6472. NS a.root-servers.nil. +dom6473. NS a.root-servers.nil. +dom6474. NS a.root-servers.nil. +dom6475. NS a.root-servers.nil. +dom6476. NS a.root-servers.nil. +dom6477. NS a.root-servers.nil. +dom6478. NS a.root-servers.nil. +dom6479. NS a.root-servers.nil. +dom6480. NS a.root-servers.nil. +dom6481. NS a.root-servers.nil. +dom6482. NS a.root-servers.nil. +dom6483. NS a.root-servers.nil. +dom6484. NS a.root-servers.nil. +dom6485. NS a.root-servers.nil. +dom6486. NS a.root-servers.nil. +dom6487. NS a.root-servers.nil. +dom6488. NS a.root-servers.nil. +dom6489. NS a.root-servers.nil. +dom6490. NS a.root-servers.nil. +dom6491. NS a.root-servers.nil. +dom6492. NS a.root-servers.nil. +dom6493. NS a.root-servers.nil. +dom6494. NS a.root-servers.nil. +dom6495. NS a.root-servers.nil. +dom6496. NS a.root-servers.nil. +dom6497. NS a.root-servers.nil. +dom6498. NS a.root-servers.nil. +dom6499. NS a.root-servers.nil. +dom6500. NS a.root-servers.nil. +dom6501. NS a.root-servers.nil. +dom6502. NS a.root-servers.nil. +dom6503. NS a.root-servers.nil. +dom6504. NS a.root-servers.nil. +dom6505. NS a.root-servers.nil. +dom6506. NS a.root-servers.nil. +dom6507. NS a.root-servers.nil. +dom6508. NS a.root-servers.nil. +dom6509. NS a.root-servers.nil. +dom6510. NS a.root-servers.nil. +dom6511. NS a.root-servers.nil. +dom6512. NS a.root-servers.nil. +dom6513. NS a.root-servers.nil. +dom6514. NS a.root-servers.nil. +dom6515. NS a.root-servers.nil. +dom6516. NS a.root-servers.nil. +dom6517. NS a.root-servers.nil. +dom6518. NS a.root-servers.nil. +dom6519. NS a.root-servers.nil. +dom6520. NS a.root-servers.nil. +dom6521. NS a.root-servers.nil. +dom6522. NS a.root-servers.nil. +dom6523. NS a.root-servers.nil. +dom6524. NS a.root-servers.nil. +dom6525. NS a.root-servers.nil. +dom6526. NS a.root-servers.nil. +dom6527. NS a.root-servers.nil. +dom6528. NS a.root-servers.nil. +dom6529. NS a.root-servers.nil. +dom6530. NS a.root-servers.nil. +dom6531. NS a.root-servers.nil. +dom6532. NS a.root-servers.nil. +dom6533. NS a.root-servers.nil. +dom6534. NS a.root-servers.nil. +dom6535. NS a.root-servers.nil. +dom6536. NS a.root-servers.nil. +dom6537. NS a.root-servers.nil. +dom6538. NS a.root-servers.nil. +dom6539. NS a.root-servers.nil. +dom6540. NS a.root-servers.nil. +dom6541. NS a.root-servers.nil. +dom6542. NS a.root-servers.nil. +dom6543. NS a.root-servers.nil. +dom6544. NS a.root-servers.nil. +dom6545. NS a.root-servers.nil. +dom6546. NS a.root-servers.nil. +dom6547. NS a.root-servers.nil. +dom6548. NS a.root-servers.nil. +dom6549. NS a.root-servers.nil. +dom6550. NS a.root-servers.nil. +dom6551. NS a.root-servers.nil. +dom6552. NS a.root-servers.nil. +dom6553. NS a.root-servers.nil. +dom6554. NS a.root-servers.nil. +dom6555. NS a.root-servers.nil. +dom6556. NS a.root-servers.nil. +dom6557. NS a.root-servers.nil. +dom6558. NS a.root-servers.nil. +dom6559. NS a.root-servers.nil. +dom6560. NS a.root-servers.nil. +dom6561. NS a.root-servers.nil. +dom6562. NS a.root-servers.nil. +dom6563. NS a.root-servers.nil. +dom6564. NS a.root-servers.nil. +dom6565. NS a.root-servers.nil. +dom6566. NS a.root-servers.nil. +dom6567. NS a.root-servers.nil. +dom6568. NS a.root-servers.nil. +dom6569. NS a.root-servers.nil. +dom6570. NS a.root-servers.nil. +dom6571. NS a.root-servers.nil. +dom6572. NS a.root-servers.nil. +dom6573. NS a.root-servers.nil. +dom6574. NS a.root-servers.nil. +dom6575. NS a.root-servers.nil. +dom6576. NS a.root-servers.nil. +dom6577. NS a.root-servers.nil. +dom6578. NS a.root-servers.nil. +dom6579. NS a.root-servers.nil. +dom6580. NS a.root-servers.nil. +dom6581. NS a.root-servers.nil. +dom6582. NS a.root-servers.nil. +dom6583. NS a.root-servers.nil. +dom6584. NS a.root-servers.nil. +dom6585. NS a.root-servers.nil. +dom6586. NS a.root-servers.nil. +dom6587. NS a.root-servers.nil. +dom6588. NS a.root-servers.nil. +dom6589. NS a.root-servers.nil. +dom6590. NS a.root-servers.nil. +dom6591. NS a.root-servers.nil. +dom6592. NS a.root-servers.nil. +dom6593. NS a.root-servers.nil. +dom6594. NS a.root-servers.nil. +dom6595. NS a.root-servers.nil. +dom6596. NS a.root-servers.nil. +dom6597. NS a.root-servers.nil. +dom6598. NS a.root-servers.nil. +dom6599. NS a.root-servers.nil. +dom6600. NS a.root-servers.nil. +dom6601. NS a.root-servers.nil. +dom6602. NS a.root-servers.nil. +dom6603. NS a.root-servers.nil. +dom6604. NS a.root-servers.nil. +dom6605. NS a.root-servers.nil. +dom6606. NS a.root-servers.nil. +dom6607. NS a.root-servers.nil. +dom6608. NS a.root-servers.nil. +dom6609. NS a.root-servers.nil. +dom6610. NS a.root-servers.nil. +dom6611. NS a.root-servers.nil. +dom6612. NS a.root-servers.nil. +dom6613. NS a.root-servers.nil. +dom6614. NS a.root-servers.nil. +dom6615. NS a.root-servers.nil. +dom6616. NS a.root-servers.nil. +dom6617. NS a.root-servers.nil. +dom6618. NS a.root-servers.nil. +dom6619. NS a.root-servers.nil. +dom6620. NS a.root-servers.nil. +dom6621. NS a.root-servers.nil. +dom6622. NS a.root-servers.nil. +dom6623. NS a.root-servers.nil. +dom6624. NS a.root-servers.nil. +dom6625. NS a.root-servers.nil. +dom6626. NS a.root-servers.nil. +dom6627. NS a.root-servers.nil. +dom6628. NS a.root-servers.nil. +dom6629. NS a.root-servers.nil. +dom6630. NS a.root-servers.nil. +dom6631. NS a.root-servers.nil. +dom6632. NS a.root-servers.nil. +dom6633. NS a.root-servers.nil. +dom6634. NS a.root-servers.nil. +dom6635. NS a.root-servers.nil. +dom6636. NS a.root-servers.nil. +dom6637. NS a.root-servers.nil. +dom6638. NS a.root-servers.nil. +dom6639. NS a.root-servers.nil. +dom6640. NS a.root-servers.nil. +dom6641. NS a.root-servers.nil. +dom6642. NS a.root-servers.nil. +dom6643. NS a.root-servers.nil. +dom6644. NS a.root-servers.nil. +dom6645. NS a.root-servers.nil. +dom6646. NS a.root-servers.nil. +dom6647. NS a.root-servers.nil. +dom6648. NS a.root-servers.nil. +dom6649. NS a.root-servers.nil. +dom6650. NS a.root-servers.nil. +dom6651. NS a.root-servers.nil. +dom6652. NS a.root-servers.nil. +dom6653. NS a.root-servers.nil. +dom6654. NS a.root-servers.nil. +dom6655. NS a.root-servers.nil. +dom6656. NS a.root-servers.nil. +dom6657. NS a.root-servers.nil. +dom6658. NS a.root-servers.nil. +dom6659. NS a.root-servers.nil. +dom6660. NS a.root-servers.nil. +dom6661. NS a.root-servers.nil. +dom6662. NS a.root-servers.nil. +dom6663. NS a.root-servers.nil. +dom6664. NS a.root-servers.nil. +dom6665. NS a.root-servers.nil. +dom6666. NS a.root-servers.nil. +dom6667. NS a.root-servers.nil. +dom6668. NS a.root-servers.nil. +dom6669. NS a.root-servers.nil. +dom6670. NS a.root-servers.nil. +dom6671. NS a.root-servers.nil. +dom6672. NS a.root-servers.nil. +dom6673. NS a.root-servers.nil. +dom6674. NS a.root-servers.nil. +dom6675. NS a.root-servers.nil. +dom6676. NS a.root-servers.nil. +dom6677. NS a.root-servers.nil. +dom6678. NS a.root-servers.nil. +dom6679. NS a.root-servers.nil. +dom6680. NS a.root-servers.nil. +dom6681. NS a.root-servers.nil. +dom6682. NS a.root-servers.nil. +dom6683. NS a.root-servers.nil. +dom6684. NS a.root-servers.nil. +dom6685. NS a.root-servers.nil. +dom6686. NS a.root-servers.nil. +dom6687. NS a.root-servers.nil. +dom6688. NS a.root-servers.nil. +dom6689. NS a.root-servers.nil. +dom6690. NS a.root-servers.nil. +dom6691. NS a.root-servers.nil. +dom6692. NS a.root-servers.nil. +dom6693. NS a.root-servers.nil. +dom6694. NS a.root-servers.nil. +dom6695. NS a.root-servers.nil. +dom6696. NS a.root-servers.nil. +dom6697. NS a.root-servers.nil. +dom6698. NS a.root-servers.nil. +dom6699. NS a.root-servers.nil. +dom6700. NS a.root-servers.nil. +dom6701. NS a.root-servers.nil. +dom6702. NS a.root-servers.nil. +dom6703. NS a.root-servers.nil. +dom6704. NS a.root-servers.nil. +dom6705. NS a.root-servers.nil. +dom6706. NS a.root-servers.nil. +dom6707. NS a.root-servers.nil. +dom6708. NS a.root-servers.nil. +dom6709. NS a.root-servers.nil. +dom6710. NS a.root-servers.nil. +dom6711. NS a.root-servers.nil. +dom6712. NS a.root-servers.nil. +dom6713. NS a.root-servers.nil. +dom6714. NS a.root-servers.nil. +dom6715. NS a.root-servers.nil. +dom6716. NS a.root-servers.nil. +dom6717. NS a.root-servers.nil. +dom6718. NS a.root-servers.nil. +dom6719. NS a.root-servers.nil. +dom6720. NS a.root-servers.nil. +dom6721. NS a.root-servers.nil. +dom6722. NS a.root-servers.nil. +dom6723. NS a.root-servers.nil. +dom6724. NS a.root-servers.nil. +dom6725. NS a.root-servers.nil. +dom6726. NS a.root-servers.nil. +dom6727. NS a.root-servers.nil. +dom6728. NS a.root-servers.nil. +dom6729. NS a.root-servers.nil. +dom6730. NS a.root-servers.nil. +dom6731. NS a.root-servers.nil. +dom6732. NS a.root-servers.nil. +dom6733. NS a.root-servers.nil. +dom6734. NS a.root-servers.nil. +dom6735. NS a.root-servers.nil. +dom6736. NS a.root-servers.nil. +dom6737. NS a.root-servers.nil. +dom6738. NS a.root-servers.nil. +dom6739. NS a.root-servers.nil. +dom6740. NS a.root-servers.nil. +dom6741. NS a.root-servers.nil. +dom6742. NS a.root-servers.nil. +dom6743. NS a.root-servers.nil. +dom6744. NS a.root-servers.nil. +dom6745. NS a.root-servers.nil. +dom6746. NS a.root-servers.nil. +dom6747. NS a.root-servers.nil. +dom6748. NS a.root-servers.nil. +dom6749. NS a.root-servers.nil. +dom6750. NS a.root-servers.nil. +dom6751. NS a.root-servers.nil. +dom6752. NS a.root-servers.nil. +dom6753. NS a.root-servers.nil. +dom6754. NS a.root-servers.nil. +dom6755. NS a.root-servers.nil. +dom6756. NS a.root-servers.nil. +dom6757. NS a.root-servers.nil. +dom6758. NS a.root-servers.nil. +dom6759. NS a.root-servers.nil. +dom6760. NS a.root-servers.nil. +dom6761. NS a.root-servers.nil. +dom6762. NS a.root-servers.nil. +dom6763. NS a.root-servers.nil. +dom6764. NS a.root-servers.nil. +dom6765. NS a.root-servers.nil. +dom6766. NS a.root-servers.nil. +dom6767. NS a.root-servers.nil. +dom6768. NS a.root-servers.nil. +dom6769. NS a.root-servers.nil. +dom6770. NS a.root-servers.nil. +dom6771. NS a.root-servers.nil. +dom6772. NS a.root-servers.nil. +dom6773. NS a.root-servers.nil. +dom6774. NS a.root-servers.nil. +dom6775. NS a.root-servers.nil. +dom6776. NS a.root-servers.nil. +dom6777. NS a.root-servers.nil. +dom6778. NS a.root-servers.nil. +dom6779. NS a.root-servers.nil. +dom6780. NS a.root-servers.nil. +dom6781. NS a.root-servers.nil. +dom6782. NS a.root-servers.nil. +dom6783. NS a.root-servers.nil. +dom6784. NS a.root-servers.nil. +dom6785. NS a.root-servers.nil. +dom6786. NS a.root-servers.nil. +dom6787. NS a.root-servers.nil. +dom6788. NS a.root-servers.nil. +dom6789. NS a.root-servers.nil. +dom6790. NS a.root-servers.nil. +dom6791. NS a.root-servers.nil. +dom6792. NS a.root-servers.nil. +dom6793. NS a.root-servers.nil. +dom6794. NS a.root-servers.nil. +dom6795. NS a.root-servers.nil. +dom6796. NS a.root-servers.nil. +dom6797. NS a.root-servers.nil. +dom6798. NS a.root-servers.nil. +dom6799. NS a.root-servers.nil. +dom6800. NS a.root-servers.nil. +dom6801. NS a.root-servers.nil. +dom6802. NS a.root-servers.nil. +dom6803. NS a.root-servers.nil. +dom6804. NS a.root-servers.nil. +dom6805. NS a.root-servers.nil. +dom6806. NS a.root-servers.nil. +dom6807. NS a.root-servers.nil. +dom6808. NS a.root-servers.nil. +dom6809. NS a.root-servers.nil. +dom6810. NS a.root-servers.nil. +dom6811. NS a.root-servers.nil. +dom6812. NS a.root-servers.nil. +dom6813. NS a.root-servers.nil. +dom6814. NS a.root-servers.nil. +dom6815. NS a.root-servers.nil. +dom6816. NS a.root-servers.nil. +dom6817. NS a.root-servers.nil. +dom6818. NS a.root-servers.nil. +dom6819. NS a.root-servers.nil. +dom6820. NS a.root-servers.nil. +dom6821. NS a.root-servers.nil. +dom6822. NS a.root-servers.nil. +dom6823. NS a.root-servers.nil. +dom6824. NS a.root-servers.nil. +dom6825. NS a.root-servers.nil. +dom6826. NS a.root-servers.nil. +dom6827. NS a.root-servers.nil. +dom6828. NS a.root-servers.nil. +dom6829. NS a.root-servers.nil. +dom6830. NS a.root-servers.nil. +dom6831. NS a.root-servers.nil. +dom6832. NS a.root-servers.nil. +dom6833. NS a.root-servers.nil. +dom6834. NS a.root-servers.nil. +dom6835. NS a.root-servers.nil. +dom6836. NS a.root-servers.nil. +dom6837. NS a.root-servers.nil. +dom6838. NS a.root-servers.nil. +dom6839. NS a.root-servers.nil. +dom6840. NS a.root-servers.nil. +dom6841. NS a.root-servers.nil. +dom6842. NS a.root-servers.nil. +dom6843. NS a.root-servers.nil. +dom6844. NS a.root-servers.nil. +dom6845. NS a.root-servers.nil. +dom6846. NS a.root-servers.nil. +dom6847. NS a.root-servers.nil. +dom6848. NS a.root-servers.nil. +dom6849. NS a.root-servers.nil. +dom6850. NS a.root-servers.nil. +dom6851. NS a.root-servers.nil. +dom6852. NS a.root-servers.nil. +dom6853. NS a.root-servers.nil. +dom6854. NS a.root-servers.nil. +dom6855. NS a.root-servers.nil. +dom6856. NS a.root-servers.nil. +dom6857. NS a.root-servers.nil. +dom6858. NS a.root-servers.nil. +dom6859. NS a.root-servers.nil. +dom6860. NS a.root-servers.nil. +dom6861. NS a.root-servers.nil. +dom6862. NS a.root-servers.nil. +dom6863. NS a.root-servers.nil. +dom6864. NS a.root-servers.nil. +dom6865. NS a.root-servers.nil. +dom6866. NS a.root-servers.nil. +dom6867. NS a.root-servers.nil. +dom6868. NS a.root-servers.nil. +dom6869. NS a.root-servers.nil. +dom6870. NS a.root-servers.nil. +dom6871. NS a.root-servers.nil. +dom6872. NS a.root-servers.nil. +dom6873. NS a.root-servers.nil. +dom6874. NS a.root-servers.nil. +dom6875. NS a.root-servers.nil. +dom6876. NS a.root-servers.nil. +dom6877. NS a.root-servers.nil. +dom6878. NS a.root-servers.nil. +dom6879. NS a.root-servers.nil. +dom6880. NS a.root-servers.nil. +dom6881. NS a.root-servers.nil. +dom6882. NS a.root-servers.nil. +dom6883. NS a.root-servers.nil. +dom6884. NS a.root-servers.nil. +dom6885. NS a.root-servers.nil. +dom6886. NS a.root-servers.nil. +dom6887. NS a.root-servers.nil. +dom6888. NS a.root-servers.nil. +dom6889. NS a.root-servers.nil. +dom6890. NS a.root-servers.nil. +dom6891. NS a.root-servers.nil. +dom6892. NS a.root-servers.nil. +dom6893. NS a.root-servers.nil. +dom6894. NS a.root-servers.nil. +dom6895. NS a.root-servers.nil. +dom6896. NS a.root-servers.nil. +dom6897. NS a.root-servers.nil. +dom6898. NS a.root-servers.nil. +dom6899. NS a.root-servers.nil. +dom6900. NS a.root-servers.nil. +dom6901. NS a.root-servers.nil. +dom6902. NS a.root-servers.nil. +dom6903. NS a.root-servers.nil. +dom6904. NS a.root-servers.nil. +dom6905. NS a.root-servers.nil. +dom6906. NS a.root-servers.nil. +dom6907. NS a.root-servers.nil. +dom6908. NS a.root-servers.nil. +dom6909. NS a.root-servers.nil. +dom6910. NS a.root-servers.nil. +dom6911. NS a.root-servers.nil. +dom6912. NS a.root-servers.nil. +dom6913. NS a.root-servers.nil. +dom6914. NS a.root-servers.nil. +dom6915. NS a.root-servers.nil. +dom6916. NS a.root-servers.nil. +dom6917. NS a.root-servers.nil. +dom6918. NS a.root-servers.nil. +dom6919. NS a.root-servers.nil. +dom6920. NS a.root-servers.nil. +dom6921. NS a.root-servers.nil. +dom6922. NS a.root-servers.nil. +dom6923. NS a.root-servers.nil. +dom6924. NS a.root-servers.nil. +dom6925. NS a.root-servers.nil. +dom6926. NS a.root-servers.nil. +dom6927. NS a.root-servers.nil. +dom6928. NS a.root-servers.nil. +dom6929. NS a.root-servers.nil. +dom6930. NS a.root-servers.nil. +dom6931. NS a.root-servers.nil. +dom6932. NS a.root-servers.nil. +dom6933. NS a.root-servers.nil. +dom6934. NS a.root-servers.nil. +dom6935. NS a.root-servers.nil. +dom6936. NS a.root-servers.nil. +dom6937. NS a.root-servers.nil. +dom6938. NS a.root-servers.nil. +dom6939. NS a.root-servers.nil. +dom6940. NS a.root-servers.nil. +dom6941. NS a.root-servers.nil. +dom6942. NS a.root-servers.nil. +dom6943. NS a.root-servers.nil. +dom6944. NS a.root-servers.nil. +dom6945. NS a.root-servers.nil. +dom6946. NS a.root-servers.nil. +dom6947. NS a.root-servers.nil. +dom6948. NS a.root-servers.nil. +dom6949. NS a.root-servers.nil. +dom6950. NS a.root-servers.nil. +dom6951. NS a.root-servers.nil. +dom6952. NS a.root-servers.nil. +dom6953. NS a.root-servers.nil. +dom6954. NS a.root-servers.nil. +dom6955. NS a.root-servers.nil. +dom6956. NS a.root-servers.nil. +dom6957. NS a.root-servers.nil. +dom6958. NS a.root-servers.nil. +dom6959. NS a.root-servers.nil. +dom6960. NS a.root-servers.nil. +dom6961. NS a.root-servers.nil. +dom6962. NS a.root-servers.nil. +dom6963. NS a.root-servers.nil. +dom6964. NS a.root-servers.nil. +dom6965. NS a.root-servers.nil. +dom6966. NS a.root-servers.nil. +dom6967. NS a.root-servers.nil. +dom6968. NS a.root-servers.nil. +dom6969. NS a.root-servers.nil. +dom6970. NS a.root-servers.nil. +dom6971. NS a.root-servers.nil. +dom6972. NS a.root-servers.nil. +dom6973. NS a.root-servers.nil. +dom6974. NS a.root-servers.nil. +dom6975. NS a.root-servers.nil. +dom6976. NS a.root-servers.nil. +dom6977. NS a.root-servers.nil. +dom6978. NS a.root-servers.nil. +dom6979. NS a.root-servers.nil. +dom6980. NS a.root-servers.nil. +dom6981. NS a.root-servers.nil. +dom6982. NS a.root-servers.nil. +dom6983. NS a.root-servers.nil. +dom6984. NS a.root-servers.nil. +dom6985. NS a.root-servers.nil. +dom6986. NS a.root-servers.nil. +dom6987. NS a.root-servers.nil. +dom6988. NS a.root-servers.nil. +dom6989. NS a.root-servers.nil. +dom6990. NS a.root-servers.nil. +dom6991. NS a.root-servers.nil. +dom6992. NS a.root-servers.nil. +dom6993. NS a.root-servers.nil. +dom6994. NS a.root-servers.nil. +dom6995. NS a.root-servers.nil. +dom6996. NS a.root-servers.nil. +dom6997. NS a.root-servers.nil. +dom6998. NS a.root-servers.nil. +dom6999. NS a.root-servers.nil. +dom7000. NS a.root-servers.nil. +dom7001. NS a.root-servers.nil. +dom7002. NS a.root-servers.nil. +dom7003. NS a.root-servers.nil. +dom7004. NS a.root-servers.nil. +dom7005. NS a.root-servers.nil. +dom7006. NS a.root-servers.nil. +dom7007. NS a.root-servers.nil. +dom7008. NS a.root-servers.nil. +dom7009. NS a.root-servers.nil. +dom7010. NS a.root-servers.nil. +dom7011. NS a.root-servers.nil. +dom7012. NS a.root-servers.nil. +dom7013. NS a.root-servers.nil. +dom7014. NS a.root-servers.nil. +dom7015. NS a.root-servers.nil. +dom7016. NS a.root-servers.nil. +dom7017. NS a.root-servers.nil. +dom7018. NS a.root-servers.nil. +dom7019. NS a.root-servers.nil. +dom7020. NS a.root-servers.nil. +dom7021. NS a.root-servers.nil. +dom7022. NS a.root-servers.nil. +dom7023. NS a.root-servers.nil. +dom7024. NS a.root-servers.nil. +dom7025. NS a.root-servers.nil. +dom7026. NS a.root-servers.nil. +dom7027. NS a.root-servers.nil. +dom7028. NS a.root-servers.nil. +dom7029. NS a.root-servers.nil. +dom7030. NS a.root-servers.nil. +dom7031. NS a.root-servers.nil. +dom7032. NS a.root-servers.nil. +dom7033. NS a.root-servers.nil. +dom7034. NS a.root-servers.nil. +dom7035. NS a.root-servers.nil. +dom7036. NS a.root-servers.nil. +dom7037. NS a.root-servers.nil. +dom7038. NS a.root-servers.nil. +dom7039. NS a.root-servers.nil. +dom7040. NS a.root-servers.nil. +dom7041. NS a.root-servers.nil. +dom7042. NS a.root-servers.nil. +dom7043. NS a.root-servers.nil. +dom7044. NS a.root-servers.nil. +dom7045. NS a.root-servers.nil. +dom7046. NS a.root-servers.nil. +dom7047. NS a.root-servers.nil. +dom7048. NS a.root-servers.nil. +dom7049. NS a.root-servers.nil. +dom7050. NS a.root-servers.nil. +dom7051. NS a.root-servers.nil. +dom7052. NS a.root-servers.nil. +dom7053. NS a.root-servers.nil. +dom7054. NS a.root-servers.nil. +dom7055. NS a.root-servers.nil. +dom7056. NS a.root-servers.nil. +dom7057. NS a.root-servers.nil. +dom7058. NS a.root-servers.nil. +dom7059. NS a.root-servers.nil. +dom7060. NS a.root-servers.nil. +dom7061. NS a.root-servers.nil. +dom7062. NS a.root-servers.nil. +dom7063. NS a.root-servers.nil. +dom7064. NS a.root-servers.nil. +dom7065. NS a.root-servers.nil. +dom7066. NS a.root-servers.nil. +dom7067. NS a.root-servers.nil. +dom7068. NS a.root-servers.nil. +dom7069. NS a.root-servers.nil. +dom7070. NS a.root-servers.nil. +dom7071. NS a.root-servers.nil. +dom7072. NS a.root-servers.nil. +dom7073. NS a.root-servers.nil. +dom7074. NS a.root-servers.nil. +dom7075. NS a.root-servers.nil. +dom7076. NS a.root-servers.nil. +dom7077. NS a.root-servers.nil. +dom7078. NS a.root-servers.nil. +dom7079. NS a.root-servers.nil. +dom7080. NS a.root-servers.nil. +dom7081. NS a.root-servers.nil. +dom7082. NS a.root-servers.nil. +dom7083. NS a.root-servers.nil. +dom7084. NS a.root-servers.nil. +dom7085. NS a.root-servers.nil. +dom7086. NS a.root-servers.nil. +dom7087. NS a.root-servers.nil. +dom7088. NS a.root-servers.nil. +dom7089. NS a.root-servers.nil. +dom7090. NS a.root-servers.nil. +dom7091. NS a.root-servers.nil. +dom7092. NS a.root-servers.nil. +dom7093. NS a.root-servers.nil. +dom7094. NS a.root-servers.nil. +dom7095. NS a.root-servers.nil. +dom7096. NS a.root-servers.nil. +dom7097. NS a.root-servers.nil. +dom7098. NS a.root-servers.nil. +dom7099. NS a.root-servers.nil. +dom7100. NS a.root-servers.nil. +dom7101. NS a.root-servers.nil. +dom7102. NS a.root-servers.nil. +dom7103. NS a.root-servers.nil. +dom7104. NS a.root-servers.nil. +dom7105. NS a.root-servers.nil. +dom7106. NS a.root-servers.nil. +dom7107. NS a.root-servers.nil. +dom7108. NS a.root-servers.nil. +dom7109. NS a.root-servers.nil. +dom7110. NS a.root-servers.nil. +dom7111. NS a.root-servers.nil. +dom7112. NS a.root-servers.nil. +dom7113. NS a.root-servers.nil. +dom7114. NS a.root-servers.nil. +dom7115. NS a.root-servers.nil. +dom7116. NS a.root-servers.nil. +dom7117. NS a.root-servers.nil. +dom7118. NS a.root-servers.nil. +dom7119. NS a.root-servers.nil. +dom7120. NS a.root-servers.nil. +dom7121. NS a.root-servers.nil. +dom7122. NS a.root-servers.nil. +dom7123. NS a.root-servers.nil. +dom7124. NS a.root-servers.nil. +dom7125. NS a.root-servers.nil. +dom7126. NS a.root-servers.nil. +dom7127. NS a.root-servers.nil. +dom7128. NS a.root-servers.nil. +dom7129. NS a.root-servers.nil. +dom7130. NS a.root-servers.nil. +dom7131. NS a.root-servers.nil. +dom7132. NS a.root-servers.nil. +dom7133. NS a.root-servers.nil. +dom7134. NS a.root-servers.nil. +dom7135. NS a.root-servers.nil. +dom7136. NS a.root-servers.nil. +dom7137. NS a.root-servers.nil. +dom7138. NS a.root-servers.nil. +dom7139. NS a.root-servers.nil. +dom7140. NS a.root-servers.nil. +dom7141. NS a.root-servers.nil. +dom7142. NS a.root-servers.nil. +dom7143. NS a.root-servers.nil. +dom7144. NS a.root-servers.nil. +dom7145. NS a.root-servers.nil. +dom7146. NS a.root-servers.nil. +dom7147. NS a.root-servers.nil. +dom7148. NS a.root-servers.nil. +dom7149. NS a.root-servers.nil. +dom7150. NS a.root-servers.nil. +dom7151. NS a.root-servers.nil. +dom7152. NS a.root-servers.nil. +dom7153. NS a.root-servers.nil. +dom7154. NS a.root-servers.nil. +dom7155. NS a.root-servers.nil. +dom7156. NS a.root-servers.nil. +dom7157. NS a.root-servers.nil. +dom7158. NS a.root-servers.nil. +dom7159. NS a.root-servers.nil. +dom7160. NS a.root-servers.nil. +dom7161. NS a.root-servers.nil. +dom7162. NS a.root-servers.nil. +dom7163. NS a.root-servers.nil. +dom7164. NS a.root-servers.nil. +dom7165. NS a.root-servers.nil. +dom7166. NS a.root-servers.nil. +dom7167. NS a.root-servers.nil. +dom7168. NS a.root-servers.nil. +dom7169. NS a.root-servers.nil. +dom7170. NS a.root-servers.nil. +dom7171. NS a.root-servers.nil. +dom7172. NS a.root-servers.nil. +dom7173. NS a.root-servers.nil. +dom7174. NS a.root-servers.nil. +dom7175. NS a.root-servers.nil. +dom7176. NS a.root-servers.nil. +dom7177. NS a.root-servers.nil. +dom7178. NS a.root-servers.nil. +dom7179. NS a.root-servers.nil. +dom7180. NS a.root-servers.nil. +dom7181. NS a.root-servers.nil. +dom7182. NS a.root-servers.nil. +dom7183. NS a.root-servers.nil. +dom7184. NS a.root-servers.nil. +dom7185. NS a.root-servers.nil. +dom7186. NS a.root-servers.nil. +dom7187. NS a.root-servers.nil. +dom7188. NS a.root-servers.nil. +dom7189. NS a.root-servers.nil. +dom7190. NS a.root-servers.nil. +dom7191. NS a.root-servers.nil. +dom7192. NS a.root-servers.nil. +dom7193. NS a.root-servers.nil. +dom7194. NS a.root-servers.nil. +dom7195. NS a.root-servers.nil. +dom7196. NS a.root-servers.nil. +dom7197. NS a.root-servers.nil. +dom7198. NS a.root-servers.nil. +dom7199. NS a.root-servers.nil. +dom7200. NS a.root-servers.nil. +dom7201. NS a.root-servers.nil. +dom7202. NS a.root-servers.nil. +dom7203. NS a.root-servers.nil. +dom7204. NS a.root-servers.nil. +dom7205. NS a.root-servers.nil. +dom7206. NS a.root-servers.nil. +dom7207. NS a.root-servers.nil. +dom7208. NS a.root-servers.nil. +dom7209. NS a.root-servers.nil. +dom7210. NS a.root-servers.nil. +dom7211. NS a.root-servers.nil. +dom7212. NS a.root-servers.nil. +dom7213. NS a.root-servers.nil. +dom7214. NS a.root-servers.nil. +dom7215. NS a.root-servers.nil. +dom7216. NS a.root-servers.nil. +dom7217. NS a.root-servers.nil. +dom7218. NS a.root-servers.nil. +dom7219. NS a.root-servers.nil. +dom7220. NS a.root-servers.nil. +dom7221. NS a.root-servers.nil. +dom7222. NS a.root-servers.nil. +dom7223. NS a.root-servers.nil. +dom7224. NS a.root-servers.nil. +dom7225. NS a.root-servers.nil. +dom7226. NS a.root-servers.nil. +dom7227. NS a.root-servers.nil. +dom7228. NS a.root-servers.nil. +dom7229. NS a.root-servers.nil. +dom7230. NS a.root-servers.nil. +dom7231. NS a.root-servers.nil. +dom7232. NS a.root-servers.nil. +dom7233. NS a.root-servers.nil. +dom7234. NS a.root-servers.nil. +dom7235. NS a.root-servers.nil. +dom7236. NS a.root-servers.nil. +dom7237. NS a.root-servers.nil. +dom7238. NS a.root-servers.nil. +dom7239. NS a.root-servers.nil. +dom7240. NS a.root-servers.nil. +dom7241. NS a.root-servers.nil. +dom7242. NS a.root-servers.nil. +dom7243. NS a.root-servers.nil. +dom7244. NS a.root-servers.nil. +dom7245. NS a.root-servers.nil. +dom7246. NS a.root-servers.nil. +dom7247. NS a.root-servers.nil. +dom7248. NS a.root-servers.nil. +dom7249. NS a.root-servers.nil. +dom7250. NS a.root-servers.nil. +dom7251. NS a.root-servers.nil. +dom7252. NS a.root-servers.nil. +dom7253. NS a.root-servers.nil. +dom7254. NS a.root-servers.nil. +dom7255. NS a.root-servers.nil. +dom7256. NS a.root-servers.nil. +dom7257. NS a.root-servers.nil. +dom7258. NS a.root-servers.nil. +dom7259. NS a.root-servers.nil. +dom7260. NS a.root-servers.nil. +dom7261. NS a.root-servers.nil. +dom7262. NS a.root-servers.nil. +dom7263. NS a.root-servers.nil. +dom7264. NS a.root-servers.nil. +dom7265. NS a.root-servers.nil. +dom7266. NS a.root-servers.nil. +dom7267. NS a.root-servers.nil. +dom7268. NS a.root-servers.nil. +dom7269. NS a.root-servers.nil. +dom7270. NS a.root-servers.nil. +dom7271. NS a.root-servers.nil. +dom7272. NS a.root-servers.nil. +dom7273. NS a.root-servers.nil. +dom7274. NS a.root-servers.nil. +dom7275. NS a.root-servers.nil. +dom7276. NS a.root-servers.nil. +dom7277. NS a.root-servers.nil. +dom7278. NS a.root-servers.nil. +dom7279. NS a.root-servers.nil. +dom7280. NS a.root-servers.nil. +dom7281. NS a.root-servers.nil. +dom7282. NS a.root-servers.nil. +dom7283. NS a.root-servers.nil. +dom7284. NS a.root-servers.nil. +dom7285. NS a.root-servers.nil. +dom7286. NS a.root-servers.nil. +dom7287. NS a.root-servers.nil. +dom7288. NS a.root-servers.nil. +dom7289. NS a.root-servers.nil. +dom7290. NS a.root-servers.nil. +dom7291. NS a.root-servers.nil. +dom7292. NS a.root-servers.nil. +dom7293. NS a.root-servers.nil. +dom7294. NS a.root-servers.nil. +dom7295. NS a.root-servers.nil. +dom7296. NS a.root-servers.nil. +dom7297. NS a.root-servers.nil. +dom7298. NS a.root-servers.nil. +dom7299. NS a.root-servers.nil. +dom7300. NS a.root-servers.nil. +dom7301. NS a.root-servers.nil. +dom7302. NS a.root-servers.nil. +dom7303. NS a.root-servers.nil. +dom7304. NS a.root-servers.nil. +dom7305. NS a.root-servers.nil. +dom7306. NS a.root-servers.nil. +dom7307. NS a.root-servers.nil. +dom7308. NS a.root-servers.nil. +dom7309. NS a.root-servers.nil. +dom7310. NS a.root-servers.nil. +dom7311. NS a.root-servers.nil. +dom7312. NS a.root-servers.nil. +dom7313. NS a.root-servers.nil. +dom7314. NS a.root-servers.nil. +dom7315. NS a.root-servers.nil. +dom7316. NS a.root-servers.nil. +dom7317. NS a.root-servers.nil. +dom7318. NS a.root-servers.nil. +dom7319. NS a.root-servers.nil. +dom7320. NS a.root-servers.nil. +dom7321. NS a.root-servers.nil. +dom7322. NS a.root-servers.nil. +dom7323. NS a.root-servers.nil. +dom7324. NS a.root-servers.nil. +dom7325. NS a.root-servers.nil. +dom7326. NS a.root-servers.nil. +dom7327. NS a.root-servers.nil. +dom7328. NS a.root-servers.nil. +dom7329. NS a.root-servers.nil. +dom7330. NS a.root-servers.nil. +dom7331. NS a.root-servers.nil. +dom7332. NS a.root-servers.nil. +dom7333. NS a.root-servers.nil. +dom7334. NS a.root-servers.nil. +dom7335. NS a.root-servers.nil. +dom7336. NS a.root-servers.nil. +dom7337. NS a.root-servers.nil. +dom7338. NS a.root-servers.nil. +dom7339. NS a.root-servers.nil. +dom7340. NS a.root-servers.nil. +dom7341. NS a.root-servers.nil. +dom7342. NS a.root-servers.nil. +dom7343. NS a.root-servers.nil. +dom7344. NS a.root-servers.nil. +dom7345. NS a.root-servers.nil. +dom7346. NS a.root-servers.nil. +dom7347. NS a.root-servers.nil. +dom7348. NS a.root-servers.nil. +dom7349. NS a.root-servers.nil. +dom7350. NS a.root-servers.nil. +dom7351. NS a.root-servers.nil. +dom7352. NS a.root-servers.nil. +dom7353. NS a.root-servers.nil. +dom7354. NS a.root-servers.nil. +dom7355. NS a.root-servers.nil. +dom7356. NS a.root-servers.nil. +dom7357. NS a.root-servers.nil. +dom7358. NS a.root-servers.nil. +dom7359. NS a.root-servers.nil. +dom7360. NS a.root-servers.nil. +dom7361. NS a.root-servers.nil. +dom7362. NS a.root-servers.nil. +dom7363. NS a.root-servers.nil. +dom7364. NS a.root-servers.nil. +dom7365. NS a.root-servers.nil. +dom7366. NS a.root-servers.nil. +dom7367. NS a.root-servers.nil. +dom7368. NS a.root-servers.nil. +dom7369. NS a.root-servers.nil. +dom7370. NS a.root-servers.nil. +dom7371. NS a.root-servers.nil. +dom7372. NS a.root-servers.nil. +dom7373. NS a.root-servers.nil. +dom7374. NS a.root-servers.nil. +dom7375. NS a.root-servers.nil. +dom7376. NS a.root-servers.nil. +dom7377. NS a.root-servers.nil. +dom7378. NS a.root-servers.nil. +dom7379. NS a.root-servers.nil. +dom7380. NS a.root-servers.nil. +dom7381. NS a.root-servers.nil. +dom7382. NS a.root-servers.nil. +dom7383. NS a.root-servers.nil. +dom7384. NS a.root-servers.nil. +dom7385. NS a.root-servers.nil. +dom7386. NS a.root-servers.nil. +dom7387. NS a.root-servers.nil. +dom7388. NS a.root-servers.nil. +dom7389. NS a.root-servers.nil. +dom7390. NS a.root-servers.nil. +dom7391. NS a.root-servers.nil. +dom7392. NS a.root-servers.nil. +dom7393. NS a.root-servers.nil. +dom7394. NS a.root-servers.nil. +dom7395. NS a.root-servers.nil. +dom7396. NS a.root-servers.nil. +dom7397. NS a.root-servers.nil. +dom7398. NS a.root-servers.nil. +dom7399. NS a.root-servers.nil. +dom7400. NS a.root-servers.nil. +dom7401. NS a.root-servers.nil. +dom7402. NS a.root-servers.nil. +dom7403. NS a.root-servers.nil. +dom7404. NS a.root-servers.nil. +dom7405. NS a.root-servers.nil. +dom7406. NS a.root-servers.nil. +dom7407. NS a.root-servers.nil. +dom7408. NS a.root-servers.nil. +dom7409. NS a.root-servers.nil. +dom7410. NS a.root-servers.nil. +dom7411. NS a.root-servers.nil. +dom7412. NS a.root-servers.nil. +dom7413. NS a.root-servers.nil. +dom7414. NS a.root-servers.nil. +dom7415. NS a.root-servers.nil. +dom7416. NS a.root-servers.nil. +dom7417. NS a.root-servers.nil. +dom7418. NS a.root-servers.nil. +dom7419. NS a.root-servers.nil. +dom7420. NS a.root-servers.nil. +dom7421. NS a.root-servers.nil. +dom7422. NS a.root-servers.nil. +dom7423. NS a.root-servers.nil. +dom7424. NS a.root-servers.nil. +dom7425. NS a.root-servers.nil. +dom7426. NS a.root-servers.nil. +dom7427. NS a.root-servers.nil. +dom7428. NS a.root-servers.nil. +dom7429. NS a.root-servers.nil. +dom7430. NS a.root-servers.nil. +dom7431. NS a.root-servers.nil. +dom7432. NS a.root-servers.nil. +dom7433. NS a.root-servers.nil. +dom7434. NS a.root-servers.nil. +dom7435. NS a.root-servers.nil. +dom7436. NS a.root-servers.nil. +dom7437. NS a.root-servers.nil. +dom7438. NS a.root-servers.nil. +dom7439. NS a.root-servers.nil. +dom7440. NS a.root-servers.nil. +dom7441. NS a.root-servers.nil. +dom7442. NS a.root-servers.nil. +dom7443. NS a.root-servers.nil. +dom7444. NS a.root-servers.nil. +dom7445. NS a.root-servers.nil. +dom7446. NS a.root-servers.nil. +dom7447. NS a.root-servers.nil. +dom7448. NS a.root-servers.nil. +dom7449. NS a.root-servers.nil. +dom7450. NS a.root-servers.nil. +dom7451. NS a.root-servers.nil. +dom7452. NS a.root-servers.nil. +dom7453. NS a.root-servers.nil. +dom7454. NS a.root-servers.nil. +dom7455. NS a.root-servers.nil. +dom7456. NS a.root-servers.nil. +dom7457. NS a.root-servers.nil. +dom7458. NS a.root-servers.nil. +dom7459. NS a.root-servers.nil. +dom7460. NS a.root-servers.nil. +dom7461. NS a.root-servers.nil. +dom7462. NS a.root-servers.nil. +dom7463. NS a.root-servers.nil. +dom7464. NS a.root-servers.nil. +dom7465. NS a.root-servers.nil. +dom7466. NS a.root-servers.nil. +dom7467. NS a.root-servers.nil. +dom7468. NS a.root-servers.nil. +dom7469. NS a.root-servers.nil. +dom7470. NS a.root-servers.nil. +dom7471. NS a.root-servers.nil. +dom7472. NS a.root-servers.nil. +dom7473. NS a.root-servers.nil. +dom7474. NS a.root-servers.nil. +dom7475. NS a.root-servers.nil. +dom7476. NS a.root-servers.nil. +dom7477. NS a.root-servers.nil. +dom7478. NS a.root-servers.nil. +dom7479. NS a.root-servers.nil. +dom7480. NS a.root-servers.nil. +dom7481. NS a.root-servers.nil. +dom7482. NS a.root-servers.nil. +dom7483. NS a.root-servers.nil. +dom7484. NS a.root-servers.nil. +dom7485. NS a.root-servers.nil. +dom7486. NS a.root-servers.nil. +dom7487. NS a.root-servers.nil. +dom7488. NS a.root-servers.nil. +dom7489. NS a.root-servers.nil. +dom7490. NS a.root-servers.nil. +dom7491. NS a.root-servers.nil. +dom7492. NS a.root-servers.nil. +dom7493. NS a.root-servers.nil. +dom7494. NS a.root-servers.nil. +dom7495. NS a.root-servers.nil. +dom7496. NS a.root-servers.nil. +dom7497. NS a.root-servers.nil. +dom7498. NS a.root-servers.nil. +dom7499. NS a.root-servers.nil. +dom7500. NS a.root-servers.nil. +dom7501. NS a.root-servers.nil. +dom7502. NS a.root-servers.nil. +dom7503. NS a.root-servers.nil. +dom7504. NS a.root-servers.nil. +dom7505. NS a.root-servers.nil. +dom7506. NS a.root-servers.nil. +dom7507. NS a.root-servers.nil. +dom7508. NS a.root-servers.nil. +dom7509. NS a.root-servers.nil. +dom7510. NS a.root-servers.nil. +dom7511. NS a.root-servers.nil. +dom7512. NS a.root-servers.nil. +dom7513. NS a.root-servers.nil. +dom7514. NS a.root-servers.nil. +dom7515. NS a.root-servers.nil. +dom7516. NS a.root-servers.nil. +dom7517. NS a.root-servers.nil. +dom7518. NS a.root-servers.nil. +dom7519. NS a.root-servers.nil. +dom7520. NS a.root-servers.nil. +dom7521. NS a.root-servers.nil. +dom7522. NS a.root-servers.nil. +dom7523. NS a.root-servers.nil. +dom7524. NS a.root-servers.nil. +dom7525. NS a.root-servers.nil. +dom7526. NS a.root-servers.nil. +dom7527. NS a.root-servers.nil. +dom7528. NS a.root-servers.nil. +dom7529. NS a.root-servers.nil. +dom7530. NS a.root-servers.nil. +dom7531. NS a.root-servers.nil. +dom7532. NS a.root-servers.nil. +dom7533. NS a.root-servers.nil. +dom7534. NS a.root-servers.nil. +dom7535. NS a.root-servers.nil. +dom7536. NS a.root-servers.nil. +dom7537. NS a.root-servers.nil. +dom7538. NS a.root-servers.nil. +dom7539. NS a.root-servers.nil. +dom7540. NS a.root-servers.nil. +dom7541. NS a.root-servers.nil. +dom7542. NS a.root-servers.nil. +dom7543. NS a.root-servers.nil. +dom7544. NS a.root-servers.nil. +dom7545. NS a.root-servers.nil. +dom7546. NS a.root-servers.nil. +dom7547. NS a.root-servers.nil. +dom7548. NS a.root-servers.nil. +dom7549. NS a.root-servers.nil. +dom7550. NS a.root-servers.nil. +dom7551. NS a.root-servers.nil. +dom7552. NS a.root-servers.nil. +dom7553. NS a.root-servers.nil. +dom7554. NS a.root-servers.nil. +dom7555. NS a.root-servers.nil. +dom7556. NS a.root-servers.nil. +dom7557. NS a.root-servers.nil. +dom7558. NS a.root-servers.nil. +dom7559. NS a.root-servers.nil. +dom7560. NS a.root-servers.nil. +dom7561. NS a.root-servers.nil. +dom7562. NS a.root-servers.nil. +dom7563. NS a.root-servers.nil. +dom7564. NS a.root-servers.nil. +dom7565. NS a.root-servers.nil. +dom7566. NS a.root-servers.nil. +dom7567. NS a.root-servers.nil. +dom7568. NS a.root-servers.nil. +dom7569. NS a.root-servers.nil. +dom7570. NS a.root-servers.nil. +dom7571. NS a.root-servers.nil. +dom7572. NS a.root-servers.nil. +dom7573. NS a.root-servers.nil. +dom7574. NS a.root-servers.nil. +dom7575. NS a.root-servers.nil. +dom7576. NS a.root-servers.nil. +dom7577. NS a.root-servers.nil. +dom7578. NS a.root-servers.nil. +dom7579. NS a.root-servers.nil. +dom7580. NS a.root-servers.nil. +dom7581. NS a.root-servers.nil. +dom7582. NS a.root-servers.nil. +dom7583. NS a.root-servers.nil. +dom7584. NS a.root-servers.nil. +dom7585. NS a.root-servers.nil. +dom7586. NS a.root-servers.nil. +dom7587. NS a.root-servers.nil. +dom7588. NS a.root-servers.nil. +dom7589. NS a.root-servers.nil. +dom7590. NS a.root-servers.nil. +dom7591. NS a.root-servers.nil. +dom7592. NS a.root-servers.nil. +dom7593. NS a.root-servers.nil. +dom7594. NS a.root-servers.nil. +dom7595. NS a.root-servers.nil. +dom7596. NS a.root-servers.nil. +dom7597. NS a.root-servers.nil. +dom7598. NS a.root-servers.nil. +dom7599. NS a.root-servers.nil. +dom7600. NS a.root-servers.nil. +dom7601. NS a.root-servers.nil. +dom7602. NS a.root-servers.nil. +dom7603. NS a.root-servers.nil. +dom7604. NS a.root-servers.nil. +dom7605. NS a.root-servers.nil. +dom7606. NS a.root-servers.nil. +dom7607. NS a.root-servers.nil. +dom7608. NS a.root-servers.nil. +dom7609. NS a.root-servers.nil. +dom7610. NS a.root-servers.nil. +dom7611. NS a.root-servers.nil. +dom7612. NS a.root-servers.nil. +dom7613. NS a.root-servers.nil. +dom7614. NS a.root-servers.nil. +dom7615. NS a.root-servers.nil. +dom7616. NS a.root-servers.nil. +dom7617. NS a.root-servers.nil. +dom7618. NS a.root-servers.nil. +dom7619. NS a.root-servers.nil. +dom7620. NS a.root-servers.nil. +dom7621. NS a.root-servers.nil. +dom7622. NS a.root-servers.nil. +dom7623. NS a.root-servers.nil. +dom7624. NS a.root-servers.nil. +dom7625. NS a.root-servers.nil. +dom7626. NS a.root-servers.nil. +dom7627. NS a.root-servers.nil. +dom7628. NS a.root-servers.nil. +dom7629. NS a.root-servers.nil. +dom7630. NS a.root-servers.nil. +dom7631. NS a.root-servers.nil. +dom7632. NS a.root-servers.nil. +dom7633. NS a.root-servers.nil. +dom7634. NS a.root-servers.nil. +dom7635. NS a.root-servers.nil. +dom7636. NS a.root-servers.nil. +dom7637. NS a.root-servers.nil. +dom7638. NS a.root-servers.nil. +dom7639. NS a.root-servers.nil. +dom7640. NS a.root-servers.nil. +dom7641. NS a.root-servers.nil. +dom7642. NS a.root-servers.nil. +dom7643. NS a.root-servers.nil. +dom7644. NS a.root-servers.nil. +dom7645. NS a.root-servers.nil. +dom7646. NS a.root-servers.nil. +dom7647. NS a.root-servers.nil. +dom7648. NS a.root-servers.nil. +dom7649. NS a.root-servers.nil. +dom7650. NS a.root-servers.nil. +dom7651. NS a.root-servers.nil. +dom7652. NS a.root-servers.nil. +dom7653. NS a.root-servers.nil. +dom7654. NS a.root-servers.nil. +dom7655. NS a.root-servers.nil. +dom7656. NS a.root-servers.nil. +dom7657. NS a.root-servers.nil. +dom7658. NS a.root-servers.nil. +dom7659. NS a.root-servers.nil. +dom7660. NS a.root-servers.nil. +dom7661. NS a.root-servers.nil. +dom7662. NS a.root-servers.nil. +dom7663. NS a.root-servers.nil. +dom7664. NS a.root-servers.nil. +dom7665. NS a.root-servers.nil. +dom7666. NS a.root-servers.nil. +dom7667. NS a.root-servers.nil. +dom7668. NS a.root-servers.nil. +dom7669. NS a.root-servers.nil. +dom7670. NS a.root-servers.nil. +dom7671. NS a.root-servers.nil. +dom7672. NS a.root-servers.nil. +dom7673. NS a.root-servers.nil. +dom7674. NS a.root-servers.nil. +dom7675. NS a.root-servers.nil. +dom7676. NS a.root-servers.nil. +dom7677. NS a.root-servers.nil. +dom7678. NS a.root-servers.nil. +dom7679. NS a.root-servers.nil. +dom7680. NS a.root-servers.nil. +dom7681. NS a.root-servers.nil. +dom7682. NS a.root-servers.nil. +dom7683. NS a.root-servers.nil. +dom7684. NS a.root-servers.nil. +dom7685. NS a.root-servers.nil. +dom7686. NS a.root-servers.nil. +dom7687. NS a.root-servers.nil. +dom7688. NS a.root-servers.nil. +dom7689. NS a.root-servers.nil. +dom7690. NS a.root-servers.nil. +dom7691. NS a.root-servers.nil. +dom7692. NS a.root-servers.nil. +dom7693. NS a.root-servers.nil. +dom7694. NS a.root-servers.nil. +dom7695. NS a.root-servers.nil. +dom7696. NS a.root-servers.nil. +dom7697. NS a.root-servers.nil. +dom7698. NS a.root-servers.nil. +dom7699. NS a.root-servers.nil. +dom7700. NS a.root-servers.nil. +dom7701. NS a.root-servers.nil. +dom7702. NS a.root-servers.nil. +dom7703. NS a.root-servers.nil. +dom7704. NS a.root-servers.nil. +dom7705. NS a.root-servers.nil. +dom7706. NS a.root-servers.nil. +dom7707. NS a.root-servers.nil. +dom7708. NS a.root-servers.nil. +dom7709. NS a.root-servers.nil. +dom7710. NS a.root-servers.nil. +dom7711. NS a.root-servers.nil. +dom7712. NS a.root-servers.nil. +dom7713. NS a.root-servers.nil. +dom7714. NS a.root-servers.nil. +dom7715. NS a.root-servers.nil. +dom7716. NS a.root-servers.nil. +dom7717. NS a.root-servers.nil. +dom7718. NS a.root-servers.nil. +dom7719. NS a.root-servers.nil. +dom7720. NS a.root-servers.nil. +dom7721. NS a.root-servers.nil. +dom7722. NS a.root-servers.nil. +dom7723. NS a.root-servers.nil. +dom7724. NS a.root-servers.nil. +dom7725. NS a.root-servers.nil. +dom7726. NS a.root-servers.nil. +dom7727. NS a.root-servers.nil. +dom7728. NS a.root-servers.nil. +dom7729. NS a.root-servers.nil. +dom7730. NS a.root-servers.nil. +dom7731. NS a.root-servers.nil. +dom7732. NS a.root-servers.nil. +dom7733. NS a.root-servers.nil. +dom7734. NS a.root-servers.nil. +dom7735. NS a.root-servers.nil. +dom7736. NS a.root-servers.nil. +dom7737. NS a.root-servers.nil. +dom7738. NS a.root-servers.nil. +dom7739. NS a.root-servers.nil. +dom7740. NS a.root-servers.nil. +dom7741. NS a.root-servers.nil. +dom7742. NS a.root-servers.nil. +dom7743. NS a.root-servers.nil. +dom7744. NS a.root-servers.nil. +dom7745. NS a.root-servers.nil. +dom7746. NS a.root-servers.nil. +dom7747. NS a.root-servers.nil. +dom7748. NS a.root-servers.nil. +dom7749. NS a.root-servers.nil. +dom7750. NS a.root-servers.nil. +dom7751. NS a.root-servers.nil. +dom7752. NS a.root-servers.nil. +dom7753. NS a.root-servers.nil. +dom7754. NS a.root-servers.nil. +dom7755. NS a.root-servers.nil. +dom7756. NS a.root-servers.nil. +dom7757. NS a.root-servers.nil. +dom7758. NS a.root-servers.nil. +dom7759. NS a.root-servers.nil. +dom7760. NS a.root-servers.nil. +dom7761. NS a.root-servers.nil. +dom7762. NS a.root-servers.nil. +dom7763. NS a.root-servers.nil. +dom7764. NS a.root-servers.nil. +dom7765. NS a.root-servers.nil. +dom7766. NS a.root-servers.nil. +dom7767. NS a.root-servers.nil. +dom7768. NS a.root-servers.nil. +dom7769. NS a.root-servers.nil. +dom7770. NS a.root-servers.nil. +dom7771. NS a.root-servers.nil. +dom7772. NS a.root-servers.nil. +dom7773. NS a.root-servers.nil. +dom7774. NS a.root-servers.nil. +dom7775. NS a.root-servers.nil. +dom7776. NS a.root-servers.nil. +dom7777. NS a.root-servers.nil. +dom7778. NS a.root-servers.nil. +dom7779. NS a.root-servers.nil. +dom7780. NS a.root-servers.nil. +dom7781. NS a.root-servers.nil. +dom7782. NS a.root-servers.nil. +dom7783. NS a.root-servers.nil. +dom7784. NS a.root-servers.nil. +dom7785. NS a.root-servers.nil. +dom7786. NS a.root-servers.nil. +dom7787. NS a.root-servers.nil. +dom7788. NS a.root-servers.nil. +dom7789. NS a.root-servers.nil. +dom7790. NS a.root-servers.nil. +dom7791. NS a.root-servers.nil. +dom7792. NS a.root-servers.nil. +dom7793. NS a.root-servers.nil. +dom7794. NS a.root-servers.nil. +dom7795. NS a.root-servers.nil. +dom7796. NS a.root-servers.nil. +dom7797. NS a.root-servers.nil. +dom7798. NS a.root-servers.nil. +dom7799. NS a.root-servers.nil. +dom7800. NS a.root-servers.nil. +dom7801. NS a.root-servers.nil. +dom7802. NS a.root-servers.nil. +dom7803. NS a.root-servers.nil. +dom7804. NS a.root-servers.nil. +dom7805. NS a.root-servers.nil. +dom7806. NS a.root-servers.nil. +dom7807. NS a.root-servers.nil. +dom7808. NS a.root-servers.nil. +dom7809. NS a.root-servers.nil. +dom7810. NS a.root-servers.nil. +dom7811. NS a.root-servers.nil. +dom7812. NS a.root-servers.nil. +dom7813. NS a.root-servers.nil. +dom7814. NS a.root-servers.nil. +dom7815. NS a.root-servers.nil. +dom7816. NS a.root-servers.nil. +dom7817. NS a.root-servers.nil. +dom7818. NS a.root-servers.nil. +dom7819. NS a.root-servers.nil. +dom7820. NS a.root-servers.nil. +dom7821. NS a.root-servers.nil. +dom7822. NS a.root-servers.nil. +dom7823. NS a.root-servers.nil. +dom7824. NS a.root-servers.nil. +dom7825. NS a.root-servers.nil. +dom7826. NS a.root-servers.nil. +dom7827. NS a.root-servers.nil. +dom7828. NS a.root-servers.nil. +dom7829. NS a.root-servers.nil. +dom7830. NS a.root-servers.nil. +dom7831. NS a.root-servers.nil. +dom7832. NS a.root-servers.nil. +dom7833. NS a.root-servers.nil. +dom7834. NS a.root-servers.nil. +dom7835. NS a.root-servers.nil. +dom7836. NS a.root-servers.nil. +dom7837. NS a.root-servers.nil. +dom7838. NS a.root-servers.nil. +dom7839. NS a.root-servers.nil. +dom7840. NS a.root-servers.nil. +dom7841. NS a.root-servers.nil. +dom7842. NS a.root-servers.nil. +dom7843. NS a.root-servers.nil. +dom7844. NS a.root-servers.nil. +dom7845. NS a.root-servers.nil. +dom7846. NS a.root-servers.nil. +dom7847. NS a.root-servers.nil. +dom7848. NS a.root-servers.nil. +dom7849. NS a.root-servers.nil. +dom7850. NS a.root-servers.nil. +dom7851. NS a.root-servers.nil. +dom7852. NS a.root-servers.nil. +dom7853. NS a.root-servers.nil. +dom7854. NS a.root-servers.nil. +dom7855. NS a.root-servers.nil. +dom7856. NS a.root-servers.nil. +dom7857. NS a.root-servers.nil. +dom7858. NS a.root-servers.nil. +dom7859. NS a.root-servers.nil. +dom7860. NS a.root-servers.nil. +dom7861. NS a.root-servers.nil. +dom7862. NS a.root-servers.nil. +dom7863. NS a.root-servers.nil. +dom7864. NS a.root-servers.nil. +dom7865. NS a.root-servers.nil. +dom7866. NS a.root-servers.nil. +dom7867. NS a.root-servers.nil. +dom7868. NS a.root-servers.nil. +dom7869. NS a.root-servers.nil. +dom7870. NS a.root-servers.nil. +dom7871. NS a.root-servers.nil. +dom7872. NS a.root-servers.nil. +dom7873. NS a.root-servers.nil. +dom7874. NS a.root-servers.nil. +dom7875. NS a.root-servers.nil. +dom7876. NS a.root-servers.nil. +dom7877. NS a.root-servers.nil. +dom7878. NS a.root-servers.nil. +dom7879. NS a.root-servers.nil. +dom7880. NS a.root-servers.nil. +dom7881. NS a.root-servers.nil. +dom7882. NS a.root-servers.nil. +dom7883. NS a.root-servers.nil. +dom7884. NS a.root-servers.nil. +dom7885. NS a.root-servers.nil. +dom7886. NS a.root-servers.nil. +dom7887. NS a.root-servers.nil. +dom7888. NS a.root-servers.nil. +dom7889. NS a.root-servers.nil. +dom7890. NS a.root-servers.nil. +dom7891. NS a.root-servers.nil. +dom7892. NS a.root-servers.nil. +dom7893. NS a.root-servers.nil. +dom7894. NS a.root-servers.nil. +dom7895. NS a.root-servers.nil. +dom7896. NS a.root-servers.nil. +dom7897. NS a.root-servers.nil. +dom7898. NS a.root-servers.nil. +dom7899. NS a.root-servers.nil. +dom7900. NS a.root-servers.nil. +dom7901. NS a.root-servers.nil. +dom7902. NS a.root-servers.nil. +dom7903. NS a.root-servers.nil. +dom7904. NS a.root-servers.nil. +dom7905. NS a.root-servers.nil. +dom7906. NS a.root-servers.nil. +dom7907. NS a.root-servers.nil. +dom7908. NS a.root-servers.nil. +dom7909. NS a.root-servers.nil. +dom7910. NS a.root-servers.nil. +dom7911. NS a.root-servers.nil. +dom7912. NS a.root-servers.nil. +dom7913. NS a.root-servers.nil. +dom7914. NS a.root-servers.nil. +dom7915. NS a.root-servers.nil. +dom7916. NS a.root-servers.nil. +dom7917. NS a.root-servers.nil. +dom7918. NS a.root-servers.nil. +dom7919. NS a.root-servers.nil. +dom7920. NS a.root-servers.nil. +dom7921. NS a.root-servers.nil. +dom7922. NS a.root-servers.nil. +dom7923. NS a.root-servers.nil. +dom7924. NS a.root-servers.nil. +dom7925. NS a.root-servers.nil. +dom7926. NS a.root-servers.nil. +dom7927. NS a.root-servers.nil. +dom7928. NS a.root-servers.nil. +dom7929. NS a.root-servers.nil. +dom7930. NS a.root-servers.nil. +dom7931. NS a.root-servers.nil. +dom7932. NS a.root-servers.nil. +dom7933. NS a.root-servers.nil. +dom7934. NS a.root-servers.nil. +dom7935. NS a.root-servers.nil. +dom7936. NS a.root-servers.nil. +dom7937. NS a.root-servers.nil. +dom7938. NS a.root-servers.nil. +dom7939. NS a.root-servers.nil. +dom7940. NS a.root-servers.nil. +dom7941. NS a.root-servers.nil. +dom7942. NS a.root-servers.nil. +dom7943. NS a.root-servers.nil. +dom7944. NS a.root-servers.nil. +dom7945. NS a.root-servers.nil. +dom7946. NS a.root-servers.nil. +dom7947. NS a.root-servers.nil. +dom7948. NS a.root-servers.nil. +dom7949. NS a.root-servers.nil. +dom7950. NS a.root-servers.nil. +dom7951. NS a.root-servers.nil. +dom7952. NS a.root-servers.nil. +dom7953. NS a.root-servers.nil. +dom7954. NS a.root-servers.nil. +dom7955. NS a.root-servers.nil. +dom7956. NS a.root-servers.nil. +dom7957. NS a.root-servers.nil. +dom7958. NS a.root-servers.nil. +dom7959. NS a.root-servers.nil. +dom7960. NS a.root-servers.nil. +dom7961. NS a.root-servers.nil. +dom7962. NS a.root-servers.nil. +dom7963. NS a.root-servers.nil. +dom7964. NS a.root-servers.nil. +dom7965. NS a.root-servers.nil. +dom7966. NS a.root-servers.nil. +dom7967. NS a.root-servers.nil. +dom7968. NS a.root-servers.nil. +dom7969. NS a.root-servers.nil. +dom7970. NS a.root-servers.nil. +dom7971. NS a.root-servers.nil. +dom7972. NS a.root-servers.nil. +dom7973. NS a.root-servers.nil. +dom7974. NS a.root-servers.nil. +dom7975. NS a.root-servers.nil. +dom7976. NS a.root-servers.nil. +dom7977. NS a.root-servers.nil. +dom7978. NS a.root-servers.nil. +dom7979. NS a.root-servers.nil. +dom7980. NS a.root-servers.nil. +dom7981. NS a.root-servers.nil. +dom7982. NS a.root-servers.nil. +dom7983. NS a.root-servers.nil. +dom7984. NS a.root-servers.nil. +dom7985. NS a.root-servers.nil. +dom7986. NS a.root-servers.nil. +dom7987. NS a.root-servers.nil. +dom7988. NS a.root-servers.nil. +dom7989. NS a.root-servers.nil. +dom7990. NS a.root-servers.nil. +dom7991. NS a.root-servers.nil. +dom7992. NS a.root-servers.nil. +dom7993. NS a.root-servers.nil. +dom7994. NS a.root-servers.nil. +dom7995. NS a.root-servers.nil. +dom7996. NS a.root-servers.nil. +dom7997. NS a.root-servers.nil. +dom7998. NS a.root-servers.nil. +dom7999. NS a.root-servers.nil. +dom8000. NS a.root-servers.nil. +dom8001. NS a.root-servers.nil. +dom8002. NS a.root-servers.nil. +dom8003. NS a.root-servers.nil. +dom8004. NS a.root-servers.nil. +dom8005. NS a.root-servers.nil. +dom8006. NS a.root-servers.nil. +dom8007. NS a.root-servers.nil. +dom8008. NS a.root-servers.nil. +dom8009. NS a.root-servers.nil. +dom8010. NS a.root-servers.nil. +dom8011. NS a.root-servers.nil. +dom8012. NS a.root-servers.nil. +dom8013. NS a.root-servers.nil. +dom8014. NS a.root-servers.nil. +dom8015. NS a.root-servers.nil. +dom8016. NS a.root-servers.nil. +dom8017. NS a.root-servers.nil. +dom8018. NS a.root-servers.nil. +dom8019. NS a.root-servers.nil. +dom8020. NS a.root-servers.nil. +dom8021. NS a.root-servers.nil. +dom8022. NS a.root-servers.nil. +dom8023. NS a.root-servers.nil. +dom8024. NS a.root-servers.nil. +dom8025. NS a.root-servers.nil. +dom8026. NS a.root-servers.nil. +dom8027. NS a.root-servers.nil. +dom8028. NS a.root-servers.nil. +dom8029. NS a.root-servers.nil. +dom8030. NS a.root-servers.nil. +dom8031. NS a.root-servers.nil. +dom8032. NS a.root-servers.nil. +dom8033. NS a.root-servers.nil. +dom8034. NS a.root-servers.nil. +dom8035. NS a.root-servers.nil. +dom8036. NS a.root-servers.nil. +dom8037. NS a.root-servers.nil. +dom8038. NS a.root-servers.nil. +dom8039. NS a.root-servers.nil. +dom8040. NS a.root-servers.nil. +dom8041. NS a.root-servers.nil. +dom8042. NS a.root-servers.nil. +dom8043. NS a.root-servers.nil. +dom8044. NS a.root-servers.nil. +dom8045. NS a.root-servers.nil. +dom8046. NS a.root-servers.nil. +dom8047. NS a.root-servers.nil. +dom8048. NS a.root-servers.nil. +dom8049. NS a.root-servers.nil. +dom8050. NS a.root-servers.nil. +dom8051. NS a.root-servers.nil. +dom8052. NS a.root-servers.nil. +dom8053. NS a.root-servers.nil. +dom8054. NS a.root-servers.nil. +dom8055. NS a.root-servers.nil. +dom8056. NS a.root-servers.nil. +dom8057. NS a.root-servers.nil. +dom8058. NS a.root-servers.nil. +dom8059. NS a.root-servers.nil. +dom8060. NS a.root-servers.nil. +dom8061. NS a.root-servers.nil. +dom8062. NS a.root-servers.nil. +dom8063. NS a.root-servers.nil. +dom8064. NS a.root-servers.nil. +dom8065. NS a.root-servers.nil. +dom8066. NS a.root-servers.nil. +dom8067. NS a.root-servers.nil. +dom8068. NS a.root-servers.nil. +dom8069. NS a.root-servers.nil. +dom8070. NS a.root-servers.nil. +dom8071. NS a.root-servers.nil. +dom8072. NS a.root-servers.nil. +dom8073. NS a.root-servers.nil. +dom8074. NS a.root-servers.nil. +dom8075. NS a.root-servers.nil. +dom8076. NS a.root-servers.nil. +dom8077. NS a.root-servers.nil. +dom8078. NS a.root-servers.nil. +dom8079. NS a.root-servers.nil. +dom8080. NS a.root-servers.nil. +dom8081. NS a.root-servers.nil. +dom8082. NS a.root-servers.nil. +dom8083. NS a.root-servers.nil. +dom8084. NS a.root-servers.nil. +dom8085. NS a.root-servers.nil. +dom8086. NS a.root-servers.nil. +dom8087. NS a.root-servers.nil. +dom8088. NS a.root-servers.nil. +dom8089. NS a.root-servers.nil. +dom8090. NS a.root-servers.nil. +dom8091. NS a.root-servers.nil. +dom8092. NS a.root-servers.nil. +dom8093. NS a.root-servers.nil. +dom8094. NS a.root-servers.nil. +dom8095. NS a.root-servers.nil. +dom8096. NS a.root-servers.nil. +dom8097. NS a.root-servers.nil. +dom8098. NS a.root-servers.nil. +dom8099. NS a.root-servers.nil. +dom8100. NS a.root-servers.nil. +dom8101. NS a.root-servers.nil. +dom8102. NS a.root-servers.nil. +dom8103. NS a.root-servers.nil. +dom8104. NS a.root-servers.nil. +dom8105. NS a.root-servers.nil. +dom8106. NS a.root-servers.nil. +dom8107. NS a.root-servers.nil. +dom8108. NS a.root-servers.nil. +dom8109. NS a.root-servers.nil. +dom8110. NS a.root-servers.nil. +dom8111. NS a.root-servers.nil. +dom8112. NS a.root-servers.nil. +dom8113. NS a.root-servers.nil. +dom8114. NS a.root-servers.nil. +dom8115. NS a.root-servers.nil. +dom8116. NS a.root-servers.nil. +dom8117. NS a.root-servers.nil. +dom8118. NS a.root-servers.nil. +dom8119. NS a.root-servers.nil. +dom8120. NS a.root-servers.nil. +dom8121. NS a.root-servers.nil. +dom8122. NS a.root-servers.nil. +dom8123. NS a.root-servers.nil. +dom8124. NS a.root-servers.nil. +dom8125. NS a.root-servers.nil. +dom8126. NS a.root-servers.nil. +dom8127. NS a.root-servers.nil. +dom8128. NS a.root-servers.nil. +dom8129. NS a.root-servers.nil. +dom8130. NS a.root-servers.nil. +dom8131. NS a.root-servers.nil. +dom8132. NS a.root-servers.nil. +dom8133. NS a.root-servers.nil. +dom8134. NS a.root-servers.nil. +dom8135. NS a.root-servers.nil. +dom8136. NS a.root-servers.nil. +dom8137. NS a.root-servers.nil. +dom8138. NS a.root-servers.nil. +dom8139. NS a.root-servers.nil. +dom8140. NS a.root-servers.nil. +dom8141. NS a.root-servers.nil. +dom8142. NS a.root-servers.nil. +dom8143. NS a.root-servers.nil. +dom8144. NS a.root-servers.nil. +dom8145. NS a.root-servers.nil. +dom8146. NS a.root-servers.nil. +dom8147. NS a.root-servers.nil. +dom8148. NS a.root-servers.nil. +dom8149. NS a.root-servers.nil. +dom8150. NS a.root-servers.nil. +dom8151. NS a.root-servers.nil. +dom8152. NS a.root-servers.nil. +dom8153. NS a.root-servers.nil. +dom8154. NS a.root-servers.nil. +dom8155. NS a.root-servers.nil. +dom8156. NS a.root-servers.nil. +dom8157. NS a.root-servers.nil. +dom8158. NS a.root-servers.nil. +dom8159. NS a.root-servers.nil. +dom8160. NS a.root-servers.nil. +dom8161. NS a.root-servers.nil. +dom8162. NS a.root-servers.nil. +dom8163. NS a.root-servers.nil. +dom8164. NS a.root-servers.nil. +dom8165. NS a.root-servers.nil. +dom8166. NS a.root-servers.nil. +dom8167. NS a.root-servers.nil. +dom8168. NS a.root-servers.nil. +dom8169. NS a.root-servers.nil. +dom8170. NS a.root-servers.nil. +dom8171. NS a.root-servers.nil. +dom8172. NS a.root-servers.nil. +dom8173. NS a.root-servers.nil. +dom8174. NS a.root-servers.nil. +dom8175. NS a.root-servers.nil. +dom8176. NS a.root-servers.nil. +dom8177. NS a.root-servers.nil. +dom8178. NS a.root-servers.nil. +dom8179. NS a.root-servers.nil. +dom8180. NS a.root-servers.nil. +dom8181. NS a.root-servers.nil. +dom8182. NS a.root-servers.nil. +dom8183. NS a.root-servers.nil. +dom8184. NS a.root-servers.nil. +dom8185. NS a.root-servers.nil. +dom8186. NS a.root-servers.nil. +dom8187. NS a.root-servers.nil. +dom8188. NS a.root-servers.nil. +dom8189. NS a.root-servers.nil. +dom8190. NS a.root-servers.nil. +dom8191. NS a.root-servers.nil. +dom8192. NS a.root-servers.nil. +dom8193. NS a.root-servers.nil. +dom8194. NS a.root-servers.nil. +dom8195. NS a.root-servers.nil. +dom8196. NS a.root-servers.nil. +dom8197. NS a.root-servers.nil. +dom8198. NS a.root-servers.nil. +dom8199. NS a.root-servers.nil. +dom8200. NS a.root-servers.nil. +dom8201. NS a.root-servers.nil. +dom8202. NS a.root-servers.nil. +dom8203. NS a.root-servers.nil. +dom8204. NS a.root-servers.nil. +dom8205. NS a.root-servers.nil. +dom8206. NS a.root-servers.nil. +dom8207. NS a.root-servers.nil. +dom8208. NS a.root-servers.nil. +dom8209. NS a.root-servers.nil. +dom8210. NS a.root-servers.nil. +dom8211. NS a.root-servers.nil. +dom8212. NS a.root-servers.nil. +dom8213. NS a.root-servers.nil. +dom8214. NS a.root-servers.nil. +dom8215. NS a.root-servers.nil. +dom8216. NS a.root-servers.nil. +dom8217. NS a.root-servers.nil. +dom8218. NS a.root-servers.nil. +dom8219. NS a.root-servers.nil. +dom8220. NS a.root-servers.nil. +dom8221. NS a.root-servers.nil. +dom8222. NS a.root-servers.nil. +dom8223. NS a.root-servers.nil. +dom8224. NS a.root-servers.nil. +dom8225. NS a.root-servers.nil. +dom8226. NS a.root-servers.nil. +dom8227. NS a.root-servers.nil. +dom8228. NS a.root-servers.nil. +dom8229. NS a.root-servers.nil. +dom8230. NS a.root-servers.nil. +dom8231. NS a.root-servers.nil. +dom8232. NS a.root-servers.nil. +dom8233. NS a.root-servers.nil. +dom8234. NS a.root-servers.nil. +dom8235. NS a.root-servers.nil. +dom8236. NS a.root-servers.nil. +dom8237. NS a.root-servers.nil. +dom8238. NS a.root-servers.nil. +dom8239. NS a.root-servers.nil. +dom8240. NS a.root-servers.nil. +dom8241. NS a.root-servers.nil. +dom8242. NS a.root-servers.nil. +dom8243. NS a.root-servers.nil. +dom8244. NS a.root-servers.nil. +dom8245. NS a.root-servers.nil. +dom8246. NS a.root-servers.nil. +dom8247. NS a.root-servers.nil. +dom8248. NS a.root-servers.nil. +dom8249. NS a.root-servers.nil. +dom8250. NS a.root-servers.nil. +dom8251. NS a.root-servers.nil. +dom8252. NS a.root-servers.nil. +dom8253. NS a.root-servers.nil. +dom8254. NS a.root-servers.nil. +dom8255. NS a.root-servers.nil. +dom8256. NS a.root-servers.nil. +dom8257. NS a.root-servers.nil. +dom8258. NS a.root-servers.nil. +dom8259. NS a.root-servers.nil. +dom8260. NS a.root-servers.nil. +dom8261. NS a.root-servers.nil. +dom8262. NS a.root-servers.nil. +dom8263. NS a.root-servers.nil. +dom8264. NS a.root-servers.nil. +dom8265. NS a.root-servers.nil. +dom8266. NS a.root-servers.nil. +dom8267. NS a.root-servers.nil. +dom8268. NS a.root-servers.nil. +dom8269. NS a.root-servers.nil. +dom8270. NS a.root-servers.nil. +dom8271. NS a.root-servers.nil. +dom8272. NS a.root-servers.nil. +dom8273. NS a.root-servers.nil. +dom8274. NS a.root-servers.nil. +dom8275. NS a.root-servers.nil. +dom8276. NS a.root-servers.nil. +dom8277. NS a.root-servers.nil. +dom8278. NS a.root-servers.nil. +dom8279. NS a.root-servers.nil. +dom8280. NS a.root-servers.nil. +dom8281. NS a.root-servers.nil. +dom8282. NS a.root-servers.nil. +dom8283. NS a.root-servers.nil. +dom8284. NS a.root-servers.nil. +dom8285. NS a.root-servers.nil. +dom8286. NS a.root-servers.nil. +dom8287. NS a.root-servers.nil. +dom8288. NS a.root-servers.nil. +dom8289. NS a.root-servers.nil. +dom8290. NS a.root-servers.nil. +dom8291. NS a.root-servers.nil. +dom8292. NS a.root-servers.nil. +dom8293. NS a.root-servers.nil. +dom8294. NS a.root-servers.nil. +dom8295. NS a.root-servers.nil. +dom8296. NS a.root-servers.nil. +dom8297. NS a.root-servers.nil. +dom8298. NS a.root-servers.nil. +dom8299. NS a.root-servers.nil. +dom8300. NS a.root-servers.nil. +dom8301. NS a.root-servers.nil. +dom8302. NS a.root-servers.nil. +dom8303. NS a.root-servers.nil. +dom8304. NS a.root-servers.nil. +dom8305. NS a.root-servers.nil. +dom8306. NS a.root-servers.nil. +dom8307. NS a.root-servers.nil. +dom8308. NS a.root-servers.nil. +dom8309. NS a.root-servers.nil. +dom8310. NS a.root-servers.nil. +dom8311. NS a.root-servers.nil. +dom8312. NS a.root-servers.nil. +dom8313. NS a.root-servers.nil. +dom8314. NS a.root-servers.nil. +dom8315. NS a.root-servers.nil. +dom8316. NS a.root-servers.nil. +dom8317. NS a.root-servers.nil. +dom8318. NS a.root-servers.nil. +dom8319. NS a.root-servers.nil. +dom8320. NS a.root-servers.nil. +dom8321. NS a.root-servers.nil. +dom8322. NS a.root-servers.nil. +dom8323. NS a.root-servers.nil. +dom8324. NS a.root-servers.nil. +dom8325. NS a.root-servers.nil. +dom8326. NS a.root-servers.nil. +dom8327. NS a.root-servers.nil. +dom8328. NS a.root-servers.nil. +dom8329. NS a.root-servers.nil. +dom8330. NS a.root-servers.nil. +dom8331. NS a.root-servers.nil. +dom8332. NS a.root-servers.nil. +dom8333. NS a.root-servers.nil. +dom8334. NS a.root-servers.nil. +dom8335. NS a.root-servers.nil. +dom8336. NS a.root-servers.nil. +dom8337. NS a.root-servers.nil. +dom8338. NS a.root-servers.nil. +dom8339. NS a.root-servers.nil. +dom8340. NS a.root-servers.nil. +dom8341. NS a.root-servers.nil. +dom8342. NS a.root-servers.nil. +dom8343. NS a.root-servers.nil. +dom8344. NS a.root-servers.nil. +dom8345. NS a.root-servers.nil. +dom8346. NS a.root-servers.nil. +dom8347. NS a.root-servers.nil. +dom8348. NS a.root-servers.nil. +dom8349. NS a.root-servers.nil. +dom8350. NS a.root-servers.nil. +dom8351. NS a.root-servers.nil. +dom8352. NS a.root-servers.nil. +dom8353. NS a.root-servers.nil. +dom8354. NS a.root-servers.nil. +dom8355. NS a.root-servers.nil. +dom8356. NS a.root-servers.nil. +dom8357. NS a.root-servers.nil. +dom8358. NS a.root-servers.nil. +dom8359. NS a.root-servers.nil. +dom8360. NS a.root-servers.nil. +dom8361. NS a.root-servers.nil. +dom8362. NS a.root-servers.nil. +dom8363. NS a.root-servers.nil. +dom8364. NS a.root-servers.nil. +dom8365. NS a.root-servers.nil. +dom8366. NS a.root-servers.nil. +dom8367. NS a.root-servers.nil. +dom8368. NS a.root-servers.nil. +dom8369. NS a.root-servers.nil. +dom8370. NS a.root-servers.nil. +dom8371. NS a.root-servers.nil. +dom8372. NS a.root-servers.nil. +dom8373. NS a.root-servers.nil. +dom8374. NS a.root-servers.nil. +dom8375. NS a.root-servers.nil. +dom8376. NS a.root-servers.nil. +dom8377. NS a.root-servers.nil. +dom8378. NS a.root-servers.nil. +dom8379. NS a.root-servers.nil. +dom8380. NS a.root-servers.nil. +dom8381. NS a.root-servers.nil. +dom8382. NS a.root-servers.nil. +dom8383. NS a.root-servers.nil. +dom8384. NS a.root-servers.nil. +dom8385. NS a.root-servers.nil. +dom8386. NS a.root-servers.nil. +dom8387. NS a.root-servers.nil. +dom8388. NS a.root-servers.nil. +dom8389. NS a.root-servers.nil. +dom8390. NS a.root-servers.nil. +dom8391. NS a.root-servers.nil. +dom8392. NS a.root-servers.nil. +dom8393. NS a.root-servers.nil. +dom8394. NS a.root-servers.nil. +dom8395. NS a.root-servers.nil. +dom8396. NS a.root-servers.nil. +dom8397. NS a.root-servers.nil. +dom8398. NS a.root-servers.nil. +dom8399. NS a.root-servers.nil. +dom8400. NS a.root-servers.nil. +dom8401. NS a.root-servers.nil. +dom8402. NS a.root-servers.nil. +dom8403. NS a.root-servers.nil. +dom8404. NS a.root-servers.nil. +dom8405. NS a.root-servers.nil. +dom8406. NS a.root-servers.nil. +dom8407. NS a.root-servers.nil. +dom8408. NS a.root-servers.nil. +dom8409. NS a.root-servers.nil. +dom8410. NS a.root-servers.nil. +dom8411. NS a.root-servers.nil. +dom8412. NS a.root-servers.nil. +dom8413. NS a.root-servers.nil. +dom8414. NS a.root-servers.nil. +dom8415. NS a.root-servers.nil. +dom8416. NS a.root-servers.nil. +dom8417. NS a.root-servers.nil. +dom8418. NS a.root-servers.nil. +dom8419. NS a.root-servers.nil. +dom8420. NS a.root-servers.nil. +dom8421. NS a.root-servers.nil. +dom8422. NS a.root-servers.nil. +dom8423. NS a.root-servers.nil. +dom8424. NS a.root-servers.nil. +dom8425. NS a.root-servers.nil. +dom8426. NS a.root-servers.nil. +dom8427. NS a.root-servers.nil. +dom8428. NS a.root-servers.nil. +dom8429. NS a.root-servers.nil. +dom8430. NS a.root-servers.nil. +dom8431. NS a.root-servers.nil. +dom8432. NS a.root-servers.nil. +dom8433. NS a.root-servers.nil. +dom8434. NS a.root-servers.nil. +dom8435. NS a.root-servers.nil. +dom8436. NS a.root-servers.nil. +dom8437. NS a.root-servers.nil. +dom8438. NS a.root-servers.nil. +dom8439. NS a.root-servers.nil. +dom8440. NS a.root-servers.nil. +dom8441. NS a.root-servers.nil. +dom8442. NS a.root-servers.nil. +dom8443. NS a.root-servers.nil. +dom8444. NS a.root-servers.nil. +dom8445. NS a.root-servers.nil. +dom8446. NS a.root-servers.nil. +dom8447. NS a.root-servers.nil. +dom8448. NS a.root-servers.nil. +dom8449. NS a.root-servers.nil. +dom8450. NS a.root-servers.nil. +dom8451. NS a.root-servers.nil. +dom8452. NS a.root-servers.nil. +dom8453. NS a.root-servers.nil. +dom8454. NS a.root-servers.nil. +dom8455. NS a.root-servers.nil. +dom8456. NS a.root-servers.nil. +dom8457. NS a.root-servers.nil. +dom8458. NS a.root-servers.nil. +dom8459. NS a.root-servers.nil. +dom8460. NS a.root-servers.nil. +dom8461. NS a.root-servers.nil. +dom8462. NS a.root-servers.nil. +dom8463. NS a.root-servers.nil. +dom8464. NS a.root-servers.nil. +dom8465. NS a.root-servers.nil. +dom8466. NS a.root-servers.nil. +dom8467. NS a.root-servers.nil. +dom8468. NS a.root-servers.nil. +dom8469. NS a.root-servers.nil. +dom8470. NS a.root-servers.nil. +dom8471. NS a.root-servers.nil. +dom8472. NS a.root-servers.nil. +dom8473. NS a.root-servers.nil. +dom8474. NS a.root-servers.nil. +dom8475. NS a.root-servers.nil. +dom8476. NS a.root-servers.nil. +dom8477. NS a.root-servers.nil. +dom8478. NS a.root-servers.nil. +dom8479. NS a.root-servers.nil. +dom8480. NS a.root-servers.nil. +dom8481. NS a.root-servers.nil. +dom8482. NS a.root-servers.nil. +dom8483. NS a.root-servers.nil. +dom8484. NS a.root-servers.nil. +dom8485. NS a.root-servers.nil. +dom8486. NS a.root-servers.nil. +dom8487. NS a.root-servers.nil. +dom8488. NS a.root-servers.nil. +dom8489. NS a.root-servers.nil. +dom8490. NS a.root-servers.nil. +dom8491. NS a.root-servers.nil. +dom8492. NS a.root-servers.nil. +dom8493. NS a.root-servers.nil. +dom8494. NS a.root-servers.nil. +dom8495. NS a.root-servers.nil. +dom8496. NS a.root-servers.nil. +dom8497. NS a.root-servers.nil. +dom8498. NS a.root-servers.nil. +dom8499. NS a.root-servers.nil. +dom8500. NS a.root-servers.nil. +dom8501. NS a.root-servers.nil. +dom8502. NS a.root-servers.nil. +dom8503. NS a.root-servers.nil. +dom8504. NS a.root-servers.nil. +dom8505. NS a.root-servers.nil. +dom8506. NS a.root-servers.nil. +dom8507. NS a.root-servers.nil. +dom8508. NS a.root-servers.nil. +dom8509. NS a.root-servers.nil. +dom8510. NS a.root-servers.nil. +dom8511. NS a.root-servers.nil. +dom8512. NS a.root-servers.nil. +dom8513. NS a.root-servers.nil. +dom8514. NS a.root-servers.nil. +dom8515. NS a.root-servers.nil. +dom8516. NS a.root-servers.nil. +dom8517. NS a.root-servers.nil. +dom8518. NS a.root-servers.nil. +dom8519. NS a.root-servers.nil. +dom8520. NS a.root-servers.nil. +dom8521. NS a.root-servers.nil. +dom8522. NS a.root-servers.nil. +dom8523. NS a.root-servers.nil. +dom8524. NS a.root-servers.nil. +dom8525. NS a.root-servers.nil. +dom8526. NS a.root-servers.nil. +dom8527. NS a.root-servers.nil. +dom8528. NS a.root-servers.nil. +dom8529. NS a.root-servers.nil. +dom8530. NS a.root-servers.nil. +dom8531. NS a.root-servers.nil. +dom8532. NS a.root-servers.nil. +dom8533. NS a.root-servers.nil. +dom8534. NS a.root-servers.nil. +dom8535. NS a.root-servers.nil. +dom8536. NS a.root-servers.nil. +dom8537. NS a.root-servers.nil. +dom8538. NS a.root-servers.nil. +dom8539. NS a.root-servers.nil. +dom8540. NS a.root-servers.nil. +dom8541. NS a.root-servers.nil. +dom8542. NS a.root-servers.nil. +dom8543. NS a.root-servers.nil. +dom8544. NS a.root-servers.nil. +dom8545. NS a.root-servers.nil. +dom8546. NS a.root-servers.nil. +dom8547. NS a.root-servers.nil. +dom8548. NS a.root-servers.nil. +dom8549. NS a.root-servers.nil. +dom8550. NS a.root-servers.nil. +dom8551. NS a.root-servers.nil. +dom8552. NS a.root-servers.nil. +dom8553. NS a.root-servers.nil. +dom8554. NS a.root-servers.nil. +dom8555. NS a.root-servers.nil. +dom8556. NS a.root-servers.nil. +dom8557. NS a.root-servers.nil. +dom8558. NS a.root-servers.nil. +dom8559. NS a.root-servers.nil. +dom8560. NS a.root-servers.nil. +dom8561. NS a.root-servers.nil. +dom8562. NS a.root-servers.nil. +dom8563. NS a.root-servers.nil. +dom8564. NS a.root-servers.nil. +dom8565. NS a.root-servers.nil. +dom8566. NS a.root-servers.nil. +dom8567. NS a.root-servers.nil. +dom8568. NS a.root-servers.nil. +dom8569. NS a.root-servers.nil. +dom8570. NS a.root-servers.nil. +dom8571. NS a.root-servers.nil. +dom8572. NS a.root-servers.nil. +dom8573. NS a.root-servers.nil. +dom8574. NS a.root-servers.nil. +dom8575. NS a.root-servers.nil. +dom8576. NS a.root-servers.nil. +dom8577. NS a.root-servers.nil. +dom8578. NS a.root-servers.nil. +dom8579. NS a.root-servers.nil. +dom8580. NS a.root-servers.nil. +dom8581. NS a.root-servers.nil. +dom8582. NS a.root-servers.nil. +dom8583. NS a.root-servers.nil. +dom8584. NS a.root-servers.nil. +dom8585. NS a.root-servers.nil. +dom8586. NS a.root-servers.nil. +dom8587. NS a.root-servers.nil. +dom8588. NS a.root-servers.nil. +dom8589. NS a.root-servers.nil. +dom8590. NS a.root-servers.nil. +dom8591. NS a.root-servers.nil. +dom8592. NS a.root-servers.nil. +dom8593. NS a.root-servers.nil. +dom8594. NS a.root-servers.nil. +dom8595. NS a.root-servers.nil. +dom8596. NS a.root-servers.nil. +dom8597. NS a.root-servers.nil. +dom8598. NS a.root-servers.nil. +dom8599. NS a.root-servers.nil. +dom8600. NS a.root-servers.nil. +dom8601. NS a.root-servers.nil. +dom8602. NS a.root-servers.nil. +dom8603. NS a.root-servers.nil. +dom8604. NS a.root-servers.nil. +dom8605. NS a.root-servers.nil. +dom8606. NS a.root-servers.nil. +dom8607. NS a.root-servers.nil. +dom8608. NS a.root-servers.nil. +dom8609. NS a.root-servers.nil. +dom8610. NS a.root-servers.nil. +dom8611. NS a.root-servers.nil. +dom8612. NS a.root-servers.nil. +dom8613. NS a.root-servers.nil. +dom8614. NS a.root-servers.nil. +dom8615. NS a.root-servers.nil. +dom8616. NS a.root-servers.nil. +dom8617. NS a.root-servers.nil. +dom8618. NS a.root-servers.nil. +dom8619. NS a.root-servers.nil. +dom8620. NS a.root-servers.nil. +dom8621. NS a.root-servers.nil. +dom8622. NS a.root-servers.nil. +dom8623. NS a.root-servers.nil. +dom8624. NS a.root-servers.nil. +dom8625. NS a.root-servers.nil. +dom8626. NS a.root-servers.nil. +dom8627. NS a.root-servers.nil. +dom8628. NS a.root-servers.nil. +dom8629. NS a.root-servers.nil. +dom8630. NS a.root-servers.nil. +dom8631. NS a.root-servers.nil. +dom8632. NS a.root-servers.nil. +dom8633. NS a.root-servers.nil. +dom8634. NS a.root-servers.nil. +dom8635. NS a.root-servers.nil. +dom8636. NS a.root-servers.nil. +dom8637. NS a.root-servers.nil. +dom8638. NS a.root-servers.nil. +dom8639. NS a.root-servers.nil. +dom8640. NS a.root-servers.nil. +dom8641. NS a.root-servers.nil. +dom8642. NS a.root-servers.nil. +dom8643. NS a.root-servers.nil. +dom8644. NS a.root-servers.nil. +dom8645. NS a.root-servers.nil. +dom8646. NS a.root-servers.nil. +dom8647. NS a.root-servers.nil. +dom8648. NS a.root-servers.nil. +dom8649. NS a.root-servers.nil. +dom8650. NS a.root-servers.nil. +dom8651. NS a.root-servers.nil. +dom8652. NS a.root-servers.nil. +dom8653. NS a.root-servers.nil. +dom8654. NS a.root-servers.nil. +dom8655. NS a.root-servers.nil. +dom8656. NS a.root-servers.nil. +dom8657. NS a.root-servers.nil. +dom8658. NS a.root-servers.nil. +dom8659. NS a.root-servers.nil. +dom8660. NS a.root-servers.nil. +dom8661. NS a.root-servers.nil. +dom8662. NS a.root-servers.nil. +dom8663. NS a.root-servers.nil. +dom8664. NS a.root-servers.nil. +dom8665. NS a.root-servers.nil. +dom8666. NS a.root-servers.nil. +dom8667. NS a.root-servers.nil. +dom8668. NS a.root-servers.nil. +dom8669. NS a.root-servers.nil. +dom8670. NS a.root-servers.nil. +dom8671. NS a.root-servers.nil. +dom8672. NS a.root-servers.nil. +dom8673. NS a.root-servers.nil. +dom8674. NS a.root-servers.nil. +dom8675. NS a.root-servers.nil. +dom8676. NS a.root-servers.nil. +dom8677. NS a.root-servers.nil. +dom8678. NS a.root-servers.nil. +dom8679. NS a.root-servers.nil. +dom8680. NS a.root-servers.nil. +dom8681. NS a.root-servers.nil. +dom8682. NS a.root-servers.nil. +dom8683. NS a.root-servers.nil. +dom8684. NS a.root-servers.nil. +dom8685. NS a.root-servers.nil. +dom8686. NS a.root-servers.nil. +dom8687. NS a.root-servers.nil. +dom8688. NS a.root-servers.nil. +dom8689. NS a.root-servers.nil. +dom8690. NS a.root-servers.nil. +dom8691. NS a.root-servers.nil. +dom8692. NS a.root-servers.nil. +dom8693. NS a.root-servers.nil. +dom8694. NS a.root-servers.nil. +dom8695. NS a.root-servers.nil. +dom8696. NS a.root-servers.nil. +dom8697. NS a.root-servers.nil. +dom8698. NS a.root-servers.nil. +dom8699. NS a.root-servers.nil. +dom8700. NS a.root-servers.nil. +dom8701. NS a.root-servers.nil. +dom8702. NS a.root-servers.nil. +dom8703. NS a.root-servers.nil. +dom8704. NS a.root-servers.nil. +dom8705. NS a.root-servers.nil. +dom8706. NS a.root-servers.nil. +dom8707. NS a.root-servers.nil. +dom8708. NS a.root-servers.nil. +dom8709. NS a.root-servers.nil. +dom8710. NS a.root-servers.nil. +dom8711. NS a.root-servers.nil. +dom8712. NS a.root-servers.nil. +dom8713. NS a.root-servers.nil. +dom8714. NS a.root-servers.nil. +dom8715. NS a.root-servers.nil. +dom8716. NS a.root-servers.nil. +dom8717. NS a.root-servers.nil. +dom8718. NS a.root-servers.nil. +dom8719. NS a.root-servers.nil. +dom8720. NS a.root-servers.nil. +dom8721. NS a.root-servers.nil. +dom8722. NS a.root-servers.nil. +dom8723. NS a.root-servers.nil. +dom8724. NS a.root-servers.nil. +dom8725. NS a.root-servers.nil. +dom8726. NS a.root-servers.nil. +dom8727. NS a.root-servers.nil. +dom8728. NS a.root-servers.nil. +dom8729. NS a.root-servers.nil. +dom8730. NS a.root-servers.nil. +dom8731. NS a.root-servers.nil. +dom8732. NS a.root-servers.nil. +dom8733. NS a.root-servers.nil. +dom8734. NS a.root-servers.nil. +dom8735. NS a.root-servers.nil. +dom8736. NS a.root-servers.nil. +dom8737. NS a.root-servers.nil. +dom8738. NS a.root-servers.nil. +dom8739. NS a.root-servers.nil. +dom8740. NS a.root-servers.nil. +dom8741. NS a.root-servers.nil. +dom8742. NS a.root-servers.nil. +dom8743. NS a.root-servers.nil. +dom8744. NS a.root-servers.nil. +dom8745. NS a.root-servers.nil. +dom8746. NS a.root-servers.nil. +dom8747. NS a.root-servers.nil. +dom8748. NS a.root-servers.nil. +dom8749. NS a.root-servers.nil. +dom8750. NS a.root-servers.nil. +dom8751. NS a.root-servers.nil. +dom8752. NS a.root-servers.nil. +dom8753. NS a.root-servers.nil. +dom8754. NS a.root-servers.nil. +dom8755. NS a.root-servers.nil. +dom8756. NS a.root-servers.nil. +dom8757. NS a.root-servers.nil. +dom8758. NS a.root-servers.nil. +dom8759. NS a.root-servers.nil. +dom8760. NS a.root-servers.nil. +dom8761. NS a.root-servers.nil. +dom8762. NS a.root-servers.nil. +dom8763. NS a.root-servers.nil. +dom8764. NS a.root-servers.nil. +dom8765. NS a.root-servers.nil. +dom8766. NS a.root-servers.nil. +dom8767. NS a.root-servers.nil. +dom8768. NS a.root-servers.nil. +dom8769. NS a.root-servers.nil. +dom8770. NS a.root-servers.nil. +dom8771. NS a.root-servers.nil. +dom8772. NS a.root-servers.nil. +dom8773. NS a.root-servers.nil. +dom8774. NS a.root-servers.nil. +dom8775. NS a.root-servers.nil. +dom8776. NS a.root-servers.nil. +dom8777. NS a.root-servers.nil. +dom8778. NS a.root-servers.nil. +dom8779. NS a.root-servers.nil. +dom8780. NS a.root-servers.nil. +dom8781. NS a.root-servers.nil. +dom8782. NS a.root-servers.nil. +dom8783. NS a.root-servers.nil. +dom8784. NS a.root-servers.nil. +dom8785. NS a.root-servers.nil. +dom8786. NS a.root-servers.nil. +dom8787. NS a.root-servers.nil. +dom8788. NS a.root-servers.nil. +dom8789. NS a.root-servers.nil. +dom8790. NS a.root-servers.nil. +dom8791. NS a.root-servers.nil. +dom8792. NS a.root-servers.nil. +dom8793. NS a.root-servers.nil. +dom8794. NS a.root-servers.nil. +dom8795. NS a.root-servers.nil. +dom8796. NS a.root-servers.nil. +dom8797. NS a.root-servers.nil. +dom8798. NS a.root-servers.nil. +dom8799. NS a.root-servers.nil. +dom8800. NS a.root-servers.nil. +dom8801. NS a.root-servers.nil. +dom8802. NS a.root-servers.nil. +dom8803. NS a.root-servers.nil. +dom8804. NS a.root-servers.nil. +dom8805. NS a.root-servers.nil. +dom8806. NS a.root-servers.nil. +dom8807. NS a.root-servers.nil. +dom8808. NS a.root-servers.nil. +dom8809. NS a.root-servers.nil. +dom8810. NS a.root-servers.nil. +dom8811. NS a.root-servers.nil. +dom8812. NS a.root-servers.nil. +dom8813. NS a.root-servers.nil. +dom8814. NS a.root-servers.nil. +dom8815. NS a.root-servers.nil. +dom8816. NS a.root-servers.nil. +dom8817. NS a.root-servers.nil. +dom8818. NS a.root-servers.nil. +dom8819. NS a.root-servers.nil. +dom8820. NS a.root-servers.nil. +dom8821. NS a.root-servers.nil. +dom8822. NS a.root-servers.nil. +dom8823. NS a.root-servers.nil. +dom8824. NS a.root-servers.nil. +dom8825. NS a.root-servers.nil. +dom8826. NS a.root-servers.nil. +dom8827. NS a.root-servers.nil. +dom8828. NS a.root-servers.nil. +dom8829. NS a.root-servers.nil. +dom8830. NS a.root-servers.nil. +dom8831. NS a.root-servers.nil. +dom8832. NS a.root-servers.nil. +dom8833. NS a.root-servers.nil. +dom8834. NS a.root-servers.nil. +dom8835. NS a.root-servers.nil. +dom8836. NS a.root-servers.nil. +dom8837. NS a.root-servers.nil. +dom8838. NS a.root-servers.nil. +dom8839. NS a.root-servers.nil. +dom8840. NS a.root-servers.nil. +dom8841. NS a.root-servers.nil. +dom8842. NS a.root-servers.nil. +dom8843. NS a.root-servers.nil. +dom8844. NS a.root-servers.nil. +dom8845. NS a.root-servers.nil. +dom8846. NS a.root-servers.nil. +dom8847. NS a.root-servers.nil. +dom8848. NS a.root-servers.nil. +dom8849. NS a.root-servers.nil. +dom8850. NS a.root-servers.nil. +dom8851. NS a.root-servers.nil. +dom8852. NS a.root-servers.nil. +dom8853. NS a.root-servers.nil. +dom8854. NS a.root-servers.nil. +dom8855. NS a.root-servers.nil. +dom8856. NS a.root-servers.nil. +dom8857. NS a.root-servers.nil. +dom8858. NS a.root-servers.nil. +dom8859. NS a.root-servers.nil. +dom8860. NS a.root-servers.nil. +dom8861. NS a.root-servers.nil. +dom8862. NS a.root-servers.nil. +dom8863. NS a.root-servers.nil. +dom8864. NS a.root-servers.nil. +dom8865. NS a.root-servers.nil. +dom8866. NS a.root-servers.nil. +dom8867. NS a.root-servers.nil. +dom8868. NS a.root-servers.nil. +dom8869. NS a.root-servers.nil. +dom8870. NS a.root-servers.nil. +dom8871. NS a.root-servers.nil. +dom8872. NS a.root-servers.nil. +dom8873. NS a.root-servers.nil. +dom8874. NS a.root-servers.nil. +dom8875. NS a.root-servers.nil. +dom8876. NS a.root-servers.nil. +dom8877. NS a.root-servers.nil. +dom8878. NS a.root-servers.nil. +dom8879. NS a.root-servers.nil. +dom8880. NS a.root-servers.nil. +dom8881. NS a.root-servers.nil. +dom8882. NS a.root-servers.nil. +dom8883. NS a.root-servers.nil. +dom8884. NS a.root-servers.nil. +dom8885. NS a.root-servers.nil. +dom8886. NS a.root-servers.nil. +dom8887. NS a.root-servers.nil. +dom8888. NS a.root-servers.nil. +dom8889. NS a.root-servers.nil. +dom8890. NS a.root-servers.nil. +dom8891. NS a.root-servers.nil. +dom8892. NS a.root-servers.nil. +dom8893. NS a.root-servers.nil. +dom8894. NS a.root-servers.nil. +dom8895. NS a.root-servers.nil. +dom8896. NS a.root-servers.nil. +dom8897. NS a.root-servers.nil. +dom8898. NS a.root-servers.nil. +dom8899. NS a.root-servers.nil. +dom8900. NS a.root-servers.nil. +dom8901. NS a.root-servers.nil. +dom8902. NS a.root-servers.nil. +dom8903. NS a.root-servers.nil. +dom8904. NS a.root-servers.nil. +dom8905. NS a.root-servers.nil. +dom8906. NS a.root-servers.nil. +dom8907. NS a.root-servers.nil. +dom8908. NS a.root-servers.nil. +dom8909. NS a.root-servers.nil. +dom8910. NS a.root-servers.nil. +dom8911. NS a.root-servers.nil. +dom8912. NS a.root-servers.nil. +dom8913. NS a.root-servers.nil. +dom8914. NS a.root-servers.nil. +dom8915. NS a.root-servers.nil. +dom8916. NS a.root-servers.nil. +dom8917. NS a.root-servers.nil. +dom8918. NS a.root-servers.nil. +dom8919. NS a.root-servers.nil. +dom8920. NS a.root-servers.nil. +dom8921. NS a.root-servers.nil. +dom8922. NS a.root-servers.nil. +dom8923. NS a.root-servers.nil. +dom8924. NS a.root-servers.nil. +dom8925. NS a.root-servers.nil. +dom8926. NS a.root-servers.nil. +dom8927. NS a.root-servers.nil. +dom8928. NS a.root-servers.nil. +dom8929. NS a.root-servers.nil. +dom8930. NS a.root-servers.nil. +dom8931. NS a.root-servers.nil. +dom8932. NS a.root-servers.nil. +dom8933. NS a.root-servers.nil. +dom8934. NS a.root-servers.nil. +dom8935. NS a.root-servers.nil. +dom8936. NS a.root-servers.nil. +dom8937. NS a.root-servers.nil. +dom8938. NS a.root-servers.nil. +dom8939. NS a.root-servers.nil. +dom8940. NS a.root-servers.nil. +dom8941. NS a.root-servers.nil. +dom8942. NS a.root-servers.nil. +dom8943. NS a.root-servers.nil. +dom8944. NS a.root-servers.nil. +dom8945. NS a.root-servers.nil. +dom8946. NS a.root-servers.nil. +dom8947. NS a.root-servers.nil. +dom8948. NS a.root-servers.nil. +dom8949. NS a.root-servers.nil. +dom8950. NS a.root-servers.nil. +dom8951. NS a.root-servers.nil. +dom8952. NS a.root-servers.nil. +dom8953. NS a.root-servers.nil. +dom8954. NS a.root-servers.nil. +dom8955. NS a.root-servers.nil. +dom8956. NS a.root-servers.nil. +dom8957. NS a.root-servers.nil. +dom8958. NS a.root-servers.nil. +dom8959. NS a.root-servers.nil. +dom8960. NS a.root-servers.nil. +dom8961. NS a.root-servers.nil. +dom8962. NS a.root-servers.nil. +dom8963. NS a.root-servers.nil. +dom8964. NS a.root-servers.nil. +dom8965. NS a.root-servers.nil. +dom8966. NS a.root-servers.nil. +dom8967. NS a.root-servers.nil. +dom8968. NS a.root-servers.nil. +dom8969. NS a.root-servers.nil. +dom8970. NS a.root-servers.nil. +dom8971. NS a.root-servers.nil. +dom8972. NS a.root-servers.nil. +dom8973. NS a.root-servers.nil. +dom8974. NS a.root-servers.nil. +dom8975. NS a.root-servers.nil. +dom8976. NS a.root-servers.nil. +dom8977. NS a.root-servers.nil. +dom8978. NS a.root-servers.nil. +dom8979. NS a.root-servers.nil. +dom8980. NS a.root-servers.nil. +dom8981. NS a.root-servers.nil. +dom8982. NS a.root-servers.nil. +dom8983. NS a.root-servers.nil. +dom8984. NS a.root-servers.nil. +dom8985. NS a.root-servers.nil. +dom8986. NS a.root-servers.nil. +dom8987. NS a.root-servers.nil. +dom8988. NS a.root-servers.nil. +dom8989. NS a.root-servers.nil. +dom8990. NS a.root-servers.nil. +dom8991. NS a.root-servers.nil. +dom8992. NS a.root-servers.nil. +dom8993. NS a.root-servers.nil. +dom8994. NS a.root-servers.nil. +dom8995. NS a.root-servers.nil. +dom8996. NS a.root-servers.nil. +dom8997. NS a.root-servers.nil. +dom8998. NS a.root-servers.nil. +dom8999. NS a.root-servers.nil. +dom9000. NS a.root-servers.nil. +dom9001. NS a.root-servers.nil. +dom9002. NS a.root-servers.nil. +dom9003. NS a.root-servers.nil. +dom9004. NS a.root-servers.nil. +dom9005. NS a.root-servers.nil. +dom9006. NS a.root-servers.nil. +dom9007. NS a.root-servers.nil. +dom9008. NS a.root-servers.nil. +dom9009. NS a.root-servers.nil. +dom9010. NS a.root-servers.nil. +dom9011. NS a.root-servers.nil. +dom9012. NS a.root-servers.nil. +dom9013. NS a.root-servers.nil. +dom9014. NS a.root-servers.nil. +dom9015. NS a.root-servers.nil. +dom9016. NS a.root-servers.nil. +dom9017. NS a.root-servers.nil. +dom9018. NS a.root-servers.nil. +dom9019. NS a.root-servers.nil. +dom9020. NS a.root-servers.nil. +dom9021. NS a.root-servers.nil. +dom9022. NS a.root-servers.nil. +dom9023. NS a.root-servers.nil. +dom9024. NS a.root-servers.nil. +dom9025. NS a.root-servers.nil. +dom9026. NS a.root-servers.nil. +dom9027. NS a.root-servers.nil. +dom9028. NS a.root-servers.nil. +dom9029. NS a.root-servers.nil. +dom9030. NS a.root-servers.nil. +dom9031. NS a.root-servers.nil. +dom9032. NS a.root-servers.nil. +dom9033. NS a.root-servers.nil. +dom9034. NS a.root-servers.nil. +dom9035. NS a.root-servers.nil. +dom9036. NS a.root-servers.nil. +dom9037. NS a.root-servers.nil. +dom9038. NS a.root-servers.nil. +dom9039. NS a.root-servers.nil. +dom9040. NS a.root-servers.nil. +dom9041. NS a.root-servers.nil. +dom9042. NS a.root-servers.nil. +dom9043. NS a.root-servers.nil. +dom9044. NS a.root-servers.nil. +dom9045. NS a.root-servers.nil. +dom9046. NS a.root-servers.nil. +dom9047. NS a.root-servers.nil. +dom9048. NS a.root-servers.nil. +dom9049. NS a.root-servers.nil. +dom9050. NS a.root-servers.nil. +dom9051. NS a.root-servers.nil. +dom9052. NS a.root-servers.nil. +dom9053. NS a.root-servers.nil. +dom9054. NS a.root-servers.nil. +dom9055. NS a.root-servers.nil. +dom9056. NS a.root-servers.nil. +dom9057. NS a.root-servers.nil. +dom9058. NS a.root-servers.nil. +dom9059. NS a.root-servers.nil. +dom9060. NS a.root-servers.nil. +dom9061. NS a.root-servers.nil. +dom9062. NS a.root-servers.nil. +dom9063. NS a.root-servers.nil. +dom9064. NS a.root-servers.nil. +dom9065. NS a.root-servers.nil. +dom9066. NS a.root-servers.nil. +dom9067. NS a.root-servers.nil. +dom9068. NS a.root-servers.nil. +dom9069. NS a.root-servers.nil. +dom9070. NS a.root-servers.nil. +dom9071. NS a.root-servers.nil. +dom9072. NS a.root-servers.nil. +dom9073. NS a.root-servers.nil. +dom9074. NS a.root-servers.nil. +dom9075. NS a.root-servers.nil. +dom9076. NS a.root-servers.nil. +dom9077. NS a.root-servers.nil. +dom9078. NS a.root-servers.nil. +dom9079. NS a.root-servers.nil. +dom9080. NS a.root-servers.nil. +dom9081. NS a.root-servers.nil. +dom9082. NS a.root-servers.nil. +dom9083. NS a.root-servers.nil. +dom9084. NS a.root-servers.nil. +dom9085. NS a.root-servers.nil. +dom9086. NS a.root-servers.nil. +dom9087. NS a.root-servers.nil. +dom9088. NS a.root-servers.nil. +dom9089. NS a.root-servers.nil. +dom9090. NS a.root-servers.nil. +dom9091. NS a.root-servers.nil. +dom9092. NS a.root-servers.nil. +dom9093. NS a.root-servers.nil. +dom9094. NS a.root-servers.nil. +dom9095. NS a.root-servers.nil. +dom9096. NS a.root-servers.nil. +dom9097. NS a.root-servers.nil. +dom9098. NS a.root-servers.nil. +dom9099. NS a.root-servers.nil. +dom9100. NS a.root-servers.nil. +dom9101. NS a.root-servers.nil. +dom9102. NS a.root-servers.nil. +dom9103. NS a.root-servers.nil. +dom9104. NS a.root-servers.nil. +dom9105. NS a.root-servers.nil. +dom9106. NS a.root-servers.nil. +dom9107. NS a.root-servers.nil. +dom9108. NS a.root-servers.nil. +dom9109. NS a.root-servers.nil. +dom9110. NS a.root-servers.nil. +dom9111. NS a.root-servers.nil. +dom9112. NS a.root-servers.nil. +dom9113. NS a.root-servers.nil. +dom9114. NS a.root-servers.nil. +dom9115. NS a.root-servers.nil. +dom9116. NS a.root-servers.nil. +dom9117. NS a.root-servers.nil. +dom9118. NS a.root-servers.nil. +dom9119. NS a.root-servers.nil. +dom9120. NS a.root-servers.nil. +dom9121. NS a.root-servers.nil. +dom9122. NS a.root-servers.nil. +dom9123. NS a.root-servers.nil. +dom9124. NS a.root-servers.nil. +dom9125. NS a.root-servers.nil. +dom9126. NS a.root-servers.nil. +dom9127. NS a.root-servers.nil. +dom9128. NS a.root-servers.nil. +dom9129. NS a.root-servers.nil. +dom9130. NS a.root-servers.nil. +dom9131. NS a.root-servers.nil. +dom9132. NS a.root-servers.nil. +dom9133. NS a.root-servers.nil. +dom9134. NS a.root-servers.nil. +dom9135. NS a.root-servers.nil. +dom9136. NS a.root-servers.nil. +dom9137. NS a.root-servers.nil. +dom9138. NS a.root-servers.nil. +dom9139. NS a.root-servers.nil. +dom9140. NS a.root-servers.nil. +dom9141. NS a.root-servers.nil. +dom9142. NS a.root-servers.nil. +dom9143. NS a.root-servers.nil. +dom9144. NS a.root-servers.nil. +dom9145. NS a.root-servers.nil. +dom9146. NS a.root-servers.nil. +dom9147. NS a.root-servers.nil. +dom9148. NS a.root-servers.nil. +dom9149. NS a.root-servers.nil. +dom9150. NS a.root-servers.nil. +dom9151. NS a.root-servers.nil. +dom9152. NS a.root-servers.nil. +dom9153. NS a.root-servers.nil. +dom9154. NS a.root-servers.nil. +dom9155. NS a.root-servers.nil. +dom9156. NS a.root-servers.nil. +dom9157. NS a.root-servers.nil. +dom9158. NS a.root-servers.nil. +dom9159. NS a.root-servers.nil. +dom9160. NS a.root-servers.nil. +dom9161. NS a.root-servers.nil. +dom9162. NS a.root-servers.nil. +dom9163. NS a.root-servers.nil. +dom9164. NS a.root-servers.nil. +dom9165. NS a.root-servers.nil. +dom9166. NS a.root-servers.nil. +dom9167. NS a.root-servers.nil. +dom9168. NS a.root-servers.nil. +dom9169. NS a.root-servers.nil. +dom9170. NS a.root-servers.nil. +dom9171. NS a.root-servers.nil. +dom9172. NS a.root-servers.nil. +dom9173. NS a.root-servers.nil. +dom9174. NS a.root-servers.nil. +dom9175. NS a.root-servers.nil. +dom9176. NS a.root-servers.nil. +dom9177. NS a.root-servers.nil. +dom9178. NS a.root-servers.nil. +dom9179. NS a.root-servers.nil. +dom9180. NS a.root-servers.nil. +dom9181. NS a.root-servers.nil. +dom9182. NS a.root-servers.nil. +dom9183. NS a.root-servers.nil. +dom9184. NS a.root-servers.nil. +dom9185. NS a.root-servers.nil. +dom9186. NS a.root-servers.nil. +dom9187. NS a.root-servers.nil. +dom9188. NS a.root-servers.nil. +dom9189. NS a.root-servers.nil. +dom9190. NS a.root-servers.nil. +dom9191. NS a.root-servers.nil. +dom9192. NS a.root-servers.nil. +dom9193. NS a.root-servers.nil. +dom9194. NS a.root-servers.nil. +dom9195. NS a.root-servers.nil. +dom9196. NS a.root-servers.nil. +dom9197. NS a.root-servers.nil. +dom9198. NS a.root-servers.nil. +dom9199. NS a.root-servers.nil. +dom9200. NS a.root-servers.nil. +dom9201. NS a.root-servers.nil. +dom9202. NS a.root-servers.nil. +dom9203. NS a.root-servers.nil. +dom9204. NS a.root-servers.nil. +dom9205. NS a.root-servers.nil. +dom9206. NS a.root-servers.nil. +dom9207. NS a.root-servers.nil. +dom9208. NS a.root-servers.nil. +dom9209. NS a.root-servers.nil. +dom9210. NS a.root-servers.nil. +dom9211. NS a.root-servers.nil. +dom9212. NS a.root-servers.nil. +dom9213. NS a.root-servers.nil. +dom9214. NS a.root-servers.nil. +dom9215. NS a.root-servers.nil. +dom9216. NS a.root-servers.nil. +dom9217. NS a.root-servers.nil. +dom9218. NS a.root-servers.nil. +dom9219. NS a.root-servers.nil. +dom9220. NS a.root-servers.nil. +dom9221. NS a.root-servers.nil. +dom9222. NS a.root-servers.nil. +dom9223. NS a.root-servers.nil. +dom9224. NS a.root-servers.nil. +dom9225. NS a.root-servers.nil. +dom9226. NS a.root-servers.nil. +dom9227. NS a.root-servers.nil. +dom9228. NS a.root-servers.nil. +dom9229. NS a.root-servers.nil. +dom9230. NS a.root-servers.nil. +dom9231. NS a.root-servers.nil. +dom9232. NS a.root-servers.nil. +dom9233. NS a.root-servers.nil. +dom9234. NS a.root-servers.nil. +dom9235. NS a.root-servers.nil. +dom9236. NS a.root-servers.nil. +dom9237. NS a.root-servers.nil. +dom9238. NS a.root-servers.nil. +dom9239. NS a.root-servers.nil. +dom9240. NS a.root-servers.nil. +dom9241. NS a.root-servers.nil. +dom9242. NS a.root-servers.nil. +dom9243. NS a.root-servers.nil. +dom9244. NS a.root-servers.nil. +dom9245. NS a.root-servers.nil. +dom9246. NS a.root-servers.nil. +dom9247. NS a.root-servers.nil. +dom9248. NS a.root-servers.nil. +dom9249. NS a.root-servers.nil. +dom9250. NS a.root-servers.nil. +dom9251. NS a.root-servers.nil. +dom9252. NS a.root-servers.nil. +dom9253. NS a.root-servers.nil. +dom9254. NS a.root-servers.nil. +dom9255. NS a.root-servers.nil. +dom9256. NS a.root-servers.nil. +dom9257. NS a.root-servers.nil. +dom9258. NS a.root-servers.nil. +dom9259. NS a.root-servers.nil. +dom9260. NS a.root-servers.nil. +dom9261. NS a.root-servers.nil. +dom9262. NS a.root-servers.nil. +dom9263. NS a.root-servers.nil. +dom9264. NS a.root-servers.nil. +dom9265. NS a.root-servers.nil. +dom9266. NS a.root-servers.nil. +dom9267. NS a.root-servers.nil. +dom9268. NS a.root-servers.nil. +dom9269. NS a.root-servers.nil. +dom9270. NS a.root-servers.nil. +dom9271. NS a.root-servers.nil. +dom9272. NS a.root-servers.nil. +dom9273. NS a.root-servers.nil. +dom9274. NS a.root-servers.nil. +dom9275. NS a.root-servers.nil. +dom9276. NS a.root-servers.nil. +dom9277. NS a.root-servers.nil. +dom9278. NS a.root-servers.nil. +dom9279. NS a.root-servers.nil. +dom9280. NS a.root-servers.nil. +dom9281. NS a.root-servers.nil. +dom9282. NS a.root-servers.nil. +dom9283. NS a.root-servers.nil. +dom9284. NS a.root-servers.nil. +dom9285. NS a.root-servers.nil. +dom9286. NS a.root-servers.nil. +dom9287. NS a.root-servers.nil. +dom9288. NS a.root-servers.nil. +dom9289. NS a.root-servers.nil. +dom9290. NS a.root-servers.nil. +dom9291. NS a.root-servers.nil. +dom9292. NS a.root-servers.nil. +dom9293. NS a.root-servers.nil. +dom9294. NS a.root-servers.nil. +dom9295. NS a.root-servers.nil. +dom9296. NS a.root-servers.nil. +dom9297. NS a.root-servers.nil. +dom9298. NS a.root-servers.nil. +dom9299. NS a.root-servers.nil. +dom9300. NS a.root-servers.nil. +dom9301. NS a.root-servers.nil. +dom9302. NS a.root-servers.nil. +dom9303. NS a.root-servers.nil. +dom9304. NS a.root-servers.nil. +dom9305. NS a.root-servers.nil. +dom9306. NS a.root-servers.nil. +dom9307. NS a.root-servers.nil. +dom9308. NS a.root-servers.nil. +dom9309. NS a.root-servers.nil. +dom9310. NS a.root-servers.nil. +dom9311. NS a.root-servers.nil. +dom9312. NS a.root-servers.nil. +dom9313. NS a.root-servers.nil. +dom9314. NS a.root-servers.nil. +dom9315. NS a.root-servers.nil. +dom9316. NS a.root-servers.nil. +dom9317. NS a.root-servers.nil. +dom9318. NS a.root-servers.nil. +dom9319. NS a.root-servers.nil. +dom9320. NS a.root-servers.nil. +dom9321. NS a.root-servers.nil. +dom9322. NS a.root-servers.nil. +dom9323. NS a.root-servers.nil. +dom9324. NS a.root-servers.nil. +dom9325. NS a.root-servers.nil. +dom9326. NS a.root-servers.nil. +dom9327. NS a.root-servers.nil. +dom9328. NS a.root-servers.nil. +dom9329. NS a.root-servers.nil. +dom9330. NS a.root-servers.nil. +dom9331. NS a.root-servers.nil. +dom9332. NS a.root-servers.nil. +dom9333. NS a.root-servers.nil. +dom9334. NS a.root-servers.nil. +dom9335. NS a.root-servers.nil. +dom9336. NS a.root-servers.nil. +dom9337. NS a.root-servers.nil. +dom9338. NS a.root-servers.nil. +dom9339. NS a.root-servers.nil. +dom9340. NS a.root-servers.nil. +dom9341. NS a.root-servers.nil. +dom9342. NS a.root-servers.nil. +dom9343. NS a.root-servers.nil. +dom9344. NS a.root-servers.nil. +dom9345. NS a.root-servers.nil. +dom9346. NS a.root-servers.nil. +dom9347. NS a.root-servers.nil. +dom9348. NS a.root-servers.nil. +dom9349. NS a.root-servers.nil. +dom9350. NS a.root-servers.nil. +dom9351. NS a.root-servers.nil. +dom9352. NS a.root-servers.nil. +dom9353. NS a.root-servers.nil. +dom9354. NS a.root-servers.nil. +dom9355. NS a.root-servers.nil. +dom9356. NS a.root-servers.nil. +dom9357. NS a.root-servers.nil. +dom9358. NS a.root-servers.nil. +dom9359. NS a.root-servers.nil. +dom9360. NS a.root-servers.nil. +dom9361. NS a.root-servers.nil. +dom9362. NS a.root-servers.nil. +dom9363. NS a.root-servers.nil. +dom9364. NS a.root-servers.nil. +dom9365. NS a.root-servers.nil. +dom9366. NS a.root-servers.nil. +dom9367. NS a.root-servers.nil. +dom9368. NS a.root-servers.nil. +dom9369. NS a.root-servers.nil. +dom9370. NS a.root-servers.nil. +dom9371. NS a.root-servers.nil. +dom9372. NS a.root-servers.nil. +dom9373. NS a.root-servers.nil. +dom9374. NS a.root-servers.nil. +dom9375. NS a.root-servers.nil. +dom9376. NS a.root-servers.nil. +dom9377. NS a.root-servers.nil. +dom9378. NS a.root-servers.nil. +dom9379. NS a.root-servers.nil. +dom9380. NS a.root-servers.nil. +dom9381. NS a.root-servers.nil. +dom9382. NS a.root-servers.nil. +dom9383. NS a.root-servers.nil. +dom9384. NS a.root-servers.nil. +dom9385. NS a.root-servers.nil. +dom9386. NS a.root-servers.nil. +dom9387. NS a.root-servers.nil. +dom9388. NS a.root-servers.nil. +dom9389. NS a.root-servers.nil. +dom9390. NS a.root-servers.nil. +dom9391. NS a.root-servers.nil. +dom9392. NS a.root-servers.nil. +dom9393. NS a.root-servers.nil. +dom9394. NS a.root-servers.nil. +dom9395. NS a.root-servers.nil. +dom9396. NS a.root-servers.nil. +dom9397. NS a.root-servers.nil. +dom9398. NS a.root-servers.nil. +dom9399. NS a.root-servers.nil. +dom9400. NS a.root-servers.nil. +dom9401. NS a.root-servers.nil. +dom9402. NS a.root-servers.nil. +dom9403. NS a.root-servers.nil. +dom9404. NS a.root-servers.nil. +dom9405. NS a.root-servers.nil. +dom9406. NS a.root-servers.nil. +dom9407. NS a.root-servers.nil. +dom9408. NS a.root-servers.nil. +dom9409. NS a.root-servers.nil. +dom9410. NS a.root-servers.nil. +dom9411. NS a.root-servers.nil. +dom9412. NS a.root-servers.nil. +dom9413. NS a.root-servers.nil. +dom9414. NS a.root-servers.nil. +dom9415. NS a.root-servers.nil. +dom9416. NS a.root-servers.nil. +dom9417. NS a.root-servers.nil. +dom9418. NS a.root-servers.nil. +dom9419. NS a.root-servers.nil. +dom9420. NS a.root-servers.nil. +dom9421. NS a.root-servers.nil. +dom9422. NS a.root-servers.nil. +dom9423. NS a.root-servers.nil. +dom9424. NS a.root-servers.nil. +dom9425. NS a.root-servers.nil. +dom9426. NS a.root-servers.nil. +dom9427. NS a.root-servers.nil. +dom9428. NS a.root-servers.nil. +dom9429. NS a.root-servers.nil. +dom9430. NS a.root-servers.nil. +dom9431. NS a.root-servers.nil. +dom9432. NS a.root-servers.nil. +dom9433. NS a.root-servers.nil. +dom9434. NS a.root-servers.nil. +dom9435. NS a.root-servers.nil. +dom9436. NS a.root-servers.nil. +dom9437. NS a.root-servers.nil. +dom9438. NS a.root-servers.nil. +dom9439. NS a.root-servers.nil. +dom9440. NS a.root-servers.nil. +dom9441. NS a.root-servers.nil. +dom9442. NS a.root-servers.nil. +dom9443. NS a.root-servers.nil. +dom9444. NS a.root-servers.nil. +dom9445. NS a.root-servers.nil. +dom9446. NS a.root-servers.nil. +dom9447. NS a.root-servers.nil. +dom9448. NS a.root-servers.nil. +dom9449. NS a.root-servers.nil. +dom9450. NS a.root-servers.nil. +dom9451. NS a.root-servers.nil. +dom9452. NS a.root-servers.nil. +dom9453. NS a.root-servers.nil. +dom9454. NS a.root-servers.nil. +dom9455. NS a.root-servers.nil. +dom9456. NS a.root-servers.nil. +dom9457. NS a.root-servers.nil. +dom9458. NS a.root-servers.nil. +dom9459. NS a.root-servers.nil. +dom9460. NS a.root-servers.nil. +dom9461. NS a.root-servers.nil. +dom9462. NS a.root-servers.nil. +dom9463. NS a.root-servers.nil. +dom9464. NS a.root-servers.nil. +dom9465. NS a.root-servers.nil. +dom9466. NS a.root-servers.nil. +dom9467. NS a.root-servers.nil. +dom9468. NS a.root-servers.nil. +dom9469. NS a.root-servers.nil. +dom9470. NS a.root-servers.nil. +dom9471. NS a.root-servers.nil. +dom9472. NS a.root-servers.nil. +dom9473. NS a.root-servers.nil. +dom9474. NS a.root-servers.nil. +dom9475. NS a.root-servers.nil. +dom9476. NS a.root-servers.nil. +dom9477. NS a.root-servers.nil. +dom9478. NS a.root-servers.nil. +dom9479. NS a.root-servers.nil. +dom9480. NS a.root-servers.nil. +dom9481. NS a.root-servers.nil. +dom9482. NS a.root-servers.nil. +dom9483. NS a.root-servers.nil. +dom9484. NS a.root-servers.nil. +dom9485. NS a.root-servers.nil. +dom9486. NS a.root-servers.nil. +dom9487. NS a.root-servers.nil. +dom9488. NS a.root-servers.nil. +dom9489. NS a.root-servers.nil. +dom9490. NS a.root-servers.nil. +dom9491. NS a.root-servers.nil. +dom9492. NS a.root-servers.nil. +dom9493. NS a.root-servers.nil. +dom9494. NS a.root-servers.nil. +dom9495. NS a.root-servers.nil. +dom9496. NS a.root-servers.nil. +dom9497. NS a.root-servers.nil. +dom9498. NS a.root-servers.nil. +dom9499. NS a.root-servers.nil. +dom9500. NS a.root-servers.nil. +dom9501. NS a.root-servers.nil. +dom9502. NS a.root-servers.nil. +dom9503. NS a.root-servers.nil. +dom9504. NS a.root-servers.nil. +dom9505. NS a.root-servers.nil. +dom9506. NS a.root-servers.nil. +dom9507. NS a.root-servers.nil. +dom9508. NS a.root-servers.nil. +dom9509. NS a.root-servers.nil. +dom9510. NS a.root-servers.nil. +dom9511. NS a.root-servers.nil. +dom9512. NS a.root-servers.nil. +dom9513. NS a.root-servers.nil. +dom9514. NS a.root-servers.nil. +dom9515. NS a.root-servers.nil. +dom9516. NS a.root-servers.nil. +dom9517. NS a.root-servers.nil. +dom9518. NS a.root-servers.nil. +dom9519. NS a.root-servers.nil. +dom9520. NS a.root-servers.nil. +dom9521. NS a.root-servers.nil. +dom9522. NS a.root-servers.nil. +dom9523. NS a.root-servers.nil. +dom9524. NS a.root-servers.nil. +dom9525. NS a.root-servers.nil. +dom9526. NS a.root-servers.nil. +dom9527. NS a.root-servers.nil. +dom9528. NS a.root-servers.nil. +dom9529. NS a.root-servers.nil. +dom9530. NS a.root-servers.nil. +dom9531. NS a.root-servers.nil. +dom9532. NS a.root-servers.nil. +dom9533. NS a.root-servers.nil. +dom9534. NS a.root-servers.nil. +dom9535. NS a.root-servers.nil. +dom9536. NS a.root-servers.nil. +dom9537. NS a.root-servers.nil. +dom9538. NS a.root-servers.nil. +dom9539. NS a.root-servers.nil. +dom9540. NS a.root-servers.nil. +dom9541. NS a.root-servers.nil. +dom9542. NS a.root-servers.nil. +dom9543. NS a.root-servers.nil. +dom9544. NS a.root-servers.nil. +dom9545. NS a.root-servers.nil. +dom9546. NS a.root-servers.nil. +dom9547. NS a.root-servers.nil. +dom9548. NS a.root-servers.nil. +dom9549. NS a.root-servers.nil. +dom9550. NS a.root-servers.nil. +dom9551. NS a.root-servers.nil. +dom9552. NS a.root-servers.nil. +dom9553. NS a.root-servers.nil. +dom9554. NS a.root-servers.nil. +dom9555. NS a.root-servers.nil. +dom9556. NS a.root-servers.nil. +dom9557. NS a.root-servers.nil. +dom9558. NS a.root-servers.nil. +dom9559. NS a.root-servers.nil. +dom9560. NS a.root-servers.nil. +dom9561. NS a.root-servers.nil. +dom9562. NS a.root-servers.nil. +dom9563. NS a.root-servers.nil. +dom9564. NS a.root-servers.nil. +dom9565. NS a.root-servers.nil. +dom9566. NS a.root-servers.nil. +dom9567. NS a.root-servers.nil. +dom9568. NS a.root-servers.nil. +dom9569. NS a.root-servers.nil. +dom9570. NS a.root-servers.nil. +dom9571. NS a.root-servers.nil. +dom9572. NS a.root-servers.nil. +dom9573. NS a.root-servers.nil. +dom9574. NS a.root-servers.nil. +dom9575. NS a.root-servers.nil. +dom9576. NS a.root-servers.nil. +dom9577. NS a.root-servers.nil. +dom9578. NS a.root-servers.nil. +dom9579. NS a.root-servers.nil. +dom9580. NS a.root-servers.nil. +dom9581. NS a.root-servers.nil. +dom9582. NS a.root-servers.nil. +dom9583. NS a.root-servers.nil. +dom9584. NS a.root-servers.nil. +dom9585. NS a.root-servers.nil. +dom9586. NS a.root-servers.nil. +dom9587. NS a.root-servers.nil. +dom9588. NS a.root-servers.nil. +dom9589. NS a.root-servers.nil. +dom9590. NS a.root-servers.nil. +dom9591. NS a.root-servers.nil. +dom9592. NS a.root-servers.nil. +dom9593. NS a.root-servers.nil. +dom9594. NS a.root-servers.nil. +dom9595. NS a.root-servers.nil. +dom9596. NS a.root-servers.nil. +dom9597. NS a.root-servers.nil. +dom9598. NS a.root-servers.nil. +dom9599. NS a.root-servers.nil. +dom9600. NS a.root-servers.nil. +dom9601. NS a.root-servers.nil. +dom9602. NS a.root-servers.nil. +dom9603. NS a.root-servers.nil. +dom9604. NS a.root-servers.nil. +dom9605. NS a.root-servers.nil. +dom9606. NS a.root-servers.nil. +dom9607. NS a.root-servers.nil. +dom9608. NS a.root-servers.nil. +dom9609. NS a.root-servers.nil. +dom9610. NS a.root-servers.nil. +dom9611. NS a.root-servers.nil. +dom9612. NS a.root-servers.nil. +dom9613. NS a.root-servers.nil. +dom9614. NS a.root-servers.nil. +dom9615. NS a.root-servers.nil. +dom9616. NS a.root-servers.nil. +dom9617. NS a.root-servers.nil. +dom9618. NS a.root-servers.nil. +dom9619. NS a.root-servers.nil. +dom9620. NS a.root-servers.nil. +dom9621. NS a.root-servers.nil. +dom9622. NS a.root-servers.nil. +dom9623. NS a.root-servers.nil. +dom9624. NS a.root-servers.nil. +dom9625. NS a.root-servers.nil. +dom9626. NS a.root-servers.nil. +dom9627. NS a.root-servers.nil. +dom9628. NS a.root-servers.nil. +dom9629. NS a.root-servers.nil. +dom9630. NS a.root-servers.nil. +dom9631. NS a.root-servers.nil. +dom9632. NS a.root-servers.nil. +dom9633. NS a.root-servers.nil. +dom9634. NS a.root-servers.nil. +dom9635. NS a.root-servers.nil. +dom9636. NS a.root-servers.nil. +dom9637. NS a.root-servers.nil. +dom9638. NS a.root-servers.nil. +dom9639. NS a.root-servers.nil. +dom9640. NS a.root-servers.nil. +dom9641. NS a.root-servers.nil. +dom9642. NS a.root-servers.nil. +dom9643. NS a.root-servers.nil. +dom9644. NS a.root-servers.nil. +dom9645. NS a.root-servers.nil. +dom9646. NS a.root-servers.nil. +dom9647. NS a.root-servers.nil. +dom9648. NS a.root-servers.nil. +dom9649. NS a.root-servers.nil. +dom9650. NS a.root-servers.nil. +dom9651. NS a.root-servers.nil. +dom9652. NS a.root-servers.nil. +dom9653. NS a.root-servers.nil. +dom9654. NS a.root-servers.nil. +dom9655. NS a.root-servers.nil. +dom9656. NS a.root-servers.nil. +dom9657. NS a.root-servers.nil. +dom9658. NS a.root-servers.nil. +dom9659. NS a.root-servers.nil. +dom9660. NS a.root-servers.nil. +dom9661. NS a.root-servers.nil. +dom9662. NS a.root-servers.nil. +dom9663. NS a.root-servers.nil. +dom9664. NS a.root-servers.nil. +dom9665. NS a.root-servers.nil. +dom9666. NS a.root-servers.nil. +dom9667. NS a.root-servers.nil. +dom9668. NS a.root-servers.nil. +dom9669. NS a.root-servers.nil. +dom9670. NS a.root-servers.nil. +dom9671. NS a.root-servers.nil. +dom9672. NS a.root-servers.nil. +dom9673. NS a.root-servers.nil. +dom9674. NS a.root-servers.nil. +dom9675. NS a.root-servers.nil. +dom9676. NS a.root-servers.nil. +dom9677. NS a.root-servers.nil. +dom9678. NS a.root-servers.nil. +dom9679. NS a.root-servers.nil. +dom9680. NS a.root-servers.nil. +dom9681. NS a.root-servers.nil. +dom9682. NS a.root-servers.nil. +dom9683. NS a.root-servers.nil. +dom9684. NS a.root-servers.nil. +dom9685. NS a.root-servers.nil. +dom9686. NS a.root-servers.nil. +dom9687. NS a.root-servers.nil. +dom9688. NS a.root-servers.nil. +dom9689. NS a.root-servers.nil. +dom9690. NS a.root-servers.nil. +dom9691. NS a.root-servers.nil. +dom9692. NS a.root-servers.nil. +dom9693. NS a.root-servers.nil. +dom9694. NS a.root-servers.nil. +dom9695. NS a.root-servers.nil. +dom9696. NS a.root-servers.nil. +dom9697. NS a.root-servers.nil. +dom9698. NS a.root-servers.nil. +dom9699. NS a.root-servers.nil. +dom9700. NS a.root-servers.nil. +dom9701. NS a.root-servers.nil. +dom9702. NS a.root-servers.nil. +dom9703. NS a.root-servers.nil. +dom9704. NS a.root-servers.nil. +dom9705. NS a.root-servers.nil. +dom9706. NS a.root-servers.nil. +dom9707. NS a.root-servers.nil. +dom9708. NS a.root-servers.nil. +dom9709. NS a.root-servers.nil. +dom9710. NS a.root-servers.nil. +dom9711. NS a.root-servers.nil. +dom9712. NS a.root-servers.nil. +dom9713. NS a.root-servers.nil. +dom9714. NS a.root-servers.nil. +dom9715. NS a.root-servers.nil. +dom9716. NS a.root-servers.nil. +dom9717. NS a.root-servers.nil. +dom9718. NS a.root-servers.nil. +dom9719. NS a.root-servers.nil. +dom9720. NS a.root-servers.nil. +dom9721. NS a.root-servers.nil. +dom9722. NS a.root-servers.nil. +dom9723. NS a.root-servers.nil. +dom9724. NS a.root-servers.nil. +dom9725. NS a.root-servers.nil. +dom9726. NS a.root-servers.nil. +dom9727. NS a.root-servers.nil. +dom9728. NS a.root-servers.nil. +dom9729. NS a.root-servers.nil. +dom9730. NS a.root-servers.nil. +dom9731. NS a.root-servers.nil. +dom9732. NS a.root-servers.nil. +dom9733. NS a.root-servers.nil. +dom9734. NS a.root-servers.nil. +dom9735. NS a.root-servers.nil. +dom9736. NS a.root-servers.nil. +dom9737. NS a.root-servers.nil. +dom9738. NS a.root-servers.nil. +dom9739. NS a.root-servers.nil. +dom9740. NS a.root-servers.nil. +dom9741. NS a.root-servers.nil. +dom9742. NS a.root-servers.nil. +dom9743. NS a.root-servers.nil. +dom9744. NS a.root-servers.nil. +dom9745. NS a.root-servers.nil. +dom9746. NS a.root-servers.nil. +dom9747. NS a.root-servers.nil. +dom9748. NS a.root-servers.nil. +dom9749. NS a.root-servers.nil. +dom9750. NS a.root-servers.nil. +dom9751. NS a.root-servers.nil. +dom9752. NS a.root-servers.nil. +dom9753. NS a.root-servers.nil. +dom9754. NS a.root-servers.nil. +dom9755. NS a.root-servers.nil. +dom9756. NS a.root-servers.nil. +dom9757. NS a.root-servers.nil. +dom9758. NS a.root-servers.nil. +dom9759. NS a.root-servers.nil. +dom9760. NS a.root-servers.nil. +dom9761. NS a.root-servers.nil. +dom9762. NS a.root-servers.nil. +dom9763. NS a.root-servers.nil. +dom9764. NS a.root-servers.nil. +dom9765. NS a.root-servers.nil. +dom9766. NS a.root-servers.nil. +dom9767. NS a.root-servers.nil. +dom9768. NS a.root-servers.nil. +dom9769. NS a.root-servers.nil. +dom9770. NS a.root-servers.nil. +dom9771. NS a.root-servers.nil. +dom9772. NS a.root-servers.nil. +dom9773. NS a.root-servers.nil. +dom9774. NS a.root-servers.nil. +dom9775. NS a.root-servers.nil. +dom9776. NS a.root-servers.nil. +dom9777. NS a.root-servers.nil. +dom9778. NS a.root-servers.nil. +dom9779. NS a.root-servers.nil. +dom9780. NS a.root-servers.nil. +dom9781. NS a.root-servers.nil. +dom9782. NS a.root-servers.nil. +dom9783. NS a.root-servers.nil. +dom9784. NS a.root-servers.nil. +dom9785. NS a.root-servers.nil. +dom9786. NS a.root-servers.nil. +dom9787. NS a.root-servers.nil. +dom9788. NS a.root-servers.nil. +dom9789. NS a.root-servers.nil. +dom9790. NS a.root-servers.nil. +dom9791. NS a.root-servers.nil. +dom9792. NS a.root-servers.nil. +dom9793. NS a.root-servers.nil. +dom9794. NS a.root-servers.nil. +dom9795. NS a.root-servers.nil. +dom9796. NS a.root-servers.nil. +dom9797. NS a.root-servers.nil. +dom9798. NS a.root-servers.nil. +dom9799. NS a.root-servers.nil. +dom9800. NS a.root-servers.nil. +dom9801. NS a.root-servers.nil. +dom9802. NS a.root-servers.nil. +dom9803. NS a.root-servers.nil. +dom9804. NS a.root-servers.nil. +dom9805. NS a.root-servers.nil. +dom9806. NS a.root-servers.nil. +dom9807. NS a.root-servers.nil. +dom9808. NS a.root-servers.nil. +dom9809. NS a.root-servers.nil. +dom9810. NS a.root-servers.nil. +dom9811. NS a.root-servers.nil. +dom9812. NS a.root-servers.nil. +dom9813. NS a.root-servers.nil. +dom9814. NS a.root-servers.nil. +dom9815. NS a.root-servers.nil. +dom9816. NS a.root-servers.nil. +dom9817. NS a.root-servers.nil. +dom9818. NS a.root-servers.nil. +dom9819. NS a.root-servers.nil. +dom9820. NS a.root-servers.nil. +dom9821. NS a.root-servers.nil. +dom9822. NS a.root-servers.nil. +dom9823. NS a.root-servers.nil. +dom9824. NS a.root-servers.nil. +dom9825. NS a.root-servers.nil. +dom9826. NS a.root-servers.nil. +dom9827. NS a.root-servers.nil. +dom9828. NS a.root-servers.nil. +dom9829. NS a.root-servers.nil. +dom9830. NS a.root-servers.nil. +dom9831. NS a.root-servers.nil. +dom9832. NS a.root-servers.nil. +dom9833. NS a.root-servers.nil. +dom9834. NS a.root-servers.nil. +dom9835. NS a.root-servers.nil. +dom9836. NS a.root-servers.nil. +dom9837. NS a.root-servers.nil. +dom9838. NS a.root-servers.nil. +dom9839. NS a.root-servers.nil. +dom9840. NS a.root-servers.nil. +dom9841. NS a.root-servers.nil. +dom9842. NS a.root-servers.nil. +dom9843. NS a.root-servers.nil. +dom9844. NS a.root-servers.nil. +dom9845. NS a.root-servers.nil. +dom9846. NS a.root-servers.nil. +dom9847. NS a.root-servers.nil. +dom9848. NS a.root-servers.nil. +dom9849. NS a.root-servers.nil. +dom9850. NS a.root-servers.nil. +dom9851. NS a.root-servers.nil. +dom9852. NS a.root-servers.nil. +dom9853. NS a.root-servers.nil. +dom9854. NS a.root-servers.nil. +dom9855. NS a.root-servers.nil. +dom9856. NS a.root-servers.nil. +dom9857. NS a.root-servers.nil. +dom9858. NS a.root-servers.nil. +dom9859. NS a.root-servers.nil. +dom9860. NS a.root-servers.nil. +dom9861. NS a.root-servers.nil. +dom9862. NS a.root-servers.nil. +dom9863. NS a.root-servers.nil. +dom9864. NS a.root-servers.nil. +dom9865. NS a.root-servers.nil. +dom9866. NS a.root-servers.nil. +dom9867. NS a.root-servers.nil. +dom9868. NS a.root-servers.nil. +dom9869. NS a.root-servers.nil. +dom9870. NS a.root-servers.nil. +dom9871. NS a.root-servers.nil. +dom9872. NS a.root-servers.nil. +dom9873. NS a.root-servers.nil. +dom9874. NS a.root-servers.nil. +dom9875. NS a.root-servers.nil. +dom9876. NS a.root-servers.nil. +dom9877. NS a.root-servers.nil. +dom9878. NS a.root-servers.nil. +dom9879. NS a.root-servers.nil. +dom9880. NS a.root-servers.nil. +dom9881. NS a.root-servers.nil. +dom9882. NS a.root-servers.nil. +dom9883. NS a.root-servers.nil. +dom9884. NS a.root-servers.nil. +dom9885. NS a.root-servers.nil. +dom9886. NS a.root-servers.nil. +dom9887. NS a.root-servers.nil. +dom9888. NS a.root-servers.nil. +dom9889. NS a.root-servers.nil. +dom9890. NS a.root-servers.nil. +dom9891. NS a.root-servers.nil. +dom9892. NS a.root-servers.nil. +dom9893. NS a.root-servers.nil. +dom9894. NS a.root-servers.nil. +dom9895. NS a.root-servers.nil. +dom9896. NS a.root-servers.nil. +dom9897. NS a.root-servers.nil. +dom9898. NS a.root-servers.nil. +dom9899. NS a.root-servers.nil. +dom9900. NS a.root-servers.nil. +dom9901. NS a.root-servers.nil. +dom9902. NS a.root-servers.nil. +dom9903. NS a.root-servers.nil. +dom9904. NS a.root-servers.nil. +dom9905. NS a.root-servers.nil. +dom9906. NS a.root-servers.nil. +dom9907. NS a.root-servers.nil. +dom9908. NS a.root-servers.nil. +dom9909. NS a.root-servers.nil. +dom9910. NS a.root-servers.nil. +dom9911. NS a.root-servers.nil. +dom9912. NS a.root-servers.nil. +dom9913. NS a.root-servers.nil. +dom9914. NS a.root-servers.nil. +dom9915. NS a.root-servers.nil. +dom9916. NS a.root-servers.nil. +dom9917. NS a.root-servers.nil. +dom9918. NS a.root-servers.nil. +dom9919. NS a.root-servers.nil. +dom9920. NS a.root-servers.nil. +dom9921. NS a.root-servers.nil. +dom9922. NS a.root-servers.nil. +dom9923. NS a.root-servers.nil. +dom9924. NS a.root-servers.nil. +dom9925. NS a.root-servers.nil. +dom9926. NS a.root-servers.nil. +dom9927. NS a.root-servers.nil. +dom9928. NS a.root-servers.nil. +dom9929. NS a.root-servers.nil. +dom9930. NS a.root-servers.nil. +dom9931. NS a.root-servers.nil. +dom9932. NS a.root-servers.nil. +dom9933. NS a.root-servers.nil. +dom9934. NS a.root-servers.nil. +dom9935. NS a.root-servers.nil. +dom9936. NS a.root-servers.nil. +dom9937. NS a.root-servers.nil. +dom9938. NS a.root-servers.nil. +dom9939. NS a.root-servers.nil. +dom9940. NS a.root-servers.nil. +dom9941. NS a.root-servers.nil. +dom9942. NS a.root-servers.nil. +dom9943. NS a.root-servers.nil. +dom9944. NS a.root-servers.nil. +dom9945. NS a.root-servers.nil. +dom9946. NS a.root-servers.nil. +dom9947. NS a.root-servers.nil. +dom9948. NS a.root-servers.nil. +dom9949. NS a.root-servers.nil. +dom9950. NS a.root-servers.nil. +dom9951. NS a.root-servers.nil. +dom9952. NS a.root-servers.nil. +dom9953. NS a.root-servers.nil. +dom9954. NS a.root-servers.nil. +dom9955. NS a.root-servers.nil. +dom9956. NS a.root-servers.nil. +dom9957. NS a.root-servers.nil. +dom9958. NS a.root-servers.nil. +dom9959. NS a.root-servers.nil. +dom9960. NS a.root-servers.nil. +dom9961. NS a.root-servers.nil. +dom9962. NS a.root-servers.nil. +dom9963. NS a.root-servers.nil. +dom9964. NS a.root-servers.nil. +dom9965. NS a.root-servers.nil. +dom9966. NS a.root-servers.nil. +dom9967. NS a.root-servers.nil. +dom9968. NS a.root-servers.nil. +dom9969. NS a.root-servers.nil. +dom9970. NS a.root-servers.nil. +dom9971. NS a.root-servers.nil. +dom9972. NS a.root-servers.nil. +dom9973. NS a.root-servers.nil. +dom9974. NS a.root-servers.nil. +dom9975. NS a.root-servers.nil. +dom9976. NS a.root-servers.nil. +dom9977. NS a.root-servers.nil. +dom9978. NS a.root-servers.nil. +dom9979. NS a.root-servers.nil. +dom9980. NS a.root-servers.nil. +dom9981. NS a.root-servers.nil. +dom9982. NS a.root-servers.nil. +dom9983. NS a.root-servers.nil. +dom9984. NS a.root-servers.nil. +dom9985. NS a.root-servers.nil. +dom9986. NS a.root-servers.nil. +dom9987. NS a.root-servers.nil. +dom9988. NS a.root-servers.nil. +dom9989. NS a.root-servers.nil. +dom9990. NS a.root-servers.nil. +dom9991. NS a.root-servers.nil. +dom9992. NS a.root-servers.nil. +dom9993. NS a.root-servers.nil. +dom9994. NS a.root-servers.nil. +dom9995. NS a.root-servers.nil. +dom9996. NS a.root-servers.nil. +dom9997. NS a.root-servers.nil. +dom9998. NS a.root-servers.nil. +dom9999. NS a.root-servers.nil. diff --git a/bin/tests/system/doth/ns2/cert.pem b/bin/tests/system/doth/ns2/cert.pem new file mode 100644 index 0000000..f9c7e61 --- /dev/null +++ b/bin/tests/system/doth/ns2/cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICHTCCAcOgAwIBAgIUATq1E48Hj7vAQBwn8H/1oQvqvJ0wCgYIKoZIzj0EAwIw +YzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENp +dHkxDDAKBgNVBAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2Fs +aG9zdDAgFw0yMTAyMTIwMzIxMzFaGA8yMTIxMDExOTAzMjEzMVowYzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgMAkNBMRUwEwYDVQQHDAxSZWR3b29kIENpdHkxDDAKBgNV +BAoMA0lTQzEOMAwGA1UECwwFQklORDkxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABC1uCviud7QFTJ8DfdrLwjkBolYHJJR9c9HP +bshvKDXahhRU9+HCbWBNLlqFR6aMs8wyE32cXHLZ70XaILkH88SjUzBRMB0GA1Ud +DgQWBBRPpE9aC2MO0TAlCp18vR9vqe4R2TAfBgNVHSMEGDAWgBRPpE9aC2MO0TAl +Cp18vR9vqe4R2TAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIE3L +zx4iRVqjnOACc+/G0Shru+AIk/MEglfrvP5wxZaVAiEArcmut+hYb+cG0UW5ct/U +Q183Kk25XYJkTj39GSBiiiA= +-----END CERTIFICATE----- diff --git a/bin/tests/system/doth/ns2/key.pem b/bin/tests/system/doth/ns2/key.pem new file mode 100644 index 0000000..90716c8 --- /dev/null +++ b/bin/tests/system/doth/ns2/key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFBLYPWvhrGBMyfi04oC53LOl00LZRZbVOVnC0K30XOCoAoGCCqGSM49 +AwEHoUQDQgAELW4K+K53tAVMnwN92svCOQGiVgcklH1z0c9uyG8oNdqGFFT34cJt +YE0uWoVHpoyzzDITfZxcctnvRdoguQfzxA== +-----END EC PRIVATE KEY----- diff --git a/bin/tests/system/doth/ns2/named.conf.in b/bin/tests/system/doth/ns2/named.conf.in new file mode 100644 index 0000000..a7b0961 --- /dev/null +++ b/bin/tests/system/doth/ns2/named.conf.in @@ -0,0 +1,200 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../CA/certs/srv02.crt01.example.com.key"; + cert-file "../CA/certs/srv02.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +http local { + endpoints { "/dns-query"; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + tls-port @TLSPORT@; + https-port @HTTPSPORT@; + http-port @HTTPPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on tls local { 10.53.0.2; }; // DoT + listen-on-v6 tls local { fd92:7065:b8e:ffff::2; }; + listen-on tls local http local { 10.53.0.2; }; // DoH + listen-on-v6 tls local http local { fd92:7065:b8e:ffff::2; }; + listen-on tls none http local { 10.53.0.2; }; // unencrypted DoH + listen-on-v6 tls none http local { fd92:7065:b8e:ffff::2; }; + listen-on-v6 { none; }; + recursion yes; + allow-recursion { any; }; + allow-query-cache { any; }; + allow-recursion-on { 10.53.0.2; }; # allow-query-cache-on inherits; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; + max-records-per-type 0; + transfers-in 100; + transfers-out 100; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-example-primary-wrong-ca { + remote-hostname "srv01.crt01.example.com"; // enable Strict TLS + ca-file "not-a-file.pem"; +}; + +zone "test.example.com" { + type forward; + forward only; + forwarders port @TLSPORT@ { 10.53.0.2 tls tls-example-primary-wrong-ca; }; +}; + +tls tls-example-primary { + remote-hostname "srv01.crt01.example.com"; // enable Strict TLS + ca-file "../CA/CA.pem"; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-example-primary; }; + file "example.db"; + allow-transfer { any; }; +}; + +# the server's certificate does not contain SubjectAltName, which is required for DoT +tls tls-example-primary-no-san { + remote-hostname "srv01.crt02-no-san.example.com"; // enable Strict TLS + ca-file "../CA/CA.pem"; +}; + +zone "example3" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT2@ tls tls-example-primary-no-san; }; + file "example3.db"; + allow-transfer { any; }; +}; + +# As you can see, the "remote-hostname" is missing, but "ca-file" is +# specified. As the result, the primaries server certificate will be +# verified using the IP address instead of hostname. That is fine, +# because the server certificate is issued with IP address in the +# SubjectAltName section. +tls tls-example-primary-strict-tls-no-hostname { + ca-file "../CA/CA.pem"; // enable Strict TLS +}; + +zone "example4" { + type secondary; + primaries { 10.53.0.1 tls tls-example-primary-strict-tls-no-hostname; }; + file "example4.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-strict-tls-ipv4 { + remote-hostname "10.53.0.1"; # the IP is in the server's cert SAN + ca-file "../CA/CA.pem"; # enable Strict TLS +}; + +zone "example5" { + type secondary; + primaries { 10.53.0.1 tls tls-example-primary-strict-tls-ipv4; }; + file "example5.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-strict-tls-ipv6 { + remote-hostname "fd92:7065:b8e:ffff::1"; # the IP is in the server's cert SAN + ca-file "../CA/CA.pem"; # enable Strict TLS +}; + +zone "example6" { + type secondary; + primaries { 10.53.0.1 tls tls-example-primary-strict-tls-ipv6; }; + file "example6.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-strict-tls-wrong-host { + remote-hostname "not-present.example.com"; # this is not present in the server's cert SAN + ca-file "../CA/CA.pem"; # enable Strict TLS +}; + +zone "example7" { + type secondary; + primaries { 10.53.0.1 tls tls-example-primary-strict-tls-wrong-host; }; + file "example7.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-strict-tls-expired { + remote-hostname "srv01.crt03-expired.example.com"; + ca-file "../CA/CA.pem"; +}; + +zone "example8" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT4@ tls tls-example-primary-strict-tls-expired; }; + file "example8.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-mutual-tls { + remote-hostname "srv01.crt01.example.com"; + ca-file "../CA/CA.pem"; + cert-file "../CA/certs/srv01.client02-ns2.example.com.pem"; + key-file "../CA/certs/srv01.client02-ns2.example.com.key"; +}; + +zone "example9" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary-mutual-tls; }; + file "example9.db"; + allow-transfer { any; }; +}; + +zone "example10" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary; }; + file "example10.db"; + allow-transfer { any; }; +}; + +tls tls-example-primary-mutual-tls-expired { + remote-hostname "srv01.crt01.example.com"; + ca-file "../CA/CA.pem"; + cert-file "../CA/certs/srv01.client03-ns2-expired.example.com.pem"; + key-file "../CA/certs/srv01.client03-ns2-expired.example.com.key"; +}; + +zone "example11" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT5@ tls tls-example-primary-mutual-tls-expired; }; + file "example11.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/doth/ns3/named.conf.in b/bin/tests/system/doth/ns3/named.conf.in new file mode 100644 index 0000000..daf3164 --- /dev/null +++ b/bin/tests/system/doth/ns3/named.conf.in @@ -0,0 +1,82 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../CA/certs/srv03.crt01.example.com.key"; + cert-file "../CA/certs/srv03.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +http local { + endpoints { "/dns-query"; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + tls-port @TLSPORT@; + https-port @HTTPSPORT@; + http-port @HTTPPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on tls local { 10.53.0.3; }; // DoT + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; + max-records-per-type 0; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.2-pfs { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.2-pfs; }; + file "example.db"; + allow-transfer { any; }; +}; + +tls tls-pfs-aes-128 { + protocols { TLSv1.2; }; + // AES128 does not match the setting on the server: AES256 + ciphers "AES128:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers no; +}; + +zone "example2" { + type secondary; + primaries port @EXTRAPORT1@ { 10.53.0.1 tls tls-pfs-aes-128; }; + file "example2.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/doth/ns4/named.conf.in b/bin/tests/system/doth/ns4/named.conf.in new file mode 100644 index 0000000..d637a9c --- /dev/null +++ b/bin/tests/system/doth/ns4/named.conf.in @@ -0,0 +1,76 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# We need a separate instance for the "rndc reconfig" test in order to +# ensure that it does not use ephemeral keys (these are costly to +# generate) and creates a minimal amount of TLS contexts, reducing the +# time needed for startup/reconfiguration. Long +# startup/reconfiguration was known to cause timeout issues in the CI +# system, where many tests run in parallel. + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls local { + key-file "../CA/certs/srv04.crt01.example.com.key"; + cert-file "../CA/certs/srv04.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +http local { + endpoints { "/dns-query"; }; +}; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + tls-port @TLSPORT@; + https-port @HTTPSPORT@; + http-port @HTTPPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on tls local { 10.53.0.4; }; // DoT + listen-on tls local http local { 10.53.0.4; }; // DoH + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; + max-records-per-type 0; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +tls tls-v1.2-pfs { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers no; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.1 tls tls-v1.2-pfs; }; + file "example.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/doth/ns5/named.conf.in b/bin/tests/system/doth/ns5/named.conf.in new file mode 100644 index 0000000..7aa3757 --- /dev/null +++ b/bin/tests/system/doth/ns5/named.conf.in @@ -0,0 +1,86 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# We need a separate instance for the "rndc reconfig" test in order to +# ensure that it does not use ephemeral keys (these are costly to +# generate) and creates a minimal amount of TLS contexts, reducing the +# time needed for startup/reconfiguration. Long +# startup/reconfiguration was known to cause timeout issues in the CI +# system, where many tests run in parallel. + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + tls-port @TLSPORT@; + https-port @HTTPSPORT@; + http-port @HTTPPORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + notify no; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation yes; + max-records-per-type 0; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +# Let's reuse the same entry multiple times to see if transfers will succeed + +tls tls-v1.2 { + protocols { TLSv1.2; }; + prefer-server-ciphers yes; +}; + +zone "example12" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT7@ tls tls-v1.2; }; + file "example12.db"; + allow-transfer { any; }; +}; + +zone "example13" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT7@ tls tls-v1.2; }; + file "example13.db"; + allow-transfer { any; }; +}; + +zone "example14" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT7@ tls tls-v1.2; }; + file "example14.db"; + allow-transfer { any; }; +}; + +zone "example15" { + type secondary; + primaries { 10.53.0.1 port @EXTRAPORT7@ tls tls-v1.2; }; + file "example15.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/doth/prereq.sh b/bin/tests/system/doth/prereq.sh new file mode 100644 index 0000000..fe62dcb --- /dev/null +++ b/bin/tests/system/doth/prereq.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --with-libnghttp2 || { + echo_i "This test requires libnghttp2 support." >&2 + exit 255 +} + +$FEATURETEST --have-fips-dh || { + echo_i "FIPS mode Diffie-Hellman not working - skipping doth test" + exit 255 +} + +exit 0 diff --git a/bin/tests/system/doth/setup.sh b/bin/tests/system/doth/setup.sh new file mode 100644 index 0000000..775dd33 --- /dev/null +++ b/bin/tests/system/doth/setup.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns1/example.db + +echo '; huge answer' >>ns1/example.db +x=1 +while [ $x -le 50 ]; do + y=1 + while [ $y -le 50 ]; do + printf 'biganswer\t\tA\t\t10.10.%d.%d\n' $x $y >>ns1/example.db + y=$((y + 1)) + done + x=$((x + 1)) +done + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py new file mode 100755 index 0000000..ca1fddb --- /dev/null +++ b/bin/tests/system/doth/stress_http_quota.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import sys +import socket +import subprocess +import random +import time + +from functools import reduce +from resource import getrlimit +from resource import setrlimit +from resource import RLIMIT_NOFILE + +MULTIDIG_INSTANCES = 10 +CONNECT_TRIES = 5 + +random.seed() + +# Ensure we have enough file desriptors to work +rlimit_nofile = getrlimit(RLIMIT_NOFILE) +if rlimit_nofile[0] < 1024: + setrlimit(RLIMIT_NOFILE, (1024, rlimit_nofile[1])) + + +# Introduce some random delay +def jitter(): + time.sleep((500 + random.randint(0, 250)) / 1000000.0) + + +# A set of simple procedures to get the test's configuration options +def get_http_port(http_secure=False): + http_port_env = None + if http_secure: + http_port_env = os.getenv("HTTPSPORT") + else: + http_port_env = os.getenv("HTTPPORT") + if http_port_env: + return int(http_port_env) + return 443 + + +def get_http_host(): + bind_host = os.getenv("BINDHOST") + if bind_host: + return bind_host + return "localhost" + + +def get_dig_path(): + dig_path = os.getenv("DIG") + if dig_path: + return dig_path + return "dig" + + +# A simple class which creates the given number of TCP connections to +# the given host in order to stress the BIND's quota facility +class TCPConnector: + def __init__(self, host, port): + self.host = host + self.port = port + self.connections = [] + + def connect_one(self): + tries = CONNECT_TRIES + while tries > 0: + try: + sock = socket.create_connection( + address=(self.host, self.port), timeout=None + ) + self.connections.append(sock) + break + except ConnectionResetError: + # some jitter for BSDs + jitter() + continue + except TimeoutError: + jitter() + continue + finally: + tries -= 1 + + # Close an established connection (randomly) + def disconnect_random(self): + pos = random.randint(0, len(self.connections) - 1) + conn = self.connections[pos] + try: + conn.shutdown(socket.SHUT_RDWR) + conn.close() + except OSError: + conn.close() + finally: + self.connections.remove(conn) + + def disconnect_all(self): + while len(self.connections) != 0: + self.disconnect_random() + + +# A simple class which allows running a dig instance under control of +# the process +class SubDIG: + def __init__(self, http_secure=None, extra_args=None): + self.sub_process = None + self.dig_path = get_dig_path() + self.host = get_http_host() + self.port = get_http_port(http_secure=http_secure) + if http_secure: + self.http_secure = True + else: + self.http_secure = False + self.extra_args = extra_args + + # This method constructs a command string + def get_command(self): + command = self.dig_path + " -p " + str(self.port) + " " + command = command + "+noadd +nosea +nostat +noquest +nocmd +time=30 " + if self.http_secure: + command = command + "+https " + else: + command = command + "+http-plain " + command = command + "@" + self.host + " " + if self.extra_args: + command = command + self.extra_args + return command + + def run(self): + # pylint: disable=consider-using-with + with open(os.devnull, "w", encoding="utf-8") as devnull: + self.sub_process = subprocess.Popen( + self.get_command(), shell=True, stdout=devnull + ) + + def wait(self, timeout=None): + res = None + if timeout is None: + return self.sub_process.wait() + try: + res = self.sub_process.wait(timeout=timeout) + except subprocess.TimeoutExpired: + return None + return res + + def alive(self): + return self.sub_process.poll() is None + + +# A simple wrapper class which allows running multiple dig instances +# and examining their statuses in one logical operation. +class MultiDIG: + def __init__(self, numdigs, http_secure=None, extra_args=None): + assert int(numdigs) > 0, f"numdigs={numdigs}" + digs = [] + for _ in range(1, int(numdigs) + 1): + digs.append(SubDIG(http_secure=http_secure, extra_args=extra_args)) + self.digs = digs + assert len(self.digs) == int(numdigs), f"len={len(self.digs)} numdigs={numdigs}" + + def run(self): + for p in self.digs: + p.run() + + def wait(self): + return map(lambda p: (p.wait()), self.digs) + + # Wait for the all instances to terminate with expected given + # status. Returns true or false. + def wait_for_result(self, result): + return reduce( + lambda a, b: ((a == result or a is True) and b == result), self.wait() + ) + + def alive(self): + return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), self.digs)) + + def completed(self): + total = 0 + for p in self.digs: + if not p.alive(): + total += 1 + return total + + +# The test's main logic +def run_test(http_secure=True): + query_args = "SOA ." + # Let's try to make a successful query + subdig = SubDIG(http_secure=http_secure, extra_args=query_args) + subdig.run() + assert subdig.wait() == 0, "DIG was expected to succeed" + # Let's create a lot of TCP connections to the server stress the + # HTTP quota + connector = TCPConnector(get_http_host(), get_http_port(http_secure=http_secure)) + # Let's make queries until the quota kicks in + subdig = SubDIG(http_secure=http_secure, extra_args=query_args) + subdig.run() + while True: + connector.connect_one() + subdig = SubDIG(http_secure=http_secure, extra_args=query_args) + subdig.run() + if subdig.wait(timeout=5) is None: + break + + # At this point quota has kicked in. Additionally, let's create a + # bunch of dig processes all trying to make a query against the + # server with exceeded quota + multidig = MultiDIG( + MULTIDIG_INSTANCES, http_secure=http_secure, extra_args=query_args + ) + multidig.run() + # Wait for the dig instance to complete. Not a single instance has + # a chance to complete successfully because of the exceeded quota + assert ( + subdig.wait(timeout=5) is None + ), "The single DIG instance has stopped prematurely" + assert subdig.alive(), "The single DIG instance is expected to be alive" + assert multidig.alive(), ( + "The DIG instances from the set are all expected to " + "be alive, but {} of them have completed" + ).format(multidig.completed()) + # Let's close opened connections (in random order) to let all dig + # processes to complete + connector.disconnect_all() + # Wait for all processes to complete successfully + assert subdig.wait() == 0, "Single DIG instance failed" + assert ( + multidig.wait_for_result(0) is True + ), "One or more of DIG instances returned unexpected results" + + +def main(): + run_test(http_secure=True) + run_test(http_secure=False) + # If we have reached this point we could safely return 0 + # (success). If the test fails because of an assert, the whole + # program will return non-zero exit code and produce the backtrace + return 0 + + +sys.exit(main()) diff --git a/bin/tests/system/doth/tests.sh b/bin/tests/system/doth/tests.sh new file mode 100644 index 0000000..3559c67 --- /dev/null +++ b/bin/tests/system/doth/tests.sh @@ -0,0 +1,929 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck disable=SC1091 +. ../conf.sh + +common_dig_options="+noadd +nosea +nostat +noquest +nocmd" +msg_xfrs_not_allowed=";; zone transfers over the established TLS connection are not allowed" +msg_peer_verification_failed=";; TLS peer certificate verification" + +ca_file="./CA/CA.pem" + +if [ -x "$PYTHON" ]; then + OPENSSL_VERSION=$("$PYTHON" "$TOP_SRCDIR/bin/tests/system/doth/get_openssl_version.py") + OPENSSL_VERSION_MAJOR=$(echo "$OPENSSL_VERSION" | cut -d ' ' -f 1) + OPENSSL_VERSION_MINOR=$(echo "$OPENSSL_VERSION" | cut -d ' ' -f 2) +fi + +# According to the RFC 8310, Section 8.1, Subject field MUST +# NOT be inspected when verifying a hostname when using +# DoT. Only SubjectAltName must be checked instead. That is +# not the case for HTTPS, though. + +# Unfortunately, some quite old versions of OpenSSL (< 1.1.1) +# might lack the functionality to implement that. It should +# have very little real-world consequences, as most of the +# production-ready certificates issued by real CAs will have +# SubjectAltName set. In such a case, the Subject field is +# ignored. +# +# On the platforms with too old TLS versions, e.g. RedHat 7, we should +# ignore the tests checking the correct handling of absence of +# SubjectAltName. +if [ -n "$OPENSSL_VERSION" ]; then + if [ $OPENSSL_VERSION_MAJOR -gt 1 ]; then + run_san_tests=1 + elif [ $OPENSSL_VERSION_MAJOR -eq 1 ] && [ $OPENSSL_VERSION_MINOR -ge 1 ]; then + run_san_tests=1 + fi +fi + +dig_with_tls_opts() { + # shellcheck disable=SC2086 + "$DIG" +tls $common_dig_options -p "${TLSPORT}" "$@" +} + +dig_with_https_opts() { + # shellcheck disable=SC2086 + "$DIG" +https $common_dig_options -p "${HTTPSPORT}" "$@" +} + +dig_with_http_opts() { + # shellcheck disable=SC2086 + "$DIG" +http-plain $common_dig_options -p "${HTTPPORT}" "$@" +} + +dig_with_opts() { + # shellcheck disable=SC2086 + "$DIG" $common_dig_options -p "${PORT}" "$@" +} + +wait_for_tls_xfer() ( + srv_number="$1" + shift + zone_name="$1" + shift + # Let's bind to .10 to make it possible to easily distinguish dig from NSs in packet traces + dig_with_tls_opts -b 10.53.0.10 "@10.53.0.$srv_number" "${zone_name}." AXFR >"dig.out.ns$srv_number.${zone_name}.test$n" || return 1 + grep "^;" "dig.out.ns$srv_number.${zone_name}.test$n" >/dev/null && return 1 + return 0 +) + +status=0 +n=0 + +n=$((n + 1)) +echo_i "testing XoT server functionality (using dig) ($n)" +ret=0 +dig_with_tls_opts example. -b 10.53.0.10 @10.53.0.1 axfr >dig.out.ns1.test$n || ret=1 +grep "^;" dig.out.ns1.test$n | cat_i +digcomp example.axfr.good dig.out.ns1.test$n || ret=1 +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example; then + digcomp example.axfr.good "dig.out.ns2.example.test$n" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns2.example.test$n" | cat_i + ret=1 +fi +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +if [ -n "$run_san_tests" ]; then + n=$((n + 1)) + echo_i "testing incoming XoT functionality (from the first secondary, no SubjectAltName, failure expected) ($n)" + ret=0 + if retry_quiet 10 wait_for_tls_xfer 2 example3; then + ret=1 + else + echo_i "timed out waiting for zone transfer" + fi + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via implicit IP) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example4; then + retry_quiet 5 test -f "ns2/example4.db" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns2.example4.test$n" | cat_i + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via specified IPv4) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example5; then + retry_quiet 5 test -f "ns2/example5.db" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns2.example5.test$n" | cat_i + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, StrictTLS via specified IPv6) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example6; then + retry_quiet 5 test -f "ns2/example6.db" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns2.example6.test$n" | cat_i + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, wrong hostname, failure expected) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example7; then + ret=1 +else + echo_i "timed out waiting for zone transfer" +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, expired certificate, failure expected) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example8; then + ret=1 +else + echo_i "timed out waiting for zone transfer" +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example9; then + retry_quiet 5 test -f "ns2/example9.db" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns2.example9.test$n" | cat_i + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS, no client cert, failure expected) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example10; then + ret=1 +else + echo_i "timed out waiting for zone transfer" +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the first secondary, MutualTLS, expired client cert, failure expected) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 2 example11; then + ret=1 +else + echo_i "timed out waiting for zone transfer" +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the second secondary) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 3 example; then + digcomp example.axfr.good "dig.out.ns3.example.test$n" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns3.example.test$n" | cat_i + ret=1 +fi +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the second secondary, mismatching ciphers, failure expected) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 3 example2; then + ret=1 +else + echo_i "timed out waiting for zone transfer" +fi +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incoming XoT functionality (from the third secondary) ($n)" +ret=0 +if retry_quiet 10 wait_for_tls_xfer 4 example; then + digcomp example.axfr.good "dig.out.ns4.example.test$n" || ret=1 +else + echo_i "timed out waiting for zone transfer" + grep "^;" "dig.out.ns4.example.test$n" | cat_i + ret=1 +fi +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (ephemeral key) ($n)" +ret=0 +dig_with_tls_opts @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query via IPv6 (ephemeral key) ($n)" +ret=0 +dig_with_tls_opts -6 @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (static key) ($n)" +ret=0 +dig_with_tls_opts @10.53.0.2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query via IPv6 (static key) ($n)" +ret=0 +dig_with_tls_opts -6 @fd92:7065:b8e:ffff::2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT XFR ($n)" +ret=0 +dig_with_tls_opts +comm @10.53.0.1 . AXFR >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# zone transfers are allowed only via TLS +n=$((n + 1)) +echo_i "testing zone transfer over Do53 server functionality (using dig, failure expected) ($n)" +ret=0 +dig_with_opts example. -b 10.53.0.10 @10.53.0.1 axfr >dig.out.ns1.test$n || ret=1 +grep "; Transfer failed." dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# querying zones is still allowed via UDP/TCP +n=$((n + 1)) +echo_i "checking Do53 query ($n)" +ret=0 +dig_with_opts @10.53.0.1 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# In this test we are trying to establish a DoT connection over the +# DoH port. That is intentional, as dig should fail right after +# handshake has happened and before sending any queries, as XFRs, per +# the RFC, could happen only over a connection where "dot" ALPN token +# was negotiated. over DoH it cannot happen, as only "h2" token could +# be selected for a DoH connection. +n=$((n + 1)) +echo_i "checking DoT XFR with wrong ALPN token (h2, failure expected) ($n)" +ret=0 +# shellcheck disable=SC2086 +"$DIG" +tls $common_dig_options -p "${HTTPSPORT}" +comm @10.53.0.1 . AXFR >dig.out.test$n +grep "$msg_xfrs_not_allowed" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Let's try to issue an HTTP/2 query over TLS port to check if dig +# will detect ALPN token negotiation problem. +n=$((n + 1)) +echo_i "checking DoH query when ALPN is expected to fail (dot, failure expected) ($n)" +ret=0 +# shellcheck disable=SC2086 +"$DIG" +https $common_dig_options -p "${TLSPORT}" "$@" @10.53.0.1 . SOA >dig.out.test$n && ret=1 +grep "ALPN for HTTP/2 failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST) ($n)" +ret=0 +dig_with_https_opts +stat @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTPS)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (POST) ($n)" +ret=0 +dig_with_https_opts +stat -6 @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTPS)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST, static key) ($n)" +ret=0 +dig_with_https_opts @10.53.0.2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (POST, static key) ($n)" +ret=0 +dig_with_https_opts -6 @fd92:7065:b8e:ffff::2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST, nonstandard endpoint) ($n)" +ret=0 +dig_with_https_opts +https=/alter @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (POST, nonstandard endpoint) ($n)" +ret=0 +dig_with_https_opts -6 +https=/alter @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST, undefined endpoint, failure expected) ($n)" +ret=0 +dig_with_https_opts +tries=1 +time=1 +https=/fake @10.53.0.1 . SOA >dig.out.test$n && ret=1 +grep "communications error" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (POST, undefined endpoint, failure expected) ($n)" +ret=0 +dig_with_https_opts -6 +tries=1 +time=1 +https=/fake @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n && ret=1 +grep "communications error" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH XFR (POST) (failure expected) ($n)" +ret=0 +dig_with_https_opts +comm @10.53.0.1 . AXFR >dig.out.test$n || ret=1 +grep "; Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (GET) ($n)" +ret=0 +dig_with_https_opts +stat +https-get @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTPS-GET)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (GET) ($n)" +ret=0 +dig_with_https_opts -6 +stat +https-get @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTPS-GET)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (GET, static key) ($n)" +ret=0 +dig_with_https_opts +https-get @10.53.0.2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (GET, static key) ($n)" +ret=0 +dig_with_https_opts -6 +https-get @fd92:7065:b8e:ffff::2 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (GET, nonstandard endpoint) ($n)" +ret=0 +dig_with_https_opts +https-get=/alter @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (GET, nonstandard endpoint) ($n)" +ret=0 +dig_with_https_opts -6 +https-get=/alter @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (GET, undefined endpoint, failure expected) ($n)" +ret=0 +dig_with_https_opts +tries=1 +time=1 +https-get=/fake @10.53.0.1 . SOA >dig.out.test$n && ret=1 +grep "communications error" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 (GET, undefined endpoint, failure expected) ($n)" +ret=0 +dig_with_https_opts -6 +tries=1 +time=1 +https-get=/fake @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n && ret=1 +grep "communications error" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH XFR (GET) (failure expected) ($n)" +ret=0 +dig_with_https_opts +https-get +comm @10.53.0.1 . AXFR >dig.out.test$n || ret=1 +grep "; Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query (POST) ($n)" +ret=0 +dig_with_http_opts +stat @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTP)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query via IPv6 (POST) ($n)" +ret=0 +dig_with_http_opts -6 +stat @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTP)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query (GET) ($n)" +ret=0 +dig_with_http_opts +stat +http-plain-get @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTP-GET)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query via IPv6 (GET) ($n)" +ret=0 +dig_with_http_opts -6 +stat +http-plain-get @fd92:7065:b8e:ffff::1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep -F "(HTTP-GET)" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH XFR (failure expected) ($n)" +ret=0 +dig_with_http_opts +comm @10.53.0.1 . AXFR >dig.out.test$n || ret=1 +grep "; Transfer failed." dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query for a large answer (POST) ($n)" +ret=0 +dig_with_https_opts @10.53.0.1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 for a large answer (POST) ($n)" +ret=0 +dig_with_https_opts -6 @fd92:7065:b8e:ffff::1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query for a large answer (GET) ($n)" +ret=0 +dig_with_https_opts +https-get @10.53.0.1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query via IPv6 for a large answer (GET) ($n)" +ret=0 +dig_with_https_opts -6 +https-get @fd92:7065:b8e:ffff::1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query for a large answer (POST) ($n)" +ret=0 +dig_with_http_opts @10.53.0.1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query via IPv6 for a large answer (POST) ($n)" +ret=0 +dig_with_http_opts -6 @fd92:7065:b8e:ffff::1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query for a large answer (GET) ($n)" +ret=0 +dig_with_http_opts +http-plain-get @10.53.0.1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking unencrypted DoH query via IPv6 for a large answer (GET) ($n)" +ret=0 +dig_with_http_opts -6 +http-plain-get @fd92:7065:b8e:ffff::1 biganswer.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2500" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +wait_for_tlsctx_update_ns4() { + grep "updating TLS context on 10.53.0.4#${HTTPSPORT}" ns4/named.run >/dev/null || return 1 + grep "updating TLS context on 10.53.0.4#${TLSPORT}" ns4/named.run >/dev/null || return 1 + return 0 +} + +n=$((n + 1)) +echo_i "doing rndc reconfig to see that queries keep being served after that ($n)" +ret=0 +rndc_reconfig ns4 10.53.0.4 60 +retry_quiet 15 wait_for_tlsctx_update_ns4 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query after a reconfiguration ($n)" +ret=0 +dig_with_tls_opts @10.53.0.4 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST) after a reconfiguration ($n)" +ret=0 +dig_with_https_opts @10.53.0.4 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "doing rndc reconfig to see if HTTP endpoints have gotten reconfigured ($n)" +ret=0 +# 'sed -i ...' is not portable. Sigh... +sed 's/\/dns-query/\/dns-query-test/g' "ns4/named.conf" >"ns4/named.conf.sed" +mv -f "ns4/named.conf.sed" "ns4/named.conf" +rndc_reconfig ns4 10.53.0.4 60 +retry_quiet 15 wait_for_tlsctx_update_ns4 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (POST) to verify HTTP endpoint reconfiguration ($n)" +ret=0 +dig_with_https_opts +https='/dns-query-test' @10.53.0.4 example SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (with TLS verification enabled) ($n)" +ret=0 +dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (with TLS verification enabled, self-signed cert, failure expected) ($n)" +ret=0 +dig_with_https_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (with TLS verification using the system's CA store, failure expected) ($n)" +ret=0 +dig_with_tls_opts +tls-ca +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (with TLS verification using the system's CA store, failure expected) ($n)" +ret=0 +dig_with_https_opts +tls-ca +tls-hostname="srv01.crt01.example.com" @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# the primary server's certificate contains the IP address in the +# SubjectAltName section +n=$((n + 1)) +echo_i "checking DoT query (with TLS verification, hostname is not specified, IP address is used instead) ($n)" +ret=0 +dig_with_tls_opts +tls-ca="$ca_file" @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if [ -n "$run_san_tests" ]; then + # SubjectAltName is required for DoT as according to RFC 8310, Subject + # field MUST NOT be inspected when verifying hostname for DoT. + n=$((n + 1)) + echo_i "checking DoT query (with TLS verification enabled when SubjectAltName is not set, failure expected) ($n)" + ret=0 + dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" @10.53.0.1 . SOA >dig.out.test$n || ret=1 + grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking DoT XFR over a TLS port where SubjectAltName is not set (failure expected) ($n)" + ret=0 + # shellcheck disable=SC2086 + dig_with_tls_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" -p "${EXTRAPORT2}" +comm @10.53.0.1 . AXFR >dig.out.test$n || ret=1 + grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +# SubjectAltName is not required for HTTPS. Having a properly set +# Common Name in the Subject field is enough. +n=$((n + 1)) +echo_i "checking DoH query (when SubjectAltName is not set) ($n)" +ret=0 +dig_with_https_opts +tls-ca="$ca_file" +tls-hostname="srv01.crt02-no-san.example.com" -p "${EXTRAPORT3}" +comm @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (expired certificate, Opportunistic TLS) ($n)" +ret=0 +dig_with_tls_opts +tls -p "${EXTRAPORT4}" +comm @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoT query (expired certificate, Strict TLS, failure expected) ($n)" +ret=0 +dig_with_tls_opts +tls-ca="$ca_file" -p "${EXTRAPORT4}" +comm @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "$msg_peer_verification_failed" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing XoT server functionality (using dig, client certificate required, failure expected) ($n)" +ret=0 +dig_with_tls_opts +tls-ca="$ca_file" -p "${EXTRAPORT5}" example8. -b 10.53.0.10 @10.53.0.1 axfr >dig.out.ns1.test$n || ret=1 +grep "; Transfer failed." dig.out.ns1.test$n >/dev/null || ret=1 +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing XoT server functionality (using dig, client certificate used) ($n)" +ret=0 +dig_with_tls_opts +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT5}" example8. -b 10.53.0.10 @10.53.0.1 axfr >dig.out.ns1.test$n || ret=1 +digcomp dig.out.ns1.test$n example8.axfr.good >/dev/null || ret=1 +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (client certificate required, failure expected) ($n)" +ret=0 +dig_with_https_opts +tls-ca="$ca_file" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA >dig.out.test$n && ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DoH query (client certificate used) ($n)" +ret=0 +# shellcheck disable=SC2086 +dig_with_https_opts +https +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# send two requests one after another so that session resumption will happen +n=$((n + 1)) +echo_i "checking DoH query (client certificate used - session resumption when using Mutual TLS) ($n)" +ret=0 +# shellcheck disable=SC2086 +dig_with_https_opts +https +tls-ca="$ca_file" +tls-certfile="./CA/certs/srv01.client01.example.com.pem" +tls-keyfile="./CA/certs/srv01.client01.example.com.key" -p "${EXTRAPORT6}" +comm @10.53.0.1 . SOA . SOA >dig.out.test$n || ret=1 +grep "TLS error" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +test_opcodes() { + EXPECT_STATUS="$1" + shift + for op in "$@"; do + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoH for opcode $op ($n)" + ret=0 + dig_with_https_opts +https @10.53.0.1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoH via IPv6 for opcode $op ($n)" + ret=0 + dig_with_https_opts -6 +https @fd92:7065:b8e:ffff::1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoH without encryption for opcode $op ($n)" + ret=0 + dig_with_http_opts +http-plain @10.53.0.1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoH via IPv6 without encryption for opcode $op ($n)" + ret=0 + dig_with_http_opts -6 +http-plain @fd92:7065:b8e:ffff::1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoT for opcode $op ($n)" + ret=0 + dig_with_tls_opts +tls @10.53.0.1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking unexpected opcode query over DoT via IPv6 for opcode $op ($n)" + ret=0 + dig_with_tls_opts -6 +tls @fd92:7065:b8e:ffff::1 +opcode="$op" >dig.out.test$n || ret=1 + grep "status: $EXPECT_STATUS" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + done +} + +test_opcodes NOERROR 0 +test_opcodes NOTIMP 1 2 3 6 7 8 9 10 11 12 13 14 15 +test_opcodes FORMERR 4 5 + +n=$((n + 1)) +echo_i "checking server quotas for both encrypted and unencrypted HTTP ($n)" +ret=0 +if [ -x "$PYTHON" ]; then + BINDHOST="10.53.0.1" "$PYTHON" "$TOP_SRCDIR/bin/tests/system/doth/stress_http_quota.py" || ret=$? +else + echo_i "Python is not available. Skipping the test..." +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# check whether we can use curl for sending test queries. +if [ -x "${CURL}" ]; then + CURL_HTTP2="$(${CURL} --version | grep -E '^Features:.* HTTP2( |$)' || true)" + + if [ -n "$CURL_HTTP2" ]; then + testcurl=1 + else + echo_i "The available version of CURL does not have HTTP/2 support" + fi +fi + +# Note: see README.curl for information on how to generate curl +# queries. +if [ -n "$testcurl" ]; then + n=$((n + 1)) + echo_i "checking max-age for positive answer ($n)" + ret=0 + # use curl to query for 'example/SOA' + $CURL -kD headers.$n "https://10.53.0.1:${HTTPSPORT}/dns-query?dns=AAEAAAABAAAAAAAAB2V4YW1wbGUAAAYAAQ" >/dev/null 2>&1 || ret=1 + grep "cache-control: max-age=86400" headers.$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking max-age for negative answer ($n)" + ret=0 + # use curl to query for 'fake.example/TXT' + $CURL -kD headers.$n "https://10.53.0.1:${HTTPSPORT}/dns-query?dns=AAEAAAABAAAAAAAABGZha2UHZXhhbXBsZQAAEAAB" >/dev/null 2>&1 || ret=1 + grep "cache-control: max-age=3600" headers.$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "checking Do53 query to NS5 for zone \"example12\" (verifying successful client TLS context reuse by the NS5 server instance during XoT) ($n)" +ret=0 +dig_with_opts +comm @10.53.0.5 example12 SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking Do53 query to NS5 for zone \"example13\" (verifying successful client TLS context reuse by the NS5 server instance during XoT) ($n)" +ret=0 +dig_with_opts +comm @10.53.0.5 example13 SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking Do53 query to NS5 for zone \"example14\" (verifying successful client TLS context reuse by the NS5 server instance during XoT) ($n)" +ret=0 +dig_with_opts +comm @10.53.0.5 example14 SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking Do53 query to NS5 for zone \"example15\" (verifying successful client TLS context reuse by the NS5 server instance during XoT) ($n)" +ret=0 +dig_with_opts +comm @10.53.0.5 example15 SOA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# see GL #4572 +n=$((n + 1)) +echo_i "testing that zone forwarding fails when using a wrong TLS configuration on the server without aborting it (a condition for bug #4572, failure expected) ($n)" +ret=0 +dig_with_opts test.example.com. -b 10.53.0.10 @10.53.0.2 >dig.out.test$n || ret=1 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +if test $ret != 0; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/doth/tests_gnutls.py b/bin/tests/system/doth/tests_gnutls.py new file mode 100644 index 0000000..8770206 --- /dev/null +++ b/bin/tests/system/doth/tests_gnutls.py @@ -0,0 +1,115 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import selectors +import struct +import subprocess +import time + +import pytest + +pytest.importorskip("dns") +import dns.exception +import dns.message +import dns.name +import dns.rdataclass +import dns.rdatatype + +pytestmark = pytest.mark.extra_artifacts( + [ + "gnutls-cli.*", + "ns*/example*.db", + ] +) + + +def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): + # Prepare the example/SOA query which will be sent over TLS. + query = dns.message.make_query("example.", dns.rdatatype.SOA) + query_wire = query.to_wire() + query_with_length = struct.pack(">H", len(query_wire)) + query_wire + + # Run gnutls-cli. + gnutls_cli_args = [ + gnutls_cli_executable, + "--no-ca-verification", + "-V", + "--no-ocsp", + "--alpn=dot", + "--logfile=gnutls-cli.log", + "--port=%d" % named_tlsport, + "10.53.0.1", + ] + with open("gnutls-cli.err", "wb") as gnutls_cli_stderr, subprocess.Popen( + gnutls_cli_args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=gnutls_cli_stderr, + bufsize=0, + ) as gnutls_cli: + # Send the example/SOA query to the standard input of gnutls-cli. Do + # not close standard input yet because that causes gnutls-cli to close + # the TLS connection immediately, preventing the response from being + # read. + gnutls_cli.stdin.write(query_with_length) + gnutls_cli.stdin.flush() + + # Keep reading data from the standard output of gnutls-cli until a full + # DNS message is received or a timeout is exceeded or gnutls-cli exits. + # Popen.communicate() cannot be used here because: a) it closes + # standard input after sending data to the process (see above why this + # is a problem), b) gnutls-cli is not DNS-aware, so it does not exit + # upon receiving a DNS response. + selector = selectors.DefaultSelector() + selector.register(gnutls_cli.stdout, selectors.EVENT_READ) + deadline = time.time() + 10 + gnutls_cli_output = b"" + response = b"" + while not response and not gnutls_cli.poll(): + if not selector.select(timeout=deadline - time.time()): + break + gnutls_cli_output += gnutls_cli.stdout.read(512) + try: + # Ignore TCP length, just try to parse a DNS message from + # the rest of the data received. + response = dns.message.from_wire(gnutls_cli_output[2:]) + except dns.exception.FormError: + continue + + # At this point either a DNS response was received or a timeout fired + # or gnutls-cli exited prematurely. Close the standard input of + # gnutls-cli. Terminate it if that does not cause it to shut down + # gracefully. + gnutls_cli.stdin.close() + try: + gnutls_cli.wait(5) + except subprocess.TimeoutExpired: + gnutls_cli.kill() + + # Store the response received for diagnostic purposes. + with open("gnutls-cli.out.bin", "wb") as response_bin: + response_bin.write(gnutls_cli_output) + if response: + with open("gnutls-cli.out.txt", "w", encoding="utf-8") as response_txt: + response_txt.write(response.to_text()) + + # Check whether a response was received and whether it is sane. + assert response + assert query.id == response.id + assert len(response.answer) == 1 + assert response.answer[0].match( + dns.name.from_text("example."), + dns.rdataclass.IN, + dns.rdatatype.SOA, + dns.rdatatype.NONE, + ) diff --git a/bin/tests/system/doth/tests_sh_doth.py b/bin/tests/system/doth/tests_sh_doth.py new file mode 100644 index 0000000..69e92fa --- /dev/null +++ b/bin/tests/system/doth/tests_sh_doth.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "headers.*", + "ns*/example*.db", + ] +) + + +def test_doth(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/doth/tests_sslyze.py b/bin/tests/system/doth/tests_sslyze.py new file mode 100644 index 0000000..33d916a --- /dev/null +++ b/bin/tests/system/doth/tests_sslyze.py @@ -0,0 +1,74 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import pathlib +import subprocess + +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "sslyze.log.*", + "ns*/example*.db", + ] +) + + +def is_pid_alive(pid): + try: + os.kill(pid, 0) + return True + except OSError: + return False + + +def run_sslyze_in_a_loop(executable, port, log_file_prefix): + # Determine the PID of ns1. + with open(pathlib.Path("ns1", "named.pid"), encoding="utf-8") as pidfile: + pid = int(pidfile.read()) + + # Ensure ns1 is alive before starting the loop below to avoid reporting + # false positives. + if not is_pid_alive(pid): + pytest.skip(f"ns1 (PID: {pid}) is not running") + + # Run sslyze on ns1 in a loop with a limit of 30 iterations. Interrupt the + # test as soon as ns1 is determined to not be running any more. Log sslyze + # output. + sslyze_args = [executable, f"10.53.0.1:{port}"] + for i in range(0, 30): + log_file = f"{log_file_prefix}.ns1.{port}.{i + 1}" + with open(log_file, "wb") as sslyze_log: + # Run sslyze, logging stdout+stderr. Ignore the exit code since + # sslyze is only used for triggering crashes here rather than + # actual TLS analysis. + isctest.run.cmd( + sslyze_args, + stdout=sslyze_log, + stderr=subprocess.STDOUT, + timeout=30, + raise_on_exception=False, + ) + # Ensure ns1 is still alive after each sslyze run. + assert is_pid_alive(pid), f"ns1 (PID: {pid}) exited prematurely" + + +def test_sslyze_doh(sslyze_executable, named_httpsport): + run_sslyze_in_a_loop(sslyze_executable, named_httpsport, "sslyze.log.doh") + + +def test_sslyze_dot(sslyze_executable, named_tlsport): + run_sslyze_in_a_loop(sslyze_executable, named_tlsport, "sslyze.log.dot") diff --git a/bin/tests/system/dsdigest/ns1/named.conf.in b/bin/tests/system/dsdigest/ns1/named.conf.in new file mode 100644 index 0000000..da27c58 --- /dev/null +++ b/bin/tests/system/dsdigest/ns1/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dsdigest/ns1/root.db.in b/bin/tests/system/dsdigest/ns1/root.db.in new file mode 100644 index 0000000..30c61e9 --- /dev/null +++ b/bin/tests/system/dsdigest/ns1/root.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2012062000 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +good. NS ns2.good. +ns2.good. A 10.53.0.2 +bad. NS ns2.bad. +ns2.bad. A 10.53.0.2 diff --git a/bin/tests/system/dsdigest/ns1/sign.sh b/bin/tests/system/dsdigest/ns1/sign.sh new file mode 100644 index 0000000..a4abccc --- /dev/null +++ b/bin/tests/system/dsdigest/ns1/sign.sh @@ -0,0 +1,36 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +(cd ../ns2 && $SHELL sign.sh) + +cp ../ns2/dsset-good. . +cp ../ns2/dsset-bad. . + +key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +# Configure the resolving server with a static key. +keyfile_to_static_ds $key2 >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns4/trusted.conf diff --git a/bin/tests/system/dsdigest/ns2/bad.db.in b/bin/tests/system/dsdigest/ns2/bad.db.in new file mode 100644 index 0000000..c5e8c83 --- /dev/null +++ b/bin/tests/system/dsdigest/ns2/bad.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 diff --git a/bin/tests/system/dsdigest/ns2/good.db.in b/bin/tests/system/dsdigest/ns2/good.db.in new file mode 100644 index 0000000..c5e8c83 --- /dev/null +++ b/bin/tests/system/dsdigest/ns2/good.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 diff --git a/bin/tests/system/dsdigest/ns2/named.conf.in b/bin/tests/system/dsdigest/ns2/named.conf.in new file mode 100644 index 0000000..b20a027 --- /dev/null +++ b/bin/tests/system/dsdigest/ns2/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "good" { + type primary; + file "good.db.signed"; +}; + +zone "bad" { + type primary; + file "bad.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dsdigest/ns2/sign.sh b/bin/tests/system/dsdigest/ns2/sign.sh new file mode 100644 index 0000000..37456fe --- /dev/null +++ b/bin/tests/system/dsdigest/ns2/sign.sh @@ -0,0 +1,42 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone1=good +infile1=good.db.in +zonefile1=good.db +zone2=bad +infile2=bad.db.in +zonefile2=bad.db + +keyname11=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone1) +keyname12=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone1) +keyname21=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone2) +keyname22=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone2) + +cat $infile1 $keyname11.key $keyname12.key >$zonefile1 +cat $infile2 $keyname21.key $keyname22.key >$zonefile2 + +$SIGNER -P -g -o $zone1 $zonefile1 >/dev/null +$SIGNER -P -g -o $zone2 $zonefile2 >/dev/null + +DSFILENAME1=dsset-${zone1}. +DSFILENAME2=dsset-${zone2}. +$DSFROMKEY -a SHA-256 $keyname12 >$DSFILENAME1 +$DSFROMKEY -a SHA-256 $keyname22 >$DSFILENAME2 + +algo=SHA-384 + +$DSFROMKEY -a $algo $keyname12 >>$DSFILENAME1 +$DSFROMKEY -a $algo $keyname22 >$DSFILENAME2 diff --git a/bin/tests/system/dsdigest/ns3/named.conf.in b/bin/tests/system/dsdigest/ns3/named.conf.in new file mode 100644 index 0000000..bd4eb83 --- /dev/null +++ b/bin/tests/system/dsdigest/ns3/named.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + dnssec-must-be-secure . yes; + /* only SHA-256 is enabled */ + disable-ds-digests . { SHA-1; SHA-384; 5; 6; 7; 8; 9; }; + +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dsdigest/ns4/named.conf.in b/bin/tests/system/dsdigest/ns4/named.conf.in new file mode 100644 index 0000000..74e8960 --- /dev/null +++ b/bin/tests/system/dsdigest/ns4/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + /* only SHA-256 is enabled */ + disable-ds-digests . { SHA-1; SHA-384; 5; 6; 7; 8; 9; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dsdigest/setup.sh b/bin/tests/system/dsdigest/setup.sh new file mode 100644 index 0000000..44bcc9d --- /dev/null +++ b/bin/tests/system/dsdigest/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +cd ns1 && $SHELL sign.sh diff --git a/bin/tests/system/dsdigest/tests_dsdigest.py b/bin/tests/system/dsdigest/tests_dsdigest.py new file mode 100644 index 0000000..f741a21 --- /dev/null +++ b/bin/tests/system/dsdigest/tests_dsdigest.py @@ -0,0 +1,68 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.message +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/K*", + "ns*/dsset-*", + "ns*/trusted.conf", + "ns*/*.signed", + "ns1/root.db", + "ns2/bad.db", + "ns2/good.db", + ] +) + + +def test_dsdigest_good(): + """Check that validation with enabled digest types works""" + msg = dns.message.make_query("a.good.", "A", want_dnssec=True) + res = isctest.query.tcp( + msg, + "10.53.0.3", + ) + isctest.check.noerror(res) + assert res.flags & dns.flags.AD + + +def test_dsdigest_bad(): + """Check that validation with not supported digest types + and "dnssec-must-be-secure yes;" results in SERVFAIL""" + msg = dns.message.make_query("a.bad.", "A", want_dnssec=True) + res = isctest.query.tcp( + msg, + "10.53.0.3", + ) + isctest.check.servfail(res) + + +def test_dsdigest_insecure(): + """Check that validation with not supported digest algorithms is insecure""" + msg_ds = dns.message.make_query("bad.", "DS", want_dnssec=True) + res_ds = isctest.query.tcp( + msg_ds, + "10.53.0.4", + ) + isctest.check.noerror(res_ds) + assert res_ds.flags & dns.flags.AD + + msg_a = dns.message.make_query("a.bad.", "A", want_dnssec=True) + res_a = isctest.query.tcp( + msg_a, + "10.53.0.4", + ) + isctest.check.noerror(res_a) + assert not res_a.flags & dns.flags.AD diff --git a/bin/tests/system/dyndb/driver/AUTHORS b/bin/tests/system/dyndb/driver/AUTHORS new file mode 100644 index 0000000..5b37853 --- /dev/null +++ b/bin/tests/system/dyndb/driver/AUTHORS @@ -0,0 +1,33 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +Copyright (C) 2009-2015 Red Hat + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + +This sample driver is based on bind-dyndb-ldap project and small portions +of code from ISC BIND 9.10. + +Authors listed in alphabetical order: +Adam Tkac +Jiri Kuncar +Martin Nagy +Petr Spacek diff --git a/bin/tests/system/dyndb/driver/Makefile.am b/bin/tests/system/dyndb/driver/Makefile.am new file mode 100644 index 0000000..3e6b4a4 --- /dev/null +++ b/bin/tests/system/dyndb/driver/Makefile.am @@ -0,0 +1,23 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +noinst_LTLIBRARIES = sample.la + +sample_la_SOURCES = \ + db.c \ + driver.c \ + instance.c \ + log.c \ + syncptr.c \ + zone.c \ + db.h \ + instance.h \ + log.h \ + syncptr.h \ + util.h \ + zone.h + +sample_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) diff --git a/bin/tests/system/dyndb/driver/Makefile.in b/bin/tests/system/dyndb/driver/Makefile.in new file mode 100644 index 0000000..f1e2bf5 --- /dev/null +++ b/bin/tests/system/dyndb/driver/Makefile.in @@ -0,0 +1,815 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = bin/tests/system/dyndb/driver +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +sample_la_LIBADD = +am_sample_la_OBJECTS = db.lo driver.lo instance.lo log.lo syncptr.lo \ + zone.lo +sample_la_OBJECTS = $(am_sample_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +sample_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(sample_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/db.Plo ./$(DEPDIR)/driver.Plo \ + ./$(DEPDIR)/instance.Plo ./$(DEPDIR)/log.Plo \ + ./$(DEPDIR)/syncptr.Plo ./$(DEPDIR)/zone.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(sample_la_SOURCES) +DIST_SOURCES = $(sample_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp AUTHORS README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = sample.la +sample_la_SOURCES = \ + db.c \ + driver.c \ + instance.c \ + log.c \ + syncptr.c \ + zone.c \ + db.h \ + instance.h \ + log.h \ + syncptr.h \ + util.h \ + zone.h + +sample_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/dyndb/driver/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/system/dyndb/driver/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +sample.la: $(sample_la_OBJECTS) $(sample_la_DEPENDENCIES) $(EXTRA_sample_la_DEPENDENCIES) + $(AM_V_CCLD)$(sample_la_LINK) $(sample_la_OBJECTS) $(sample_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instance.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncptr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/db.Plo + -rm -f ./$(DEPDIR)/driver.Plo + -rm -f ./$(DEPDIR)/instance.Plo + -rm -f ./$(DEPDIR)/log.Plo + -rm -f ./$(DEPDIR)/syncptr.Plo + -rm -f ./$(DEPDIR)/zone.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/db.Plo + -rm -f ./$(DEPDIR)/driver.Plo + -rm -f ./$(DEPDIR)/instance.Plo + -rm -f ./$(DEPDIR)/log.Plo + -rm -f ./$(DEPDIR)/syncptr.Plo + -rm -f ./$(DEPDIR)/zone.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/system/dyndb/driver/README b/bin/tests/system/dyndb/driver/README new file mode 100644 index 0000000..db73396 --- /dev/null +++ b/bin/tests/system/dyndb/driver/README @@ -0,0 +1,92 @@ + + +To use the Dynamic DB sample driver, run named and check the log. + + $ cd testing + $ named -gc named.conf + +You should be able to see something like: + +zone test/IN: loaded serial 0 +zone arpa/IN: loaded serial 0 + +This means that the sample driver created empty zones "test." and +"arpa." as defined by "arg" parameters in named.conf. + +$ dig @localhost test. + +should work as usual and you should be able to see the dummy zone with +NS record pointing to the zone apex and A record with 127.0.0.1: + +;; ANSWER SECTION: +test. 86400 IN A 127.0.0.1 +test. 86400 IN NS test. +test. 86400 IN SOA test. test. 0 28800 7200 604800 86400 + +This driver creates two empty zones and allows query/transfer/update to +all IP addresses for demonstration purposes. + +The driver wraps the RBT database implementation used natively by BIND, +and modifies the addrdataset() and substractrdataset() functions to do +additional work during dynamic updates. + +A dynamic update modifies the target zone as usual. After that, the +driver detects whether the modified RR was of type A or AAAA, and if so, +attempts to appropriately generate or delete a matching PTR record in +one of the two zones managed by the driver. + +E.g.: + +$ nsupdate +> update add a.test. 300 IN A 192.0.2.1 +> send + +will add the A record +a.test. 300 IN A 192.0.2.1 + +and also automatically generate the PTR record +1.2.0.192.in-addr.arpa. 300 IN PTR a.test. + +AXFR and RR deletion via dynamic updates should work as usual. Deletion +of a type A or AAAA record should delete the corresponding PTR record +too. + +The zone is stored only in memory, and all changes will be lost on +reload/reconfig. + +Hints for code readers: +- Driver initialization starts in driver.c: dyndb_init() function. +- New database implementation is registered by calling dns_db_register() + and passing a function pointer to it. This sample uses the function + create_db() to initialize the database. +- Zones are created later in instance.c: load_sample_instance_zones(). +- Database entry points are in structure db.c: dns_dbmethods_t + sampledb_methods +- sampledb_methods points to an implementation of the database interface. + See the db.c: addrdataset() implementation and look at how the RBT + database instance is wrapped into an additional layer of logic. diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c new file mode 100644 index 0000000..8639f49 --- /dev/null +++ b/bin/tests/system/dyndb/driver/db.c @@ -0,0 +1,646 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2009-2015 Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Database API implementation. The interface is defined in lib/dns/db.h. + * + * dns_db_*() calls on database instances backed by this driver use + * struct sampledb_methods to find appropriate function implementation. + * + * This example re-uses RBT DB implementation from original BIND and blindly + * proxies most of dns_db_*() calls to this underlying RBT DB. + * See struct sampledb below. + */ + +#include "db.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "instance.h" +#include "syncptr.h" +#include "util.h" + +#define SAMPLEDB_MAGIC ISC_MAGIC('S', 'M', 'D', 'B') +#define VALID_SAMPLEDB(sampledb) \ + ((sampledb) != NULL && (sampledb)->common.impmagic == SAMPLEDB_MAGIC) + +struct sampledb { + dns_db_t common; + sample_instance_t *inst; + + /* + * Internal RBT database implementation provided by BIND. + * Most dns_db_* calls (find(), createiterator(), etc.) + * are blindly forwarded to this RBT DB. + */ + dns_db_t *rbtdb; +}; + +typedef struct sampledb sampledb_t; + +static void +destroy(dns_db_t *db) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_db_detach(&sampledb->rbtdb); + dns_name_free(&sampledb->common.origin, sampledb->common.mctx); + isc_mem_putanddetach(&sampledb->common.mctx, sampledb, + sizeof(*sampledb)); +} + +static void +currentversion(dns_db_t *db, dns_dbversion_t **versionp) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_db_currentversion(sampledb->rbtdb, versionp); +} + +static isc_result_t +newversion(dns_db_t *db, dns_dbversion_t **versionp) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_newversion(sampledb->rbtdb, versionp); +} + +static void +attachversion(dns_db_t *db, dns_dbversion_t *source, + dns_dbversion_t **targetp) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_db_attachversion(sampledb->rbtdb, source, targetp); +} + +static void +closeversion(dns_db_t *db, dns_dbversion_t **versionp, + bool commit DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns__db_closeversion(sampledb->rbtdb, versionp, + commit DNS__DB_FLARG_PASS); +} + +static isc_result_t +findnode(dns_db_t *db, const dns_name_t *name, bool create, + dns_dbnode_t **nodep DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findnode(sampledb->rbtdb, name, create, + nodep DNS__DB_FLARG_PASS); +} + +static isc_result_t +find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_find(sampledb->rbtdb, name, version, type, options, now, + nodep, foundname, rdataset, + sigrdataset DNS__DB_FLARG_PASS); +} + +static isc_result_t +findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, + isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, + dns_name_t *dcname, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findzonecut(sampledb->rbtdb, name, options, now, nodep, + foundname, dcname, rdataset, + sigrdataset DNS__DB_FLARG_PASS); +} + +static void +attachnode(dns_db_t *db, dns_dbnode_t *source, + dns_dbnode_t **targetp DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns__db_attachnode(sampledb->rbtdb, source, targetp DNS__DB_FLARG_PASS); +} + +static void +detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns__db_detachnode(sampledb->rbtdb, targetp DNS__DB_FLARG_PASS); +} + +static isc_result_t +createiterator(dns_db_t *db, unsigned int options, + dns_dbiterator_t **iteratorp) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_createiterator(sampledb->rbtdb, options, iteratorp); +} + +static isc_result_t +findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findrdataset(sampledb->rbtdb, node, version, type, + covers, now, rdataset, + sigrdataset DNS__DB_FLARG_PASS); +} + +static isc_result_t +allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + unsigned int options, isc_stdtime_t now, + dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_allrdatasets(sampledb->rbtdb, node, version, options, + now, iteratorp DNS__DB_FLARG_PASS); +} + +static isc_result_t +addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, + dns_rdataset_t *addedrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + isc_result_t result; + dns_fixedname_t name; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_fixedname_init(&name); + CHECK(dns__db_addrdataset(sampledb->rbtdb, node, version, now, rdataset, + options, addedrdataset DNS__DB_FLARG_PASS)); + if (rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa) + { + CHECK(dns_db_nodefullname(sampledb->rbtdb, node, + dns_fixedname_name(&name))); + CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), + rdataset, DNS_DIFFOP_ADD)); + } + +cleanup: + return result; +} + +static isc_result_t +subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdataset_t *rdataset, unsigned int options, + dns_rdataset_t *newrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + isc_result_t result; + dns_fixedname_t name; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_fixedname_init(&name); + result = dns__db_subtractrdataset(sampledb->rbtdb, node, version, + rdataset, options, + newrdataset DNS__DB_FLARG_PASS); + if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) { + goto cleanup; + } + + if (rdataset->type == dns_rdatatype_a || + rdataset->type == dns_rdatatype_aaaa) + { + CHECK(dns_db_nodefullname(sampledb->rbtdb, node, + dns_fixedname_name(&name))); + CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), + rdataset, DNS_DIFFOP_DEL)); + } + +cleanup: + return result; +} + +/* + * deleterdataset() function is not used during DNS update processing so syncptr + * implementation is left as an exercise to the reader. + */ +static isc_result_t +deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + dns_rdatatype_t type, dns_rdatatype_t covers DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_deleterdataset(sampledb->rbtdb, node, version, type, + covers DNS__DB_FLARG_PASS); +} + +static bool +issecure(dns_db_t *db) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_issecure(sampledb->rbtdb); +} + +static unsigned int +nodecount(dns_db_t *db, dns_dbtree_t tree) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_nodecount(sampledb->rbtdb, tree); +} + +static void +setloop(dns_db_t *db, isc_loop_t *loop) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + dns_db_setloop(sampledb->rbtdb, loop); +} + +static isc_result_t +getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_getoriginnode(sampledb->rbtdb, nodep DNS__DB_FLARG_PASS); +} + +static isc_result_t +getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash, + uint8_t *flags, uint16_t *iterations, unsigned char *salt, + size_t *salt_length) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_getnsec3parameters(sampledb->rbtdb, version, hash, flags, + iterations, salt, salt_length); +} + +static isc_result_t +findnsec3node(dns_db_t *db, const dns_name_t *name, bool create, + dns_dbnode_t **nodep DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findnsec3node(sampledb->rbtdb, name, create, + nodep DNS__DB_FLARG_PASS); +} + +static isc_result_t +setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_setsigningtime(sampledb->rbtdb, rdataset, resign); +} + +static isc_result_t +getsigningtime(dns_db_t *db, isc_stdtime_t *resign, dns_name_t *name, + dns_typepair_t *type) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_getsigningtime(sampledb->rbtdb, resign, name, type); +} + +static dns_stats_t * +getrrsetstats(dns_db_t *db) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_getrrsetstats(sampledb->rbtdb); +} + +static isc_result_t +findnodeext(dns_db_t *db, const dns_name_t *name, bool create, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_dbnode_t **nodep DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findnodeext(sampledb->rbtdb, name, create, methods, + clientinfo, nodep DNS__DB_FLARG_PASS); +} + +static isc_result_t +findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, + dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, + dns_dbnode_t **nodep, dns_name_t *foundname, + dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset DNS__DB_FLARG) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns__db_findext(sampledb->rbtdb, name, version, type, options, + now, nodep, foundname, methods, clientinfo, + rdataset, sigrdataset DNS__DB_FLARG_PASS); +} + +static isc_result_t +setcachestats(dns_db_t *db, isc_stats_t *stats) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_setcachestats(sampledb->rbtdb, stats); +} + +static isc_result_t +nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) { + sampledb_t *sampledb = (sampledb_t *)db; + + REQUIRE(VALID_SAMPLEDB(sampledb)); + + return dns_db_nodefullname(sampledb->rbtdb, node, name); +} + +/* + * DB interface definition. Database driver uses this structure to + * determine which implementation of dns_db_*() function to call. + */ +static dns_dbmethods_t sampledb_methods = { + .destroy = destroy, + .currentversion = currentversion, + .newversion = newversion, + .attachversion = attachversion, + .closeversion = closeversion, + .findnode = findnode, + .find = find, + .findzonecut = findzonecut, + .attachnode = attachnode, + .detachnode = detachnode, + .createiterator = createiterator, + .findrdataset = findrdataset, + .allrdatasets = allrdatasets, + .addrdataset = addrdataset, + .subtractrdataset = subtractrdataset, + .deleterdataset = deleterdataset, + .issecure = issecure, + .nodecount = nodecount, + .setloop = setloop, + .getoriginnode = getoriginnode, + .getnsec3parameters = getnsec3parameters, + .findnsec3node = findnsec3node, + .setsigningtime = setsigningtime, + .getsigningtime = getsigningtime, + .getrrsetstats = getrrsetstats, + .findnodeext = findnodeext, + .findext = findext, + .setcachestats = setcachestats, + .nodefullname = nodefullname, +}; + +/* Auxiliary driver functions. */ + +/* + * Auxiliary functions add_*() create minimal database which can be loaded. + * This is necessary because this driver create empty 'fake' zone which + * is not loaded from disk so there is no way for user to supply SOA, NS and A + * records. + * + * Following functions were copied from BIND 9.10.2rc1 named/server.c, + * credit goes to ISC. + */ +static isc_result_t +add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + const dns_name_t *origin, const dns_name_t *contact) { + dns_dbnode_t *node = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_result_t result; + unsigned char buf[DNS_SOA_BUFFERSIZE]; + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 0, 28800, + 7200, 604800, 86400, buf, &rdata)); + rdatalist.type = rdata.type; + rdatalist.covers = 0; + rdatalist.rdclass = rdata.rdclass; + rdatalist.ttl = 86400; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + CHECK(dns_db_findnode(db, name, true, &node)); + CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); +cleanup: + if (node != NULL) { + dns_db_detachnode(db, &node); + } + return result; +} + +static isc_result_t +add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + const dns_name_t *nsname) { + dns_dbnode_t *node = NULL; + dns_rdata_ns_t ns; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_result_t result; + isc_buffer_t b; + unsigned char buf[DNS_NAME_MAXWIRE]; + + isc_buffer_init(&b, buf, sizeof(buf)); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + ns.common.rdtype = dns_rdatatype_ns; + ns.common.rdclass = dns_db_class(db); + ns.mctx = NULL; + dns_name_init(&ns.name, NULL); + dns_name_clone(nsname, &ns.name); + CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, + &ns, &b)); + rdatalist.type = rdata.type; + rdatalist.covers = 0; + rdatalist.rdclass = rdata.rdclass; + rdatalist.ttl = 86400; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + CHECK(dns_db_findnode(db, name, true, &node)); + CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); +cleanup: + if (node != NULL) { + dns_db_detachnode(db, &node); + } + return result; +} + +static isc_result_t +add_a(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + struct in_addr addr) { + dns_dbnode_t *node = NULL; + dns_rdata_in_a_t a; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + isc_result_t result; + isc_buffer_t b; + unsigned char buf[DNS_NAME_MAXWIRE]; + + isc_buffer_init(&b, buf, sizeof(buf)); + + dns_rdataset_init(&rdataset); + dns_rdatalist_init(&rdatalist); + a.common.rdtype = dns_rdatatype_a; + a.common.rdclass = dns_db_class(db); + a.in_addr = addr; + CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a, + &a, &b)); + rdatalist.type = rdata.type; + rdatalist.covers = 0; + rdatalist.rdclass = rdata.rdclass; + rdatalist.ttl = 86400; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + CHECK(dns_db_findnode(db, name, true, &node)); + CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); +cleanup: + if (node != NULL) { + dns_db_detachnode(db, &node); + } + return result; +} + +/* + * Driver-specific implementation of dns_db_create(). + * + * @param[in] argv Database-specific parameters from dns_db_create(). + * @param[in] driverarg Driver-specific parameter from dns_db_register(). + */ +isc_result_t +create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, + dns_rdataclass_t rdclass, unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp) { + sampledb_t *sampledb = NULL; + isc_result_t result; + dns_dbversion_t *version = NULL; + struct in_addr a_addr; + + REQUIRE(type == dns_dbtype_zone); + REQUIRE(rdclass == dns_rdataclass_in); + REQUIRE(argc == 0); + REQUIRE(argv != NULL); + REQUIRE(driverarg != NULL); /* pointer to driver instance */ + REQUIRE(dbp != NULL && *dbp == NULL); + + UNUSED(driverarg); /* no driver-specific configuration */ + + a_addr.s_addr = 0x0100007fU; + + sampledb = isc_mem_get(mctx, sizeof(*sampledb)); + *sampledb = (sampledb_t){ + .common.magic = DNS_DB_MAGIC, + .common.impmagic = SAMPLEDB_MAGIC, + .common.methods = &sampledb_methods, + .common.rdclass = rdclass, + }; + + isc_mem_attach(mctx, &sampledb->common.mctx); + dns_name_init(&sampledb->common.origin, NULL); + + dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin); + + isc_refcount_init(&sampledb->common.references, 1); + + /* Translate instance name to instance pointer. */ + sampledb->inst = driverarg; + + /* Create internal instance of DB implementation from BIND. */ + CHECK(dns_db_create(mctx, ZONEDB_DEFAULT, origin, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, &sampledb->rbtdb)); + + /* Create fake SOA, NS, and A records to make database loadable. */ + CHECK(dns_db_newversion(sampledb->rbtdb, &version)); + CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin)); + CHECK(add_ns(sampledb->rbtdb, version, origin, origin)); + CHECK(add_a(sampledb->rbtdb, version, origin, a_addr)); + dns_db_closeversion(sampledb->rbtdb, &version, true); + + *dbp = (dns_db_t *)sampledb; + + return ISC_R_SUCCESS; + +cleanup: + if (dns_name_dynamic(&sampledb->common.origin)) { + dns_name_free(&sampledb->common.origin, mctx); + } + + isc_mem_putanddetach(&sampledb->common.mctx, sampledb, + sizeof(*sampledb)); + + return result; +} diff --git a/bin/tests/system/dyndb/driver/db.h b/bin/tests/system/dyndb/driver/db.h new file mode 100644 index 0000000..c520c8b --- /dev/null +++ b/bin/tests/system/dyndb/driver/db.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2009-2015 Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * Database API implementation. + */ + +#pragma once + +#include +#include + +#include +#include +#include +#include + +isc_result_t +create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, + dns_rdataclass_t rdclass, unsigned int argc, char *argv[], + void *driverarg, dns_db_t **dbp); diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c new file mode 100644 index 0000000..dd81ecd --- /dev/null +++ b/bin/tests/system/dyndb/driver/driver.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Driver API implementation and main entry point for BIND. + * + * BIND calls dyndb_version() before loading, dyndb_init() during startup + * and dyndb_destroy() during shutdown. + * + * It is completely up to implementation what to do. + * + * dyndb {} sections in named.conf are independent so + * driver init() and destroy() functions are called independently for + * each section even if they reference the same driver/library. It is + * up to driver implementation to detect and catch this situation if + * it is undesirable. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "db.h" +#include "instance.h" +#include "log.h" +#include "util.h" + +/* aliases for the exported symbols */ + +dns_dyndb_destroy_t dyndb_destroy; +dns_dyndb_register_t dyndb_init; +dns_dyndb_version_t dyndb_version; + +/* + * Driver init is called for each dyndb section in named.conf + * once during startup and then again on every reload. + * + * @code + * dyndb example-name "sample.so" { param1 param2 }; + * @endcode + * + * @param[in] name User-defined string from dyndb "name" {}; definition + * in named.conf. + * The example above will have name = "example-name". + * @param[in] parameters User-defined parameters from dyndb section as one + * string. The example above will have + * params = "param1 param2"; + * @param[in] file The name of the file from which the parameters + * were read. + * @param[in] line The line number from which the parameters were read. + * @param[out] instp Pointer to instance-specific data + * (for one dyndb section). + */ +isc_result_t +dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters, + const char *file, unsigned long line, const dns_dyndbctx_t *dctx, + void **instp) { + isc_result_t result; + unsigned int argc; + char **argv = NULL; + char *s = NULL; + sample_instance_t *sample_inst = NULL; + + REQUIRE(name != NULL); + REQUIRE(dctx != NULL); + + s = isc_mem_strdup(mctx, parameters); + + result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "dyndb_init: isc_commandline_strtoargv -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + log_write(ISC_LOG_DEBUG(9), "loading params for dyndb '%s' from %s:%lu", + name, file, line); + + /* Finally, create the instance. */ + result = new_sample_instance(mctx, name, argc, argv, dctx, + &sample_inst); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "dyndb_init: new_sample_instance -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + /* + * This is an example so we create and load zones + * right now. This step can be arbitrarily postponed. + */ + result = load_sample_instance_zones(sample_inst); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "dyndb_init: load_sample_instance_zones -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + *instp = sample_inst; + +cleanup: + isc_mem_free(mctx, s); + if (argv != NULL) { + isc_mem_cput(mctx, argv, argc, sizeof(*argv)); + } + + return result; +} + +/* + * Driver destroy is called for every instance on every reload and then once + * during shutdown. + * + * @param[out] instp Pointer to instance-specific data (for one dyndb section). + */ +void +dyndb_destroy(void **instp) { + destroy_sample_instance((sample_instance_t **)instp); +} + +/* + * Driver version is called when loading the driver to ensure there + * is no API mismatch between the driver and the caller. + */ +int +dyndb_version(unsigned int *flags) { + UNUSED(flags); + + return DNS_DYNDB_VERSION; +} diff --git a/bin/tests/system/dyndb/driver/instance.c b/bin/tests/system/dyndb/driver/instance.c new file mode 100644 index 0000000..f2ee4aa --- /dev/null +++ b/bin/tests/system/dyndb/driver/instance.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2009-2015 Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Driver instance object. + * + * One instance is equivalent to dynamic-db section in named.conf. + * This module parses arguments and provide high-level operations + * instance init/zone load/instance destroy. + */ + +#include "instance.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "db.h" +#include "log.h" +#include "util.h" +#include "zone.h" + +/* + * Parse parameters and convert them to zone names. Caller has to deallocate + * resulting DNS names. + * + * @param[in] argv NULL-terminated string array of length 2 (excluding NULL) + * Each string has to be a valid DNS name. + * @param[out] z1 Zone name from argv[0] + * @param[out] z2 Zone name from argv[1] + */ +static isc_result_t +parse_params(isc_mem_t *mctx, int argc, char **argv, dns_name_t *z1, + dns_name_t *z2) { + isc_result_t result; + int i; + + REQUIRE(argv != NULL); + REQUIRE(z1 != NULL); + REQUIRE(z2 != NULL); + + for (i = 0; i < argc; i++) { + log_info("param: '%s'", argv[i]); + } + log_info("number of params: %d", i); + + if (argc != 2) { + log_error("exactly two parameters " + "(absolute zone names) are required"); + result = ISC_R_FAILURE; + goto cleanup; + } + result = dns_name_fromstring(z1, argv[0], dns_rootname, 0, mctx); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "parse_params: dns_name_fromstring2 -> %s", + isc_result_totext(result)); + goto cleanup; + } + result = dns_name_fromstring(z2, argv[1], dns_rootname, 0, mctx); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "parse_params: dns_name_fromstring2 -> %s", + isc_result_totext(result)); + goto cleanup; + } + + result = ISC_R_SUCCESS; + +cleanup: + return result; +} + +/* + * Initialize new driver instance. It will not create zones until + * load_sample_instance_zones() is called. + */ +isc_result_t +new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv, + const dns_dyndbctx_t *dctx, + sample_instance_t **sample_instp) { + isc_result_t result; + + REQUIRE(sample_instp != NULL && *sample_instp == NULL); + + sample_instance_t *inst = isc_mem_get(mctx, sizeof(*inst)); + *inst = (sample_instance_t){ 0 }; + + isc_mem_attach(mctx, &inst->mctx); + + inst->db_name = isc_mem_strdup(mctx, db_name); + inst->zone1_name = dns_fixedname_initname(&inst->zone1_fn); + inst->zone2_name = dns_fixedname_initname(&inst->zone2_fn); + + result = parse_params(mctx, argc, argv, inst->zone1_name, + inst->zone2_name); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "new_sample_instance: parse_params -> %s", + isc_result_totext(result)); + goto cleanup; + } + + dns_view_attach(dctx->view, &inst->view); + dns_zonemgr_attach(dctx->zmgr, &inst->zmgr); + inst->loopmgr = dctx->loopmgr; + + /* Register new DNS DB implementation. */ + result = dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "new_sample_instance: dns_db_register -> %s", + isc_result_totext(result)); + goto cleanup; + } + + *sample_instp = inst; + result = ISC_R_SUCCESS; + +cleanup: + if (result != ISC_R_SUCCESS) { + destroy_sample_instance(&inst); + } + return result; +} + +/* + * Create empty zones, add fake SOA, NS, and A records, load fake zones + * and add them to inst->view. + */ +isc_result_t +load_sample_instance_zones(sample_instance_t *inst) { + isc_result_t result; + + result = create_zone(inst, inst->zone1_name, &inst->zone1); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "load_sample_instance_zones: create_zone -> %s", + isc_result_totext(result)); + goto cleanup; + } + result = activate_zone(inst, inst->zone1); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "load_sample_instance_zones: activate_zone -> %s", + isc_result_totext(result)); + goto cleanup; + } + + result = create_zone(inst, inst->zone2_name, &inst->zone2); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "load_sample_instance_zones: create_zone -> %s", + isc_result_totext(result)); + goto cleanup; + } + result = activate_zone(inst, inst->zone2); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "load_sample_instance_zones: activate_zone -> %s", + isc_result_totext(result)); + goto cleanup; + } + +cleanup: + return result; +} + +void +destroy_sample_instance(sample_instance_t **instp) { + sample_instance_t *inst; + REQUIRE(instp != NULL); + + inst = *instp; + *instp = NULL; + if (inst == NULL) { + return; + } + + if (inst->db_name != NULL) { + isc_mem_free(inst->mctx, inst->db_name); + } + if (inst->zone1 != NULL) { + dns_zone_detach(&inst->zone1); + } + if (inst->zone2 != NULL) { + dns_zone_detach(&inst->zone2); + } + if (inst->db_imp != NULL) { + dns_db_unregister(&inst->db_imp); + } + + dns_view_detach(&inst->view); + dns_zonemgr_detach(&inst->zmgr); + + isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst)); +} diff --git a/bin/tests/system/dyndb/driver/instance.h b/bin/tests/system/dyndb/driver/instance.h new file mode 100644 index 0000000..1ce89ba --- /dev/null +++ b/bin/tests/system/dyndb/driver/instance.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2009-2015 Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * Driver instance object. + */ + +#pragma once + +#include + +#include +#include +#include + +struct sample_instance { + isc_mem_t *mctx; + char *db_name; + dns_dbimplementation_t *db_imp; + + /* These are needed for zone creation. */ + dns_view_t *view; + dns_zonemgr_t *zmgr; + isc_loopmgr_t *loopmgr; + bool exiting; + + dns_zone_t *zone1; + dns_fixedname_t zone1_fn; + dns_name_t *zone1_name; + + dns_zone_t *zone2; + dns_fixedname_t zone2_fn; + dns_name_t *zone2_name; +}; + +typedef struct sample_instance sample_instance_t; + +isc_result_t +new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv, + const dns_dyndbctx_t *dctx, + sample_instance_t **sample_instp); + +isc_result_t +load_sample_instance_zones(sample_instance_t *inst); + +void +destroy_sample_instance(sample_instance_t **sample_instp); diff --git a/bin/tests/system/dyndb/driver/log.c b/bin/tests/system/dyndb/driver/log.c new file mode 100644 index 0000000..ef8b1ee --- /dev/null +++ b/bin/tests/system/dyndb/driver/log.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "log.h" + +#include + +#include + +void +log_write(int level, const char *format, ...) { + va_list args; + + va_start(args, format); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, + level, format, args); + va_end(args); +} diff --git a/bin/tests/system/dyndb/driver/log.h b/bin/tests/system/dyndb/driver/log.h new file mode 100644 index 0000000..375db2b --- /dev/null +++ b/bin/tests/system/dyndb/driver/log.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include +#include + +#include + +#define log_error_r(fmt, ...) \ + log_error(fmt ": %s", ##__VA_ARGS__, isc_result_totext(result)) + +#define log_error(format, ...) log_write(ISC_LOG_ERROR, format, ##__VA_ARGS__) + +#define log_info(format, ...) log_write(ISC_LOG_INFO, format, ##__VA_ARGS__) + +void +log_write(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); diff --git a/bin/tests/system/dyndb/driver/syncptr.c b/bin/tests/system/dyndb/driver/syncptr.c new file mode 100644 index 0000000..7703321 --- /dev/null +++ b/bin/tests/system/dyndb/driver/syncptr.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Automatic A/AAAA/PTR record synchronization. + */ + +#include "syncptr.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "instance.h" +#include "util.h" + +/* + * Event used for making changes to reverse zones. + */ +typedef struct syncptr syncptr_t; +struct syncptr { + isc_mem_t *mctx; + dns_zone_t *zone; + dns_diff_t diff; + dns_fixedname_t ptr_target_name; /* referenced by owner name in + * tuple */ + isc_buffer_t b; /* referenced by target name in tuple */ + unsigned char buf[DNS_NAME_MAXWIRE]; +}; + +/* + * Write diff generated in syncptr() to reverse zone. + * + * This function will be called asynchronously and syncptr() will not get + * any result from it. + * + */ +static void +syncptr_write(void *arg) { + syncptr_t *syncptr = (syncptr_t *)arg; + dns_dbversion_t *version = NULL; + dns_db_t *db = NULL; + isc_result_t result; + + log_write(ISC_LOG_INFO, "ENTER: syncptr_write"); + + result = dns_zone_getdb(syncptr->zone, &db); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr_write: dns_zone_getdb -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + result = dns_db_newversion(db, &version); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr_write: dns_db_newversion -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + result = dns_diff_apply(&syncptr->diff, db, version); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr_write: dns_diff_apply -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + +cleanup: + if (db != NULL) { + if (version != NULL) { + dns_db_closeversion(db, &version, true); + } + dns_db_detach(&db); + } + dns_zone_detach(&syncptr->zone); + dns_diff_clear(&syncptr->diff); + isc_mem_putanddetach(&syncptr->mctx, syncptr, sizeof(*syncptr)); +} + +/* + * Find a reverse zone for given IP address. + * + * @param[in] rdata IP address as A/AAAA record + * @param[out] name Owner name for the PTR record + * @param[out] zone DNS zone for reverse record matching the IP address + * + * @retval ISC_R_SUCCESS DNS name derived from given IP address belongs to an + * reverse zone managed by this driver instance. + * PTR record synchronization can continue. + * @retval ISC_R_NOTFOUND Suitable reverse zone was not found because it + * does not exist or is not managed by this driver. + */ +static isc_result_t +syncptr_find_zone(sample_instance_t *inst, dns_rdata_t *rdata, dns_name_t *name, + dns_zone_t **zone) { + isc_result_t result; + isc_netaddr_t isc_ip; /* internal net address representation */ + dns_rdata_in_a_t ipv4; + dns_rdata_in_aaaa_t ipv6; + + REQUIRE(inst != NULL); + REQUIRE(zone != NULL && *zone == NULL); + + switch (rdata->type) { + case dns_rdatatype_a: + CHECK(dns_rdata_tostruct(rdata, &ipv4, inst->mctx)); + isc_netaddr_fromin(&isc_ip, &ipv4.in_addr); + break; + + case dns_rdatatype_aaaa: + CHECK(dns_rdata_tostruct(rdata, &ipv6, inst->mctx)); + isc_netaddr_fromin6(&isc_ip, &ipv6.in6_addr); + break; + + default: + FATAL_ERROR("unsupported address type 0x%x", rdata->type); + break; + } + + /* + * Convert IP address to PTR owner name. + * + * @example + * 192.168.0.1 -> 1.0.168.192.in-addr.arpa + */ + result = dns_byaddr_createptrname(&isc_ip, name); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr_find_zone: dns_byaddr_createptrname -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + /* Find a zone containing owner name of the PTR record. */ + result = dns_view_findzone(inst->view, name, 0, zone); + if (result == DNS_R_PARTIALMATCH) { + result = ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr_find_zone: dns_zt_find -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + /* Make sure that the zone is managed by this driver. */ + if (*zone != inst->zone1 && *zone != inst->zone2) { + dns_zone_detach(zone); + log_write(ISC_LOG_INFO, "syncptr_find_zone: zone not managed"); + result = ISC_R_NOTFOUND; + } + +cleanup: + if (rdata->type == dns_rdatatype_a) { + dns_rdata_freestruct(&ipv4); + } else { + dns_rdata_freestruct(&ipv6); + } + + return result; +} + +/* + * Generate update event for PTR record to reflect change in A/AAAA record. + * + * @pre Reverse zone is managed by this driver. + * + * @param[in] a_name DNS domain of modified A/AAAA record + * @param[in] af Address family + * @param[in] ip_str IP address as a string (IPv4 or IPv6) + * @param[in] mod_op LDAP_MOD_DELETE if A/AAAA record is being deleted + * or LDAP_MOD_ADD if A/AAAA record is being added. + * + * @retval ISC_R_SUCCESS Event for PTR record update was generated and send. + * Change to reverse zone will be done asynchronously. + * @retval other Synchronization failed - reverse doesn't exist, + * is not managed by this driver instance, + * memory allocation error, etc. + */ +static isc_result_t +syncptr(sample_instance_t *inst, dns_name_t *name, dns_rdata_t *addr_rdata, + dns_ttl_t ttl, dns_diffop_t op) { + isc_result_t result; + isc_mem_t *mctx = inst->mctx; + dns_fixedname_t ptr_name; + dns_zone_t *ptr_zone = NULL; + dns_rdata_ptr_t ptr_struct; + dns_rdata_t ptr_rdata = DNS_RDATA_INIT; + dns_difftuple_t *tp = NULL; + syncptr_t *syncptr = NULL; + + dns_fixedname_init(&ptr_name); + DNS_RDATACOMMON_INIT(&ptr_struct, dns_rdatatype_ptr, dns_rdataclass_in); + dns_name_init(&ptr_struct.ptr, NULL); + + syncptr = isc_mem_get(mctx, sizeof(*syncptr)); + *syncptr = (syncptr_t){ 0 }; + isc_mem_attach(mctx, &syncptr->mctx); + isc_buffer_init(&syncptr->b, syncptr->buf, sizeof(syncptr->buf)); + dns_fixedname_init(&syncptr->ptr_target_name); + + /* Check if reverse zone is managed by this driver */ + result = syncptr_find_zone(inst, addr_rdata, + dns_fixedname_name(&ptr_name), &ptr_zone); + if (result != ISC_R_SUCCESS) { + log_error_r("PTR record synchronization skipped: reverse zone " + "is not managed by driver instance '%s'", + inst->db_name); + goto cleanup; + } + + /* Reverse zone is managed by this driver, prepare PTR record */ + dns_zone_attach(ptr_zone, &syncptr->zone); + dns_name_copy(name, dns_fixedname_name(&syncptr->ptr_target_name)); + dns_name_clone(dns_fixedname_name(&syncptr->ptr_target_name), + &ptr_struct.ptr); + dns_diff_init(inst->mctx, &syncptr->diff); + result = dns_rdata_fromstruct(&ptr_rdata, dns_rdataclass_in, + dns_rdatatype_ptr, &ptr_struct, + &syncptr->b); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr: dns_rdata_fromstruct -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + /* Create diff */ + result = dns_difftuple_create(mctx, op, dns_fixedname_name(&ptr_name), + ttl, &ptr_rdata, &tp); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "syncptr: dns_difftuple_create -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + dns_diff_append(&syncptr->diff, &tp); + + /* + * Send update event to the reverse zone. + * It will be processed asynchronously. + */ + isc_async_run(dns_zone_getloop(ptr_zone), syncptr_write, syncptr); + syncptr = NULL; + +cleanup: + if (ptr_zone != NULL) { + dns_zone_detach(&ptr_zone); + } + if (tp != NULL) { + dns_difftuple_free(&tp); + } + if (syncptr != NULL) { + isc_mem_put(mctx, syncptr, sizeof(*syncptr)); + } + + return result; +} + +/* + * Generate update event for every rdata in rdataset. + * + * @param[in] name Owner name for A/AAAA records in rdataset. + * @param[in] rdataset A/AAAA records. + * @param[in] op DNS_DIFFOP_ADD / DNS_DIFFOP_DEL for adding / deleting + * the rdata + */ +isc_result_t +syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset, + dns_diffop_t op) { + isc_result_t result; + dns_rdata_t rdata = DNS_RDATA_INIT; + + for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_rdataset_current(rdataset, &rdata); + result = syncptr(inst, name, &rdata, rdataset->ttl, op); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + goto cleanup; + } + } + if (result == ISC_R_NOMORE) { + result = ISC_R_SUCCESS; + } + +cleanup: + return result; +} diff --git a/bin/tests/system/dyndb/driver/syncptr.h b/bin/tests/system/dyndb/driver/syncptr.h new file mode 100644 index 0000000..91edee1 --- /dev/null +++ b/bin/tests/system/dyndb/driver/syncptr.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Sync PTR records + */ + +#pragma once + +#include + +#include +#include +#include + +#include "instance.h" + +isc_result_t +syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset, + dns_diffop_t op); diff --git a/bin/tests/system/dyndb/driver/util.h b/bin/tests/system/dyndb/driver/util.h new file mode 100644 index 0000000..e3ccedf --- /dev/null +++ b/bin/tests/system/dyndb/driver/util.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Memory allocation and error handling utilities. + */ + +#pragma once + +#include + +#include + +#include "log.h" + +#define CLEANUP_WITH(result_code) \ + do { \ + result = (result_code); \ + goto cleanup; \ + } while (0) + +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c new file mode 100644 index 0000000..d8c7022 --- /dev/null +++ b/bin/tests/system/dyndb/driver/zone.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Zone management. + */ + +#include "zone.h" +#include +#include + +#include + +#include +#include +#include + +#include "instance.h" +#include "log.h" +#include "util.h" + +extern const char *impname; + +/* + * Create a new zone with origin 'name'. The zone stay invisible to clients + * until it is explicitly added to a view. + */ +isc_result_t +create_zone(sample_instance_t *const inst, dns_name_t *const name, + dns_zone_t **const rawp) { + isc_result_t result; + dns_zone_t *raw = NULL; + const char *zone_argv[1]; + char zone_name[DNS_NAME_FORMATSIZE]; + dns_acl_t *acl_any = NULL; + + REQUIRE(inst != NULL); + REQUIRE(name != NULL); + REQUIRE(rawp != NULL && *rawp == NULL); + + zone_argv[0] = inst->db_name; + + dns_zone_create(&raw, inst->mctx, 0); /* FIXME: all zones are assigned + to loop 0 */ + result = dns_zone_setorigin(raw, name); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "create_zone: dns_zone_setorigin -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + dns_zone_setclass(raw, dns_rdataclass_in); + dns_zone_settype(raw, dns_zone_primary); + dns_zone_setdbtype(raw, 1, zone_argv); + + result = dns_zonemgr_managezone(inst->zmgr, raw); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "create_zone: dns_zonemgr_managezone -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + + /* This is completely insecure - use some sensible values instead! */ + result = dns_acl_any(inst->mctx, &acl_any); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, "create_zone: dns_acl_any -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + dns_zone_setupdateacl(raw, acl_any); + dns_zone_setqueryacl(raw, acl_any); + dns_zone_setxfracl(raw, acl_any); + dns_acl_detach(&acl_any); + + *rawp = raw; + return ISC_R_SUCCESS; + +cleanup: + dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE); + log_error_r("failed to create new zone '%s'", zone_name); + + if (raw != NULL) { + if (dns_zone_getmgr(raw) != NULL) { + dns_zonemgr_releasezone(inst->zmgr, raw); + } + dns_zone_detach(&raw); + } + if (acl_any != NULL) { + dns_acl_detach(&acl_any); + } + + return result; +} + +/* + * Add zone to the view defined in inst->view. This will make the zone visible + * to clients. + */ +static isc_result_t +publish_zone(sample_instance_t *inst, dns_zone_t *zone) { + isc_result_t result; + bool freeze = false; + dns_zone_t *zone_in_view = NULL; + dns_view_t *view_in_zone = NULL; + + REQUIRE(inst != NULL); + REQUIRE(zone != NULL); + + /* Return success if the zone is already in the view as expected. */ + result = dns_view_findzone(inst->view, dns_zone_getorigin(zone), + DNS_ZTFIND_EXACT, &zone_in_view); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + goto cleanup; + } + + view_in_zone = dns_zone_getview(zone); + if (view_in_zone != NULL) { + /* Zone has a view set -> view should contain the same zone. */ + if (zone_in_view == zone) { + /* Zone is already published in the right view. */ + CLEANUP_WITH(ISC_R_SUCCESS); + } else if (view_in_zone != inst->view) { + /* + * Un-published inactive zone will have + * inst->view in zone but will not be present + * in the view itself. + */ + dns_zone_log(zone, ISC_LOG_ERROR, + "zone->view doesn't " + "match data in the view"); + CLEANUP_WITH(ISC_R_UNEXPECTED); + } + } + + if (zone_in_view != NULL) { + dns_zone_log(zone, ISC_LOG_ERROR, + "cannot publish zone: view already " + "contains another zone with this name"); + CLEANUP_WITH(ISC_R_UNEXPECTED); + } + + if (inst->view->frozen) { + freeze = true; + dns_view_thaw(inst->view); + } + + dns_zone_setview(zone, inst->view); + result = dns_view_addzone(inst->view, zone); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "publish_zone: dns_view_addzone -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + +cleanup: + if (zone_in_view != NULL) { + dns_zone_detach(&zone_in_view); + } + if (freeze) { + dns_view_freeze(inst->view); + } + + return result; +} + +/* + * @warning Never call this on raw part of in-line secure zone, call it only + * on the secure zone! + */ +static isc_result_t +load_zone(dns_zone_t *zone) { + isc_result_t result; + bool zone_dynamic; + uint32_t serial; + + result = dns_zone_load(zone, false); + if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE && + result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE) + { + goto cleanup; + } + zone_dynamic = (result == DNS_R_DYNAMIC); + + result = dns_zone_getserial(zone, &serial); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, + "load_zone: dns_zone_getserial -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial); + + if (zone_dynamic) { + dns_zone_notify(zone); + } + +cleanup: + return result; +} + +/* + * Add zone to view and call dns_zone_load(). + */ +isc_result_t +activate_zone(sample_instance_t *inst, dns_zone_t *raw) { + isc_result_t result; + + /* + * Zone has to be published *before* zone load + * otherwise it will race with zone->view != NULL check + * in zone_maintenance() in zone.c. + */ + result = publish_zone(inst, raw); + if (result != ISC_R_SUCCESS) { + dns_zone_log(raw, ISC_LOG_ERROR, "cannot add zone to view: %s", + isc_result_totext(result)); + goto cleanup; + } + + result = load_zone(raw); + if (result != ISC_R_SUCCESS) { + log_write(ISC_LOG_ERROR, "activate_zone: load_zone -> %s\n", + isc_result_totext(result)); + goto cleanup; + } + +cleanup: + return result; +} diff --git a/bin/tests/system/dyndb/driver/zone.h b/bin/tests/system/dyndb/driver/zone.h new file mode 100644 index 0000000..85575a0 --- /dev/null +++ b/bin/tests/system/dyndb/driver/zone.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) Red Hat + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + * USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include + +#include + +#include "instance.h" + +isc_result_t +create_zone(sample_instance_t *const inst, dns_name_t *const name, + dns_zone_t **const rawp); + +isc_result_t +activate_zone(sample_instance_t *inst, dns_zone_t *raw); diff --git a/bin/tests/system/dyndb/ns1/named.conf.j2 b/bin/tests/system/dyndb/ns1/named.conf.j2 new file mode 100644 index 0000000..d319a2a --- /dev/null +++ b/bin/tests/system/dyndb/ns1/named.conf.j2 @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.1; 127.0.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dyndb sample "../driver/.libs/sample.so" { ipv4.example.nil. in-addr.arpa. }; +dyndb sample2 "../driver/.libs/sample.so" { ipv6.example.nil. 8.b.d.0.1.0.0.2.ip6.arpa. }; diff --git a/bin/tests/system/dyndb/prereq.sh b/bin/tests/system/dyndb/prereq.sh new file mode 100644 index 0000000..3bab2a6 --- /dev/null +++ b/bin/tests/system/dyndb/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --tsan && { + echo_i "TSAN - skipping dyndb test" + exit 255 +} + +exit 0 diff --git a/bin/tests/system/dyndb/tests.sh b/bin/tests/system/dyndb/tests.sh new file mode 100644 index 0000000..dc6c3d0 --- /dev/null +++ b/bin/tests/system/dyndb/tests.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +DIGOPTS="@10.53.0.1 -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +newtest() { + n=$((n + 1)) + echo_i "${1} (${n})" + ret=0 +} + +test_add() { + host="$1" + type="$2" + ip="$3" + + cat <ns1/update.txt +server 10.53.0.1 ${PORT} +ttl 86400 +update add $host $type $ip +send +EOF + + newtest "adding $host $type $ip" + $NSUPDATE ns1/update.txt >/dev/null 2>&1 || { + [ "$should_fail" ] \ + || echo_i "update failed for $host $type $ip" + return 1 + } + + out=$($DIG $DIGOPTS +noall +answer -t $type -q $host) + echo $out >added.a.out.$n + lines=$(echo "$out" | grep "$ip" | wc -l) + [ $lines -eq 1 ] || { + [ "$should_fail" ] \ + || echo_i "dig output incorrect for $host $type $cmd: $out" + return 1 + } + + for i in 1 2 3 4 5 6 7 8 9 10; do + out=$($DIG $DIGOPTS +noall +answer -x $ip) + echo $out >added.ptr.out.$n + lines=$(echo "$out" | grep "$host" | wc -l) + [ $lines -eq 1 ] && break + $PERL -e 'select(undef, undef, undef, 0.1);' + done + [ $lines -eq 1 ] || { + [ "$should_fail" ] \ + || echo_i "dig reverse output incorrect for $host $type $cmd: $out" + return 1 + } + + return 0 +} + +test_del() { + host="$1" + type="$2" + + ip=$($DIG $DIGOPTS +short $host $type) + + cat <ns1/update.txt +server 10.53.0.1 ${PORT} +update del $host $type +send +EOF + + newtest "deleting $host $type (was $ip)" + $NSUPDATE ns1/update.txt >/dev/null 2>&1 || { + [ "$should_fail" ] \ + || echo_i "update failed deleting $host $type" + return 1 + } + + out=$($DIG $DIGOPTS +noall +answer -t $type -q $host) + echo $out >deleted.a.out.$n + lines=$(echo "$out" | grep "$ip" | wc -l) + [ $lines -eq 0 ] || { + [ "$should_fail" ] \ + || echo_i "dig output incorrect for $host $type $cmd: $out" + return 1 + } + + for i in 1 2 3 4 5 6 7 8 9 10; do + out=$($DIG $DIGOPTS +noall +answer -x $ip) + echo $out >deleted.ptr.out.$n + lines=$(echo "$out" | grep "$host" | wc -l) + [ $lines -eq 0 ] && break + $PERL -e 'select(undef, undef, undef, 0.1);' + done + [ $lines -eq 0 ] || { + [ "$should_fail" ] \ + || echo_i "dig reverse output incorrect for $host $type $cmd: $out" + return 1 + } + + return 0 +} + +test_add test1.ipv4.example.nil. A "10.53.0.10" || ret=1 +status=$((status + ret)) + +test_add test2.ipv4.example.nil. A "10.53.0.11" || ret=1 +status=$((status + ret)) + +test_add test3.ipv4.example.nil. A "10.53.0.12" || ret=1 +status=$((status + ret)) + +test_add test4.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 +status=$((status + ret)) + +test_del test1.ipv4.example.nil. A || ret=1 +status=$((status + ret)) + +test_del test2.ipv4.example.nil. A || ret=1 +status=$((status + ret)) + +test_del test3.ipv4.example.nil. A || ret=1 +status=$((status + ret)) + +test_del test4.ipv6.example.nil. AAAA || ret=1 +status=$((status + ret)) + +newtest "checking parameter logging" +grep "loading params for dyndb 'sample' from .*named.conf:" ns1/named.run >/dev/null || ret=1 +grep "loading params for dyndb 'sample2' from .*named.conf:" ns1/named.run >/dev/null || ret=1 +[ $ret -eq 1 ] && echo_i "failed" +status=$((status + ret)) + +echo_i "checking dyndb still works after reload" +rndc_reload ns1 10.53.0.1 + +test_add test5.ipv4.example.nil. A "10.53.0.10" || ret=1 +status=$((status + ret)) + +test_add test6.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 +status=$((status + ret)) + +test_del test5.ipv4.example.nil. A || ret=1 +status=$((status + ret)) + +test_del test6.ipv6.example.nil. AAAA || ret=1 +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dyndb/tests_sh_dyndb.py b/bin/tests/system/dyndb/tests_sh_dyndb.py new file mode 100644 index 0000000..dab651d --- /dev/null +++ b/bin/tests/system/dyndb/tests_sh_dyndb.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "added.*", + "deleted.*", + "ns1/update.txt", + ] +) + + +def test_dyndb(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/ecdsa/ns1/named.conf.in b/bin/tests/system/ecdsa/ns1/named.conf.in new file mode 100644 index 0000000..da27c58 --- /dev/null +++ b/bin/tests/system/ecdsa/ns1/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/ecdsa/ns1/root.db.in b/bin/tests/system/ecdsa/ns1/root.db.in new file mode 100644 index 0000000..3bff1d1 --- /dev/null +++ b/bin/tests/system/ecdsa/ns1/root.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA fdupont.isc.org. a.root.servers.nil. ( + 2012040600 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/ecdsa/ns1/sign.sh b/bin/tests/system/ecdsa/ns1/sign.sh new file mode 100644 index 0000000..ec41d20 --- /dev/null +++ b/bin/tests/system/ecdsa/ns1/sign.sh @@ -0,0 +1,51 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +echo_i "ns1/sign.sh" + +cp $infile $zonefile + +if [ $ECDSAP256SHA256_SUPPORTED = 1 ]; then + zsk256=$($KEYGEN -q -a ECDSA256 -n zone "$zone") + ksk256=$($KEYGEN -q -a ECDSA256 -n zone -f KSK "$zone") + cat "$ksk256.key" "$zsk256.key" >>"$zonefile" + $DSFROMKEY -a sha-256 "$ksk256.key" >>dsset-256 +fi + +if [ $ECDSAP384SHA384_SUPPORTED = 1 ]; then + zsk384=$($KEYGEN -q -a ECDSA384 -n zone "$zone") + ksk384=$($KEYGEN -q -a ECDSA384 -n zone -f KSK "$zone") + cat "$ksk384.key" "$zsk384.key" >>"$zonefile" + $DSFROMKEY -a sha-256 "$ksk384.key" >>dsset-256 +fi + +# Configure the resolving server with a static key. +if [ $ECDSAP256SHA256_SUPPORTED = 1 ]; then + keyfile_to_static_ds $ksk256 >trusted.conf + cp trusted.conf ../ns2/trusted.conf +fi + +if [ $ECDSAP384SHA384_SUPPORTED = 1 ]; then + keyfile_to_static_ds $ksk384 >trusted.conf + cp trusted.conf ../ns3/trusted.conf +fi + +$SIGNER -P -g -o "$zone" "$zonefile" >/dev/null 2>signer.err || cat signer.err diff --git a/bin/tests/system/ecdsa/ns2/named.conf.in b/bin/tests/system/ecdsa/ns2/named.conf.in new file mode 100644 index 0000000..bb8a89c --- /dev/null +++ b/bin/tests/system/ecdsa/ns2/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/ecdsa/ns3/named.conf.in b/bin/tests/system/ecdsa/ns3/named.conf.in new file mode 100644 index 0000000..0053898 --- /dev/null +++ b/bin/tests/system/ecdsa/ns3/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/ecdsa/setup.sh b/bin/tests/system/ecdsa/setup.sh new file mode 100644 index 0000000..89aa024 --- /dev/null +++ b/bin/tests/system/ecdsa/setup.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +( + cd ns1 + $SHELL sign.sh +) diff --git a/bin/tests/system/ecdsa/tests_ecdsa.py b/bin/tests/system/ecdsa/tests_ecdsa.py new file mode 100644 index 0000000..1329fa7 --- /dev/null +++ b/bin/tests/system/ecdsa/tests_ecdsa.py @@ -0,0 +1,53 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import pytest + +import dns.message +import isctest + + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/trusted.conf", + "ns1/K*", + "ns1/dsset-*", + "ns1/root.db", + "ns1/root.db.signed", + "ns1/signer.err", + ] +) + + +def check_server_soa(resolver): + msg = dns.message.make_query(".", "SOA") + msg.flags += dns.flags.AD + res1 = isctest.query.tcp(msg, "10.53.0.1") + res2 = isctest.query.tcp(msg, resolver) + isctest.check.rrsets_equal(res1.answer, res2.answer) + assert res2.flags & dns.flags.AD + + +@pytest.mark.skipif( + not os.getenv("ECDSAP256SHA256_SUPPORTED"), + reason="algorithm ECDSA256 not supported", +) +def test_ecdsa256(): + check_server_soa("10.53.0.2") + + +@pytest.mark.skipif( + not os.getenv("ECDSAP384SHA384_SUPPORTED"), + reason="algorithm ECDSA384 not supported", +) +def test_ecdsa384(): + check_server_soa("10.53.0.3") diff --git a/bin/tests/system/eddsa/ns1/named.conf.in b/bin/tests/system/eddsa/ns1/named.conf.in new file mode 100644 index 0000000..da27c58 --- /dev/null +++ b/bin/tests/system/eddsa/ns1/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/eddsa/ns1/root.db.in b/bin/tests/system/eddsa/ns1/root.db.in new file mode 100644 index 0000000..3bff1d1 --- /dev/null +++ b/bin/tests/system/eddsa/ns1/root.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA fdupont.isc.org. a.root.servers.nil. ( + 2012040600 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/eddsa/ns1/sign.sh b/bin/tests/system/eddsa/ns1/sign.sh new file mode 100644 index 0000000..d1b06f7 --- /dev/null +++ b/bin/tests/system/eddsa/ns1/sign.sh @@ -0,0 +1,57 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +echo_i "ns1/sign.sh" + +cp $infile $zonefile + +if [ $ED25519_SUPPORTED = 1 ]; then + zsk25519=$($KEYGEN -q -a ED25519 -n zone "$zone") + ksk25519=$($KEYGEN -q -a ED25519 -n zone -f KSK "$zone") + cat "$ksk25519.key" "$zsk25519.key" >>"$zonefile" + $DSFROMKEY -a sha-256 "$ksk25519.key" >>dsset-256 +fi + +if [ $ED448_SUPPORTED = 1 ]; then + zsk448=$($KEYGEN -q -a ED448 -n zone "$zone") + ksk448=$($KEYGEN -q -a ED448 -n zone -f KSK "$zone") + cat "$ksk448.key" "$zsk448.key" >>"$zonefile" + $DSFROMKEY -a sha-256 "$ksk448.key" >>dsset-256 +fi + +# Configure the resolving server with a static key. +if [ $ED25519_SUPPORTED = 1 ]; then + keyfile_to_static_ds $ksk25519 >trusted.conf + cp trusted.conf ../ns2/trusted.conf +else + keyfile_to_static_ds $ksk448 >trusted.conf + cp trusted.conf ../ns2/trusted.conf +fi + +if [ $ED448_SUPPORTED = 1 ]; then + keyfile_to_static_ds $ksk448 >trusted.conf + cp trusted.conf ../ns3/trusted.conf +else + keyfile_to_static_ds $ksk25519 >trusted.conf + cp trusted.conf ../ns3/trusted.conf +fi + +$SIGNER -P -g -o "$zone" "$zonefile" >/dev/null 2>signer.err || cat signer.err diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key new file mode 100644 index 0000000..ff6d5bf --- /dev/null +++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.key @@ -0,0 +1 @@ +example.com. IN DNSKEY 257 3 15 l02Woi0iS8Aa25FQkUd9RMzZHJpBoRQwAQEX1SxZJA4= diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private new file mode 100644 index 0000000..788b2d7 --- /dev/null +++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+03613.private @@ -0,0 +1,4 @@ +Private-key-format: v1.2 +Algorithm: 15 (ED25519) +PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI= + diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key new file mode 100644 index 0000000..71e4620 --- /dev/null +++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.key @@ -0,0 +1 @@ +example.com. IN DNSKEY 257 3 15 zPnZ/QwEe7S8C5SPz2OfS5RR40ATk2/rYnE9xHIEijs= diff --git a/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private new file mode 100644 index 0000000..78ec36d --- /dev/null +++ b/bin/tests/system/eddsa/ns2/Xexample.com.+015+35217.private @@ -0,0 +1,3 @@ +Private-key-format: v1.2 +Algorithm: 15 (ED25519) +PrivateKey: DSSF3o0s0f+ElWzj9E/Osxw8hLpk55chkmx0LYN5WiY= diff --git a/bin/tests/system/eddsa/ns2/example.com.db.in b/bin/tests/system/eddsa/ns2/example.com.db.in new file mode 100644 index 0000000..0ecda67 --- /dev/null +++ b/bin/tests/system/eddsa/ns2/example.com.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA fdupont.isc.org. ns.example.com. ( + 2012040600 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 3600 ; minimum + ) + MX 10 mail.example.com. + NS ns.example.com. +ns.example.com. A 10.53.0.2 diff --git a/bin/tests/system/eddsa/ns2/named.conf.in b/bin/tests/system/eddsa/ns2/named.conf.in new file mode 100644 index 0000000..bb8a89c --- /dev/null +++ b/bin/tests/system/eddsa/ns2/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/eddsa/ns2/sign.sh b/bin/tests/system/eddsa/ns2/sign.sh new file mode 100644 index 0000000..175263c --- /dev/null +++ b/bin/tests/system/eddsa/ns2/sign.sh @@ -0,0 +1,37 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../../conf.sh + +zone=example.com. +infile=example.com.db.in +zonefile=example.com.db +starttime=20150729220000 +endtime=20150819220000 + +echo_i "ns2/sign.sh" + +cp $infile $zonefile + +if [ $ED25519_SUPPORTED = 1 ]; then + + for i in Xexample.com.+015+03613 Xexample.com.+015+35217; do + cp "$i.key" "$(echo $i.key | sed s/X/K/)" + cp "$i.private" "$(echo $i.private | sed s/X/K/)" + cat "$(echo $i.key | sed s/X/K/)" >>"$zonefile" + done +fi + +$SIGNER -P -z -s "$starttime" -e "$endtime" -o "$zone" "$zonefile" >/dev/null 2>signer.err || cat signer.err diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key new file mode 100644 index 0000000..5c4628f --- /dev/null +++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.key @@ -0,0 +1 @@ +example.com. IN DNSKEY 257 3 16 3kgROaDjrh0H2iuixWBrc8g2EpBBLCdGzHmn+G2MpTPhpj/OiBVHHSfPodx1FYYUcJKm1MDpJtIA diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private new file mode 100644 index 0000000..eb065f9 --- /dev/null +++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+09713.private @@ -0,0 +1,3 @@ +Private-key-format: v1.2 +Algorithm: 16 (ED448) +PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key new file mode 100644 index 0000000..705856d --- /dev/null +++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.key @@ -0,0 +1 @@ +example.com. IN DNSKEY 257 3 16 kkreGWoccSDmUBGAe7+zsbG6ZAFQp+syPmYUurBRQc3tDjeMCJcVMRDmgcNLp5HlHAMy12VoISsA diff --git a/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private new file mode 100644 index 0000000..b512d80 --- /dev/null +++ b/bin/tests/system/eddsa/ns3/Xexample.com.+016+38353.private @@ -0,0 +1,3 @@ +Private-key-format: v1.2 +Algorithm: 16 (ED448) +PrivateKey: WEykD3ht3MHkU8iH4uVOLz8JLwtRBSqiBoM6fF72+Mrp/u5gjxuB1DV6NnPO2BlZdz4hdSTkOdOA diff --git a/bin/tests/system/eddsa/ns3/example.com.db.in b/bin/tests/system/eddsa/ns3/example.com.db.in new file mode 100644 index 0000000..9a1aab6 --- /dev/null +++ b/bin/tests/system/eddsa/ns3/example.com.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA fdupont.isc.org. ns.example.com. ( + 2012040600 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 3600 ; minimum + ) + MX 10 mail.example.com. + NS ns.example.com. +ns.example.com. A 10.53.0.3 diff --git a/bin/tests/system/eddsa/ns3/named.conf.in b/bin/tests/system/eddsa/ns3/named.conf.in new file mode 100644 index 0000000..0053898 --- /dev/null +++ b/bin/tests/system/eddsa/ns3/named.conf.in @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/eddsa/ns3/sign.sh b/bin/tests/system/eddsa/ns3/sign.sh new file mode 100644 index 0000000..1245adb --- /dev/null +++ b/bin/tests/system/eddsa/ns3/sign.sh @@ -0,0 +1,36 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../../conf.sh + +zone=example.com. +infile=example.com.db.in +zonefile=example.com.db +starttime=20150729220000 +endtime=20150819220000 + +echo_i "ns3/sign.sh" + +cp $infile $zonefile + +if [ $ED448_SUPPORTED = 1 ]; then + for i in Xexample.com.+016+09713 Xexample.com.+016+38353; do + cp "$i.key" "$(echo $i.key | sed s/X/K/)" + cp "$i.private" "$(echo $i.private | sed s/X/K/)" + cat "$(echo $i.key | sed s/X/K/)" >>"$zonefile" + done +fi + +$SIGNER -P -z -s "$starttime" -e "$endtime" -o "$zone" "$zonefile" >/dev/null 2>signer.err || cat signer.err diff --git a/bin/tests/system/eddsa/prereq.sh b/bin/tests/system/eddsa/prereq.sh new file mode 100644 index 0000000..ccf967b --- /dev/null +++ b/bin/tests/system/eddsa/prereq.sh @@ -0,0 +1,20 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +if [ $ED25519_SUPPORTED = 0 ] && [ $ED448_SUPPORTED = 0 ]; then + exit 1 +fi diff --git a/bin/tests/system/eddsa/setup.sh b/bin/tests/system/eddsa/setup.sh new file mode 100644 index 0000000..5d25331 --- /dev/null +++ b/bin/tests/system/eddsa/setup.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf + +( + cd ns1 + $SHELL sign.sh +) +( + cd ns2 + $SHELL sign.sh +) +( + cd ns3 + $SHELL sign.sh +) diff --git a/bin/tests/system/eddsa/tests.sh b/bin/tests/system/eddsa/tests.sh new file mode 100644 index 0000000..4967ff2 --- /dev/null +++ b/bin/tests/system/eddsa/tests.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +dig_with_opts() { + "$DIG" +tcp +noau +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" +} + +if [ $ED25519_SUPPORTED = 1 ]; then + # Check the example. domain + n=$((n + 1)) + echo_i "checking that Ed25519 positive validation works ($n)" + ret=0 + dig_with_opts . @10.53.0.1 soa >dig.out.ns1.test$n || ret=1 + dig_with_opts . @10.53.0.2 soa >dig.out.ns2.test$n || ret=1 + $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns2.test$n || ret=1 + grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # Check test vectors (RFC 8080 + errata) + n=$((n + 1)) + echo_i "checking that Ed25519 test vectors match ($n)" + ret=0 + grep 'oL9krJun7xfBOIWcGHi7mag5/hdZrKWw15jP' ns2/example.com.db.signed >/dev/null || ret=1 + grep 'VrbpMngwcrqNAg==' ns2/example.com.db.signed >/dev/null || ret=1 + grep 'zXQ0bkYgQTEFyfLyi9QoiY6D8ZdYo4wyUhVi' ns2/example.com.db.signed >/dev/null || ret=1 + grep 'R0O7KuI5k2pcBg==' ns2/example.com.db.signed >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "algorithm Ed25519 not supported, skipping vectors match test" +fi + +n=$((n + 1)) +ret=0 +if [ $ED448_SUPPORTED = 1 ]; then + # Check the example. domain + n=$((n + 1)) + echo_i "checking that Ed448 positive validation works ($n)" + ret=0 + dig_with_opts . @10.53.0.1 soa >dig.out.ns1.test$n || ret=1 + dig_with_opts . @10.53.0.3 soa >dig.out.ns3.test$n || ret=1 + $PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns3.test$n || ret=1 + grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # Check test vectors (RFC 8080 + errata) + n=$((n + 1)) + echo_i "checking that Ed448 test vectors match ($n)" + ret=0 + grep '3cPAHkmlnxcDHMyg7vFC34l0blBhuG1qpwLm' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'jInI8w1CMB29FkEAIJUA0amxWndkmnBZ6SKi' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'wZSAxGILn/NBtOXft0+Gj7FSvOKxE/07+4RQ' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'vE581N3Aj/JtIyaiYVdnYtyMWbSNyGEY2213' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'WKsJlwEA' ns3/example.com.db.signed >/dev/null || ret=1 + + grep 'E1/oLjSGIbmLny/4fcgM1z4oL6aqo+izT3ur' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'CyHyvEp4Sp8Syg1eI+lJ57CSnZqjJP41O/9l' ns3/example.com.db.signed >/dev/null || ret=1 + grep '4m0AsQ4f7qI1gVnML8vWWiyW2KXhT9kuAICU' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'Sxv5OWbf81Rq7Yu60npabODB0QFPb/rkW3kU' ns3/example.com.db.signed >/dev/null || ret=1 + grep 'ZmQ0YQUA' ns3/example.com.db.signed >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "algorithm Ed448 not supported, skipping vectors match test" +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/eddsa/tests_sh_eddsa.py b/bin/tests/system/eddsa/tests_sh_eddsa.py new file mode 100644 index 0000000..587748f --- /dev/null +++ b/bin/tests/system/eddsa/tests_sh_eddsa.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns*/*.signed", + "ns*/K*", + "ns*/dsset-*", + "ns*/signer.err", + "ns*/trusted.conf", + "ns1/root.db", + "ns2/example.com.db", + "ns3/example.com.db", + ] +) + + +def test_eddsa(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/ednscompliance/ns1/named.conf.j2 b/bin/tests/system/ednscompliance/ns1/named.conf.j2 new file mode 100644 index 0000000..3a640ff --- /dev/null +++ b/bin/tests/system/ednscompliance/ns1/named.conf.j2 @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + server-id "ns1"; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/ednscompliance/ns1/root.db b/bin/tests/system/ednscompliance/ns1/root.db new file mode 100644 index 0000000..f9bfbe9 --- /dev/null +++ b/bin/tests/system/ednscompliance/ns1/root.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.6 diff --git a/bin/tests/system/ednscompliance/tests.sh b/bin/tests/system/ednscompliance/tests.sh new file mode 100644 index 0000000..3fae211 --- /dev/null +++ b/bin/tests/system/ednscompliance/tests.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+norec -p ${PORT}" + +status=0 +n=0 +zone=. + +n=$((n + 1)) +echo_i "check +edns=100 sets version 100 ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +qr +edns=100 soa $zone >dig.out$n || ret=1 +grep "EDNS: version: 100," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 reason= +echo_i "check +ednsopt=100 adds option 100 ($n)" +$DIG $DIGOPTS @10.53.0.1 +qr +ednsopt=100 soa $zone >dig.out$n || ret=1 +grep "; OPT=100" dig.out$n >/dev/null || { + ret=1 + reason="option" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check +ednsflags=0x80 sets flags to 0x0080 ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +qr +ednsflags=0x80 soa $zone >dig.out$n || ret=1 +grep "MBZ: 0x0080," dig.out$n >/dev/null || { + ret=1 + reason="flags" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Unknown EDNS version ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +edns=100 +nsid +noednsnegotiation soa $zone >dig.out$n || ret=1 +grep "status: BADVERS," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "; COOKIE: .* (good)" dig.out$n >/dev/null || { + ret=1 + reason="cookie missing" +} +grep '; NSID: 6e 73 31 ("ns1")' dig.out$n >/dev/null || { + ret=1 + reason="nsid missing" +} +grep "IN.SOA." dig.out$n >/dev/null && { + ret=1 + reason="soa" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Unknown EDNS option ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +ednsopt=100 soa $zone >dig.out$n || ret=1 +grep "status: NOERROR," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "; OPT=100" dig.out$n >/dev/null && { + ret=1 + reason="option" +} +grep "IN.SOA." dig.out$n >/dev/null || { + ret=1 + reason="nosoa" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Unknown EDNS version + option ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsneg +ednsopt=100 soa $zone >dig.out$n || ret=1 +grep "status: BADVERS," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "; OPT=100" dig.out$n >/dev/null && { + ret=1 + reason="option" +} +grep "IN.SOA." dig.out$n >/dev/null && { + ret=1 + reason="soa" +} +if [ $ret != 0 ]; then echo_i "failed: $reason"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "Unknown EDNS flag ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +ednsflags=0x80 soa $zone >dig.out$n || ret=1 +grep "status: NOERROR," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "EDNS:.*MBZ" dig.out$n >/dev/null >/dev/null && { + ret=1 + reason="mbz" +} +grep ".IN.SOA." dig.out$n >/dev/null || { + ret=1 + reason="nosoa" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Unknown EDNS version + flag ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +edns=100 +noednsneg +ednsflags=0x80 soa $zone >dig.out$n || ret=1 +grep "status: BADVERS," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "EDNS:.*MBZ" dig.out$n >/dev/null >/dev/null && { + ret=1 + reason="mbz" +} +grep "IN.SOA." dig.out$n >/dev/null && { + ret=1 + reason="soa" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "DiG's EDNS negotiation ($n)" +ret=0 reason= +$DIG $DIGOPTS @10.53.0.1 +edns=100 soa $zone >dig.out$n || ret=1 +grep "status: NOERROR," dig.out$n >/dev/null || { + ret=1 + reason="status" +} +grep "EDNS: version: 0," dig.out$n >/dev/null || { + ret=1 + reason="version" +} +grep "IN.SOA." dig.out$n >/dev/null || { + ret=1 + reason="soa" +} +if [ $ret != 0 ]; then echo_i "failed $reason"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py b/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py new file mode 100644 index 0000000..cdd2f30 --- /dev/null +++ b/bin/tests/system/ednscompliance/tests_sh_ednscompliance.py @@ -0,0 +1,22 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + ] +) + + +def test_ednscompliance(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/emptyzones/ns1/empty.db b/bin/tests/system/emptyzones/ns1/empty.db new file mode 100644 index 0000000..70dbcaf --- /dev/null +++ b/bin/tests/system/emptyzones/ns1/empty.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 SOA . . 0 0 0 0 0 +@ 0 NS . diff --git a/bin/tests/system/emptyzones/ns1/named.conf.j2 b/bin/tests/system/emptyzones/ns1/named.conf.j2 new file mode 100644 index 0000000..2787ccb --- /dev/null +++ b/bin/tests/system/emptyzones/ns1/named.conf.j2 @@ -0,0 +1,54 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + algorithm @DEFAULT_HMAC@; + secret "1234abcd8765"; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } + except-from { "example.org"; }; + deny-answer-aliases { "example.org"; } + except-from { "goodcname.example.net"; + "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; + allow-transfer { none; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +{% set automatic_empty_zones = automatic_empty_zones | default(False) %} +{% if automatic_empty_zones %} +zone "1.10.in-addr.arpa" { + type primary; file "empty.db"; +}; +{% else %} +include "rfc1918.zones"; +{% endif %} diff --git a/bin/tests/system/emptyzones/ns1/rfc1918.zones b/bin/tests/system/emptyzones/ns1/rfc1918.zones new file mode 100644 index 0000000..07858f9 --- /dev/null +++ b/bin/tests/system/emptyzones/ns1/rfc1918.zones @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "10.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "16.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "17.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "18.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "19.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "20.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "21.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "22.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "23.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "24.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "25.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "26.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "27.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "28.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "29.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "30.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "31.172.IN-ADDR.ARPA" { type primary; file "empty.db"; }; +zone "168.192.IN-ADDR.ARPA" { type primary; file "empty.db"; }; + diff --git a/bin/tests/system/emptyzones/ns1/root.hint b/bin/tests/system/emptyzones/ns1/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/emptyzones/ns1/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/emptyzones/tests_emptyzones.py b/bin/tests/system/emptyzones/tests_emptyzones.py new file mode 100644 index 0000000..7a8d396 --- /dev/null +++ b/bin/tests/system/emptyzones/tests_emptyzones.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.message + +import isctest + + +def test_emptyzones(servers, templates): + # check that switching to automatic empty zones works + ns1 = servers["ns1"] + ns1.rndc("reload") + templates.render("ns1/named.conf", {"automatic_empty_zones": True}) + ns1.rndc("reload") + msg = dns.message.make_query("version.bind", "TXT", "CH") + res = isctest.query.tcp(msg, "10.53.0.1") + isctest.check.noerror(res) + + # check that allow-transfer { none; } works + msg = dns.message.make_query("10.in-addr.arpa", "AXFR") + res = isctest.query.tcp(msg, "10.53.0.1") + isctest.check.refused(res) diff --git a/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt b/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt new file mode 100644 index 0000000..b9c5a32 --- /dev/null +++ b/bin/tests/system/enginepkcs11/2037-pk11_numbits-crash-test.pkt @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. +edda 2800 0001 0000 0001 0000 0972 7361 +7368 6132 3536 0765 7861 6d70 6c65 0000 +0600 01c0 0c00 3000 0100 0001 2c01 0801 +0003 0803 0100 0100 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 0000 0000 0000 0000 0000 +0000 0000 0000 00 diff --git a/bin/tests/system/enginepkcs11/ns1/named.args.in b/bin/tests/system/enginepkcs11/ns1/named.args.in new file mode 100644 index 0000000..8899921 --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns1/named.args.in @@ -0,0 +1 @@ +@ENGINE_ARGS@ -D enginepkcs11-ns1 -m record -c named.conf -d 99 -T maxcachesize=2097152 diff --git a/bin/tests/system/enginepkcs11/ns1/named.conf.in b/bin/tests/system/enginepkcs11/ns1/named.conf.in new file mode 100644 index 0000000..b6c2d2d --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns1/named.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key-store "hsm" { + directory "."; + pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234"; +}; + +key-store "pin" { + directory "."; + pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-source=pin"; +}; + +key-store "disk" { + directory "keys"; +}; diff --git a/bin/tests/system/enginepkcs11/ns1/template.db.in b/bin/tests/system/enginepkcs11/ns1/template.db.in new file mode 100644 index 0000000..f2baaa7 --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns1/template.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 + +txt TXT "test" + diff --git a/bin/tests/system/enginepkcs11/ns2/named.args.in b/bin/tests/system/enginepkcs11/ns2/named.args.in new file mode 100644 index 0000000..1d6beb9 --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns2/named.args.in @@ -0,0 +1 @@ +@ENGINE_ARGS@ -D enginepkcs11-ns2 -m record -c named.conf -d 99 -U 4 -T maxcachesize=2097152 diff --git a/bin/tests/system/enginepkcs11/ns2/named.conf.in b/bin/tests/system/enginepkcs11/ns2/named.conf.in new file mode 100644 index 0000000..0622a94 --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns2/named.conf.in @@ -0,0 +1,57 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify no; +}; + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key-store "hsm" { + directory "."; + pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234"; +}; + +key-store "hsm2" { + directory "keys"; + pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-value=1234"; +}; + +key-store "pin" { + directory "."; + pkcs11-uri "pkcs11:token=softhsm2-enginepkcs11;pin-source=pin"; +}; + +key-store "disk" { + directory "keys"; +}; + diff --git a/bin/tests/system/enginepkcs11/ns2/template.db.in b/bin/tests/system/enginepkcs11/ns2/template.db.in new file mode 100644 index 0000000..a140bff --- /dev/null +++ b/bin/tests/system/enginepkcs11/ns2/template.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.2 + +txt TXT "test" diff --git a/bin/tests/system/enginepkcs11/prereq.sh b/bin/tests/system/enginepkcs11/prereq.sh new file mode 100644 index 0000000..335b348 --- /dev/null +++ b/bin/tests/system/enginepkcs11/prereq.sh @@ -0,0 +1,36 @@ +#!/bin/sh -e +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +[ "prereq/var/tmp/etc/openssl-provider.cnf" = "prereq${OPENSSL_CONF}" ] || { + echo_i "skip: pkcs11-provider not enabled" + exit 255 +} + +[ -n "${SOFTHSM2_CONF}" ] || { + echo_i "skip: softhsm2 configuration not available" + exit 255 +} + +[ -f "$SOFTHSM2_MODULE" ] || { + echo_i "skip: softhsm2 module not available" + exit 1 +} + +for _bin in softhsm2-util pkcs11-tool; do + command -v "$_bin" >/dev/null || { + echo_i "skip: $_bin not available" + exit 1 + } +done diff --git a/bin/tests/system/enginepkcs11/setup.sh b/bin/tests/system/enginepkcs11/setup.sh new file mode 100644 index 0000000..a91368a --- /dev/null +++ b/bin/tests/system/enginepkcs11/setup.sh @@ -0,0 +1,329 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +OPENSSL_CONF= softhsm2-util --delete-token --token "softhsm2-enginepkcs11" >/dev/null 2>&1 || true +OPENSSL_CONF= softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-enginepkcs11" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }' + +printf '%s' "${HSMPIN:-1234}" >ns1/pin +PWD=$(pwd) + +keygen() { + type="$1" + bits="$2" + zone="$3" + id="$4" + + label="${id}-${zone}" + p11id=$(echo "${label}" | openssl sha1 -r | awk '{print $1}') + OPENSSL_CONF= pkcs11-tool --module $SOFTHSM2_MODULE --token-label "softhsm2-enginepkcs11" -l -k --key-type $type:$bits --label "${label}" --id "${p11id}" --pin $(cat $PWD/ns1/pin) >pkcs11-tool.out.$zone.$id 2>pkcs11-tool.err.$zone.$id || return 1 +} + +keyfromlabel() { + alg="$1" + zone="$2" + id="$3" + dir="$4" + shift 4 + + $KEYFRLAB $ENGINE_ARG -K $dir -a $alg -l "pkcs11:token=softhsm2-enginepkcs11;object=${id}-${zone};pin-source=$PWD/ns1/pin" "$@" $zone >>keyfromlabel.out.$zone.$id 2>keyfromlabel.err.$zone.$id || return 1 + cat keyfromlabel.out.$zone.$id +} + +# Setup ns1. +copy_setports ns1/named.conf.in ns1/named.conf +sed -e "s/@ENGINE_ARGS@/${ENGINE_ARG}/g" ns1/named.args + +mkdir ns1/keys + +dir="ns1" +infile="${dir}/template.db.in" +for algtypebits in rsasha256:rsa:2048 rsasha512:rsa:2048 \ + ecdsap256sha256:EC:prime256v1 ecdsap384sha384:EC:prime384v1; do # Edwards curves are not yet supported by OpenSC + # ed25519:EC:edwards25519 ed448:EC:edwards448 + alg=$(echo "$algtypebits" | cut -f 1 -d :) + type=$(echo "$algtypebits" | cut -f 2 -d :) + bits=$(echo "$algtypebits" | cut -f 3 -d :) + alg_upper=$(echo "$alg" | tr '[:lower:]' '[:upper:]') + supported=$(eval "echo \$${alg_upper}_SUPPORTED") + + tld="example" + if [ "${supported}" = 1 ]; then + zone="$alg.$tld" + zonefile="zone.$alg.$tld.db" + ret=0 + + echo_i "Generate keys $alg $type:$bits for zone $zone" + keygen $type $bits $zone enginepkcs11-zsk || ret=1 + keygen $type $bits $zone enginepkcs11-ksk || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Get ZSK $alg $zone $type:$bits" + zsk1=$(keyfromlabel $alg $zone enginepkcs11-zsk $dir) + test -z "$zsk1" && exit 1 + + echo_i "Get KSK $alg $zone $type:$bits" + ksk1=$(keyfromlabel $alg $zone enginepkcs11-ksk $dir -f KSK) + test -z "$ksk1" && exit 1 + + ( + cd $dir + zskid1=$(keyfile_to_key_id $zsk1) + kskid1=$(keyfile_to_key_id $ksk1) + echo "$zskid1" >$zone.zskid1 + echo "$kskid1" >$zone.kskid1 + ) + + echo_i "Sign zone with $ksk1 $zsk1" + cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile}" + $SIGNER $ENGINE_ARG -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile}" >signer.out.$zone || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Generate successor keys $alg $type:$bits for zone $zone" + keygen $type $bits $zone enginepkcs11-zsk2 || ret=1 + keygen $type $bits $zone enginepkcs11-ksk2 || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Get ZSK $alg $id-$zone $type:$bits" + zsk2=$(keyfromlabel $alg $zone enginepkcs11-zsk2 $dir) + test -z "$zsk2" && exit 1 + + echo_i "Get KSK $alg $id-$zone $type:$bits" + ksk2=$(keyfromlabel $alg $zone enginepkcs11-ksk2 $dir -f KSK) + test -z "$ksk2" && exit 1 + + ( + cd $dir + zskid2=$(keyfile_to_key_id $zsk2) + kskid2=$(keyfile_to_key_id $ksk2) + echo "$zskid2" >$zone.zskid2 + echo "$kskid2" >$zone.kskid2 + cp "${zsk2}.key" "${zsk2}.zsk2" + cp "${ksk2}.key" "${ksk2}.ksk2" + ) + + echo_i "Add zone $alg.kasp to named.conf" + cp $infile ${dir}/zone.${alg}.kasp.db + + echo_i "Add zone $alg.split to named.conf" + cp $infile ${dir}/zone.${alg}.split.db + + echo_i "Add weird zone to named.conf" + cp $infile ${dir}/zone.${alg}.weird.db + + echo_i "Add zone $zone to named.conf" + cat >>"${dir}/named.conf" <ns2/named.args + +mkdir ns2/keys + +dir="ns2" +infile="${dir}/template.db.in" +algtypebits="ecdsap256sha256:EC:prime256v1" +alg=$(echo "$algtypebits" | cut -f 1 -d :) +type=$(echo "$algtypebits" | cut -f 2 -d :) +bits=$(echo "$algtypebits" | cut -f 3 -d :) +alg_upper=$(echo "$alg" | tr '[:lower:]' '[:upper:]') +supported=$(eval "echo \$${alg_upper}_SUPPORTED") +tld="views" + +if [ "${supported}" = 1 ]; then + zone="$alg.$tld" + zonefile1="zone.$alg.$tld.view1.db" + zonefile2="zone.$alg.$tld.view2.db" + ret=0 + + echo_i "Generate keys $alg $type:$bits for zone $zone" + keygen $type $bits $zone enginepkcs11-zsk || ret=1 + keygen $type $bits $zone enginepkcs11-ksk || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Get ZSK $alg $zone $type:$bits" + zsk1=$(keyfromlabel $alg $zone enginepkcs11-zsk $dir) + test -z "$zsk1" && exit 1 + + echo_i "Get KSK $alg $zone $type:$bits" + ksk1=$(keyfromlabel $alg $zone enginepkcs11-ksk $dir -f KSK) + test -z "$ksk1" && exit 1 + + ( + cd $dir + zskid1=$(keyfile_to_key_id $zsk1) + kskid1=$(keyfile_to_key_id $ksk1) + echo "$zskid1" >$zone.zskid1 + echo "$kskid1" >$zone.kskid1 + ) + + echo_i "Sign zone with $ksk1 $zsk1" + cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile1}" + $SIGNER $ENGINE_ARG -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile1}" >signer.out.view1.$zone || ret=1 + test "$ret" -eq 0 || exit 1 + + cat "$infile" "${dir}/${ksk1}.key" "${dir}/${zsk1}.key" >"${dir}/${zonefile2}" + $SIGNER $ENGINE_ARG -K $dir -S -a -g -O full -o "$zone" "${dir}/${zonefile2}" >signer.out.view2.$zone || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Generate successor keys $alg $type:$bits for zone $zone" + keygen $type $bits $zone enginepkcs11-zsk2 || ret=1 + keygen $type $bits $zone enginepkcs11-ksk2 || ret=1 + test "$ret" -eq 0 || exit 1 + + echo_i "Get ZSK $alg $id-$zone $type:$bits" + zsk2=$(keyfromlabel $alg $zone enginepkcs11-zsk2 $dir) + test -z "$zsk2" && exit 1 + + echo_i "Get KSK $alg $id-$zone $type:$bits" + ksk2=$(keyfromlabel $alg $zone enginepkcs11-ksk2 $dir -f KSK) + test -z "$ksk2" && exit 1 + + ( + cd $dir + zskid2=$(keyfile_to_key_id $zsk2) + kskid2=$(keyfile_to_key_id $ksk2) + echo "$zskid2" >$zone.zskid2 + echo "$kskid2" >$zone.kskid2 + cp "${zsk2}.key" "${zsk2}.zsk2" + cp "${ksk2}.key" "${ksk2}.ksk2" + ) + + echo_i "Add zone $alg.same-policy.$tld to named.conf" + cp $infile ${dir}/zone.${alg}.same-policy.view1.db + cp $infile ${dir}/zone.${alg}.same-policy.view2.db + + echo_i "Add zone zone-with.different-policy.$tld to named.conf" + cp $infile ${dir}/zone.zone-with.different-policy.view1.db + cp $infile ${dir}/zone.zone-with.different-policy.view2.db + + echo_i "Add zone $zone to named.conf" + cat >>"${dir}/named.conf" <verify.out.$zone.$n 2>&1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (dnssec-verify failed)" + status=$((status + ret)) + + # Test inline signing with keys stored in engine. + zskid1=$(cat "${zone}.zskid1") + zskid2=$(cat "${zone}.zskid2") + + n=$((n + 1)) + ret=0 + echo_i "Test inline signing for $zone ($n)" + dig_with_opts "$zone" @10.53.0.1 SOA >dig.out.soa.$zone.$n || ret=1 + awk '$4 == "RRSIG" { print $11 }' dig.out.soa.$zone.$n >dig.out.keyids.$zone.$n || ret=1 + numsigs=$(cat dig.out.keyids.$zone.$n | wc -l) + test $numsigs -eq 1 || ret=1 + grep -w "$zskid1" dig.out.keyids.$zone.$n >/dev/null || ret=1 + test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed with key $zskid1)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Dynamically update $zone, add new zsk ($n)" + zsk2=$(grep -v ';' K${zone}.*.zsk2) + cat >"update.cmd.zsk.$zone.$n" <"update.log.zsk.$zone.$n" <"update.cmd.zsk.$zone.$n" || ret=1 + test "$ret" -eq 0 || echo_i "failed (update failed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY response for $zone after inline signing ($n)" + _dig_dnskey() { + dig_with_opts "$zone" @10.53.0.1 DNSKEY >dig.out.dnskey.$zone.$n || return 1 + count=$(awk 'BEGIN { count = 0 } $4 == "DNSKEY" { count++ } END {print count}' dig.out.dnskey.$zone.$n) + test $count -eq 3 + } + retry_quiet 10 _dig_dnskey || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 3 DNSKEY records)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA response for $zone after inline signing ($n)" + _dig_soa() { + dig_with_opts "$zone" @10.53.0.1 SOA >dig.out.soa.$zone.$n || return 1 + awk '$4 == "RRSIG" { print $11 }' dig.out.soa.$zone.$n >dig.out.keyids.$zone.$n || return 1 + numsigs=$(cat dig.out.keyids.$zone.$n | wc -l) + test $numsigs -eq 2 || return 1 + grep -w "$zskid1" dig.out.keyids.$zone.$n >/dev/null || return 1 + grep -w "$zskid2" dig.out.keyids.$zone.$n >/dev/null || return 1 + return 0 + } + retry_quiet 10 _dig_soa || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 2 SOA RRSIG records)" + status=$((status + ret)) + + # Test inline signing with keys stored in engine (key signing). + kskid1=$(cat "${zone}.kskid1") + kskid2=$(cat "${zone}.kskid2") + + n=$((n + 1)) + ret=0 + echo_i "Dynamically update $zone, add new ksk ($n)" + ksk2=$(grep -v ';' K${zone}.*.ksk2) + cat >"update.cmd.ksk.$zone.$n" <"update.log.ksk.$zone.$n" <"update.cmd.ksk.$zone.$n" || ret=1 + test "$ret" -eq 0 || echo_i "failed (update failed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY response for $zone after inline signing (key signing) ($n)" + _dig_dnskey_ksk() { + dig_with_opts "$zone" @10.53.0.1 DNSKEY >dig.out.dnskey.$zone.$n || return 1 + count=$(awk 'BEGIN { count = 0 } $4 == "DNSKEY" { count++ } END {print count}' dig.out.dnskey.$zone.$n) + test $count -eq 4 || return 1 + awk '$4 == "RRSIG" { print $11 }' dig.out.dnskey.$zone.$n >dig.out.keyids.$zone.$n || return 1 + numsigs=$(cat dig.out.keyids.$zone.$n | wc -l) + test $numsigs -eq 2 || return 1 + grep -w "$kskid1" dig.out.keyids.$zone.$n >/dev/null || return 1 + grep -w "$kskid2" dig.out.keyids.$zone.$n >/dev/null || return 1 + return 0 + } + retry_quiet 10 _dig_dnskey_ksk || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 4 DNSKEY records, 2 KSK signatures)" + status=$((status + ret)) + + # Check dnssec-policy interaction. + + # Basic checks if setup was successful (dnssec-policy). + zone="${alg}.kasp" + n=$((n + 1)) + ret=0 + ret=0 + echo_i "Test key generation was successful for $zone ($n)" + check_keys $zone 2 || ret=1 + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY response for $zone ($n)" + _dig_policy_dnskey() { + dig_with_opts "$zone" @10.53.0.1 DNSKEY >dig.out.dnskey.$zone.$n || return 1 + count=$(awk 'BEGIN { count = 0 } $4 == "DNSKEY" { count++ } END {print count}' dig.out.dnskey.$zone.$n) + test $count -eq 2 + } + retry_quiet 2 _dig_policy_dnskey || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 2 DNSKEY records)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA response for $zone ($n)" + _dig_policy_soa() { + dig_with_opts "$zone" @10.53.0.1 SOA >dig.out.soa.$zone.$n || return 1 + awk '$4 == "RRSIG" && $5 == "SOA" { print $11 }' dig.out.soa.$zone.$n >dig.out.keyids.$zone.$n || return 1 + numsigs=$(cat dig.out.keyids.$zone.$n | wc -l) + test $numsigs -eq 1 || return 1 + return 0 + } + retry_quiet 2 _dig_policy_soa || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected a SOA RRSIG record)" + + zone="$alg.\"\:\;\?\&\[\]\@\!\$\*\+\,\|\=\.\(\)foo.weird" + keyfile="${alg}.%22%3A%3B%3F%26%5B%5D%40%21%24%2A%2B%2C%7C%3D%2E%28%29foo.weird" + n=$((n + 1)) + ret=0 + echo_i "Test key generation was successful for $zone ($n)" + check_keys $keyfile 2 || ret=1 + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY response for $zone ($n)" + retry_quiet 2 _dig_policy_dnskey || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 2 DNSKEY records)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA response for $zone ($n)" + retry_quiet 2 _dig_policy_soa || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected a SOA RRSIG record)" + status=$((status + ret)) + + # Check a dnssec-policy that uses multiple key-stores. + zone="${alg}.split" + echo_i "Test key generation was successful for $zone ($n)" + # Check KSK. + check_keys $zone 1 || ret=1 + # Check ZSK. + count=$(ls keys/K*.key | grep "K${_zone}" | wc -l) + test "$count" -eq 1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 1 key, got $count)" + status=$((status + ret)) + ret=0 + count=$(cat keys/K${zone}*.private | grep Engine | wc -l) + test "$count" -eq 0 || ret=1 + count=$(cat keys/K${zone}*.private | grep Label | wc -l) + test "$count" -eq 0 || ret=1 + test "$ret" -eq 0 || echo_i "failed (unexpected Engine and Label in key files)" + status=$((status + ret)) + + # Check dnssec-keygen with dnssec-policy and key-store. + zone="${alg}.keygen" + n=$((n + 1)) + ret=0 + echo_i "Test dnssec-keygen for $zone ($n)" + $KEYGEN $ENGINE_ARG -k $alg -l named.conf $zone >keygen.out.$zone.$n 2>/dev/null || ret=1 + check_keys $zone 2 || ret=1 + status=$((status + ret)) + +done + +# Go back to main test dir. +cd .. + +# Perform tests inside ns2 dir +cd ns2 + +algtypebits="ecdsap256sha256:EC:prime256v1" +alg=$(echo "$algtypebits" | cut -f 1 -d :) +type=$(echo "$algtypebits" | cut -f 2 -d :) +bits=$(echo "$algtypebits" | cut -f 3 -d :) +zone="${alg}.views" +zonefile1="zone.$alg.views.view1.db.signed" +zonefile2="zone.$alg.views.view2.db.signed" + +skip=0 +if [ ! -f $zonefile1 ]; then + echo_i "skipping test for ${alg}:${type}:${bits}, no signed zone file ${zonefile1}" + skip=1 +fi + +if [ ! -f $zonefile2 ]; then + echo_i "skipping test for ${alg}:${type}:${bits}, no signed zone file ${zonefile2}" + skip=1 +fi + +if [ $skip -eq 0 ]; then + # Basic checks if setup was successful. + n=$((n + 1)) + ret=0 + echo_i "Test key generation was successful for $zone ($n)" + check_keys $zone 4 || ret=1 + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test zone signing was successful for $zone in view1 ($n)" + $VERIFY -z -o $zone "${zonefile1}" >verify.out.$zone.view1.$n 2>&1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (dnssec-verify failed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test zone signing was successful for $zone in view2 ($n)" + $VERIFY -z -o $zone "${zonefile2}" >verify.out.$zone.view2.$n 2>&1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (dnssec-verify failed)" + status=$((status + ret)) + + # Test dnssec-policy signing with keys stored in engine. + zone="${alg}.same-policy.views" + + n=$((n + 1)) + ret=0 + echo_i "Test key generation was successful for $zone ($n)" + check_keys $zone 1 || ret=1 + status=$((status + ret)) + + _dig_inview() { + _qtype="$1" + _alg="$2" + _tsig="$DEFAULT_HMAC:$3:$4" + dig_with_opts "$zone" @10.53.0.2 $_qtype -y "$_tsig" >dig.out.$zone.$n || return 1 + awk -v cov="$_qtype" '$4 == "RRSIG" && $5 == cov { print $6 }' dig.out.$zone.$n >dig.out.alg.$zone.$n || return 1 + numsigs=$(cat dig.out.alg.$zone.$n | wc -l) + test $numsigs -eq 1 || return 1 + grep -w "$_alg" dig.out.alg.$zone.$n >/dev/null || return 1 + } + + n=$((n + 1)) + ret=0 + echo_i "Test SOA is signed for $zone in view1 ($n)" + VIEW1="YPfMoAk6h+3iN8MDRQC004iSNHY=" + retry_quiet 4 _dig_inview SOA 13 keyforview1 $VIEW1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY is signed for $zone in view1 ($n)" + retry_quiet 4 _dig_inview DNSKEY 13 keyforview1 $VIEW1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (DNSKEY RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA is signed for $zone in view2 ($n)" + VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8=" + retry_quiet 4 _dig_inview SOA 13 keyforview2 $VIEW2 || ret=1 + test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY is signed for $zone in view2 ($n)" + retry_quiet 4 _dig_inview DNSKEY 13 keyforview2 $VIEW2 || ret=1 + test "$ret" -eq 0 || echo_i "failed (DNSKEY RRset not signed)" + status=$((status + ret)) + + # Now test zone in different views using a different dnssec-policy. + zone="zone-with.different-policy.views" + + n=$((n + 1)) + ret=0 + echo_i "Test key generation was successful for $zone in view1 ($n)" + # view1 + check_keys $zone 1 || ret=1 + status=$((status + ret)) + # view2 + echo_i "Test key generation was successful for $zone in view2 ($n)" + count=$(ls keys/K*.key | grep "K${zone}" | wc -l) + test "$count" -eq 1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (expected 1 key, got $count)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA is signed for $zone in view1 ($n)" + VIEW1="YPfMoAk6h+3iN8MDRQC004iSNHY=" + retry_quiet 4 _dig_inview SOA 13 keyforview1 $VIEW1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY is signed for $zone in view1 ($n)" + retry_quiet 4 _dig_inview DNSKEY 13 keyforview1 $VIEW1 || ret=1 + test "$ret" -eq 0 || echo_i "failed (DNSKEY RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test SOA is signed for $zone in view2 ($n)" + VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8=" + retry_quiet 4 _dig_inview SOA 8 keyforview2 $VIEW2 || ret=1 + test "$ret" -eq 0 || echo_i "failed (SOA RRset not signed)" + status=$((status + ret)) + + n=$((n + 1)) + ret=0 + echo_i "Test DNSKEY is signed for $zone in view2 ($n)" + retry_quiet 4 _dig_inview DNSKEY 8 keyforview2 $VIEW2 || ret=1 + test "$ret" -eq 0 || echo_i "failed (DNSKEY RRset not signed)" + status=$((status + ret)) +fi + +# Go back to main test dir. +cd .. + +n=$((n + 1)) +ret=0 +echo_i "Checking for assertion failure in pk11_numbits()" +$PERL ../packet.pl -a "10.53.0.1" -p "$PORT" -t udp 2037-pk11_numbits-crash-test.pkt +dig_with_opts @10.53.0.1 version.bind. CH TXT >dig.out.pk11_numbits || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py new file mode 100644 index 0000000..5a5fef6 --- /dev/null +++ b/bin/tests/system/enginepkcs11/tests_sh_enginepkcs11.py @@ -0,0 +1,58 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "dsset-*", + "keyfromlabel.err.*", + "keyfromlabel.out.*", + "pkcs11-tool.err.*", + "pkcs11-tool.out.*", + "signer.out.*", + "ns*/dig.out.*", + "ns*/K*", + "ns*/keygen.out.*", + "ns*/update.cmd.*", + "ns*/update.log.*", + "ns*/verify.out.*", + "ns*/pin", + "ns*/zone.*.jbk", + "ns*/zone.*.jnl", + "ns*/*.kskid1", + "ns*/*.kskid2", + "ns*/*.zskid1", + "ns*/*.zskid2", + "ns1/keys", + "ns1/named.args", + "ns1/*.example.db", + "ns1/*.example.db.signed", + "ns1/*.kasp.db", + "ns1/*.kasp.db.signed", + "ns1/*.split.db", + "ns1/*.split.db.signed", + "ns1/*.weird.db", + "ns1/*.weird.db.signed", + "ns2/keys", + "ns2/named.args", + "ns2/*.view*.db", + "ns2/*.view*.db.signed", + ] +) + + +@isctest.mark.flaky(max_runs=3) # GL#4605 +def test_enginepkcs11(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c new file mode 100644 index 0000000..514542e --- /dev/null +++ b/bin/tests/system/feature-test.c @@ -0,0 +1,294 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include + +#include +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include + +static void +usage(void) { + fprintf(stderr, "usage: feature-test \n"); + fprintf(stderr, "args:\n"); + fprintf(stderr, "\t--edns-version\n"); + fprintf(stderr, "\t--enable-dnsrps\n"); + fprintf(stderr, "\t--enable-dnstap\n"); + fprintf(stderr, "\t--enable-querytrace\n"); + fprintf(stderr, "\t--fips-provider\n"); + fprintf(stderr, "\t--gethostname\n"); + fprintf(stderr, "\t--gssapi\n"); + fprintf(stderr, "\t--have-fips-dh\n"); + fprintf(stderr, "\t--have-fips-mode\n"); + fprintf(stderr, "\t--have-geoip2\n"); + fprintf(stderr, "\t--have-json-c\n"); + fprintf(stderr, "\t--have-libxml2\n"); + fprintf(stderr, "\t--have-openssl-cipher-suites\n"); + fprintf(stderr, "\t--ipv6only=no\n"); + fprintf(stderr, "\t--md5\n"); + fprintf(stderr, "\t--rsasha1\n"); + fprintf(stderr, "\t--tsan\n"); + fprintf(stderr, "\t--with-dlz-filesystem\n"); + fprintf(stderr, "\t--with-libidn2\n"); + fprintf(stderr, "\t--with-lmdb\n"); + fprintf(stderr, "\t--with-libnghttp2\n"); + fprintf(stderr, "\t--with-zlib\n"); +} + +int +main(int argc, char **argv) { + if (argc != 2) { + usage(); + return 1; + } + + if (strcmp(argv[1], "--edns-version") == 0) { +#ifdef DNS_EDNS_VERSION + printf("%d\n", DNS_EDNS_VERSION); +#else /* ifdef DNS_EDNS_VERSION */ + printf("0\n"); +#endif /* ifdef DNS_EDNS_VERSION */ + return 0; + } + + if (strcmp(argv[1], "--enable-dnsrps") == 0) { +#ifdef USE_DNSRPS + return 0; +#else /* ifdef USE_DNSRPS */ + return 1; +#endif /* ifdef USE_DNSRPS */ + } + + if (strcmp(argv[1], "--enable-dnstap") == 0) { +#ifdef HAVE_DNSTAP + return 0; +#else /* ifdef HAVE_DNSTAP */ + return 1; +#endif /* ifdef HAVE_DNSTAP */ + } + + if (strcmp(argv[1], "--enable-querytrace") == 0) { +#ifdef WANT_QUERYTRACE + return 0; +#else /* ifdef WANT_QUERYTRACE */ + return 1; +#endif /* ifdef WANT_QUERYTRACE */ + } + + if (strcasecmp(argv[1], "--fips-provider") == 0) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + OSSL_PROVIDER *fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips != NULL) { + OSSL_PROVIDER_unload(fips); + } + return fips != NULL ? 0 : 1; +#else + return 1; +#endif + } + + if (strcmp(argv[1], "--gethostname") == 0) { + char hostname[_POSIX_HOST_NAME_MAX + 1]; + int n; + + n = gethostname(hostname, sizeof(hostname)); + if (n == -1) { + perror("gethostname"); + return 1; + } + fprintf(stdout, "%s\n", hostname); + return 0; + } + + if (strcmp(argv[1], "--gssapi") == 0) { +#if HAVE_GSSAPI + return 0; +#else /* HAVE_GSSAPI */ + return 1; +#endif /* HAVE_GSSAPI */ + } + + if (strcmp(argv[1], "--have-fips-dh") == 0) { +#if defined(ENABLE_FIPS_MODE) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + return 0; +#else + return 1; +#endif +#else + if (isc_fips_mode()) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 + return 0; +#else + return 1; +#endif + } + return 0; +#endif + } + + if (strcmp(argv[1], "--have-fips-mode") == 0) { +#if defined(ENABLE_FIPS_MODE) + return 0; +#else + return isc_fips_mode() ? 0 : 1; +#endif + } + + if (strcmp(argv[1], "--have-geoip2") == 0) { +#ifdef HAVE_GEOIP2 + return 0; +#else /* ifdef HAVE_GEOIP2 */ + return 1; +#endif /* ifdef HAVE_GEOIP2 */ + } + + if (strcmp(argv[1], "--have-json-c") == 0) { +#ifdef HAVE_JSON_C + return 0; +#else /* ifdef HAVE_JSON_C */ + return 1; +#endif /* ifdef HAVE_JSON_C */ + } + + if (strcmp(argv[1], "--have-libxml2") == 0) { +#ifdef HAVE_LIBXML2 + return 0; +#else /* ifdef HAVE_LIBXML2 */ + return 1; +#endif /* ifdef HAVE_LIBXML2 */ + } + + if (strcmp(argv[1], "--have-openssl-cipher-suites") == 0) { +#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES + return 0; +#else /* ifdef HAVE_SSL_CTX_SET_CIPHERSUITES */ + return 1; +#endif /* ifdef HAVE_SSL_CTX_SET_CIPHERSUITES */ + } + + if (strcmp(argv[1], "--tsan") == 0) { +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) + return 0; +#endif +#endif +#if __SANITIZE_THREAD__ + return 0; +#else + return 1; +#endif + } + + if (strcmp(argv[1], "--md5") == 0) { + isc_mem_t *mctx = NULL; + int answer; + + isc_mem_create(&mctx); + dst_lib_init(mctx, NULL); + answer = dst_algorithm_supported(DST_ALG_HMACMD5) ? 0 : 1; + dst_lib_destroy(); + isc_mem_detach(&mctx); + return answer; + } + + if (strcmp(argv[1], "--ipv6only=no") == 0) { +#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) + int s; + int n = -1; + int v6only = -1; + socklen_t len = sizeof(v6only); + + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s >= 0) { + n = getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&v6only, &len); + close(s); + } + return (n == 0 && v6only == 0) ? 0 : 1; +#else /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */ + return 1; +#endif /* defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) */ + } + + if (strcasecmp(argv[1], "--rsasha1") == 0) { + int answer; + isc_mem_t *mctx = NULL; + isc_mem_create(&mctx); + dst_lib_init(mctx, NULL); + answer = dst_algorithm_supported(DST_ALG_RSASHA1) ? 0 : 1; + dst_lib_destroy(); + isc_mem_detach(&mctx); + return answer; + } + + if (strcmp(argv[1], "--with-dlz-filesystem") == 0) { +#ifdef DLZ_FILESYSTEM + return 0; +#else /* ifdef DLZ_FILESYSTEM */ + return 1; +#endif /* ifdef DLZ_FILESYSTEM */ + } + + if (strcmp(argv[1], "--with-libidn2") == 0) { +#ifdef HAVE_LIBIDN2 + return 0; +#else /* ifdef HAVE_LIBIDN2 */ + return 1; +#endif /* ifdef HAVE_LIBIDN2 */ + } + + if (strcmp(argv[1], "--with-lmdb") == 0) { +#ifdef HAVE_LMDB + return 0; +#else /* ifdef HAVE_LMDB */ + return 1; +#endif /* ifdef HAVE_LMDB */ + } + + if (strcmp(argv[1], "--with-libnghttp2") == 0) { +#ifdef HAVE_LIBNGHTTP2 + return 0; +#else /* ifdef HAVE_LIBNGHTTP2 */ + return 1; +#endif /* ifdef HAVE_LIBNGHTTP2 */ + } + + if (strcmp(argv[1], "--with-zlib") == 0) { +#ifdef HAVE_ZLIB + return 0; +#else /* ifdef HAVE_ZLIB */ + return 1; +#endif /* ifdef HAVE_ZLIB */ + } + + fprintf(stderr, "unknown arg: %s\n", argv[1]); + usage(); + return 1; +} diff --git a/bin/tests/system/fetchlimit/ans4/ans.pl b/bin/tests/system/fetchlimit/ans4/ans.pl new file mode 100644 index 0000000..f44cf8b --- /dev/null +++ b/bin/tests/system/fetchlimit/ans4/ans.pl @@ -0,0 +1,90 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Don't respond if the "norespond" file exists; otherwise respond to +# any A or AAAA query. +# + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.4", + LocalPort => $localport, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + my $donotrespond = 0; + + if (-e 'norespond') { + $donotrespond = 1; + } else { + $packet->header->aa(1); + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 A 192.0.2.1")); + } elsif ($qtype eq "AAAA") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 AAAA 2001:db8:beef::1")); + } + } + + if ($donotrespond == 0) { + if (index($qname, "latency") == 0) { + # 50ms latency + select(undef, undef, undef, 0.05); + } + $sock->send($packet->data); + print "RESPONSE:\n"; + $packet->print; + print "\n"; + } +} diff --git a/bin/tests/system/fetchlimit/ns1/named.conf.in b/bin/tests/system/fetchlimit/ns1/named.conf.in new file mode 100644 index 0000000..9725d01 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns1/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example.info." { + type primary; + file "example-info.db"; +}; diff --git a/bin/tests/system/fetchlimit/ns1/root.db b/bin/tests/system/fetchlimit/ns1/root.db new file mode 100644 index 0000000..17780d1 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/fetchlimit/ns2/example.db b/bin/tests/system/fetchlimit/ns2/example.db new file mode 100644 index 0000000..5bf9999 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns2/example.db @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example NS ns2.example. +ns2.example. A 10.53.0.2 + +a.example. A 10.0.0.1 + MX 10 mail.example. + +mail.example. A 10.0.0.2 + +lamesub.example. NS ns4.example. +ns4.example. A 10.53.0.4 + +0.example. A 10.53.1.0 +1.example. A 10.53.1.1 +2.example. A 10.53.1.2 +3.example. A 10.53.1.3 +4.example. A 10.53.1.4 +5.example. A 10.53.1.5 diff --git a/bin/tests/system/fetchlimit/ns2/named.conf.in b/bin/tests/system/fetchlimit/ns2/named.conf.in new file mode 100644 index 0000000..1d57632 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns2/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "example" { + type primary; + file "example.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/fetchlimit/ns3/named.args b/bin/tests/system/fetchlimit/ns3/named.args new file mode 100644 index 0000000..d4fcf15 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns3/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 1 -D fetchlimit-ns3 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/fetchlimit/ns3/named1.conf.in b/bin/tests/system/fetchlimit/ns3/named1.conf.in new file mode 100644 index 0000000..da1661d --- /dev/null +++ b/bin/tests/system/fetchlimit/ns3/named1.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + fetches-per-server 400; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns3/named2.conf.in b/bin/tests/system/fetchlimit/ns3/named2.conf.in new file mode 100644 index 0000000..d354dfd --- /dev/null +++ b/bin/tests/system/fetchlimit/ns3/named2.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + fetches-per-zone 40; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns3/named3.conf.in b/bin/tests/system/fetchlimit/ns3/named3.conf.in new file mode 100644 index 0000000..db32409 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns3/named3.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + recursive-clients 400; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns3/root.hint b/bin/tests/system/fetchlimit/ns3/root.hint new file mode 100644 index 0000000..e0f186c --- /dev/null +++ b/bin/tests/system/fetchlimit/ns3/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/fetchlimit/ns5/named1.conf.in b/bin/tests/system/fetchlimit/ns5/named1.conf.in new file mode 100644 index 0000000..f26b8a1 --- /dev/null +++ b/bin/tests/system/fetchlimit/ns5/named1.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + clients-per-query 5; + max-clients-per-query 10; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns5/named2.conf.in b/bin/tests/system/fetchlimit/ns5/named2.conf.in new file mode 100644 index 0000000..32b281d --- /dev/null +++ b/bin/tests/system/fetchlimit/ns5/named2.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-client-timeout 0; + clients-per-query 5; + max-clients-per-query 10; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns5/named3.conf.in b/bin/tests/system/fetchlimit/ns5/named3.conf.in new file mode 100644 index 0000000..7fb1baf --- /dev/null +++ b/bin/tests/system/fetchlimit/ns5/named3.conf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-client-timeout 0; + /* max-clients-per-query < clients-per-query */ + clients-per-query 10; + max-clients-per-query 5; +}; + +trust-anchors { }; + +server 10.53.0.4 { + edns no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/fetchlimit/ns5/root.hint b/bin/tests/system/fetchlimit/ns5/root.hint new file mode 100644 index 0000000..e0f186c --- /dev/null +++ b/bin/tests/system/fetchlimit/ns5/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/fetchlimit/prereq.sh b/bin/tests/system/fetchlimit/prereq.sh new file mode 100644 index 0000000..c52be9c --- /dev/null +++ b/bin/tests/system/fetchlimit/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/fetchlimit/setup.sh b/bin/tests/system/fetchlimit/setup.sh new file mode 100644 index 0000000..f98749b --- /dev/null +++ b/bin/tests/system/fetchlimit/setup.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named1.conf.in ns3/named.conf +copy_setports ns5/named1.conf.in ns5/named.conf diff --git a/bin/tests/system/fetchlimit/tests.sh b/bin/tests/system/fetchlimit/tests.sh new file mode 100644 index 0000000..0909f57 --- /dev/null +++ b/bin/tests/system/fetchlimit/tests.sh @@ -0,0 +1,341 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGCMD="$DIG @10.53.0.3 -p ${PORT} +tcp +tries=1 +time=1" + +rndccmd() ( + "$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "$@" +) + +burst() { + server=${1} + num=${4:-20} + rm -f burst.input.$$ + while [ $num -gt 0 ]; do + num=$((num - 1)) + if [ "${5}" = "dup" ]; then + # burst with duplicate queries + echo "${2}${3}.lamesub.example A" >>burst.input.$$ + else + # burst with unique queries + echo "${num}${2}${3}.lamesub.example A" >>burst.input.$$ + fi + done + $PERL ../ditch.pl -p ${PORT} -s ${server} -b ${EXTRAPORT8} burst.input.$$ + rm -f burst.input.$$ +} + +stat() { + clients=$(rndccmd ${1} status | grep "recursive clients" \ + | sed 's;.*: \([^/][^/]*\)/.*;\1;') + echo_i "clients: $clients" + [ "$clients" = "" ] && return 1 + [ "$clients" -ge $2 ] || return 1 + [ "$clients" -le $3 ] || return 1 + return 0 +} + +_wait_for_message() ( + nextpartpeek "$1" >wait_for_message.$n + grep -F "$2" wait_for_message.$n >/dev/null +) + +wait_for_message() ( + retry_quiet 20 _wait_for_message "$@" +) + +n=0 +status=0 + +n=$((n + 1)) +echo_i "checking recursing clients are dropped at the per-server limit ($n)" +ret=0 +# make the server lame and restart +rndccmd 10.53.0.3 flush +touch ans4/norespond +for try in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + burst 10.53.0.3 a $try + # fetches-per-server is at 400, but at 20qps against a lame server, + # we'll reach 200 at the tenth second, and the quota should have been + # tuned to less than that by then. + [ $try -le 5 ] && low=$((try * 10)) + stat 10.53.0.3 20 200 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "dumping ADB data ($n)" +ret=0 +info=$(rndccmd 10.53.0.3 fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/') +echo_i $info +set -- $info +quota=$2 +[ ${quota:-200} -lt 200 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking servfail statistics ($n)" +ret=0 +rm -f ns3/named.stats +rndccmd 10.53.0.3 stats +for try in 1 2 3 4 5; do + [ -f ns3/named.stats ] && break + sleep 1 +done +sspill=$(grep 'spilled due to server' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/') +[ -z "$sspill" ] && sspill=0 +fails=$(grep 'queries resulted in SERVFAIL' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/') +[ -z "$fails" ] && fails=0 +[ "$fails" -ge "$sspill" ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking lame server recovery ($n)" +ret=0 +test -f ans4/norespond && rm -f ans4/norespond +for try in 1 2 3 4 5; do + burst 10.53.0.3 b $try + stat 10.53.0.3 0 200 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "dumping ADB data ($n)" +ret=0 +info=$(rndccmd 10.53.0.3 fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/') +echo_i $info +set -- $info +[ ${2:-${quota}} -lt $quota ] || ret=1 +quota=$2 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking lame server recovery (continued) ($n)" +ret=0 +for try in 1 2 3 4 5 6 7 8 9 10; do + burst 10.53.0.3 c $try + stat 10.53.0.3 0 20 || ret=1 + [ $ret -eq 1 ] && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "dumping ADB data ($n)" +ret=0 +info=$(rndccmd 10.53.0.3 fetchlimit | grep 10.53.0.4 | sed 's/.*quota .*(\([0-9]*\).*atr \([.0-9]*\).*/\2 \1/') +echo_i $info +set -- $info +[ ${2:-${quota}} -gt $quota ] || ret=1 +quota=$2 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +copy_setports ns3/named2.conf.in ns3/named.conf +rndc_reconfig ns3 10.53.0.3 + +n=$((n + 1)) +echo_i "checking lame server clients are dropped at the per-domain limit ($n)" +ret=0 +fail=0 +success=0 +touch ans4/norespond +for try in 1 2 3 4 5; do + burst 10.53.0.3 d $try 300 + $DIGCMD a ${try}.example >dig.out.ns3.$n.$try + grep "status: NOERROR" dig.out.ns3.$n.$try >/dev/null 2>&1 \ + && success=$((success + 1)) + grep "status: SERVFAIL" dig.out.ns3.$n.$try >/dev/null 2>&1 \ + && fail=$(($fail + 1)) + stat 10.53.0.3 40 40 || ret=1 + allowed=$(rndccmd 10.53.0.3 fetchlimit | awk '/lamesub/ { print $6 }') + [ "${allowed:-0}" -eq 40 ] || ret=1 + [ $ret -eq 1 ] && break + sleep 1 +done +echo_i "$success successful valid queries, $fail SERVFAIL" +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop statistics ($n)" +ret=0 +rm -f ns3/named.stats +rndccmd 10.53.0.3 stats +for try in 1 2 3 4 5; do + [ -f ns3/named.stats ] && break + sleep 1 +done +zspill=$(grep 'spilled due to zone' ns3/named.stats | sed 's/\([0-9][0-9]*\) spilled.*/\1/') +[ -z "$zspill" ] && zspill=0 +drops=$(grep 'queries dropped' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/') +[ -z "$drops" ] && drops=0 +[ "$drops" -ge "$zspill" ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +copy_setports ns3/named3.conf.in ns3/named.conf +rndc_reconfig ns3 10.53.0.3 + +n=$((n + 1)) +echo_i "checking lame server clients are dropped below the hard limit ($n)" +ret=0 +fail=0 +exceeded=0 +success=0 +touch ans4/norespond +for try in 1 2 3 4 5; do + burst 10.53.0.3 b $try 400 + $DIGCMD +time=2 a ${try}.example >dig.out.ns3.$n.$try + stat 10.53.0.3 1 400 || exceeded=$((exceeded + 1)) + grep "status: NOERROR" dig.out.ns3.$n.$try >/dev/null 2>&1 \ + && success=$((success + 1)) + grep "status: SERVFAIL" dig.out.ns3.$n.$try >/dev/null 2>&1 \ + && fail=$(($fail + 1)) + sleep 1 +done +echo_i "$success successful valid queries (expected 5)" +[ "$success" -eq 5 ] || { + echo_i "failed" + ret=1 +} +echo_i "$fail SERVFAIL responses (expected 0)" +[ "$fail" -eq 0 ] || { + echo_i "failed" + ret=1 +} +echo_i "clients count exceeded 400 on $exceeded trials (expected 0)" +[ "$exceeded" -eq 0 ] || { + echo_i "failed" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop statistics ($n)" +ret=0 +rm -f ns3/named.stats +touch ns3/named.stats +rndccmd 10.53.0.3 stats +wait_for_log 5 "queries dropped due to recursive client limit" ns3/named.stats || ret=1 +drops=$(grep 'queries dropped due to recursive client limit' ns3/named.stats | sed 's/\([0-9][0-9]*\) queries.*/\1/') +[ "${drops:-0}" -ne 0 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns5/named.run >/dev/null + +n=$((n + 1)) +echo_i "checking clients are dropped at the clients-per-query limit ($n)" +ret=0 +test -f ans4/norespond && rm -f ans4/norespond +for try in 1 2 3 4 5; do + burst 10.53.0.5 latency $try 20 "dup" + sleep 1 +done +wait_for_message ns5/named.run "clients-per-query increased to 10" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop statistics ($n)" +ret=0 +rm -f ns5/named.stats +rndccmd 10.53.0.5 stats +for try in 1 2 3 4 5; do + [ -f ns5/named.stats ] && break + sleep 1 +done +zspill=$(grep 'spilled due to clients per query' ns5/named.stats | sed 's/ *\([0-9][0-9]*\) spilled.*/\1/') +[ -z "$zspill" ] && zspill=0 +# ns5 configuration: +# clients-per-query 5 +# max-clients-per-query 10 +# expected spills: +# 15 (out of 20) spilled for the first burst, and 10 (out of 20) spilled for +# the next 4 bursts (because of auto-tuning): 15 + (4 * 10) == 55 +expected=55 +[ "$zspill" -eq "$expected" ] || ret=1 +echo_i "$zspill clients spilled (expected $expected)" +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "stop ns5" +stop_server --use-rndc --port ${CONTROLPORT} ns5 +copy_setports ns5/named2.conf.in ns5/named.conf +echo_i "start ns5" +start_server --noclean --restart --port ${PORT} ns5 + +nextpart ns5/named.run >/dev/null + +n=$((n + 1)) +echo_i "checking clients are dropped at the clients-per-query limit with stale-answer-client-timeout ($n)" +ret=0 +test -f ans4/norespond && rm -f ans4/norespond +for try in 1 2 3 4 5; do + burst 10.53.0.5 latency $try 20 "dup" + sleep 1 +done +wait_for_message ns5/named.run "clients-per-query increased to 10" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop statistics ($n)" +ret=0 +rm -f ns5/named.stats +rndccmd 10.53.0.5 stats +for try in 1 2 3 4 5; do + [ -f ns5/named.stats ] && break + sleep 1 +done +zspill=$(grep 'spilled due to clients per query' ns5/named.stats | sed 's/ *\([0-9][0-9]*\) spilled.*/\1/') +[ -z "$zspill" ] && zspill=0 +# ns5 configuration: +# clients-per-query 5 +# max-clients-per-query 10 +# expected spills: +# 15 (out of 20) spilled for the first burst, and 10 (out of 20) spilled for +# the next 4 bursts (because of auto-tuning): 15 + (4 * 10) == 55 +expected=55 +[ "$zspill" -eq "$expected" ] || ret=1 +echo_i "$zspill clients spilled (expected $expected)" +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking a warning is logged if max-clients-per-query < clients-per-query ($n)" +ret=0 +copy_setports ns5/named3.conf.in ns5/named.conf +rndc_reconfig ns5 10.53.0.5 +wait_for_message ns5/named.run "configured clients-per-query (10) exceeds max-clients-per-query (5); automatically adjusting max-clients-per-query to (10)" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py b/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py new file mode 100644 index 0000000..39dddf3 --- /dev/null +++ b/bin/tests/system/fetchlimit/tests_sh_fetchlimit.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "wait_for_message.*", + "ans*/ans.run", + "ns3/named.stats", + "ns3/named.stats.prev", + "ns5/named.stats", + ] +) + +import isctest.mark + + +@isctest.mark.flaky(max_runs=2) +def test_fetchlimit(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/filter-aaaa/conf/bad1.conf b/bin/tests/system/filter-aaaa/conf/bad1.conf new file mode 100644 index 0000000..e498c19 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/bad1.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { none; }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/bad2.conf b/bin/tests/system/filter-aaaa/conf/bad2.conf new file mode 100644 index 0000000..fcb972a --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/bad2.conf @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + /* + * While this matches the defaults, it is not a good configuration + * to have in named.conf as the two options contradict each other + * indicating a error on behalf of the operator. + * + * The default is to have filter-aaaa-on-v4 off, but if it is turned + * on then it applies to all IPv4 queries. This results in + * contradictory defaults. + */ + filter-aaaa-on-v4 no; + filter-aaaa { any; }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/bad3.conf b/bin/tests/system/filter-aaaa/conf/bad3.conf new file mode 100644 index 0000000..5f77361 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/bad3.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view myview { + plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 no; + filter-aaaa { any; }; + }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/bad4.conf b/bin/tests/system/filter-aaaa/conf/bad4.conf new file mode 100644 index 0000000..4a37e64 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/bad4.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view myview { + plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { none; }; + }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/bad5.conf b/bin/tests/system/filter-aaaa/conf/bad5.conf new file mode 100644 index 0000000..eee2336 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/bad5.conf @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { 1.0.0.0/8; }; +}; + +view myview { + match-clients { any; }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/good1.conf b/bin/tests/system/filter-aaaa/conf/good1.conf new file mode 100644 index 0000000..c330d86 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/good1.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; +}; diff --git a/bin/tests/system/filter-aaaa/conf/good2.conf b/bin/tests/system/filter-aaaa/conf/good2.conf new file mode 100644 index 0000000..aa3c9a5 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/good2.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 break-dnssec; +}; diff --git a/bin/tests/system/filter-aaaa/conf/good3.conf b/bin/tests/system/filter-aaaa/conf/good3.conf new file mode 100644 index 0000000..26e50f5 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/good3.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 break-dnssec; + filter-aaaa { 1.0.0.0/8; }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/good4.conf b/bin/tests/system/filter-aaaa/conf/good4.conf new file mode 100644 index 0000000..b646c8d --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/good4.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { 1.0.0.0/8; }; +}; diff --git a/bin/tests/system/filter-aaaa/conf/good5.conf b/bin/tests/system/filter-aaaa/conf/good5.conf new file mode 100644 index 0000000..260fdf1 --- /dev/null +++ b/bin/tests/system/filter-aaaa/conf/good5.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +view myview { + plugin query "../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { 1.0.0.0/8; }; + }; +}; diff --git a/bin/tests/system/filter-aaaa/ns1/named1.conf.in b/bin/tests/system/filter-aaaa/ns1/named1.conf.in new file mode 100644 index 0000000..c4e6eac --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/named1.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +trust-anchors { }; + +acl filterees { 10.53.0.1; }; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { filterees; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { type primary; file "root.db"; }; +zone "signed" { type primary; file "signed.db.signed"; }; +zone "unsigned" { type primary; file "unsigned.db"; }; diff --git a/bin/tests/system/filter-aaaa/ns1/named2.conf.in b/bin/tests/system/filter-aaaa/ns1/named2.conf.in new file mode 100644 index 0000000..d82ed2d --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/named2.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +trust-anchors { }; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v6 yes; + filter-aaaa { fd92:7065:b8e:ffff::1; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type primary; file "root.db"; }; +zone "signed" { type primary; file "signed.db.signed"; }; +zone "unsigned" { type primary; file "unsigned.db"; }; diff --git a/bin/tests/system/filter-aaaa/ns1/root.db b/bin/tests/system/filter-aaaa/ns1/root.db new file mode 100644 index 0000000..150aa72 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/root.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 ) +@ NS ns.utld +ns.utld A 10.53.0.1 +ns.utld AAAA fd92:7065:b8e:ffff::1 +; + +signed NS ns.signed +ns.signed A 10.53.0.1 +ns.signed AAAA fd92:7065:b8e:ffff::1 + +unsigned NS ns.unsigned +ns.unsigned A 10.53.0.1 +ns.unsigned AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/filter-aaaa/ns1/sign.sh b/bin/tests/system/filter-aaaa/ns1/sign.sh new file mode 100755 index 0000000..c29dcfa --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/sign.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +SYSTESTDIR=filter-aaaa + +zone=signed. +infile=signed.db.in +zonefile=signed.db.signed +outfile=signed.db.signed + +$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 >/dev/null | cat_i +$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 >keygen.out | cat_i +keyname=$(cat keygen.out) +rm -f keygen.out + +keyfile_to_static_ds $keyname >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns5/trusted.conf + +$SIGNER -S -o $zone -f $outfile $infile >/dev/null 2>signer.err || cat signer.err +echo_i "signed zone '$zone'" diff --git a/bin/tests/system/filter-aaaa/ns1/signed.db.in b/bin/tests/system/filter-aaaa/ns1/signed.db.in new file mode 100644 index 0000000..36a0373 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/signed.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + +a-only NS 1.0.0.1 +aaaa-only AAAA 2001:db8::2 +dual A 1.0.0.3 +dual AAAA 2001:db8::3 +mx A 1.0.0.3 +mx AAAA 2001:db8::3 diff --git a/bin/tests/system/filter-aaaa/ns1/unsigned.db b/bin/tests/system/filter-aaaa/ns1/unsigned.db new file mode 100644 index 0000000..abc3947 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns1/unsigned.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + +a-only NS 1.0.0.4 +aaaa-only AAAA 2001:db8::5 +dual A 1.0.0.6 +dual AAAA 2001:db8::6 +mx A 1.0.0.3 +mx AAAA 2001:db8::3 diff --git a/bin/tests/system/filter-aaaa/ns2/hints b/bin/tests/system/filter-aaaa/ns2/hints new file mode 100644 index 0000000..fa0d3e4 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns2/hints @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 + +. NS ns.utld. +ns.utld. A 10.53.0.1 +ns.utld. AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/filter-aaaa/ns2/named1.conf.in b/bin/tests/system/filter-aaaa/ns2/named1.conf.in new file mode 100644 index 0000000..2a1486d --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns2/named1.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion yes; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 yes; + filter-aaaa { 10.53.0.2; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints"; }; + +include "trusted.conf"; diff --git a/bin/tests/system/filter-aaaa/ns2/named2.conf.in b/bin/tests/system/filter-aaaa/ns2/named2.conf.in new file mode 100644 index 0000000..4e5a1ef --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns2/named2.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion yes; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v6 yes; + filter-aaaa { fd92:7065:b8e:ffff::2; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints"; }; + +include "trusted.conf"; diff --git a/bin/tests/system/filter-aaaa/ns3/hints b/bin/tests/system/filter-aaaa/ns3/hints new file mode 100644 index 0000000..fa0d3e4 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns3/hints @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 + +. NS ns.utld. +ns.utld. A 10.53.0.1 +ns.utld. AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/filter-aaaa/ns3/named1.conf.in b/bin/tests/system/filter-aaaa/ns3/named1.conf.in new file mode 100644 index 0000000..602859b --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns3/named1.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 break-dnssec; + filter-aaaa { 10.53.0.3; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints"; }; + +include "trusted.conf"; diff --git a/bin/tests/system/filter-aaaa/ns3/named2.conf.in b/bin/tests/system/filter-aaaa/ns3/named2.conf.in new file mode 100644 index 0000000..db449af --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns3/named2.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v6 break-dnssec; + filter-aaaa { fd92:7065:b8e:ffff::3; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints"; }; + +include "trusted.conf"; diff --git a/bin/tests/system/filter-aaaa/ns4/named1.conf.in b/bin/tests/system/filter-aaaa/ns4/named1.conf.in new file mode 100644 index 0000000..0aa3007 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/named1.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { fd92:7065:b8e:ffff::4; }; + recursion no; + dnssec-validation no; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 break-dnssec; + filter-aaaa { 10.53.0.4; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type primary; file "root.db"; }; +zone "signed" { type primary; file "signed.db.signed"; }; +zone "unsigned" { type primary; file "unsigned.db"; }; diff --git a/bin/tests/system/filter-aaaa/ns4/named2.conf.in b/bin/tests/system/filter-aaaa/ns4/named2.conf.in new file mode 100644 index 0000000..e534e54 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/named2.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { fd92:7065:b8e:ffff::4; }; + recursion no; + dnssec-validation no; + notify yes; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v6 break-dnssec; + filter-aaaa { fd92:7065:b8e:ffff::4; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type primary; file "root.db"; }; +zone "signed" { type primary; file "signed.db.signed"; }; +zone "unsigned" { type primary; file "unsigned.db"; }; diff --git a/bin/tests/system/filter-aaaa/ns4/root.db b/bin/tests/system/filter-aaaa/ns4/root.db new file mode 100644 index 0000000..7984c37 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 ) +@ NS ns.utld +ns.utld A 10.53.0.4 +ns.utld AAAA fd92:7065:b8e:ffff::4 +; + +signed NS ns.signed +ns.signed A 10.53.0.4 +ns.signed AAAA fd92:7065:b8e:ffff::4 + +unsigned NS ns.unsigned +ns.unsigned A 10.53.0.4 +ns.unsigned AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/filter-aaaa/ns4/sign.sh b/bin/tests/system/filter-aaaa/ns4/sign.sh new file mode 100755 index 0000000..2a819b3 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/sign.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +SYSTESTDIR=filter-aaaa + +zone=signed. +infile=signed.db.in +zonefile=signed.db.signed +outfile=signed.db.signed + +$KEYGEN -a $DEFAULT_ALGORITHM $zone 2>&1 >/dev/null | cat_i +$KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 >/dev/null | cat_i + +$SIGNER -S -o $zone -f $outfile $infile >/dev/null 2>signer.err || cat signer.err +echo_i "signed zone '$zone'" diff --git a/bin/tests/system/filter-aaaa/ns4/signed.db.in b/bin/tests/system/filter-aaaa/ns4/signed.db.in new file mode 100644 index 0000000..fa52106 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/signed.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.signed. hostmaster.ns.signed. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.4 + AAAA fd92:7065:b8e:ffff::4 + +a-only NS 1.0.0.1 +aaaa-only AAAA 2001:db8::2 +dual A 1.0.0.3 +dual AAAA 2001:db8::3 +mx A 1.0.0.3 +mx AAAA 2001:db8::3 diff --git a/bin/tests/system/filter-aaaa/ns4/unsigned.db b/bin/tests/system/filter-aaaa/ns4/unsigned.db new file mode 100644 index 0000000..4baa462 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns4/unsigned.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.4 + AAAA fd92:7065:b8e:ffff::4 + +a-only NS 1.0.0.4 +aaaa-only AAAA 2001:db8::5 +dual A 1.0.0.6 +dual AAAA 2001:db8::6 +mx A 1.0.0.3 +mx AAAA 2001:db8::3 diff --git a/bin/tests/system/filter-aaaa/ns5/hints b/bin/tests/system/filter-aaaa/ns5/hints new file mode 100644 index 0000000..fa0d3e4 --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns5/hints @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 + +. NS ns.utld. +ns.utld. A 10.53.0.1 +ns.utld. AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/filter-aaaa/ns5/named.conf.in b/bin/tests/system/filter-aaaa/ns5/named.conf.in new file mode 100644 index 0000000..36380cd --- /dev/null +++ b/bin/tests/system/filter-aaaa/ns5/named.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { fd92:7065:b8e:ffff::5; }; + recursion yes; + dnssec-validation no; + notify yes; + dns64 64:ff9b::/96 { + clients { any; }; + exclude { any; }; + mapped { any; }; + }; + minimal-responses no; +}; + +plugin query "../../../../plugins/.libs/filter-aaaa.so" { + filter-aaaa-on-v4 break-dnssec; + filter-aaaa { any; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints"; }; + +include "trusted.conf"; diff --git a/bin/tests/system/filter-aaaa/setup.sh b/bin/tests/system/filter-aaaa/setup.sh new file mode 100644 index 0000000..c3901c5 --- /dev/null +++ b/bin/tests/system/filter-aaaa/setup.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns2/named1.conf.in ns2/named.conf +copy_setports ns3/named1.conf.in ns3/named.conf +copy_setports ns4/named1.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +(cd ns1 && $SHELL -e sign.sh) +(cd ns4 && $SHELL -e sign.sh) diff --git a/bin/tests/system/filter-aaaa/tests.sh b/bin/tests/system/filter-aaaa/tests.sh new file mode 100644 index 0000000..e6cca52 --- /dev/null +++ b/bin/tests/system/filter-aaaa/tests.sh @@ -0,0 +1,1405 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +for conf in conf/good*.conf; do + n=$((n + 1)) + echo_i "checking that $conf is accepted ($n)" + ret=0 + $CHECKCONF "$conf" || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for conf in conf/bad*.conf; do + n=$((n + 1)) + echo_i "checking that $conf is rejected ($n)" + ret=0 + $CHECKCONF "$conf" >/dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +# +# Authoritative tests against: +# filter-aaaa-on-v4 yes; +# filter-aaaa { 10.53.0.1; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep ::5 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns1.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6 ($n)" +if testsock6 fd92:7065:b8e:ffff::1; then + ret=0 + $DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 + grep 2001:db8::6 dig.out.ns1.test$n >/dev/null || ret=1 + grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)" +ret=0 +$DIG $DIGOPTS +add ns unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep AAAA dig.out.ns1.test$n >/dev/null 2>&1 && ret=1 +grep "ANSWER: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep "ADDITIONAL: 2" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6 ($n)" +if testsock6 fd92:7065:b8e:ffff::1; then + ret=0 + $DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 + grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 + grep "AUTHORITY: 1," dig.out.ns1.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +# +# Authoritative tests against: +# filter-aaaa-on-v4 break-dnssec; +# filter-aaaa { 10.53.0.4; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns4.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns4.test$n >/dev/null || ret=1 +grep ::5 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns4.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns4.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6 with break-dnssec ($n)" +if testsock6 fd92:7065:b8e:ffff::4; then + ret=0 + $DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 + grep 2001:db8::6 dig.out.ns4.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add ns unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep AAAA dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns4.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6, with break-dnssec ($n)" +if testsock6 fd92:7065:b8e:ffff::4; then + ret=0 + $DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 + grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +# +# Recursive tests against: +# filter-aaaa-on-v4 yes; +# filter-aaaa { 10.53.0.2; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep ::5 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns2.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6, recursive ($n)" +if testsock6 fd92:7065:b8e:ffff::2; then + ret=0 + $DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 + grep 2001:db8::6 dig.out.ns2.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)" +ret=0 +$DIG $DIGOPTS +add ns unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep AAAA dig.out.ns2.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, signed, recursive ($n)" +ret=0 +# we need to prime the cache with addresses for the MX, since additional +# section data won't be included unless it's validated, and that doesn't +# necessarily happen otherwise. +$DIG $DIGOPTS +dnssec mx.signed @10.53.0.2 >/dev/null +$DIG $DIGOPTS +dnssec mx.signed aaaa @10.53.0.2 >/dev/null +$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, recursive, over IPv6 ($n)" +if testsock6 fd92:7065:b8e:ffff::2; then + ret=0 + $DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 + grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +# +# Recursive tests against: +# filter-aaaa-on-v4 break-dnssec; +# filter-aaaa { 10.53.0.3; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep ::5 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns3.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv6, recursive with break-dnssec ($n)" +if testsock6 fd92:7065:b8e:ffff::3; then + ret=0 + $DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 + grep 2001:db8::6 dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add ns unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep AAAA dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns3.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv6, recursive with break-dnssec ($n)" +if testsock6 fd92:7065:b8e:ffff::3; then + ret=0 + $DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 + grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +if ! testsock6 fd92:7065:b8e:ffff::1; then + echo_i "IPv6 address not configured; skipping IPv6 query tests" + echo_i "exit status: $status" + exit $status +fi + +# Reconfiguring for IPv6 tests +echo_i "reconfiguring servers" +copy_setports ns1/named2.conf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 +copy_setports ns2/named2.conf.in ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +copy_setports ns3/named2.conf.in ns3/named.conf +rndc_reconfig ns3 10.53.0.3 +copy_setports ns4/named2.conf.in ns4/named.conf +rndc_reconfig ns4 10.53.0.4 + +# BEGIN IPv6 TESTS + +# +# Authoritative tests against: +# filter-aaaa-on-v6 yes; +# filter-aaaa { fd92:7065:b8e:ffff::1; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep ::2 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep ::5 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep ::3 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns1.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns1.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns1.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4 ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep 2001:db8::6 dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep AAAA dig.out.ns1.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 >dig.out.ns1.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4 ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Authoritative tests against: +# filter-aaaa-on-v6 break-dnssec; +# filter-aaaa { fd92:7065:b8e:ffff::4; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep ::2 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep ::5 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns4.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns4.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns4.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns4.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4 with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep 2001:db8::6 dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep AAAA dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns4.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::4 @fd92:7065:b8e:ffff::4 >dig.out.ns4.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4, with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.4 @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns4.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Recursive tests against: +# filter-aaaa-on-v6 yes; +# filter-aaaa { fd92:7065:b8e:ffff::2; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep ::5 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist, signed and DO set, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, signed, qtype=ANY and DO is set, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns2.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns2.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4, recursive ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep 2001:db8::6 dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep AAAA dig.out.ns2.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, signed ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::2 @fd92:7065:b8e:ffff::2 >dig.out.ns2.test$n || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4 ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.2 @10.53.0.2 >dig.out.ns2.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns2.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Recursive tests against: +# filter-aaaa-on-v6 yes; +# filter-aaaa { fd92:7065:b8e:ffff::3; }; +# +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::2 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when only AAAA record exists, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep ::5 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, signed and DO set, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.signed +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that NODATA/NOERROR is returned when both AAAA and A records exist, unsigned and DO set, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A records exist and query source does not match acl, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::3" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned and qtype=ANY with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, signed, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.signed +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.3" dig.out.ns3.test$n >/dev/null || ret=1 +grep ::3 dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that A and not AAAA is returned when both AAAA and A records exist, unsigned, qtype=ANY and DO is set with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned +dnssec -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "1.0.0.6" dig.out.ns3.test$n >/dev/null || ret=1 +grep "::6" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that both A and AAAA are returned when both AAAA and A records exist, qtype=ANY and query source does not match acl, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS any dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep 1.0.0.6 dig.out.ns3.test$n >/dev/null || ret=1 +grep ::6 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is returned when both AAAA and A record exists, unsigned over IPv4, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep 2001:db8::6 dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=NS, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec ns unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep AAAA dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +grep "ADDITIONAL: 2" dig.out.ns3.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, unsigned, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is omitted from additional section, qtype=MX, signed, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx signed -b fd92:7065:b8e:ffff::3 @fd92:7065:b8e:ffff::3 >dig.out.ns3.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null || ret=1 +grep "^mx.signed.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that AAAA is included in additional section, qtype=MX, unsigned, over IPv4, recursive with break-dnssec ($n)" +ret=0 +$DIG $DIGOPTS +add +dnssec mx unsigned -b 10.53.0.3 @10.53.0.3 >dig.out.ns3.test$n || ret=1 +grep "^mx.unsigned.*AAAA" dig.out.ns3.test$n >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# We don't check for the AAAA record here as configuration in ns5 does +# not make sense. The AAAA record is wanted by filter-aaaa but discarded +# by the dns64 configuration. We just want to ensure the server stays +# running. +n=$((n + 1)) +echo_i "checking filter-aaaa with dns64 ($n)" +ret=0 +$DIG $DIGOPTS aaaa aaaa-only.unsigned @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "status: NOERROR" dig.out.ns5.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py b/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py new file mode 100644 index 0000000..6e1df65 --- /dev/null +++ b/bin/tests/system/filter-aaaa/tests_sh_filter_aaaa.py @@ -0,0 +1,31 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns*/trusted.conf", + "ns1/K*", + "ns1/dsset-*", + "ns1/*.signed", + "ns1/signer.err", + "ns4/K*", + "ns4/dsset-*", + "ns4/*.signed", + "ns4/signer.err", + ] +) + + +def test_filter_aaaa(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/formerr/badnsec3owner b/bin/tests/system/formerr/badnsec3owner new file mode 100644 index 0000000..de6e692 --- /dev/null +++ b/bin/tests/system/formerr/badnsec3owner @@ -0,0 +1,7 @@ +# bad NSEC3 owner (:) not in base32hex valid characters +# header: id=0008 opcode=query questions=1 authority=1 +00 08 00 00 00 01 00 00 00 01 00 00 +# question: ./A/IN +00 00 01 00 01 +# :./NSEC3/IN/1 length=7 hashtype=240 flags=0 interations=0 salt=- hashlen=1 hash=ff +01 58 00 00 32 00 01 00 00 00 01 00 07 f0 00 00 00 00 01 ff diff --git a/bin/tests/system/formerr/badrecordname b/bin/tests/system/formerr/badrecordname new file mode 100644 index 0000000..f79df49 --- /dev/null +++ b/bin/tests/system/formerr/badrecordname @@ -0,0 +1,21 @@ +# oversized owner name +# header: additional=1 +00 00 00 00 00 00 00 00 00 00 00 01 +# owner name too big (256 octets) A/IN/1 0.0.0.0 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 00 01 00 00 00 01 00 04 00 00 00 00 diff --git a/bin/tests/system/formerr/dupans b/bin/tests/system/formerr/dupans new file mode 100644 index 0000000..142022a --- /dev/null +++ b/bin/tests/system/formerr/dupans @@ -0,0 +1,8 @@ +# multiple singletons (SOA) +# header questions=1 answers=2 +00 00 00 00 00 01 00 02 00 00 00 00 +# question SOA/IN +00 00 06 00 01 +# 2 SOA records that differ in expire +00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 +00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06 diff --git a/bin/tests/system/formerr/dupquestion b/bin/tests/system/formerr/dupquestion new file mode 100644 index 0000000..327b8ca --- /dev/null +++ b/bin/tests/system/formerr/dupquestion @@ -0,0 +1,10 @@ +# header: 2 questions +00 00 00 00 00 02 00 00 00 00 00 00 +# question: AAAAAAAAAAAAAA./A/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 +00 01 +# question: AAAAAAAAAAAAAA./A/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 +00 01 diff --git a/bin/tests/system/formerr/formerr.pl b/bin/tests/system/formerr/formerr.pl new file mode 100644 index 0000000..fd7d298 --- /dev/null +++ b/bin/tests/system/formerr/formerr.pl @@ -0,0 +1,97 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# This is a tool for sending an arbitrary packet via UDP or TCP to an +# arbitrary address and port. The packet is specified in a file or on +# the standard input, in the form of a series of bytes in hexadecimal. +# Whitespace is ignored, as is anything following a '#' symbol. +# +# For example, the following input would generate normal query for +# isc.org/NS/IN": +# +# # QID: +# 0c d8 +# # header: +# 01 00 00 01 00 00 00 00 00 00 +# # qname isc.org: +# 03 69 73 63 03 6f 72 67 00 +# # qtype NS: +# 00 02 +# # qclass IN: +# 00 01 +# +# Note that we do not wait for a response for the server. This is simply +# a way of injecting arbitrary packets to test server resposnes. +# +# Usage: packet.pl [-a
] [-p ] [-t (udp|tcp)] [filename] +# +# If not specified, address defaults to 127.0.0.1, port to 53, protocol +# to udp, and file to stdin. +# +# XXX: Doesn't support IPv6 yet + +require 5.006_001; + +use strict; +use Getopt::Std; +use IO::File; +use IO::Socket; + +sub usage { + print ("Usage: packet.pl [-a address] [-p port] [file]\n"); + exit 1; +} + +my %options={}; +getopts("a:p:", \%options); + +my $addr = "127.0.0.1"; +$addr = $options{a} if defined $options{a}; + +my $port = 53; +$port = $options{p} if defined $options{p}; + +my $file = "STDIN"; +if (@ARGV >= 1) { + my $filename = shift @ARGV; + open FH, "<$filename" or die "$filename: $!"; + $file = "FH"; +} + +my $input = ""; +while (defined(my $line = <$file>) ) { + chomp $line; + $line =~ s/#.*$//; + $input .= $line; +} + +$input =~ s/\s+//g; +my $data = pack("H*", $input); +my $len = length $data; + +my $output = unpack("H*", $data); +print ("sending: $output\n"); + +my $sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port, + Proto => "tcp") or die "$!"; + +my $bytes; +$bytes = $sock->syswrite(pack("n", $len), 2); +$bytes = $sock->syswrite($data, $len); +$bytes = $sock->sysread($data, 2); +$len = unpack("n", $data); +$bytes = $sock->sysread($data, $len); +print "got: ", unpack("H*", $data). "\n"; + +$sock->close; +close $file; diff --git a/bin/tests/system/formerr/keyclass b/bin/tests/system/formerr/keyclass new file mode 100644 index 0000000..c84568a --- /dev/null +++ b/bin/tests/system/formerr/keyclass @@ -0,0 +1,7 @@ +# mismatched key class +# header: questions=1 additional=1 +00 00 00 00 00 01 00 00 00 00 00 01 +# question: ./A/IN +00 00 01 00 01 +# additional: ./KEY/CLASS2 flags=0 protocol=0 algorithm=248 keydata=00 +00 00 19 00 02 00 00 00 01 00 05 00 00 00 f8 00 diff --git a/bin/tests/system/formerr/malformeddeltype b/bin/tests/system/formerr/malformeddeltype new file mode 100644 index 0000000..2d14ae4 --- /dev/null +++ b/bin/tests/system/formerr/malformeddeltype @@ -0,0 +1,5 @@ +# UPDATE malformed 'delete type' update change (non empty data) +# header: UPDATE authority=1 +00 00 28 00 00 00 00 00 00 01 00 00 +# ./A/ANY TTL=0 length=1 data=00 +00 00 01 00 ff 00 00 00 00 00 01 00 diff --git a/bin/tests/system/formerr/malformedrrsig b/bin/tests/system/formerr/malformedrrsig new file mode 100644 index 0000000..07d2af0 --- /dev/null +++ b/bin/tests/system/formerr/malformedrrsig @@ -0,0 +1,5 @@ +# malformed RRRSIG +# header: QUERY, additional=1 +00 00 00 00 00 00 00 00 00 00 00 01 +# ./RRSIG/IN TTL=1 covers=0 algorithm=240 labels=0 ttl=1 expire=2 signed=3 id=0 +00 00 2e 00 01 00 00 00 01 00 14 00 00 f0 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 00 diff --git a/bin/tests/system/formerr/nametoolong b/bin/tests/system/formerr/nametoolong new file mode 100644 index 0000000..b81545f --- /dev/null +++ b/bin/tests/system/formerr/nametoolong @@ -0,0 +1,19 @@ +00 00 00 00 00 01 00 00 00 00 00 00 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 +00 01 diff --git a/bin/tests/system/formerr/noquestions b/bin/tests/system/formerr/noquestions new file mode 100644 index 0000000..f087bcd --- /dev/null +++ b/bin/tests/system/formerr/noquestions @@ -0,0 +1 @@ +00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/bin/tests/system/formerr/ns1/named.conf.j2 b/bin/tests/system/formerr/ns1/named.conf.j2 new file mode 100644 index 0000000..1334c85 --- /dev/null +++ b/bin/tests/system/formerr/ns1/named.conf.j2 @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/formerr/ns1/root.db b/bin/tests/system/formerr/ns1/root.db new file mode 100644 index 0000000..f4d4c69 --- /dev/null +++ b/bin/tests/system/formerr/ns1/root.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.4 diff --git a/bin/tests/system/formerr/optwrongname b/bin/tests/system/formerr/optwrongname new file mode 100644 index 0000000..7b486d9 --- /dev/null +++ b/bin/tests/system/formerr/optwrongname @@ -0,0 +1,5 @@ +# OPT record with wrong name (not .) +# header: QUERY, additional=1 +00 00 00 00 00 00 00 00 00 00 00 01 +# OPT record (owner A.) +01 41 00 00 29 00 01 00 00 00 00 00 00 diff --git a/bin/tests/system/formerr/qtypeasanswer b/bin/tests/system/formerr/qtypeasanswer new file mode 100644 index 0000000..d254d1d --- /dev/null +++ b/bin/tests/system/formerr/qtypeasanswer @@ -0,0 +1,5 @@ +# QTYPE-only type as answer +# header, answers=1 +00 00 00 00 00 00 00 01 00 00 00 00 +# ./MAILB/IN +00 00 fd 00 01 00 00 00 01 00 00 diff --git a/bin/tests/system/formerr/questionclass b/bin/tests/system/formerr/questionclass new file mode 100644 index 0000000..b34d1e3 --- /dev/null +++ b/bin/tests/system/formerr/questionclass @@ -0,0 +1,7 @@ +# two questions of different classes +# header: QUERY, questions=2 +00 00 00 00 00 02 00 00 00 00 00 00 +# ./A/IN +00 00 01 00 01 +# ./A/CLASS2 +00 00 01 00 02 diff --git a/bin/tests/system/formerr/shortquestion b/bin/tests/system/formerr/shortquestion new file mode 100644 index 0000000..168ed90 --- /dev/null +++ b/bin/tests/system/formerr/shortquestion @@ -0,0 +1,5 @@ +# truncated question section +# header: QUERY, questions=1 +00 00 00 00 00 01 00 00 00 00 00 00 +# truncated question (no class) +00 00 01 diff --git a/bin/tests/system/formerr/shortrecord b/bin/tests/system/formerr/shortrecord new file mode 100644 index 0000000..d9a2ab7 --- /dev/null +++ b/bin/tests/system/formerr/shortrecord @@ -0,0 +1,5 @@ +# truncated record +# header: QUERY, additional=1 +00 09 00 00 00 00 00 00 00 00 00 01 +# truncated A record (no ttl, length or data) +00 00 01 00 01 diff --git a/bin/tests/system/formerr/tests.sh b/bin/tests/system/formerr/tests.sh new file mode 100644 index 0000000..2ec7448 --- /dev/null +++ b/bin/tests/system/formerr/tests.sh @@ -0,0 +1,177 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 + +echo_i "test name too long" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} nametoolong >nametoolong.out +ans=$(grep got: nametoolong.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "two question names" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestionnames >twoquestionnames.out +ans=$(grep got: twoquestionnames.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "two question types" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} twoquestiontypes >twoquestiontypes.out +ans=$(grep got: twoquestiontypes.out) +if [ "${ans}" != "got: 0000800100020000000000000e41414141414141414141414141410000010001c00c00020001" ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "duplicate questions" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} dupquestion >dupquestion.out +ans=$(grep got: dupquestion.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "duplicate answer" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} dupans >dupans.out +ans=$(grep got: dupans.out) +if [ "${ans}" != "got: 0000800100010000000000000000060001" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "question only type in answer" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} qtypeasanswer >qtypeasanswer.out +ans=$(grep got: qtypeasanswer.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +# this would be NOERROR if it included a COOKIE option, +# but is a FORMERR without one. +echo_i "empty question section (and no COOKIE option)" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} noquestions >noquestions.out +ans=$(grep got: noquestions.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "bad nsec3 owner" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} badnsec3owner >badnsec3owner.out +ans=$(grep got: badnsec3owner.out) +# SERVFAIL (2) rather than FORMERR (1) +if [ "${ans}" != "got: 0008800200010000000000000000010001" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "short record before rdata " +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} shortrecord >shortrecord.out +ans=$(grep got: shortrecord.out) +if [ "${ans}" != "got: 000980010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "short question" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} shortquestion >shortquestion.out +ans=$(grep got: shortquestion.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "mismatch classes in question section" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} questionclass >questionclass.out +ans=$(grep got: questionclass.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "bad record owner name" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} badrecordname >badrecordname.out +ans=$(grep got: badrecordname.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "mismatched class in record" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} wrongclass >wrongclass.out +ans=$(grep got: wrongclass.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "mismatched KEY class" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} keyclass >keyclass.out +ans=$(grep got: keyclass.out) +if [ "${ans}" != "got: 0000800100010000000000000000010001" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "OPT wrong owner name" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} optwrongname >optwrongname.out +ans=$(grep got: optwrongname.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "RRSIG invalid covers" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} malformedrrsig >malformedrrsig.out +ans=$(grep got: malformedrrsig.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "UPDATE malformed delete type" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} malformeddeltype >malformeddeltype.out +ans=$(grep got: malformeddeltype.out) +if [ "${ans}" != "got: 0000a8010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "TSIG wrong class" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} tsigwrongclass >tsigwrongclass.out +ans=$(grep got: tsigwrongclass.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "TSIG not last" +$PERL formerr.pl -a 10.53.0.1 -p ${PORT} tsignotlast >tsignotlast.out +ans=$(grep got: tsignotlast.out) +if [ "${ans}" != "got: 000080010000000000000000" ]; then + echo_i "failed" + status=$(expr $status + 1) +fi + +echo_i "exit status: $status" + +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/formerr/tests_sh_formerr.py b/bin/tests/system/formerr/tests_sh_formerr.py new file mode 100644 index 0000000..a091546 --- /dev/null +++ b/bin/tests/system/formerr/tests_sh_formerr.py @@ -0,0 +1,40 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "badnsec3owner.out", + "badrecordname.out", + "dupans.out", + "dupquestion.out", + "keyclass.out", + "malformeddeltype.out", + "malformedrrsig.out", + "nametoolong.out", + "noquestions.out", + "optwrongname.out", + "qtypeasanswer.out", + "questionclass.out", + "shortquestion.out", + "shortrecord.out", + "tsignotlast.out", + "tsigwrongclass.out", + "twoquestionnames.out", + "twoquestiontypes.out", + "wrongclass.out", + ] +) + + +def test_formerr(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/formerr/tsignotlast b/bin/tests/system/formerr/tsignotlast new file mode 100644 index 0000000..108936c --- /dev/null +++ b/bin/tests/system/formerr/tsignotlast @@ -0,0 +1,8 @@ +# SIG not last in additional +# header: QUERY additional=2 +00 00 00 00 00 00 00 00 00 00 00 02 +# Additional records: +# SIG record (class ANY) +00 00 fa 00 ff 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00 +# A record +00 00 01 00 01 00 00 00 01 00 04 00 00 00 00 diff --git a/bin/tests/system/formerr/tsigwrongclass b/bin/tests/system/formerr/tsigwrongclass new file mode 100644 index 0000000..29aea08 --- /dev/null +++ b/bin/tests/system/formerr/tsigwrongclass @@ -0,0 +1,5 @@ +# TSIG wrong class +# header: QUERY, additional=1 +00 00 00 00 00 00 00 00 00 00 00 01 +# class should be ANY (00 ff) not IN (00 01) +00 00 fa 00 01 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00 diff --git a/bin/tests/system/formerr/twoquestionnames b/bin/tests/system/formerr/twoquestionnames new file mode 100644 index 0000000..f363a23 --- /dev/null +++ b/bin/tests/system/formerr/twoquestionnames @@ -0,0 +1,11 @@ +# two questions with different names +00 00 00 00 00 02 00 00 00 00 00 00 +# AAAAAAAAAAAAAA./A/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 +00 01 +# AAAAAAAAAAAAAB./A/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 42 00 +00 01 +00 01 diff --git a/bin/tests/system/formerr/twoquestiontypes b/bin/tests/system/formerr/twoquestiontypes new file mode 100644 index 0000000..451f8f6 --- /dev/null +++ b/bin/tests/system/formerr/twoquestiontypes @@ -0,0 +1,10 @@ +# two questions that differ by type +00 00 00 00 00 02 00 00 00 00 00 00 +# AAAAAAAAAAAAAAA./A/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 01 +00 01 +# AAAAAAAAAAAAAAA./NS/IN +0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00 +00 02 +00 01 diff --git a/bin/tests/system/formerr/wrongclass b/bin/tests/system/formerr/wrongclass new file mode 100644 index 0000000..96211e0 --- /dev/null +++ b/bin/tests/system/formerr/wrongclass @@ -0,0 +1,7 @@ +# class mismatch +# header: QUERY, additional=2 +00 00 00 00 00 00 00 00 00 00 00 02 +# ./A/IN +00 00 01 00 01 00 00 00 01 00 04 00 00 00 00 +# ./TYPE65280/CLASS256 +00 ff 00 01 00 02 00 00 01 00 04 00 00 00 00 diff --git a/bin/tests/system/forward/CA/CA.cfg b/bin/tests/system/forward/CA/CA.cfg new file mode 100644 index 0000000..369e43a --- /dev/null +++ b/bin/tests/system/forward/CA/CA.cfg @@ -0,0 +1,77 @@ +# See ../../doth/CA/ca.cfg for more information + +# certificate authority configuration +[ca] +default_ca = CA_default # The default ca section + +[CA_default] +dir = . +new_certs_dir = $dir/newcerts # new certs dir (must be created) +certificate = $dir/CA.pem # The CA cert +private_key = $dir/private/CA.key # CA private key + +serial = $dir/serial # serial number file for the next certificate + # Update before issuing it: + # xxd -l 8 -u -ps /dev/urandom > ./serial +database = $dir/index.txt # (must be created manually: touch ./index.txt) + +default_days = 10950 # how long to certify for + +#default_crl_days = 30 # the number of days before the +default_crl_days = 10950 # next CRL is due. That is the + # days from now to place in the + # CRL nextUpdate field. If CRL + # is expired, certificate + # verifications will fail even + # for otherwise valid + # certificates. Clients might + # cache the CRL, so the expiry + # period should normally be + # relatively short (default: + # 30) for production CAs. + +default_md = sha256 # digest to use + +policy = policy_default # default policy +email_in_dn = no # Don't add the email into cert DN + +name_opt = ca_default # Subject name display option +cert_opt = ca_default # Certificate display option + +# We need the following in order to copy Subject Alt Name(s) from a +# request to the certificate. +copy_extensions = copy # copy extensions from request + +[policy_default] +countryName = optional +stateOrProvinceName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# default certificate requests settings +[req] +# Options for the `req` tool (`man req`). +default_bits = 3072 # for RSA only +distinguished_name = req_default +string_mask = utf8only +# SHA-1 is deprecated, so use SHA-256 instead. +default_md = sha256 +# do not encrypt the private key file +encrypt_key = no + +[req_default] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (e.g., city) +0.organizationName = Organization Name (e.g., company) +organizationalUnitName = Organizational Unit Name (e.g. department) +commonName = Common Name (e.g. server FQDN or YOUR name) +emailAddress = Email Address +# defaults +countryName_default = UA +stateOrProvinceName_default = Kharkiv Oblast +localityName_default = Kharkiv +0.organizationName_default = ISC +organizationalUnitName_default = Software Engeneering (BIND 9) diff --git a/bin/tests/system/forward/CA/CA.pem b/bin/tests/system/forward/CA/CA.pem new file mode 100644 index 0000000..1f725db --- /dev/null +++ b/bin/tests/system/forward/CA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE3TCCA0WgAwIBAgIUeZPKrvbGEBZaRc2jNczlIsJXyPYwDQYJKoZIhvcNAQEL +BQAwfTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G +A1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0 +aXVtMRwwGgYDVQQDDBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDEyNDEyNDA1 +NFoYDzIwNTIwMTE3MTI0MDU0WjB9MQswCQYDVQQGEwJVQTEYMBYGA1UECAwPS2hh +cmtpdiBPYmxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5l +dCBTeXN0ZW1zIENvbnNvcnRpdW0xHDAaBgNVBAMME2NhLnRlc3QuZXhhbXBsZS5j +b20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCi6hEegBzpUKbE1NTo +Z7uz7EMUY7TBckkiw/7ydTLKNa8YI4JpBguFvWQsDY0dGFJIoVwyHyNx3seW/LoI +B5zWPZ2xbOvLLceA+t2NZpbc98E7jUOVS123yED+nqlfZjCq9Zt0r/ezwnQtjnFF +ko1mcU4H9Jvg8aIgnU2AxE78zciU9CY8799pFFNThIjbooI8oVbfjbzbpmLzxjA5 +3rDmZBTh+ySTlMa2U2oT4WPjRltZWnJVegRRLpG95GnTbQ1fkJAbj1Iu10XTkCee +wBOqaA1UJem0a6pby5odE414Y7c0ETKcmaJtYENQyO0IJwZWDKtVe5OTIAklakia +eyFTCAw1h5tHCYLaJW/Yu2wlLl5RNQcRZ9+cWXnldTY+TI1iBjfmADjLdKJYUlhX +z7kWJtTi63Sdv6WYcEXxaWpxT+R3e2kaR/R7GOo4gdkWpX1siGlRteHHH2/36CSQ +ZD2etcTUpGW+KDHFR4grnEfL1rt9UgvCjpa4KcssmZtWSSUCAwEAAaNTMFEwHQYD +VR0OBBYEFHyJ6Fzr5R9ySATFj/uSCJz1YCY5MB8GA1UdIwQYMBaAFHyJ6Fzr5R9y +SATFj/uSCJz1YCY5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGB +AF3y0hvzyZWtmuG1JwIcOcc1aPl1KdRy8bao/5iHYGYYrsdDgcO5/e+y9S/izalc +TdW7SKB5iBOCiE8fBNtToCvGP+fxNxHijpAmTr37G5sWuSo1T1VYFizHWL+df/Ig +TcSvDrEjSnAwaEdNJUWtjoIC4VzNKTLtZf16QIATTzTZa3bfgSetpWS7LhLQbHod +CSGI2QB1LRbqGC+a1Y85QxHv81jWzPWPzXYvnOLrDdQyBMOBcxDzrN4b6zg+5Itz +qGYt+IS71jAH0IhxAyD/U5n1jGJv02BnSq0ynLEOD6gsnZjqAwPbt/PM9pGbtbXO +70Q9rxr+vQc1IISKAEiH3txaEPi10wU98d6LbInJvQrmgHo/ntet8skWNYuxlEzS +wvynuE9KvvQtOTodWt5AePtKrhHdxu527a4CHVp59nYUjKSdMKjvmhMRXM1cNjFE +rA/pyyhozR47w3RzHMJVHw2GJ2B/HeqmxpXr1CmJjoRP38QCR7N+mqiZy85Fq2j2 +8Q== +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/README b/bin/tests/system/forward/CA/README new file mode 100644 index 0000000..13069ca --- /dev/null +++ b/bin/tests/system/forward/CA/README @@ -0,0 +1,2 @@ +Please take a look at the contents of the CA.cfg file for further +instructions and configurations options. diff --git a/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.key b/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.key new file mode 100644 index 0000000..03e7e99 --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCT6jpDg/+SgAa+ +TqBTXQudybG4/tXM3K+Uequ6Ew/AtplxeJCxf0EHhVkmkBSIe/wMZHA38yo5gIBI +Tl93dCb6qt0/e45jtabOvLxaqh0ssJpUjANGi+YZUlFIFi2IrN9zu12G9YD/EpPR +U387aTVWbYGK6ku9ddW/orj5mBfHR+daCkegAD1cd0KV72Dq4iyrl6nzHcen+aov +XQO2W0iHtCdLmbPjmfjNu1GI9B401T7jEjwtwLcqnQtzfzqtJ5cXWFFwCId1QtKH +R2fA28a5+LAxpssVJHtUBv2S5iRxP1UCAnHyR3/l/r7UXx61WPcJ+mDjNiW99JFY +5vL98VoA6Hcm3C0gEPzHohYK4Vnk5aBy1COIp1ZxHWn1HuTB7Id67xnd3/ol8Dtv +xV8UICb6m+CvUcQYPzxJfSYlwtlcZ134r3MgWK5lXnEDd3h9RTcKo7cy6/7/X8bp +uFs38WHVhCdQ01VyLIp1FpqVtfkt69AiSVdrZYeqcahtOZb+56kCAwEAAQKCAYBG +jKj2i+5p10OgIItqx43jWBC6/l1GZZofVTU0PqQ8VDuyugE1j88aAbnIYV9Ry+Un +mf5GSWaB368QDcWOCaoP1FBL16hOGZWytKWYDtx0dNVfbxqe2tpIiJE5M07LijzY +C+1rkgxRXPCBHnSohyFIFFn9wouWla36Reg5MBhjVgHcWdvYzlR2FnH9ZpwQ3AjX +XTLTwQf6L+RCy/gZ0ccx5rT5Y5m//LAFnIsiqeEAbReeIZPvdKRIoHgWQgBgF2nJ +KAXFrf62gLSIXmnvvxiWL/xAUktg4kv+PFvEFjMjlxz3hOQuOwJQMt7zZkO0Pw2G +Ow08OznR3dXCOO7csmfTktWdB71vgtf+Y/RzCWbyHPBy4tfWDbiqQCFJSsn7CsC8 +r4YscQ55Xmw2AVsUd356Z6ONiM5LZmd+OIpamrVh4Bfgkk1ElPetnelEZO2ZPsBT +cud487ZOY0lD+lpNCAMqS2VeKRi+X/sefZHe3ZMJopRuyPLkqt3qh/sZlms3uWsC +gcEAvWeiyE75Y7DzTBY3sWCxOzj0g8oqFle4G0dxw/CxyF0ASlGNZtjyj/l2dJ1b +wRSk4HmJqgRrkW+cXYVMfoz8zoUfO/vXUe7+1ioxbQMxl7fH5O4R6ps7RxEaX9GE +Rhxx8B1Y1S8tauCFz0STOtvi6CXlCkRALMsEg7MbJJ2PjIrPSSpuWGZBYlJbh53u +spgElwq6qT0xqS8EFpGjSMsnPfXoOnKpWZpyJfKwkm9gwrvVjiVmw1TRcvcODoov +wSZrAoHBAMfsFIauVfoWGHgL80+/8NsYo0Ap3nycFWXH6XaIuhBfQdr8aLTDmj7Y +nlonP5PtsQBfpdlbm/xTTBiZ2hzTcRX7Ayu7eSmZFFP7yE4Amo+bdh9y9KWbIWjA +K5XwwJ7kTWrgiai5nu0JRH+FuMOOEpUHikfOIci7V8LGbkFQ7G1pmXyQwpFT1ClR +ORHnv2A/YklP2jpa7KdPNZgYBQic5JnaNZdFzF0pi1v69UyAP4JBzaWHOz1kMH/B +JxknYpJnOwKBwQCeSyLsrbQX8SclC9x3zgvRJwSTsD4EdkNT6R3XWC38+lznv8ih +j+cJFMA/LdQlRg+V232GLjOIVPMl5eXMTiBqqS81foCx5T/t1U2Bgg3McrgJSD6J +CDs+ZbjZI82cmuFOf/hiEw+uJv8t/m3d3y+APUtyjR/lT7byKpogu93g45Hh4Chg +kPVMKvB8Iy3+7LXJVhoynwYGE1kjU4xXphGh4wa28mU+kamctXuEprkDhuAv8Go2 +DYkOwBNra2oFzwkCgcA+TpRjGShQhdxgZZESFMby8a3HTIU7nsWIcBKRz7D1c0qp +/ip/08pZtdc8T6kf6F9Wt3iP0l49+JPpwuFYRImlCRMG6SmszjmopvrZXJTPFuts +h745cqyp4eJzm5Hcs1hxa8NbY2Zlh5Lij4Fy6O9fpPbyxAqBbem/GWq5Togw3U1p +phANjOu9aMP5kZlyXK68HHft4fKJfkU8vperBIK2dGxpVeaITm9RXlhe3EVuyiVW +ZlwPGQ+IcWFHFKBC8osCgcEAiTMZ0gMkuPHnDRcLeBqU6iGpme/+LES9RmBgL4AT +mZHOfsvwkNOdyHb20/ns/OQqBgJpbkQCCrTPJyhv1gqaYtwKlSaI334Lmfg2CP/7 +ZFxwo/MfqYDwYZQj35/cN1SkNNvuuKVIX61CNPTr0Wxrs5ZFUwG00RtZzhzYWaku +R0f3FTLR0KbQOKt8nhEgqo8NRzQGrMU9mj+61kMXTdt6N5ipxzPuAUv+D62QbO0T +ndTltEnt0w6vtzmImIWupyBm +-----END PRIVATE KEY----- diff --git a/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.pem b/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.pem new file mode 100644 index 0000000..ea6030f --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv02.crt01.example.nil.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8b + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 8 11:52:43 2022 GMT + Not After : Nov 30 11:52:43 2052 GMT + Subject: CN=srv02.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:93:ea:3a:43:83:ff:92:80:06:be:4e:a0:53:5d: + 0b:9d:c9:b1:b8:fe:d5:cc:dc:af:94:7a:ab:ba:13: + 0f:c0:b6:99:71:78:90:b1:7f:41:07:85:59:26:90: + 14:88:7b:fc:0c:64:70:37:f3:2a:39:80:80:48:4e: + 5f:77:74:26:fa:aa:dd:3f:7b:8e:63:b5:a6:ce:bc: + bc:5a:aa:1d:2c:b0:9a:54:8c:03:46:8b:e6:19:52: + 51:48:16:2d:88:ac:df:73:bb:5d:86:f5:80:ff:12: + 93:d1:53:7f:3b:69:35:56:6d:81:8a:ea:4b:bd:75: + d5:bf:a2:b8:f9:98:17:c7:47:e7:5a:0a:47:a0:00: + 3d:5c:77:42:95:ef:60:ea:e2:2c:ab:97:a9:f3:1d: + c7:a7:f9:aa:2f:5d:03:b6:5b:48:87:b4:27:4b:99: + b3:e3:99:f8:cd:bb:51:88:f4:1e:34:d5:3e:e3:12: + 3c:2d:c0:b7:2a:9d:0b:73:7f:3a:ad:27:97:17:58: + 51:70:08:87:75:42:d2:87:47:67:c0:db:c6:b9:f8: + b0:31:a6:cb:15:24:7b:54:06:fd:92:e6:24:71:3f: + 55:02:02:71:f2:47:7f:e5:fe:be:d4:5f:1e:b5:58: + f7:09:fa:60:e3:36:25:bd:f4:91:58:e6:f2:fd:f1: + 5a:00:e8:77:26:dc:2d:20:10:fc:c7:a2:16:0a:e1: + 59:e4:e5:a0:72:d4:23:88:a7:56:71:1d:69:f5:1e: + e4:c1:ec:87:7a:ef:19:dd:df:fa:25:f0:3b:6f:c5: + 5f:14:20:26:fa:9b:e0:af:51:c4:18:3f:3c:49:7d: + 26:25:c2:d9:5c:67:5d:f8:af:73:20:58:ae:65:5e: + 71:03:77:78:7d:45:37:0a:a3:b7:32:eb:fe:ff:5f: + c6:e9:b8:5b:37:f1:61:d5:84:27:50:d3:55:72:2c: + 8a:75:16:9a:95:b5:f9:2d:eb:d0:22:49:57:6b:65: + 87:aa:71:a8:6d:39:96:fe:e7:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.nil, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 70:90:94:81:4A:B2:BF:13:D6:29:1A:90:D9:33:A4:C5:74:29:CF:59 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 77:6c:f4:07:36:0b:ef:6e:86:2d:41:73:e0:ba:f7:4c:f1:bd: + 8f:77:89:1a:8c:63:2e:39:93:a2:43:ee:70:85:f1:5d:01:60: + ab:e6:50:a1:5e:72:e3:89:13:77:e0:a5:f7:fa:27:31:93:1f: + 3a:a7:35:5f:7d:59:3c:d2:26:9c:12:fa:51:2b:d3:31:0c:5a: + e7:a8:be:6a:2e:b2:82:6c:42:f2:86:74:9c:0a:c8:58:a8:68: + 35:73:6e:1b:0c:9e:3b:08:3f:b9:ef:68:61:e9:d3:40:1d:aa: + dd:42:e3:1d:b0:1b:6e:b8:58:60:a1:68:4a:ff:09:b7:58:5b: + 72:e8:36:a3:6d:10:78:c7:7f:52:f6:dc:39:5c:05:7d:7a:ae: + 8d:3f:89:8f:10:a6:4d:8b:55:6a:9b:cb:2c:1d:00:59:9b:0c: + c3:55:e0:a3:25:69:b4:29:30:2f:20:bf:07:f4:21:88:b7:d0: + 62:ad:d7:ca:e1:91:45:9f:a2:5f:7d:07:f4:98:b0:5e:d4:3a: + 92:86:e9:a1:fb:c0:9b:81:46:da:56:ed:92:47:c0:1a:aa:55: + 37:0e:3c:92:2c:44:7a:80:55:1f:15:7a:7c:c4:7e:ad:d5:b0: + a5:7e:33:63:09:23:6b:78:42:de:37:aa:04:a7:52:ed:06:fe: + d4:56:36:12:85:b6:ec:ff:03:ea:4b:e2:7a:42:49:73:b6:ab: + e4:7d:4a:2b:94:65:1f:b1:17:a3:be:17:0b:4e:53:3d:8a:d3: + d7:04:0f:f1:1a:63:b2:a6:eb:00:31:64:b4:80:e9:ae:bb:69: + 12:04:a5:7d:2c:bd:91:62:2c:b9:5a:6e:af:e0:ee:27:f0:88: + 15:8b:b7:ce:07:5e:bc:6b:e9:3e:3f:23:c7:f9:c9:48:20:69: + 6a:8e:f2:17:9b:58:ff:72:36:21:ed:d3:83:16:60:ec:de:6f: + c4:50:47:b7:61:ce:75:c1:d6:60:28:de:bd:69:7c:e6:db:0e: + b9:fa:7b:84:24:35 +-----BEGIN CERTIFICATE----- +MIIEkDCCAvigAwIBAgIJAMzBGAgmMuGLMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yMjEyMDgxMTUyNDNaGA8yMDUyMTEz +MDExNTI0M1owIjEgMB4GA1UEAwwXc3J2MDIuY3J0MDEuZXhhbXBsZS5uaWwwggGi +MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCT6jpDg/+SgAa+TqBTXQudybG4 +/tXM3K+Uequ6Ew/AtplxeJCxf0EHhVkmkBSIe/wMZHA38yo5gIBITl93dCb6qt0/ +e45jtabOvLxaqh0ssJpUjANGi+YZUlFIFi2IrN9zu12G9YD/EpPRU387aTVWbYGK +6ku9ddW/orj5mBfHR+daCkegAD1cd0KV72Dq4iyrl6nzHcen+aovXQO2W0iHtCdL +mbPjmfjNu1GI9B401T7jEjwtwLcqnQtzfzqtJ5cXWFFwCId1QtKHR2fA28a5+LAx +pssVJHtUBv2S5iRxP1UCAnHyR3/l/r7UXx61WPcJ+mDjNiW99JFY5vL98VoA6Hcm +3C0gEPzHohYK4Vnk5aBy1COIp1ZxHWn1HuTB7Id67xnd3/ol8DtvxV8UICb6m+Cv +UcQYPzxJfSYlwtlcZ134r3MgWK5lXnEDd3h9RTcKo7cy6/7/X8bpuFs38WHVhCdQ +01VyLIp1FpqVtfkt69AiSVdrZYeqcahtOZb+56kCAwEAAaNsMGowKAYDVR0RBCEw +H4IXc3J2MDIuY3J0MDEuZXhhbXBsZS5uaWyHBAo1AAIwHQYDVR0OBBYEFHCQlIFK +sr8T1ikakNkzpMV0Kc9ZMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQB3bPQHNgvvboYtQXPguvdM8b2Pd4kajGMuOZOi +Q+5whfFdAWCr5lChXnLjiRN34KX3+icxkx86pzVffVk80iacEvpRK9MxDFrnqL5q +LrKCbELyhnScCshYqGg1c24bDJ47CD+572hh6dNAHardQuMdsBtuuFhgoWhK/wm3 +WFty6DajbRB4x39S9tw5XAV9eq6NP4mPEKZNi1Vqm8ssHQBZmwzDVeCjJWm0KTAv +IL8H9CGIt9BirdfK4ZFFn6JffQf0mLBe1DqShumh+8CbgUbaVu2SR8AaqlU3DjyS +LER6gFUfFXp8xH6t1bClfjNjCSNreELeN6oEp1LtBv7UVjYShbbs/wPqS+J6Qklz +tqvkfUorlGUfsRejvhcLTlM9itPXBA/xGmOypusAMWS0gOmuu2kSBKV9LL2RYiy5 +Wm6v4O4n8IgVi7fOB168a+k+PyPH+clIIGlqjvIXm1j/cjYh7dODFmDs3m/EUEe3 +Yc51wdZgKN69aXzm2w65+nuEJDU= +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.key b/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.key new file mode 100644 index 0000000..3711943 --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/QIBADANBgkqhkiG9w0BAQEFAASCBucwggbjAgEAAoIBgQDOADZuuD/b/pD3 +3uHtQ0sZl3jYrjI8S9WOzR8peOKv0wKVNCxezVSKB3BrYamvIqduz4a2cddNtK/z +8JsoSRiMZohnY0fpzajpXGPAvgiyd4EFg8c6UxvGeoKZ+lRvTzCAUJaSFm4QFsp2 +7snlkGOYmOdYYQkV6UVnifHfIWm2rbckaJIHtm+T+Pu9tZDJV1rlRmzQczM8EG4B +3Eb1hJVdKwPjOg1mWfiSN3hJdDIylvq9BSdD+PmQfOQrNlTA8nf9T+2HAAgjTVeB +oE/2LpygIj32J7I57USOXJJMS7l0uwrEl+OFZin8dTu1PeEiVzMRLpqpQYSC6kS1 +/Dq0iDERRpjC7NtDVXKnn6FlwL8Rp0Qno4sGTwgqLUzJqtU9AyRm5gObnJgaX0Xo +uR3xBUDYPu1ABR76iljFovIqocslfmGMDjzMW0M6fIunZLjFK2sWWQat7Bm1HXNE +L/RsMfFu9FX2RDfu2yD+VJJDKPhEy5+ftiyqYR8vGhUVzGHzuW8CAwEAAQKCAYAM +G58XauT1/URwDT2iQG5NlsWXlsWFHb/zoMLQITbRtslUE7j36YGqiz1kUl0y2gqV +TMVSO+a3voMJB39XItS6i9xAl2lGqLvg23lRftnsA3Il7NTs7K2ZQOIkQr5rvG/R +Wus+surNL0m/K9HaGF6CPZp7a1ipXQijSUxaHRClmBhHn43VvjdYry28vMtBykyh +ZT5IEj1UrnKI0XWqQJy22SxlUqgu9+LQVUpQpu+8YXtjWMYyDJQ+ldijYZIhtR6V +WfLEE2SRWpViHwtZEs5p0E9X8rGQYYdWC1zAh+B0TtPCC3I+MAyjQOVglwUpPQnG +GqRJfJnb4PENdy9DYxEmg/AlrTCuRLcGuGVnaz55KCUN9GbL8ei2EKuTQMdR6Ysd +fKPe2L1FyjG7OmTq+1kWicDdbn++ng51C5fwTmyjOnN5//vy19rgNL11TP9UaDaQ +5/Ox7UaxQZXdskvXelzBAe4gGgwdVO3/WEAJNFyUn+O9iWSdEvdv9AeEGe5G0KEC +gcEA51ZSfPG0y4ckyyMB/BHo1sxkKFwMlLOtKHH+zXQ5mCMaFpHDnSpQ8WxE/0mZ +2qX53YpqZU11SV81CPsUox+Fn4bNyLFpDiJ412/yl/xDRHOaRqdWxz3Wg4ynLbpU +xiwFUcjoff63RelQWZka+XSz/eNzSJJe6UXSuNJ0yCCrKTBMlMEtqocFeOYzBMzj +SWbvvKiM8NYqa3pm9VAaQnQPEiwaVa4XDQZZ4EVGdO4U89M6xlrdA8OXm3Jni9CA +eAOtAoHBAOP2aGVcLDch/tP4Be15g1z1ipFQuvlKF481Fxdjy5zXNGj1n6poUgt2 ++lVt6jhkunR6Sxs4sEoa0QtcSDCfZWygP05pz41dKF8+j7aYwsDMo1v4brUNKa1y +jFwdhd4xb/YG84pNln5diLzXKbAJgDu684H9tEvl0Is3TYp9Ex2YVhDbauxourHt +shYRi3zcea5S3IE1Qx+dyimliCrsp+ufnh4MrUjn9msAt19ZmzWO1TPucPtx5gUz +zwaQl0P1CwKBwQDRSFW9tQjjq7JMl7Ie8bDcSfI+VPAIwvffBCoIgqHsEa1zR5FZ +KMQrdNCCx3oJxWfj1WnllYqKwzf+lO8Zl9XR+SlH67/nyqXZ+OvWNaBBV/f0/URT +YY0kW2WOx+gTlBWH5KL4ASyacbWAKTOvA7Yl9NQBjnGQxdsZ20NNHcjarVhKpu0C +Pb5knpT/PcBNUnOGEFHZO1cK/qQQP9RR1B8iSIXWh3VREjLS4rkX5Z9M6gZdFiym +UBdiyMAGS609Zc0CgcAI55csXm1bufg6T3Xr0NNQzkabZovnMP26mlhMkZlihwWF +FBMolOqfiAY/UAvWKBkgc6Z7abt5KZMA3pnzTEap95iBd6Cj5P+uuMLkXxM8dMHs +1cd9SwZVwCO7dWvFQikdcygQPveh+AVfWwhF2BkqPCNG8KIaVN/QkFh3EGuuvESg +Y/HJSk4ApUhPlF/egL5AEPyMD4iPs5oyBkVLZ/MnQRTsF5KtRmJZy61eDCID9ZBe +dvHy4IAbs+piV0ORZAECgcBsqhBAB1CdUOjj4EVPeEKngGZweQkJPRLKblCLGK8l +QtcSUfrqoxP8b9Ary/I0gbMhWtkUP/kZOZi/GNelswnzdSlxRKdzQvns5vw+jLfl +aw5v2ps600+e11KQ1IMVSdRdwESEBs0IQAJV3lfmpNcdxIwf8EjLjGL+uq4KGylW +z8vfM0/i2GK33hxNrQRXSrTHsiqiKGK78h7S+twll5W8T1ZYFkI1oROZOmMlA/hU +d8ykPRRZ7XjXCmIgCS9TsF8= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.pem b/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.pem new file mode 100644 index 0000000..455655d --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv02.crt02-expired.example.nil.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8c + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 7 11:55:54 2022 GMT + Not After : Dec 8 11:55:54 2022 GMT + Subject: CN=srv02.crt02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:ce:00:36:6e:b8:3f:db:fe:90:f7:de:e1:ed:43: + 4b:19:97:78:d8:ae:32:3c:4b:d5:8e:cd:1f:29:78: + e2:af:d3:02:95:34:2c:5e:cd:54:8a:07:70:6b:61: + a9:af:22:a7:6e:cf:86:b6:71:d7:4d:b4:af:f3:f0: + 9b:28:49:18:8c:66:88:67:63:47:e9:cd:a8:e9:5c: + 63:c0:be:08:b2:77:81:05:83:c7:3a:53:1b:c6:7a: + 82:99:fa:54:6f:4f:30:80:50:96:92:16:6e:10:16: + ca:76:ee:c9:e5:90:63:98:98:e7:58:61:09:15:e9: + 45:67:89:f1:df:21:69:b6:ad:b7:24:68:92:07:b6: + 6f:93:f8:fb:bd:b5:90:c9:57:5a:e5:46:6c:d0:73: + 33:3c:10:6e:01:dc:46:f5:84:95:5d:2b:03:e3:3a: + 0d:66:59:f8:92:37:78:49:74:32:32:96:fa:bd:05: + 27:43:f8:f9:90:7c:e4:2b:36:54:c0:f2:77:fd:4f: + ed:87:00:08:23:4d:57:81:a0:4f:f6:2e:9c:a0:22: + 3d:f6:27:b2:39:ed:44:8e:5c:92:4c:4b:b9:74:bb: + 0a:c4:97:e3:85:66:29:fc:75:3b:b5:3d:e1:22:57: + 33:11:2e:9a:a9:41:84:82:ea:44:b5:fc:3a:b4:88: + 31:11:46:98:c2:ec:db:43:55:72:a7:9f:a1:65:c0: + bf:11:a7:44:27:a3:8b:06:4f:08:2a:2d:4c:c9:aa: + d5:3d:03:24:66:e6:03:9b:9c:98:1a:5f:45:e8:b9: + 1d:f1:05:40:d8:3e:ed:40:05:1e:fa:8a:58:c5:a2: + f2:2a:a1:cb:25:7e:61:8c:0e:3c:cc:5b:43:3a:7c: + 8b:a7:64:b8:c5:2b:6b:16:59:06:ad:ec:19:b5:1d: + 73:44:2f:f4:6c:31:f1:6e:f4:55:f6:44:37:ee:db: + 20:fe:54:92:43:28:f8:44:cb:9f:9f:b6:2c:aa:61: + 1f:2f:1a:15:15:cc:61:f3:b9:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt02-expired.example.nil, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + A7:8A:6D:EA:10:B4:6B:B8:13:16:6B:BA:A0:26:C3:9A:E7:A6:71:7E + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 34:7b:38:92:d9:c1:ba:ed:c7:b3:61:63:e6:d2:11:4e:0c:83: + 8f:97:3a:11:97:51:3e:8d:9b:49:bb:f5:2c:92:d1:c2:e4:3b: + ad:db:69:cc:1f:cf:58:3d:4f:51:97:d1:09:19:2f:22:b5:3d: + e1:0d:e5:65:40:2a:54:19:55:22:11:85:18:1a:08:31:97:d8: + fe:cf:4c:9b:ec:8b:8f:9c:cd:cf:5b:a1:56:e4:1d:e0:79:4b: + ee:6b:1c:0b:60:a8:d8:fd:5c:a8:9d:dc:74:4f:ce:b8:f8:19: + a4:00:db:93:7b:ae:34:55:c6:fb:35:1b:9e:bc:d0:5f:da:8d: + 77:0e:1f:45:89:d4:dd:f1:a9:4e:48:64:d2:4e:b6:4b:57:a0: + 87:cf:a8:30:35:6e:09:91:56:59:9b:01:af:8a:f7:11:8c:d8: + 2e:56:89:eb:a5:a0:6c:d2:56:0c:da:13:4d:36:92:28:50:b1: + e5:cd:64:60:ac:93:f4:98:d7:eb:df:7b:42:89:da:c0:6d:6e: + 75:ae:45:28:9b:e8:de:00:dc:eb:df:ba:4f:63:2a:61:e5:42: + f3:e0:8f:aa:bd:f7:f6:9b:67:1b:ed:1e:a6:ae:4c:81:a2:62: + ff:a8:8f:94:da:a8:9d:27:fa:a4:46:44:2e:13:f2:05:2b:c4: + a6:57:d3:95:1c:ca:f8:e3:d2:0f:28:70:8a:1b:37:4f:b7:c1: + b3:fd:4b:85:ca:9d:8a:bb:62:85:47:66:c7:31:b8:db:c4:5d: + 66:9d:6e:7b:94:07:fa:09:ae:5b:5b:23:31:ba:c8:40:82:4b: + 6a:48:d2:83:0c:5f:b9:62:64:06:16:05:dd:e8:a8:02:eb:d7: + 7a:9b:d9:49:d6:87:0e:16:ca:d6:4e:46:46:e5:37:e4:0d:68: + b7:d2:d6:78:c4:ee:c1:3b:38:8e:83:df:1f:39:63:1c:65:7a: + e0:26:1f:96:8a:57:9d:6b:27:62:6e:40:86:83:29:fd:1f:a1: + 69:2a:92:cf:ab:db +-----BEGIN CERTIFICATE----- +MIIEnjCCAwagAwIBAgIJAMzBGAgmMuGMMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAeFw0yMjEyMDcxMTU1NTRaFw0yMjEyMDgx +MTU1NTRaMCoxKDAmBgNVBAMMH3NydjAyLmNydDAyLWV4cGlyZWQuZXhhbXBsZS5u +aWwwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDOADZuuD/b/pD33uHt +Q0sZl3jYrjI8S9WOzR8peOKv0wKVNCxezVSKB3BrYamvIqduz4a2cddNtK/z8Jso +SRiMZohnY0fpzajpXGPAvgiyd4EFg8c6UxvGeoKZ+lRvTzCAUJaSFm4QFsp27snl +kGOYmOdYYQkV6UVnifHfIWm2rbckaJIHtm+T+Pu9tZDJV1rlRmzQczM8EG4B3Eb1 +hJVdKwPjOg1mWfiSN3hJdDIylvq9BSdD+PmQfOQrNlTA8nf9T+2HAAgjTVeBoE/2 +LpygIj32J7I57USOXJJMS7l0uwrEl+OFZin8dTu1PeEiVzMRLpqpQYSC6kS1/Dq0 +iDERRpjC7NtDVXKnn6FlwL8Rp0Qno4sGTwgqLUzJqtU9AyRm5gObnJgaX0XouR3x +BUDYPu1ABR76iljFovIqocslfmGMDjzMW0M6fIunZLjFK2sWWQat7Bm1HXNEL/Rs +MfFu9FX2RDfu2yD+VJJDKPhEy5+ftiyqYR8vGhUVzGHzuW8CAwEAAaN0MHIwMAYD +VR0RBCkwJ4Ifc3J2MDIuY3J0MDItZXhwaXJlZC5leGFtcGxlLm5pbIcECjUAAjAd +BgNVHQ4EFgQUp4pt6hC0a7gTFmu6oCbDmuemcX4wHwYDVR0jBBgwFoAUfInoXOvl +H3JIBMWP+5IInPVgJjkwDQYJKoZIhvcNAQELBQADggGBADR7OJLZwbrtx7NhY+bS +EU4Mg4+XOhGXUT6Nm0m79SyS0cLkO63bacwfz1g9T1GX0QkZLyK1PeEN5WVAKlQZ +VSIRhRgaCDGX2P7PTJvsi4+czc9boVbkHeB5S+5rHAtgqNj9XKid3HRPzrj4GaQA +25N7rjRVxvs1G5680F/ajXcOH0WJ1N3xqU5IZNJOtktXoIfPqDA1bgmRVlmbAa+K +9xGM2C5WieuloGzSVgzaE002kihQseXNZGCsk/SY1+vfe0KJ2sBtbnWuRSib6N4A +3Ovfuk9jKmHlQvPgj6q99/abZxvtHqauTIGiYv+oj5TaqJ0n+qRGRC4T8gUrxKZX +05Ucyvjj0g8ocIobN0+3wbP9S4XKnYq7YoVHZscxuNvEXWadbnuUB/oJrltbIzG6 +yECCS2pI0oMMX7liZAYWBd3oqALr13qb2UnWhw4WytZORkblN+QNaLfS1njE7sE7 +OI6D3x85YxxleuAmH5aKV51rJ2JuQIaDKf0foWkqks+r2w== +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.key b/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.key new file mode 100644 index 0000000..3b5c4b1 --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCN5ooQbwaPsuX0 +3hRN1DwaIQP+MgLWbQolNT1QAHHWe3XR4AQ2INo5253fGf5bw+LQcsQNvlfYwj8w +qJmxwxrIlqWKDHrm6Ss+yfn1RrLMFEzm0WUlGfssK+RtALp8f/YHJBcwQssE6ZQ2 +4xiLYHdsaNOeYoGCZCQs6bq40EAv5v3p+qoUg28mFsG3s239Sj+Poanme73BYKFr +/wKTzAiTnh4MozEpIHTlN0bYQRDHEfTY50N8Tbz7/Tk6eY7CC/4h3xbC/BCzm9rM +gNNkVm8Jr/Zzi8tk5P7FTIVOw+2kCgpT9r6NXnpCT82wIaSO5EX+KPZNKVjbSrRw +ej8L22Q+I6WZRxF7LGaDqXknCUVyrEr6NW8fZNSrzwmQknFK0QKAsauwGewBxqcx +K0vcOwkArZoSyunNVL2WI6MULkBYM1gvcAXJxijxPtSUE9sJs2N4b1dy6B8ob3y2 +JXZOqxHJpdfKMgBfXhSuU2UTNyvSmDzUR3RAz/8brVk1wdHTpv8CAwEAAQKCAYAZ +f+E1nM4ACrT6MOJTLh1y0JYIGvKZl9Sn5Q5Ujw/l7B+7DFeVZofwt7+B9QjZcrUS +ol0K3zaoFBgI5XNhF197xl6PFTkMv7/us5sAcaj1tXwwSlazuRyCzoxo7iWU8+XB +WMH2ATq8ckEZL+wcN8SeLaRBpRAC334EuCe+yGWQdiEQ5+OidhAGNzaujUbpqmsL +o5CFg50Q4A2B+7x51MOBy3s46CaQbm2zNyC7Ac5DB74JMF3XO50HZ3TeRjPaOQ84 +f8fWoFTqfwS3h7SIswsWpZRa2Lz9Q3FTQjtZ54ZVdnIqQblXnFh5yTw5ERmVWgXZ +EGmUPqMHyhOPRM2kTIvs4GFs+wAJiy2keMgWd39ZT4Z0qXlOrYpTKpRxoG49QS/v +zzddU3FgcjrrA3PZqMse9/elBWaFGxa/3Y8FI5wMaSL1Y7z+sTozF5qb+HGwd71M +09/N2vU3M4dqgSfEjsCPxeG+/6z693nyzrqYh0D0LeEl+ZsyHsTfkAUrFG330fEC +gcEAuhy8LM6sdoMTLYPkAxTs4mUfZtZS3EFQsPyjbcJXbOeugNUphEMr6mik/yYf +fkOKz7VZ6CR8ugX4mLGHB57YIX5QjoPN0Obu1BeCxspAq36XDYrRcJM5eEsWdkfB +43YN4xzMT0uH+660hMnrvxU1kCAVjF+e4AUwFUY/2879LtQZZbdOupwLEmYAaYUI +RyWLmdDPf8W1R38K7QRLG6VCjwdo0reEYIOqj/01fErzKwRdRYbjMJUtUZ8Iy20o +O8vnAoHBAMMvqc9oaxFicVsHMZU3mc91jcOVJqvNCINP7y3fNwcvwcdwXecNFoTn +ygTWgkBDRzueZcxJwtcZOtiq2o4L+zlEZinFyROmJqKVcy+g/hvepj9mbT+5CwYx +/J6AKWwFAIylFbWmqVMeBsZp4K/9qQN+s4V2MWsMNrqoVFCjlBxef4grIbyJSOzU +DZVqz97vA5IqWnAQU53BPUoVns3u2jHkgNDMdMPIdhx++l7++FinNluWheV5KYOF +T1OJe6gpKQKBwQCWubbcQvUBdd4OOoZqyIOgRm1MB79LicojzDc/KOlM1cVJqVja +ONxUFzOpP+K5i1HcLe8GRqaMsVFHuF63GTnIxlfPU4dX6+737aKIBDyjpv4Ghaph +FZqxhX5HhI3N/Un56NS+U1lpx2+DK1S1iCO8+X76FGbC3vC2ChKlndkGF9gJvI8S +KlX9LIag7pBprkqE48tom2HY6Vab5aI+XXSuCT4niWC4GWoE+vhaFQkiiYJQUJGm +QupU9AtXVKwE4XkCgcEAtef35Fq2Xi9W4bUkmqKE8HnoMv0QW1DsvCSFDkVXrZTu +jgbFHQ5vjFHRTwzzuxx4iLGowemEcp8K3t7sbTHxYn/Cju/L5EoW+7M49IygBi1M +1w2Ih7jW82EmxDlBYXCQAIPiZbb7W4FCYyxNwPcwyxcMDDgI+nEZmIBEhBrPcFkJ +lkhMWr+/fShruHMhY+1xcImUW5h7tSxhCGh55gbSx2jkPLQvpj9vBEO650nM/iJo +YJc6FpEDBZX6Rip9Wk1xAoHAUcms1tuGcDRTtzCRdKOl0PiZTr8qzwJPzZlDxrsA +KqcONMhhiFMXneu4xj/M09EVMiElcf1xxs0CtD/1aod3kK5IMq4D+ck2rd/1QKed +FH5jOesE7PRZtW4Du8PCsi2D5V8dR/yBLy/525unqTTCCEZWZ1hrZqStR3nNFcNQ +aC6hhkMTr2GqFJsfNowFQ9gto4kn2XsIpvMW14Gqm0rW+K0i3HDjXk7R7RTDSO5J +B2yNl2lHM+2aSG8A3vug23aE +-----END PRIVATE KEY----- diff --git a/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.pem b/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.pem new file mode 100644 index 0000000..7a8fbc1 --- /dev/null +++ b/bin/tests/system/forward/CA/certs/srv04.crt01.example.nil.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 8 11:58:45 2022 GMT + Not After : Nov 30 11:58:45 2052 GMT + Subject: CN=srv04.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:8d:e6:8a:10:6f:06:8f:b2:e5:f4:de:14:4d:d4: + 3c:1a:21:03:fe:32:02:d6:6d:0a:25:35:3d:50:00: + 71:d6:7b:75:d1:e0:04:36:20:da:39:db:9d:df:19: + fe:5b:c3:e2:d0:72:c4:0d:be:57:d8:c2:3f:30:a8: + 99:b1:c3:1a:c8:96:a5:8a:0c:7a:e6:e9:2b:3e:c9: + f9:f5:46:b2:cc:14:4c:e6:d1:65:25:19:fb:2c:2b: + e4:6d:00:ba:7c:7f:f6:07:24:17:30:42:cb:04:e9: + 94:36:e3:18:8b:60:77:6c:68:d3:9e:62:81:82:64: + 24:2c:e9:ba:b8:d0:40:2f:e6:fd:e9:fa:aa:14:83: + 6f:26:16:c1:b7:b3:6d:fd:4a:3f:8f:a1:a9:e6:7b: + bd:c1:60:a1:6b:ff:02:93:cc:08:93:9e:1e:0c:a3: + 31:29:20:74:e5:37:46:d8:41:10:c7:11:f4:d8:e7: + 43:7c:4d:bc:fb:fd:39:3a:79:8e:c2:0b:fe:21:df: + 16:c2:fc:10:b3:9b:da:cc:80:d3:64:56:6f:09:af: + f6:73:8b:cb:64:e4:fe:c5:4c:85:4e:c3:ed:a4:0a: + 0a:53:f6:be:8d:5e:7a:42:4f:cd:b0:21:a4:8e:e4: + 45:fe:28:f6:4d:29:58:db:4a:b4:70:7a:3f:0b:db: + 64:3e:23:a5:99:47:11:7b:2c:66:83:a9:79:27:09: + 45:72:ac:4a:fa:35:6f:1f:64:d4:ab:cf:09:90:92: + 71:4a:d1:02:80:b1:ab:b0:19:ec:01:c6:a7:31:2b: + 4b:dc:3b:09:00:ad:9a:12:ca:e9:cd:54:bd:96:23: + a3:14:2e:40:58:33:58:2f:70:05:c9:c6:28:f1:3e: + d4:94:13:db:09:b3:63:78:6f:57:72:e8:1f:28:6f: + 7c:b6:25:76:4e:ab:11:c9:a5:d7:ca:32:00:5f:5e: + 14:ae:53:65:13:37:2b:d2:98:3c:d4:47:74:40:cf: + ff:1b:ad:59:35:c1:d1:d3:a6:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv04.crt01.example.nil, IP Address:10.53.0.4 + X509v3 Subject Key Identifier: + CA:83:06:FB:3E:57:50:DD:FD:BF:00:5A:60:E2:6D:98:71:CD:2C:F2 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 6f:24:c5:ba:8e:62:5d:58:50:a5:25:a1:fc:41:fc:18:cb:7c: + 11:02:0a:ad:7f:13:2a:20:07:92:5a:82:c0:92:9d:35:40:b0: + c9:85:5a:23:26:fb:55:b7:99:7a:18:a7:ae:b4:6e:a2:29:f8: + 25:70:fa:3e:bf:b0:ec:91:d7:46:55:55:ab:fd:22:a6:c1:b4: + 50:92:27:ea:d8:a1:71:ec:14:84:69:0a:c9:de:3f:c1:63:94: + 17:5e:78:e7:85:34:80:bf:c3:58:f1:4d:fb:0c:b4:2e:2b:9c: + 66:15:1f:e3:d6:3a:c1:95:b1:f5:f2:9c:dc:99:cb:d5:39:35: + 6a:bf:bc:f4:81:9d:7c:4c:c1:76:f8:4d:26:ab:f4:f0:50:b2: + f9:41:65:6c:df:9d:16:57:e3:dc:7d:85:0a:14:5f:20:ea:08: + 5e:ab:3c:75:ae:f6:7e:55:62:3b:4c:4a:c7:48:4f:24:f2:78: + e6:99:52:76:87:6e:b3:08:7c:d6:4e:41:72:8f:ed:f1:5a:1a: + 20:e7:c2:cd:a0:6f:04:6c:f1:71:87:21:00:49:29:c1:fb:bd: + 08:a7:51:34:bb:e0:f1:f7:59:3d:b8:9e:c6:48:06:fe:e6:ea: + 30:8b:65:8f:d2:31:c5:d6:4e:a8:22:7e:fc:85:05:3d:e4:7c: + 38:54:07:46:cc:94:8e:a5:d3:4c:09:71:6e:60:63:e4:6a:8e: + aa:c2:81:df:31:37:2a:96:b3:53:36:a2:76:44:59:18:33:81: + 6c:24:84:a3:61:68:63:a2:02:bd:fd:b2:9c:db:0f:cc:a6:44: + 54:c6:2d:13:fb:96:80:63:e7:e9:2e:36:3c:00:34:3e:62:5d: + fe:59:95:cb:b2:d0:cc:9a:69:ce:00:cc:59:c3:f7:79:3a:4f: + 95:e9:64:c9:ad:28:96:e2:80:dd:59:45:29:6c:ed:0d:6e:4e: + 50:69:6e:ef:50:32:4e:5c:af:63:39:57:90:08:0f:b9:4e:ba: + b2:24:ae:bb:78:39 +-----BEGIN CERTIFICATE----- +MIIEkDCCAvigAwIBAgIJAMzBGAgmMuGNMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yMjEyMDgxMTU4NDVaGA8yMDUyMTEz +MDExNTg0NVowIjEgMB4GA1UEAwwXc3J2MDQuY3J0MDEuZXhhbXBsZS5uaWwwggGi +MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCN5ooQbwaPsuX03hRN1DwaIQP+ +MgLWbQolNT1QAHHWe3XR4AQ2INo5253fGf5bw+LQcsQNvlfYwj8wqJmxwxrIlqWK +DHrm6Ss+yfn1RrLMFEzm0WUlGfssK+RtALp8f/YHJBcwQssE6ZQ24xiLYHdsaNOe +YoGCZCQs6bq40EAv5v3p+qoUg28mFsG3s239Sj+Poanme73BYKFr/wKTzAiTnh4M +ozEpIHTlN0bYQRDHEfTY50N8Tbz7/Tk6eY7CC/4h3xbC/BCzm9rMgNNkVm8Jr/Zz +i8tk5P7FTIVOw+2kCgpT9r6NXnpCT82wIaSO5EX+KPZNKVjbSrRwej8L22Q+I6WZ +RxF7LGaDqXknCUVyrEr6NW8fZNSrzwmQknFK0QKAsauwGewBxqcxK0vcOwkArZoS +yunNVL2WI6MULkBYM1gvcAXJxijxPtSUE9sJs2N4b1dy6B8ob3y2JXZOqxHJpdfK +MgBfXhSuU2UTNyvSmDzUR3RAz/8brVk1wdHTpv8CAwEAAaNsMGowKAYDVR0RBCEw +H4IXc3J2MDQuY3J0MDEuZXhhbXBsZS5uaWyHBAo1AAQwHQYDVR0OBBYEFMqDBvs+ +V1Dd/b8AWmDibZhxzSzyMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQBvJMW6jmJdWFClJaH8QfwYy3wRAgqtfxMqIAeS +WoLAkp01QLDJhVojJvtVt5l6GKeutG6iKfglcPo+v7DskddGVVWr/SKmwbRQkifq +2KFx7BSEaQrJ3j/BY5QXXnjnhTSAv8NY8U37DLQuK5xmFR/j1jrBlbH18pzcmcvV +OTVqv7z0gZ18TMF2+E0mq/TwULL5QWVs350WV+PcfYUKFF8g6gheqzx1rvZ+VWI7 +TErHSE8k8njmmVJ2h26zCHzWTkFyj+3xWhog58LNoG8EbPFxhyEASSnB+70Ip1E0 +u+Dx91k9uJ7GSAb+5uowi2WP0jHF1k6oIn78hQU95Hw4VAdGzJSOpdNMCXFuYGPk +ao6qwoHfMTcqlrNTNqJ2RFkYM4FsJISjYWhjogK9/bKc2w/MpkRUxi0T+5aAY+fp +LjY8ADQ+Yl3+WZXLstDMmmnOAMxZw/d5Ok+V6WTJrSiW4oDdWUUpbO0Nbk5QaW7v +UDJOXK9jOVeQCA+5TrqyJK67eDk= +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/index.txt b/bin/tests/system/forward/CA/index.txt new file mode 100644 index 0000000..1d7c495 --- /dev/null +++ b/bin/tests/system/forward/CA/index.txt @@ -0,0 +1,3 @@ +V 20521130115243Z CCC118082632E18B unknown /CN=srv02.crt01.example.nil +V 221208115554Z CCC118082632E18C unknown /CN=srv02.crt02-expired.example.nil +V 20521130115845Z CCC118082632E18D unknown /CN=srv04.crt01.example.nil diff --git a/bin/tests/system/forward/CA/index.txt.attr b/bin/tests/system/forward/CA/index.txt.attr new file mode 100644 index 0000000..8f7e63a --- /dev/null +++ b/bin/tests/system/forward/CA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/bin/tests/system/forward/CA/newcerts/CCC118082632E18B.pem b/bin/tests/system/forward/CA/newcerts/CCC118082632E18B.pem new file mode 100644 index 0000000..ea6030f --- /dev/null +++ b/bin/tests/system/forward/CA/newcerts/CCC118082632E18B.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8b + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 8 11:52:43 2022 GMT + Not After : Nov 30 11:52:43 2052 GMT + Subject: CN=srv02.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:93:ea:3a:43:83:ff:92:80:06:be:4e:a0:53:5d: + 0b:9d:c9:b1:b8:fe:d5:cc:dc:af:94:7a:ab:ba:13: + 0f:c0:b6:99:71:78:90:b1:7f:41:07:85:59:26:90: + 14:88:7b:fc:0c:64:70:37:f3:2a:39:80:80:48:4e: + 5f:77:74:26:fa:aa:dd:3f:7b:8e:63:b5:a6:ce:bc: + bc:5a:aa:1d:2c:b0:9a:54:8c:03:46:8b:e6:19:52: + 51:48:16:2d:88:ac:df:73:bb:5d:86:f5:80:ff:12: + 93:d1:53:7f:3b:69:35:56:6d:81:8a:ea:4b:bd:75: + d5:bf:a2:b8:f9:98:17:c7:47:e7:5a:0a:47:a0:00: + 3d:5c:77:42:95:ef:60:ea:e2:2c:ab:97:a9:f3:1d: + c7:a7:f9:aa:2f:5d:03:b6:5b:48:87:b4:27:4b:99: + b3:e3:99:f8:cd:bb:51:88:f4:1e:34:d5:3e:e3:12: + 3c:2d:c0:b7:2a:9d:0b:73:7f:3a:ad:27:97:17:58: + 51:70:08:87:75:42:d2:87:47:67:c0:db:c6:b9:f8: + b0:31:a6:cb:15:24:7b:54:06:fd:92:e6:24:71:3f: + 55:02:02:71:f2:47:7f:e5:fe:be:d4:5f:1e:b5:58: + f7:09:fa:60:e3:36:25:bd:f4:91:58:e6:f2:fd:f1: + 5a:00:e8:77:26:dc:2d:20:10:fc:c7:a2:16:0a:e1: + 59:e4:e5:a0:72:d4:23:88:a7:56:71:1d:69:f5:1e: + e4:c1:ec:87:7a:ef:19:dd:df:fa:25:f0:3b:6f:c5: + 5f:14:20:26:fa:9b:e0:af:51:c4:18:3f:3c:49:7d: + 26:25:c2:d9:5c:67:5d:f8:af:73:20:58:ae:65:5e: + 71:03:77:78:7d:45:37:0a:a3:b7:32:eb:fe:ff:5f: + c6:e9:b8:5b:37:f1:61:d5:84:27:50:d3:55:72:2c: + 8a:75:16:9a:95:b5:f9:2d:eb:d0:22:49:57:6b:65: + 87:aa:71:a8:6d:39:96:fe:e7:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.nil, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 70:90:94:81:4A:B2:BF:13:D6:29:1A:90:D9:33:A4:C5:74:29:CF:59 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 77:6c:f4:07:36:0b:ef:6e:86:2d:41:73:e0:ba:f7:4c:f1:bd: + 8f:77:89:1a:8c:63:2e:39:93:a2:43:ee:70:85:f1:5d:01:60: + ab:e6:50:a1:5e:72:e3:89:13:77:e0:a5:f7:fa:27:31:93:1f: + 3a:a7:35:5f:7d:59:3c:d2:26:9c:12:fa:51:2b:d3:31:0c:5a: + e7:a8:be:6a:2e:b2:82:6c:42:f2:86:74:9c:0a:c8:58:a8:68: + 35:73:6e:1b:0c:9e:3b:08:3f:b9:ef:68:61:e9:d3:40:1d:aa: + dd:42:e3:1d:b0:1b:6e:b8:58:60:a1:68:4a:ff:09:b7:58:5b: + 72:e8:36:a3:6d:10:78:c7:7f:52:f6:dc:39:5c:05:7d:7a:ae: + 8d:3f:89:8f:10:a6:4d:8b:55:6a:9b:cb:2c:1d:00:59:9b:0c: + c3:55:e0:a3:25:69:b4:29:30:2f:20:bf:07:f4:21:88:b7:d0: + 62:ad:d7:ca:e1:91:45:9f:a2:5f:7d:07:f4:98:b0:5e:d4:3a: + 92:86:e9:a1:fb:c0:9b:81:46:da:56:ed:92:47:c0:1a:aa:55: + 37:0e:3c:92:2c:44:7a:80:55:1f:15:7a:7c:c4:7e:ad:d5:b0: + a5:7e:33:63:09:23:6b:78:42:de:37:aa:04:a7:52:ed:06:fe: + d4:56:36:12:85:b6:ec:ff:03:ea:4b:e2:7a:42:49:73:b6:ab: + e4:7d:4a:2b:94:65:1f:b1:17:a3:be:17:0b:4e:53:3d:8a:d3: + d7:04:0f:f1:1a:63:b2:a6:eb:00:31:64:b4:80:e9:ae:bb:69: + 12:04:a5:7d:2c:bd:91:62:2c:b9:5a:6e:af:e0:ee:27:f0:88: + 15:8b:b7:ce:07:5e:bc:6b:e9:3e:3f:23:c7:f9:c9:48:20:69: + 6a:8e:f2:17:9b:58:ff:72:36:21:ed:d3:83:16:60:ec:de:6f: + c4:50:47:b7:61:ce:75:c1:d6:60:28:de:bd:69:7c:e6:db:0e: + b9:fa:7b:84:24:35 +-----BEGIN CERTIFICATE----- +MIIEkDCCAvigAwIBAgIJAMzBGAgmMuGLMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yMjEyMDgxMTUyNDNaGA8yMDUyMTEz +MDExNTI0M1owIjEgMB4GA1UEAwwXc3J2MDIuY3J0MDEuZXhhbXBsZS5uaWwwggGi +MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCT6jpDg/+SgAa+TqBTXQudybG4 +/tXM3K+Uequ6Ew/AtplxeJCxf0EHhVkmkBSIe/wMZHA38yo5gIBITl93dCb6qt0/ +e45jtabOvLxaqh0ssJpUjANGi+YZUlFIFi2IrN9zu12G9YD/EpPRU387aTVWbYGK +6ku9ddW/orj5mBfHR+daCkegAD1cd0KV72Dq4iyrl6nzHcen+aovXQO2W0iHtCdL +mbPjmfjNu1GI9B401T7jEjwtwLcqnQtzfzqtJ5cXWFFwCId1QtKHR2fA28a5+LAx +pssVJHtUBv2S5iRxP1UCAnHyR3/l/r7UXx61WPcJ+mDjNiW99JFY5vL98VoA6Hcm +3C0gEPzHohYK4Vnk5aBy1COIp1ZxHWn1HuTB7Id67xnd3/ol8DtvxV8UICb6m+Cv +UcQYPzxJfSYlwtlcZ134r3MgWK5lXnEDd3h9RTcKo7cy6/7/X8bpuFs38WHVhCdQ +01VyLIp1FpqVtfkt69AiSVdrZYeqcahtOZb+56kCAwEAAaNsMGowKAYDVR0RBCEw +H4IXc3J2MDIuY3J0MDEuZXhhbXBsZS5uaWyHBAo1AAIwHQYDVR0OBBYEFHCQlIFK +sr8T1ikakNkzpMV0Kc9ZMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQB3bPQHNgvvboYtQXPguvdM8b2Pd4kajGMuOZOi +Q+5whfFdAWCr5lChXnLjiRN34KX3+icxkx86pzVffVk80iacEvpRK9MxDFrnqL5q +LrKCbELyhnScCshYqGg1c24bDJ47CD+572hh6dNAHardQuMdsBtuuFhgoWhK/wm3 +WFty6DajbRB4x39S9tw5XAV9eq6NP4mPEKZNi1Vqm8ssHQBZmwzDVeCjJWm0KTAv +IL8H9CGIt9BirdfK4ZFFn6JffQf0mLBe1DqShumh+8CbgUbaVu2SR8AaqlU3DjyS +LER6gFUfFXp8xH6t1bClfjNjCSNreELeN6oEp1LtBv7UVjYShbbs/wPqS+J6Qklz +tqvkfUorlGUfsRejvhcLTlM9itPXBA/xGmOypusAMWS0gOmuu2kSBKV9LL2RYiy5 +Wm6v4O4n8IgVi7fOB168a+k+PyPH+clIIGlqjvIXm1j/cjYh7dODFmDs3m/EUEe3 +Yc51wdZgKN69aXzm2w65+nuEJDU= +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/newcerts/CCC118082632E18C.pem b/bin/tests/system/forward/CA/newcerts/CCC118082632E18C.pem new file mode 100644 index 0000000..455655d --- /dev/null +++ b/bin/tests/system/forward/CA/newcerts/CCC118082632E18C.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8c + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 7 11:55:54 2022 GMT + Not After : Dec 8 11:55:54 2022 GMT + Subject: CN=srv02.crt02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:ce:00:36:6e:b8:3f:db:fe:90:f7:de:e1:ed:43: + 4b:19:97:78:d8:ae:32:3c:4b:d5:8e:cd:1f:29:78: + e2:af:d3:02:95:34:2c:5e:cd:54:8a:07:70:6b:61: + a9:af:22:a7:6e:cf:86:b6:71:d7:4d:b4:af:f3:f0: + 9b:28:49:18:8c:66:88:67:63:47:e9:cd:a8:e9:5c: + 63:c0:be:08:b2:77:81:05:83:c7:3a:53:1b:c6:7a: + 82:99:fa:54:6f:4f:30:80:50:96:92:16:6e:10:16: + ca:76:ee:c9:e5:90:63:98:98:e7:58:61:09:15:e9: + 45:67:89:f1:df:21:69:b6:ad:b7:24:68:92:07:b6: + 6f:93:f8:fb:bd:b5:90:c9:57:5a:e5:46:6c:d0:73: + 33:3c:10:6e:01:dc:46:f5:84:95:5d:2b:03:e3:3a: + 0d:66:59:f8:92:37:78:49:74:32:32:96:fa:bd:05: + 27:43:f8:f9:90:7c:e4:2b:36:54:c0:f2:77:fd:4f: + ed:87:00:08:23:4d:57:81:a0:4f:f6:2e:9c:a0:22: + 3d:f6:27:b2:39:ed:44:8e:5c:92:4c:4b:b9:74:bb: + 0a:c4:97:e3:85:66:29:fc:75:3b:b5:3d:e1:22:57: + 33:11:2e:9a:a9:41:84:82:ea:44:b5:fc:3a:b4:88: + 31:11:46:98:c2:ec:db:43:55:72:a7:9f:a1:65:c0: + bf:11:a7:44:27:a3:8b:06:4f:08:2a:2d:4c:c9:aa: + d5:3d:03:24:66:e6:03:9b:9c:98:1a:5f:45:e8:b9: + 1d:f1:05:40:d8:3e:ed:40:05:1e:fa:8a:58:c5:a2: + f2:2a:a1:cb:25:7e:61:8c:0e:3c:cc:5b:43:3a:7c: + 8b:a7:64:b8:c5:2b:6b:16:59:06:ad:ec:19:b5:1d: + 73:44:2f:f4:6c:31:f1:6e:f4:55:f6:44:37:ee:db: + 20:fe:54:92:43:28:f8:44:cb:9f:9f:b6:2c:aa:61: + 1f:2f:1a:15:15:cc:61:f3:b9:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt02-expired.example.nil, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + A7:8A:6D:EA:10:B4:6B:B8:13:16:6B:BA:A0:26:C3:9A:E7:A6:71:7E + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 34:7b:38:92:d9:c1:ba:ed:c7:b3:61:63:e6:d2:11:4e:0c:83: + 8f:97:3a:11:97:51:3e:8d:9b:49:bb:f5:2c:92:d1:c2:e4:3b: + ad:db:69:cc:1f:cf:58:3d:4f:51:97:d1:09:19:2f:22:b5:3d: + e1:0d:e5:65:40:2a:54:19:55:22:11:85:18:1a:08:31:97:d8: + fe:cf:4c:9b:ec:8b:8f:9c:cd:cf:5b:a1:56:e4:1d:e0:79:4b: + ee:6b:1c:0b:60:a8:d8:fd:5c:a8:9d:dc:74:4f:ce:b8:f8:19: + a4:00:db:93:7b:ae:34:55:c6:fb:35:1b:9e:bc:d0:5f:da:8d: + 77:0e:1f:45:89:d4:dd:f1:a9:4e:48:64:d2:4e:b6:4b:57:a0: + 87:cf:a8:30:35:6e:09:91:56:59:9b:01:af:8a:f7:11:8c:d8: + 2e:56:89:eb:a5:a0:6c:d2:56:0c:da:13:4d:36:92:28:50:b1: + e5:cd:64:60:ac:93:f4:98:d7:eb:df:7b:42:89:da:c0:6d:6e: + 75:ae:45:28:9b:e8:de:00:dc:eb:df:ba:4f:63:2a:61:e5:42: + f3:e0:8f:aa:bd:f7:f6:9b:67:1b:ed:1e:a6:ae:4c:81:a2:62: + ff:a8:8f:94:da:a8:9d:27:fa:a4:46:44:2e:13:f2:05:2b:c4: + a6:57:d3:95:1c:ca:f8:e3:d2:0f:28:70:8a:1b:37:4f:b7:c1: + b3:fd:4b:85:ca:9d:8a:bb:62:85:47:66:c7:31:b8:db:c4:5d: + 66:9d:6e:7b:94:07:fa:09:ae:5b:5b:23:31:ba:c8:40:82:4b: + 6a:48:d2:83:0c:5f:b9:62:64:06:16:05:dd:e8:a8:02:eb:d7: + 7a:9b:d9:49:d6:87:0e:16:ca:d6:4e:46:46:e5:37:e4:0d:68: + b7:d2:d6:78:c4:ee:c1:3b:38:8e:83:df:1f:39:63:1c:65:7a: + e0:26:1f:96:8a:57:9d:6b:27:62:6e:40:86:83:29:fd:1f:a1: + 69:2a:92:cf:ab:db +-----BEGIN CERTIFICATE----- +MIIEnjCCAwagAwIBAgIJAMzBGAgmMuGMMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAeFw0yMjEyMDcxMTU1NTRaFw0yMjEyMDgx +MTU1NTRaMCoxKDAmBgNVBAMMH3NydjAyLmNydDAyLWV4cGlyZWQuZXhhbXBsZS5u +aWwwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDOADZuuD/b/pD33uHt +Q0sZl3jYrjI8S9WOzR8peOKv0wKVNCxezVSKB3BrYamvIqduz4a2cddNtK/z8Jso +SRiMZohnY0fpzajpXGPAvgiyd4EFg8c6UxvGeoKZ+lRvTzCAUJaSFm4QFsp27snl +kGOYmOdYYQkV6UVnifHfIWm2rbckaJIHtm+T+Pu9tZDJV1rlRmzQczM8EG4B3Eb1 +hJVdKwPjOg1mWfiSN3hJdDIylvq9BSdD+PmQfOQrNlTA8nf9T+2HAAgjTVeBoE/2 +LpygIj32J7I57USOXJJMS7l0uwrEl+OFZin8dTu1PeEiVzMRLpqpQYSC6kS1/Dq0 +iDERRpjC7NtDVXKnn6FlwL8Rp0Qno4sGTwgqLUzJqtU9AyRm5gObnJgaX0XouR3x +BUDYPu1ABR76iljFovIqocslfmGMDjzMW0M6fIunZLjFK2sWWQat7Bm1HXNEL/Rs +MfFu9FX2RDfu2yD+VJJDKPhEy5+ftiyqYR8vGhUVzGHzuW8CAwEAAaN0MHIwMAYD +VR0RBCkwJ4Ifc3J2MDIuY3J0MDItZXhwaXJlZC5leGFtcGxlLm5pbIcECjUAAjAd +BgNVHQ4EFgQUp4pt6hC0a7gTFmu6oCbDmuemcX4wHwYDVR0jBBgwFoAUfInoXOvl +H3JIBMWP+5IInPVgJjkwDQYJKoZIhvcNAQELBQADggGBADR7OJLZwbrtx7NhY+bS +EU4Mg4+XOhGXUT6Nm0m79SyS0cLkO63bacwfz1g9T1GX0QkZLyK1PeEN5WVAKlQZ +VSIRhRgaCDGX2P7PTJvsi4+czc9boVbkHeB5S+5rHAtgqNj9XKid3HRPzrj4GaQA +25N7rjRVxvs1G5680F/ajXcOH0WJ1N3xqU5IZNJOtktXoIfPqDA1bgmRVlmbAa+K +9xGM2C5WieuloGzSVgzaE002kihQseXNZGCsk/SY1+vfe0KJ2sBtbnWuRSib6N4A +3Ovfuk9jKmHlQvPgj6q99/abZxvtHqauTIGiYv+oj5TaqJ0n+qRGRC4T8gUrxKZX +05Ucyvjj0g8ocIobN0+3wbP9S4XKnYq7YoVHZscxuNvEXWadbnuUB/oJrltbIzG6 +yECCS2pI0oMMX7liZAYWBd3oqALr13qb2UnWhw4WytZORkblN+QNaLfS1njE7sE7 +OI6D3x85YxxleuAmH5aKV51rJ2JuQIaDKf0foWkqks+r2w== +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/newcerts/CCC118082632E18D.pem b/bin/tests/system/forward/CA/newcerts/CCC118082632E18D.pem new file mode 100644 index 0000000..7a8fbc1 --- /dev/null +++ b/bin/tests/system/forward/CA/newcerts/CCC118082632E18D.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + cc:c1:18:08:26:32:e1:8d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Dec 8 11:58:45 2022 GMT + Not After : Nov 30 11:58:45 2052 GMT + Subject: CN=srv04.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (3072 bit) + Modulus: + 00:8d:e6:8a:10:6f:06:8f:b2:e5:f4:de:14:4d:d4: + 3c:1a:21:03:fe:32:02:d6:6d:0a:25:35:3d:50:00: + 71:d6:7b:75:d1:e0:04:36:20:da:39:db:9d:df:19: + fe:5b:c3:e2:d0:72:c4:0d:be:57:d8:c2:3f:30:a8: + 99:b1:c3:1a:c8:96:a5:8a:0c:7a:e6:e9:2b:3e:c9: + f9:f5:46:b2:cc:14:4c:e6:d1:65:25:19:fb:2c:2b: + e4:6d:00:ba:7c:7f:f6:07:24:17:30:42:cb:04:e9: + 94:36:e3:18:8b:60:77:6c:68:d3:9e:62:81:82:64: + 24:2c:e9:ba:b8:d0:40:2f:e6:fd:e9:fa:aa:14:83: + 6f:26:16:c1:b7:b3:6d:fd:4a:3f:8f:a1:a9:e6:7b: + bd:c1:60:a1:6b:ff:02:93:cc:08:93:9e:1e:0c:a3: + 31:29:20:74:e5:37:46:d8:41:10:c7:11:f4:d8:e7: + 43:7c:4d:bc:fb:fd:39:3a:79:8e:c2:0b:fe:21:df: + 16:c2:fc:10:b3:9b:da:cc:80:d3:64:56:6f:09:af: + f6:73:8b:cb:64:e4:fe:c5:4c:85:4e:c3:ed:a4:0a: + 0a:53:f6:be:8d:5e:7a:42:4f:cd:b0:21:a4:8e:e4: + 45:fe:28:f6:4d:29:58:db:4a:b4:70:7a:3f:0b:db: + 64:3e:23:a5:99:47:11:7b:2c:66:83:a9:79:27:09: + 45:72:ac:4a:fa:35:6f:1f:64:d4:ab:cf:09:90:92: + 71:4a:d1:02:80:b1:ab:b0:19:ec:01:c6:a7:31:2b: + 4b:dc:3b:09:00:ad:9a:12:ca:e9:cd:54:bd:96:23: + a3:14:2e:40:58:33:58:2f:70:05:c9:c6:28:f1:3e: + d4:94:13:db:09:b3:63:78:6f:57:72:e8:1f:28:6f: + 7c:b6:25:76:4e:ab:11:c9:a5:d7:ca:32:00:5f:5e: + 14:ae:53:65:13:37:2b:d2:98:3c:d4:47:74:40:cf: + ff:1b:ad:59:35:c1:d1:d3:a6:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv04.crt01.example.nil, IP Address:10.53.0.4 + X509v3 Subject Key Identifier: + CA:83:06:FB:3E:57:50:DD:FD:BF:00:5A:60:E2:6D:98:71:CD:2C:F2 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 6f:24:c5:ba:8e:62:5d:58:50:a5:25:a1:fc:41:fc:18:cb:7c: + 11:02:0a:ad:7f:13:2a:20:07:92:5a:82:c0:92:9d:35:40:b0: + c9:85:5a:23:26:fb:55:b7:99:7a:18:a7:ae:b4:6e:a2:29:f8: + 25:70:fa:3e:bf:b0:ec:91:d7:46:55:55:ab:fd:22:a6:c1:b4: + 50:92:27:ea:d8:a1:71:ec:14:84:69:0a:c9:de:3f:c1:63:94: + 17:5e:78:e7:85:34:80:bf:c3:58:f1:4d:fb:0c:b4:2e:2b:9c: + 66:15:1f:e3:d6:3a:c1:95:b1:f5:f2:9c:dc:99:cb:d5:39:35: + 6a:bf:bc:f4:81:9d:7c:4c:c1:76:f8:4d:26:ab:f4:f0:50:b2: + f9:41:65:6c:df:9d:16:57:e3:dc:7d:85:0a:14:5f:20:ea:08: + 5e:ab:3c:75:ae:f6:7e:55:62:3b:4c:4a:c7:48:4f:24:f2:78: + e6:99:52:76:87:6e:b3:08:7c:d6:4e:41:72:8f:ed:f1:5a:1a: + 20:e7:c2:cd:a0:6f:04:6c:f1:71:87:21:00:49:29:c1:fb:bd: + 08:a7:51:34:bb:e0:f1:f7:59:3d:b8:9e:c6:48:06:fe:e6:ea: + 30:8b:65:8f:d2:31:c5:d6:4e:a8:22:7e:fc:85:05:3d:e4:7c: + 38:54:07:46:cc:94:8e:a5:d3:4c:09:71:6e:60:63:e4:6a:8e: + aa:c2:81:df:31:37:2a:96:b3:53:36:a2:76:44:59:18:33:81: + 6c:24:84:a3:61:68:63:a2:02:bd:fd:b2:9c:db:0f:cc:a6:44: + 54:c6:2d:13:fb:96:80:63:e7:e9:2e:36:3c:00:34:3e:62:5d: + fe:59:95:cb:b2:d0:cc:9a:69:ce:00:cc:59:c3:f7:79:3a:4f: + 95:e9:64:c9:ad:28:96:e2:80:dd:59:45:29:6c:ed:0d:6e:4e: + 50:69:6e:ef:50:32:4e:5c:af:63:39:57:90:08:0f:b9:4e:ba: + b2:24:ae:bb:78:39 +-----BEGIN CERTIFICATE----- +MIIEkDCCAvigAwIBAgIJAMzBGAgmMuGNMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yMjEyMDgxMTU4NDVaGA8yMDUyMTEz +MDExNTg0NVowIjEgMB4GA1UEAwwXc3J2MDQuY3J0MDEuZXhhbXBsZS5uaWwwggGi +MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCN5ooQbwaPsuX03hRN1DwaIQP+ +MgLWbQolNT1QAHHWe3XR4AQ2INo5253fGf5bw+LQcsQNvlfYwj8wqJmxwxrIlqWK +DHrm6Ss+yfn1RrLMFEzm0WUlGfssK+RtALp8f/YHJBcwQssE6ZQ24xiLYHdsaNOe +YoGCZCQs6bq40EAv5v3p+qoUg28mFsG3s239Sj+Poanme73BYKFr/wKTzAiTnh4M +ozEpIHTlN0bYQRDHEfTY50N8Tbz7/Tk6eY7CC/4h3xbC/BCzm9rMgNNkVm8Jr/Zz +i8tk5P7FTIVOw+2kCgpT9r6NXnpCT82wIaSO5EX+KPZNKVjbSrRwej8L22Q+I6WZ +RxF7LGaDqXknCUVyrEr6NW8fZNSrzwmQknFK0QKAsauwGewBxqcxK0vcOwkArZoS +yunNVL2WI6MULkBYM1gvcAXJxijxPtSUE9sJs2N4b1dy6B8ob3y2JXZOqxHJpdfK +MgBfXhSuU2UTNyvSmDzUR3RAz/8brVk1wdHTpv8CAwEAAaNsMGowKAYDVR0RBCEw +H4IXc3J2MDQuY3J0MDEuZXhhbXBsZS5uaWyHBAo1AAQwHQYDVR0OBBYEFMqDBvs+ +V1Dd/b8AWmDibZhxzSzyMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQBvJMW6jmJdWFClJaH8QfwYy3wRAgqtfxMqIAeS +WoLAkp01QLDJhVojJvtVt5l6GKeutG6iKfglcPo+v7DskddGVVWr/SKmwbRQkifq +2KFx7BSEaQrJ3j/BY5QXXnjnhTSAv8NY8U37DLQuK5xmFR/j1jrBlbH18pzcmcvV +OTVqv7z0gZ18TMF2+E0mq/TwULL5QWVs350WV+PcfYUKFF8g6gheqzx1rvZ+VWI7 +TErHSE8k8njmmVJ2h26zCHzWTkFyj+3xWhog58LNoG8EbPFxhyEASSnB+70Ip1E0 +u+Dx91k9uJ7GSAb+5uowi2WP0jHF1k6oIn78hQU95Hw4VAdGzJSOpdNMCXFuYGPk +ao6qwoHfMTcqlrNTNqJ2RFkYM4FsJISjYWhjogK9/bKc2w/MpkRUxi0T+5aAY+fp +LjY8ADQ+Yl3+WZXLstDMmmnOAMxZw/d5Ok+V6WTJrSiW4oDdWUUpbO0Nbk5QaW7v +UDJOXK9jOVeQCA+5TrqyJK67eDk= +-----END CERTIFICATE----- diff --git a/bin/tests/system/forward/CA/private/CA.key b/bin/tests/system/forward/CA/private/CA.key new file mode 100644 index 0000000..2d5419d --- /dev/null +++ b/bin/tests/system/forward/CA/private/CA.key @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEAouoRHoAc6VCmxNTU6Ge7s+xDFGO0wXJJIsP+8nUyyjWvGCOC +aQYLhb1kLA2NHRhSSKFcMh8jcd7Hlvy6CAec1j2dsWzryy3HgPrdjWaW3PfBO41D +lUtdt8hA/p6pX2YwqvWbdK/3s8J0LY5xRZKNZnFOB/Sb4PGiIJ1NgMRO/M3IlPQm +PO/faRRTU4SI26KCPKFW342826Zi88YwOd6w5mQU4fskk5TGtlNqE+Fj40ZbWVpy +VXoEUS6RveRp020NX5CQG49SLtdF05AnnsATqmgNVCXptGuqW8uaHRONeGO3NBEy +nJmibWBDUMjtCCcGVgyrVXuTkyAJJWpImnshUwgMNYebRwmC2iVv2LtsJS5eUTUH +EWffnFl55XU2PkyNYgY35gA4y3SiWFJYV8+5FibU4ut0nb+lmHBF8WlqcU/kd3tp +Gkf0exjqOIHZFqV9bIhpUbXhxx9v9+gkkGQ9nrXE1KRlvigxxUeIK5xHy9a7fVIL +wo6WuCnLLJmbVkklAgMBAAECggGBAI5ZV3v/FUQIZK+4CBDKEwizeClotZgR9DWc +bDgOj8KABe5hmKGL1qWVRuH3NUYm6j7sP1LMQnxM3LjhOuupOzE3xYIyWhW+eoQI +r23OJiQNl5ohZNweblUXdTMGD5h8AipfUOY0m4tGbZ0gyXixBTxt5HCvG0UB3VgC +GqZY4Wujo5ADhSXZsqxuRiDDvZGr/YBcuTu87Tg/ulam5ZyrKIcnC9gpSVxqsva9 +DAMy/cSoxUjd7ukhJISK3G3AF3fV4GSslQcJTlyJ2D3+LnqPuHJKYTI4hc46lN3x +E2g24GdSCPYf6SoEPwACXtbavV8TXwQPJrHN+f+0/ePCI4jkYe5NoA3gwVgMb/WB +wFchxzVh3V4e8tPGiG+ofKl81DSAW8VZCJLUIbTEce9oxafPT78WJxdC0wWbh5S8 +V/qN6sW/yWnK3oY9SilWhJGRwKOZ+8xtStaDeCzyCaOqEcWi8ZR0QfC33UozlhdC +SrMKnOXmn/rUuXGrVR56IzIl0M7YAQKBwQDM3GJDdlFuHn6L0syKYdHDS8gXD9ke +s+ochIP6jvkEPcayaEoZGl8s7RT3iztqXod7wLaZdotktxfDAZnJfeuOcVrCu+Bx +HLytnBvV6czMfp3REGgQAJQeusSgtlBCTHHVOsDzIjdnkY3WBa7IiFYWO5wnYrGx +r3ucnwnHaUVDMj1r4YI7mYIpCuYQl6eGyW7mhWewyhVwoQXKbifdrXxjvOigL0Cp +tgsoU9pql3hpphOaYMX6hLOincTfaMxfnCECgcEAy5UXp3dA0OwK+4iDGKr+cUpk +AtGTheiE+8zEVh2KYFLt921mW/QZiB1+xtnkknp3c7u07Ugk8jAEXzCkwMnN5ZCx +LrJ72fC+cLIAbRm6/vMMP8iz83wyttao4qNMeoOBBfE9rEiP+lrugpv282V3ZHYa +IUZWTeugJbckUHTbD3RZQExmQcRVG3m/TzonBfoZ8HoRj/n3d7V2T911cHUhi8Xn +RQIi2m63VofOIep86LgartlKneMWnL0oOPq4RKyFAoHAZUzpDkD4nUJZAx025Yrf +ZfoYNEcy7vq6XmWsuX5vZoiBs4DcezNOMvH9NzdTJxMdXbV61cIHxcK/7j7hZABv +NZ2Z6sdqgaRbLGIQZaPaEJjfwxygyKDwnY1vY6UjZNVWSMFn3hJiYUVZZKakuiao +ow/Q9KzZ/2ot7tG5zTCh/ktekfUOKBiNg2wPPc8wGPeMblMzZflXxrzpFyOHdRev +dcZZJbSX/hO1yrhEPgculNd5xBHsdCegiF4JlwvEW9bhAoHAZQQiy5bx03j8bhkr +q6bVQFPAUmG5iL16lxLg7TYVPnyH1bk0DDaQIKk6CeN+dmxML2IZgY/FvWK0GKOj +bIH2J43nTRuFNvwtEvBQI9KbpfvlvRSSriOXaoATJvoObdAoylEM4BrVTk2mgapw +HA/h8Thk+NPU6S8ctPouC7ogJIf/7Va7erC35j0//0kEqgOSsW9wnXdUItMo1LI3 +nsiQD7Hwcp5/utErKcWTM+MNfdA0dUQesT9ILhfyCGvn2TOdAoHBAKldZkDyRcu9 +r9uDF1bhUEnpV2k4hgvTuCvQ3rzyx3WrVT8ChEmePC8Ke5A54ffu/YdbpDLbdf2c +j4n5CQhHbMIZs3P2hB3WqDCImApCfMbXaltfBbaT0j7uLJPMp+2+f/wWYpc3R+bn +HVnaRI2PoXXmG9OjQSQdVZ5gNpkEuemAo3dJOSS6BMqQaSxUynGy7o/a/d4izBjd +B58Fwq3sZI/Xv90Se9+b6ICST3YJ3p0vn8RKzmlCQjLg/xynpCByiw== +-----END RSA PRIVATE KEY----- diff --git a/bin/tests/system/forward/CA/serial b/bin/tests/system/forward/CA/serial new file mode 100644 index 0000000..2e4ab4f --- /dev/null +++ b/bin/tests/system/forward/CA/serial @@ -0,0 +1 @@ +CCC118082632E18E diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py new file mode 100644 index 0000000..8d0b3e9 --- /dev/null +++ b/bin/tests/system/forward/ans11/ans.py @@ -0,0 +1,58 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from typing import AsyncGenerator + +import dns.rdatatype + +from isctest.asyncserver import ( + ControllableAsyncDnsServer, + DnsResponseSend, + DomainHandler, + QueryContext, + ResponseAction, + ToggleResponsesCommand, +) + + +class ExtraAnswersHandler(DomainHandler): + """ + Answer from zone data, inserting extra RRsets into responses to A queries. + """ + + domains = ["attackSecureDomain.net3."] + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + if qctx.qtype == dns.rdatatype.A: + ns_rrset = dns.rrset.from_text( + "net3.", 300, qctx.qclass, dns.rdatatype.NS, "local.net3." + ) + qctx.response.answer.append(ns_rrset) + a_rrset = dns.rrset.from_text( + "local.net3.", 300, qctx.qclass, dns.rdatatype.A, "10.53.0.11" + ) + qctx.response.additional.append(a_rrset) + + yield DnsResponseSend(qctx.response) + + +def main() -> None: + server = ControllableAsyncDnsServer(commands=[ToggleResponsesCommand]) + server.install_response_handler(ExtraAnswersHandler()) + server.run() + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/forward/ans11/attackSecureDomain.net3.db b/bin/tests/system/forward/ans11/attackSecureDomain.net3.db new file mode 100644 index 0000000..5b17056 --- /dev/null +++ b/bin/tests/system/forward/ans11/attackSecureDomain.net3.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ SOA . . 0 0 0 0 0 +@ NS . +@ A 10.53.0.11 diff --git a/bin/tests/system/forward/ans6/ans.py b/bin/tests/system/forward/ans6/ans.py new file mode 100644 index 0000000..f63cdcd --- /dev/null +++ b/bin/tests/system/forward/ans6/ans.py @@ -0,0 +1,81 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from typing import AsyncGenerator + +import dns + +from isctest.asyncserver import ( + ControllableAsyncDnsServer, + DnsResponseSend, + QueryContext, + ResponseAction, + ResponseHandler, + ToggleResponsesCommand, +) + + +class ChaseDsHandler(ResponseHandler): + """ + Yield responses triggering DS chasing logic in `named`. These responses + cannot be served from a static zone file because most of them need to be + generated dynamically so that the owner name of the returned RRset is + copied from the QNAME sent by the client: + + - A/AAAA queries for `ns1.sld.tld.` elicit responses with IP addresses, + - all NS queries below `sld.tld.` elicit a delegation to `ns1.sld.tld.`, + - all other queries elicit a negative response with a common SOA record. + """ + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + ns1_sld_tld = dns.name.from_text("ns1.sld.tld.") + sld_tld = dns.name.from_text("sld.tld.") + + if qctx.qname == ns1_sld_tld and qctx.qtype == dns.rdatatype.A: + response_type = dns.rdatatype.A + response_rdata = "10.53.0.2" + response_section = qctx.response.answer + elif qctx.qname == ns1_sld_tld and qctx.qtype == dns.rdatatype.AAAA: + response_type = dns.rdatatype.AAAA + response_rdata = "fd92:7065:b8e:ffff::2" + response_section = qctx.response.answer + elif qctx.qname.is_subdomain(sld_tld) and qctx.qtype == dns.rdatatype.NS: + response_type = dns.rdatatype.NS + response_rdata = "ns1.sld.tld." + response_section = qctx.response.answer + else: + response_type = dns.rdatatype.SOA + response_rdata = ". . 0 0 0 0 0" + response_section = qctx.response.authority + + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.use_edns(None) + + response_rrset = dns.rrset.from_text( + qctx.qname, 300, qctx.qclass, response_type, response_rdata + ) + response_section.append(response_rrset) + + yield DnsResponseSend(qctx.response, authoritative=True) + + +def main() -> None: + server = ControllableAsyncDnsServer([ToggleResponsesCommand]) + server.install_response_handler(ChaseDsHandler()) + server.run() + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/forward/dhparam3072.pem b/bin/tests/system/forward/dhparam3072.pem new file mode 100644 index 0000000..fb31ccd --- /dev/null +++ b/bin/tests/system/forward/dhparam3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 +7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 +nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu +N///////////AgEC +-----END DH PARAMETERS----- diff --git a/bin/tests/system/forward/ns1/diditwork.net.db b/bin/tests/system/forward/ns1/diditwork.net.db new file mode 100644 index 0000000..fd9a46e --- /dev/null +++ b/bin/tests/system/forward/ns1/diditwork.net.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns + TXT "recursed" +ns A 10.53.0.1 diff --git a/bin/tests/system/forward/ns1/example.db b/bin/tests/system/forward/ns1/example.db new file mode 100644 index 0000000..aac1bef --- /dev/null +++ b/bin/tests/system/forward/ns1/example.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 + +txt TXT "recursed" diff --git a/bin/tests/system/forward/ns1/named.conf.in b/bin/tests/system/forward/ns1/named.conf.in new file mode 100644 index 0000000..eff6e84 --- /dev/null +++ b/bin/tests/system/forward/ns1/named.conf.in @@ -0,0 +1,97 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + query-source-v6 address fd92:7065:b8e:ffff::1; + notify-source 10.53.0.1; + notify-source-v6 fd92:7065:b8e:ffff::1; + transfer-source 10.53.0.1; + transfer-source-v6 fd92:7065:b8e:ffff::1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +zone "example1." { + type primary; + file "example.db"; +}; + +zone "example2." { + type primary; + file "example.db"; +}; + +zone "example3." { + type primary; + file "example.db"; +}; + +zone "example4." { + type primary; + file "example.db"; +}; + +zone "example5." { + type primary; + file "example.db"; +}; + +zone "sld.tld" { + type primary; + file "sld.tld.db"; +}; + +/* A forward zone without forwarders. */ +zone "example6" { + type forward; +}; + +zone "example8." { + type primary; + file "example.db"; +}; + +zone "example9." { + type primary; + file "example.db"; +}; + +zone "diditwork.net" { + type primary; + file "diditwork.net.db"; +}; + +zone "spoofed.net" { + type primary; + file "spoofed.net.db"; +}; + +zone "sub.local.net" { + type primary; + file "sub.local.net.db"; +}; + +zone "net.example.lll" { + type master; + file "net.example.lll"; +}; diff --git a/bin/tests/system/forward/ns1/net.example.lll b/bin/tests/system/forward/ns1/net.example.lll new file mode 100644 index 0000000..ba0804f --- /dev/null +++ b/bin/tests/system/forward/ns1/net.example.lll @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +net.example.lll. SOA . . 0 0 0 0 0 +net.example.lll. NS attackSecureDomain.net. +didItWork.net.example.lll. TXT "if you can see this record the attack worked" diff --git a/bin/tests/system/forward/ns1/root.db.in b/bin/tests/system/forward/ns1/root.db.in new file mode 100644 index 0000000..95ffac3 --- /dev/null +++ b/bin/tests/system/forward/ns1/root.db.in @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 + +example7 NS ns.example7 +ns.example7 A 10.53.0.2 + +tld NS ns.tld +ns.tld A 10.53.0.2 diff --git a/bin/tests/system/forward/ns1/sign.sh b/bin/tests/system/forward/ns1/sign.sh new file mode 100644 index 0000000..5e85fd5 --- /dev/null +++ b/bin/tests/system/forward/ns1/sign.sh @@ -0,0 +1,34 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +zone=. +infile=root.db.in +zonefile=root.db + +echo_i "ns1/sign.sh" + +ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile" + +"$SIGNER" -P -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# Configure the resolving server with a static key. +keyfile_to_static_ds "$ksk" >trusted.conf +cp trusted.conf ../ns3/trusted.conf diff --git a/bin/tests/system/forward/ns1/sld.tld.db b/bin/tests/system/forward/ns1/sld.tld.db new file mode 100644 index 0000000..f0d4b05 --- /dev/null +++ b/bin/tests/system/forward/ns1/sld.tld.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 +xxx TXT "foo" diff --git a/bin/tests/system/forward/ns1/spoofed.net.db b/bin/tests/system/forward/ns1/spoofed.net.db new file mode 100644 index 0000000..eedc46f --- /dev/null +++ b/bin/tests/system/forward/ns1/spoofed.net.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 +sub TXT "recursed" diff --git a/bin/tests/system/forward/ns1/sub.local.net.db b/bin/tests/system/forward/ns1/sub.local.net.db new file mode 100644 index 0000000..fd9a46e --- /dev/null +++ b/bin/tests/system/forward/ns1/sub.local.net.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns + TXT "recursed" +ns A 10.53.0.1 diff --git a/bin/tests/system/forward/ns10/fakenet.zone b/bin/tests/system/forward/ns10/fakenet.zone new file mode 100644 index 0000000..b655a32 --- /dev/null +++ b/bin/tests/system/forward/ns10/fakenet.zone @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +net. SOA . . 0 0 0 0 0 +net. NS attackSecureDomain.net. +attackSecureDomain.net. A 10.53.0.10 +didItWork.net. TXT "if you can see this record the attack worked" +ns.spoofed.net. A 10.53.0.10 diff --git a/bin/tests/system/forward/ns10/fakenet2.zone b/bin/tests/system/forward/ns10/fakenet2.zone new file mode 100644 index 0000000..cd1e6e9 --- /dev/null +++ b/bin/tests/system/forward/ns10/fakenet2.zone @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +net2. SOA . . 0 0 0 0 0 +net2. NS attackSecureDomain.net. +net2. DNAME net.example.lll. diff --git a/bin/tests/system/forward/ns10/fakesublocalnet.zone b/bin/tests/system/forward/ns10/fakesublocalnet.zone new file mode 100644 index 0000000..160b533 --- /dev/null +++ b/bin/tests/system/forward/ns10/fakesublocalnet.zone @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +sub.local.net. SOA . . 0 0 0 0 0 +sub.local.net. NS ns.spoofed.net. +sub.local.net. TXT "if you see this attacker overrode local delegation" diff --git a/bin/tests/system/forward/ns10/fakesublocaltld.zone b/bin/tests/system/forward/ns10/fakesublocaltld.zone new file mode 100644 index 0000000..f78cbc7 --- /dev/null +++ b/bin/tests/system/forward/ns10/fakesublocaltld.zone @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +sub.local.tld. 3600 IN SOA . . 0 0 0 0 0 +sub.local.tld. 3600 IN NS ns.sub.local.tld. +sub.local.tld. 3600 IN TXT bad +ns.sub.local.tld. 3600 IN A 10.53.0.8 diff --git a/bin/tests/system/forward/ns10/named.conf.in b/bin/tests/system/forward/ns10/named.conf.in new file mode 100644 index 0000000..8148d9e --- /dev/null +++ b/bin/tests/system/forward/ns10/named.conf.in @@ -0,0 +1,54 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.10; + notify-source 10.53.0.10; + transfer-source 10.53.0.10; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.10; }; + listen-on-v6 { none; }; + minimal-responses no; + dnssec-validation no; +}; + +zone "net." { + type master; + file "fakenet.zone"; +}; + +zone "spoofed.net." { + type master; + file "spoofednet.zone"; +}; + +zone "sub.local.net." { + type master; + file "fakesublocalnet.zone"; +}; + +zone "net2" { + type master; + file "fakenet2.zone"; +}; + +zone "net.example.lll" { + type master; + file "net.example.lll"; +}; + +zone "sub.local.tld." { + type master; + file "fakesublocaltld.zone"; +}; diff --git a/bin/tests/system/forward/ns10/net.example.lll b/bin/tests/system/forward/ns10/net.example.lll new file mode 100644 index 0000000..ba0804f --- /dev/null +++ b/bin/tests/system/forward/ns10/net.example.lll @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +net.example.lll. SOA . . 0 0 0 0 0 +net.example.lll. NS attackSecureDomain.net. +didItWork.net.example.lll. TXT "if you can see this record the attack worked" diff --git a/bin/tests/system/forward/ns10/spoofednet.zone b/bin/tests/system/forward/ns10/spoofednet.zone new file mode 100644 index 0000000..fb70a43 --- /dev/null +++ b/bin/tests/system/forward/ns10/spoofednet.zone @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +spoofed.net. SOA . . 0 0 0 0 0 +spoofed.net. NS ns.spoofed.net. +ns.spoofed.net. A 10.53.0.10 +spoofed.net. TXT "this record is clearly spoofed" diff --git a/bin/tests/system/forward/ns2/example.db b/bin/tests/system/forward/ns2/example.db new file mode 100644 index 0000000..df3e52c --- /dev/null +++ b/bin/tests/system/forward/ns2/example.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 + +txt TXT "forwarded" diff --git a/bin/tests/system/forward/ns2/named-tls.conf.in b/bin/tests/system/forward/ns2/named-tls.conf.in new file mode 100644 index 0000000..2c68c6f --- /dev/null +++ b/bin/tests/system/forward/ns2/named-tls.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls tls-forward-secrecy { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt01.example.nil.key"; + cert-file "../CA/certs/srv02.crt01.example.nil.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-forward-secrecy-mutual-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt01.example.nil.key"; + cert-file "../CA/certs/srv02.crt01.example.nil.pem"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-expired { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt02-expired.example.nil.key"; + cert-file "../CA/certs/srv02.crt02-expired.example.nil.pem"; + dhparam-file "../dhparam3072.pem"; +}; diff --git a/bin/tests/system/forward/ns2/named.conf.in b/bin/tests/system/forward/ns2/named.conf.in new file mode 100644 index 0000000..02da868 --- /dev/null +++ b/bin/tests/system/forward/ns2/named.conf.in @@ -0,0 +1,85 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "named-tls.conf"; + +options { + query-source address 10.53.0.2; + query-source-v6 address fd92:7065:b8e:ffff::2; + notify-source 10.53.0.2; + notify-source-v6 fd92:7065:b8e:ffff::2; + transfer-source 10.53.0.2; + transfer-source-v6 fd92:7065:b8e:ffff::2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + include "options-tls.conf"; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "example1." { + type primary; + file "example.db"; +}; + +zone "example2." { + type primary; + file "example.db"; +}; + +zone "example3." { + type primary; + file "example.db"; +}; + +zone "example4." { + type primary; + file "example.db"; +}; + +zone "example7." { + type primary; + file "example.db"; +}; + +zone "example8." { + type primary; + file "example.db"; +}; + +zone "example9." { + type primary; + file "example.db"; +}; + +zone "grafted." { + type primary; + file "example.db"; +}; + +zone "1.0.10.in-addr.arpa." { + type primary; + file "example.db"; +}; + +zone "tld" { + type primary; + file "tld.db"; +}; diff --git a/bin/tests/system/forward/ns2/options-tls.conf.in b/bin/tests/system/forward/ns2/options-tls.conf.in new file mode 100644 index 0000000..fab1fa7 --- /dev/null +++ b/bin/tests/system/forward/ns2/options-tls.conf.in @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + tls-port @TLSPORT@; + listen-on tls ephemeral { 10.53.0.2; }; + listen-on port @EXTRAPORT1@ tls tls-forward-secrecy { 10.53.0.2; }; + listen-on port @EXTRAPORT2@ tls tls-forward-secrecy-mutual-tls { 10.53.0.2; }; + listen-on port @EXTRAPORT3@ tls tls-expired { 10.53.0.2; }; diff --git a/bin/tests/system/forward/ns2/root.db b/bin/tests/system/forward/ns2/root.db new file mode 100644 index 0000000..7108723 --- /dev/null +++ b/bin/tests/system/forward/ns2/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 diff --git a/bin/tests/system/forward/ns2/tld.db b/bin/tests/system/forward/ns2/tld.db new file mode 100644 index 0000000..965f2a4 --- /dev/null +++ b/bin/tests/system/forward/ns2/tld.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.2 +sld NS ns.sld +ns.sld A 10.53.0.1 +local NS ns.local +ns.local A 10.53.0.9 +sibling NS ns.sibling +ns.sibling A 10.53.0.4 +sibling NS ns.sub.local +ns.sub.local A 10.53.0.10 diff --git a/bin/tests/system/forward/ns3/named1.conf.in b/bin/tests/system/forward/ns3/named1.conf.in new file mode 100644 index 0000000..91de8f8 --- /dev/null +++ b/bin/tests/system/forward/ns3/named1.conf.in @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + query-source-v6 address fd92:7065:b8e:ffff::3; + notify-source 10.53.0.3; + notify-source-v6 fd92:7065:b8e:ffff::3; + transfer-source 10.53.0.3; + transfer-source-v6 fd92:7065:b8e:ffff::3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + forwarders { fd92:7065:b8e:ffff::2; }; + forward first; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "example1." { + type forward; + forward first; + forwarders { 10.53.0.2; }; +}; + +zone "example2." { + type forward; + forward first; + forwarders { }; +}; + +zone "example3." { + type forward; + forward only; + forwarders { }; +}; + +zone "example7." { + type forward; + forward first; + forwarders { 10.53.0.6; }; +}; diff --git a/bin/tests/system/forward/ns3/named2.conf.in b/bin/tests/system/forward/ns3/named2.conf.in new file mode 100644 index 0000000..986a60e --- /dev/null +++ b/bin/tests/system/forward/ns3/named2.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + query-source-v6 address fd92:7065:b8e:ffff::3; + notify-source 10.53.0.3; + notify-source-v6 fd92:7065:b8e:ffff::3; + transfer-source 10.53.0.3; + transfer-source-v6 fd92:7065:b8e:ffff::3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + forwarders { 10.53.0.6; }; + dnssec-validation yes; +}; + +include "trusted.conf"; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/forward/ns3/root.db b/bin/tests/system/forward/ns3/root.db new file mode 100644 index 0000000..7108723 --- /dev/null +++ b/bin/tests/system/forward/ns3/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 diff --git a/bin/tests/system/forward/ns3/root2.db b/bin/tests/system/forward/ns3/root2.db new file mode 100644 index 0000000..40586f0 --- /dev/null +++ b/bin/tests/system/forward/ns3/root2.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.11 diff --git a/bin/tests/system/forward/ns4/malicious.db b/bin/tests/system/forward/ns4/malicious.db new file mode 100644 index 0000000..e4859c1 --- /dev/null +++ b/bin/tests/system/forward/ns4/malicious.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA malicious. admin.malicious. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 86400 ) ; Negative Cache TTL + +@ IN NS ns + +ns IN A 10.53.0.4 + +target IN CNAME subdomain.rebind. diff --git a/bin/tests/system/forward/ns4/named-tls.conf.in b/bin/tests/system/forward/ns4/named-tls.conf.in new file mode 100644 index 0000000..ed8c865 --- /dev/null +++ b/bin/tests/system/forward/ns4/named-tls.conf.in @@ -0,0 +1,83 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls tls-forward-secrecy { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-forward-secrecy-remote-hostname { + protocols { TLSv1.2; }; + ca-file "../CA/CA.pem"; + remote-hostname "srv02.crt01.example.nil"; +}; + +tls tls-forward-secrecy-bad-remote-hostname { + protocols { TLSv1.2; }; + ca-file "../CA/CA.pem"; + remote-hostname "srv02-bad.crt01.example.nil"; +}; + +tls tls-forward-secrecy-mutual-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + key-file "../CA/certs/srv04.crt01.example.nil.key"; + cert-file "../CA/certs/srv04.crt01.example.nil.pem"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-expired { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +zone "example1." { + type forward; + forward first; + forwarders { 10.53.0.2 tls ephemeral; }; +}; + +zone "example3." { + type forward; + forwarders port @EXTRAPORT1@ tls tls-forward-secrecy { 10.53.0.2; }; +}; + +zone "example4." { + type forward; + forward only; + forwarders port @EXTRAPORT1@ tls tls-forward-secrecy { 10.53.0.2 tls tls-expired port @EXTRAPORT3@; }; +}; + +zone "example8." { + type forward; + forward only; + forwarders port @EXTRAPORT1@ tls tls-forward-secrecy-remote-hostname { 10.53.0.2; }; +}; + +zone "example9." { + type forward; + forward only; + forwarders port @EXTRAPORT1@ tls tls-forward-secrecy-bad-remote-hostname { 10.53.0.2; }; +}; + +zone "1.0.10.in-addr.arpa" { + type forward; + forward only; + forwarders { 10.53.0.2 tls tls-forward-secrecy-mutual-tls port @EXTRAPORT2@; }; +}; diff --git a/bin/tests/system/forward/ns4/named.conf.in b/bin/tests/system/forward/ns4/named.conf.in new file mode 100644 index 0000000..5777c0d --- /dev/null +++ b/bin/tests/system/forward/ns4/named.conf.in @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "named-tls.conf"; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + include "options-tls.conf"; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + minimal-responses yes; +}; + +trust-anchors { }; + +statistics-channels { inet 10.53.0.4 port @EXTRAPORT1@ allow { localhost; }; }; + +zone "." { + type hint; + file "root.db"; +}; + +zone "example5." { + type forward; + forward only; + forwarders { 10.53.0.2; }; +}; + +zone "grafted" { + type forward; + forward only; + forwarders { 10.53.0.2; }; +}; + +zone "malicious." { + type primary; + file "malicious.db"; +}; + +zone "sibling.tld" { + type primary; + file "sibling.tld.db"; +}; diff --git a/bin/tests/system/forward/ns4/options-tls.conf.in b/bin/tests/system/forward/ns4/options-tls.conf.in new file mode 100644 index 0000000..fe3491e --- /dev/null +++ b/bin/tests/system/forward/ns4/options-tls.conf.in @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + tls-port @TLSPORT@; diff --git a/bin/tests/system/forward/ns4/root.db b/bin/tests/system/forward/ns4/root.db new file mode 100644 index 0000000..7108723 --- /dev/null +++ b/bin/tests/system/forward/ns4/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 diff --git a/bin/tests/system/forward/ns4/sibling.tld.db b/bin/tests/system/forward/ns4/sibling.tld.db new file mode 100644 index 0000000..fe080ae --- /dev/null +++ b/bin/tests/system/forward/ns4/sibling.tld.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA malicious. admin.malicious. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 86400 ) ; Negative Cache TTL + +@ IN NS ns + +ns IN A 10.53.0.4 diff --git a/bin/tests/system/forward/ns5/named.conf.in b/bin/tests/system/forward/ns5/named.conf.in new file mode 100644 index 0000000..15b89dd --- /dev/null +++ b/bin/tests/system/forward/ns5/named.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + forward only; + forwarders { 10.53.0.4; }; + deny-answer-aliases { "rebind"; }; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.db"; +}; + +zone "rebind" { + type primary; + file "rebind.db"; +}; diff --git a/bin/tests/system/forward/ns5/rebind.db b/bin/tests/system/forward/ns5/rebind.db new file mode 100644 index 0000000..aed6c2e --- /dev/null +++ b/bin/tests/system/forward/ns5/rebind.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA rebind. admin.rebind. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 86400 ) ; Negative Cache TTL + +@ IN NS ns + +ns IN A 10.53.0.5 + +subdomain IN A 10.53.0.1 diff --git a/bin/tests/system/forward/ns5/root.db b/bin/tests/system/forward/ns5/root.db new file mode 100644 index 0000000..7108723 --- /dev/null +++ b/bin/tests/system/forward/ns5/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 diff --git a/bin/tests/system/forward/ns7/named.conf.in b/bin/tests/system/forward/ns7/named.conf.in new file mode 100644 index 0000000..c6e55a8 --- /dev/null +++ b/bin/tests/system/forward/ns7/named.conf.in @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + forwarders { 10.53.0.4; }; + forward first; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/forward/ns7/root.db b/bin/tests/system/forward/ns7/root.db new file mode 100644 index 0000000..7108723 --- /dev/null +++ b/bin/tests/system/forward/ns7/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example1 NS ns.example1 +ns.example1 A 10.53.0.1 + +example2 NS ns.example2 +ns.example2 A 10.53.0.1 + +example3 NS ns.example3 +ns.example3 A 10.53.0.1 diff --git a/bin/tests/system/forward/ns8/named.conf.in b/bin/tests/system/forward/ns8/named.conf.in new file mode 100644 index 0000000..13c3859 --- /dev/null +++ b/bin/tests/system/forward/ns8/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + forwarders { 10.53.0.2; }; // returns referrals + forward first; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "root.db"; +}; + +zone "sub.local.tld" { + type primary; + file "sub.local.tld.db"; +}; diff --git a/bin/tests/system/forward/ns8/root.db b/bin/tests/system/forward/ns8/root.db new file mode 100644 index 0000000..2cbdff5 --- /dev/null +++ b/bin/tests/system/forward/ns8/root.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/forward/ns8/sub.local.tld.db b/bin/tests/system/forward/ns8/sub.local.tld.db new file mode 100644 index 0000000..f2234c7 --- /dev/null +++ b/bin/tests/system/forward/ns8/sub.local.tld.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +sub.local.tld. 3600 IN SOA . . 0 0 0 0 0 +sub.local.tld. 3600 IN NS ns.sub.local.tld. +sub.local.tld. 3600 IN TXT good +ns.sub.local.tld. 3600 IN A 10.53.0.8 diff --git a/bin/tests/system/forward/ns9/local.net.db b/bin/tests/system/forward/ns9/local.net.db new file mode 100644 index 0000000..af0d2a5 --- /dev/null +++ b/bin/tests/system/forward/ns9/local.net.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +local.net. 3600 IN SOA . . 0 0 0 0 0 +local.net. 3600 IN NS localhost. +ns.local.net. 3600 IN A 10.53.0.9 +txt.local.net. 3600 IN TXT "something in the local auth zone" +sub.local.net. 3600 IN NS ns.spoofed.net. ; attacker will try to override this diff --git a/bin/tests/system/forward/ns9/local.tld.db b/bin/tests/system/forward/ns9/local.tld.db new file mode 100644 index 0000000..876a913 --- /dev/null +++ b/bin/tests/system/forward/ns9/local.tld.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +local.tld. 3600 IN SOA . . 0 0 0 0 0 +local.tld. 3600 IN NS localhost. +sub.local.tld. 3600 IN NS ns.sub.local.tld. +ns.sub.local.tld. 3600 IN A 10.53.0.8 diff --git a/bin/tests/system/forward/ns9/named1.conf.in b/bin/tests/system/forward/ns9/named1.conf.in new file mode 100644 index 0000000..54fed8f --- /dev/null +++ b/bin/tests/system/forward/ns9/named1.conf.in @@ -0,0 +1,67 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + dnssec-validation no; + edns-udp-size 1232; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +server 10.53.0.10 { + edns no; +}; + +server 10.53.0.11 { + edns no; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "attacksecuredomain.net." { + type forward; + forwarders { 10.53.0.10; }; +}; + +zone "attacksecuredomain.net2." { + type forward; + forwarders { 10.53.0.10; }; +}; + +zone "attacksecuredomain.net3." { + type forward; + forwarders { 10.53.0.11; }; +}; + +zone "local.net." { + type primary; + file "local.net.db"; + forwarders {}; +}; diff --git a/bin/tests/system/forward/ns9/named2.conf.in b/bin/tests/system/forward/ns9/named2.conf.in new file mode 100644 index 0000000..34f7eea --- /dev/null +++ b/bin/tests/system/forward/ns9/named2.conf.in @@ -0,0 +1,70 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + dnssec-validation no; + edns-udp-size 1232; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +server 10.53.0.10 { + edns no; +}; + +server 10.53.0.11 { + edns no; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "attacksecuredomain.net." { + type forward; + forward only; + forwarders { 10.53.0.10; }; +}; + +zone "attacksecuredomain.net2." { + type forward; + forward only; + forwarders { 10.53.0.10; }; +}; + +zone "attacksecuredomain.net3." { + type forward; + forward only; + forwarders { 10.53.0.11; }; +}; + +zone "local.net." { + type primary; + file "local.net.db"; + forwarders {}; +}; diff --git a/bin/tests/system/forward/ns9/named3.conf.in b/bin/tests/system/forward/ns9/named3.conf.in new file mode 100644 index 0000000..c07281f --- /dev/null +++ b/bin/tests/system/forward/ns9/named3.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + dnssec-validation no; + edns-udp-size 1232; + forward only; + forwarders { 10.53.0.10; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +server 10.53.0.10 { + edns no; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "local.net." { + type primary; + file "local.net.db"; + forwarders {}; +}; diff --git a/bin/tests/system/forward/ns9/named4.conf.in b/bin/tests/system/forward/ns9/named4.conf.in new file mode 100644 index 0000000..c06b361 --- /dev/null +++ b/bin/tests/system/forward/ns9/named4.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + dnssec-validation no; + edns-udp-size 1232; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +server 10.53.0.10 { + edns no; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "local.tld." { + type primary; + file "local.tld.db"; +}; diff --git a/bin/tests/system/forward/ns9/root.db b/bin/tests/system/forward/ns9/root.db new file mode 100644 index 0000000..2cbdff5 --- /dev/null +++ b/bin/tests/system/forward/ns9/root.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/forward/prereq.sh b/bin/tests/system/forward/prereq.sh new file mode 100644 index 0000000..32889aa --- /dev/null +++ b/bin/tests/system/forward/prereq.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/forward/rfc1918-inherited.conf b/bin/tests/system/forward/rfc1918-inherited.conf new file mode 100644 index 0000000..66569dc --- /dev/null +++ b/bin/tests/system/forward/rfc1918-inherited.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone 10.in-addr.arpa { + type forward; + forwarders { 1.2.3.4; }; +}; diff --git a/bin/tests/system/forward/rfc1918-notinherited.conf b/bin/tests/system/forward/rfc1918-notinherited.conf new file mode 100644 index 0000000..d6d5c2d --- /dev/null +++ b/bin/tests/system/forward/rfc1918-notinherited.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone 10.in-addr.arpa { + type forward; + forward first; + forwarders { 1.2.3.4; }; +}; diff --git a/bin/tests/system/forward/setup.sh b/bin/tests/system/forward/setup.sh new file mode 100644 index 0000000..4251008 --- /dev/null +++ b/bin/tests/system/forward/setup.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf + +if $FEATURETEST --have-fips-dh; then + copy_setports ns2/named-tls.conf.in ns2/named-tls.conf + copy_setports ns2/options-tls.conf.in ns2/options-tls.conf + copy_setports ns2/named.conf.in ns2/named.conf +else + cp /dev/null ns2/named-tls.conf + cp /dev/null ns2/options-tls.conf + copy_setports ns2/named.conf.in ns2/named.conf +fi + +copy_setports ns3/named1.conf.in ns3/named.conf + +if $FEATURETEST --have-fips-dh; then + copy_setports ns4/named-tls.conf.in ns4/named-tls.conf + copy_setports ns4/options-tls.conf.in ns4/options-tls.conf + copy_setports ns4/named.conf.in ns4/named.conf +else + cp /dev/null ns4/named-tls.conf + cp /dev/null ns4/options-tls.conf + copy_setports ns4/named.conf.in ns4/named.conf +fi + +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf +copy_setports ns9/named1.conf.in ns9/named.conf +copy_setports ns10/named.conf.in ns10/named.conf + +( + cd ns1 + $SHELL sign.sh +) diff --git a/bin/tests/system/forward/tests.sh b/bin/tests/system/forward/tests.sh new file mode 100644 index 0000000..25f2048 --- /dev/null +++ b/bin/tests/system/forward/tests.sh @@ -0,0 +1,468 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +#shellcheck source=conf.sh +. ../conf.sh + +dig_with_opts() ( + "$DIG" -p "$PORT" "$@" +) + +sendcmd() ( + dig_with_opts "@${1}" "${2}._control." TXT +time=5 +tries=1 +tcp >/dev/null 2>&1 +) + +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +root=10.53.0.1 +hidden=10.53.0.2 +f1=10.53.0.3 +f2=10.53.0.4 + +status=0 +n=0 + +n=$((n + 1)) +echo_i "checking that a forward zone overrides global forwarders ($n)" +ret=0 +dig_with_opts +noadd +noauth txt.example1. txt @$hidden >dig.out.$n.hidden || ret=1 +dig_with_opts +noadd +noauth txt.example1. txt @$f1 >dig.out.$n.f1 || ret=1 +digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a forward first zone no forwarders recurses ($n)" +ret=0 +dig_with_opts +noadd +noauth txt.example2. txt @$root >dig.out.$n.root || ret=1 +dig_with_opts +noadd +noauth txt.example2. txt @$f1 >dig.out.$n.f1 || ret=1 +digcomp dig.out.$n.root dig.out.$n.f1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a forward only zone no forwarders fails ($n)" +ret=0 +dig_with_opts +noadd +noauth txt.example2. txt @$root >dig.out.$n.root || ret=1 +dig_with_opts +noadd +noauth txt.example2. txt @$f1 >dig.out.$n.f1 || ret=1 +digcomp dig.out.$n.root dig.out.$n.f1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that global forwarders work ($n)" +ret=0 +dig_with_opts +noadd +noauth txt.example4. txt @$hidden >dig.out.$n.hidden || ret=1 +dig_with_opts +noadd +noauth txt.example4. txt @$f1 >dig.out.$n.f1 || ret=1 +digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that DoT expired certificate does not work ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + nextpart ns4/named.run >/dev/null + dig_with_opts +noadd +noauth txt.example4. txt @$hidden >dig.out.$n.hidden || ret=1 + dig_with_opts +noadd +noauth txt.example4. txt @$f2 >dig.out.$n.f2 || ret=1 + digcomp dig.out.$n.hidden dig.out.$n.f2 >/dev/null 2>&1 && ret=1 + wait_for_log 1 "TLS peer certificate verification failed" ns4/named.run || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that a forward zone works (DoT insecure) ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + nextpart ns4/named.run >/dev/null + dig_with_opts +noadd +noauth txt.example1. txt @$hidden >dig.out.$n.hidden || ret=1 + dig_with_opts +noadd +noauth txt.example1. txt @$f2 >dig.out.$n.f2 || ret=1 + digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1 + wait_for_log 1 "TLS client session created for 10.53.0.2" ns4/named.run || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that forwarding doesn't spontaneously happen ($n)" +ret=0 +dig_with_opts +noadd +noauth txt.example2. txt @$root >dig.out.$n.root || ret=1 +dig_with_opts +noadd +noauth txt.example2. txt @$f2 >dig.out.$n.f2 || ret=1 +digcomp dig.out.$n.root dig.out.$n.f2 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a forward zone with no specified policy works (DoT forward-secrecy) ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + nextpart ns4/named.run >/dev/null + dig_with_opts +noadd +noauth txt.example3. txt @$hidden >dig.out.$n.hidden || ret=1 + dig_with_opts +noadd +noauth txt.example3. txt @$f2 >dig.out.$n.f2 || ret=1 + digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1 + wait_for_log 1 "TLS client session created for 10.53.0.2" ns4/named.run || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that DoT remote-hostname works ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + nextpart ns4/named.run >/dev/null + dig_with_opts +noadd +noauth txt.example8. txt @$hidden >dig.out.$n.hidden || ret=1 + dig_with_opts +noadd +noauth txt.example8. txt @$f2 >dig.out.$n.f2 || ret=1 + digcomp dig.out.$n.hidden dig.out.$n.f2 >/dev/null 2>&1 || ret=1 + wait_for_log 1 "TLS client session created for 10.53.0.2" ns4/named.run || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that DoT bad remote-hostname does not work ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + nextpart ns4/named.run >/dev/null + dig_with_opts +noadd +noauth txt.example9. txt @$hidden >dig.out.$n.hidden || ret=1 + dig_with_opts +noadd +noauth txt.example9. txt @$f2 >dig.out.$n.f2 || ret=1 + digcomp dig.out.$n.hidden dig.out.$n.f2 >/dev/null 2>&1 && ret=1 + wait_for_log 1 "TLS peer certificate verification failed" ns4/named.run || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that a forward only doesn't recurse ($n)" +ret=0 +dig_with_opts txt.example5. txt @$f2 >dig.out.$n.f2 || ret=1 +grep "SERVFAIL" dig.out.$n.f2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# GL#1793 +n=$((n + 1)) +echo_i "checking that the 'serverquota' counter isn't increased because of the SERVFAIL in the previous check ($n)" +ret=0 +"${CURL}" "http://10.53.0.4:${EXTRAPORT1}/json/v1" 2>/dev/null >statschannel.out.$n +grep -F "ServerQuota" statschannel.out.$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking for negative caching of forwarder response ($n)" +# prime the cache, shutdown the forwarder then check that we can +# get the answer from the cache. restart forwarder. +ret=0 +dig_with_opts nonexist. txt @10.53.0.5 >dig.out.$n.f2 || ret=1 +grep "status: NXDOMAIN" dig.out.$n.f2 >/dev/null || ret=1 +stop_server ns4 || ret=1 +dig_with_opts nonexist. txt @10.53.0.5 >dig.out.$n.f2 || ret=1 +grep "status: NXDOMAIN" dig.out.$n.f2 >/dev/null || ret=1 +start_server --restart --noclean --port "${PORT}" ns4 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +check_override() ( + dig_with_opts 1.0.10.in-addr.arpa TXT @$f2 >dig.out.$n.f2 \ + && grep "status: NOERROR" dig.out.$n.f2 >/dev/null \ + && dig_with_opts 2.0.10.in-addr.arpa TXT @$f2 >dig.out.$n.f2 \ + && grep "status: NXDOMAIN" dig.out.$n.f2 >/dev/null +) + +n=$((n + 1)) +echo_i "checking that forward only zone overrides empty zone (DoT forward-secrecy-mutual-tls) ($n)" +if $FEATURETEST --have-fips-dh; then + ret=0 + # retry loop in case the server restart above causes transient failure + retry_quiet 10 check_override || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped." +fi + +n=$((n + 1)) +echo_i "checking that DS lookups for grafting forward zones are isolated ($n)" +ret=0 +dig_with_opts grafted A @10.53.0.4 >dig.out.$n.q1 || ret=1 +dig_with_opts grafted DS @10.53.0.4 >dig.out.$n.q2 || ret=1 +dig_with_opts grafted A @10.53.0.4 >dig.out.$n.q3 || ret=1 +dig_with_opts grafted AAAA @10.53.0.4 >dig.out.$n.q4 || ret=1 +grep "status: NOERROR" dig.out.$n.q1 >/dev/null || ret=1 +grep "status: NXDOMAIN" dig.out.$n.q2 >/dev/null || ret=1 +grep "status: NOERROR" dig.out.$n.q3 >/dev/null || ret=1 +grep "status: NOERROR" dig.out.$n.q4 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that rfc1918 inherited 'forward first;' zones are warned about ($n)" +ret=0 +$CHECKCONF rfc1918-inherited.conf | grep "forward first;" >/dev/null || ret=1 +$CHECKCONF rfc1918-notinherited.conf | grep "forward first;" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that ULA inherited 'forward first;' zones are warned about ($n)" +ret=0 +$CHECKCONF ula-inherited.conf | grep "forward first;" >/dev/null || ret=1 +$CHECKCONF ula-notinherited.conf | grep "forward first;" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +count_sent() ( + logfile="$1" + start_pattern="$2" + pattern="$3" + nextpartpeek "$logfile" | sed -n "/$start_pattern/,/^\$/p" | grep -c "$pattern" +) + +check_sent() ( + expected="$1" + shift + count=$(count_sent "$@") + [ "$expected" = "$count" ] +) + +wait_for_log() ( + nextpartpeek "$1" | grep "$2" >/dev/null + +) + +n=$((n + 1)) +echo_i "checking that a forwarder timeout prevents it from being reused in the same fetch context ($n)" +ret=0 +# Make ans6 receive queries without responding to them. +sendcmd 10.53.0.6 "disable.send-responses" +# Query for a record in a zone which is forwarded to a non-responding forwarder +# and is delegated from the root to check whether the forwarder will be retried +# when a delegation is encountered after falling back to full recursive +# resolution. +nextpart ns3/named.run >/dev/null +dig_with_opts txt.example7. txt @$f1 >dig.out.$n.f1 || ret=1 +# The forwarder for the "example7" zone should only be queried once. +start_pattern="sending packet to 10\.53\.0\.6" +retry_quiet 5 wait_for_log ns3/named.run "$start_pattern" +check_sent 1 ns3/named.run "$start_pattern" ";txt\.example7\.[[:space:]]*IN[[:space:]]*TXT$" || ret=1 +sendcmd 10.53.0.6 "enable.send-responses" +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that priming queries are not forwarded ($n)" +ret=0 +nextpart ns7/named.run >/dev/null +dig_with_opts +noadd +noauth txt.example1. txt @10.53.0.7 >dig.out.$n.f7 || ret=1 +received_pattern="received packet from 10\.53\.0\.1" +start_pattern="sending packet to 10\.53\.0\.1" +retry_quiet 5 wait_for_log ns7/named.run "$received_pattern" || ret=1 +check_sent 1 ns7/named.run "$start_pattern" ";\.[[:space:]]*IN[[:space:]]*NS$" || ret=1 +sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns4/named.run || true) +[ "$sent" -eq 0 ] || ret=1 +sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns1/named.run || true) +[ "$sent" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recovery from forwarding to a non-recursive server ($n)" +ret=0 +dig_with_opts xxx.sld.tld txt @10.53.0.8 >dig.out.$n.f8 || ret=1 +grep "status: NOERROR" dig.out.$n.f8 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that rebinding protection works in forward only mode ($n)" +ret=0 +# 10.53.0.5 will forward target.malicious. query to 10.53.0.4 +# which in turn will return a CNAME for subdomain.rebind. +# to honor the option deny-answer-aliases { "rebind"; }; +# ns5 should return a SERVFAIL to avoid potential rebinding attacks +dig_with_opts +noadd +noauth @10.53.0.5 target.malicious. >dig.out.$n || ret=1 +grep "status: SERVFAIL" dig.out.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking switch from forwarding to normal resolution while chasing DS ($n)" +ret=0 +copy_setports ns3/named2.conf.in ns3/named.conf +rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 1 +nextpart ns3/named.run >/dev/null +dig_with_opts @$f1 xxx.yyy.sld.tld ds >dig.out.$n.f1 || ret=1 +grep "status: SERVFAIL" dig.out.$n.f1 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# See [GL #3129]. +# Enable silent mode for ans11. +sendcmd 10.53.0.11 "disable.send-responses" +n=$((n + 1)) +echo_i "checking the handling of hung DS fetch while chasing DS ($n)" +ret=0 +copy_setports ns3/named2.conf.in ns3/tmp +sed 's/root.db/root2.db/' ns3/tmp >ns3/named.conf +rm -f ns3/tmp +rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +rndccmd 10.53.0.3 flush 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 1 +nextpart ns3/named.run >/dev/null +dig_with_opts @$f1 xxx.yyy.sld.tld ds >dig.out.$n.f1 || ret=1 +grep "status: SERVFAIL" dig.out.$n.f1 >/dev/null || ret=1 +# Disable silent mode for ans11. +sendcmd 10.53.0.11 "enable.send-responses" +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Check various spoofed response scenarios. The same tests will be +# run twice, with "forward first" and "forward only" configurations. +# +run_spooftests() { + n=$((n + 1)) + echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)" + ret=0 + # prime + dig_with_opts @10.53.0.9 attackSecureDomain.net >dig.out.$n.prime || ret=1 + # check 'net' is not poisoned. + dig_with_opts @10.53.0.9 diditwork.net. TXT >dig.out.$n.net || ret=1 + grep '^diditwork\.net\..*TXT.*"recursed"' dig.out.$n.net >/dev/null || ret=1 + # check 'sub.local.net' is not poisoned. + dig_with_opts @10.53.0.9 sub.local.net TXT >dig.out.$n.sub || ret=1 + grep '^sub\.local\.net\..*TXT.*"recursed"' dig.out.$n.sub >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)" + ret=0 + # prime + dig_with_opts @10.53.0.9 attackSecureDomain.net2 >dig.out.$n.prime || ret=1 + # check that net2/DNAME is not cached + dig_with_opts @10.53.0.9 net2. DNAME >dig.out.$n.net2 || ret=1 + grep "ANSWER: 0," dig.out.$n.net2 >/dev/null || ret=1 + grep "status: NXDOMAIN" dig.out.$n.net2 >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + n=$((n + 1)) + echo_i "checking spoofed response scenario 3 - extra answer ($n)" + ret=0 + # prime + dig_with_opts @10.53.0.9 attackSecureDomain.net3 >dig.out.$n.prime || ret=1 + # check extra net3 records are not cached + rndccmd 10.53.0.9 dumpdb -cache 2>&1 | sed 's/^/ns9 /' | cat_i + for try in 1 2 3 4 5; do + lines=$(grep "net3" ns9/named_dump.db | wc -l) + if [ ${lines} -eq 0 ]; then + sleep 1 + continue + fi + [ ${lines} -eq 1 ] || ret=1 + grep -q '^attackSecureDomain.net3' ns9/named_dump.db || ret=1 + grep -q '^local.net3' ns9/named_dump.db && ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +} + +echo_i "checking spoofed response scenarios with forward first zones" +run_spooftests + +copy_setports ns9/named2.conf.in ns9/named.conf +rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 1 + +echo_i "rechecking spoofed response scenarios with forward only zones" +run_spooftests + +# +# This scenario expects the spoofed response to succeed. The tests are +# similar to the ones above, but not identical. +# +echo_i "rechecking spoofed response scenarios with 'forward only' set globally" +copy_setports ns9/named3.conf.in ns9/named.conf +rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 1 + +n=$((n + 1)) +echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)" +ret=0 +# prime +dig_with_opts @10.53.0.9 attackSecureDomain.net >dig.out.$n.prime || ret=1 +# check 'net' is poisoned. +dig_with_opts @10.53.0.9 diditwork.net. TXT >dig.out.$n.net || ret=1 +grep '^didItWork\.net\..*TXT.*"if you can see this record the attack worked"' dig.out.$n.net >/dev/null || ret=1 +# check 'sub.local.net' is poisoned. +dig_with_opts @10.53.0.9 sub.local.net TXT >dig.out.$n.sub || ret=1 +grep '^sub\.local\.net\..*TXT.*"if you see this attacker overrode local delegation"' dig.out.$n.sub >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)" +ret=0 +# prime +dig_with_opts @10.53.0.9 attackSecureDomain.net2 >dig.out.$n.prime || ret=1 +# check that net2/DNAME is cached +dig_with_opts @10.53.0.9 net2. DNAME >dig.out.$n.net2 || ret=1 +grep "ANSWER: 1," dig.out.$n.net2 >/dev/null || ret=1 +grep "net2\..*IN.DNAME.net\.example\.lll\." dig.out.$n.net2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# This test doesn't use any forwarder clauses but is here because it +# is similar to forwarders, as the set of servers that can populate +# the namespace is defined by the zone content. +# +echo_i "rechecking spoofed response scenarios glue below local zone" +copy_setports ns9/named4.conf.in ns9/named.conf +rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i +rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 1 + +n=$((n + 1)) +echo_i "checking sibling glue below zone ($n)" +ret=0 +# prime +dig_with_opts @10.53.0.9 sibling.tld >dig.out.$n.prime || ret=1 +# check for glue A record for sub.local.tld is not used +dig_with_opts @10.53.0.9 sub.local.tld TXT >dig.out.$n.sub || ret=1 +grep "ANSWER: 1," dig.out.$n.sub >/dev/null || ret=1 +grep 'sub\.local\.tld\..*IN.TXT."good"$' dig.out.$n.sub >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/forward/tests_sh_forward.py b/bin/tests/system/forward/tests_sh_forward.py new file mode 100644 index 0000000..0decea6 --- /dev/null +++ b/bin/tests/system/forward/tests_sh_forward.py @@ -0,0 +1,35 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "statschannel.out.*", + "ans*/ans.run", + "ns*/trusted.conf", + "ns1/K*", + "ns1/dsset-*", + "ns1/root.db", + "ns1/root.db.signed", + "ns2/named-tls.conf", + "ns2/options-tls.conf", + "ns3/trusted.conf", + "ns4/named-tls.conf", + "ns4/options-tls.conf", + "ns9/named_dump.db", + ] +) + + +def test_forward(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/forward/ula-inherited.conf b/bin/tests/system/forward/ula-inherited.conf new file mode 100644 index 0000000..1fb94b1 --- /dev/null +++ b/bin/tests/system/forward/ula-inherited.conf @@ -0,0 +1,17 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone d.f.ip6.arpa { + type forward; + forwarders { 1.2.3.4; }; +}; diff --git a/bin/tests/system/forward/ula-notinherited.conf b/bin/tests/system/forward/ula-notinherited.conf new file mode 100644 index 0000000..300001a --- /dev/null +++ b/bin/tests/system/forward/ula-notinherited.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone d.f.ip6.arpa { + type forward; + forward first; + forwarders { 1.2.3.4; }; +}; diff --git a/bin/tests/system/fromhex.pl b/bin/tests/system/fromhex.pl new file mode 100644 index 0000000..2a229e0 --- /dev/null +++ b/bin/tests/system/fromhex.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Converts hex ascii into raw data. +# (This can be used, for example, to construct input for "wire_data -d".) + +require 5.006.001; + +use strict; +use IO::File; + +sub usage { + print ("Usage: packet.pl [file]\n"); + exit 1; +} + +my $file = "STDIN"; +if (@ARGV >= 1) { + my $filename = shift @ARGV; + open FH, "<$filename" or die "$filename: $!"; + $file = "FH"; +} + +my $input = ""; +while (defined(my $line = <$file>) ) { + chomp $line; + $line =~ s/#.*$//; + $input .= $line; +} + +$input =~ s/\s+//g; +my $data = pack("H*", $input); +my $len = length $data; + +binmode(STDOUT); +print($data); +exit(0); diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh new file mode 100644 index 0000000..8922092 --- /dev/null +++ b/bin/tests/system/genzone.sh @@ -0,0 +1,520 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Set up a test zone +# +# Usage: genzone.sh primary-server-number secondary-server-number... +# +# e.g., "genzone.sh 2 3 4" means ns2 is the primary and ns3, ns4 +# are secondaries. +# + +primary="$1" + +cat < 'utf8_string', + en => 'utf8_string', + es => 'utf8_string', + fr => 'utf8_string', + ja => 'utf8_string', + 'pt-BR' => 'utf8_string', + ru => 'utf8_string', + 'zh-CN' => 'utf8_string', + + # production + accuracy_radius => 'uint16', + autonomous_system_number => 'uint32', + autonomous_system_organization => 'utf8_string', + average_income => 'uint32', + city => 'map', + code => 'utf8_string', + confidence => 'uint16', + connection_type => 'utf8_string', + continent => 'map', + country => 'map', + domain => 'utf8_string', + geoname_id => 'uint32', + ipv4_24 => 'uint32', + ipv4_32 => 'uint32', + ipv6_32 => 'uint32', + ipv6_48 => 'uint32', + ipv6_64 => 'uint32', + is_anonymous => 'boolean', + is_anonymous_proxy => 'boolean', + is_anonymous_vpn => 'boolean', + is_hosting_provider => 'boolean', + is_in_european_union => 'boolean', + is_legitimate_proxy => 'boolean', + is_public_proxy => 'boolean', + is_satellite_provider => 'boolean', + is_tor_exit_node => 'boolean', + iso_code => 'utf8_string', + isp => 'utf8_string', + latitude => 'double', + location => 'map', + longitude => 'double', + metro_code => 'uint16', + names => 'map', + organization => 'utf8_string', + population_density => 'uint32', + postal => 'map', + registered_country => 'map', + represented_country => 'map', + subdivisions => [ 'array', 'map' ], + time_zone => 'utf8_string', + traits => 'map', + traits => 'map', + type => 'utf8_string', + user_type => 'utf8_string', + + # for testing only + foo => 'utf8_string', + bar => 'utf8_string', + buzz => 'utf8_string', + our_value => 'utf8_string', + }; + + my $callback = sub { + my $key = shift; + + return $map->{$key} || die <<"ERROR"; +Unknown tree key '$key'. + +The universal_map_key_type_callback doesn't know what type to use for the passed +key. If you are adding a new key that will be used in a frozen tree / mmdb then +you should update the mapping in both our internal code and here. +ERROR + }; + + return $callback; +} + +sub _write_geoip2_db { + my $type = shift; + my $populate_all_networks_with_data = shift; + my $description = shift; + + my $writer = MaxMind::DB::Writer::Tree->new( + ip_version => 6, + record_size => 28, + ip_version => 6, + database_type => $type, + languages => [ 'en', $type eq 'GeoIP2-City' ? ('zh') : () ], + description => { + en => ( $type =~ s/-/ /gr ) + . " $description Database (fake GeoIP2 data, for example purposes only)", + $type eq 'GeoIP2-City' ? ( zh => '小型数据库' ) : (), + }, + alias_ipv6_to_ipv4 => 1, + map_key_type_callback => _universal_map_key_type_callback(), + remove_reserved_networks => 0, + ); + + _populate_all_networks( $writer, $populate_all_networks_with_data ) + if $populate_all_networks_with_data; + + my $value = shift; + my $nodes + = decode_json( read_binary("$Dir/$type.json") ); + + for my $node (@$nodes) { + for my $network ( keys %$node ) { + $writer->insert_network( + Net::Works::Network->new_from_string( string => $network ), + $node->{$network} + ); + } + } + + open my $output_fh, '>', "$Dir/$type.mmdb"; + $writer->write_tree($output_fh); + close $output_fh; + + return; +} + +sub _populate_all_networks { + my $writer = shift; + my $data = shift; + + my $max_uint128 = uint128(0) - 1; + my @networks = Net::Works::Network->range_as_subnets( + Net::Works::Address->new_from_integer( + integer => 0, + version => 6, + ), + Net::Works::Address->new_from_integer( + integer => $max_uint128, + version => 6, + ), + ); + + for my $network (@networks) { + $writer->insert_network( $network => $data ); + } +} + +main(); diff --git a/bin/tests/system/geoip2/ns2/example.db.in b/bin/tests/system/geoip2/ns2/example.db.in new file mode 100644 index 0000000..fa3874c --- /dev/null +++ b/bin/tests/system/geoip2/ns2/example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/geoip2/ns2/named1.conf.in b/bin/tests/system/geoip2/ns2/named1.conf.in new file mode 100644 index 0000000..2b01a5c --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named1.conf.in @@ -0,0 +1,108 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country country AU; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country country US; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country country GB; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db country country CA; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db country country CL; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db country country DE; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db country country EH; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view other { + match-clients { geoip db country country O1; }; + zone "example" { + type primary; + file "exampleother.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named10.conf.in b/bin/tests/system/geoip2/ns2/named10.conf.in new file mode 100644 index 0000000..5cac0f7 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named10.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip asnum 100001; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip asnum 100002; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip asnum 100003; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip asnum 100004; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip asnum 100005; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip asnum 100006; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip asnum 100007; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named11.conf.in b/bin/tests/system/geoip2/ns2/named11.conf.in new file mode 100644 index 0000000..b6d2a44 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named11.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip domain one.de; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip domain two.com; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip domain three.com; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip domain four.edu; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip domain five.es; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip domain six.it; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip domain seven.org; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named12.conf.in b/bin/tests/system/geoip2/ns2/named12.conf.in new file mode 100644 index 0000000..2528164 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named12.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +acl blocking { + geoip db country country AU; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; + blackhole { blocking; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/geoip2/ns2/named2.conf.in b/bin/tests/system/geoip2/ns2/named2.conf.in new file mode 100644 index 0000000..c28f15b --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named2.conf.in @@ -0,0 +1,108 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 127.0.0.1; 10.53.0.2; }; + listen-on-v6 { ::1; fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +acl gAU { geoip db country country AU; }; +acl gUS { geoip db country country US; }; +acl gGB { geoip db country country GB; }; +acl gCA { geoip db country country CA; }; +acl gCL { geoip db country country CL; }; +acl gDE { geoip db country country DE; }; +acl gEH { geoip db country country EH; }; + +view one { + match-clients { gAU; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { gUS; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { gGB; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { gCA; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { gCL; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { gDE; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { gEH; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "examplebogus.db"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named3.conf.in b/bin/tests/system/geoip2/ns2/named3.conf.in new file mode 100644 index 0000000..f3b35e5 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named3.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country country Australia; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country country "United States"; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country country "United Kingdom"; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip db country country Canada; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip db country country Chile; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip db country country Germany; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip db country country "Western Sahara"; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named4.conf.in b/bin/tests/system/geoip2/ns2/named4.conf.in new file mode 100644 index 0000000..7ccd200 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named4.conf.in @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip db country continent OC; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip db country continent NA; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip db country continent EU; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view five { + match-clients { geoip db country continent SA; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view seven { + match-clients { geoip db country continent AF; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named5.conf.in b/bin/tests/system/geoip2/ns2/named5.conf.in new file mode 100644 index 0000000..ec0b371 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named5.conf.in @@ -0,0 +1,92 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip region CA; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view three { + match-clients { geoip region OK; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip region VA; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip region GA; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip region CO; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip region AK; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named6.conf.in b/bin/tests/system/geoip2/ns2/named6.conf.in new file mode 100644 index 0000000..b2bb091 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named6.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip city "Redwood City"; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip city "Santa Cruz"; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip city "Oklahoma City"; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip city "Ashland"; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip city "Atlanta"; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip city "Morrison"; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip city "Ketchikan"; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named7.conf.in b/bin/tests/system/geoip2/ns2/named7.conf.in new file mode 100644 index 0000000..99b6960 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named7.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip isp "One Systems, Inc."; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip isp "Two Technology Ltd."; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip isp "Three Network Labs"; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip isp "Four University"; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip isp "Five Telecom"; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip isp "Six Company"; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip isp "Seven Communications"; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named8.conf.in b/bin/tests/system/geoip2/ns2/named8.conf.in new file mode 100644 index 0000000..4470ad6 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named8.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip org "One Systems, Inc."; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip org "Two Technology Ltd."; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip org "Three Network Labs"; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip org "Four University"; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip org "Five Telecom"; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip org "Six Company"; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip org "Seven Communications"; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/ns2/named9.conf.in b/bin/tests/system/geoip2/ns2/named9.conf.in new file mode 100644 index 0000000..5aee393 --- /dev/null +++ b/bin/tests/system/geoip2/ns2/named9.conf.in @@ -0,0 +1,100 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + dnssec-validation no; + geoip-directory "../data"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view one { + match-clients { geoip asnum "AS100001"; }; + zone "example" { + type primary; + file "example1.db"; + }; +}; + +view two { + match-clients { geoip asnum "AS100002"; }; + zone "example" { + type primary; + file "example2.db"; + }; +}; + +view three { + match-clients { geoip asnum "AS100003"; }; + zone "example" { + type primary; + file "example3.db"; + }; +}; + +view four { + match-clients { geoip asnum "AS100004"; }; + zone "example" { + type primary; + file "example4.db"; + }; +}; + +view five { + match-clients { geoip asnum "AS100005"; }; + zone "example" { + type primary; + file "example5.db"; + }; +}; + +view six { + match-clients { geoip asnum "AS100006"; }; + zone "example" { + type primary; + file "example6.db"; + }; +}; + +view seven { + match-clients { geoip asnum "AS100007"; }; + zone "example" { + type primary; + file "example7.db"; + }; +}; + +view none { + match-clients { any; }; + zone "example" { + type primary; + file "example.db.in"; + }; +}; diff --git a/bin/tests/system/geoip2/prereq.sh b/bin/tests/system/geoip2/prereq.sh new file mode 100644 index 0000000..942888e --- /dev/null +++ b/bin/tests/system/geoip2/prereq.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --have-geoip2 || { + echo_i "This test requires GeoIP support." >&2 + exit 255 +} +exit 0 diff --git a/bin/tests/system/geoip2/setup.sh b/bin/tests/system/geoip2/setup.sh new file mode 100644 index 0000000..b9ec49f --- /dev/null +++ b/bin/tests/system/geoip2/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns2/named1.conf.in ns2/named.conf + +for i in 1 2 3 4 5 6 7 other bogus; do + cp ns2/example.db.in ns2/example${i}.db + echo "@ IN TXT \"$i\"" >>ns2/example$i.db +done diff --git a/bin/tests/system/geoip2/tests.sh b/bin/tests/system/geoip2/tests.sh new file mode 100644 index 0000000..ac1df74 --- /dev/null +++ b/bin/tests/system/geoip2/tests.sh @@ -0,0 +1,477 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +short -p ${PORT} @10.53.0.2" +DIGOPTS6="+tcp +short -p ${PORT} @fd92:7065:b8e:ffff::2 -6" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +for conf in conf/good*.conf; do + n=$((n + 1)) + echo_i "checking that $conf is accepted ($n)" + ret=0 + $CHECKCONF "$conf" || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for conf in conf/bad*.conf; do + n=$((n + 1)) + echo_i "checking that $conf is rejected ($n)" + ret=0 + $CHECKCONF "$conf" >/dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +n=$((n + 1)) +echo_i "checking Country database by code using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking Country database by code using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 country code test" +fi + +echo_i "reloading server" +copy_setports ns2/named2.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking Country database with nested ACLs using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking Country database with nested ACLs using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 country nested ACL test" +fi + +echo_i "reloading server" +copy_setports ns2/named3.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking Country database by name using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking Country database by name using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 country name test" +fi + +echo_i "reloading server" +copy_setports ns2/named4.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking Country database by continent code using IPv4 ($n)" +ret=0 +lret=0 +# deliberately skipping 4 and 6 as they have duplicate continents +for i in 1 2 3 5 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking Country database by continent code using IPv6 ($n)" + ret=0 + lret=0 + # deliberately skipping 4 and 6 as they have duplicate continents + for i in 1 2 3 5 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 continent code test" +fi + +echo_i "reloading server" +copy_setports ns2/named5.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking City database by region code using IPv4 ($n)" +ret=0 +lret=0 +# skipping 2 on purpose here; it has the same region code as 1 +for i in 1 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking City database by region code using IPv6 ($n)" + ret=0 + lret=0 + # skipping 2 on purpose here; it has the same region code as 1 + for i in 1 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 region code test" +fi + +n=$((n + 1)) +echo_i "reloading server" +copy_setports ns2/named6.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking City database by city name using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking City database by city name using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 city test" +fi + +echo_i "reloading server" +copy_setports ns2/named7.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking ISP database using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking ISP database using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 ISP test" +fi + +echo_i "reloading server" +copy_setports ns2/named8.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking ASN database by org name using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking ASN database by org name using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 ASN test" +fi + +echo_i "reloading server" +copy_setports ns2/named9.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking GeoIP6 ASN database, ASNNNN only, using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking ASN database, ASNNNN only, using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 ASN test" +fi + +echo_i "reloading server" +copy_setports ns2/named10.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking GeoIP6 ASN database, NNNN only, using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking ASN database, NNNN only, using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 ASN test" +fi + +echo_i "reloading server" +copy_setports ns2/named11.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking Domain database using IPv4 ($n)" +ret=0 +lret=0 +for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS txt example -b 10.53.0.$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break +done +[ $lret -eq 1 ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +if testsock6 fd92:7065:b8e:ffff::3; then + n=$((n + 1)) + echo_i "checking Domain database using IPv6 ($n)" + ret=0 + lret=0 + for i in 1 2 3 4 5 6 7; do + $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::$i >dig.out.ns2.test$n.$i || lret=1 + j=$(cat dig.out.ns2.test$n.$i | tr -d '"') + [ "$i" = "$j" ] || lret=1 + [ $lret -eq 1 ] && break + done + [ $lret -eq 1 ] && ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) +else + echo_i "IPv6 unavailable; skipping IPv6 Domain test" +fi + +echo_i "reloading server" +copy_setports ns2/named12.conf.in ns2/named.conf +$CHECKCONF ns2/named.conf | cat_i +rndc_reload ns2 10.53.0.2 +sleep 3 + +n=$((n + 1)) +echo_i "checking geoip blackhole ACL ($n)" +ret=0 +$DIG $DIGOPTS txt example -b 10.53.0.7 >dig.out.ns2.test$n || ret=1 +$RNDCCMD 10.53.0.2 status 2>&1 >rndc.out.ns2.test$n || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/geoip2/tests_sh_geoip2.py b/bin/tests/system/geoip2/tests_sh_geoip2.py new file mode 100644 index 0000000..e0dc60b --- /dev/null +++ b/bin/tests/system/geoip2/tests_sh_geoip2.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "ns2/example*.db", + ] +) + + +def test_geoip2(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/get_core_dumps.sh b/bin/tests/system/get_core_dumps.sh new file mode 100755 index 0000000..1469c3c --- /dev/null +++ b/bin/tests/system/get_core_dumps.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +dir=$(dirname "$0") +. "$dir/conf.sh" + +systest=$1 +status=0 + +export SYSTESTDIR="${TOP_BUILDDIR}/bin/tests/system/${systest}" + +get_core_dumps() { + find "$SYSTESTDIR/" \( -name 'core' -or -name 'core.*' -or -name '*.core' \) ! -name '*.gz' ! -name '*.txt' | sort +} + +core_dumps=$(get_core_dumps | tr '\n' ' ') +if [ -n "$core_dumps" ]; then + status=1 + echoinfo "I:$systest:Core dump(s) found: $core_dumps" + get_core_dumps | while read -r coredump; do + echoinfo "D:$systest:backtrace from $coredump:" + echoinfo "D:$systest:--------------------------------------------------------------------------------" + binary=$(gdb --batch --core="$coredump" 2>/dev/null | sed -ne "s|Core was generated by \`\([^' ]*\)[' ].*|\1|p") + if [ ! -f "${binary}" ]; then + binary=$(find "${TOP_BUILDDIR}" -path "*/.libs/${binary}" -type f) + fi + "${TOP_BUILDDIR}/libtool" --mode=execute gdb \ + -batch \ + -ex bt \ + -core="$coredump" \ + -- \ + "$binary" 2>/dev/null | sed -n '/^Core was generated by/,$p' | cat_d + echoinfo "D:$systest:--------------------------------------------------------------------------------" + coredump_backtrace="${coredump}-backtrace.txt" + echoinfo "D:$systest:full backtrace from $coredump saved in $coredump_backtrace" + "${TOP_BUILDDIR}/libtool" --mode=execute gdb \ + -batch \ + -command="${TOP_SRCDIR}/bin/tests/system/run.gdb" \ + -core="$coredump" \ + -- \ + "$binary" >"$coredump_backtrace" 2>&1 + echoinfo "D:$systest:core dump $coredump archived as $coredump.gz" + gzip -1 "${coredump}" + done +fi + +assertion_failures=$(find "$SYSTESTDIR/" -name named.run -exec grep "assertion failure" {} + | wc -l) +if [ "$assertion_failures" -ne 0 ]; then + status=1 + echoinfo "I:$systest:$assertion_failures assertion failure(s) found" +fi + +tsan_failures=$(find "$SYSTESTDIR/" -name 'tsan.*' | wc -l) +if [ "$tsan_failures" -ne 0 ]; then + status=1 + echoinfo "I:$systest:$tsan_failures TSAN sanitizer report(s) found" + find "$SYSTESTDIR/" -name 'tsan.*' -exec grep "SUMMARY: " {} + | sort -u | cat_d +fi + +exit $status diff --git a/bin/tests/system/glue/ns1/named.conf.in b/bin/tests/system/glue/ns1/named.conf.in new file mode 100644 index 0000000..19595a9 --- /dev/null +++ b/bin/tests/system/glue/ns1/named.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "root-servers.nil" { + type primary; + file "root-servers.nil.db"; +}; + +zone "net" { + type primary; + file "net.db"; +}; + +zone "tc-test-unsigned" { + type master; + file "tc-test-unsigned.db"; +}; + +zone "tc-test-signed" { + type master; + file "tc-test-signed.db.signed"; +}; diff --git a/bin/tests/system/glue/ns1/net.db b/bin/tests/system/glue/ns1/net.db new file mode 100644 index 0000000..db784cc --- /dev/null +++ b/bin/tests/system/glue/ns1/net.db @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN net. +$TTL 300 +@ IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS a.root-servers.nil. + +; FI. authoritative servers, for the FI. glue test. +uu.net. NS ns.uu.net. +NS.UU.NET. 172800 IN A 137.39.1.3 +eu.net. NS ns.eu.net. +NS.EU.NET. 172800 IN A 192.16.202.11 + +; Referral outside of server authority, but with glue records present. +; Don't hand out the glue. +example.net. NS ns1.example. +example.net. NS ns2.example. +ns1.example. 172800 IN A 1.1.1.1 +ns2.example. 172800 IN A 2.2.2.2 diff --git a/bin/tests/system/glue/ns1/root-servers.nil.db b/bin/tests/system/glue/ns1/root-servers.nil.db new file mode 100644 index 0000000..1475aed --- /dev/null +++ b/bin/tests/system/glue/ns1/root-servers.nil.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3600 + ) + NS a +a A 10.53.0.1 +b A 10.53.0.2 + + + diff --git a/bin/tests/system/glue/ns1/root.db b/bin/tests/system/glue/ns1/root.db new file mode 100644 index 0000000..debdf01 --- /dev/null +++ b/bin/tests/system/glue/ns1/root.db @@ -0,0 +1,44 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. + +root-servers.nil. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +; Delegate some domains that contain name servers for the sample +; ccTLDs below. +net. 172800 IN NS a.root-servers.nil. + +; +; A sample ccTLD +; +fi. 172800 IN NS NS.TELE.fi. +fi. 172800 IN NS PRIFI.EUNET.fi. +fi. 172800 IN NS NS.UU.NET. +fi. 172800 IN NS T.NS.VERIO.NET. +fi. 172800 IN NS HYDRA.HELSINKI.fi. +fi. 172800 IN NS NS.EU.NET. +NS.TELE.fi. 172800 IN A 193.210.18.18 +NS.TELE.fi. 172800 IN A 193.210.19.19 +PRIFI.EUNET.fi. 172800 IN A 193.66.1.146 +NS.UU.NET. 172800 IN A 137.39.1.3 +T.NS.VERIO.NET. 172800 IN A 192.67.14.16 +HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29 +NS.EU.NET. 172800 IN A 192.16.202.11 diff --git a/bin/tests/system/glue/ns1/sign.sh b/bin/tests/system/glue/ns1/sign.sh new file mode 100644 index 0000000..7a68626 --- /dev/null +++ b/bin/tests/system/glue/ns1/sign.sh @@ -0,0 +1,27 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=tc-test-signed +infile=tc-test-signed.db.in +zonefile=tc-test-signed.db + +# The signing algorithm and key sizes used here are NOT arbitrary - they have +# been carefully chosen to ensure that the signed referral response checked in +# the test will be around 512 bytes in size with glue records excluded. Please +# keep this in mind when updating signing algorithms used in system tests. +keyname=$($KEYGEN -q -a RSASHA256 -b 2048 -n zone $zone) +cat "$infile" "$keyname.key" >"$zonefile" + +$SIGNER -P -o $zone $zonefile >/dev/null diff --git a/bin/tests/system/glue/ns1/tc-test-signed.db.in b/bin/tests/system/glue/ns1/tc-test-signed.db.in new file mode 100644 index 0000000..5c0181d --- /dev/null +++ b/bin/tests/system/glue/ns1/tc-test-signed.db.in @@ -0,0 +1,55 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; CAUTION: Contents of this zone were carefully crafted so that the responses +; to the queries used in the "glue" system test have a very specific size. +; Editing this zone is not recommended as it may break the relevant checks. + +$TTL 300 +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3600 + ) + NS a +a A 10.53.0.1 + +subdomain-a NS 0123456789.subdomain-a + NS 0123456.subdomain-a + NS 0123.subdomain-a + +0123456789.subdomain-a A 10.53.0.1 +0123456.subdomain-a A 10.53.0.1 +0123.subdomain-a A 10.53.0.1 + +subdomain-aaaa NS 0123456789.subdomain-aaaa + NS 0123456.subdomain-aaaa + NS 0123.subdomain-aaaa + +0123456789.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +0123456.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +0123.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 + +subdomain-both NS 0123456789.subdomain-both + NS 0123456.subdomain-both + NS 0123.subdomain-both + NS 0.subdomain-both + +0123456789.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +0123456.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +0123.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +0.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/glue/ns1/tc-test-unsigned.db b/bin/tests/system/glue/ns1/tc-test-unsigned.db new file mode 100644 index 0000000..de326c0 --- /dev/null +++ b/bin/tests/system/glue/ns1/tc-test-unsigned.db @@ -0,0 +1,112 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; CAUTION: Contents of this zone were carefully crafted so that the responses +; to the queries used in the "glue" system test have a very specific size. +; Editing this zone is not recommended as it may break the relevant checks. + +$TTL 300 +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3600 + ) + NS a +a A 10.53.0.1 + +subdomain-a NS abcdefghijklmnopqrstuvwxyz.subdomain-a + NS bcdefghijklmnopqrstuvwxyz.subdomain-a + NS cdefghijklmnopqrstuvwxyz.subdomain-a + NS defghijklmnopqrstuvwxyz.subdomain-a + NS efghijklmnopqrstuvwxyz.subdomain-a + NS fghijklmnopqrstuvwxyz.subdomain-a + NS ghijklmnopqrstuvwxyz.subdomain-a + NS hijklmnopqrstuvwxyz.subdomain-a + NS ijklmnopqrstuvwxyz.subdomain-a + NS jklmnopqrstuvwxyz.subdomain-a + NS klmnopqrstuvwxyz.subdomain-a + NS lmnopqrstuvwxyz.subdomain-a + NS mnopqrstuvwxyz.subdomain-a + +abcdefghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +bcdefghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +cdefghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +defghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +efghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +fghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +ghijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +hijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +ijklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +jklmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +klmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +lmnopqrstuvwxyz.subdomain-a A 10.53.0.1 +mnopqrstuvwxyz.subdomain-a A 10.53.0.1 + +subdomain-aaaa NS abcdefghijklmnopqrstuvwxyz.subdomain-aaaa + NS bcdefghijklmnopqrstuvwxyz.subdomain-aaaa + NS cdefghijklmnopqrstuvwxyz.subdomain-aaaa + NS defghijklmnopqrstuvwxyz.subdomain-aaaa + NS efghijklmnopqrstuvwxyz.subdomain-aaaa + NS fghijklmnopqrstuvwxyz.subdomain-aaaa + NS ghijklmnopqrstuvwxyz.subdomain-aaaa + NS hijklmnopqrstuvwxyz.subdomain-aaaa + NS ijklmnopqrstuvwxyz.subdomain-aaaa + NS jklmnopqrstuvwxyz.subdomain-aaaa + NS klmnopqrstuvwxyz.subdomain-aaaa + NS lmnopqrstuvwxyz.subdomain-aaaa + NS mnopqrstuvwxyz.subdomain-aaaa + +abcdefghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +bcdefghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +cdefghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +defghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +efghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +fghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +ghijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +hijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +ijklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +jklmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +klmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +lmnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 +mnopqrstuvwxyz.subdomain-aaaa AAAA fd92:7065:b8e:ffff::1 + +subdomain-both NS abcdefghijklmnopqrstuvwxyz.subdomain-both + NS bcdefghijklmnopqrstuvwxyz.subdomain-both + NS cdefghijklmnopqrstuvwxyz.subdomain-both + NS defghijklmnopqrstuvwxyz.subdomain-both + NS efghijklmnopqrstuvwxyz.subdomain-both + NS fghijklmnopqrstuvwxyz.subdomain-both + NS ghijklmnopqrstuvwxyz.subdomain-both + NS hijklmnopqrstuvwxyz.subdomain-both + NS ijklmnopqrstuvwxyz.subdomain-both + NS jklmnopqrstuvwxyz.subdomain-both + NS klmnopqrstuvwxyz.subdomain-both + NS lmnopqrstuvwxyz.subdomain-both + NS mnopqrstuvwxyz.subdomain-both + +abcdefghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +bcdefghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +cdefghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +defghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +efghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +fghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +ghijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 +hijklmnopqrstuvwxyz.subdomain-both A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/glue/setup.sh b/bin/tests/system/glue/setup.sh new file mode 100644 index 0000000..6dcede5 --- /dev/null +++ b/bin/tests/system/glue/setup.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf + +(cd ns1 && $SHELL sign.sh) diff --git a/bin/tests/system/glue/tests_glue.py b/bin/tests/system/glue/tests_glue.py new file mode 100644 index 0000000..f346998 --- /dev/null +++ b/bin/tests/system/glue/tests_glue.py @@ -0,0 +1,113 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + + +import dns.message +import pytest + +import isctest + +pytest.importorskip("dns", minversion="2.0.0") + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns1/*", + "ns1/dsset-*", + "ns1/tc-test-signed.db", + "ns1/tc-test-signed.db.signed", + ] +) + + +def test_glue_full_glue_set(): + """test that a ccTLD referral gets a full glue set from the root zone""" + msg = dns.message.make_query("foo.bar.fi", "A") + msg.flags &= ~dns.flags.RD + res = isctest.query.udp(msg, "10.53.0.1") + + answer = """;ANSWER +;AUTHORITY +fi. 172800 IN NS HYDRA.HELSINKI.fi. +fi. 172800 IN NS NS.EU.NET. +fi. 172800 IN NS NS.UU.NET. +fi. 172800 IN NS NS.TELE.fi. +fi. 172800 IN NS T.NS.VERIO.NET. +fi. 172800 IN NS PRIFI.EUNET.fi. +;ADDITIONAL +NS.TELE.fi. 172800 IN A 193.210.18.18 +NS.TELE.fi. 172800 IN A 193.210.19.19 +PRIFI.EUNET.fi. 172800 IN A 193.66.1.146 +HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29 +NS.EU.NET. 172800 IN A 192.16.202.11 +T.NS.VERIO.NET. 172800 IN A 192.67.14.16 +NS.UU.NET. 172800 IN A 137.39.1.3 +""" + expected_answer = dns.message.from_text(answer) + + isctest.check.noerror(res) + isctest.check.rrsets_equal(res.answer, expected_answer.answer) + isctest.check.rrsets_equal(res.authority, expected_answer.authority) + isctest.check.rrsets_equal(res.additional, expected_answer.additional) + + +def test_glue_no_glue_set(): + """test that out-of-zone glue is not found""" + msg = dns.message.make_query("example.net.", "A") + msg.flags &= ~dns.flags.RD + res = isctest.query.udp(msg, "10.53.0.1") + + answer = """;ANSWER +;AUTHORITY +example.net. 300 IN NS ns2.example. +example.net. 300 IN NS ns1.example. +;ADDITIONAL +""" + expected_answer = dns.message.from_text(answer) + + isctest.check.noerror(res) + isctest.check.rrsets_equal(res.answer, expected_answer.answer) + isctest.check.rrsets_equal(res.authority, expected_answer.authority) + isctest.check.rrsets_equal(res.additional, expected_answer.additional) + + +@pytest.mark.parametrize( + "qname,dnssec", + [ + # test truncation for unsigned referrals close to UDP packet size limit (A glue) + ("foo.subdomain-a.tc-test-unsigned.", False), + # test truncation for unsigned referrals close to UDP packet size limit (AAAA glue) + ("foo.subdomain-aaaa.tc-test-unsigned.", False), + # test truncation for unsigned referrals close to UDP packet size limit (A+AAAA glue) + ("foo.subdomain-both.tc-test-unsigned.", False), + # test truncation for signed referrals close to UDP packet size limit (A glue) + ("foo.subdomain-a.tc-test-signed.", True), + # test truncation for signed referrals close to UDP packet size limit (AAAA glue) + ("foo.subdomain-aaaa.tc-test-signed.", True), + # test truncation for signed referrals close to UDP packet size limit (A+AAAA glue) + ("foo.subdomain-both.tc-test-signed.", True), + ], +) +def test_glue_truncation(qname, dnssec): + msg = dns.message.make_query(qname, "A") + msg.flags &= ~dns.flags.RD + if dnssec: + msg.use_edns( + payload=512, + # Zones used in this test were created with dig in mind that, unlike dnspython, + # by default, sets a cookie. Given that the message size must be close to the + # truncation limit, we also need to set a cookie here. + options=[dns.edns.GenericOption(dns.edns.OptionType.COOKIE, b"0xda13cc")], + ) + msg.want_dnssec(wanted=True) + res = isctest.query.udp(msg, "10.53.0.1") + + isctest.check.noerror(res) + assert res.flags & dns.flags.TC diff --git a/bin/tests/system/hooks/driver/Makefile.am b/bin/tests/system/hooks/driver/Makefile.am new file mode 100644 index 0000000..b0c4b79 --- /dev/null +++ b/bin/tests/system/hooks/driver/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) \ + $(LIBISCCFG_CFLAGS) + +noinst_LTLIBRARIES = test-async.la + +test_async_la_SOURCES = test-async.c +test_async_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) diff --git a/bin/tests/system/hooks/driver/Makefile.in b/bin/tests/system/hooks/driver/Makefile.in new file mode 100644 index 0000000..8200552 --- /dev/null +++ b/bin/tests/system/hooks/driver/Makefile.in @@ -0,0 +1,785 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = bin/tests/system/hooks/driver +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +test_async_la_LIBADD = +am_test_async_la_OBJECTS = test-async.lo +test_async_la_OBJECTS = $(am_test_async_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +test_async_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(test_async_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/test-async.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_async_la_SOURCES) +DIST_SOURCES = $(test_async_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = \ + $(STD_CFLAGS) + +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) \ + $(LIBNS_CFLAGS) $(LIBISCCFG_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = test-async.la +test_async_la_SOURCES = test-async.c +test_async_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/hooks/driver/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/system/hooks/driver/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +test-async.la: $(test_async_la_OBJECTS) $(test_async_la_DEPENDENCIES) $(EXTRA_test_async_la_DEPENDENCIES) + $(AM_V_CCLD)$(test_async_la_LINK) $(test_async_la_OBJECTS) $(test_async_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-async.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/test-async.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/test-async.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/system/hooks/driver/test-async.c b/bin/tests/system/hooks/driver/test-async.c new file mode 100644 index 0000000..160ae63 --- /dev/null +++ b/bin/tests/system/hooks/driver/test-async.c @@ -0,0 +1,350 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/* aliases for the exported symbols */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define CHECK(op) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + goto cleanup; \ + } \ + } while (0) + +/* + * Persistent data for use by this module. This will be associated + * with client object address in the hash table, and will remain + * accessible until the client object is detached. + */ +typedef struct async_instance { + ns_plugin_t *module; + isc_mem_t *mctx; + isc_ht_t *ht; + isc_mutex_t hlock; + isc_log_t *lctx; +} async_instance_t; + +typedef struct state { + bool async; + ns_hook_resume_t *rev; + ns_hookpoint_t hookpoint; + isc_result_t origresult; +} state_t; + +/* + * Forward declarations of functions referenced in install_hooks(). + */ +static ns_hookresult_t +async_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +async_query_done_begin(void *arg, void *cbdata, isc_result_t *resp); +static ns_hookresult_t +async_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp); + +/*% + * Register the functions to be called at each hook point in 'hooktable', using + * memory context 'mctx' for allocating copies of stack-allocated structures + * passed to ns_hook_add(). Make sure 'inst' will be passed as the 'cbdata' + * argument to every callback. + */ +static void +install_hooks(ns_hooktable_t *hooktable, isc_mem_t *mctx, + async_instance_t *inst) { + const ns_hook_t async_init = { + .action = async_qctx_initialize, + .action_data = inst, + }; + const ns_hook_t async_donebegin = { + .action = async_query_done_begin, + .action_data = inst, + }; + const ns_hook_t async_destroy = { + .action = async_qctx_destroy, + .action_data = inst, + }; + + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_INITIALIZED, &async_init); + ns_hook_add(hooktable, mctx, NS_QUERY_DONE_BEGIN, &async_donebegin); + ns_hook_add(hooktable, mctx, NS_QUERY_QCTX_DESTROYED, &async_destroy); +} + +static void +logmsg(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + isc_log_write(ns_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_INFO, fmt, ap); + va_end(ap); +} + +/** +** Mandatory plugin API functions: +** +** - plugin_destroy +** - plugin_register +** - plugin_version +** - plugin_check +**/ + +/* + * Called by ns_plugin_register() to initialize the plugin and + * register hook functions into the view hook table. + */ +isc_result_t +plugin_register(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx, ns_hooktable_t *hooktable, void **instp) { + async_instance_t *inst = NULL; + + UNUSED(parameters); + UNUSED(cfg); + UNUSED(actx); + + isc_log_write(lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_INFO, + "registering 'test-async' module from %s:%lu", cfg_file, + cfg_line); + + inst = isc_mem_get(mctx, sizeof(*inst)); + *inst = (async_instance_t){ .mctx = NULL }; + isc_mem_attach(mctx, &inst->mctx); + + isc_ht_init(&inst->ht, mctx, 1, ISC_HT_CASE_SENSITIVE); + isc_mutex_init(&inst->hlock); + + /* + * Set hook points in the view's hooktable. + */ + install_hooks(hooktable, mctx, inst); + + *instp = inst; + + return ISC_R_SUCCESS; +} + +isc_result_t +plugin_check(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, isc_log_t *lctx, + void *actx) { + UNUSED(parameters); + UNUSED(cfg); + UNUSED(cfg_file); + UNUSED(cfg_line); + UNUSED(mctx); + UNUSED(lctx); + UNUSED(actx); + + return ISC_R_SUCCESS; +} + +/* + * Called by ns_plugins_free(); frees memory allocated by + * the module when it was registered. + */ +void +plugin_destroy(void **instp) { + async_instance_t *inst = (async_instance_t *)*instp; + + if (inst->ht != NULL) { + isc_ht_destroy(&inst->ht); + isc_mutex_destroy(&inst->hlock); + } + + isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst)); + *instp = NULL; + + return; +} + +/* + * Returns plugin API version for compatibility checks. + */ +int +plugin_version(void) { + return NS_PLUGIN_VERSION; +} + +static state_t * +client_state_get(const query_ctx_t *qctx, async_instance_t *inst) { + state_t *state = NULL; + isc_result_t result; + + LOCK(&inst->hlock); + result = isc_ht_find(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), (void **)&state); + UNLOCK(&inst->hlock); + + return result == ISC_R_SUCCESS ? state : NULL; +} + +static void +client_state_create(const query_ctx_t *qctx, async_instance_t *inst) { + state_t *state = NULL; + isc_result_t result; + + state = isc_mem_get(inst->mctx, sizeof(*state)); + *state = (state_t){ .async = false }; + + LOCK(&inst->hlock); + result = isc_ht_add(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client), state); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +static void +client_state_destroy(const query_ctx_t *qctx, async_instance_t *inst) { + state_t *state = client_state_get(qctx, inst); + isc_result_t result; + + if (state == NULL) { + return; + } + + LOCK(&inst->hlock); + result = isc_ht_delete(inst->ht, (const unsigned char *)&qctx->client, + sizeof(qctx->client)); + UNLOCK(&inst->hlock); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + isc_mem_put(inst->mctx, state, sizeof(*state)); +} + +static ns_hookresult_t +async_qctx_initialize(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + async_instance_t *inst = (async_instance_t *)cbdata; + state_t *state = NULL; + + logmsg("qctx init hook"); + *resp = ISC_R_UNSET; + + state = client_state_get(qctx, inst); + if (state == NULL) { + client_state_create(qctx, inst); + } + + return NS_HOOK_CONTINUE; +} + +static void +cancelasync(ns_hookasync_t *hctx) { + UNUSED(hctx); + logmsg("cancelasync"); +} + +static void +destroyasync(ns_hookasync_t **ctxp) { + ns_hookasync_t *ctx = *ctxp; + + logmsg("destroyasync"); + *ctxp = NULL; + isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); +} + +static isc_result_t +doasync(query_ctx_t *qctx, isc_mem_t *mctx, void *arg, isc_loop_t *loop, + isc_job_cb cb, void *evarg, ns_hookasync_t **ctxp) { + ns_hook_resume_t *rev = isc_mem_get(mctx, sizeof(*rev)); + ns_hookasync_t *ctx = isc_mem_get(mctx, sizeof(*ctx)); + state_t *state = (state_t *)arg; + + logmsg("doasync"); + *ctx = (ns_hookasync_t){ + .cancel = cancelasync, + .destroy = destroyasync, + }; + isc_mem_attach(mctx, &ctx->mctx); + + qctx->result = DNS_R_NOTIMP; + *rev = (ns_hook_resume_t){ + .hookpoint = state->hookpoint, + .origresult = qctx->result, + .saved_qctx = qctx, + .ctx = ctx, + .arg = evarg, + }; + + state->rev = rev; + + isc_async_run(loop, cb, rev); + + *ctxp = ctx; + return ISC_R_SUCCESS; +} + +static ns_hookresult_t +async_query_done_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + async_instance_t *inst = (async_instance_t *)cbdata; + state_t *state = client_state_get(qctx, inst); + + UNUSED(qctx); + UNUSED(cbdata); + UNUSED(state); + + logmsg("done begin hook"); + if (state->async) { + /* resuming */ + state->async = false; + return NS_HOOK_CONTINUE; + } + + /* initial call */ + state->async = true; + state->hookpoint = NS_QUERY_DONE_BEGIN; + state->origresult = *resp; + ns_query_hookasync(qctx, doasync, state); + return NS_HOOK_RETURN; +} + +static ns_hookresult_t +async_qctx_destroy(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + async_instance_t *inst = (async_instance_t *)cbdata; + + logmsg("qctx destroy hook"); + *resp = ISC_R_UNSET; + + if (!qctx->detach_client) { + return NS_HOOK_CONTINUE; + } + + client_state_destroy(qctx, inst); + + return NS_HOOK_CONTINUE; +} diff --git a/bin/tests/system/hooks/ns1/example.db b/bin/tests/system/hooks/ns1/example.db new file mode 100644 index 0000000..1d7173f --- /dev/null +++ b/bin/tests/system/hooks/ns1/example.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + +a A 1.1.1.1 +mx A 2.2.2.2 diff --git a/bin/tests/system/hooks/ns1/named.conf.j2 b/bin/tests/system/hooks/ns1/named.conf.j2 new file mode 100644 index 0000000..30ae85a --- /dev/null +++ b/bin/tests/system/hooks/ns1/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + recursion no; + dnssec-validation yes; + notify yes; + minimal-responses no; +}; + +trust-anchors { }; + +plugin query "../driver/.libs/test-async.so"; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "example.com" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/hooks/tests_async_plugin.py b/bin/tests/system/hooks/tests_async_plugin.py new file mode 100644 index 0000000..ac89c85 --- /dev/null +++ b/bin/tests/system/hooks/tests_async_plugin.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest +import isctest + +pytest.importorskip("dns") +import dns.message + + +def test_async_hook(): + msg = dns.message.make_query("example.com.", "A") + res = isctest.query.udp(msg, "10.53.0.1") + # the test-async plugin changes the status of any positive answer to NOTIMP + isctest.check.notimp(res) diff --git a/bin/tests/system/host/ns1/example.net.db b/bin/tests/system/host/ns1/example.net.db new file mode 100644 index 0000000..73aeeb1 --- /dev/null +++ b/bin/tests/system/host/ns1/example.net.db @@ -0,0 +1,31 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 + +@ 86400 IN SOA ns1 hostmaster ( + 1397051952 ; "SER0" + 5 + 5 + 1814400 + 3600 ) +@ NS ns1 +ns1 A 10.53.0.1 + +a-only A 1.2.3.4 +aaaa-only AAAA 2001::ffff + +dual A 1.2.3.4 + AAAA 2001::ffff + +cname-a-only CNAME a-only +cname-aaaa-only CNAME aaaa-only +cname-dual CNAME dual diff --git a/bin/tests/system/host/ns1/named.conf.in b/bin/tests/system/host/ns1/named.conf.in new file mode 100644 index 0000000..8338a9c --- /dev/null +++ b/bin/tests/system/host/ns1/named.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "example.net" { + type primary; + file "example.net.db"; +}; diff --git a/bin/tests/system/host/setup.sh b/bin/tests/system/host/setup.sh new file mode 100644 index 0000000..15300ed --- /dev/null +++ b/bin/tests/system/host/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 >ns1/example.db + +copy_setports ns1/named.conf.in ns1/named.conf diff --git a/bin/tests/system/host/tests.sh b/bin/tests/system/host/tests.sh new file mode 100644 index 0000000..4bc3bf9 --- /dev/null +++ b/bin/tests/system/host/tests.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck disable=SC2086 +. ../conf.sh + +status=0 +n=0 + +n=$((n + 1)) +echo_i "Check A only lookup ($n)" +ret=0 +$HOST -p ${PORT} a-only.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check AAAA only lookup ($n)" +ret=0 +$HOST -p ${PORT} aaaa-only.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check dual A + AAAA lookup ($n)" +ret=0 +$HOST -p ${PORT} dual.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +grep "2001::ffff" host.out${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to A only lookup ($n)" +ret=0 +$HOST -p ${PORT} cname-a-only.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to AAAA only lookup ($n)" +ret=0 +$HOST -p ${PORT} cname-aaaa-only.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to dual A + AAAA lookup ($n)" +ret=0 +$HOST -p ${PORT} cname-dual.example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1 +lines=$(wc -l host.err${n} >host.out${n} || ret=1 +lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" host.out${n}) +test $lines -eq 1 || ret=1 +lines=$(grep -c 'example.net has SOA record ns1.example.net. hostmaster.example.net. 1397051952 5 5 1814400 3600' host.out${n}) +test $lines -eq 1 || ret=1 +lines=$(grep -c 'example.net name server ns1.example.net.' host.out${n}) +test $lines -eq 1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/host/tests_sh_host.py b/bin/tests/system/host/tests_sh_host.py new file mode 100644 index 0000000..b605160 --- /dev/null +++ b/bin/tests/system/host/tests_sh_host.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "host.err*", + "host.out*", + "ns1/example.db", + ] +) + + +def test_host(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/idna/ns1/named.conf.j2 b/bin/tests/system/idna/ns1/named.conf.j2 new file mode 100644 index 0000000..df552bd --- /dev/null +++ b/bin/tests/system/idna/ns1/named.conf.j2 @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/idna/ns1/root.db b/bin/tests/system/idna/ns1/root.db new file mode 100644 index 0000000..b43cc40 --- /dev/null +++ b/bin/tests/system/idna/ns1/root.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +a.root-servers.nil. AAAA fd92:7065:b8e:ffff::1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +ns2.example. AAAA fd92:7065:b8e:ffff::2 diff --git a/bin/tests/system/idna/tests.sh b/bin/tests/system/idna/tests.sh new file mode 100644 index 0000000..4a8dc51 --- /dev/null +++ b/bin/tests/system/idna/tests.sh @@ -0,0 +1,388 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +# Set known locale for the tests + +if locale -a | grep -qE "^C\\.(UTF-8|utf8)"; then + LC_ALL="C.UTF-8" +elif locale -a | grep -qE "^en_US\\.(UTF-8|utf8)"; then + LC_ALL="en_US.UTF-8" +fi +export LC_ALL + +# This set of tests check the behavior of the IDNA options in "dig". +# +# The tests run "dig" against an authoritative server configured with a minimal +# root zone and nothing else. As a result, all queries will result in an +# NXDOMAIN. The server will return the qname sent, which "dig" will display +# according to the options selected. This returned string is compared with +# the qname originally sent. +# +# In the comments below, the following nomenclature (taken from RFC 5890) is +# used: +# +# A-label: Label comprising ASCII characters that starts xn-- and whose +# characters after the xn-- are a valid output of the Punycode +# algorithm. +# +# Fake A-label: An A-label whose characters after the xn-- are not valid +# Punycode output. +# +# U-label: Unicode (native character) form of a label. +# +# For the purpose of this test script, U-labels do not include labels that +# comprise purely ASCII characters, which are referred to as "ASCII-labels" +# here. Valid ASCII-labels comprise letters, digits and hyphens and do not +# start with a hyphen. +# +# References: +# 1. http://www.unicode.org/reports/tr46/#Deviations +# 2. http://www.unicode.org/reports/tr46/#IDNAComparison + +DIGCMD="$DIG -p ${PORT} @10.53.0.1" + +# Initialize test count and status return +n=0 +status=0 + +# Function for extracting the qname from the response +# +# This is the first field in the line after the line starting +# ";; QUESTION SECTION:". +# +# The string returned includes the trailing period. + +qname() { + awk 'BEGIN { qs = 0; } \ + /;; QUESTION SECTION:/ { qs = 1; next; } \ + qs == 1 {sub(";", "", $1) ; print $1; exit 0; }' \ + $1 +} + +# Function for performing a test where "dig" is expected to succeed. +# +# $1 - Description of the test +# $2 - Dig command additional options +# $3 - Name being queried +# $4 - The name that is expected to be displayed by "dig". Note that names +# displayed by "dig" will always have a trailing period, so this +# parameter should have that period as well. + +idna_test() { + n=$((n + 1)) + description=$1 + if [ "$2" != "" ]; then + description="${description}: $2" + fi + echo_i "$description ($n)" + + ret=0 + { + $DIGCMD $2 $3 >dig.out.$n 2>&1 + rc=$? + } || true + if [ $rc -ne 0 ]; then + echo_i "failed: dig command returned non-zero status" + ret=1 + else + actual=$(qname dig.out.$n) + if [ "$4" != "$actual" ]; then + echo_i "failed: expected answer $4, actual result $actual" + ret=1 + fi + fi + status=$((status + ret)) +} + +# Function for performing a test where "dig" is expected to fail +# +# $1 - Description of the test +# $2 - Dig command additional options +# $3 - Name being queried + +idna_fail() { + n=$((n + 1)) + description=$1 + if [ "$2" != "" ]; then + description="${description}: $2" + fi + echo_i "$description ($n)" + + ret=0 + { + $DIGCMD $2 $3 >dig.out.$n 2>&1 + rc=$? + } || true + if [ $rc -eq 0 ]; then + echo_i "failed: dig command unexpectedly succeeded" + ret=1 + fi + status=$((status + ret)) +} + +# Function to check that case is preserved for an all-ASCII label. +# +# Without IDNA support, case-preservation is the expected behavior. +# +# With IDNA support... not really. IDNA maps uppercase ASCII characters to +# their lower-case equivalent. When IDNA support in "dig" was updated to +# non-transitional IDNA 2008, the switch "+idnin" was added and made the default +# behaviour. This meant that the command "dig LocalhosT" (no command switches) +# sends the qname "localhost", a change in behavior from earlier versions. +# +# This was felt to be confusing to the significant number of users who are +# not interested in IDNA. For this reason, after "dig" passes the input qname +# through the IDNA conversion, is does a case-insensitive comparison with the +# result. If the two are the same, "dig" can conclude that the qname is +# entirely ASCII and is uses the entered string instead of the converted string +# as the qname. + +ascii_case_preservation_test() { + text="Checking valid ASCII label" + idna_test "$text" "+noidn" LocalhosT LocalhosT. + idna_test "$text" "+noidnin +noidnout" LocalhosT LocalhosT. + idna_test "$text" "+noidnin +idnout" LocalhosT LocalhosT. + idna_test "$text" "+idnin +noidnout" LocalhosT LocalhosT. + idna_test "$text" "+idnin +idnout" LocalhosT LocalhosT. + idna_test "$text" "+idn" LocalhosT LocalhosT. +} + +# Function to perform the tests if IDNA is enabled. + +idna_enabled_test() { + echo_i "IDNA is enabled, all IDNA tests will be performed" + # Check that case is preserved on an ASCII label. + + ascii_case_preservation_test + + # Test of a valid U-label + # + # +noidnin +noidnout: The label is sent as a unicode octet stream and dig + # will display the string in the \nnn format. + # +noidnin +idnout: As for the previous case. + # +idnin +noidnout: The label is converted to the xn-- format. "dig" + # displays the returned xn-- text. + # +idnin +idnout: The label is converted to the xn-- format. "dig" + # converts the returned xn-- string back to the original + # unicode text. + # + # Note that ASCII characters are converted to lower-case. + + text="Checking valid non-ASCII label" + idna_test "$text" "+noidn" "München" "M\195\188nchen." + idna_test "$text" "+noidnin +noidnout" "München" "M\195\188nchen." + idna_test "$text" "+noidnin +idnout" "München" "M\195\188nchen." + idna_test "$text" "+idnin +noidnout" "München" "xn--mnchen-3ya." + idna_test "$text" "+idnin +idnout" "München" "münchen." + idna_test "$text" "+idn" "München" "münchen." + + # Tests of transitional processing of a valid U-label + # + # IDNA2003 introduced national character sets but, unfortunately, didn't + # support several characters properly. One of those was the German + # character "ß" (the "Eszett" or "sharp s"), which was interpreted as "ss". + # So the domain “faß.de” domain (for example) was processed as “fass.de”. + # + # This was corrected in IDNA2008, although some vendors that adopted this + # standard chose to keep the existing IDNA2003 translation for this + # character to prevent problems (e.g. people visiting www.faß.example would, + # under IDNA2003, go to www.fass.example but under IDNA2008 would end up at + # www.fa\195\159.example - a different web site). + # + # BIND has adopted a (mostly) hard transition, so this test checks that + # the transitional mapping is not used for characters that are valid in + # IDNA2008. The tests are essentially the same as for the valid U-label. + + text="Checking that non-transitional IDNA processing is used" + idna_test "$text" "+noidn" "faß.de" "fa\195\159.de." + idna_test "$text" "+noidnin +noidnout" "faß.de" "fa\195\159.de." + idna_test "$text" "+noidnin +idnout" "faß.de" "fa\195\159.de." + idna_test "$text" "+idnin +noidnout" "faß.de" "xn--fa-hia.de." + idna_test "$text" "+idnin +idnout" "faß.de" "faß.de." + idna_test "$text" "+idn" "faß.de" "faß.de." + + # Another problem character. The final character in the first label mapped + # onto the Greek sigma character ("σ") in IDNA2003. + + text="Second check that non-transitional IDNA processing is used" + idna_test "$text" "+noidn" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." + idna_test "$text" "+noidnin +noidnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." + idna_test "$text" "+noidnin +idnout" "βόλος.com" "\206\178\207\140\206\187\206\191\207\130.com." + idna_test "$text" "+idnin +noidnout" "βόλος.com" "xn--nxasmm1c.com." + idna_test "$text" "+idnin +idnout" "βόλος.com" "βόλος.com." + idna_test "$text" "+idn" "βόλος.com" "βόλος.com." + + # Tests of a valid A-label (i.e. starting xn--) + # + # +noidnout: The string is sent as-is to the server and the returned qname + # is displayed in the same form. + # +idnout: The string is sent as-is to the server and the returned qname + # is displayed as the corresponding U-label. + # + # The "+[no]idnin" flag has no effect in these cases. + + text="Checking valid A-label" + idna_test "$text" "+noidn" "xn--nxasmq6b.com" "xn--nxasmq6b.com." + idna_test "$text" "+noidnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com." + idna_test "$text" "+noidnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com." + idna_test "$text" "+idnin +noidnout" "xn--nxasmq6b.com" "xn--nxasmq6b.com." + idna_test "$text" "+idnin +idnout" "xn--nxasmq6b.com" "βόλοσ.com." + idna_test "$text" "+idn" "xn--nxasmq6b.com" "βόλοσ.com." + + # Test of valid A-label in locale that cannot display it + # + # +noidnout: The string is sent as-is to the server and the returned qname + # is displayed in the same form. + # +idnout: The string is sent as-is to the server and the returned qname + # is displayed as the corresponding A-label. + # + # The "+[no]idnout" flag has no effect in these cases. + saved_LC_ALL="${LC_ALL}" + LC_ALL="C" + text="Checking valid A-label in C locale" + label="xn--nxasmq6b.com" + if command -v idn2 >/dev/null && ! idn2 -d "$label" >/dev/null 2>/dev/null; then + idna_test "$text" "+noidn" "$label" "$label." + idna_test "$text" "+noidnin +noidnout" "$label" "$label." + idna_test "$text" "+noidnin +idnout" "$label" "$label." + idna_test "$text" "+idnin +noidnout" "$label" "$label." + idna_test "$text" "+idnin +idnout" "$label" "$label." + idna_test "$text" "+noidnin +idnout" "$label" "$label." + idna_test "$text" "+idn" "$label" "$label." + fi + LC_ALL="${saved_LC_ALL}" + + # Tests of invalid A-labels + # + # +noidnin: The label is sent as-is to the server and dig will display the + # returned fake A-label in the same form. + # +idnin: "dig" should report that the label is not correct. + # + # +[no]idnout: If the label makes it to the server (via +noidnin), "dig" + # should report an error if +idnout is specified. + # + # +idn=lax: The label is sent and printed as-is. + + # The minimum length of a punycode A-label is 7 characters. Check that + # a shorter label is detected and rejected. + + text="Checking punycode label shorter than minimum valid length" + idna_test "$text" "+noidn" "xn--xx" "xn--xx." + idna_test "$text" "+noidnin +noidnout" "xn--xx" "xn--xx." + idna_test "$text" "+noidnin +idnout" "xn--xx" "xn--xx." + idna_test "$text" "+idnin +noidnout" "xn--xx" "xn--xx." + idna_test "$text" "+idnin +idnout" "xn--xx" "xn--xx." + idna_test "$text" "+idn" "xn--xx" "xn--xx." + + # Fake A-label - the string does not translate to anything. + # "xn--0000h" decodes to a single "code point" value of U+127252 + # (1,208,914) which is not a legal Unicode code point. + # (https://www.farsightsecurity.com/blog/txt-record/punycode-20180711/) + + text="Checking fake A-label" + idna_test "$text" "+noidn" "xn--0000h" "xn--0000h." + idna_test "$text" "+noidnin +noidnout" "xn--0000h" "xn--0000h." + idna_test "$text" "+noidnin +idnout" "xn--0000h" "xn--0000h." + idna_test "$text" "+idnin +noidnout" "xn--0000h" "xn--0000h." + idna_test "$text" "+idnin +idnout" "xn--0000h" "xn--0000h." + idna_test "$text" "+idn" "xn--0000h" "xn--0000h." + + # Too long a label. The punycode string is too long (at 64 characters). + # BIND rejects such labels: with +idnin + + label="xn--xflod18hstflod18hstflod18hstflod18hstflod18hstflod18-1iejjjj" + text="Checking punycode label longer than maximum valid length" + idna_fail "$text" "+noidn" "$label" + idna_fail "$text" "+noidnin +noidnout" "$label" + idna_fail "$text" "+noidnin +idnout" "$label" + idna_fail "$text" "+idnin +noidnout" "$label" + idna_fail "$text" "+idnin +idnout" "$label" + idna_fail "$text" "+idn" "$label" + + # Tests of a valid unicode string but an invalid U-label (input) + # + # Symbols are not valid IDNA2008 names, but are allowed by IDNA2003. + # + # +noidnin: "dig" should send unicode octets to the server and display the + # returned qname in the same form. + # +idnin: "dig" should generate an error. + # + # The +[no]idnout options should not have any effect on the test. + + text="Checking invalid input U-label" + idna_test "$text" "+noidn" "√.com" "\226\136\154.com." + idna_test "$text" "+noidnin +noidnout" "√.com" "\226\136\154.com." + idna_test "$text" "+noidnin +idnout" "√.com" "\226\136\154.com." + idna_test "$text" "+idnin +noidnout" "√.com" "xn--19g.com." + idna_test "$text" "+idnin +idnout" "√.com" "√.com." + idna_test "$text" "+idn" "√.com" "√.com." + + # Tests of a valid unicode string but an invalid U-label (output) + # + # Symbols are not valid IDNA2008 names, but are allowed by IDNA2003. + # + # +noidnout: "dig" should send the ACE string to the server and display the + # returned qname. + # +idnout: "dig" should generate an error. + # + # The +[no]idnin options should not have any effect on the test. + + text="Checking invalid output U-label" + idna_test "$text" "+noidn" "xn--19g" "xn--19g." + idna_test "$text" "+noidnin +noidnout" "xn--19g" "xn--19g." + idna_test "$text" "+noidnin +idnout" "xn--19g" "√." + idna_test "$text" "+idnin +noidnout" "xn--19g" "xn--19g." + idna_test "$text" "+idnin +idnout" "xn--19g" "√." + idna_test "$text" "+idn" "xn--19g" "√." + + # Test that non-letter characters are preserved in the output. When + # UseSTD3ASCIIRules are enabled, it would mangle non-letter characters like + # `_` (underscore) and `*` (wildcard. + + text="Checking valid non-letter characters" + idna_test "$text" "+noidn" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." + idna_test "$text" "+noidnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." + idna_test "$text" "+noidnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com." + idna_test "$text" "+idnin +noidnout" "*.xn--nxasmq6b.com" "*.xn--nxasmq6b.com." + idna_test "$text" "+idnin +idnout" "*.xn--nxasmq6b.com" "*.βόλοσ.com." + idna_test "$text" "+idn" "*.xn--nxasmq6b.com" "*.βόλοσ.com." + + idna_test "$text" "+noidn" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." + idna_test "$text" "+noidnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." + idna_test "$text" "+noidnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." + idna_test "$text" "+idnin +noidnout" "_tcp.xn--nxasmq6b.com" "_tcp.xn--nxasmq6b.com." + idna_test "$text" "+idnin +idnout" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." + idna_test "$text" "+idn=strict" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." + idna_test "$text" "+idn=lax" "_tcp.xn--nxasmq6b.com" "_tcp.βόλοσ.com." +} + +# Function to perform tests if IDNA is not enabled. + +idna_disabled_test() { + echo_i "IDNA is disabled, only case mapping tests will be performed" + ascii_case_preservation_test +} + +# Main test begins here + +if $FEATURETEST --with-libidn2; then + idna_enabled_test +else + idna_disabled_test +fi + +exit $status diff --git a/bin/tests/system/idna/tests_sh_idna.py b/bin/tests/system/idna/tests_sh_idna.py new file mode 100644 index 0000000..f4a9ed0 --- /dev/null +++ b/bin/tests/system/idna/tests_sh_idna.py @@ -0,0 +1,22 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + ] +) + + +def test_idna(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/ifconfig.sh.in b/bin/tests/system/ifconfig.sh.in new file mode 100755 index 0000000..ef50291 --- /dev/null +++ b/bin/tests/system/ifconfig.sh.in @@ -0,0 +1,282 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Set up interface aliases for bind9 system tests. +# +# IPv4: 10.53.0.{1..11} RFC 1918 +# 10.53.1.{1..2} +# 10.53.2.{1..2} +# IPv6: fd92:7065:b8e:ffff::{1..11} ULA +# fd92:7065:b8e:99ff::{1..2} +# fd92:7065:b8e:ff::{1..2} +# fd92:7065:b8e:fffe::10.53.0.4 +# 2002:0a35:0007::1 6to4 for 10.53.0.7 +# +# We also set the MTU on the 1500 bytes to match the default MTU on physical +# interfaces, so we can properly test the cases with packets bigger than +# interface MTU. +# +# See also org.isc.bind.system (a version of this script for use on macOS) +# and testsock.pl (which checks the interfaces are configured) +# + +top_srcdir=@abs_top_srcdir@ + +sys=$(@SHELL@ "$top_srcdir/config.guess") + +use_ip= +case "$sys" in + *-*-linux*) + if type ip >/dev/null; then + use_ip=yes + elif type ifconfig >/dev/null; then + : + else + echo "$0: can't find ip or ifconfig" >&2 + exit 1 + fi + ;; +esac + +up() { + case "$sys" in + *-pc-solaris2.5.1) + [ "$a" ] && ifconfig lo0:$int $a netmask 0xffffffff up + ;; + *-sun-solaris2.[6-7]) + [ "$a" ] && ifconfig lo0:$int $a netmask 0xffffffff up + ;; + *-*-solaris2.[8-9] | *-*-solaris2.10) + [ "$a" ] && { + /sbin/ifconfig lo0:$int plumb + /sbin/ifconfig lo0:$int $a up + /sbin/ifconfig lo0:$int mtu 1500 + } + [ "$aaaa" ] && { + /sbin/ifconfig lo0:$int inet6 plumb + /sbin/ifconfig lo0:$int inet6 $aaaa up + } + ;; + *-*-solaris2.1[1-9]) + [ "$a" ] && { + /sbin/ipadm create-addr -t -T static \ + -a $a lo0/bind9v4$int \ + || echo failed lo0/bind9v4$int + } + [ "$aaaa" ] && { + /sbin/ipadm create-addr -t -T static \ + -a $aaaa lo0/bind9v6$int \ + || echo failed lo0/bind9v6$int + } + ;; + *-*-linux*) + if [ "$use_ip" ]; then + [ "$a" ] && ip address add $a/24 dev lo:$int + [ "$aaaa" ] && ip address add $aaaa/64 dev lo + ip link set dev lo:$int mtu 1500 + else + ifconfig lo:$int $a up netmask 255.255.255.0 mtu 1500 + [ "$aaaa" ] && ifconfig lo inet6 add $aaaa/64 + fi + ;; + *-unknown-freebsd*) + [ "$a" ] && ifconfig lo0 $a alias netmask 0xffffffff mtu 1500 + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias + ;; + *-unknown-dragonfly* | *-unknown-netbsd* | *-unknown-openbsd*) + [ "$a" ] && ifconfig lo0 $a alias netmask 255.255.255.0 mtu 1500 + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias + ;; + *-*-bsdi[3-5].*) + [ "$a" ] && ifconfig lo0 add $a netmask 255.255.255.0 + ;; + *-dec-osf[4-5].*) + [ "$a" ] && ifconfig lo0 alias $a + ;; + *-sgi-irix6.*) + [ "$a" ] && ifconfig lo0 alias $a + ;; + *-*-sysv5uw7* | *-*-sysv*UnixWare* | *-*-sysv*OpenUNIX*) + [ "$a" ] && ifconfig lo0 $a alias netmask 0xffffffff + ;; + *-ibm-aix4.* | *-ibm-aix5.*) + [ "$a" ] && ifconfig lo0 alias $a + [ "$aaaa" ] && ifconfig lo0 inet6 alias -dad $aaaa/64 + ;; + hpux) + [ "$a" ] && ifconfig lo0:$int $a netmask 255.255.255.0 up + [ "$aaaa" ] && ifconfig lo0:$int inet6 $aaaa up + ;; + *-sco3.2v*) + [ "$a" ] && ifconfig lo0 alias $a + ;; + *-darwin*) + [ "$a" ] && ifconfig lo0 alias $a + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa alias + ;; + *) + echo "Don't know how to set up interface. Giving up." + exit 1 + ;; + esac +} + +down() { + case "$sys" in + *-pc-solaris2.5.1) + [ "$a" ] && ifconfig lo0:$int 0.0.0.0 down + ;; + *-sun-solaris2.[6-7]) + [ "$a" ] && ifconfig lo0:$int $a down + ;; + *-*-solaris2.[8-9] | *-*-solaris2.10) + [ "$a" ] && { + ifconfig lo0:$int $a down + ifconfig lo0:$int $a unplumb + } + [ "$aaaa" ] && { + ifconfig lo0:$int inet6 down + ifconfig lo0:$int inet6 unplumb + } + ;; + *-*-solaris2.1[1-9]) + [ "$a" ] && { + ipadm delete-addr lo0/bind9v4$int \ + || echo failed lo0/bind9v4$int + } + [ "$aaaa" ] && { + ipadm delete-addr lo0/bind9v6$int \ + || echo failed lo0/bind9v6$int + } + ;; + + *-*-linux*) + if [ "$use_ip" ]; then + [ "$a" ] && ip address del $a/24 dev lo:$int + [ "$aaaa" ] && ip address del $aaaa/64 dev lo + else + [ "$a" ] && ifconfig lo:$int $a down + [ "$aaaa" ] && ifconfig lo inet6 del $aaaa/64 + fi + ;; + *-unknown-freebsd*) + [ "$a" ] && ifconfig lo0 $a delete + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete + ;; + *-unknown-netbsd*) + [ "$a" ] && ifconfig lo0 $a delete + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete + ;; + *-unknown-openbsd*) + [ "$a" ] && ifconfig lo0 $a delete + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete + ;; + *-*-bsdi[3-5].*) + [ "$a" ] && ifconfig lo0 remove $a + ;; + *-dec-osf[4-5].*) + [ "$a" ] && ifconfig lo0 -alias $a + ;; + *-sgi-irix6.*) + [ "$a" ] && ifconfig lo0 -alias $a + ;; + *-*-sysv5uw7* | *-*-sysv*UnixWare* | *-*-sysv*OpenUNIX*) + [ "$a" ] && ifconfig lo0 -alias $a + ;; + *-ibm-aix4.* | *-ibm-aix5.*) + [ "$a" ] && ifconfig lo0 delete $a + [ "$aaaa" ] && ifconfig lo0 delete inet6 $aaaa/64 + ;; + hpux) + [ "$a" ] && ifconfig lo0:$int 0.0.0.0 + [ "$aaaa" ] && ifconfig lo0:$int inet6 :: + ;; + *-sco3.2v*) + [ "$a" ] && ifconfig lo0 -alias $a + ;; + *darwin*) + [ "$a" ] && ifconfig lo0 -alias $a + [ "$aaaa" ] && ifconfig lo0 inet6 $aaaa delete + ;; + *) + echo "Don't know how to destroy interface. Giving up." + exit 1 + ;; + esac +} + +sequence() ( + awk -v s=$1 -v e=$2 ' + BEGIN { + for (i = s ; i <= e; i++) { print i; } + exit; + }' +) + +# +# 'max', 'i' and 'ns' are used to compute the interface identifier for +# systems that need it and must be unique for each interface (e.g. lo:$int). +# +# int=$((i * max + ns)) +# +# 'max' is the number of nameservers configured in the inner loop. +# 'i' is the outer loop counter. +# 'ns' in the namserver being configured. +# 'int' interface identifier. +# +# See also `org.isc.bind.system`. +# +# This `max` setting is grepped out for use by testsock.pl +# +max=11 +case $1 in + start | up | stop | down) + for i in $(sequence 0 4); do + case $i in + 0) ipv6="ff" ;; + 1) ipv6="99" ;; + 2) ipv6="00" ;; + *) ipv6="" ;; + esac + for ns in $(sequence 1 $max); do + int=$((i * max + ns)) + case $i in + 0 | 1 | 2) + [ $i -gt 0 -a $ns -gt 3 ] && break + a=10.53.$i.$ns + aaaa=fd92:7065:b8e:${ipv6}ff::$ns + ;; + 3) + [ $ns -ne 4 ] && continue + a= + aaaa=fd92:7065:b8e:fffe::10.53.0.$ns + ;; + 4) + [ $ns -ne 1 ] && continue + a= + aaaa=2002:0a35:0007::$ns + ;; + esac + case "$1" in + start | up) up ;; + stop | down) down ;; + esac + done + done + ;; + *) + echo "Usage: $0 { up | down }" + exit 1 + ;; +esac diff --git a/bin/tests/system/include-multiplecfg/ns2/mars.com.db b/bin/tests/system/include-multiplecfg/ns2/mars.com.db new file mode 100644 index 0000000..cbae017 --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/mars.com.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA dns1.mars.com. hostmaster.mars.com. ( + 2001062501 ; serial + 21600 ; refresh after 6 hours + 3600 ; retry after 1 hour + 604800 ; expire after 1 week + 86400 ) ; minimum TTL of 1 day + + IN NS dns1.mars.com. + + IN A 10.53.0.1 + +dns1 IN A 10.53.0.1 diff --git a/bin/tests/system/include-multiplecfg/ns2/mars.conf b/bin/tests/system/include-multiplecfg/ns2/mars.conf new file mode 100644 index 0000000..31f6da3 --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/mars.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "mars.com" { + type primary; + file "mars.com.db"; +}; + diff --git a/bin/tests/system/include-multiplecfg/ns2/named.conf.j2 b/bin/tests/system/include-multiplecfg/ns2/named.conf.j2 new file mode 100644 index 0000000..0dfe01d --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/named.conf.j2 @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation no; +}; + +# Should include all files matching pattern. +include "zone*.conf"; + +# Shouldn't break standard file pattern. +include "mars.conf"; + diff --git a/bin/tests/system/include-multiplecfg/ns2/zone1.com.db b/bin/tests/system/include-multiplecfg/ns2/zone1.com.db new file mode 100644 index 0000000..ef9cff4 --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/zone1.com.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA dns1.zone1.com. hostmaster.zone1.com. ( + 2001062501 ; serial + 21600 ; refresh after 6 hours + 3600 ; retry after 1 hour + 604800 ; expire after 1 week + 86400 ) ; minimum TTL of 1 day + + IN NS dns1.zone1.com. + + IN A 10.53.0.1 + +dns1 IN A 10.53.0.1 diff --git a/bin/tests/system/include-multiplecfg/ns2/zone1.conf b/bin/tests/system/include-multiplecfg/ns2/zone1.conf new file mode 100644 index 0000000..e5c15ad --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/zone1.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "zone1.com" { + type primary; + file "zone1.com.db"; +}; + diff --git a/bin/tests/system/include-multiplecfg/ns2/zone2.com.db b/bin/tests/system/include-multiplecfg/ns2/zone2.com.db new file mode 100644 index 0000000..6df12b2 --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/zone2.com.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 86400 +@ IN SOA dns1.zone2.com. hostmaster.zone2.com. ( + 2001062501 ; serial + 21600 ; refresh after 6 hours + 3600 ; retry after 1 hour + 604800 ; expire after 1 week + 86400 ) ; minimum TTL of 1 day + + IN NS dns1.zone2.com. + + IN A 10.53.0.1 + +dns1 IN A 10.53.0.1 diff --git a/bin/tests/system/include-multiplecfg/ns2/zone2.conf b/bin/tests/system/include-multiplecfg/ns2/zone2.conf new file mode 100644 index 0000000..b122b0f --- /dev/null +++ b/bin/tests/system/include-multiplecfg/ns2/zone2.conf @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "zone2.com" { + type primary; + file "zone2.com.db"; +}; + diff --git a/bin/tests/system/include-multiplecfg/tests_include_multiplecfg.py b/bin/tests/system/include-multiplecfg/tests_include_multiplecfg.py new file mode 100644 index 0000000..346f334 --- /dev/null +++ b/bin/tests/system/include-multiplecfg/tests_include_multiplecfg.py @@ -0,0 +1,39 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +import isctest +import pytest + +import dns.message + + +@pytest.mark.parametrize( + "qname", + [ + "zone1.com.", # glob include of zone1 config + "zone2.com.", # glob include of zone2 config + "mars.com.", # checking include of standard file path config + ], +) +def test_include_multiplecfg(qname): + msg = dns.message.make_query(qname, "A") + res = isctest.query.tcp(msg, "10.53.0.2") + + isctest.check.noerror(res) + + assert res.answer[0] == dns.rrset.from_text(qname, 86400, "IN", "A", "10.53.0.1") + + +def test_include_multiplecfg_checkconf(): + """Test that named-checkconf correctly parses glob includes""" + isctest.run.cmd([os.environ["CHECKCONF"], "named.conf"], cwd="ns2") diff --git a/bin/tests/system/inline/ns1/named.conf.in b/bin/tests/system/inline/ns1/named.conf.in new file mode 100644 index 0000000..897e764 --- /dev/null +++ b/bin/tests/system/inline/ns1/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +controls { /* empty */ }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/inline/ns1/root.db.in b/bin/tests/system/inline/ns1/root.db.in new file mode 100644 index 0000000..7747688 --- /dev/null +++ b/bin/tests/system/inline/ns1/root.db.in @@ -0,0 +1,50 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +bits. NS ns3.bits. +bits. NS ns4.bits. +ns3.bits. A 10.53.0.3 +ns4.bits. A 10.53.0.4 + +noixfr. NS ns3.noixfr. +ns3.noixfr. A 10.53.0.3 + +primary. NS ns3.primary. +ns3.primary. A 10.53.0.3 + +dynamic. NS ns3.dynamic. +ns3.dynamic. A 10.53.0.3 + +updated. NS ns3.updated. +ns3.updated. A 10.53.0.3 + +expired. NS ns3.expired. +ns3.expired. A 10.53.0.3 + +retransfer. NS ns3.retransfer. +ns3.retransfer. A 10.53.0.3 + +nsec3. NS ns3.nsec3. +ns3.nsec3. A 10.53.0.3 + +externalkey. NS ns3.externalkey. +ns3.externalkey. A 10.53.0.3 diff --git a/bin/tests/system/inline/ns1/sign.sh b/bin/tests/system/inline/ns1/sign.sh new file mode 100644 index 0000000..e55f5e7 --- /dev/null +++ b/bin/tests/system/inline/ns1/sign.sh @@ -0,0 +1,25 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +rm -f K.+*+*.key +rm -f K.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$SIGNER -S -x -T 1200 -o ${zone} root.db >signer.out +[ $? = 0 ] || cat signer.out + +keyfile_to_static_ds $keyname >trusted.conf +cp trusted.conf ../ns6/trusted.conf diff --git a/bin/tests/system/inline/ns2/bits.db.in b/bin/tests/system/inline/ns2/bits.db.in new file mode 100644 index 0000000..2652047 --- /dev/null +++ b/bin/tests/system/inline/ns2/bits.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns2 . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/inline/ns2/named.conf.in b/bin/tests/system/inline/ns2/named.conf.in new file mode 100644 index 0000000..30c8af3 --- /dev/null +++ b/bin/tests/system/inline/ns2/named.conf.in @@ -0,0 +1,67 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + notify-delay 0; + allow-new-zones yes; + dnssec-validation no; +}; + +zone "bits" { + type primary; + file "bits.db"; + allow-update { any; }; +}; + +zone "retransfer" { + type primary; + file "retransfer.db"; + allow-update { any; }; + notify no; +}; + +zone "nsec3-loop" { + type primary; + file "nsec3-loop.db"; + notify no; +}; + +zone "nokeys" { + type primary; + file "nokeys.db"; + allow-update { any; }; +}; + +zone "removedkeys-secondary" { + type primary; + file "removedkeys-secondary.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/inline/ns2/nsec3-loop.db.in b/bin/tests/system/inline/ns2/nsec3-loop.db.in new file mode 100644 index 0000000..d12af8d --- /dev/null +++ b/bin/tests/system/inline/ns2/nsec3-loop.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; NOTE: This zone's data has been crafted in order to reproduce a very specific +; scenario (see ns7/named.conf for more details). Please do not modify this +; file. + +$TTL 300 ; 5 minutes +@ IN SOA ns2 . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/inline/ns3/delayedkeys.conf.1 b/bin/tests/system/inline/ns3/delayedkeys.conf.1 new file mode 100644 index 0000000..72ed2aa --- /dev/null +++ b/bin/tests/system/inline/ns3/delayedkeys.conf.1 @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "delayedkeys" { + type primary; + file "delayedkeys.db"; + inline-signing yes; + dnssec-policy insecure; +}; diff --git a/bin/tests/system/inline/ns3/delayedkeys.conf.2 b/bin/tests/system/inline/ns3/delayedkeys.conf.2 new file mode 100644 index 0000000..fa7cbcd --- /dev/null +++ b/bin/tests/system/inline/ns3/delayedkeys.conf.2 @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "delayedkeys" { + type primary; + file "delayedkeys.db"; + inline-signing yes; + dnssec-policy inline; +}; diff --git a/bin/tests/system/inline/ns3/include.db.in b/bin/tests/system/inline/ns3/include.db.in new file mode 100644 index 0000000..c46a6a8 --- /dev/null +++ b/bin/tests/system/inline/ns3/include.db.in @@ -0,0 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +f A 10.0.0.7 diff --git a/bin/tests/system/inline/ns3/named.conf.in b/bin/tests/system/inline/ns3/named.conf.in new file mode 100644 index 0000000..8c6a41c --- /dev/null +++ b/bin/tests/system/inline/ns3/named.conf.in @@ -0,0 +1,175 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion no; + allow-transfer { any; }; + notify yes; + try-tcp-refresh no; + notify-delay 0; + allow-new-zones yes; + dnssec-validation no; +}; + +dnssec-policy "inline" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + nsec3param iterations 0 optout no salt-length 0; +}; + +dnssec-policy "external" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + }; +}; + +zone "bits" { + type secondary; + primaries { 10.53.0.2; }; + inline-signing yes; + dnssec-policy inline; + allow-update-forwarding { any; }; + file "bits.bk"; + sig-signing-signatures 1; // force incremental processing +}; + +server 10.53.0.4 { request-ixfr no; }; + +zone "noixfr" { + type secondary; + primaries { 10.53.0.4; }; + inline-signing yes; + dnssec-policy inline; + allow-update-forwarding { any; }; + file "noixfr.bk"; +}; + +zone "primary" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "primary.db"; + notify explicit; + also-notify { + 10.53.0.3; + }; +}; + +zone "dynamic" { + type primary; + inline-signing yes; + dnssec-policy inline; + allow-update { any; }; + file "dynamic.db"; +}; + +zone "updated" { + type primary; + inline-signing yes; + dnssec-policy inline; + allow-update { none; }; + file "updated.db"; +}; + +zone "expired" { + type primary; + inline-signing yes; + dnssec-policy inline; + allow-update { any; }; + file "expired.db"; +}; + +zone "retransfer" { + type secondary; + primaries { 10.53.0.2; }; + inline-signing yes; + dnssec-policy inline; + file "retransfer.bk"; +}; + +zone "nsec3" { + type primary; + inline-signing yes; + dnssec-policy nsec3; + allow-update { any; }; + file "nsec3.db"; +}; + +zone "externalkey" { + type primary; + inline-signing yes; + dnssec-policy external; + allow-update { any; }; + file "externalkey.db"; +}; + +zone "nokeys" { + type secondary; + primaries { 10.53.0.2; }; + inline-signing yes; + dnssec-policy insecure; + file "nokeys.bk"; +}; + +zone "removedkeys-primary" { + type primary; + inline-signing yes; + dnssec-policy inline; + allow-update { any; }; + also-notify { 10.53.0.2; }; + file "removedkeys-primary.db"; +}; + +zone "removedkeys-secondary" { + type secondary; + primaries { 10.53.0.2; }; + inline-signing yes; + dnssec-policy inline; + file "removedkeys-secondary.bk"; +}; + +zone "unsupported" { + type primary; + file "unsupported.db"; + inline-signing yes; + dnssec-policy inline; +}; + +include "delayedkeys.conf"; diff --git a/bin/tests/system/inline/ns3/primary.db.in b/bin/tests/system/inline/ns3/primary.db.in new file mode 100644 index 0000000..4d30cf6 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/inline/ns3/primary2.db.in b/bin/tests/system/inline/ns3/primary2.db.in new file mode 100644 index 0000000..24a0666 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary2.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042408 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +e A 10.0.0.5 diff --git a/bin/tests/system/inline/ns3/primary3.db.in b/bin/tests/system/inline/ns3/primary3.db.in new file mode 100644 index 0000000..f3062c3 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary3.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042409 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +c A 10.0.0.3 +e A 10.0.0.5 diff --git a/bin/tests/system/inline/ns3/primary4.db.in b/bin/tests/system/inline/ns3/primary4.db.in new file mode 100644 index 0000000..737e2e2 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary4.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 hostmaster. ( + 2000042410 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +c A 10.0.0.3 +e A 10.0.0.5 diff --git a/bin/tests/system/inline/ns3/primary5.db.in b/bin/tests/system/inline/ns3/primary5.db.in new file mode 100644 index 0000000..a1e1300 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary5.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042411 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +c A 10.0.0.3 +e A 10.0.0.5 diff --git a/bin/tests/system/inline/ns3/primary6.db.in b/bin/tests/system/inline/ns3/primary6.db.in new file mode 100644 index 0000000..de3e651 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary6.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042412 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +c A 10.0.0.3 +e A 10.0.0.5 + +$INCLUDE missingfile.db diff --git a/bin/tests/system/inline/ns3/primary7.db.in b/bin/tests/system/inline/ns3/primary7.db.in new file mode 100644 index 0000000..a3e33e7 --- /dev/null +++ b/bin/tests/system/inline/ns3/primary7.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns3 . ( + 2000042412 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns3 A 10.53.0.3 + +c A 10.0.0.3 +e A 10.0.0.5 + +$INCLUDE include.db diff --git a/bin/tests/system/inline/ns3/sign.sh b/bin/tests/system/inline/ns3/sign.sh new file mode 100755 index 0000000..1b2a905 --- /dev/null +++ b/bin/tests/system/inline/ns3/sign.sh @@ -0,0 +1,131 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +# Fake an unsupported key +unsupportedkey=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone unsupported) +awk '$3 == "DNSKEY" { $6 = 255 } { print }' ${unsupportedkey}.key >${unsupportedkey}.tmp +mv ${unsupportedkey}.tmp ${unsupportedkey}.key + +zone=bits +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=noixfr +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=primary +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=dynamic +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=updated +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -L 3600 -n zone $zone) +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -L 3600 -n zone -f KSK $zone) +$SETTIME -s -g OMNIPRESENT -k RUMOURED now -z RUMOURED now "$zsk" >settime.out.updated.1 2>&1 +$SETTIME -s -g OMNIPRESENT -k RUMOURED now -r RUMOURED now -d HIDDEN now "$ksk" >settime.out.updated.2 2>&1 +$DSFROMKEY -T 1200 $ksk >>../ns1/root.db +$SIGNER -S -x -O raw -L 2000042407 -o ${zone} ${zone}.db >/dev/null +cp primary2.db.in updated.db + +# signatures are expired and should be regenerated on startup +zone=expired +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db +$SIGNER -PS -s 20100101000000 -e 20110101000000 -O raw -L 2000042407 -o ${zone} ${zone}.db >/dev/null + +zone=retransfer +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=nsec3 +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +$DSFROMKEY -T 1200 $keyname >>../ns1/root.db + +zone=delayedkeys +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +# Keys for the "delayedkeys" zone should not be initially accessible. +mv K${zone}.+*+*.* ../ + +zone=removedkeys-primary +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) + +zone=removedkeys-secondary +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) + +for s in a c d h k l m q z; do + zone=test-$s + keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +done + +for s in b f i o p t v; do + zone=test-$s + keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) + keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +done + +zone=externalkey +zonefile=${zone}.db +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private + +for alg in ${DEFAULT_ALGORITHM} ${ALTERNATIVE_ALGORITHM}; do + k1=$($KEYGEN -q -a $alg -n zone -f KSK $zone) + k2=$($KEYGEN -q -a $alg -n zone $zone) + k3=$($KEYGEN -q -a $alg -n zone $zone) + k4=$($KEYGEN -q -a $alg -n zone -f KSK $zone) + $DSFROMKEY -T 1200 $k4 >>../ns1/root.db + + cat $k1.key $k2.key >>$zonefile + + rm -f $k1.key + rm -f $k1.private + rm -f $k2.key + rm -f $k2.private +done diff --git a/bin/tests/system/inline/ns4/named.conf.in b/bin/tests/system/inline/ns4/named.conf.in new file mode 100644 index 0000000..42a21bd --- /dev/null +++ b/bin/tests/system/inline/ns4/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + notify-delay 0; + dnssec-validation no; +}; + +zone "noixfr" { + type primary; + file "noixfr.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/inline/ns4/noixfr.db.in b/bin/tests/system/inline/ns4/noixfr.db.in new file mode 100644 index 0000000..c40f011 --- /dev/null +++ b/bin/tests/system/inline/ns4/noixfr.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns4 . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 +ns4 A 10.53.0.4 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/inline/ns5/named.conf.post b/bin/tests/system/inline/ns5/named.conf.post new file mode 100644 index 0000000..17d5dd5 --- /dev/null +++ b/bin/tests/system/inline/ns5/named.conf.post @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; + notify-delay 0; + servfail-ttl 0; +}; + +dnssec-policy "inline" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +zone "bits" { + type secondary; + primaries { 10.53.0.2; }; + file "bits.bk"; + dnssec-policy inline; + inline-signing yes; +}; diff --git a/bin/tests/system/inline/ns5/named.conf.pre b/bin/tests/system/inline/ns5/named.conf.pre new file mode 100644 index 0000000..a3ea6f2 --- /dev/null +++ b/bin/tests/system/inline/ns5/named.conf.pre @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; + notify-delay 0; +}; + +zone "bits" { + type secondary; + primaries { 10.53.0.2; }; + file "bits.bk"; +}; diff --git a/bin/tests/system/inline/ns6/named.conf.in b/bin/tests/system/inline/ns6/named.conf.in new file mode 100644 index 0000000..05de001 --- /dev/null +++ b/bin/tests/system/inline/ns6/named.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + notify-delay 0; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/inline/ns7/named.conf.in b/bin/tests/system/inline/ns7/named.conf.in new file mode 100644 index 0000000..3415ba5 --- /dev/null +++ b/bin/tests/system/inline/ns7/named.conf.in @@ -0,0 +1,61 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * NS7 + * + * NOTE: This named instance is used to reproduce a scenario which involves a + * number of functions getting called in a very specific order which results in + * an infinite loop while iterating over NSEC3 red-black tree. Ensuring this + * happens requires carefully setting the number of signing keys, NSEC3 + * parameters (number of iterations and salt value), zone data and named + * configuration. Changing any of these and/or influencing this instance's + * behavior (e.g. by sending extra queries to it) might render this test moot + * as it will no longer be able to reproduce the exact scenario it attempts to. + * + * Given the above, please do not use this instance for any other test than the + * one it was meant for. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify no; + try-tcp-refresh no; + allow-new-zones yes; + sig-signing-nodes 100; + sig-signing-signatures 10; +}; + +dnssec-policy "nsec3" { + keys { + ksk key-directory lifetime unlimited algorithm RSASHA256 2048; + zsk key-directory lifetime unlimited algorithm RSASHA256 2048; + zsk key-directory lifetime unlimited algorithm RSASHA256 4096; + }; + + nsec3param iterations 0 optout no salt-length 0; +}; diff --git a/bin/tests/system/inline/ns7/sign.sh b/bin/tests/system/inline/ns7/sign.sh new file mode 100755 index 0000000..8479388 --- /dev/null +++ b/bin/tests/system/inline/ns7/sign.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +# NOTE: The number of signing keys generated below is not coincidental. More +# details can be found in the comment inside ns7/named.conf. + +zone=nsec3-loop +rm -f K${zone}.+*+*.key +rm -f K${zone}.+*+*.private +keyname=$($KEYGEN -q -a RSASHA256 -b 4096 -n zone $zone) +keyname=$($KEYGEN -q -a RSASHA256 -b 2048 -n zone $zone) +keyname=$($KEYGEN -q -a RSASHA256 -b 2048 -n zone -f KSK $zone) diff --git a/bin/tests/system/inline/ns8/example.com.db.in b/bin/tests/system/inline/ns8/example.com.db.in new file mode 100644 index 0000000..dfc7630 --- /dev/null +++ b/bin/tests/system/inline/ns8/example.com.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns8 . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns8 +ns8 A 10.53.0.8 diff --git a/bin/tests/system/inline/ns8/example.db.in b/bin/tests/system/inline/ns8/example.db.in new file mode 100644 index 0000000..3ebf398 --- /dev/null +++ b/bin/tests/system/inline/ns8/example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns8 +ns8 A 10.53.0.8 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/inline/ns8/example2.db.in b/bin/tests/system/inline/ns8/example2.db.in new file mode 100644 index 0000000..1f42c3a --- /dev/null +++ b/bin/tests/system/inline/ns8/example2.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 2 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns8 +ns8 A 10.53.0.8 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/inline/ns8/example3.db.in b/bin/tests/system/inline/ns8/example3.db.in new file mode 100644 index 0000000..a9e3daa --- /dev/null +++ b/bin/tests/system/inline/ns8/example3.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 400 +@ IN SOA mname1. . ( + 3 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns8 +ns8 A 10.53.0.8 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/inline/ns8/named.conf.in b/bin/tests/system/inline/ns8/named.conf.in new file mode 100644 index 0000000..e604c7a --- /dev/null +++ b/bin/tests/system/inline/ns8/named.conf.in @@ -0,0 +1,170 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS8 + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + try-tcp-refresh no; + notify-delay 0; + allow-new-zones yes; + dnssec-validation no; +}; + +dnssec-policy "inline" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +zone "example01.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example01.com.db"; +}; + +zone "example02.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example02.com.db"; +}; + +zone "example03.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example03.com.db"; +}; + +zone "example04.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example04.com.db"; +}; + +zone "example05.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example05.com.db"; +}; + +zone "example06.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example06.com.db"; +}; + +zone "example07.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example07.com.db"; +}; + +zone "example08.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example08.com.db"; +}; + +zone "example09.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example09.com.db"; +}; + +zone "example10.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example10.com.db"; +}; + +zone "example11.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example11.com.db"; +}; + +zone "example12.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example12.com.db"; +}; + +zone "example13.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example13.com.db"; +}; + +zone "example14.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example14.com.db"; +}; + +zone "example15.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example15.com.db"; +}; + +zone "example16.com" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example16.com.db"; +}; + +zone example { + type primary; + inline-signing yes; + dnssec-policy inline; + file "example.db"; +}; + +zone "unsigned-serial-test" { + type primary; + inline-signing yes; + dnssec-policy inline; + file "unsigned-serial-test.db"; +}; diff --git a/bin/tests/system/inline/ns8/sign.sh b/bin/tests/system/inline/ns8/sign.sh new file mode 100755 index 0000000..56d097d --- /dev/null +++ b/bin/tests/system/inline/ns8/sign.sh @@ -0,0 +1,34 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +for zone in example01.com example02.com example03.com example04.com \ + example05.com example06.com example07.com example08.com \ + example09.com example10.com example11.com example12.com \ + example13.com example14.com example15.com example16.com; do + rm -f K${zone}.+*+*.key + rm -f K${zone}.+*+*.private + keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone) + keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone -f KSK $zone) + cp example.com.db.in ${zone}.db + $SIGNER -S -T 3600 -O raw -L 2000042407 -o ${zone} ${zone}.db >/dev/null 2>&1 +done + +for zone in example unsigned-serial-test; do + rm -f K${zone}.+*+*.key + rm -f K${zone}.+*+*.private + keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone) + keyname=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone -f KSK $zone) + cp example.db.in ${zone}.db +done diff --git a/bin/tests/system/inline/setup.sh b/bin/tests/system/inline/setup.sh new file mode 100644 index 0000000..b832c20 --- /dev/null +++ b/bin/tests/system/inline/setup.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +cp ns1/root.db.in ns1/root.db + +touch ns2/trusted.conf +cp ns2/nsec3-loop.db.in ns2/nsec3-loop.db +cp ns2/bits.db.in ns2/bits.db +cp ns2/bits.db.in ns2/nokeys.db +cp ns2/bits.db.in ns2/removedkeys-secondary.db +cp ns2/bits.db.in ns2/retransfer.db + +cp ns3/primary.db.in ns3/primary.db +cp ns3/primary.db.in ns3/dynamic.db +cp ns3/primary.db.in ns3/updated.db +cp ns3/primary.db.in ns3/unsupported.db +cp ns3/primary.db.in ns3/expired.db +cp ns3/primary.db.in ns3/nsec3.db +cp ns3/primary.db.in ns3/externalkey.db +cp ns3/primary.db.in ns3/delayedkeys.db +cp ns3/primary.db.in ns3/removedkeys-primary.db +cp ns3/include.db.in ns3/include.db + +mkdir ns3/removedkeys + +touch ns4/trusted.conf +cp ns4/noixfr.db.in ns4/noixfr.db + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +cp ns3/delayedkeys.conf.1 ns3/delayedkeys.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.pre ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf + +( + cd ns3 + $SHELL -e sign.sh +) +( + cd ns1 + $SHELL -e sign.sh +) +( + cd ns7 + $SHELL -e sign.sh +) +( + cd ns8 + $SHELL -e sign.sh +) diff --git a/bin/tests/system/inline/tests.sh b/bin/tests/system/inline/tests.sh new file mode 100755 index 0000000..a476513 --- /dev/null +++ b/bin/tests/system/inline/tests.sh @@ -0,0 +1,1387 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +dnssec -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +dig_with_opts() { + $DIG $DIGOPTS "$@" +} + +rndccmd() { + $RNDCCMD "$@" +} + +wait_for_serial() ( + $DIG $DIGOPTS "@$1" "$2" SOA >"$4" + serial=$(awk '$4 == "SOA" { print $7 }' "$4") + [ "$3" -eq "${serial:--1}" ] +) + +status=0 +n=0 +ret=0 + +# Make sure nsec3 zone is NSEC3 signed. +for i in 1 2 3 4 5 6 7 8 9 0; do + nsec3param=$($DIG $DIGOPTS +nodnssec +short @10.53.0.3 nsec3param nsec3.) || ret=1 + test "$nsec3param" = "1 0 0 -" && break + sleep 1 +done + +if [ $ret != 0 ]; then + echo_i "pre-condition failed, test aborted" + exit 1 +fi + +n=$((n + 1)) +echo_i "checking that an unsupported algorithm is not used for signing ($n)" +ret=0 +grep -q "algorithm is unsupported" ns3/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that rrsigs are replaced with ksk only ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 axfr nsec3. \ + | awk '/RRSIG NSEC3/ {a[$1]++} END { for (i in a) {if (a[i] != 1) exit (1)}}' || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the zone is signed on initial transfer ($n)" +ret=0 +zone_is_signed() { + $DIG $DIGOPTS @10.53.0.3 bits. AXFR >dig.out.ns3.test$n || return 1 + $VERIFY -z -o bits. dig.out.ns3.test$n >verify.out.bits.test$n || return 1 + return 0 +} +retry_quiet 10 zone_is_signed || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking expired signatures are updated on load ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 +noall +answer +dnssec expired SOA >dig.out.ns3.test$n || ret=1 +expiry=$(awk '$4 == "RRSIG" { print $9 }' dig.out.ns3.test$n) +[ "$expiry" = "20110101000000" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking removal of private type record via 'rndc signing -clear' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 signing -list bits >signing.out.test$n 2>&1 || ret=1 +keys=$(sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n) +for key in $keys; do + $RNDCCMD 10.53.0.3 signing -clear ${key} bits >/dev/null || ret=1 + break # We only want to remove 1 record for now. +done 2>&1 | sed 's/^/ns3 /' | cat_i + +for i in 1 2 3 4 5 6 7 8 9 10; do + ans=0 + $RNDCCMD 10.53.0.3 signing -list bits >signing.out.test$n 2>&1 || ret=1 + num=$(grep "Done signing with" signing.out.test$n | wc -l) + [ $num = 1 ] && break + sleep 1 +done +[ $ans = 0 ] || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking private type was properly signed ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.6 bits TYPE65534 >dig.out.ns6.test$n || ret=1 +# One private type record, one signature +grep "ANSWER: 2," dig.out.ns6.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns6.test$n >/dev/null || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking removal of remaining private type record via 'rndc signing -clear all' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 signing -clear all bits >signing.out.test$n.clear || ret=1 + +for i in 1 2 3 4 5 6 7 8 9 10; do + ans=0 + $RNDCCMD 10.53.0.3 signing -list bits >signing.out.test$n 2>&1 || ret=1 + grep "No signing records found" signing.out.test$n >/dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking negative private type response was properly signed ($n)" +ret=0 +sleep 1 +$DIG $DIGOPTS @10.53.0.6 bits TYPE65534 >dig.out.ns6.test$n || ret=1 +grep "status: NOERROR" dig.out.ns6.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns6.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns6.test$n >/dev/null || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the record is added on the hidden primary ($n)" +ret=0 + +$NSUPDATE <dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that update has been transferred and has been signed ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 added.bits A >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072400) serial on hidden primary ($n)" +ret=0 + +$NSUPDATE <dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2011072400" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072400) serial in signed zone ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 bits SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072400" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the zone is signed on initial transfer, noixfr ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $RNDCCMD 10.53.0.3 signing -list noixfr >signing.out.test$n 2>&1 || ret=1 + keys=$(grep '^Done signing' signing.out.test$n | wc -l) + [ $keys = 2 ] || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the record is added on the hidden primary, noixfr ($n)" +ret=0 + +$NSUPDATE <dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that update has been transferred and has been signed, noixfr ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 added.noixfr A >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072400) serial on hidden primary, noixfr ($n)" +ret=0 + +$NSUPDATE <dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +grep "2011072400" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072400) serial in signed zone, noixfr ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 noixfr SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072400" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the primary zone signed on initial load ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $RNDCCMD 10.53.0.3 signing -list primary >signing.out.test$n 2>&1 || ret=1 + keys=$(grep '^Done signing' signing.out.test$n | wc -l) + [ $keys = 2 ] || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking removal of private type record via 'rndc signing -clear' (primary) ($n)" +ret=0 +$RNDCCMD 10.53.0.3 signing -list primary >signing.out.test$n 2>&1 || ret=1 +keys=$(sed -n -e 's/Done signing with key \(.*\)$/\1/p' signing.out.test$n) +for key in $keys; do + $RNDCCMD 10.53.0.3 signing -clear ${key} primary >/dev/null || ret=1 + break # We only want to remove 1 record for now. +done 2>&1 | sed 's/^/ns3 /' | cat_i + +for i in 1 2 3 4 5 6 7 8 9; do + ans=0 + $RNDCCMD 10.53.0.3 signing -list primary >signing.out.test$n 2>&1 || ret=1 + num=$(grep "Done signing with" signing.out.test$n | wc -l) + [ $num = 1 ] && break + sleep 1 +done +[ $ans = 0 ] || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking private type was properly signed (primary) ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.6 primary TYPE65534 >dig.out.ns6.test$n || ret=1 +grep "ANSWER: 2," dig.out.ns6.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns6.test$n >/dev/null || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking removal of remaining private type record via 'rndc signing -clear' (primary) ($n)" +ret=0 +$RNDCCMD 10.53.0.3 signing -clear all primary >/dev/null || ret=1 +for i in 1 2 3 4 5 6 7 8 9 10; do + ans=0 + $RNDCCMD 10.53.0.3 signing -list primary >signing.out.test$n 2>&1 || ret=1 + grep "No signing records found" signing.out.test$n >/dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check adding of record to unsigned primary ($n)" +ret=0 +cp ns3/primary2.db.in ns3/primary.db +rndc_reload ns3 10.53.0.3 primary +for i in 1 2 3 4 5 6 7 8 9; do + ans=0 + $DIG $DIGOPTS @10.53.0.3 e.primary A >dig.out.ns3.test$n || ret=1 + grep "10.0.0.5" dig.out.ns3.test$n >/dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check adding record fails when SOA serial not changed ($n)" +ret=0 +echo "c A 10.0.0.3" >>ns3/primary.db +rndc_reload ns3 10.53.0.3 +sleep 1 +$DIG $DIGOPTS @10.53.0.3 c.primary A >dig.out.ns3.test$n || ret=1 +grep "NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check adding record works after updating SOA serial ($n)" +ret=0 +cp ns3/primary3.db.in ns3/primary.db +$RNDCCMD 10.53.0.3 reload primary 2>&1 | sed 's/^/ns3 /' | cat_i +for i in 1 2 3 4 5 6 7 8 9; do + ans=0 + $DIG $DIGOPTS @10.53.0.3 c.primary A >dig.out.ns3.test$n || ret=1 + grep "10.0.0.3" dig.out.ns3.test$n >/dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check the added record was properly signed ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 e.primary A >dig.out.ns6.test$n || ret=1 +grep "10.0.0.5" dig.out.ns6.test$n >/dev/null || ans=1 +grep "ANSWER: 2," dig.out.ns6.test$n >/dev/null || ans=1 +grep "flags:.* ad[ ;]" dig.out.ns6.test$n >/dev/null || ans=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the dynamic primary zone signed on initial load ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $RNDCCMD 10.53.0.3 signing -list dynamic >signing.out.test$n 2>&1 || ret=1 + keys=$(grep '^Done signing' signing.out.test$n | wc -l) + [ $keys = 2 ] || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking primary zone that was updated while offline is correct ($n)" +ret=0 +$DIG $DIGOPTS +nodnssec +short @10.53.0.3 updated SOA >dig.out.ns3.soa.test$n || ret=1 +serial=$(awk '{print $3}' dig.out.ns3.soa.test$n) +# serial should have changed +[ "$serial" = "2000042407" ] && ret=1 +# e.updated should exist and should be signed +$DIG $DIGOPTS @10.53.0.3 e.updated A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 +# updated.db.signed.jnl should exist, should have the source serial +# of primary2.db, and should show a minimal diff: no more than 8 added +# records (SOA/RRSIG, 2 x NSEC/RRSIG, A/RRSIG), and 4 removed records +# (SOA/RRSIG, NSEC/RRSIG). +$JOURNALPRINT ns3/updated.db.signed.jnl >journalprint.out.test$n || ret=1 +serial=$(awk '/Source serial =/ {print $4}' journalprint.out.test$n) +[ "$serial" = "2000042408" ] || ret=1 +diffsize=$(wc -l dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ans=1 + grep "1.2.3.4" dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 0 ] && break + sleep 1 +done +[ $ans = 0 ] || { + ret=1 + echo_i "signed record not found" + cat dig.out.ns3.test$n +} + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "stop bump in the wire signer server ($n)" +ret=0 +stop_server ns3 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "restart bump in the wire signer server ($n)" +ret=0 +start_server --noclean --restart --port ${PORT} ns3 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072450) serial on hidden primary ($n)" +ret=0 + +$NSUPDATE <dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2011072450" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072450) serial in signed zone ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 bits SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072450" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072450) serial on hidden primary, noixfr ($n)" +ret=0 + +$NSUPDATE <dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +grep "2011072450" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking YYYYMMDDVV (2011072450) serial in signed zone, noixfr ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 noixfr SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072450" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking forwarded update on hidden primary ($n)" +ret=0 + +$NSUPDATE <dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +grep "2011072460" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking forwarded update on signed zone ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 bits SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072460" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking forwarded update on hidden primary, noixfr ($n)" +ret=0 + +$NSUPDATE <dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 +grep "2011072460" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking forwarded update on signed zone, noixfr ($n)" +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 noixfr SOA >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + grep "2011072460" dig.out.ns3.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +ret=0 +n=$((n + 1)) +echo_i "checking turning on of inline signing in a secondary zone via reload ($n)" +$DIG $DIGOPTS @10.53.0.5 +dnssec bits SOA >dig.out.ns5.test$n || ret=1 +grep "status: NOERROR" dig.out.ns5.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns5.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "setup broken"; fi +status=$((status + ret)) +copy_setports ns5/named.conf.post ns5/named.conf +( + cd ns5 + $KEYGEN -q -a ${DEFAULT_ALGORITHM} bits +) >/dev/null 2>&1 +( + cd ns5 + $KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK bits +) >/dev/null 2>&1 +rndc_reload ns5 10.53.0.5 +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG $DIGOPTS @10.53.0.5 bits SOA >dig.out.ns5.test$n || ret=1 + grep "status: NOERROR" dig.out.ns5.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns5.test$n >/dev/null || ret=1 + if [ $ret = 0 ]; then break; fi + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking rndc freeze/thaw of dynamic inline zone no change ($n)" +ret=0 +$RNDCCMD 10.53.0.3 freeze dynamic >freeze.test$n 2>&1 || { + echo_i "/' < freeze.test$n" + ret=1 +} +sleep 1 +$RNDCCMD 10.53.0.3 thaw dynamic >thaw.test$n 2>&1 || { + echo_i "rndc thaw dynamic failed" + ret=1 +} +sleep 1 +grep "zone dynamic/IN (unsigned): ixfr-from-differences: unchanged" ns3/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking rndc freeze/thaw of dynamic inline zone ($n)" +ret=0 +$RNDCCMD 10.53.0.3 freeze dynamic >freeze.test$n 2>&1 || ret=1 +sleep 1 +awk '$2 == ";" && $3 ~ /serial/ { printf("%d %s %s\n", $1 + 1, $2, $3); next; } + { print; } + END { print "freeze1.dynamic. 0 TXT freeze1"; } ' ns3/dynamic.db >ns3/dynamic.db.new +mv ns3/dynamic.db.new ns3/dynamic.db +$RNDCCMD 10.53.0.3 thaw dynamic >thaw.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check added record freeze1.dynamic ($n)" +for i in 1 2 3 4 5 6 7 8 9; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 freeze1.dynamic TXT >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + test $ret = 0 && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# allow 1 second so that file time stamps change +sleep 1 + +n=$((n + 1)) +echo_i "checking rndc freeze/thaw of server ($n)" +ret=0 +$RNDCCMD 10.53.0.3 freeze >freeze.test$n 2>&1 || ret=1 +sleep 1 +awk '$2 == ";" && $3 ~ /serial/ { printf("%d %s %s\n", $1 + 1, $2, $3); next; } + { print; } + END { print "freeze2.dynamic. 0 TXT freeze2"; } ' ns3/dynamic.db >ns3/dynamic.db.new +mv ns3/dynamic.db.new ns3/dynamic.db +$RNDCCMD 10.53.0.3 thaw >thaw.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check added record freeze2.dynamic ($n)" +for i in 1 2 3 4 5 6 7 8 9; do + ret=0 + $DIG $DIGOPTS @10.53.0.3 freeze2.dynamic TXT >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ret=1 + test $ret = 0 && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc reload allows reuse of inline-signing zones ($n)" +ret=0 +{ $RNDCCMD 10.53.0.3 reload 2>&1 || ret=1; } | sed 's/^/ns3 /' | cat_i +grep "not reusable" ns3/named.run >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc sync removes both signed and unsigned journals ($n)" +ret=0 +[ -f ns3/dynamic.db.jnl ] || ret=1 +[ -f ns3/dynamic.db.signed.jnl ] || ret=1 +$RNDCCMD 10.53.0.3 sync -clean dynamic 2>&1 || ret=1 +[ -f ns3/dynamic.db.jnl ] && ret=1 +[ -f ns3/dynamic.db.signed.jnl ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the retransfer record is added on the hidden primary ($n)" +ret=0 + +$NSUPDATE <dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the change has not been transferred due to notify ($n)" +ret=0 +for i in 0 1 2 3 4 5 6 7 8 9; do + ans=0 + $DIG $DIGOPTS @10.53.0.3 added.retransfer A >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 0 ] && break + sleep 1 +done +if [ $ans != 1 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc retransfer of a inline secondary zone works ($n)" +ret=0 +$RNDCCMD 10.53.0.3 retransfer retransfer 2>&1 || ret=1 +for i in 0 1 2 3 4 5 6 7 8 9; do + ans=0 + $DIG $DIGOPTS @10.53.0.3 added.retransfer A >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 0 ] && break + sleep 1 +done +[ $ans = 1 ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# NOTE: The test below should be considered fragile. More details can be found +# in the comment inside ns7/named.conf. +n=$((n + 1)) +echo_i "check rndc retransfer of a inline nsec3 secondary does not trigger an infinite loop ($n)" +ret=0 +zone=nsec3-loop +# Add secondary zone using rndc +$RNDCCMD 10.53.0.7 addzone $zone \ + '{ type secondary; primaries { 10.53.0.2; }; file "'$zone'.db"; inline-signing yes; dnssec-policy default; };' || ret=1 +# Wait until secondary zone is fully signed using NSEC +for i in 1 2 3 4 5 6 7 8 9 0; do + ret=1 + $RNDCCMD 10.53.0.7 signing -list $zone >signing.out.test$n 2>&1 || ret=1 + keys=$(grep '^Done signing' signing.out.test$n | wc -l) + [ $keys -eq 3 ] && ret=0 && break + sleep 1 +done +# Switch secondary zone to NSEC3 +$RNDCCMD 10.53.0.7 modzone $zone \ + '{ type secondary; primaries { 10.53.0.2; }; file "'$zone'.db"; inline-signing yes; dnssec-policy nsec3; };' || ret=1 +# Wait until secondary zone is fully signed using NSEC3 +for i in 1 2 3 4 5 6 7 8 9 0; do + ret=1 + $DIG $DIGOPTS +nodnssec +short @10.53.0.7 nsec3param $zone >dig.out.ns7.test$n + nsec3param=$(cat dig.out.ns7.test$n) + test "$nsec3param" = "1 0 0 -" && ret=0 && break + sleep 1 +done + +# Attempt to retransfer the secondary zone from primary +$RNDCCMD 10.53.0.7 retransfer $zone || ret=1 +# Check whether the signer managed to fully sign the retransferred zone by +# waiting for a specific SOA serial number to appear in the logs; if this +# specific SOA serial number does not appear in the logs, it means the signer +# has either ran into an infinite loop or crashed; note that we check the logs +# instead of sending SOA queries to the signer as these may influence its +# behavior in a way which may prevent the desired scenario from being +# reproduced (see comment in ns7/named.conf) +for i in 1 2 3 4 5 6 7 8 9 0; do + ret=1 + { + grep "ns2.$zone. . 10 20 20 1814400 3600" ns7/named.run >/dev/null 2>&1 + rc=$? + } || true + [ $rc -eq 0 ] && ret=0 && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "stop bump in the wire signer server ($n)" +ret=0 +stop_server ns3 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "update SOA record while stopped" +cp ns3/primary4.db.in ns3/primary.db +rm -f ns3/primary.db.jnl + +n=$((n + 1)) +echo_i "restart bump in the wire signer server ($n)" +ret=0 +start_server --noclean --restart --port ${PORT} ns3 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "updates to SOA parameters other than serial while stopped are reflected in signed zone ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9; do + ans=0 + $DIG $DIGOPTS @10.53.0.3 primary SOA >dig.out.ns3.test$n || ret=1 + grep "hostmaster" dig.out.ns3.test$n >/dev/null || ans=1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || ans=1 + [ $ans = 1 ] || break + sleep 1 +done +[ $ans = 0 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that reloading all zones does not cause zone maintenance to cease for inline-signed zones ($n)" +ret=1 +# Ensure "rndc reload" attempts to load ns3/primary.db by waiting 1 second so +# that the file modification time has no possibility of being equal to +# the one stored during server startup. +sleep 1 +nextpart ns3/named.run >/dev/null +cp ns3/primary5.db.in ns3/primary.db +rndc_reload ns3 10.53.0.3 +for i in 1 2 3 4 5 6 7 8 9 10; do + if nextpart ns3/named.run | grep "zone primary.*sending notifies" >/dev/null; then + ret=0 + break + fi + sleep 1 +done +# Sanity check: file updates should be reflected in the signed zone, +# i.e. SOA RNAME should no longer be set to "hostmaster". +$DIG $DIGOPTS @10.53.0.3 primary SOA >dig.out.ns3.test$n || ret=1 +grep "hostmaster" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that reloading errors prevent synchronization ($n)" +ret=1 +$DIG $DIGOPTS +short @10.53.0.3 primary SOA >dig.out.ns3.test$n.1 || ret=1 +sleep 1 +nextpart ns3/named.run >/dev/null +cp ns3/primary6.db.in ns3/primary.db +rndc_reload ns3 10.53.0.3 +for i in 1 2 3 4 5 6 7 8 9 10; do + if nextpart ns3/named.run | grep "not loaded due to errors" >/dev/null; then + ret=0 + break + fi + sleep 1 +done +# Sanity check: the SOA record should be unchanged +$DIG $DIGOPTS +short @10.53.0.3 primary SOA | grep -v '^;' >dig.out.ns3.test$n.2 +diff dig.out.ns3.test$n.1 dig.out.ns3.test$n.2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check inline-signing with an include file ($n)" +ret=0 +$DIG $DIGOPTS +short @10.53.0.3 primary SOA >dig.out.ns3.test$n.1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +sleep 1 +nextpart ns3/named.run >/dev/null +cp ns3/primary7.db.in ns3/primary.db +rndc_reload ns3 10.53.0.3 +_includefile_loaded() { + $DIG $DIGOPTS @10.53.0.3 f.primary A >dig.out.ns3.test$n || return 1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || return 1 + grep "ANSWER: 2," dig.out.ns3.test$n >/dev/null || return 1 + grep "10\.0\.0\.7" dig.out.ns3.test$n >/dev/null || return 1 + return 0 +} +retry_quiet 10 _includefile_loaded +# Sanity check: the SOA record should be changed +$DIG $DIGOPTS +short @10.53.0.3 primary SOA | grep -v '^;' >dig.out.ns3.test$n.2 +diff dig.out.ns3.test$n.1 dig.out.ns3.test$n.2 >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test add/del zone combinations ($n)" +ret=0 +for zone in a b c d e f g h i j k l m n o p q r s t u v w x y z; do + $RNDCCMD 10.53.0.2 addzone test-$zone \ + '{ type primary; file "bits.db.in"; allow-transfer { any; }; };' || ret=1 + $DIG $DIGOPTS @10.53.0.2 test-$zone SOA >dig.out.ns2.$zone.test$n || ret=1 + grep "status: NOERROR," dig.out.ns2.$zone.test$n >/dev/null || { + ret=1 + cat dig.out.ns2.$zone.test$n + } + $RNDCCMD 10.53.0.3 addzone test-$zone \ + '{ type secondary; primaries { 10.53.0.2; }; file "'test-$zone.bk'"; inline-signing yes; dnssec-policy default; allow-transfer { any; }; };' || ret=1 + $RNDCCMD 10.53.0.3 delzone test-$zone >/dev/null 2>&1 || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing adding external keys to a inline zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 dnskey externalkey >dig.out.ns3.test$n || ret=1 +for alg in ${DEFAULT_ALGORITHM_NUMBER} ${ALTERNATIVE_ALGORITHM_NUMBER}; do + [ $alg = 13 -a ! -f checkecdsa ] && continue + + case $alg in + 7) echo_i "checking NSEC3RSASHA1" ;; + 8) echo_i "checking RSASHA256" ;; + 13) echo_i "checking ECDSAP256SHA256" ;; + *) echo_i "checking $alg" ;; + esac + + dnskeys=$(grep "IN.DNSKEY.25[67] [0-9]* $alg " dig.out.ns3.test$n | wc -l) + rrsigs=$(grep "RRSIG.DNSKEY $alg " dig.out.ns3.test$n | wc -l) + test ${dnskeys:-0} -eq 4 || { + echo_i "failed $alg (dnskeys ${dnskeys:-0})" + ret=1 + } + test ${rrsigs:-0} -eq 1 || { + echo_i "failed $alg (rrsigs ${rrsigs:-0})" + ret=1 + } +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing imported key won't overwrite a private key ($n)" +ret=0 +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} import.example) +cp ${key}.key import.key +# import should fail +$IMPORTKEY -f import.key import.example >/dev/null 2>&1 && ret=1 +rm -f ${key}.private +# private key removed; import should now succeed +$IMPORTKEY -f import.key import.example >/dev/null 2>&1 || ret=1 +# now that it's an external key, re-import should succeed +$IMPORTKEY -f import.key import.example >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing updating inline secure serial via 'rndc signing -serial' ($n)" +ret=0 +$DIG $DIGOPTS nsec3. SOA @10.53.0.3 >dig.out.n3.pre.test$n || ret=1 +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +retry_quiet 5 wait_for_serial 10.53.0.3 nsec3. "${newserial:-0}" dig.out.ns3.post.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing updating inline secure serial via 'rndc signing -serial' with negative change ($n)" +ret=0 +$DIG $DIGOPTS nsec3. SOA @10.53.0.3 >dig.out.n3.pre.test$n || ret=1 +oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n) +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] - 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +sleep 1 +$DIG $DIGOPTS nsec3. SOA @10.53.0.3 >dig.out.ns3.post.test$n || ret=1 +serial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns3.post.test$n) +[ ${oldserial:-0} -eq ${serial:-1} ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Freezing only operates on the raw zone. +# +n=$((n + 1)) +echo_i "testing updating inline secure serial via 'rndc signing -serial' when frozen ($n)" +ret=0 +$DIG $DIGOPTS nsec3. SOA @10.53.0.3 >dig.out.n3.pre.test$n || ret=1 +oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.n3.pre.test$n) +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 signing -serial ${newserial:-0} nsec3 >/dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.3 thaw nsec3 >/dev/null 2>&1 || ret=1 +retry_quiet 5 wait_for_serial 10.53.0.3 nsec3. "${newserial:-0}" dig.out.ns3.post1.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing updating dynamic serial via 'rndc signing -serial' ($n)" +ret=0 +$DIG $DIGOPTS bits. SOA @10.53.0.2 >dig.out.ns2.pre.test$n || ret=1 +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-0}" dig.out.ns2.post.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing updating dynamic serial via 'rndc signing -serial' with negative change ($n)" +ret=0 +$DIG $DIGOPTS bits. SOA @10.53.0.2 >dig.out.ns2.pre.test$n || ret=1 +oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n) +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] - 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-1}" dig.out.ns2.post1.test$n && ret=1 +retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${oldserial:-1}" dig.out.ns2.post2.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing updating dynamic serial via 'rndc signing -serial' when frozen ($n)" +ret=0 +$DIG $DIGOPTS bits. SOA @10.53.0.2 >dig.out.ns2.pre.test$n || ret=1 +oldserial=$(awk '$4 == "SOA" { print $7 }' dig.out.ns2.pre.test$n) +newserial=$($PERL -e 'while (<>) { chomp; my @field = split /\s+/; printf("%u\n", $field[6] + 10) if ($field[3] eq "SOA"); }' /dev/null 2>&1 || ret=1 +$RNDCCMD 10.53.0.2 signing -serial ${newserial:-0} bits >/dev/null 2>&1 && ret=1 +$RNDCCMD 10.53.0.2 thaw bits >/dev/null 2>&1 || ret=1 +retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${newserial:-1}" dig.out.ns2.post1.test$n && ret=1 +retry_quiet 5 wait_for_serial 10.53.0.2 bits. "${oldserial:-1}" dig.out.ns2.post2.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Wait until an update to the raw part of a given inline signed zone is fully +# processed. As waiting for a fixed amount of time is suboptimal and there is +# no single message that would signify both a successful modification and an +# error in a race-free manner, instead wait until either notifies are sent +# (which means the secure zone was modified) or a receive_secure_serial() error +# is logged (which means the zone was not modified and will not be modified any +# further in response to the relevant raw zone update). +wait_until_raw_zone_update_is_processed() { + zone="$1" + for i in 1 2 3 4 5 6 7 8 9 10; do + if nextpart ns3/named.run | grep -E "zone ${zone}.*(sending notifies|receive_secure_serial)" >/dev/null; then + return + fi + sleep 1 + done +} + +n=$((n + 1)) +echo_i "checking that changes to raw zone are applied to a previously unsigned secure zone ($n)" +ret=0 +# Query for bar.nokeys/A and ensure the response is negative. As this zone +# does not have any signing keys set up, the response must be unsigned. +$DIG $DIGOPTS @10.53.0.3 bar.nokeys. A >dig.out.ns3.pre.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.pre.test$n >/dev/null && ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null && ret=1 +# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore +# log messages generated before the raw zone is updated. +nextpart ns3/named.run >/dev/null +# Add a record to the raw zone on the primary. +$NSUPDATE <dig.out.ns3.post.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.post.test$n >/dev/null || ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that changes to raw zone are not applied to a previously signed secure zone with no keys available (primary) ($n)" +ret=0 +# Query for bar.removedkeys-primary/A and ensure the response is negative. As +# this zone has signing keys set up, the response must be signed. +$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-primary. A >dig.out.ns3.pre.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.pre.test$n >/dev/null && ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null || ret=1 +# Remove the signing keys for this zone. +mv -f ns3/Kremovedkeys-primary* ns3/removedkeys +# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore +# log messages generated before the raw zone is updated. +nextpart ns3/named.run >/dev/null +# Add a record to the raw zone on the primary. +$NSUPDATE <dig.out.ns3.post.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.post.test$n >/dev/null && ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that backlogged changes to raw zone are applied after keys become available (primary) ($n)" +ret=0 +# Restore the signing keys for this zone. +mv ns3/removedkeys/Kremovedkeys-primary* ns3 +$RNDCCMD 10.53.0.3 loadkeys removedkeys-primary >/dev/null 2>&1 || ret=1 +# Determine what a SOA record with a bumped serial number should look like. +BUMPED_SOA=$(sed -n 's/.*\(add removedkeys-primary.*IN.*SOA\)/\1/p;' ns3/named.run | tail -1 | awk '{$8 += 1; print $0}') +# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore +# log messages generated before the raw zone is updated. +nextpart ns3/named.run >/dev/null +# Bump the SOA serial number of the raw zone. +$NSUPDATE <dig.out.ns3.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "RRSIG" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that changes to raw zone are not applied to a previously signed secure zone with no keys available (secondary) ($n)" +ret=0 +# Query for bar.removedkeys-secondary/A and ensure the response is negative. As this +# zone does have signing keys set up, the response must be signed. +$DIG $DIGOPTS @10.53.0.3 bar.removedkeys-secondary. A >dig.out.ns3.pre.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.pre.test$n >/dev/null && ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null || ret=1 +# Remove the signing keys for this zone. +mv -f ns3/Kremovedkeys-secondary* ns3/removedkeys +# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore +# log messages generated before the raw zone is updated. +nextpart ns3/named.run >/dev/null +# Add a record to the raw zone on the primary. +$NSUPDATE <dig.out.ns3.post.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.post.test$n >/dev/null && ret=1 +grep "RRSIG" dig.out.ns3.pre.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that backlogged changes to raw zone are applied after keys become available (secondary) ($n)" +ret=0 +# Restore the signing keys for this zone. +mv ns3/removedkeys/Kremovedkeys-secondary* ns3 +$RNDCCMD 10.53.0.3 loadkeys removedkeys-secondary >/dev/null 2>&1 || ret=1 +# Determine what a SOA record with a bumped serial number should look like. +BUMPED_SOA=$(sed -n 's/.*\(add removedkeys-secondary.*IN.*SOA\)/\1/p;' ns2/named.run | tail -1 | awk '{$8 += 1; print $0}') +# Ensure the wait_until_raw_zone_update_is_processed() call below will ignore +# log messages generated before the raw zone is updated. +nextpart ns3/named.run >/dev/null +# Bump the SOA serial number of the raw zone on the primary. +$NSUPDATE <dig.out.ns3.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "RRSIG" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check that the file $2 for zone $1 does not contain RRSIG records +# while the journal file for that zone does contain them. +ensure_sigs_only_in_journal() { + origin="$1" + masterfile="$2" + $CHECKZONE -i none -f raw -D -o - "$origin" "$masterfile" 2>&1 | grep -w RRSIG >/dev/null && ret=1 + $CHECKZONE -j -i none -f raw -D -o - "$origin" "$masterfile" 2>&1 | grep -w RRSIG >/dev/null || ret=1 +} + +n=$((n + 1)) +echo_i "checking that records added from a journal are scheduled to be resigned ($n)" +ret=0 +zone="delayedkeys" +# Signing keys for the "delayedkeys" zone are not yet accessible. Thus, the +# zone file for the signed version of the zone will contain no DNSSEC records. +# Move keys into place now and load them, which will cause DNSSEC records to +# only be present in the journal for the signed version of the zone. +mv Kdelayedkeys* ns3/ +cp ns3/delayedkeys.conf.2 ns3/delayedkeys.conf +$RNDCCMD 10.53.0.3 reconfig >/dev/null 2>&1 || ret=1 + +#$RNDCCMD 10.53.0.3 loadkeys delayedkeys > rndc.out.ns3.pre.test$n 2>&1 || ret=1 +# Wait until the zone is signed. +check_done_signing() ( + $RNDCCMD 10.53.0.3 signing -list delayedkeys >signing.out.test$n 2>&1 || true + num=$(grep "Done signing with" signing.out.test$n | wc -l) + [ $num -eq 2 ] +) +retry_quiet 10 check_done_signing || ret=1 +# Halt rather than stopping the server to prevent the file from being +# flushed upon shutdown since we specifically want to avoid it. +stop_server --use-rndc --halt --port ${CONTROLPORT} ns3 || ret=1 +ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed +start_server --noclean --restart --port ${PORT} ns3 || ret=1 +# At this point, the raw zone journal will not have a source serial set. Upon +# server startup, receive_secure_serial() will rectify that, update SOA, resign +# it, and schedule its future resign. This will cause "rndc zonestatus" to +# return delayedkeys/SOA as the next node to resign, so we restart the server +# once again; with the raw zone journal now having a source serial set, +# receive_secure_serial() should refrain from introducing any zone changes. +stop_server --use-rndc --halt --port ${CONTROLPORT} ns3 || ret=1 +ensure_sigs_only_in_journal delayedkeys ns3/delayedkeys.db.signed +nextpart ns3/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns3 || ret=1 +# We can now test whether the secure zone journal was correctly processed: +# unless the records contained in it were scheduled for resigning, no resigning +# event will be scheduled at all since the secure zone file contains no +# DNSSEC records. +wait_for_log 20 "all zones loaded" ns3/named.run || ret=1 +$RNDCCMD 10.53.0.3 zonestatus delayedkeys >rndc.out.ns3.post.test$n 2>&1 || ret=1 +grep "next resign node:" rndc.out.ns3.post.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that zonestatus reports 'type: primary' for an inline primary zone ($n)" +ret=0 +$RNDCCMD 10.53.0.3 zonestatus primary >rndc.out.ns3.test$n || ret=1 +grep "type: primary" rndc.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that zonestatus reports 'type: secondary' for an inline secondary zone ($n)" +ret=0 +$RNDCCMD 10.53.0.3 zonestatus bits >rndc.out.ns3.test$n || ret=1 +grep "type: secondary" rndc.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking reload of touched inline zones ($n)" +ret=0 +echo_ic "pre-reload 'next key event'" +nextpart ns8/named.run >nextpart.pre$n.out +count=$(grep "zone example[0-9][0-9].com/IN (signed): next key event:" nextpart.pre$n.out | wc -l) +echo_ic "found: $count/16" +[ $count -eq 16 ] || ret=1 +echo_ic "touch and reload" +touch ns8/example??.com.db +$RNDCCMD 10.53.0.8 reload 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 5 +echo_ic "post-reload 'next key event'" +nextpart ns8/named.run >nextpart.post$n.out +count=$(grep "zone example[0-9][0-9].com/IN (signed): next key event:" nextpart.post$n.out | wc -l) +echo_ic "found: $count/16" +[ $count -eq 16 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking second reload of touched inline zones ($n)" +ret=0 +nextpart ns8/named.run >nextpart.pre$n.out +$RNDCCMD 10.53.0.8 reload 2>&1 | sed 's/^/ns3 /' | cat_i +sleep 5 +nextpart ns8/named.run >nextpart.post$n.out +grep "ixfr-from-differences: unchanged" nextpart.post$n.out && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check that 'rndc reload' of just the serial updates the signed instance ($n)" +ret=0 +dig_with_opts @10.53.0.8 example SOA >dig.out.ns8.test$n.soa1 || ret=1 +cp ns8/example2.db.in ns8/example.db || ret=1 +nextpart ns8/named.run >/dev/null +rndccmd 10.53.0.8 reload || ret=1 +wait_for_log 3 "all zones loaded" ns8/named.run +sleep 1 +dig_with_opts @10.53.0.8 example SOA >dig.out.ns8.test$n.soa2 || ret=1 +soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa1) +soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa2) +ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa1) +ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa2) +test ${soa1:-1000} -lt ${soa2:-0} || ret=1 +test ${ttl1:-0} -eq 300 || ret=1 +test ${ttl2:-0} -eq 300 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check that restart with zone changes and deleted journal works ($n)" +TSIG= +ret=0 +dig_with_opts @10.53.0.8 example SOA >dig.out.ns8.test$n.soa1 || ret=1 +stop_server --use-rndc --port ${CONTROLPORT} ns8 || ret=1 +# TTL of all records change from 300 to 400 +cp ns8/example3.db.in ns8/example.db || ret=1 +rm -f ns8/example.db.jnl +nextpart ns8/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns8 || ret=1 +wait_for_log 3 "all zones loaded" ns8/named.run +sleep 1 +dig_with_opts @10.53.0.8 example SOA >dig.out.ns8.test$n.soa2 || ret=1 +soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa1) +soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns8.test$n.soa2) +ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa1) +ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns8.test$n.soa2) +test ${soa1:-1000} -lt ${soa2:-0} || ret=1 +test ${ttl1:-0} -eq 300 || ret=1 +test ${ttl2:-0} -eq 400 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/inline/tests_sh_inline.py b/bin/tests/system/inline/tests_sh_inline.py new file mode 100644 index 0000000..094e960 --- /dev/null +++ b/bin/tests/system/inline/tests_sh_inline.py @@ -0,0 +1,41 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "K*", + "*.out*", + "freeze.test*", + "import.key", + "journalprint.out.*", + "thaw.test*", + "*/*.out*", + "ns*/K*", + "ns*/dsset-*", + "ns*/*.db", + "ns*/*.nzd", + "ns*/*.nzf", + "ns*/K*", + "ns*/trusted.conf", + "ns*/*.bk", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/*.signed", + "ns3/delayedkeys.conf", + "ns3/removedkeys", + ] +) + + +def test_inline(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/inline/tests_signed_zone_files.py b/bin/tests/system/inline/tests_signed_zone_files.py new file mode 100755 index 0000000..aefeb55 --- /dev/null +++ b/bin/tests/system/inline/tests_signed_zone_files.py @@ -0,0 +1,88 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import glob +import struct + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "K*", + "*.out*", + "*/*.out*", + "ns*/K*", + "ns*/dsset-*", + "ns*/*.bk", + "ns*/*.db", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/*.nzd", + "ns*/*.signed", + "ns*/trusted.conf", + "ns3/delayedkeys.conf", + "ns3/removedkeys", + ] +) + + +class RawFormatHeader(dict): + """ + A dictionary of raw-format header fields read from a zone file. + """ + + fields = [ + "format", + "version", + "dumptime", + "flags", + "sourceserial", + "lastxfrin", + ] + + def __init__(self, file_name): + header = struct.Struct(">IIIIII") + with open(file_name, "rb") as data: + header_data = data.read(header.size) + super().__init__(zip(self.fields, header.unpack_from(header_data))) + + +def test_unsigned_serial_number(): + """ + Check whether all signed zone files in the "ns8" subdirectory contain the + serial number of the unsigned version of the zone in the raw-format header. + The test assumes that all "*.signed" files in the "ns8" subdirectory are in + raw format. + + Notes: + + - The actual zone signing and dumping happens while the tests.sh phase of + the "inline" system test is set up and run. This check only verifies + the outcome of those events; it does not initiate any signing or + dumping itself. + + - example[0-9][0-9].com.db.signed files are initially signed by + dnssec-signzone while the others - by named. + """ + + zones_with_unsigned_serial_missing = [] + + for signed_zone in sorted(glob.glob("ns8/*.signed")): + raw_header = RawFormatHeader(signed_zone) + # Ensure the unsigned serial number is placed where it is expected. + assert raw_header["format"] == 2 + assert raw_header["version"] == 1 + # Check whether the header flags indicate that the unsigned serial + # number is set and that the latter is indeed set. + if raw_header["flags"] & 0x02 == 0 or raw_header["sourceserial"] == 0: + zones_with_unsigned_serial_missing.append(signed_zone) + + assert not zones_with_unsigned_serial_missing diff --git a/bin/tests/system/integrity/ns1/mx-cname.db b/bin/tests/system/integrity/ns1/mx-cname.db new file mode 100644 index 0000000..a700269 --- /dev/null +++ b/bin/tests/system/integrity/ns1/mx-cname.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns1 hostmaster 0 0 0 0 0 +@ NS ns1 +@ MX 0 cname +ns1 A 10.53.0.1 +cname CNAME ns1 diff --git a/bin/tests/system/integrity/ns1/named.conf.j2 b/bin/tests/system/integrity/ns1/named.conf.j2 new file mode 100644 index 0000000..c1c092f --- /dev/null +++ b/bin/tests/system/integrity/ns1/named.conf.j2 @@ -0,0 +1,115 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "mx-cname-fail" { + type primary; + check-integrity yes; + check-mx-cname fail; + file "mx-cname.db"; +}; + +zone "mx-cname-warn" { + type primary; + check-integrity yes; + check-mx-cname warn; + file "mx-cname.db"; +}; + +zone "mx-cname-ignore" { + type primary; + check-integrity yes; + check-mx-cname ignore; + file "mx-cname.db"; +}; + +zone "no-mx-cname-fail" { + type primary; + check-integrity no; + check-mx-cname fail; + file "mx-cname.db"; +}; + +zone "no-mx-cname-warn" { + type primary; + check-integrity no; + check-mx-cname warn; + file "mx-cname.db"; +}; + +zone "no-mx-cname-ignore" { + type primary; + check-integrity no; + check-mx-cname ignore; + file "mx-cname.db"; +}; + +zone "srv-cname-fail" { + type primary; + check-integrity yes; + check-srv-cname fail; + file "srv-cname.db"; +}; + +zone "srv-cname-warn" { + type primary; + check-integrity yes; + check-srv-cname warn; + file "srv-cname.db"; +}; + +zone "srv-cname-ignore" { + type primary; + check-integrity yes; + check-srv-cname ignore; + file "srv-cname.db"; +}; +zone "no-srv-cname-fail" { + type primary; + check-integrity no; + check-srv-cname fail; + file "srv-cname.db"; +}; + +zone "no-srv-cname-warn" { + type primary; + check-integrity no; + check-srv-cname warn; + file "srv-cname.db"; +}; + +zone "no-srv-cname-ignore" { + type primary; + check-integrity no; + check-srv-cname ignore; + file "srv-cname.db"; +}; diff --git a/bin/tests/system/integrity/ns1/srv-cname.db b/bin/tests/system/integrity/ns1/srv-cname.db new file mode 100644 index 0000000..d6ae603 --- /dev/null +++ b/bin/tests/system/integrity/ns1/srv-cname.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns1 hostmaster 0 0 0 0 0 +@ NS ns1 +@ SRV 0 0 0 cname +ns1 A 10.53.0.1 +cname CNAME ns1 diff --git a/bin/tests/system/integrity/tests.sh b/bin/tests/system/integrity/tests.sh new file mode 100644 index 0000000..6c87273 --- /dev/null +++ b/bin/tests/system/integrity/tests.sh @@ -0,0 +1,132 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" + +status=0 +n=1 + +echo_i "check that 'check-integrity yes; check-mx-cname fail;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx mx-cname-fail >dig.out.test$n || ret=1 +grep "status: SERVFAIL," dig.out.test$n >/dev/null || ret=1 +grep "zone mx-cname-fail/IN: mx-cname-fail/MX 'cname.mx-cname-fail' is a CNAME (illegal)" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity yes; check-mx-cname warn;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx mx-cname-warn >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone mx-cname-warn/IN: mx-cname-warn/MX 'cname.mx-cname-warn' is a CNAME (illegal)" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity yes; check-mx-cname ignore;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx mx-cname-ignore >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone mx-cname-ignore/IN: mx-cname-ignore/MX 'cname.mx-cname-ignore' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-mx-cname fail;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-fail >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-mx-cname-fail/IN: no-mx-cname-fail/MX 'cname.no-mx-cname-fail' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-mx-cname warn;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-warn >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-mx-cname-warn/IN: no-mx-cname-warn/MX 'cname.no-mx-cname-warn' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-mx-cname ignore;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 mx no-mx-cname-ignore >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-mx-cname-ignore/IN: no-mx-cname-ignore/MX 'cname.no-mx-cname-ignore' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity yes; check-srv-cname fail;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv srv-cname-fail >dig.out.test$n || ret=1 +grep "status: SERVFAIL," dig.out.test$n >/dev/null || ret=1 +grep "zone srv-cname-fail/IN: srv-cname-fail/SRV 'cname.srv-cname-fail' is a CNAME (illegal)" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity yes; check-srv-cname warn;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv srv-cname-warn >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone srv-cname-warn/IN: srv-cname-warn/SRV 'cname.srv-cname-warn' is a CNAME (illegal)" ns1/named.run >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity yes; check-srv-cname ignore;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv srv-cname-ignore >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone srv-cname-ignore/IN: srv-cname-ignore/SRV 'cname.srv-cname-ignore' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-srv-cname fail;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-fail >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-srv-cname-fail/IN: no-srv-cname-fail/SRV 'cname.no-srv-cname-fail' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-srv-cname warn;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-warn >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-srv-cname-warn/IN: no-srv-cname-warn/SRV 'cname.no-srv-cname-warn' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "check that 'check-integrity no; check-srv-cname ignore;' works ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.1 srv no-srv-cname-ignore >dig.out.test$n || ret=1 +grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 +grep "zone no-srv-cname-ignore/IN: no-srv-cname-ignore/SRV 'cname.no-srv-cname-ignore' is a CNAME (illegal)" ns1/named.run >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +test $status -eq 0 || exit 1 diff --git a/bin/tests/system/integrity/tests_sh_integrity.py b/bin/tests/system/integrity/tests_sh_integrity.py new file mode 100644 index 0000000..f8ac3a5 --- /dev/null +++ b/bin/tests/system/integrity/tests_sh_integrity.py @@ -0,0 +1,22 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + ] +) + + +def test_integrity(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/isctest/__init__.py b/bin/tests/system/isctest/__init__.py new file mode 100644 index 0000000..b2fb77d --- /dev/null +++ b/bin/tests/system/isctest/__init__.py @@ -0,0 +1,27 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from . import check +from . import instance +from . import query +from . import kasp +from . import name +from . import rndc +from . import run +from . import template +from . import log +from . import vars # pylint: disable=redefined-builtin +from . import hypothesis + +# isctest.mark module is intentionally NOT imported, because it relies on +# environment variables which might not be set at the time of import of the +# `isctest` package. To use the marks, manual `import isctest.mark` is needed +# instead. diff --git a/bin/tests/system/isctest/__main__.py b/bin/tests/system/isctest/__main__.py new file mode 100644 index 0000000..d1be74c --- /dev/null +++ b/bin/tests/system/isctest/__main__.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import logging + +from . import log +from .vars import ALL, init_vars + + +if __name__ == "__main__": + # use root logger as fallback - we're not interested in proper logs here + log.basic.LOGGERS["conftest"] = logging.getLogger() + + init_vars() + for name, value in ALL.items(): + print(f"export {name}={value}") diff --git a/bin/tests/system/isctest/asyncserver.py b/bin/tests/system/isctest/asyncserver.py new file mode 100644 index 0000000..fed86f6 --- /dev/null +++ b/bin/tests/system/isctest/asyncserver.py @@ -0,0 +1,1110 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from dataclasses import dataclass, field +from typing import ( + Any, + AsyncGenerator, + Callable, + Coroutine, + Dict, + List, + Optional, + Tuple, + Type, + Union, + cast, +) + +import abc +import asyncio +import enum +import functools +import logging +import os +import pathlib +import re +import signal +import struct +import sys + +import dns.flags +import dns.message +import dns.name +import dns.node +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.rrset +import dns.zone + +try: + RdataType = dns.rdatatype.RdataType + RdataClass = dns.rdataclass.RdataClass +except AttributeError: # dnspython < 2.0.0 compat + RdataType = int # type: ignore + RdataClass = int # type: ignore + + +_UdpHandler = Callable[ + [bytes, Tuple[str, int], asyncio.DatagramTransport], Coroutine[Any, Any, None] +] + + +_TcpHandler = Callable[ + [asyncio.StreamReader, asyncio.StreamWriter], Coroutine[Any, Any, None] +] + + +class _AsyncUdpHandler(asyncio.DatagramProtocol): + """ + Protocol implementation for handling UDP traffic using asyncio. + """ + + def __init__( + self, + handler: _UdpHandler, + ) -> None: + self._transport: Optional[asyncio.DatagramTransport] = None + self._handler: _UdpHandler = handler + + def connection_made(self, transport: asyncio.BaseTransport) -> None: + """ + Called by asyncio when a connection is made. + """ + self._transport = cast(asyncio.DatagramTransport, transport) + + def datagram_received(self, data: bytes, addr: Tuple[str, int]) -> None: + """ + Called by asyncio when a datagram is received. + """ + assert self._transport + handler_coroutine = self._handler(data, addr, self._transport) + try: + # Python >= 3.7 + asyncio.create_task(handler_coroutine) + except AttributeError: + # Python < 3.7 + loop = asyncio.get_event_loop() + loop.create_task(handler_coroutine) + + +class AsyncServer: + """ + A generic asynchronous server which may handle UDP and/or TCP traffic. + + Once the server is executed as asyncio coroutine, it will keep running + until a SIGINT/SIGTERM signal is received. + """ + + def __init__( + self, + udp_handler: Optional[_UdpHandler], + tcp_handler: Optional[_TcpHandler], + pidfile: Optional[str] = None, + ) -> None: + logging.basicConfig( + format="%(asctime)s %(levelname)8s %(message)s", + level=os.environ.get("ANS_LOG_LEVEL", "INFO").upper(), + ) + try: + ipv4_address = sys.argv[1] + except IndexError: + ipv4_address = self._get_ipv4_address_from_directory_name() + + last_ipv4_address_octet = ipv4_address.split(".")[-1] + ipv6_address = f"fd92:7065:b8e:ffff::{last_ipv4_address_octet}" + + try: + port = int(sys.argv[2]) + except IndexError: + port = int(os.environ.get("PORT", 5300)) + + logging.info("Setting up IPv4 listener at %s:%d", ipv4_address, port) + logging.info("Setting up IPv6 listener at [%s]:%d", ipv6_address, port) + + self._ip_addresses: Tuple[str, str] = (ipv4_address, ipv6_address) + self._port: int = port + self._udp_handler: Optional[_UdpHandler] = udp_handler + self._tcp_handler: Optional[_TcpHandler] = tcp_handler + self._pidfile: Optional[str] = pidfile + self._work_done: Optional[asyncio.Future] = None + + def _get_ipv4_address_from_directory_name(self) -> str: + containing_directory = pathlib.Path().absolute().stem + match_result = re.match(r"ans(?P\d+)", containing_directory) + if not match_result: + raise RuntimeError("Unable to auto-determine the IPv4 address to use") + + return f"10.53.0.{match_result.group('index')}" + + def run(self) -> None: + """ + Start the server in an asynchronous coroutine. + """ + coroutine = self._run + try: + # Python >= 3.7 + asyncio.run(coroutine()) + except AttributeError: + # Python < 3.7 + loop = asyncio.get_event_loop() + loop.run_until_complete(coroutine()) + + async def _run(self) -> None: + self._setup_exception_handler() + self._setup_signals() + assert self._work_done + await self._listen_udp() + await self._listen_tcp() + self._write_pidfile() + await self._work_done + self._cleanup_pidfile() + + def _get_asyncio_loop(self) -> asyncio.AbstractEventLoop: + try: + # Python >= 3.7 + loop = asyncio.get_running_loop() + except AttributeError: + # Python < 3.7 + loop = asyncio.get_event_loop() + return loop + + def _setup_exception_handler(self) -> None: + loop = self._get_asyncio_loop() + self._work_done = loop.create_future() + loop.set_exception_handler(self._handle_exception) + + def _handle_exception( + self, _: asyncio.AbstractEventLoop, context: Dict[str, Any] + ) -> None: + assert self._work_done + exception = context.get("exception", RuntimeError(context["message"])) + self._work_done.set_exception(exception) + + def _setup_signals(self) -> None: + loop = self._get_asyncio_loop() + loop.add_signal_handler(signal.SIGINT, functools.partial(self._signal_done)) + loop.add_signal_handler(signal.SIGTERM, functools.partial(self._signal_done)) + + def _signal_done(self) -> None: + assert self._work_done + self._work_done.set_result(True) + + async def _listen_udp(self) -> None: + if not self._udp_handler: + return + loop = self._get_asyncio_loop() + for ip_address in self._ip_addresses: + await loop.create_datagram_endpoint( + lambda: _AsyncUdpHandler(cast(_UdpHandler, self._udp_handler)), + (ip_address, self._port), + ) + + async def _listen_tcp(self) -> None: + if not self._tcp_handler: + return + for ip_address in self._ip_addresses: + await asyncio.start_server( + self._tcp_handler, host=ip_address, port=self._port + ) + + def _write_pidfile(self) -> None: + if not self._pidfile: + return + logging.info("Writing PID to %s", self._pidfile) + with open(self._pidfile, "w", encoding="ascii") as pidfile: + print(f"{os.getpid()}", file=pidfile) + + def _cleanup_pidfile(self) -> None: + if not self._pidfile: + return + logging.info("Removing %s", self._pidfile) + os.unlink(self._pidfile) + + +class DnsProtocol(enum.Enum): + UDP = enum.auto() + TCP = enum.auto() + + +@dataclass(frozen=True) +class Peer: + """ + Pretty-printed connection endpoint. + """ + + host: str + port: int + + def __str__(self) -> str: + host = f"[{self.host}]" if ":" in self.host else self.host + return f"{host}:{self.port}" + + +@dataclass +class QueryContext: + """ + Context for the incoming query which may be used for preparing the response. + """ + + query: dns.message.Message + response: dns.message.Message + peer: Peer + protocol: DnsProtocol + zone: Optional[dns.zone.Zone] = None + soa: Optional[dns.rrset.RRset] = None + node: Optional[dns.node.Node] = None + answer: Optional[dns.rdataset.Rdataset] = None + + @property + def qname(self) -> dns.name.Name: + return self.query.question[0].name + + @property + def qclass(self) -> RdataClass: + return self.query.question[0].rdclass + + @property + def qtype(self) -> RdataType: + return self.query.question[0].rdtype + + +@dataclass +class ResponseAction(abc.ABC): + """ + Base class for actions that can be taken in response to a query. + """ + + @abc.abstractmethod + async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + """ + This method is expected to carry out arbitrary actions (e.g. wait for a + specific amount of time, modify the answer, etc.) and then return the + DNS response to send (a dns.message.Message, a raw bytes object, or + None, which prevents any response from being sent). + """ + raise NotImplementedError + + +@dataclass +class DnsResponseSend(ResponseAction): + """ + Action which yields a dns.message.Message response. + + The response may be sent with a delay if requested. + + Depending on the value of the `authoritative` property, this class may set + the AA bit in the response (True), clear it (False), or not touch it at all + (None). + """ + + response: dns.message.Message + authoritative: Optional[bool] = None + delay: float = 0.0 + + async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + """ + Yield a potentially delayed response that is a dns.message.Message. + """ + assert isinstance(self.response, dns.message.Message) + if self.authoritative is not None: + if self.authoritative: + self.response.flags |= dns.flags.AA + else: + self.response.flags &= ~dns.flags.AA + if self.delay > 0: + logging.info( + "Delaying response (ID=%d) by %d ms", + self.response.id, + self.delay * 1000, + ) + await asyncio.sleep(self.delay) + return self.response + + +@dataclass +class BytesResponseSend(ResponseAction): + """ + Action which yields a raw response that is a sequence of bytes. + + The response may be sent with a delay if requested. + """ + + response: bytes + delay: float = 0.0 + + async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + """ + Yield a potentially delayed response that is a sequence of bytes. + """ + assert isinstance(self.response, bytes) + if self.delay > 0: + logging.info("Delaying raw response by %d ms", self.delay * 1000) + await asyncio.sleep(self.delay) + return self.response + + +@dataclass +class ResponseDrop(ResponseAction): + """ + Action which does nothing - as if a packet was dropped. + """ + + async def perform(self) -> Optional[Union[dns.message.Message, bytes]]: + return None + + +class ResponseHandler(abc.ABC): + """ + Base class for generic response handlers. + + If a query passes the `match()` function logic, then it is handled by this + response handler and response(s) may be generated by the `get_responses()` + method. + """ + + # pylint: disable=unused-argument + def match(self, qctx: QueryContext) -> bool: + """ + Matching logic - the first handler whose `match()` method returns True + is used for handling the query. + + The default for each handler is to handle all queries. + """ + return True + + @abc.abstractmethod + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + """ + Custom handler which may produce response(s) to matching queries. + + The response prepared from zone data is passed to this method in + qctx.response. + """ + yield DnsResponseSend(qctx.response) + + def __str__(self) -> str: + return self.__class__.__name__ + + +class IgnoreAllQueries(ResponseHandler): + """ + Do not respond to any queries sent to the server. + """ + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + yield ResponseDrop() + + +class DomainHandler(ResponseHandler): + """ + Base class used for deriving custom domain handlers. + + The derived class must specify a list of `domains` that it wants to handle. + Queries for any of these domains (and their subdomains) will then be passed + to the `get_response()` method in the derived class. + """ + + @property + @abc.abstractmethod + def domains(self) -> List[str]: + """ + A list of domain names handled by this class. + """ + raise NotImplementedError + + def __init__(self) -> None: + self._domains: List[dns.name.Name] = [ + dns.name.from_text(d) for d in self.domains + ] + + def __str__(self) -> str: + return f"{self.__class__.__name__}(domains: {', '.join(self.domains)})" + + def match(self, qctx: QueryContext) -> bool: + """ + Handle queries whose QNAME matches any of the domains handled by this + class. + """ + for domain in self._domains: + if qctx.qname.is_subdomain(domain): + return True + return False + + +@dataclass +class _ZoneTreeNode: + """ + A node representing a zone with one origin. + """ + + zone: Optional[dns.zone.Zone] + children: List["_ZoneTreeNode"] = field(default_factory=list) + + +class _ZoneTree: + """ + Tree with independent zones. + + This zone tree is used as a backing structure for the DNS server. The + individual zones are independent to allow the (single) server to serve both + the parent zone and a child zone if needed. + """ + + def __init__(self) -> None: + self._root: _ZoneTreeNode = _ZoneTreeNode(None) + + def add(self, zone: dns.zone.Zone) -> None: + """ + Add a zone to the tree and rearrange sub-zones if necessary. + """ + assert zone.origin + best_match = self._find_best_match(zone.origin, self._root) + added_node = _ZoneTreeNode(zone) + self._move_children(best_match, added_node) + best_match.children.append(added_node) + + def _find_best_match( + self, name: dns.name.Name, start_node: _ZoneTreeNode + ) -> _ZoneTreeNode: + for child in start_node.children: + assert child.zone + assert child.zone.origin + if name.is_subdomain(child.zone.origin): + return self._find_best_match(name, child) + return start_node + + def _move_children(self, node_from: _ZoneTreeNode, node_to: _ZoneTreeNode) -> None: + assert node_to.zone + assert node_to.zone.origin + + children_to_move = [] + for child in node_from.children: + assert child.zone + assert child.zone.origin + if child.zone.origin.is_subdomain(node_to.zone.origin): + children_to_move.append(child) + + for child in children_to_move: + node_from.children.remove(child) + node_to.children.append(child) + + def find_best_zone(self, name: dns.name.Name) -> Optional[dns.zone.Zone]: + """ + Return the closest matching zone (if any) for the domain name. + """ + node = self._find_best_match(name, self._root) + return node.zone if node != self._root else None + + +class AsyncDnsServer(AsyncServer): + """ + DNS server which responds to queries based on zone data and/or custom + handlers. + + The server may use custom handlers which allow arbitrary query processing. + These don't need to be standards-compliant and can be used for testing all + sorts of scenarios, including delaying responses, synthesizing them based + on query contents etc. + + The server also loads any zone files (*.db) found in its directory and + serves them. Responses prepared using zone data can then be modified, + replaced, or suppressed by query handlers. Query handlers can also generate + response from scratch, without using zone data at all. + """ + + def __init__(self, load_zones: bool = True): + super().__init__(self._handle_udp, self._handle_tcp, "ans.pid") + + self._zone_tree: _ZoneTree = _ZoneTree() + self._response_handlers: List[ResponseHandler] = [] + + if load_zones: + self._load_zones() + + def install_response_handler( + self, handler: ResponseHandler, prepend: bool = False + ) -> None: + """ + Add a response handler that will be used to handle matching queries. + + Response handlers can modify, replace, or suppress the answers prepared + from zone file contents. + + The provided handler is installed at the end of the response handler + list unless `prepend` is set to True, in which case it is installed at + the beginning of the response handler list. + """ + logging.info("Installing response handler: %s", handler) + if prepend: + self._response_handlers.insert(0, handler) + else: + self._response_handlers.append(handler) + + def uninstall_response_handler(self, handler: ResponseHandler) -> None: + """ + Remove the specified handler from the list of response handlers. + """ + logging.info("Uninstalling response handler: %s", handler) + self._response_handlers.remove(handler) + + def _load_zones(self) -> None: + for entry in os.scandir(): + entry_path = pathlib.Path(entry.path) + if entry_path.suffix != ".db": + continue + origin = dns.name.from_text(entry_path.stem) + logging.info("Loading zone file %s", entry_path) + zone = dns.zone.from_file(entry.path, origin, relativize=False) + self._zone_tree.add(zone) + + async def _handle_udp( + self, wire: bytes, addr: Tuple[str, int], transport: asyncio.DatagramTransport + ) -> None: + logging.debug("Received UDP message: %s", wire.hex()) + peer = Peer(addr[0], addr[1]) + responses = self._handle_query(wire, peer, DnsProtocol.UDP) + async for response in responses: + transport.sendto(response, addr) + + async def _handle_tcp( + self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter + ) -> None: + peer_info = writer.get_extra_info("peername") + peer = Peer(peer_info[0], peer_info[1]) + logging.debug("Accepted TCP connection from %s", peer) + + while True: + try: + wire = await self._read_tcp_query(reader, peer) + if not wire: + break + await self._send_tcp_response(writer, peer, wire) + except ConnectionResetError: + logging.error("TCP connection from %s reset by peer", peer) + return + + logging.debug("Closing TCP connection from %s", peer) + writer.close() + try: + # Python >= 3.7 + await writer.wait_closed() + except AttributeError: + # Python < 3.7 + pass + + async def _read_tcp_query( + self, reader: asyncio.StreamReader, peer: Peer + ) -> Optional[bytes]: + wire_length = await self._read_tcp_query_wire_length(reader, peer) + if not wire_length: + return None + + return await self._read_tcp_query_wire(reader, peer, wire_length) + + async def _read_tcp_query_wire_length( + self, reader: asyncio.StreamReader, peer: Peer + ) -> Optional[int]: + logging.debug("Receiving TCP message length from %s...", peer) + + wire_length_bytes = await self._read_tcp_octets(reader, peer, 2) + if not wire_length_bytes: + return None + + (wire_length,) = struct.unpack("!H", wire_length_bytes) + + return wire_length + + async def _read_tcp_query_wire( + self, reader: asyncio.StreamReader, peer: Peer, wire_length: int + ) -> Optional[bytes]: + logging.debug("Receiving TCP message (%d octets) from %s...", wire_length, peer) + + wire = await self._read_tcp_octets(reader, peer, wire_length) + if not wire: + return None + + logging.debug("Received complete TCP message from %s: %s", peer, wire.hex()) + + return wire + + async def _read_tcp_octets( + self, reader: asyncio.StreamReader, peer: Peer, expected: int + ) -> Optional[bytes]: + buffer = b"" + + while len(buffer) < expected: + chunk = await reader.read(expected - len(buffer)) + if not chunk: + if buffer: + logging.debug( + "Received short TCP message (%d octets) from %s: %s", + len(buffer), + peer, + buffer.hex(), + ) + else: + logging.debug("Received disconnect from %s", peer) + return None + + logging.debug("Received %d TCP octets from %s", len(chunk), peer) + buffer += chunk + + return buffer + + async def _send_tcp_response( + self, writer: asyncio.StreamWriter, peer: Peer, wire: bytes + ) -> None: + responses = self._handle_query(wire, peer, DnsProtocol.TCP) + async for response in responses: + writer.write(response) + await writer.drain() + + def _log_query(self, qctx: QueryContext, peer: Peer, protocol: DnsProtocol) -> None: + logging.info( + "Received %s/%s/%s (ID=%d) query from %s (%s)", + qctx.qname.to_text(omit_final_dot=True), + dns.rdataclass.to_text(qctx.qclass), + dns.rdatatype.to_text(qctx.qtype), + qctx.query.id, + peer, + protocol.name, + ) + logging.debug( + "\n".join([f"[IN] {l}" for l in [""] + str(qctx.query).splitlines()]) + ) + + def _log_response( + self, + qctx: QueryContext, + response: Optional[Union[dns.message.Message, bytes]], + peer: Peer, + protocol: DnsProtocol, + ) -> None: + if not response: + logging.info( + "Not sending a response to query (ID=%d) from %s (%s)", + qctx.query.id, + peer, + protocol.name, + ) + return + + if isinstance(response, dns.message.Message): + try: + qname = response.question[0].name.to_text(omit_final_dot=True) + qclass = dns.rdataclass.to_text(response.question[0].rdclass) + qtype = dns.rdatatype.to_text(response.question[0].rdtype) + except IndexError: + qname = "" + qclass = "-" + qtype = "-" + + logging.info( + "Sending %s/%s/%s (ID=%d) response (%d/%d/%d/%d) to a query (ID=%d) from %s (%s)", + qname, + qclass, + qtype, + response.id, + len(response.question), + len(response.answer), + len(response.authority), + len(response.additional), + qctx.query.id, + peer, + protocol.name, + ) + logging.debug( + "\n".join([f"[OUT] {l}" for l in [""] + str(response).splitlines()]) + ) + return + + logging.info( + "Sending response (%d bytes) to a query (ID=%d) from %s (%s)", + len(response), + qctx.query.id, + peer, + protocol.name, + ) + logging.debug("[OUT] %s", response.hex()) + + async def _handle_query( + self, wire: bytes, peer: Peer, protocol: DnsProtocol + ) -> AsyncGenerator[bytes, None]: + """ + Yield wire data to send as a response over the established transport. + """ + try: + query = dns.message.from_wire(wire) + except dns.exception.DNSException as exc: + logging.error("Invalid query from %s (%s): %s", peer, wire.hex(), exc) + return + response_stub = dns.message.make_response(query) + qctx = QueryContext(query, response_stub, peer, protocol) + self._log_query(qctx, peer, protocol) + responses = self._prepare_responses(qctx) + async for response in responses: + self._log_response(qctx, response, peer, protocol) + if response: + if isinstance(response, dns.message.Message): + response = response.to_wire(max_size=65535) + if protocol == DnsProtocol.UDP: + yield response + else: + response_length = struct.pack("!H", len(response)) + yield response_length + response + + async def _prepare_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[Optional[Union[dns.message.Message, bytes]], None]: + """ + Yield response(s) either from response handlers or zone data. + """ + self._prepare_response_from_zone_data(qctx) + + response_handled = False + async for action in self._run_response_handlers(qctx): + yield await action.perform() + response_handled = True + + if not response_handled: + logging.debug("Responding based on zone data") + yield qctx.response + + def _prepare_response_from_zone_data(self, qctx: QueryContext) -> None: + """ + Prepare a response to the query based on the available zone data. + + The functionality is split across smaller functions that modify the + query context until a proper response is formed. + """ + if self._refused_response(qctx): + return + + if self._delegation_response(qctx): + return + + qctx.response.flags |= dns.flags.AA + + if self._ent_response(qctx): + return + + if self._nxdomain_response(qctx): + return + + if self._nodata_response(qctx): + return + + self._noerror_response(qctx) + + def _refused_response(self, qctx: QueryContext) -> bool: + qctx.zone = self._zone_tree.find_best_zone(qctx.qname) + if qctx.zone: + return False + + qctx.response.set_rcode(dns.rcode.REFUSED) + return True + + def _delegation_response(self, qctx: QueryContext) -> bool: + assert qctx.zone + + name = qctx.qname + delegation = None + + while name != qctx.zone.origin: + node = qctx.zone.get_node(name) + if node: + delegation = node.get_rdataset(qctx.qclass, dns.rdatatype.NS) + if delegation: + break + name = name.parent() + + if not delegation: + return False + + delegation_rrset = dns.rrset.RRset(name, qctx.qclass, dns.rdatatype.NS) + delegation_rrset.update(delegation) + + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.authority.append(delegation_rrset) + + self._delegation_response_additional(qctx) + + return True + + def _delegation_response_additional(self, qctx: QueryContext) -> None: + assert qctx.zone + assert qctx.response.authority[0] + + for nameserver in qctx.response.authority[0]: + if not nameserver.target.is_subdomain(qctx.response.authority[0].name): + continue + glue_a = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.A) + if glue_a: + qctx.response.additional.append(glue_a) + glue_aaaa = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.AAAA) + if glue_aaaa: + qctx.response.additional.append(glue_aaaa) + + def _ent_response(self, qctx: QueryContext) -> bool: + assert qctx.zone + assert qctx.zone.origin + + qctx.soa = qctx.zone.find_rrset(qctx.zone.origin, dns.rdatatype.SOA) + assert qctx.soa + + qctx.node = qctx.zone.get_node(qctx.qname) + if qctx.node or not any( + n for n in qctx.zone.nodes if n.is_subdomain(qctx.qname) + ): + return False + + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.authority.append(qctx.soa) + return True + + def _nxdomain_response(self, qctx: QueryContext) -> bool: + assert qctx.soa + + if qctx.node: + return False + + qctx.response.set_rcode(dns.rcode.NXDOMAIN) + qctx.response.authority.append(qctx.soa) + return True + + def _nodata_response(self, qctx: QueryContext) -> bool: + assert qctx.node + assert qctx.soa + + qctx.answer = qctx.node.get_rdataset(qctx.qclass, qctx.qtype) + if qctx.answer: + return False + + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.authority.append(qctx.soa) + return True + + def _noerror_response(self, qctx: QueryContext) -> None: + assert qctx.answer + + answer_rrset = dns.rrset.RRset(qctx.qname, qctx.qclass, qctx.qtype) + answer_rrset.update(qctx.answer) + + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.answer.append(answer_rrset) + + async def _run_response_handlers( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + """ + Yield response(s) to the query from a matching query handler. + """ + for handler in self._response_handlers: + if handler.match(qctx): + logging.debug("Matched response handler: %s", handler) + async for response in handler.get_responses(qctx): + yield response + return + + +class ControllableAsyncDnsServer(AsyncDnsServer): + """ + An AsyncDnsServer whose behavior can be dynamically changed by sending TXT + queries to a "magic" domain. + """ + + _CONTROL_DOMAIN = "_control." + + def __init__(self, commands: List[Type["ControlCommand"]]): + super().__init__() + self._control_domain = dns.name.from_text(self._CONTROL_DOMAIN) + self._commands: Dict[dns.name.Name, "ControlCommand"] = {} + for command_class in commands: + command = command_class() + command_subdomain = dns.name.Name([command.control_subdomain]) + control_subdomain = command_subdomain.concatenate(self._control_domain) + try: + existing_command = self._commands[control_subdomain] + except KeyError: + self._commands[control_subdomain] = command + else: + raise RuntimeError( + f"{control_subdomain} already handled by {existing_command}" + ) + + async def _prepare_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[Optional[Union[dns.message.Message, bytes]], None]: + """ + Detect and handle control queries, falling back to normal processing + for non-control queries. + """ + control_response = self._handle_control_command(qctx) + if control_response: + yield await DnsResponseSend(response=control_response).perform() + return + + async for response in super()._prepare_responses(qctx): + yield response + + def _handle_control_command( + self, qctx: QueryContext + ) -> Optional[dns.message.Message]: + """ + Detect and handle control queries. + + A control query must be of type TXT; if it is not, a FORMERR response + is sent back. + + The list of commands that the server should respond to is passed to its + constructor. If the server is unable to handle the control query using + any of the enabled commands, an NXDOMAIN response is sent. + + Otherwise, the relevant command's handler is expected to provide the + response via qctx.response and/or return a string that is converted to + a TXT RRset inserted into the ANSWER section of the response to the + control query. The RCODE for a command-provided response defaults to + NOERROR, but can be overridden by the command's handler. + """ + if not qctx.qname.is_subdomain(self._control_domain): + return None + + if qctx.qtype != dns.rdatatype.TXT: + logging.error("Non-TXT control query %s from %s", qctx.qname, qctx.peer) + qctx.response.set_rcode(dns.rcode.FORMERR) + return qctx.response + + control_subdomain = dns.name.Name(qctx.qname.labels[-3:]) + try: + command = self._commands[control_subdomain] + except KeyError: + logging.error("Unhandled control query %s from %s", qctx.qname, qctx.peer) + qctx.response.set_rcode(dns.rcode.NXDOMAIN) + return qctx.response + + logging.info("Received control query %s from %s", qctx.qname, qctx.peer) + logging.debug("Handling control query %s using %s", qctx.qname, command) + qctx.response.set_rcode(dns.rcode.NOERROR) + qctx.response.flags |= dns.flags.AA + + command_qname = qctx.qname.relativize(control_subdomain) + try: + command_args = [l.decode("ascii") for l in command_qname.labels] + except UnicodeDecodeError: + logging.error("Non-ASCII control query %s from %s", qctx.qname, qctx.peer) + qctx.response.set_rcode(dns.rcode.FORMERR) + return qctx.response + + command_response = command.handle(command_args, self, qctx) + if command_response: + command_response_rrset = dns.rrset.from_text( + qctx.qname, 0, qctx.qclass, dns.rdatatype.TXT, f'"{command_response}"' + ) + qctx.response.answer.append(command_response_rrset) + + return qctx.response + + +class ControlCommand(abc.ABC): + """ + Base class for control commands. + + The derived class must define the control query subdomain that it handles + and the callback that handles the control queries. + """ + + @property + @abc.abstractmethod + def control_subdomain(self) -> str: + """ + The subdomain of the control domain handled by this command. Needs to + be defined as a string by the derived class. + """ + raise NotImplementedError + + @abc.abstractmethod + def handle( + self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> Optional[str]: + """ + This method is expected to carry out arbitrary actions in response to a + control query. Note that it is invoked synchronously (it is not a + coroutine). + + `args` is a list of arguments for the command extracted from the + control query's QNAME; these arguments (and therefore the QNAME as + well) must only contain ASCII characters. For example, if a command's + subdomain is `my-command`, control query `foo.bar.my-command._control.` + causes `args` to be set to `["foo", "bar"]` while control query + `my-command._control.` causes `args` to be set to `[]`. + + `server` is the server instance that received the control query. This + method can change the server's behavior by altering its response + handler list using the appropriate methods. + + `qctx` is the query context for the control query. By operating on + qctx.response, this method can prepare the DNS response sent to + the client in response to the control query. Alternatively (or in + addition to the above), it can also return a string; if it does, the + returned string is converted to a TXT RRset that is inserted into the + ANSWER section of the response to the control query. + """ + raise NotImplementedError + + def __str__(self) -> str: + return self.__class__.__name__ + + +class ToggleResponsesCommand(ControlCommand): + """ + Disable/enable sending responses from the server. + """ + + control_subdomain = "send-responses" + + def __init__(self) -> None: + self._current_handler: Optional[IgnoreAllQueries] = None + + def handle( + self, args: List[str], server: ControllableAsyncDnsServer, qctx: QueryContext + ) -> Optional[str]: + if len(args) != 1: + logging.error("Invalid %s query %s", self, qctx.qname) + qctx.response.set_rcode(dns.rcode.SERVFAIL) + return "invalid query; use exactly one of 'enable' or 'disable' in QNAME" + + mode = args[0] + + if mode == "disable": + if self._current_handler: + return "sending responses already disabled" + self._current_handler = IgnoreAllQueries() + server.install_response_handler(self._current_handler, prepend=True) + return "sending responses disabled" + + if mode == "enable": + if not self._current_handler: + return "sending responses already enabled" + server.uninstall_response_handler(self._current_handler) + self._current_handler = None + return "sending responses enabled" + + logging.error("Unrecognized response sending mode '%s'", mode) + qctx.response.set_rcode(dns.rcode.SERVFAIL) + return f"unrecognized response sending mode '{mode}'" diff --git a/bin/tests/system/isctest/check.py b/bin/tests/system/isctest/check.py new file mode 100644 index 0000000..b35dfe8 --- /dev/null +++ b/bin/tests/system/isctest/check.py @@ -0,0 +1,152 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import difflib +import shutil +from typing import Optional + +import dns.rcode +import dns.message +import dns.zone + +import isctest.log +from isctest.compat import dns_rcode + + +def rcode(message: dns.message.Message, expected_rcode) -> None: + assert message.rcode() == expected_rcode, str(message) + + +def noerror(message: dns.message.Message) -> None: + rcode(message, dns_rcode.NOERROR) + + +def notimp(message: dns.message.Message) -> None: + rcode(message, dns_rcode.NOTIMP) + + +def refused(message: dns.message.Message) -> None: + rcode(message, dns_rcode.REFUSED) + + +def servfail(message: dns.message.Message) -> None: + rcode(message, dns_rcode.SERVFAIL) + + +def rrsets_equal( + first_rrset: dns.rrset.RRset, + second_rrset: dns.rrset.RRset, + compare_ttl: Optional[bool] = False, +) -> None: + """Compare two RRset (optionally including TTL)""" + + def compare_rrs(rr1, rrset): + rr2 = next((other_rr for other_rr in rrset if rr1 == other_rr), None) + assert rr2 is not None, f"No corresponding RR found for: {rr1}" + if compare_ttl: + assert rr1.ttl == rr2.ttl + + isctest.log.debug( + "%s() first RRset:\n%s", + rrsets_equal.__name__, + "\n".join([str(rr) for rr in first_rrset]), + ) + isctest.log.debug( + "%s() second RRset:\n%s", + rrsets_equal.__name__, + "\n".join([str(rr) for rr in second_rrset]), + ) + for rr in first_rrset: + compare_rrs(rr, second_rrset) + for rr in second_rrset: + compare_rrs(rr, first_rrset) + + +def zones_equal( + first_zone: dns.zone.Zone, + second_zone: dns.zone.Zone, + compare_ttl: Optional[bool] = False, +) -> None: + """Compare two zones (optionally including TTL)""" + + isctest.log.debug( + "%s() first zone:\n%s", + zones_equal.__name__, + first_zone.to_text(relativize=False), + ) + isctest.log.debug( + "%s() second zone:\n%s", + zones_equal.__name__, + second_zone.to_text(relativize=False), + ) + assert first_zone == second_zone + if compare_ttl: + for name, node in first_zone.nodes.items(): + for rdataset in node: + found_rdataset = second_zone.find_rdataset( + name=name, rdtype=rdataset.rdtype + ) + assert found_rdataset + assert found_rdataset.ttl == rdataset.ttl + + +def is_executable(cmd: str, errmsg: str) -> None: + executable = shutil.which(cmd) + assert executable is not None, errmsg + + +def named_alive(named_proc, resolver_ip): + assert named_proc.poll() is None, "named isn't running" + msg = dns.message.make_query("version.bind", "TXT", "CH") + isctest.query.tcp(msg, resolver_ip, expected_rcode=dns_rcode.NOERROR) + + +def notauth(message: dns.message.Message) -> None: + rcode(message, dns.rcode.NOTAUTH) + + +def nxdomain(message: dns.message.Message) -> None: + rcode(message, dns.rcode.NXDOMAIN) + + +def single_question(message: dns.message.Message) -> None: + assert len(message.question) == 1, str(message) + + +def empty_answer(message: dns.message.Message) -> None: + assert not message.answer, str(message) + + +def is_response_to(response: dns.message.Message, query: dns.message.Message) -> None: + single_question(response) + single_question(query) + assert query.is_response(response), str(response) + + +def file_contents_equal(file1, file2): + def normalize_line(line): + # remove trailing&leading whitespace and replace multiple whitespaces + return " ".join(line.split()) + + def read_lines(file_path): + with open(file_path, "r", encoding="utf-8") as file: + return [normalize_line(line) for line in file.readlines()] + + lines1 = read_lines(file1) + lines2 = read_lines(file2) + + differ = difflib.Differ() + diff = differ.compare(lines1, lines2) + + for line in diff: + assert not line.startswith("+ ") and not line.startswith( + "- " + ), f'file contents of "{file1}" and "{file2}" differ' diff --git a/bin/tests/system/isctest/compat.py b/bin/tests/system/isctest/compat.py new file mode 100644 index 0000000..5580f1f --- /dev/null +++ b/bin/tests/system/isctest/compat.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from typing import Any + +import dns.rcode + +# compatiblity with dnspython<2.0.0 +try: + # In dnspython>=2.0.0, dns.rcode.Rcode class is available + # pylint: disable=invalid-name + dns_rcode = dns.rcode.Rcode # type: Any +except AttributeError: + # In dnspython<2.0.0, selected rcodes are available as integers directly + # from dns.rcode + dns_rcode = dns.rcode diff --git a/bin/tests/system/isctest/hypothesis/__init__.py b/bin/tests/system/isctest/hypothesis/__init__.py new file mode 100644 index 0000000..3ae0dee --- /dev/null +++ b/bin/tests/system/isctest/hypothesis/__init__.py @@ -0,0 +1,18 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +try: + import hypothesis as _ +except ImportError: + pass +else: + from . import settings + from . import strategies diff --git a/bin/tests/system/isctest/hypothesis/settings.py b/bin/tests/system/isctest/hypothesis/settings.py new file mode 100644 index 0000000..5eae010 --- /dev/null +++ b/bin/tests/system/isctest/hypothesis/settings.py @@ -0,0 +1,18 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +from hypothesis import settings + +# Timing of hypothesis tests is flaky in the CI, so we disable deadlines. +settings.register_profile("ci", deadline=None) +settings.load_profile(os.getenv("HYPOTHESIS_PROFILE", "default")) diff --git a/bin/tests/system/isctest/hypothesis/strategies.py b/bin/tests/system/isctest/hypothesis/strategies.py new file mode 100644 index 0000000..d26a90b --- /dev/null +++ b/bin/tests/system/isctest/hypothesis/strategies.py @@ -0,0 +1,170 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from typing import List +from warnings import warn + +from hypothesis.strategies import ( + binary, + builds, + composite, + integers, + just, + nothing, + permutations, +) + +import dns.name +import dns.message +import dns.rdataclass +import dns.rdatatype + +import isctest.name + + +@composite +def dns_names( + draw, + *, + prefix: dns.name.Name = dns.name.empty, + suffix: dns.name.Name = dns.name.root, + min_labels: int = 1, + max_labels: int = 128, +) -> dns.name.Name: + """ + This is a hypothesis strategy to be used for generating DNS names with given `prefix`, `suffix` + and with total number of labels specified by `min_labels` and `max labels`. + + For example, calling + ``` + dns_names( + prefix=dns.name.from_text("test"), + suffix=dns.name.from_text("isc.org"), + max_labels=6 + ).example() + ``` + will result in names like `test.abc.isc.org.` or `test.abc.def.isc.org`. + + There is no attempt to make the distribution of the generated names uniform in any way. + The strategy however minimizes towards shorter names with shorter labels. + + It can be used with to build compound strategies, like this one which generates random DNS queries. + + ``` + dns_queries = builds( + dns.message.make_query, + qname=dns_names(), + rdtype=dns_rdatatypes, + rdclass=dns_rdataclasses, + ) + ``` + """ + + prefix = prefix.relativize(dns.name.root) + suffix = suffix.derelativize(dns.name.root) + + try: + outer_name = prefix + suffix + remaining_bytes = 255 - isctest.name.len_wire_uncompressed(outer_name) + assert remaining_bytes >= 0 + except dns.name.NameTooLong: + warn( + "Maximal length name of name execeeded by prefix and suffix. Strategy won't generate any names.", + RuntimeWarning, + ) + return draw(nothing()) + + minimum_number_of_labels_to_generate = max(0, min_labels - len(outer_name.labels)) + maximum_number_of_labels_to_generate = max_labels - len(outer_name.labels) + if maximum_number_of_labels_to_generate < 0: + warn( + "Maximal number of labels execeeded by prefix and suffix. Strategy won't generate any names.", + RuntimeWarning, + ) + return draw(nothing()) + + maximum_number_of_labels_to_generate = min( + maximum_number_of_labels_to_generate, remaining_bytes // 2 + ) + if maximum_number_of_labels_to_generate < minimum_number_of_labels_to_generate: + warn( + f"Minimal number set to {minimum_number_of_labels_to_generate}, but in {remaining_bytes} bytes there is only space for maximum of {maximum_number_of_labels_to_generate} labels.", + RuntimeWarning, + ) + return draw(nothing()) + + if remaining_bytes == 0 or maximum_number_of_labels_to_generate == 0: + warn( + f"Strategy will return only one name ({outer_name}) as it exactly matches byte or label length limit.", + RuntimeWarning, + ) + return draw(just(outer_name)) + + chosen_number_of_labels_to_generate = draw( + integers( + minimum_number_of_labels_to_generate, maximum_number_of_labels_to_generate + ) + ) + chosen_number_of_bytes_to_partion = draw( + integers(2 * chosen_number_of_labels_to_generate, remaining_bytes) + ) + chosen_lengths_of_labels = draw( + _partition_bytes_to_labels( + chosen_number_of_bytes_to_partion, chosen_number_of_labels_to_generate + ) + ) + generated_labels = tuple( + draw(binary(min_size=l - 1, max_size=l - 1)) for l in chosen_lengths_of_labels + ) + + return dns.name.Name(prefix.labels + generated_labels + suffix.labels) + + +RDATACLASS_MAX = RDATATYPE_MAX = 65535 +try: + dns_rdataclasses = builds(dns.rdataclass.RdataClass, integers(0, RDATACLASS_MAX)) + dns_rdatatypes = builds(dns.rdatatype.RdataType, integers(0, RDATATYPE_MAX)) +except AttributeError: + # In old dnspython versions, RDataTypes and RDataClasses are int and not enums. + dns_rdataclasses = integers(0, RDATACLASS_MAX) # type: ignore + dns_rdatatypes = integers(0, RDATATYPE_MAX) # type: ignore +dns_rdataclasses_without_meta = dns_rdataclasses.filter(dns.rdataclass.is_metaclass) + +# NOTE: This should really be `dns_rdatatypes_without_meta = dns_rdatatypes_without_meta.filter(dns.rdatatype.is_metatype()`, +# but hypothesis then complains about the filter being too strict, so it is done in a “constructive” way. +dns_rdatatypes_without_meta = integers(0, dns.rdatatype.OPT - 1) | integers(dns.rdatatype.OPT + 1, 127) | integers(256, RDATATYPE_MAX) # type: ignore + + +@composite +def _partition_bytes_to_labels( + draw, remaining_bytes: int, number_of_labels: int +) -> List[int]: + two_bytes_reserved_for_label = 2 + + # Reserve two bytes for each label + partition = [two_bytes_reserved_for_label] * number_of_labels + remaining_bytes -= two_bytes_reserved_for_label * number_of_labels + + assert remaining_bytes >= 0 + + # Add a random number between 0 and the remainder to each partition + for i in range(number_of_labels): + added = draw( + integers(0, min(remaining_bytes, 64 - two_bytes_reserved_for_label)) + ) + partition[i] += added + remaining_bytes -= added + + # NOTE: Some of the remaining bytes will usually not be assigned to any label, but we don't care. + + return draw(permutations(partition)) diff --git a/bin/tests/system/isctest/instance.py b/bin/tests/system/isctest/instance.py new file mode 100644 index 0000000..5725b3e --- /dev/null +++ b/bin/tests/system/isctest/instance.py @@ -0,0 +1,214 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from typing import List, NamedTuple, Optional + +import logging +import os +from pathlib import Path +import re + +from .rndc import RNDCBinaryExecutor, RNDCException, RNDCExecutor +from .run import perl +from .log import info, LogFile, WatchLogFromStart, WatchLogFromHere + + +class NamedPorts(NamedTuple): + dns: int = 53 + rndc: int = 953 + + @staticmethod + def from_env(): + return NamedPorts( + dns=int(os.environ["PORT"]), + rndc=int(os.environ["CONTROLPORT"]), + ) + + +class NamedInstance: + """ + A class representing a `named` instance used in a system test. + + This class is expected to be instantiated as part of the `servers` fixture: + + ```python + def test_foo(servers): + servers["ns1"].rndc("status") + ``` + """ + + def __init__( + self, + identifier: str, + num: Optional[int] = None, + ports: Optional[NamedPorts] = None, + rndc_logger: Optional[logging.Logger] = None, + rndc_executor: Optional[RNDCExecutor] = None, + ) -> None: + """ + `identifier` is the name of the instance's directory + + `num` is optional if the identifier is in a form of `ns`, in which + case `` is assumed to be numeric identifier; otherwise it must be + provided to assign a numeric identification to the server + + `ports` is the `NamedPorts` instance listing the UDP/TCP ports on which + this `named` instance is listening for various types of traffic (both + DNS traffic and RNDC commands). Defaults to ports set by the test + framework. + + `rndc_logger` is the `logging.Logger` to use for logging RNDC + commands sent to this `named` instance. + + `rndc_executor` is an object implementing the `RNDCExecutor` interface + that is used for executing RNDC commands on this `named` instance. + """ + self.directory = Path(identifier).absolute() + if not self.directory.is_dir(): + raise ValueError(f"{self.directory} isn't a directory") + self.system_test_name = self.directory.parent.name + + self.identifier = identifier + self.num = self._identifier_to_num(identifier, num) + if ports is None: + ports = NamedPorts.from_env() + self.ports = ports + self.log = LogFile(os.path.join(identifier, "named.run")) + self._rndc_executor = rndc_executor or RNDCBinaryExecutor() + self._rndc_logger = rndc_logger + + @property + def ip(self) -> str: + """IPv4 address of the instance.""" + return f"10.53.0.{self.num}" + + @staticmethod + def _identifier_to_num(identifier: str, num: Optional[int] = None) -> int: + regex_match = re.match(r"^ns(?P[0-9]{1,2})$", identifier) + if not regex_match: + if num is None: + raise ValueError(f'Can\'t parse numeric identifier from "{identifier}"') + return num + parsed_num = int(regex_match.group("index")) + assert num is None or num == parsed_num, "mismatched num and identifier" + return parsed_num + + def rndc(self, command: str, ignore_errors: bool = False, log: bool = True) -> str: + """ + Send `command` to this named instance using RNDC. Return the server's + response. + + If the RNDC command fails, an `RNDCException` is raised unless + `ignore_errors` is set to `True`. + + The RNDC command will be logged to `rndc.log` (along with the server's + response) unless `log` is set to `False`. + + >>> # Instances of the `NamedInstance` class are expected to be passed + >>> # to pytest tests as fixtures; here, some instances are created + >>> # directly (with a fake RNDC executor) so that doctest can work. + >>> import unittest.mock + >>> mock_rndc_executor = unittest.mock.Mock() + >>> ns1 = NamedInstance("ns1", rndc_executor=mock_rndc_executor) + >>> ns2 = NamedInstance("ns2", rndc_executor=mock_rndc_executor) + >>> ns3 = NamedInstance("ns3", rndc_executor=mock_rndc_executor) + >>> ns4 = NamedInstance("ns4", rndc_executor=mock_rndc_executor) + + >>> # Send the "status" command to ns1. An `RNDCException` will be + >>> # raised if the RNDC command fails. This command will be logged. + >>> response = ns1.rndc("status") + + >>> # Send the "thaw foo" command to ns2. No exception will be raised + >>> # in case the RNDC command fails. This command will be logged + >>> # (even if it fails). + >>> response = ns2.rndc("thaw foo", ignore_errors=True) + + >>> # Send the "stop" command to ns3. An `RNDCException` will be + >>> # raised if the RNDC command fails, but this command will not be + >>> # logged (the server's response will still be returned to the + >>> # caller, though). + >>> response = ns3.rndc("stop", log=False) + + >>> # Send the "halt" command to ns4 in "fire & forget mode": no + >>> # exceptions will be raised and no logging will take place (the + >>> # server's response will still be returned to the caller, though). + >>> response = ns4.rndc("stop", ignore_errors=True, log=False) + """ + try: + response = self._rndc_executor.call(self.ip, self.ports.rndc, command) + if log: + self._rndc_log(command, response) + except RNDCException as exc: + response = str(exc) + if log: + self._rndc_log(command, response) + if not ignore_errors: + raise + + return response + + def watch_log_from_start(self) -> WatchLogFromStart: + """ + Return an instance of the `WatchLogFromStart` context manager for this + `named` instance's log file. + """ + return WatchLogFromStart(self.log.path) + + def watch_log_from_here(self) -> WatchLogFromHere: + """ + Return an instance of the `WatchLogFromHere` context manager for this + `named` instance's log file. + """ + return WatchLogFromHere(self.log.path) + + def reconfigure(self) -> None: + """ + Reconfigure this named `instance` and wait until reconfiguration is + finished. Raise an `RNDCException` if reconfiguration fails. + """ + with self.watch_log_from_here() as watcher: + self.rndc("reconfig") + watcher.wait_for_line("any newly configured zones are now loaded") + + def _rndc_log(self, command: str, response: str) -> None: + """ + Log an `rndc` invocation (and its output) to the `rndc.log` file in the + current working directory. + """ + fmt = '%(ip)s: "%(command)s"\n%(separator)s\n%(response)s%(separator)s' + args = { + "ip": self.ip, + "command": command, + "separator": "-" * 80, + "response": response, + } + if self._rndc_logger is None: + info(fmt, args) + else: + self._rndc_logger.info(fmt, args) + + def stop(self, args: Optional[List[str]] = None) -> None: + """Stop the instance.""" + args = args or [] + perl( + f"{os.environ['srcdir']}/stop.pl", + [self.system_test_name, self.identifier] + args, + ) + + def start(self, args: Optional[List[str]] = None) -> None: + """Start the instance.""" + args = args or [] + perl( + f"{os.environ['srcdir']}/start.pl", + [self.system_test_name, self.identifier] + args, + ) diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py new file mode 100644 index 0000000..51bf22f --- /dev/null +++ b/bin/tests/system/isctest/kasp.py @@ -0,0 +1,1358 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from functools import total_ordering +import glob +import os +from pathlib import Path +import re +import subprocess +import time +from typing import Dict, List, Optional, Tuple, Union + +from datetime import datetime, timedelta, timezone + +import dns +import dns.tsig +import isctest.log +import isctest.query +import isctest.util + +DEFAULT_TTL = 300 + +NEXT_KEY_EVENT_THRESHOLD = 100 + + +def _query(server, qname, qtype, tsig=None): + query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) + + if tsig is not None: + tsigkey = tsig.split(":") + keyring = dns.tsig.Key(tsigkey[1], tsigkey[2], tsigkey[0]) + query.use_tsig(keyring) + + try: + response = isctest.query.tcp(query, server.ip, server.ports.dns, timeout=3) + except dns.exception.Timeout: + isctest.log.debug(f"query timeout for query {qname} {qtype} to {server.ip}") + return None + + return response + + +@total_ordering +class KeyTimingMetadata: + """ + Represent a single timing information for a key. + + These objects can be easily compared, support addition and subtraction of + timedelta objects or integers(value in seconds). A lack of timing metadata + in the key (value 0) should be represented with None rather than an + instance of this object. + """ + + FORMAT = "%Y%m%d%H%M%S" + + def __init__(self, timestamp: str): + if int(timestamp) <= 0: + raise ValueError(f'invalid timing metadata value: "{timestamp}"') + self.value = datetime.strptime(timestamp, self.FORMAT).replace( + tzinfo=timezone.utc + ) + + def __repr__(self): + return self.value.strftime(self.FORMAT) + + def __str__(self) -> str: + return self.value.strftime(self.FORMAT) + + def __add__(self, other: Union[timedelta, int]): + if isinstance(other, int): + other = timedelta(seconds=other) + result = KeyTimingMetadata.__new__(KeyTimingMetadata) + result.value = self.value + other + return result + + def __sub__(self, other: Union[timedelta, int]): + if isinstance(other, int): + other = timedelta(seconds=other) + result = KeyTimingMetadata.__new__(KeyTimingMetadata) + result.value = self.value - other + return result + + def __iadd__(self, other: Union[timedelta, int]): + if isinstance(other, int): + other = timedelta(seconds=other) + self.value += other + + def __isub__(self, other: Union[timedelta, int]): + if isinstance(other, int): + other = timedelta(seconds=other) + self.value -= other + + def __lt__(self, other: "KeyTimingMetadata"): + return self.value < other.value + + def __eq__(self, other: object): + return isinstance(other, KeyTimingMetadata) and self.value == other.value + + @staticmethod + def now() -> "KeyTimingMetadata": + result = KeyTimingMetadata.__new__(KeyTimingMetadata) + result.value = datetime.now(timezone.utc) + return result + + +class KeyProperties: + """ + Represent the (expected) properties a key should have. + """ + + def __init__( + self, + name: str, + properties: dict, + metadata: dict, + timing: Dict[str, KeyTimingMetadata], + ): + self.name = name + self.key = None + self.properties = properties + self.metadata = metadata + self.timing = timing + + def __repr__(self): + return self.name + + def __str__(self) -> str: + return self.name + + @staticmethod + def default(with_state=True) -> "KeyProperties": + properties = { + "expect": True, + "private": True, + "legacy": False, + "role": "csk", + "role_full": "key-signing", + "dnskey_ttl": 3600, + "flags": 257, + } + metadata = { + "Algorithm": isctest.vars.algorithms.ECDSAP256SHA256.number, + "Length": 256, + "Lifetime": 0, + "KSK": "yes", + "ZSK": "yes", + } + timing: Dict[str, KeyTimingMetadata] = {} + + result = KeyProperties( + name="DEFAULT", properties=properties, metadata=metadata, timing=timing + ) + result.name = "DEFAULT" + result.key = None + if with_state: + result.metadata["GoalState"] = "omnipresent" + result.metadata["DNSKEYState"] = "rumoured" + result.metadata["KRRSIGState"] = "rumoured" + result.metadata["ZRRSIGState"] = "rumoured" + result.metadata["DSState"] = "hidden" + + return result + + def Ipub(self, config): + ipub = timedelta(0) + + if self.key.get_metadata("Predecessor", must_exist=False) != "undefined": + # Ipub = Dprp + TTLkey + ipub = ( + config["dnskey-ttl"] + + config["zone-propagation-delay"] + + config["publish-safety"] + ) + + self.timing["Active"] = self.timing["Published"] + ipub + + def IpubC(self, config): + if not self.key.is_ksk(): + return + + ttl1 = config["dnskey-ttl"] + config["publish-safety"] + ttl2 = timedelta(0) + + if self.key.get_metadata("Predecessor", must_exist=False) == "undefined": + # If this is the first key, we also need to wait until the zone + # signatures are omnipresent. Use max-zone-ttl instead of + # dnskey-ttl, and no publish-safety (because we are looking at + # signatures here, not the public key). + ttl2 = config["max-zone-ttl"] + + # IpubC = DprpC + TTLkey + ipubc = config["zone-propagation-delay"] + max(ttl1, ttl2) + + self.timing["PublishCDS"] = self.timing["Published"] + ipubc + + if self.metadata["Lifetime"] != 0: + self.timing["DeleteCDS"] = ( + self.timing["PublishCDS"] + self.metadata["Lifetime"] + ) + + def Iret(self, config): + if self.metadata["Lifetime"] == 0: + return + + sign_delay = config["signatures-validity"] - config["signatures-refresh"] + safety_interval = config["retire-safety"] + + iretKSK = timedelta(0) + iretZSK = timedelta(0) + if self.key.is_ksk(): + # Iret = DprpP + TTLds + iretKSK = ( + config["parent-propagation-delay"] + config["ds-ttl"] + safety_interval + ) + if self.key.is_zsk(): + # Iret = Dsgn + Dprp + TTLsig + iretZSK = ( + sign_delay + + config["zone-propagation-delay"] + + config["max-zone-ttl"] + + safety_interval + ) + + self.timing["Removed"] = self.timing["Retired"] + max(iretKSK, iretZSK) + + def set_expected_keytimes(self, config, offset=None, pregenerated=False): + if self.key is None: + raise ValueError("KeyProperties must be attached to a Key") + + if self.properties["legacy"]: + return + + if offset is None: + offset = self.properties["offset"] + + self.timing["Generated"] = self.key.get_timing("Created") + + self.timing["Published"] = self.timing["Generated"] + if pregenerated: + self.timing["Published"] = self.key.get_timing("Publish") + self.timing["Published"] = self.timing["Published"] + offset + self.Ipub(config) + + # Set Retired timing metadata if key has lifetime. + if self.metadata["Lifetime"] != 0: + self.timing["Retired"] = self.timing["Active"] + self.metadata["Lifetime"] + + self.IpubC(config) + self.Iret(config) + + # Key state change times must exist, but since we cannot reliably tell + # when named made the actual state change, we don't care what the + # value is. Set it to None will verify that the metadata exists, but + # without actual checking the value. + self.timing["DNSKEYChange"] = None + + if self.key.is_ksk(): + self.timing["DSChange"] = None + self.timing["KRRSIGChange"] = None + + if self.key.is_zsk(): + self.timing["ZRRSIGChange"] = None + + +@total_ordering +class Key: + """ + Represent a key from a keyfile. + + This object keeps track of its origin (keydir + name), can be used to + retrieve metadata from the underlying files and supports convenience + operations for KASP tests. + """ + + def __init__(self, name: str, keydir: Optional[Union[str, Path]] = None): + self.name = name + if keydir is None: + self.keydir = Path() + else: + self.keydir = Path(keydir) + self.path = str(self.keydir / name) + self.privatefile = f"{self.path}.private" + self.keyfile = f"{self.path}.key" + self.statefile = f"{self.path}.state" + self.tag = int(self.name[-5:]) + + def get_timing( + self, metadata: str, must_exist: bool = True + ) -> Optional[KeyTimingMetadata]: + regex = rf";\s+{metadata}:\s+(\d+).*" + with open(self.keyfile, "r", encoding="utf-8") as file: + for line in file: + match = re.match(regex, line) + if match is not None: + try: + return KeyTimingMetadata(match.group(1)) + except ValueError: + break + if must_exist: + raise ValueError( + f'timing metadata "{metadata}" for key "{self.name}" invalid' + ) + return None + + def get_metadata( + self, metadata: str, file=None, comment=False, must_exist=True + ) -> str: + if file is None: + file = self.statefile + value = "undefined" + regex = rf"{metadata}:\s+(\S+).*" + if comment: + # The expected metadata is prefixed with a ';'. + regex = rf";\s+{metadata}:\s+(\S+).*" + with open(file, "r", encoding="utf-8") as fp: + for line in fp: + match = re.match(regex, line) + if match is not None: + value = match.group(1) + break + if must_exist and value == "undefined": + raise ValueError( + f'metadata "{metadata}" for key "{self.name}" in file "{file}" undefined' + ) + return value + + def get_signing_state( + self, offline_ksk=False, zsk_missing=False + ) -> Tuple[bool, bool]: + """ + This returns the signing state derived from the key states, KRRSIGState + and ZRRSIGState. + + If 'offline_ksk' is set to True, we determine the signing state from + the timing metadata. If 'zsigning' is True, ensure the current time is + between the Active and Retired timing metadata. + + If 'zsk_missing' is set to True, it means the ZSK private key file is + missing, and the KSK should take over signing the RRset, and the + expected zone signing state (zsigning) is reversed. + """ + # Fetch key timing metadata. + now = KeyTimingMetadata.now() + activate = self.get_timing("Activate") + assert activate is not None # to silence mypy - its implied by line above + inactive = self.get_timing("Inactive", must_exist=False) + + active = now >= activate + retired = inactive is not None and inactive <= now + signing = active and not retired + + # Fetch key state metadata. + krrsigstate = self.get_metadata("KRRSIGState", must_exist=False) + ksigning = krrsigstate in ["rumoured", "omnipresent"] + zrrsigstate = self.get_metadata("ZRRSIGState", must_exist=False) + zsigning = zrrsigstate in ["rumoured", "omnipresent"] + + if ksigning: + assert self.is_ksk() + if zsigning: + assert self.is_zsk() + + # If the ZSK private key file is missing, revers the zone signing state. + if zsk_missing: + zsigning = not zsigning + + # If testing offline KSK, retrieve the signing state from the key timing + # metadata. + if offline_ksk and signing and self.is_zsk(): + assert zsigning + if offline_ksk and signing and self.is_ksk(): + ksigning = signing + + return ksigning, zsigning + + def ttl(self) -> int: + with open(self.keyfile, "r", encoding="utf-8") as file: + for line in file: + if line.startswith(";"): + continue + return int(line.split()[1]) + return 0 + + def dnskey(self): + with open(self.keyfile, "r", encoding="utf-8") as file: + for line in file: + if "DNSKEY" in line: + return line.strip() + return "undefined" + + def is_ksk(self) -> bool: + return self.get_metadata("KSK") == "yes" + + def is_zsk(self) -> bool: + return self.get_metadata("ZSK") == "yes" + + def dnskey_equals(self, value, cdnskey=False): + dnskey = value.split() + + if cdnskey: + # fourth element is the rrtype + assert dnskey[3] == "CDNSKEY" + dnskey[3] = "DNSKEY" + + dnskey_fromfile = [] + rdata = " ".join(dnskey[:7]) + + with open(self.keyfile, "r", encoding="utf-8") as file: + for line in file: + if f"{rdata}" in line: + dnskey_fromfile = line.split() + + pubkey_fromfile = "".join(dnskey_fromfile[7:]) + pubkey_fromwire = "".join(dnskey[7:]) + + return pubkey_fromfile == pubkey_fromwire + + def cds_equals(self, value, alg): + cds = value.split() + + dsfromkey_command = [ + os.environ.get("DSFROMKEY"), + "-T", + str(self.ttl()), + "-a", + alg, + "-C", + "-w", + str(self.keyfile), + ] + + out = isctest.run.cmd(dsfromkey_command, log_stdout=True) + dsfromkey = out.stdout.decode("utf-8").split() + + rdata_fromfile = " ".join(dsfromkey[:7]) + rdata_fromwire = " ".join(cds[:7]) + if rdata_fromfile != rdata_fromwire: + isctest.log.debug( + f"CDS RDATA MISMATCH: {rdata_fromfile} - {rdata_fromwire}" + ) + return False + + digest_fromfile = "".join(dsfromkey[7:]).lower() + digest_fromwire = "".join(cds[7:]).lower() + if digest_fromfile != digest_fromwire: + isctest.log.debug( + f"CDS DIGEST MISMATCH: {digest_fromfile} - {digest_fromwire}" + ) + return False + + return digest_fromfile == digest_fromwire + + def is_metadata_consistent(self, key, metadata, checkval=True): + """ + If 'key' exists in 'metadata' then it must also exist in the state + meta data. Otherwise, it must not exist in the state meta data. + If 'checkval' is True, the meta data values must also match. + """ + if key in metadata: + if checkval: + value = self.get_metadata(key) + if value != f"{metadata[key]}": + isctest.log.debug( + f"{self.name} {key} METADATA MISMATCH: {value} - {metadata[key]}" + ) + return value == f"{metadata[key]}" + + return self.get_metadata(key) != "undefined" + + value = self.get_metadata(key, must_exist=False) + if value != "undefined": + isctest.log.debug(f"{self.name} {key} METADATA UNEXPECTED: {value}") + return value == "undefined" + + def is_timing_consistent(self, key, timing, file, comment=False): + """ + If 'key' exists in 'timing' then it must match the value in the state + timing data. Otherwise, it must also not exist in the state timing data. + """ + if key in timing: + value = self.get_metadata(key, file=file, comment=comment) + if value != str(timing[key]): + isctest.log.debug( + f"{self.name} {key} TIMING MISMATCH: {value} - {timing[key]}" + ) + return value == str(timing[key]) + + value = self.get_metadata(key, file=file, comment=comment, must_exist=False) + if value != "undefined": + isctest.log.debug(f"{self.name} {key} TIMING UNEXPECTED: {value}") + return value == "undefined" + + def match_properties(self, zone, properties): + """ + Check the key with given properties. + """ + if not properties.properties["expect"]: + return False + + # Check file existence. + # Noop. If file is missing then the get_metadata calls will fail. + + # Check the public key file. + role = properties.properties["role_full"] + comment = f"This is a {role} key, keyid {self.tag}, for {zone}." + if not isctest.util.file_contents_contain(self.keyfile, comment): + isctest.log.debug(f"{self.name} COMMENT MISMATCH: expected '{comment}'") + return False + + ttl = properties.properties["dnskey_ttl"] + flags = properties.properties["flags"] + alg = properties.metadata["Algorithm"] + dnskey = f"{zone}. {ttl} IN DNSKEY {flags} 3 {alg}" + if not isctest.util.file_contents_contain(self.keyfile, dnskey): + isctest.log.debug(f"{self.name} DNSKEY MISMATCH: expected '{dnskey}'") + return False + + # Now check the private key file. + if properties.properties["private"]: + # Retrieve creation date. + created = self.get_metadata("Generated") + + pval = self.get_metadata("Created", file=self.privatefile) + if pval != created: + isctest.log.debug( + f"{self.name} Created METADATA MISMATCH: {pval} - {created}" + ) + return False + pval = self.get_metadata("Private-key-format", file=self.privatefile) + if pval != "v1.3": + isctest.log.debug( + f"{self.name} Private-key-format METADATA MISMATCH: {pval} - v1.3" + ) + return False + pval = self.get_metadata("Algorithm", file=self.privatefile) + if pval != f"{alg}": + isctest.log.debug( + f"{self.name} Algorithm METADATA MISMATCH: {pval} - {alg}" + ) + return False + + # Now check the key state file. + if properties.properties["legacy"]: + return True + + comment = f"This is the state of key {self.tag}, for {zone}." + if not isctest.util.file_contents_contain(self.statefile, comment): + isctest.log.debug(f"{self.name} COMMENT MISMATCH: expected '{comment}'") + return False + + attributes = [ + "Lifetime", + "Algorithm", + "Length", + "KSK", + "ZSK", + "GoalState", + "DNSKEYState", + "KRRSIGState", + "ZRRSIGState", + "DSState", + ] + for key in attributes: + if not self.is_metadata_consistent(key, properties.metadata): + return False + + # A match is found. + return True + + def match_timingmetadata(self, timings, file=None, comment=False): + if file is None: + file = self.statefile + + attributes = [ + "Generated", + "Created", + "Published", + "Publish", + "PublishCDS", + "SyncPublish", + "Active", + "Activate", + "Retired", + "Inactive", + "Revoked", + "Removed", + "Delete", + ] + for key in attributes: + if not self.is_timing_consistent(key, timings, file, comment=comment): + isctest.log.debug(f"{self.name} TIMING METADATA MISMATCH: {key}") + return False + + return True + + def __lt__(self, other: "Key"): + return self.name < other.name + + def __eq__(self, other: object): + return isinstance(other, Key) and self.path == other.path + + def __repr__(self): + return self.path + + +def check_zone_is_signed(server, zone, tsig=None): + addr = server.ip + fqdn = f"{zone}." + + # wait until zone is fully signed + signed = False + for _ in range(10): + response = _query(server, fqdn, dns.rdatatype.NSEC, tsig=tsig) + if not isinstance(response, dns.message.Message): + isctest.log.debug(f"no response for {fqdn} NSEC from {addr}") + elif response.rcode() != dns.rcode.NOERROR: + rcode = dns.rcode.to_text(response.rcode()) + isctest.log.debug(f"{rcode} response for {fqdn} NSEC from {addr}") + else: + has_nsec = False + has_rrsig = False + for rr in response.answer: + if not has_nsec: + has_nsec = rr.match( + dns.name.from_text(fqdn), + dns.rdataclass.IN, + dns.rdatatype.NSEC, + dns.rdatatype.NONE, + ) + if not has_rrsig: + has_rrsig = rr.match( + dns.name.from_text(fqdn), + dns.rdataclass.IN, + dns.rdatatype.RRSIG, + dns.rdatatype.NSEC, + ) + + if not has_nsec: + isctest.log.debug( + f"missing apex {fqdn} NSEC record in response from {addr}" + ) + if not has_rrsig: + isctest.log.debug( + f"missing {fqdn} NSEC signature in response from {addr}" + ) + + signed = has_nsec and has_rrsig + + if signed: + break + + time.sleep(1) + + assert signed + + +def check_keys(zone, keys, expected): + """ + Checks keys for a configured zone. This verifies: + 1. The expected number of keys exist in 'keys'. + 2. The keys match the expected properties. + """ + + def _verify_keys(): + # check number of keys matches expected. + if len(keys) != len(expected): + return False + + if len(keys) == 0: + return True + + for expect in expected: + expect.key = None + + for key in keys: + found = False + i = 0 + while not found and i < len(expected): + if expected[i].key is None: + found = key.match_properties(zone, expected[i]) + if found: + key.external = expected[i].properties["legacy"] + expected[i].key = key + i += 1 + if not found: + return False + + return True + + isctest.run.retry_with_timeout(_verify_keys, timeout=10) + + +def check_keytimes(keys, expected): + """ + Check the key timing metadata for all keys in 'keys'. + """ + assert len(keys) == len(expected) + + if len(keys) == 0: + return + + for key in keys: + for expect in expected: + if expect.properties["legacy"]: + continue + + if not key is expect.key: + continue + + synonyms = {} + if "Generated" in expect.timing: + synonyms["Created"] = expect.timing["Generated"] + if "Published" in expect.timing: + synonyms["Publish"] = expect.timing["Published"] + if "PublishCDS" in expect.timing: + synonyms["SyncPublish"] = expect.timing["PublishCDS"] + if "Active" in expect.timing: + synonyms["Activate"] = expect.timing["Active"] + if "Retired" in expect.timing: + synonyms["Inactive"] = expect.timing["Retired"] + if "DeleteCDS" in expect.timing: + synonyms["SyncDelete"] = expect.timing["DeleteCDS"] + if "Revoked" in expect.timing: + synonyms["Revoked"] = expect.timing["Revoked"] + if "Removed" in expect.timing: + synonyms["Delete"] = expect.timing["Removed"] + + assert key.match_timingmetadata(synonyms, file=key.keyfile, comment=True) + if expect.properties["private"]: + assert key.match_timingmetadata(synonyms, file=key.privatefile) + if not expect.properties["legacy"]: + assert key.match_timingmetadata(expect.timing) + + state_changes = [ + "DNSKEYChange", + "KRRSIGChange", + "ZRRSIGChange", + "DSChange", + ] + for change in state_changes: + assert key.is_metadata_consistent( + change, expect.timing, checkval=False + ) + + +def check_keyrelationships(keys, expected): + """ + Check the key relationships (Successor and Predecessor metadata). + """ + for key in keys: + for expect in expected: + if expect.properties["legacy"]: + continue + + if not key is expect.key: + continue + + relationship_status = ["Predecessor", "Successor"] + for status in relationship_status: + assert key.is_metadata_consistent(status, expect.metadata) + + +def check_dnssec_verify(server, zone, tsig=None): + # Check if zone if DNSSEC valid with dnssec-verify. + fqdn = f"{zone}." + + verified = False + for _ in range(10): + transfer = _query(server, fqdn, dns.rdatatype.AXFR, tsig=tsig) + if not isinstance(transfer, dns.message.Message): + isctest.log.debug(f"no response for {fqdn} AXFR from {server.ip}") + elif transfer.rcode() != dns.rcode.NOERROR: + rcode = dns.rcode.to_text(transfer.rcode()) + isctest.log.debug(f"{rcode} response for {fqdn} AXFR from {server.ip}") + else: + zonefile = f"{zone}.axfr" + with open(zonefile, "w", encoding="utf-8") as file: + for rr in transfer.answer: + file.write(rr.to_text()) + file.write("\n") + + try: + verify_command = [os.environ.get("VERIFY"), "-z", "-o", zone, zonefile] + verified = isctest.run.cmd(verify_command) + except subprocess.CalledProcessError: + pass + + if verified: + break + + time.sleep(1) + + assert verified + + +def check_dnssecstatus(server, zone, keys, policy=None, view=None): + # Call rndc dnssec -status on 'server' for 'zone'. Expect 'policy' in + # the output. This is a loose verification, it just tests if the right + # policy name is returned, and if all expected keys are listed. + response = "" + if view is None: + response = server.rndc(f"dnssec -status {zone}", log=False) + else: + response = server.rndc(f"dnssec -status {zone} in {view}", log=False) + + if policy is None: + assert "Zone does not have dnssec-policy" in response + return + + assert f"dnssec-policy: {policy}" in response + + for key in keys: + assert f"key: {key.tag}" in response + + +def _check_signatures( + signatures, covers, fqdn, keys, offline_ksk=False, zsk_missing=False +): + numsigs = 0 + zrrsig = True + if covers in [dns.rdatatype.DNSKEY, dns.rdatatype.CDNSKEY, dns.rdatatype.CDS]: + zrrsig = False + krrsig = not zrrsig + + for key in keys: + ksigning, zsigning = key.get_signing_state( + offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) + + alg = key.get_metadata("Algorithm") + rtype = dns.rdatatype.to_text(covers) + + expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {fqdn}" + + if zrrsig and zsigning: + has_rrsig = False + for rrsig in signatures: + if re.search(expect, rrsig) is not None: + has_rrsig = True + break + assert has_rrsig, f"Expected signature but not found: {expect}" + numsigs += 1 + + if zrrsig and not zsigning: + for rrsig in signatures: + assert re.search(expect, rrsig) is None + + if krrsig and ksigning: + has_rrsig = False + for rrsig in signatures: + if re.search(expect, rrsig) is not None: + has_rrsig = True + break + assert has_rrsig, f"Expected signature but not found: {expect}" + numsigs += 1 + + if krrsig and not ksigning: + for rrsig in signatures: + assert re.search(expect, rrsig) is None + + return numsigs + + +def check_signatures( + rrset, covers, fqdn, ksks, zsks, offline_ksk=False, zsk_missing=False +): + # Check if signatures with covering type are signed with the right keys. + # The right keys are the ones that expect a signature and have the + # correct role. + numsigs = 0 + + signatures = [] + for rr in rrset: + for rdata in rr: + rdclass = dns.rdataclass.to_text(rr.rdclass) + rdtype = dns.rdatatype.to_text(rr.rdtype) + rrsig = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" + signatures.append(rrsig) + + numsigs += _check_signatures( + signatures, covers, fqdn, ksks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) + numsigs += _check_signatures( + signatures, covers, fqdn, zsks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) + + assert numsigs == len(signatures) + + +def _check_dnskeys(dnskeys, keys, cdnskey=False): + now = KeyTimingMetadata.now() + numkeys = 0 + + publish_md = "Publish" + delete_md = "Delete" + if cdnskey: + publish_md = f"Sync{publish_md}" + delete_md = f"Sync{delete_md}" + + for key in keys: + publish = key.get_timing(publish_md, must_exist=False) + delete = key.get_timing(delete_md, must_exist=False) + published = publish is not None and now >= publish + removed = delete is not None and delete <= now + + if not published or removed: + for dnskey in dnskeys: + assert not key.dnskey_equals(dnskey, cdnskey=cdnskey) + continue + + has_dnskey = False + for dnskey in dnskeys: + if key.dnskey_equals(dnskey, cdnskey=cdnskey): + has_dnskey = True + break + + if not cdnskey: + assert has_dnskey + + if has_dnskey: + numkeys += 1 + + return numkeys + + +def check_dnskeys(rrset, ksks, zsks, cdnskey=False): + # Check if the correct DNSKEY records are published. If the current time + # is between the timing metadata 'publish' and 'delete', the key must have + # a DNSKEY record published. If 'cdnskey' is True, check against CDNSKEY + # records instead. + numkeys = 0 + + dnskeys = [] + for rr in rrset: + for rdata in rr: + rdclass = dns.rdataclass.to_text(rr.rdclass) + rdtype = dns.rdatatype.to_text(rr.rdtype) + dnskey = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" + dnskeys.append(dnskey) + + numkeys += _check_dnskeys(dnskeys, ksks, cdnskey=cdnskey) + if not cdnskey: + numkeys += _check_dnskeys(dnskeys, zsks) + + assert numkeys == len(dnskeys) + + +def check_cds(rrset, keys): + # Check if the correct CDS records are published. If the current time + # is between the timing metadata 'publish' and 'delete', the key must have + # a DNSKEY record published. If 'cdnskey' is True, check against CDNSKEY + # records instead. + now = KeyTimingMetadata.now() + numcds = 0 + + cdss = [] + for rr in rrset: + for rdata in rr: + rdclass = dns.rdataclass.to_text(rr.rdclass) + rdtype = dns.rdatatype.to_text(rr.rdtype) + cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" + cdss.append(cds) + + for key in keys: + assert key.is_ksk() + + publish = key.get_timing("SyncPublish") + delete = key.get_timing("SyncDelete", must_exist=False) + published = now >= publish + removed = delete is not None and delete <= now + if not published or removed: + for cds in cdss: + assert not key.cds_equals(cds, "SHA-256") + continue + + has_cds = False + for cds in cdss: + if key.cds_equals(cds, "SHA-256"): + has_cds = True + break + + assert has_cds + numcds += 1 + + assert numcds == len(cdss) + + +def _query_rrset(server, fqdn, qtype, tsig=None): + response = _query(server, fqdn, qtype, tsig=tsig) + assert response.rcode() == dns.rcode.NOERROR + + rrs = [] + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(fqdn), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + elif rrset.match( + dns.name.from_text(fqdn), dns.rdataclass.IN, qtype, dns.rdatatype.NONE + ): + rrs.append(rrset) + else: + assert False + + return rrs, rrsigs + + +def check_apex( + server, zone, ksks, zsks, offline_ksk=False, zsk_missing=False, tsig=None +): + # Test the apex of a zone. This checks that the SOA and DNSKEY RRsets + # are signed correctly and with the appropriate keys. + fqdn = f"{zone}." + + # test dnskey query + dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY, tsig=tsig) + check_dnskeys(dnskeys, ksks, zsks) + check_signatures( + rrsigs, dns.rdatatype.DNSKEY, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) + + # test soa query + soa, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.SOA, tsig=tsig) + assert len(soa) == 1 + assert f"{zone}. {DEFAULT_TTL} IN SOA" in soa[0].to_text() + check_signatures( + rrsigs, + dns.rdatatype.SOA, + fqdn, + ksks, + zsks, + offline_ksk=offline_ksk, + zsk_missing=zsk_missing, + ) + + # test cdnskey query + cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig) + check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + if len(cdnskeys) > 0: + assert len(rrsigs) > 0 + check_signatures( + rrsigs, dns.rdatatype.CDNSKEY, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) + + # test cds query + cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig) + check_cds(cds, ksks) + if len(cds) > 0: + assert len(rrsigs) > 0 + check_signatures( + rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) + + +def check_subdomain(server, zone, ksks, zsks, offline_ksk=False, tsig=None): + # Test an RRset below the apex and verify it is signed correctly. + fqdn = f"{zone}." + qname = f"a.{zone}." + qtype = dns.rdatatype.A + response = _query(server, qname, qtype, tsig=tsig) + assert response.rcode() == dns.rcode.NOERROR + + match = f"{qname} {DEFAULT_TTL} IN A 10.0.0.1" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + else: + assert match in rrset.to_text() + + check_signatures(rrsigs, qtype, fqdn, ksks, zsks, offline_ksk=offline_ksk) + + +def verify_update_is_signed(server, fqdn, qname, qtype, rdata, ksks, zsks, tsig=None): + """ + Test an RRset below the apex and verify it is updated and signed correctly. + """ + response = _query(server, qname, qtype, tsig=tsig) + + if response.rcode() != dns.rcode.NOERROR: + return False + + rrtype = dns.rdatatype.to_text(qtype) + match = f"{qname} {DEFAULT_TTL} IN {rrtype} {rdata}" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + elif not match in rrset.to_text(): + return False + + if len(rrsigs) == 0: + return False + + # Zone is updated, ready to verify the signatures. + check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + + return True + + +def verify_rrsig_is_refreshed( + server, fqdn, zonefile, qname, qtype, ksks, zsks, tsig=None +): + """ + Verify signature for RRset has been refreshed. + """ + response = _query(server, qname, qtype, tsig=tsig) + + if response.rcode() != dns.rcode.NOERROR: + return False + + rrtype = dns.rdatatype.to_text(qtype) + match = f"{qname}. {DEFAULT_TTL} IN {rrtype}" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + elif not match in rrset.to_text(): + return False + + if len(rrsigs) == 0: + return False + + tmp_zonefile = f"{zonefile}.tmp" + isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + "-o", + tmp_zonefile, + "-f", + "raw", + fqdn, + zonefile, + ], + ) + + zone = dns.zone.from_file(tmp_zonefile, fqdn) + for rrsig in rrsigs: + if isctest.util.zone_contains(zone, rrsig): + return False + + # Zone is updated, ready to verify the signatures. + check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + + return True + + +def verify_rrsig_is_reused(server, fqdn, zonefile, qname, qtype, ksks, zsks, tsig=None): + """ + Verify signature for RRset has been reused. + """ + response = _query(server, qname, qtype, tsig=tsig) + + assert response.rcode() == dns.rcode.NOERROR + + rrtype = dns.rdatatype.to_text(qtype) + match = f"{qname}. {DEFAULT_TTL} IN {rrtype}" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + else: + assert match in rrset.to_text() + + tmp_zonefile = f"{zonefile}.tmp" + isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + "-o", + tmp_zonefile, + "-f", + "raw", + fqdn, + zonefile, + ], + ) + + zone = dns.zone.from_file(tmp_zonefile, dns.name.from_text(fqdn), relativize=False) + for rrsig in rrsigs: + assert isctest.util.zone_contains(zone, rrsig) + + check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + + +def next_key_event_equals(server, zone, next_event): + if next_event is None: + # No next key event check. + return True + + val = int(next_event.total_seconds()) + if val == 3600: + waitfor = rf".*zone {zone}.*: next key event in (.*) seconds" + else: + # Don't want default loadkeys interval. + waitfor = rf".*zone {zone}.*: next key event in (?!3600$)(.*) seconds" + + with server.watch_log_from_start() as watcher: + watcher.wait_for_line(re.compile(waitfor)) + + # WMM: The with code below is extracting the line the watcher was + # waiting for. If WatchLog.wait_for_line()` returned the matched string, + # we can use it directly on `re.match`. + next_found = False + minval = val - NEXT_KEY_EVENT_THRESHOLD + maxval = val + NEXT_KEY_EVENT_THRESHOLD + with open(f"{server.identifier}/named.run", "r", encoding="utf-8") as fp: + for line in fp: + match = re.match(waitfor, line) + if match is not None: + nextval = int(match.group(1)) + if minval <= nextval <= maxval: + next_found = True + break + + isctest.log.debug( + f"check next key event: expected {val} in: {line.strip()}" + ) + + return next_found + + +def keydir_to_keylist( + zone: Optional[str], keydir: Optional[str] = None, in_use: bool = False +) -> List[Key]: + """ + Retrieve all keys from the key files in a directory. If 'zone' is None, + retrieve all keys in the directory, otherwise only those matching the + zone name. If 'keydir' is None, search the current directory. + """ + if zone is None: + zone = "" + + all_keys = [] + if keydir is None: + regex = rf"(K{zone}\.\+.*\+.*)\.key" + for filename in glob.glob(f"K{zone}.+*+*.key"): + match = re.match(regex, filename) + if match is not None: + all_keys.append(Key(match.group(1))) + else: + regex = rf"{keydir}/(K{zone}\.\+.*\+.*)\.key" + for filename in glob.glob(f"{keydir}/K{zone}.+*+*.key"): + match = re.match(regex, filename) + if match is not None: + all_keys.append(Key(match.group(1), keydir)) + + states = ["GoalState", "DNSKEYState", "KRRSIGState", "ZRRSIGState", "DSState"] + + def used(kk): + if not in_use: + return True + + for state in states: + val = kk.get_metadata(state, must_exist=False) + if val not in ["undefined", "hidden"]: + isctest.log.debug(f"key {kk} in use") + return True + + return False + + return [k for k in all_keys if used(k)] + + +def keystr_to_keylist(keystr: str, keydir: Optional[str] = None) -> List[Key]: + return [Key(name, keydir) for name in keystr.split()] + + +def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]: + """ + Get the policies from a list of specially formatted strings. + The splitted line should result in the following items: + line[0]: Role + line[1]: Lifetime + line[2]: Algorithm + line[3]: Length + Then, optional data for specific tests may follow: + - "goal", "dnskey", "krrsig", "zrrsig", "ds", followed by a value, + sets the given state to the specific value + - "missing", set if the private key file for this key is not available. + - "offset", an offset for testing key rollover timings + """ + proplist = [] + count = 0 + for key in keys: + count += 1 + line = key.split() + keyprop = KeyProperties(f"KEY{count}", {}, {}, {}) + keyprop.properties["expect"] = True + keyprop.properties["private"] = True + keyprop.properties["legacy"] = False + keyprop.properties["offset"] = timedelta(0) + keyprop.properties["role"] = line[0] + if line[0] == "zsk": + keyprop.properties["role_full"] = "zone-signing" + keyprop.properties["flags"] = 256 + keyprop.metadata["ZSK"] = "yes" + keyprop.metadata["KSK"] = "no" + else: + keyprop.properties["role_full"] = "key-signing" + keyprop.properties["flags"] = 257 + keyprop.metadata["ZSK"] = "yes" if line[0] == "csk" else "no" + keyprop.metadata["KSK"] = "yes" + + keyprop.properties["dnskey_ttl"] = ttl + keyprop.metadata["Algorithm"] = line[2] + keyprop.metadata["Length"] = line[3] + keyprop.metadata["Lifetime"] = 0 + if line[1] != "unlimited": + keyprop.metadata["Lifetime"] = int(line[1]) + + for i in range(4, len(line)): + if line[i].startswith("goal:"): + keyval = line[i].split(":") + keyprop.metadata["GoalState"] = keyval[1] + elif line[i].startswith("dnskey:"): + keyval = line[i].split(":") + keyprop.metadata["DNSKEYState"] = keyval[1] + elif line[i].startswith("krrsig:"): + keyval = line[i].split(":") + keyprop.metadata["KRRSIGState"] = keyval[1] + elif line[i].startswith("zrrsig:"): + keyval = line[i].split(":") + keyprop.metadata["ZRRSIGState"] = keyval[1] + elif line[i].startswith("ds:"): + keyval = line[i].split(":") + keyprop.metadata["DSState"] = keyval[1] + elif line[i].startswith("offset:"): + keyval = line[i].split(":") + keyprop.properties["offset"] = timedelta(seconds=int(keyval[1])) + elif line[i] == "missing": + keyprop.properties["private"] = False + else: + assert False, f"undefined optional data {line[i]}" + + proplist.append(keyprop) + + return proplist diff --git a/bin/tests/system/isctest/log/__init__.py b/bin/tests/system/isctest/log/__init__.py new file mode 100644 index 0000000..5975ae7 --- /dev/null +++ b/bin/tests/system/isctest/log/__init__.py @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from .basic import ( + avoid_duplicated_logs, + deinit_module_logger, + deinit_test_logger, + init_conftest_logger, + init_module_logger, + init_test_logger, + debug, + info, + warning, + error, + critical, +) + +from .watchlog import LogFile, WatchLogFromStart, WatchLogFromHere diff --git a/bin/tests/system/isctest/log/basic.py b/bin/tests/system/isctest/log/basic.py new file mode 100644 index 0000000..67121d2 --- /dev/null +++ b/bin/tests/system/isctest/log/basic.py @@ -0,0 +1,108 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import logging +from pathlib import Path +from typing import Dict, Optional + + +LOG_FORMAT = "%(asctime)s %(levelname)7s:%(name)s %(message)s" + +LOGGERS = { + "conftest": None, + "module": None, + "test": None, +} # type: Dict[str, Optional[logging.Logger]] + + +def init_conftest_logger(): + """ + This initializes the conftest logger which is used for pytest setup + and configuration before tests are executed -- aka any logging in this + file that is _not_ module-specific. + """ + LOGGERS["conftest"] = logging.getLogger("conftest") + LOGGERS["conftest"].setLevel(logging.DEBUG) + file_handler = logging.FileHandler("pytest.conftest.log.txt") + file_handler.setFormatter(logging.Formatter(LOG_FORMAT)) + LOGGERS["conftest"].addHandler(file_handler) + + +def avoid_duplicated_logs(): + """ + Remove direct root logger output to file descriptors. + This default is causing duplicates because all our messages go through + regular logging as well and are thus displayed twice. + """ + todel = [] + for handler in logging.root.handlers: + if handler.__class__ == logging.StreamHandler: + # Beware: As for pytest 7.2.2, LiveLogging and LogCapture + # handlers inherit from logging.StreamHandler + todel.append(handler) + for handler in todel: + logging.root.handlers.remove(handler) + + +def init_module_logger(system_test_name: str, testdir: Path): + logger = logging.getLogger(system_test_name) + logger.handlers.clear() + logger.setLevel(logging.DEBUG) + handler = logging.FileHandler(testdir / "pytest.log.txt", mode="w") + handler.setFormatter(logging.Formatter(LOG_FORMAT)) + logger.addHandler(handler) + LOGGERS["module"] = logger + + +def deinit_module_logger(): + for handler in LOGGERS["module"].handlers: + handler.flush() + handler.close() + LOGGERS["module"] = None + + +def init_test_logger(system_test_name: str, test_name: str): + LOGGERS["test"] = logging.getLogger(f"{system_test_name}.{test_name}") + + +def deinit_test_logger(): + LOGGERS["test"] = None + + +def log(lvl: int, msg: str, *args, **kwargs): + """Log message with the most-specific logger currently available.""" + logger = LOGGERS["test"] + if logger is None: + logger = LOGGERS["module"] + if logger is None: + logger = LOGGERS["conftest"] + assert logger is not None + logger.log(lvl, msg, *args, **kwargs) + + +def debug(msg: str, *args, **kwargs): + log(logging.DEBUG, msg, *args, **kwargs) + + +def info(msg: str, *args, **kwargs): + log(logging.INFO, msg, *args, **kwargs) + + +def warning(msg: str, *args, **kwargs): + log(logging.WARNING, msg, *args, **kwargs) + + +def error(msg: str, *args, **kwargs): + log(logging.ERROR, msg, *args, **kwargs) + + +def critical(msg: str, *args, **kwargs): + log(logging.CRITICAL, msg, *args, **kwargs) diff --git a/bin/tests/system/isctest/log/watchlog.py b/bin/tests/system/isctest/log/watchlog.py new file mode 100644 index 0000000..b17cd05 --- /dev/null +++ b/bin/tests/system/isctest/log/watchlog.py @@ -0,0 +1,295 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from typing import Iterator, Optional, TextIO, Dict, Any, Union, Pattern + +import abc +import os +import time + + +class WatchLogException(Exception): + pass + + +class LogFile: + """ + Log file wrapper with a path and means to find a string in its contents. + """ + + def __init__(self, path: str): + self.path = path + + @property + def _lines(self) -> Iterator[str]: + with open(self.path, encoding="utf-8") as f: + yield from f + + def __contains__(self, substring: str) -> bool: + """ + Return whether any of the lines in the log contains a given string. + """ + for line in self._lines: + if substring in line: + return True + return False + + def expect(self, msg: str): + """Check the string is present anywhere in the log file.""" + if msg in self: + return + assert False, f"log message not found in log {self.path}: {msg}" + + def prohibit(self, msg: str): + """Check the string is not present in the entire log file.""" + if msg in self: + assert False, f"forbidden message appeared in log {self.path}: {msg}" + + +class WatchLog(abc.ABC): + """ + Wait for a log message to appear in a text file. + + This class should not be used directly; instead, its subclasses, + `WatchLogFromStart` and `WatchLogFromHere`, should be used. For `named` + instances used in system tests, it is recommended to use the + `watch_log_from_start()` and `watch_log_from_here()` helper methods exposed + by the `NamedInstance` class (see below for recommended usage patterns). + """ + + def __init__(self, path: str) -> None: + """ + `path` is the path to the log file to watch. + + Every instance of this class must call one of the `wait_for_*()` + methods exactly once or else an `Exception` is thrown. + + >>> with WatchLogFromStart("/dev/null") as watcher: + ... print("Just print something without waiting for a log line") + Traceback (most recent call last): + ... + Exception: wait_for_*() was not called + + >>> with WatchLogFromHere("/dev/null") as watcher: + ... try: + ... watcher.wait_for_line("foo", timeout=0) + ... except TimeoutError: + ... pass + ... try: + ... watcher.wait_for_lines({"bar": 42}, timeout=0) + ... except TimeoutError: + ... pass + Traceback (most recent call last): + ... + Exception: wait_for_*() was already called + """ + self._fd = None # type: Optional[TextIO] + self._path = path + self._wait_function_called = False + + def wait_for_line(self, string: str, timeout: int = 10) -> None: + """ + Block execution until a line containing the provided `string` appears + in the log file. Return `None` once the line is found or raise a + `TimeoutError` after `timeout` seconds (default: 10) if `string` does + not appear in the log file (strings and regular expressions are + supported). (Catching this exception is discouraged as it indicates + that the test code did not behave as expected.) + + Recommended use: + + ```python + import isctest + + def test_foo(servers): + with servers["ns1"].watch_log_from_here() as watcher: + # ... do stuff here ... + watcher.wait_for_line("foo bar") + ``` + + One of `wait_for_line()` or `wait_for_lines()` must be called exactly + once for every `WatchLogFrom*` instance. + + >>> # For `WatchLogFromStart`, `wait_for_line()` returns without + >>> # raising an exception as soon as the line being looked for appears + >>> # anywhere in the file, no matter whether that happens before of + >>> # after the `with` statement is reached. + >>> import tempfile + >>> with tempfile.NamedTemporaryFile("w") as file: + ... print("foo", file=file, flush=True) + ... with WatchLogFromStart(file.name) as watcher: + ... retval = watcher.wait_for_line("foo", timeout=1) + >>> print(retval) + None + >>> with tempfile.NamedTemporaryFile("w") as file: + ... with WatchLogFromStart(file.name) as watcher: + ... print("foo", file=file, flush=True) + ... retval = watcher.wait_for_line("foo", timeout=1) + >>> print(retval) + None + + >>> # For `WatchLogFromHere`, `wait_for_line()` only returns without + >>> # raising an exception if the string being looked for appears in + >>> # the log file after the `with` statement is reached. + >>> import tempfile + >>> with tempfile.NamedTemporaryFile("w") as file: + ... print("foo", file=file, flush=True) + ... with WatchLogFromHere(file.name) as watcher: + ... watcher.wait_for_line("foo", timeout=1) #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + TimeoutError: Timeout reached watching ... + >>> with tempfile.NamedTemporaryFile("w") as file: + ... print("foo", file=file, flush=True) + ... with WatchLogFromHere(file.name) as watcher: + ... print("foo", file=file, flush=True) + ... retval = watcher.wait_for_line("foo", timeout=1) + >>> print(retval) + None + """ + return self._wait_for({string: None}, timeout) + + def wait_for_lines( + self, strings: Dict[Union[str, Pattern], Any], timeout: int = 10 + ) -> None: + """ + Block execution until a line of interest appears in the log file. This + function is a "multi-match" variant of `wait_for_line()` which is + useful when some action may cause several different (mutually + exclusive) messages to appear in the log file. + + `strings` is a `dict` associating each string to look for with the + value this function should return when that string is found in the log + file (strings and regular expressions are supported). If none of the + `strings` being looked for appear in the log file after `timeout` + seconds, a `TimeoutError` is raised. (Catching this exception is + discouraged as it indicates that the test code did not behave as + expected.) + + Since `strings` is a `dict` and preserves key order (in CPython 3.6 as + implementation detail, since 3.7 by language design), each line is + checked against each key in order until the first match. Values provided + in the `strings` dictionary (i.e. values which this function is expected + to return upon a successful match) can be of any type. + + Recommended use: + + ```python + import isctest + + def test_foo(servers): + triggers = { + "message A": "value returned when message A is found", + "message B": "value returned when message B is found", + } + with servers["ns1"].watch_log_from_here() as watcher: + # ... do stuff here ... + retval = watcher.wait_for_lines(triggers) + ``` + + One of `wait_for_line()` or `wait_for_lines()` must be called exactly + once for every `WatchLogFromHere` instance. + + >>> # Different values must be returned depending on which line is + >>> # found in the log file. + >>> import tempfile + >>> triggers = {"foo": 42, "bar": 1337} + >>> with tempfile.NamedTemporaryFile("w") as file: + ... print("foo", file=file, flush=True) + ... with WatchLogFromStart(file.name) as watcher: + ... retval1 = watcher.wait_for_lines(triggers, timeout=1) + ... with WatchLogFromHere(file.name) as watcher: + ... print("bar", file=file, flush=True) + ... retval2 = watcher.wait_for_lines(triggers, timeout=1) + >>> print(retval1) + 42 + >>> print(retval2) + 1337 + """ + return self._wait_for(strings, timeout) + + def _wait_for(self, patterns: Dict[Union[str, Pattern], Any], timeout: int) -> Any: + """ + Block execution until one of the `strings` being looked for appears in + the log file. Raise a `TimeoutError` if none of the `strings` being + looked for are found in the log file for `timeout` seconds. + """ + if self._wait_function_called: + raise WatchLogException("wait_for_*() was already called") + self._wait_function_called = True + if not self._fd: + raise WatchLogException("No file to watch") + leftover = "" + assert timeout, "Do not use this class unless you want to WAIT for something." + deadline = time.time() + timeout + while time.time() < deadline: + for line in self._fd.readlines(): + if line[-1] != "\n": + # Line is not completely written yet, buffer and keep on waiting + leftover += line + else: + line = leftover + line + leftover = "" + for string, retval in patterns.items(): + if isinstance(string, Pattern) and string.search(line): + return retval + if isinstance(string, str) and string in line: + return retval + time.sleep(0.1) + raise TimeoutError( + "Timeout reached watching {} for {}".format( + self._path, list(patterns.keys()) + ) + ) + + def __enter__(self) -> Any: + self._fd = open(self._path, encoding="utf-8") + self._seek_on_enter() + return self + + @abc.abstractmethod + def _seek_on_enter(self) -> None: + """ + This method is responsible for setting the file position indicator for + the file being watched when execution reaches the __enter__() method. + It is expected to be set differently depending on which `WatchLog` + subclass is used. Since the base `WatchLog` class should not be used + directly, raise an exception upon any attempt of such use. + """ + raise NotImplementedError + + def __exit__(self, *_: Any) -> None: + if not self._wait_function_called: + raise WatchLogException("wait_for_*() was not called") + if self._fd: + self._fd.close() + + +class WatchLogFromStart(WatchLog): + """ + A `WatchLog` subclass which looks for the provided string(s) in the entire + log file. + """ + + def _seek_on_enter(self) -> None: + pass + + +class WatchLogFromHere(WatchLog): + """ + A `WatchLog` subclass which only looks for the provided string(s) in the + portion of the log file which is appended to it after the `with` statement + is reached. + """ + + def _seek_on_enter(self) -> None: + if self._fd: + self._fd.seek(0, os.SEEK_END) diff --git a/bin/tests/system/isctest/mark.py b/bin/tests/system/isctest/mark.py new file mode 100644 index 0000000..facf103 --- /dev/null +++ b/bin/tests/system/isctest/mark.py @@ -0,0 +1,111 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +from pathlib import Path +import shutil +import subprocess + +import pytest + + +long_test = pytest.mark.skipif( + not os.environ.get("CI_ENABLE_ALL_TESTS"), reason="CI_ENABLE_ALL_TESTS not set" +) + + +def feature_test(feature): + feature_test_bin = os.environ["FEATURETEST"] + try: + subprocess.run([feature_test_bin, feature], check=True) + except subprocess.CalledProcessError as exc: + if exc.returncode != 1: + raise + return False + return True + + +DNSRPS_BIN = Path(os.environ["TOP_BUILDDIR"]) / "bin/tests/system/rpz/dnsrps" + + +def is_dnsrps_available(): + if not feature_test("--enable-dnsrps"): + return False + try: + subprocess.run([DNSRPS_BIN, "-a"], check=True) + except subprocess.CalledProcessError: + return False + return True + + +def with_dnstap(*args): # pylint: disable=unused-argument + return feature_test("--enable-dnstap") + + +def with_tsan(*args): # pylint: disable=unused-argument + return feature_test("--tsan") + + +def with_algorithm(name: str): + key = f"{name}_SUPPORTED" + assert key in os.environ, f"{key} env variable undefined" + return pytest.mark.skipif(os.getenv(key) != "1", reason=f"{name} is not supported") + + +without_fips = pytest.mark.skipif( + feature_test("--have-fips-mode"), reason="FIPS support enabled in the build" +) + +with_libxml2 = pytest.mark.skipif( + not feature_test("--have-libxml2"), reason="libxml2 support disabled in the build" +) + +with_lmdb = pytest.mark.skipif( + not feature_test("--with-lmdb"), reason="LMDB support disabled in the build" +) + +with_json_c = pytest.mark.skipif( + not feature_test("--have-json-c"), reason="json-c support disabled in the build" +) + +dnsrps_enabled = pytest.mark.skipif( + not is_dnsrps_available(), reason="dnsrps disabled in the build" +) + + +softhsm2_environment = pytest.mark.skipif( + not ( + os.getenv("SOFTHSM2_CONF") + and os.getenv("SOFTHSM2_MODULE") + and shutil.which("pkcs11-tool") + and shutil.which("softhsm2-util") + ), + reason="SOFTHSM2_CONF and SOFTHSM2_MODULE environmental variables must be set and pkcs11-tool and softhsm2-util tools present", +) + +try: + import flaky as flaky_pkg # type: ignore +except ModuleNotFoundError: + # In case the flaky package is not installed, run the tests as usual + # without any attempts to re-run them. + # pylint: disable=unused-argument + def flaky(*args, **kwargs): + """Mock decorator that doesn't do anything special, just returns the function.""" + + def wrapper(wrapped_obj): + return wrapped_obj + + return wrapper + +else: + flaky = flaky_pkg.flaky diff --git a/bin/tests/system/isctest/name.py b/bin/tests/system/isctest/name.py new file mode 100644 index 0000000..d992ae3 --- /dev/null +++ b/bin/tests/system/isctest/name.py @@ -0,0 +1,20 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.name + + +def prepend_label(label: str, name: dns.name.Name) -> dns.name.Name: + return dns.name.Name((label,) + name.labels) + + +def len_wire_uncompressed(name: dns.name.Name) -> int: + return len(name) + sum(map(len, name.labels)) diff --git a/bin/tests/system/isctest/query.py b/bin/tests/system/isctest/query.py new file mode 100644 index 0000000..6e84c81 --- /dev/null +++ b/bin/tests/system/isctest/query.py @@ -0,0 +1,89 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import time +from typing import Any, Callable, Optional + +import dns.query +import dns.message + +import isctest.log +from isctest.compat import dns_rcode + +QUERY_TIMEOUT = 10 + + +def generic_query( + query_func: Callable[..., Any], + message: dns.message.Message, + ip: str, + port: Optional[int] = None, + source: Optional[str] = None, + timeout: int = QUERY_TIMEOUT, + attempts: int = 10, + expected_rcode: dns_rcode = None, + verify: bool = False, +) -> Any: + if port is None: + if query_func.__name__ == "tls": + port = int(os.environ["TLSPORT"]) + else: + port = int(os.environ["PORT"]) + + query_args = { + "q": message, + "where": ip, + "timeout": timeout, + "port": port, + "source": source, + } + if query_func.__name__ == "tls": + query_args["verify"] = verify + + res = None + for attempt in range(attempts): + isctest.log.debug( + f"{query_func.__name__}(): ip={ip}, port={port}, source={source}, " + f"timeout={timeout}, attempts left={attempts-attempt}" + ) + try: + res = query_func(**query_args) + except (dns.exception.Timeout, ConnectionRefusedError) as e: + isctest.log.debug(f"{query_func.__name__}(): the '{e}' exception raised") + else: + if res.rcode() == expected_rcode or expected_rcode is None: + return res + time.sleep(1) + + if expected_rcode is not None: + last_rcode = dns_rcode.to_text(res.rcode()) if res else None + isctest.log.debug( + f"{query_func.__name__}(): expected rcode={dns_rcode.to_text(expected_rcode)}, last rcode={last_rcode}" + ) + raise dns.exception.Timeout + + +def udp(*args, **kwargs) -> Any: + return generic_query(dns.query.udp, *args, **kwargs) + + +def tcp(*args, **kwargs) -> Any: + return generic_query(dns.query.tcp, *args, **kwargs) + + +def tls(*args, **kwargs) -> Any: + try: + return generic_query(dns.query.tls, *args, **kwargs) + except TypeError as e: + raise RuntimeError( + "dnspython 2.5.0 or newer is required for isctest.query.tls()" + ) from e diff --git a/bin/tests/system/isctest/rndc.py b/bin/tests/system/isctest/rndc.py new file mode 100644 index 0000000..d4a0a1b --- /dev/null +++ b/bin/tests/system/isctest/rndc.py @@ -0,0 +1,69 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import abc +import os +import subprocess + + +class RNDCExecutor(abc.ABC): + """ + An interface which RNDC executors have to implement in order for the + `NamedInstance` class to be able to use them. + """ + + @abc.abstractmethod + def call(self, ip: str, port: int, command: str) -> str: + """ + Send RNDC `command` to the `named` instance at `ip:port` and return the + server's response. + """ + + +class RNDCException(Exception): + """ + Raised by classes implementing the `RNDCExecutor` interface when sending an + RNDC command fails for any reason. + """ + + +class RNDCBinaryExecutor(RNDCExecutor): + """ + An `RNDCExecutor` which sends RNDC commands to servers using the `rndc` + binary. + """ + + def __init__(self) -> None: + """ + This class needs the `RNDC` environment variable to be set to the path + to the `rndc` binary to use. + """ + rndc_path = os.environ.get("RNDC", "/bin/false") + rndc_conf = os.path.join("..", "_common", "rndc.conf") + self._base_cmdline = [rndc_path, "-c", rndc_conf] + + def call(self, ip: str, port: int, command: str) -> str: + """ + Send RNDC `command` to the `named` instance at `ip:port` and return the + server's response. + """ + cmdline = self._base_cmdline[:] + cmdline.extend(["-s", ip]) + cmdline.extend(["-p", str(port)]) + cmdline.extend(command.split()) + + try: + return subprocess.check_output( + cmdline, stderr=subprocess.STDOUT, timeout=10, encoding="utf-8" + ) + except subprocess.SubprocessError as exc: + msg = getattr(exc, "output", "RNDC exception occurred") + raise RNDCException(msg) from exc diff --git a/bin/tests/system/isctest/run.py b/bin/tests/system/isctest/run.py new file mode 100644 index 0000000..c3b37ac --- /dev/null +++ b/bin/tests/system/isctest/run.py @@ -0,0 +1,151 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +from pathlib import Path +import subprocess +import time +from typing import List, Optional + +import isctest.log + + +def cmd( + args, + cwd=None, + timeout=60, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + log_stdout=False, + log_stderr=True, + input_text: Optional[bytes] = None, + raise_on_exception=True, + env: Optional[dict] = None, +): + """Execute a command with given args as subprocess.""" + isctest.log.debug(f"command: {' '.join(args)}") + + def print_debug_logs(procdata): + if procdata: + if log_stdout and procdata.stdout: + isctest.log.debug( + f"~~~ cmd stdout ~~~\n{procdata.stdout.decode('utf-8')}\n~~~~~~~~~~~~~~~~~~" + ) + if log_stderr and procdata.stderr: + isctest.log.debug( + f"~~~ cmd stderr ~~~\n{procdata.stderr.decode('utf-8')}\n~~~~~~~~~~~~~~~~~~" + ) + + if env is None: + env = dict(os.environ) + + try: + proc = subprocess.run( + args, + stdout=stdout, + stderr=stderr, + input=input_text, + check=True, + cwd=cwd, + timeout=timeout, + env=env, + ) + print_debug_logs(proc) + return proc + except subprocess.CalledProcessError as exc: + print_debug_logs(exc) + isctest.log.debug(f" return code: {exc.returncode}") + if raise_on_exception: + raise exc + return exc + + +def _run_script( + interpreter: str, + script: str, + args: Optional[List[str]] = None, +): + if args is None: + args = [] + path = Path(script) + script = str(path) + cwd = os.getcwd() + if not path.exists(): + raise FileNotFoundError(f"script {script} not found in {cwd}") + isctest.log.debug("running script: %s %s %s", interpreter, script, " ".join(args)) + isctest.log.debug(" workdir: %s", cwd) + returncode = 1 + + command = [interpreter, script] + args + with subprocess.Popen( + command, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=1, + universal_newlines=True, + errors="backslashreplace", + ) as proc: + if proc.stdout: + for line in proc.stdout: + isctest.log.info(" %s", line.rstrip("\n")) + proc.communicate() + returncode = proc.returncode + if returncode: + raise subprocess.CalledProcessError(returncode, command) + isctest.log.debug(" exited with %d", returncode) + + +class Dig: + def __init__(self, base_params: str = ""): + self.base_params = base_params + + def __call__(self, params: str) -> str: + """Run the dig command with the given parameters and return the decoded output.""" + return cmd( + [os.environ.get("DIG")] + f"{self.base_params} {params}".split(), + log_stdout=True, + ).stdout.decode("utf-8") + + +def shell(script: str, args: Optional[List[str]] = None) -> None: + """Run a given script with system's shell interpreter.""" + _run_script(os.environ["SHELL"], script, args) + + +def perl(script: str, args: Optional[List[str]] = None) -> None: + """Run a given script with system's perl interpreter.""" + _run_script(os.environ["PERL"], script, args) + + +def retry_with_timeout(func, timeout, delay=1, msg=None): + start_time = time.time() + while time.time() < start_time + timeout: + if func(): + return + time.sleep(delay) + if msg is None: + msg = f"{func.__module__}.{func.__qualname__} timed out after {timeout} s" + assert False, msg + + +def get_named_cmdline(cfg_dir, cfg_file="named.conf"): + cfg_dir = os.path.join(os.getcwd(), cfg_dir) + assert os.path.isdir(cfg_dir) + + cfg_file = os.path.join(cfg_dir, cfg_file) + assert os.path.isfile(cfg_file) + + named = os.getenv("NAMED") + assert named is not None + + named_cmdline = [named, "-c", cfg_file, "-d", "99", "-g"] + + return named_cmdline diff --git a/bin/tests/system/isctest/template.py b/bin/tests/system/isctest/template.py new file mode 100644 index 0000000..17cf7a2 --- /dev/null +++ b/bin/tests/system/isctest/template.py @@ -0,0 +1,81 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from pathlib import Path +from typing import Any, Dict, Optional, Union + +import jinja2 + +from .log import debug +from .vars import ALL + + +class TemplateEngine: + """ + Engine for rendering jinja2 templates in system test directories. + """ + + def __init__(self, directory: Union[str, Path], env_vars=ALL): + """ + Initialize the template engine for `directory`, optionally overriding + the `env_vars` that will be used when rendering the templates (defaults + to the environment variables set by the pytest runner). + """ + self.directory = Path(directory) + self.env_vars = dict(env_vars) + self.j2env = jinja2.Environment( + loader=jinja2.FileSystemLoader(str(self.directory)), + undefined=jinja2.StrictUndefined, + variable_start_string="@", + variable_end_string="@", + ) + + def render( + self, + output: str, + data: Optional[Dict[str, Any]] = None, + template: Optional[str] = None, + ) -> None: + """ + Render `output` file from jinja `template` and fill in the `data`. The + `template` defaults to *.j2.manual or *.j2 file. The environment + variables which the engine was initialized with are also filled in. In + case of a variable name clash, `data` has precedence. + """ + if template is None: + template = f"{output}.j2.manual" + if not Path(template).is_file(): + template = f"{output}.j2" + if not Path(template).is_file(): + raise RuntimeError('No jinja2 template found for "{output}"') + + if data is None: + data = self.env_vars + else: + data = {**self.env_vars, **data} + + debug("rendering template `%s` to file `%s`", template, output) + stream = self.j2env.get_template(template).stream(data) + stream.dump(output, encoding="utf-8") + + def render_auto(self): + """ + Render all *.j2 templates with default values and write the output to + files without the .j2 extensions. + """ + templates = [ + str(filepath.relative_to(self.directory)) + for filepath in self.directory.rglob("*.j2") + ] + for template in templates: + self.render(template[:-3]) diff --git a/bin/tests/system/isctest/util.py b/bin/tests/system/isctest/util.py new file mode 100644 index 0000000..904e088 --- /dev/null +++ b/bin/tests/system/isctest/util.py @@ -0,0 +1,42 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.zone + + +def zone_contains( + zone: dns.zone.Zone, rrset: dns.rrset.RRset, compare_ttl=False +) -> bool: + """Check if a zone contains RRset""" + + def compare_rrs(rr1, rrset): + rr2 = next((other_rr for other_rr in rrset if rr1 == other_rr), None) + if rr2 is None: + return False + if compare_ttl: + return rr1.ttl == rr2.ttl + return True + + for _, node in zone.nodes.items(): + for rdataset in node: + for rr in rdataset: + if compare_rrs(rr, rrset): + return True + + return False + + +def file_contents_contain(file, substr): + with open(file, "r", encoding="utf-8") as fp: + for line in fp: + if f"{substr}" in line: + return True + return False diff --git a/bin/tests/system/isctest/vars/.ac_vars/CURL.in b/bin/tests/system/isctest/vars/.ac_vars/CURL.in new file mode 100644 index 0000000..0772e63 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/CURL.in @@ -0,0 +1 @@ +@CURL@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE.in b/bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE.in new file mode 100644 index 0000000..d6b9931 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE.in @@ -0,0 +1 @@ +@FSTRM_CAPTURE@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/NC.in b/bin/tests/system/isctest/vars/.ac_vars/NC.in new file mode 100644 index 0000000..b1181ca --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/NC.in @@ -0,0 +1 @@ +@NC@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/PERL.in b/bin/tests/system/isctest/vars/.ac_vars/PERL.in new file mode 100644 index 0000000..f6644c1 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/PERL.in @@ -0,0 +1 @@ +@PERL@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/PYTEST.in b/bin/tests/system/isctest/vars/.ac_vars/PYTEST.in new file mode 100644 index 0000000..f6700d5 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/PYTEST.in @@ -0,0 +1 @@ +@PYTEST@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/PYTHON.in b/bin/tests/system/isctest/vars/.ac_vars/PYTHON.in new file mode 100644 index 0000000..5d697c3 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/PYTHON.in @@ -0,0 +1 @@ +@PYTHON@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/SHELL.in b/bin/tests/system/isctest/vars/.ac_vars/SHELL.in new file mode 100644 index 0000000..e65178b --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/SHELL.in @@ -0,0 +1 @@ +@SHELL@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR.in b/bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR.in new file mode 100644 index 0000000..ad1e3ec --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR.in @@ -0,0 +1 @@ +@abs_top_builddir@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR.in b/bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR.in new file mode 100644 index 0000000..ab6784b --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR.in @@ -0,0 +1 @@ +@abs_top_srcdir@ diff --git a/bin/tests/system/isctest/vars/.ac_vars/XSLTPROC.in b/bin/tests/system/isctest/vars/.ac_vars/XSLTPROC.in new file mode 100644 index 0000000..86d98e0 --- /dev/null +++ b/bin/tests/system/isctest/vars/.ac_vars/XSLTPROC.in @@ -0,0 +1 @@ +@XSLTPROC@ diff --git a/bin/tests/system/isctest/vars/__init__.py b/bin/tests/system/isctest/vars/__init__.py new file mode 100644 index 0000000..1af9e20 --- /dev/null +++ b/bin/tests/system/isctest/vars/__init__.py @@ -0,0 +1,27 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +from .all import ALL +from .algorithms import init_crypto_supported, set_algorithm_set +from .openssl import parse_openssl_config +from .. import log + + +def init_vars(): + """Initializes the environment variables.""" + init_crypto_supported() + set_algorithm_set(os.getenv("ALGORITHM_SET")) + parse_openssl_config(ALL["OPENSSL_CONF"]) + + os.environ.update(ALL) + log.debug("setting following env vars: %s", ", ".join([str(key) for key in ALL])) diff --git a/bin/tests/system/isctest/vars/algorithms.py b/bin/tests/system/isctest/vars/algorithms.py new file mode 100644 index 0000000..26bcc57 --- /dev/null +++ b/bin/tests/system/isctest/vars/algorithms.py @@ -0,0 +1,280 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import platform +import random +import subprocess +import tempfile +import time +from typing import Dict, List, NamedTuple, Optional, Union + +from .basic import BASIC_VARS +from .. import log + +# Algorithms are selected randomly at runtime from a list of supported +# algorithms. The randomization is deterministic and remains stable for a +# period of time for a given platform. +ALG_VARS = { + # There are multiple algoritms sets to choose from (see ALGORITHM_SETS). To + # override the default choice, set the ALGORITHM_SET env var prior to + # loading this module or call set_algorithm_set(). + "ALGORITHM_SET": "none", + "DEFAULT_ALGORITHM": "", + "DEFAULT_ALGORITHM_NUMBER": "", + "DEFAULT_BITS": "", + # Alternative algorithm for test cases that require more than one algorithm + # (for example algorithm rollover). Must be different from + # DEFAULT_ALGORITHM. + "ALTERNATIVE_ALGORITHM": "", + "ALTERNATIVE_ALGORITHM_NUMBER": "", + "ALTERNATIVE_BITS": "", + # Algorithm that is used for tests against the "disable-algorithms" + # configuration option. Must be different from above algorithms. + "DISABLED_ALGORITHM": "", + "DISABLED_ALGORITHM_NUMBER": "", + "DISABLED_BITS": "", + # Default HMAC algorithm. Must match the rndc configuration in + # bin/tests/system/_common (rndc.conf, rndc.key) + "DEFAULT_HMAC": "hmac-sha256", +} + +STABLE_PERIOD = 3600 * 3 +"""number of secs during which algorithm selection remains stable""" + + +class Algorithm(NamedTuple): + name: str + number: int + bits: int + + +class AlgorithmSet(NamedTuple): + """Collection of DEFAULT, ALTERNATIVE and DISABLED algorithms""" + + default: Union[Algorithm, List[Algorithm]] + """DEFAULT is the algorithm for testing.""" + + alternative: Union[Algorithm, List[Algorithm]] + """ALTERNATIVE is an alternative algorithm for test cases that require more + than one algorithm (for example algorithm rollover).""" + + disabled: Union[Algorithm, List[Algorithm]] + """DISABLED is an algorithm that is used for tests against the + "disable-algorithms" configuration option.""" + + +RSASHA1 = Algorithm("RSASHA1", 5, 2048) +RSASHA256 = Algorithm("RSASHA256", 8, 2048) +RSASHA512 = Algorithm("RSASHA512", 10, 2048) +ECDSAP256SHA256 = Algorithm("ECDSAP256SHA256", 13, 256) +ECDSAP384SHA384 = Algorithm("ECDSAP384SHA384", 14, 384) +ED25519 = Algorithm("ED25519", 15, 256) +ED448 = Algorithm("ED448", 16, 456) + +ALL_ALGORITHMS = [ + RSASHA1, + RSASHA256, + RSASHA512, + ECDSAP256SHA256, + ECDSAP384SHA384, + ED25519, + ED448, +] + +ALGORITHM_SETS = { + "stable": AlgorithmSet( + default=ECDSAP256SHA256, alternative=RSASHA256, disabled=ECDSAP384SHA384 + ), + "ecc_default": AlgorithmSet( + default=[ + ECDSAP256SHA256, + ECDSAP384SHA384, + ED25519, + ED448, + ], + alternative=RSASHA256, + disabled=RSASHA512, + ), + # FUTURE The system tests needs more work before they're ready for this. + # "random": AlgorithmSet( + # default=ALL_ALGORITHMS, + # alternative=ALL_ALGORITHMS, + # disabled=ALL_ALGORITHMS, + # ), +} + + +def is_crypto_supported(alg: Algorithm) -> bool: + """Test whether a given algorithm is supported on the current platform.""" + assert alg in ALL_ALGORITHMS, f"unknown algorithm: {alg}" + with tempfile.TemporaryDirectory() as tmpdir: + proc = subprocess.run( + [ + BASIC_VARS["KEYGEN"], + "-a", + alg.name, + "-b", + str(alg.bits), + "foo", + ], + cwd=tmpdir, + check=False, + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + ) + if proc.returncode == 0: + return True + log.debug(f"dnssec-keygen stderr: {proc.stderr.decode('utf-8')}") + log.info("algorithm %s not supported", alg.name) + return False + + +# Indicate algorithm support on the current platform. +CRYPTO_SUPPORTED_VARS = { + "RSASHA1_SUPPORTED": "0", + "RSASHA256_SUPPORTED": "0", + "RSASHA512_SUPPORTED": "0", + "ECDSAP256SHA256_SUPPORTED": "0", + "ECDSAP384SHA384_SUPPORTED": "0", + "ED25519_SUPPORTED": "0", + "ED448_SUPPORTED": "0", +} + +SUPPORTED_ALGORITHMS: List[Algorithm] = [] + + +def init_crypto_supported(): + """Initialize the environment variables indicating cryptography support.""" + for alg in ALL_ALGORITHMS: + supported = is_crypto_supported(alg) + if supported: + SUPPORTED_ALGORITHMS.append(alg) + envvar = f"{alg.name}_SUPPORTED" + val = "1" if supported else "0" + CRYPTO_SUPPORTED_VARS[envvar] = val + os.environ[envvar] = val + + +def _filter_supported(algs: AlgorithmSet) -> AlgorithmSet: + """Select supported algorithms from the set.""" + filtered = {} + for alg_type in algs._fields: + candidates = getattr(algs, alg_type) + if isinstance(candidates, Algorithm): + candidates = [candidates] + supported = [alg for alg in candidates if alg in SUPPORTED_ALGORITHMS] + if len(supported) == 1: + supported = supported.pop() + elif not supported: + raise RuntimeError( + f"no {alg_type.upper()} algorithm " "supported on this platform" + ) + filtered[alg_type] = supported + return AlgorithmSet(**filtered) + + +def _select_random(algs: AlgorithmSet, stable_period=STABLE_PERIOD) -> AlgorithmSet: + """Select random DEFAULT, ALTERNATIVE and DISABLED algorithms from the set. + + The algorithm selection is deterministic for a given time period and + platform. This should make potential issues more reproducible. + + To increase the likelyhood of detecting an issue with a given algorithm in + CI, the current platform is used as a randomness source. When testing on + multiple platforms at the same time, this ensures more algorithm variance + while keeping reproducibility for a single platform. + + The function also ensures that DEFAULT, ALTERNATIVE and DISABLED algorithms + are all different. + """ + # FUTURE Random selection of ALTERNATIVE and DISABLED algorithms needs to + # be implemented. + alternative = algs.alternative + disabled = algs.disabled + assert isinstance( + alternative, Algorithm + ), "ALTERNATIVE algorithm randomization not supported yet" + assert isinstance( + disabled, Algorithm + ), "DISABLED algorithm randomization not supported yet" + + # initialize randomness + now = time.time() + time_seed = int(now - now % stable_period) + seed = f"{platform.platform()}_{time_seed}" + random.seed(seed) + + # DEFAULT selection + if isinstance(algs.default, Algorithm): + default = algs.default + else: + candidates = algs.default + for taken in [alternative, disabled]: + try: + candidates.remove(taken) + except ValueError: + pass + assert len(candidates), "no possible choice for DEFAULT algorithm" + random.shuffle(candidates) + default = candidates[0] + + # Ensure only single algorithm is present for each option + assert isinstance(default, Algorithm) + assert isinstance(alternative, Algorithm) + assert isinstance(disabled, Algorithm) + + assert default != alternative, "DEFAULT and ALTERNATIVE algorithms are the same" + assert default != disabled, "DEFAULT and DISABLED algorithms are the same" + assert alternative != disabled, "ALTERNATIVE and DISABLED algorithms are the same" + + return AlgorithmSet(default, alternative, disabled) + + +def _algorithms_env(algs: AlgorithmSet, name: str) -> Dict[str, str]: + """Return environment variables with selected algorithms as a dict.""" + algs_env = { + "ALGORITHM_SET": name, + } + + def set_alg_env(alg: Algorithm, prefix): + algs_env[f"{prefix}_ALGORITHM"] = alg.name + algs_env[f"{prefix}_ALGORITHM_NUMBER"] = str(alg.number) + algs_env[f"{prefix}_BITS"] = str(alg.bits) + + assert isinstance(algs.default, Algorithm) + assert isinstance(algs.alternative, Algorithm) + assert isinstance(algs.disabled, Algorithm) + + set_alg_env(algs.default, "DEFAULT") + set_alg_env(algs.alternative, "ALTERNATIVE") + set_alg_env(algs.disabled, "DISABLED") + + log.info("selected algorithms: %s", algs_env) + return algs_env + + +def set_algorithm_set(name: Optional[str]): + if name is None: + name = "stable" + assert name in ALGORITHM_SETS, f'ALGORITHM_SET "{name}" unknown' + if name == ALG_VARS["ALGORITHM_SET"]: + log.debug('algorithm set already configured: "%s"', name) + return + log.debug('choosing from ALGORITHM_SET "%s"', name) + + algs = ALGORITHM_SETS[name] + algs = _filter_supported(algs) + algs = _select_random(algs) + algs_env = _algorithms_env(algs, name) + + ALG_VARS.update(algs_env) + os.environ.update(algs_env) diff --git a/bin/tests/system/isctest/vars/all.py b/bin/tests/system/isctest/vars/all.py new file mode 100644 index 0000000..eabe2c3 --- /dev/null +++ b/bin/tests/system/isctest/vars/all.py @@ -0,0 +1,64 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from collections import ChainMap + +# pylint: disable=import-error +from .autoconf import AC_VARS # type: ignore + +# pylint: enable=import-error +from .algorithms import ALG_VARS, CRYPTO_SUPPORTED_VARS +from .basic import BASIC_VARS +from .dirs import DIR_VARS +from .openssl import OPENSSL_VARS +from .ports import PORT_VARS + + +class VarLookup(ChainMap): + """A dictionary-like structure to coalesce the variables from different + modules without making a copy (which would prevent updating these values + from inside the modules). Values which are None are treated as unset when + iterating.""" + + def __init__(self, *maps): + keys = set() + for m in maps: + overlap = keys.intersection(m.keys()) + if overlap: + raise RuntimeError(f"key(s) are defined multiple times: {overlap}") + keys = keys.union(m.keys()) + super().__init__(*maps) + + def __setitem__(self, *args, **kwargs): + raise RuntimeError("read-only structure") + + def keys(self): + result = set() + for m in self.maps: + for key, val in m.items(): + if val is None: # treat None as unset + continue + result.add(key) + return list(result) + + def __iter__(self): + return iter(self.keys()) + + +ALL = VarLookup( + AC_VARS, + BASIC_VARS, + OPENSSL_VARS, + PORT_VARS, + DIR_VARS, + ALG_VARS, + CRYPTO_SUPPORTED_VARS, +) diff --git a/bin/tests/system/isctest/vars/autoconf.py b/bin/tests/system/isctest/vars/autoconf.py new file mode 100644 index 0000000..7000ef2 --- /dev/null +++ b/bin/tests/system/isctest/vars/autoconf.py @@ -0,0 +1,29 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from pathlib import Path +from typing import Dict + + +def load_ac_vars_from_files() -> Dict[str, str]: + ac_vars = {} + ac_vars_dir = Path(__file__).resolve().parent / ".ac_vars" + var_paths = [ + path + for path in ac_vars_dir.iterdir() + if path.is_file() and not path.name.endswith(".in") + ] + for var_path in var_paths: + ac_vars[var_path.name] = var_path.read_text(encoding="utf-8").strip() + return ac_vars + + +AC_VARS = load_ac_vars_from_files() diff --git a/bin/tests/system/isctest/vars/basic.py b/bin/tests/system/isctest/vars/basic.py new file mode 100644 index 0000000..e76e5f1 --- /dev/null +++ b/bin/tests/system/isctest/vars/basic.py @@ -0,0 +1,64 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +# pylint: disable=import-error +from .autoconf import AC_VARS # type: ignore + +# pylint: enable=import-error + + +BASIC_VARS = { + "ARPANAME": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/arpaname", + "CDS": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-cds", + "CHECKCONF": f"{AC_VARS['TOP_BUILDDIR']}/bin/check/named-checkconf", + "CHECKZONE": f"{AC_VARS['TOP_BUILDDIR']}/bin/check/named-checkzone", + "DIG": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/dig", + "DNSTAPREAD": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/dnstap-read", + "DSFROMKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-dsfromkey", + "FEATURETEST": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/feature-test", + "HOST": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/host", + "IMPORTKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-importkey", + "JOURNALPRINT": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-journalprint", + "KEYFRLAB": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-keyfromlabel", + "KEYGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-keygen", + "KSR": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-ksr", + "MDIG": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/mdig", + "NAMED": f"{AC_VARS['TOP_BUILDDIR']}/bin/named/named", + "NSEC3HASH": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/nsec3hash", + "NSLOOKUP": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/nslookup", + "NSUPDATE": f"{AC_VARS['TOP_BUILDDIR']}/bin/nsupdate/nsupdate", + "NZD2NZF": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-nzd2nzf", + "REVOKE": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-revoke", + "RNDC": f"{AC_VARS['TOP_BUILDDIR']}/bin/rndc/rndc", + "RNDCCONFGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/confgen/rndc-confgen", + "RRCHECKER": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-rrchecker", + "SETTIME": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-settime", + "SIGNER": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-signzone", + "TSIGKEYGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/confgen/tsig-keygen", + "VERIFY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-verify", + "WIRETEST": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/wire_test", + "BIGKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/rsabigexponent/bigkey", + "GENCHECK": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/rndc/gencheck", + "MAKEJOURNAL": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/makejournal", + "PIPEQUERIES": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/pipelined/pipequeries", + "TMPDIR": os.getenv("TMPDIR", "/tmp"), + "KRB5_CONFIG": "/dev/null", # we don't want a KRB5_CONFIG setting breaking the tests + "KRB5_KTNAME": "dns.keytab", # use local keytab instead of default /etc/krb5.keytab + "DELV": ( + f"{AC_VARS['TOP_BUILDDIR']}/bin/delv/delv" + if not os.getenv("TSAN_OPTIONS", "") + else ":" # workaround for GL#4119 + ), + "LC_ALL": "C", + "ANS_LOG_LEVEL": "debug", +} diff --git a/bin/tests/system/isctest/vars/dirs.py b/bin/tests/system/isctest/vars/dirs.py new file mode 100644 index 0000000..56f4c55 --- /dev/null +++ b/bin/tests/system/isctest/vars/dirs.py @@ -0,0 +1,31 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +# pylint: disable=import-error +from .autoconf import AC_VARS # type: ignore + +# pylint: enable=import-error + + +SYSTEM_TEST_DIR_GIT_PATH = "bin/tests/system" + +DIR_VARS = { + "builddir": f"{AC_VARS['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}", + "srcdir": f"{AC_VARS['TOP_SRCDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}", + "SYSTESTDIR": None, +} + + +def set_system_test_name(name: str): + DIR_VARS["SYSTESTDIR"] = name + os.environ["SYSTESTDIR"] = name diff --git a/bin/tests/system/isctest/vars/openssl.py b/bin/tests/system/isctest/vars/openssl.py new file mode 100644 index 0000000..5df12b7 --- /dev/null +++ b/bin/tests/system/isctest/vars/openssl.py @@ -0,0 +1,53 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import re +from typing import Optional + +from .. import log + + +OPENSSL_VARS = { + "OPENSSL_CONF": os.getenv("OPENSSL_CONF", None), + "SOFTHSM2_CONF": os.getenv("SOFTHSM2_CONF", None), + "SOFTHSM2_MODULE": None, + "ENGINE_ARG": None, +} + + +def parse_openssl_config(path: Optional[str]): + if path is None or not os.path.exists(path): + OPENSSL_VARS["ENGINE_ARG"] = None + OPENSSL_VARS["SOFTHSM2_MODULE"] = None + os.environ.pop("ENGINE_ARG", None) + os.environ.pop("SOFTHSM2_MODULE", None) + return + assert os.path.isfile(path), f"{path} exists, but it's not a file" + + regex = re.compile(r"([^=]+)=(.*)") + log.debug(f"parsing openssl config: {path}") + with open(path, "r", encoding="utf-8") as conf: + for line in conf: + res = regex.match(line) + if res: + key = res.group(1).strip() + val = res.group(2).strip() + if key == "engine_id": + OPENSSL_VARS["ENGINE_ARG"] = f"-E {val}" + os.environ["ENGINE_ARG"] = f"-E {val}" + log.debug("ENGINE_ARG set to {OPENSSL_VARS['ENGINE_ARG']}") + elif key in ["MODULE_PATH", "pkcs11-module-path"]: + OPENSSL_VARS["SOFTHSM2_MODULE"] = val + os.environ["SOFTHSM2_MODULE"] = val + log.debug( + "SOFTHSM2_MODULE set to {OPENSSL_VARS['SOFTHSM2_MODULE']}" + ) diff --git a/bin/tests/system/isctest/vars/ports.py b/bin/tests/system/isctest/vars/ports.py new file mode 100644 index 0000000..c4ff533 --- /dev/null +++ b/bin/tests/system/isctest/vars/ports.py @@ -0,0 +1,54 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +from .. import log + +PORT_MIN = 5001 +PORT_MAX = 32767 +PORTS_PER_TEST = 20 + +PORT_VARS = { + "PORT": "5300", + "TLSPORT": "5301", + "HTTPPORT": "5302", + "HTTPSPORT": "5303", + "EXTRAPORT1": "5304", + "EXTRAPORT2": "5305", + "EXTRAPORT3": "5306", + "EXTRAPORT4": "5307", + "EXTRAPORT5": "5308", + "EXTRAPORT6": "5309", + "EXTRAPORT7": "5310", + "EXTRAPORT8": "5311", + "CONTROLPORT": "5312", +} + + +def set_base_port(base_port: int): + log.debug(f"setting base port {base_port}") + assert base_port >= PORT_MIN + assert base_port <= PORT_MAX + PORT_VARS["PORT"] = str(base_port) + PORT_VARS["TLSPORT"] = str(base_port + 1) + PORT_VARS["HTTPPORT"] = str(base_port + 2) + PORT_VARS["HTTPSPORT"] = str(base_port + 3) + PORT_VARS["EXTRAPORT1"] = str(base_port + 4) + PORT_VARS["EXTRAPORT2"] = str(base_port + 5) + PORT_VARS["EXTRAPORT3"] = str(base_port + 6) + PORT_VARS["EXTRAPORT4"] = str(base_port + 7) + PORT_VARS["EXTRAPORT5"] = str(base_port + 8) + PORT_VARS["EXTRAPORT6"] = str(base_port + 9) + PORT_VARS["EXTRAPORT7"] = str(base_port + 10) + PORT_VARS["EXTRAPORT8"] = str(base_port + 11) + PORT_VARS["CONTROLPORT"] = str(base_port + 12) + os.environ.update(PORT_VARS) diff --git a/bin/tests/system/ixfr/ans2/startme b/bin/tests/system/ixfr/ans2/startme new file mode 100644 index 0000000..e69de29 diff --git a/bin/tests/system/ixfr/ixfr-stats-with-expire.good b/bin/tests/system/ixfr/ixfr-stats-with-expire.good new file mode 100644 index 0000000..c02992b --- /dev/null +++ b/bin/tests/system/ixfr/ixfr-stats-with-expire.good @@ -0,0 +1,3 @@ +messages=1 +records=5 +bytes=223 diff --git a/bin/tests/system/ixfr/ixfr-stats-without-expire.good b/bin/tests/system/ixfr/ixfr-stats-without-expire.good new file mode 100644 index 0000000..0713c0b --- /dev/null +++ b/bin/tests/system/ixfr/ixfr-stats-without-expire.good @@ -0,0 +1,3 @@ +messages=1 +records=5 +bytes=215 diff --git a/bin/tests/system/ixfr/ns1/named.conf.in b/bin/tests/system/ixfr/ns1/named.conf.in new file mode 100644 index 0000000..1bf58a7 --- /dev/null +++ b/bin/tests/system/ixfr/ns1/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/ixfr/ns3/named.conf.in b/bin/tests/system/ixfr/ns3/named.conf.in new file mode 100644 index 0000000..40af324 --- /dev/null +++ b/bin/tests/system/ixfr/ns3/named.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + allow-transfer { any; }; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view "primary" { + ixfr-from-differences yes; + request-ixfr yes; + zone "test" IN { + type primary; + file "mytest.db"; + max-ixfr-ratio 75%; + }; + zone "sub.test" IN { + type primary; + file "subtest.db"; + }; + zone "large" IN { + type primary; + file "large.db"; + }; +}; diff --git a/bin/tests/system/ixfr/ns4/named.conf.in b/bin/tests/system/ixfr/ns4/named.conf.in new file mode 100644 index 0000000..83cc318 --- /dev/null +++ b/bin/tests/system/ixfr/ns4/named.conf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view "primary" { + ixfr-from-differences yes; + request-ixfr yes; + zone "test" IN { + type secondary; + file "mytest.db"; + primaries { 10.53.0.3; }; + max-ixfr-ratio unlimited; + }; + zone "sub.test" IN { + type secondary; + file "subtest.db"; + request-ixfr no; + primaries { 10.53.0.3; }; + }; +}; diff --git a/bin/tests/system/ixfr/ns5/named.conf.in b/bin/tests/system/ixfr/ns5/named.conf.in new file mode 100644 index 0000000..03c8f86 --- /dev/null +++ b/bin/tests/system/ixfr/ns5/named.conf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + provide-ixfr no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view "primary" { + ixfr-from-differences yes; + request-ixfr yes; + zone "test" IN { + type secondary; + file "mytest.db"; + primaries { 10.53.0.3; }; + }; + zone "sub.test" IN { + type secondary; + file "subtest.db"; + request-ixfr no; + primaries { 10.53.0.3; }; + }; +}; diff --git a/bin/tests/system/ixfr/prereq.sh b/bin/tests/system/ixfr/prereq.sh new file mode 100644 index 0000000..c52be9c --- /dev/null +++ b/bin/tests/system/ixfr/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/ixfr/setup.sh b/bin/tests/system/ixfr/setup.sh new file mode 100644 index 0000000..5b54441 --- /dev/null +++ b/bin/tests/system/ixfr/setup.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +# Set up db files for zone "test" - this is a series of four +# versions of the zone, the second and third having small changes +# and the fourth having a large one. + +testdb() { + cat <ns3/mytest.db +testdb test. 2 61 >ns3/mytest1.db +testdb test. 3 62 >ns3/mytest2.db +testdb test. 4 0 >ns3/mytest3.db + +# Set up similar db files for sub.test, which will have IXFR disabled +testdb sub.test. 1 60 >ns3/subtest.db +testdb sub.test. 3 61 >ns3/subtest1.db + +# Set up a large zone +i=0 +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 3 >ns3/large.db +while [ $i -lt 10000 ]; do + echo "record$i 10 IN TXT this is record %i" >>ns3/large.db + i=$((i + 1)) +done diff --git a/bin/tests/system/ixfr/tests.sh b/bin/tests/system/ixfr/tests.sh new file mode 100644 index 0000000..ca51147 --- /dev/null +++ b/bin/tests/system/ixfr/tests.sh @@ -0,0 +1,488 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# WARNING: The test labelled "testing request-ixfr option in view vs zone" +# is fragile because it depends upon counting instances of records +# in the log file - need a better approach - until then, +# if you add any tests above that point, you will break the test. + +set -e + +. ../conf.sh + +wait_for_serial() ( + $DIG $DIGOPTS "@$1" "$2" SOA >"$4" + serial=$(awk '$4 == "SOA" { print $7 }' "$4") + [ "$3" -eq "${serial:--1}" ] +) + +status=0 +n=0 + +DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}" +RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../_common/rndc.conf -s" + +sendcmd() { + send 10.53.0.2 "${EXTRAPORT1}" +} + +n=$((n + 1)) +echo_i "testing initial AXFR ($n)" +ret=0 + +sendcmd <>ns1/named.conf +zone "nil" { + type secondary; + file "myftp.db"; + primaries { 10.53.0.2; }; + max-records-per-type 5; # use a small value for fallback test +}; +EOF + +rndc_reload ns1 10.53.0.1 + +retry_quiet 10 wait_for_serial 10.53.0.1 nil. 1 dig.out.test$n || ret=1 + +$DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'initial AXFR' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing successful IXFR ($n)" +ret=0 + +# We change the IP address of a.nil., and the TXT record at the apex. +# Then we do a SOA-only update. + +sendcmd </dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing AXFR fallback after IXFR failure (not exact error) ($n)" +ret=0 + +# Provide a broken IXFR response and a working fallback AXFR response + +sendcmd </dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing AXFR fallback after IXFR failure (too many records) ($n)" +ret=0 + +# Provide an IXFR response that would cause a "too many records" condition + +sendcmd </dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +msg="error adding 'nil/TXT' in 'nil/IN' (zone): too many records (must not exceed 5)" +wait_for_log 10 "$msg" ns1/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing AXFR fallback after IXFR failure (bad SOA owner) ($n)" +ret=0 + +# Prepare for checking the logs later on. +nextpart ns1/named.run >/dev/null + +# Provide a broken IXFR response and a working fallback AXFR response. +sendcmd <dig.out.test$n.1 \ + && grep -q -F "serial 4" dig.out.test$n.1 +} +if ! retry_quiet 10 _wait_until_transfer_is_finished; then + echo_i "timed out waiting for version 4 of zone nil. to be transferred" + ret=1 +fi + +# At this point a broken server would be serving a zone with no SOA records. +# Try crashing it by triggering a SOA refresh query. +$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i + +# Do not wait until the zone refresh completes - even if a crash has not +# happened by now, a broken server would never serve the record which is only +# present in the fallback AXFR, so checking for that is enough to verify if a +# server is broken or not; if it is, it is bound to crash shortly anyway. +$DIG $DIGOPTS test.nil. TXT @10.53.0.1 >dig.out.test$n.2 || ret=1 +grep -q -F "serial 4, fallback AXFR" dig.out.test$n.2 || ret=1 + +# Ensure the expected error is logged. +nextpart ns1/named.run | grep -q -F "SOA name mismatch" || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing ixfr-from-differences option ($n)" +# ns3 is primary; ns4 is secondary +{ + $CHECKZONE test. ns3/mytest.db >/dev/null 2>&1 + rc=$? +} || true +if [ $rc -ne 0 ]; then + echo_i "named-checkzone returned failure on ns3/mytest.db" +fi + +retry_quiet 10 wait_for_serial 10.53.0.4 test. 1 dig.out.test$n || ret=1 + +nextpart ns4/named.run >/dev/null + +# modify the primary +sleep 1 +cp ns3/mytest1.db ns3/mytest.db +$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i + +# wait for primary to reload +retry_quiet 10 wait_for_serial 10.53.0.3 test. 2 dig.out.test$n || ret=1 + +# wait for secondary to reload +tret=0 +retry_quiet 5 wait_for_serial 10.53.0.4 test. 2 dig.out.test$n || tret=1 +if [ $tret -eq 1 ]; then + # re-noitfy after 5 seconds, then wait another 10 + $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i + retry_quiet 10 wait_for_serial 10.53.0.4 test. 2 dig.out.test$n || ret=1 +fi + +wait_for_log 10 'got incremental' ns4/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing 'request-ixfr no' option inheritance from view ($n)" +ret=0 +# There's a view with 2 zones. In the view, "request-ixfr yes" +# but in the zone "sub.test", request-ixfr no" +# we want to make sure that a change to sub.test results in AXFR, while +# changes to test. result in IXFR + +sleep 1 +cp ns3/subtest1.db ns3/subtest.db # change to sub.test zone, should be AXFR +nextpart ns4/named.run >/dev/null +$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i + +# wait for primary to reload +retry_quiet 10 wait_for_serial 10.53.0.3 sub.test. 3 dig.out.test$n || ret=1 + +# wait for secondary to reload +tret=0 +retry_quiet 5 wait_for_serial 10.53.0.4 sub.test. 3 dig.out.test$n || tret=1 +if [ $tret -eq 1 ]; then + # re-noitfy after 5 seconds, then wait another 10 + $RNDCCMD 10.53.0.3 notify sub.test | set 's/^/ns3 /' | cat_i + retry_quiet 10 wait_for_serial 10.53.0.4 sub.test. 3 dig.out.test$n || ret=1 +fi + +wait_for_log 10 'got nonincremental response' ns4/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing 'request-ixfr yes' option inheritance from view ($n)" +ret=0 +sleep 1 +cp ns3/mytest2.db ns3/mytest.db # change to test zone, should be IXFR +nextpart ns4/named.run >/dev/null +$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i + +# wait for primary to reload +retry_quiet 10 wait_for_serial 10.53.0.3 test. 3 dig.out.test$n || ret=1 + +# wait for secondary to reload +tret=0 +retry_quiet 5 wait_for_serial 10.53.0.4 test. 3 dig.out.test$n || tret=1 +if [ $tret -eq 1 ]; then + # re-noitfy after 5 seconds, then wait another 10 + $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i + retry_quiet 10 wait_for_serial 10.53.0.4 test. 3 dig.out.test$n || ret=1 +fi + +wait_for_log 10 'got incremental response' ns4/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "testing DiG's handling of a multi message AXFR style IXFR response ($n)" +( + (sleep 10 && kill $$) 2>/dev/null & + sub=$! + $DIG -p ${PORT} ixfr=0 large @10.53.0.3 >dig.out.test$n + kill $sub +) +lines=$(grep hostmaster.large dig.out.test$n | wc -l) +test ${lines:-0} -eq 2 || ret=1 +messages=$(sed -n 's/^;;.*messages \([0-9]*\),.*/\1/p' dig.out.test$n) +test ${messages:-0} -gt 1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'dig +notcp ixfr=' vs 'dig ixfr= +notcp' vs 'dig ixfr=' ($n)" +ret=0 +# Should be "switch to TCP" response +$DIG $DIGOPTS +notcp ixfr=1 test @10.53.0.4 >dig.out1.test$n || ret=1 +$DIG $DIGOPTS ixfr=1 +notcp test @10.53.0.4 >dig.out2.test$n || ret=1 +digcomp dig.out1.test$n dig.out2.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1 +awk '$4 == "SOA" { if ($7 == 3) exit(0); else exit(1);}' dig.out1.test$n || ret=1 +# +nextpart ns4/named.run >/dev/null +# Should be incremental transfer. +$DIG $DIGOPTS ixfr=1 test @10.53.0.4 >dig.out3.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END { if (soacnt == 6) exit(0); else exit(1);}' dig.out3.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check estimated IXFR size ($n)" +ret=0 +# note IXFR delta size will be slightly bigger with version 1 transaction +# headers as there is no correction for the overall record length storage. +# Ver1 = 4 * (6 + 10 + 10 + 17 + 5 * 4) + 2 * (13 + 10 + 4) + (6 * 4) = 330 +# Ver2 = 4 * (6 + 10 + 10 + 17 + 5 * 4) + 2 * (13 + 10 + 4) = 306 +nextpart ns4/named.run | grep "IXFR delta size (306 bytes)" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# make sure ns5 has transfered the zone +# wait for secondary to reload +tret=0 +retry_quiet 5 wait_for_serial 10.53.0.5 test. 4 dig.out.test$n || tret=1 +if [ $tret -eq 1 ]; then + # re-noitfy after 5 seconds, then wait another 10 + $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i + retry_quiet 10 wait_for_serial 10.53.0.5 test. 3 dig.out.test$n || ret=1 +fi + +n=$((n + 1)) +echo_i "test 'provide-ixfr no;' (serial < current) ($n)" +ret=0 +nextpart ns5/named.run >/dev/null +# Should be "AXFR style" response +$DIG $DIGOPTS ixfr=1 test @10.53.0.5 >dig.out1.test$n || ret=1 +# Should be "switch to TCP" response +$DIG $DIGOPTS ixfr=1 +notcp test @10.53.0.5 >dig.out2.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 2) exit(0); else exit(1);}' dig.out1.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1 +msg="IXFR delta response disabled due to 'provide-ixfr no;' being set" +nextpart ns5/named.run | grep "$msg" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'provide-ixfr no;' (serial = current) ($n)" +ret=0 +# Should be "AXFR style" response +$DIG $DIGOPTS ixfr=3 test @10.53.0.5 >dig.out1.test$n || ret=1 +# Should be "switch to TCP" response +$DIG $DIGOPTS ixfr=3 +notcp test @10.53.0.5 >dig.out2.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'provide-ixfr no;' (serial > current) ($n)" +ret=0 +# Should be "AXFR style" response +$DIG $DIGOPTS ixfr=4 test @10.53.0.5 >dig.out1.test$n || ret=1 +# Should be "switch to TCP" response +$DIG $DIGOPTS ixfr=4 +notcp test @10.53.0.5 >dig.out2.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out1.test$n || ret=1 +awk '$4 == "SOA" { soacnt++} END {if (soacnt == 1) exit(0); else exit(1);}' dig.out2.test$n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking whether dig calculates IXFR statistics correctly ($n)" +ret=0 +$DIG $DIGOPTS +expire +nocookie +stat -b 10.53.0.4 @10.53.0.4 test. ixfr=2 >dig.out1.test$n +get_dig_xfer_stats dig.out1.test$n >stats.dig +diff ixfr-stats-with-expire.good stats.dig >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Note: in the next two tests, we use ns4 logs for checking both incoming and +# outgoing transfer statistics as ns4 is both a secondary server (for ns3) and a +# primary server (for dig queries from the previous test) for "test". + +_wait_for_stats() { + get_named_xfer_stats ns4/named.run "$1" test "$2" >"$3" + diff "$4" "$3" >/dev/null || return 1 + return 0 +} + +n=$((n + 1)) +echo_i "checking whether named calculates incoming IXFR statistics correctly ($n)" +ret=0 +retry_quiet 10 _wait_for_stats 10.53.0.3 "Transfer completed" stats.incoming ixfr-stats-without-expire.good || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking whether named calculates outgoing IXFR statistics correctly ($n)" +retry_quiet 10 _wait_for_stats 10.53.0.4 "IXFR ended" stats.outgoing ixfr-stats-with-expire.good || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "testing fallback to AXFR when max-ixfr-ratio is exceeded ($n)" +nextpart ns4/named.run >/dev/null + +sleep 1 +cp ns3/mytest3.db ns3/mytest.db # change to test zone, too big for IXFR +$RNDCCMD 10.53.0.3 reload | sed 's/^/ns3 /' | cat_i + +# wait for secondary to reload +tret=0 +retry_quiet 5 wait_for_serial 10.53.0.4 test. 4 dig.out.test$n || tret=1 +if [ $tret -eq 1 ]; then + # re-noitfy after 5 seconds, then wait another 10 + $RNDCCMD 10.53.0.3 notify test | set 's/^/ns3 /' | cat_i + retry_quiet 10 wait_for_serial 10.53.0.4 test. 4 dig.out.test$n || ret=1 +fi + +wait_for_log 10 'got nonincremental response' ns4/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/ixfr/tests_sh_ixfr.py b/bin/tests/system/ixfr/tests_sh_ixfr.py new file mode 100644 index 0000000..171a0c6 --- /dev/null +++ b/bin/tests/system/ixfr/tests_sh_ixfr.py @@ -0,0 +1,34 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + "stats.*", + "ans*/ans.run", + "ns*/*.jnl", + "ns1/named.run.prev*", + "ns1/myftp.db", + "ns3/large.db", + "ns3/mytest*.db", + "ns3/subtest*.db", + "ns4/mytest.db", + "ns4/subtest.db", + "ns5/mytest.db", + "ns5/subtest.db", + ] +) + + +def test_ixfr(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/journal/ns1/changed.ver1.jnl.saved b/bin/tests/system/journal/ns1/changed.ver1.jnl.saved new file mode 100644 index 0000000..b449a7d Binary files /dev/null and b/bin/tests/system/journal/ns1/changed.ver1.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/changed.ver2.jnl.saved b/bin/tests/system/journal/ns1/changed.ver2.jnl.saved new file mode 100644 index 0000000..d2fa199 Binary files /dev/null and b/bin/tests/system/journal/ns1/changed.ver2.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/d1212.jnl.saved b/bin/tests/system/journal/ns1/d1212.jnl.saved new file mode 100644 index 0000000..57c1497 Binary files /dev/null and b/bin/tests/system/journal/ns1/d1212.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/d2121.jnl.saved b/bin/tests/system/journal/ns1/d2121.jnl.saved new file mode 100644 index 0000000..ec21372 Binary files /dev/null and b/bin/tests/system/journal/ns1/d2121.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/generic.db.in b/bin/tests/system/journal/ns1/generic.db.in new file mode 100644 index 0000000..55669d7 --- /dev/null +++ b/bin/tests/system/journal/ns1/generic.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2012010901 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +addr1 A 10.53.0.1 diff --git a/bin/tests/system/journal/ns1/ixfr.db.in b/bin/tests/system/journal/ns1/ixfr.db.in new file mode 100644 index 0000000..0cb1184 --- /dev/null +++ b/bin/tests/system/journal/ns1/ixfr.db.in @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ SOA ns hostmaster 2012010902 3600 1200 604800 1200 + NS ns +ns A 192.0.2.1 + +addr1 A 10.53.0.1 +addr2 A 10.53.0.2 diff --git a/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved b/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved new file mode 100644 index 0000000..10b5116 Binary files /dev/null and b/bin/tests/system/journal/ns1/ixfr.ver1.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/managed-keys.bind.in b/bin/tests/system/journal/ns1/managed-keys.bind.in new file mode 100644 index 0000000..923e98b --- /dev/null +++ b/bin/tests/system/journal/ns1/managed-keys.bind.in @@ -0,0 +1,2 @@ +. 0 IN SOA . . 3297 0 0 0 0 +. 0 IN TYPE65533 \# 276 60621140598E0A83000000000101030803010001ACFFB409BCC939F8 31F7A1E5EC88F7A59255EC53040BE432027390A4CE896D6F9086F3C5 E177FBFE118163AAEC7AF1462C47945944C4E2C026BE5E98BBCDED25 978272E1E3E079C5094D573F0E83C92F02B32D3513B1550B826929C8 0DD0F92CAC966D17769FD5867B647C3F38029ABDC48152EB8F207159 ECC5D232C7C1537C79F4B7AC28FF11682F21681BF6D6ABA555032BF6 F9F036BEB2AAA5B3778D6EEBFBA6BF9EA191BE4AB0CAEA759E2F773A 1F9029C73ECB8D5735B9321DB085F1B8E2D8038FE2941992548CEE0D 67DD4547E11DD63AF9C9FC1C5466FB684CF009D7197C2CF79E792AB5 01E6A8A1CA519AF2CB9B5F6367E94C0D47502451357BE1B5 diff --git a/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in b/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in new file mode 100644 index 0000000..a63f91c --- /dev/null +++ b/bin/tests/system/journal/ns1/managed-keys.bind.jnl.in @@ -0,0 +1,704 @@ +3b42494e44204c4f472056390a000000 +00000cd20000020000000ce200002bf8 +00000038000000000000000000000000 +00000000000000000000000000000000 +00000cd20000020000000cd30000049c +00000cd40000073800000cd5000009d8 +00000cd600000c7800000cd700000f18 +00000cd8000011b800000cd900001458 +00000cda000016f800000cdb00001998 +00000cdc00001c3800000cdd00001ed8 +00000cde0000217800000cdf00002418 +00000ce0000026b800000ce100002958 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +0000029000000cd200000cd300000021 +0000060001000000000016000000000c +d2000000000000000000000000000000 +000000011f00fffd0001000000000114 +6058a4c2598e0a830000000001010308 +03010001acffb409bcc939f831f7a1e5 +ec88f7a59255ec53040be432027390a4 +ce896d6f9086f3c5e177fbfe118163aa +ec7af1462c47945944c4e2c026be5e98 +bbcded25978272e1e3e079c5094d573f +0e83c92f02b32d3513b1550b826929c8 +0dd0f92cac966d17769fd5867b647c3f +38029abdc48152eb8f207159ecc5d232 +c7c1537c79f4b7ac28ff11682f21681b +f6d6aba555032bf6f9f036beb2aaa5b3 +778d6eebfba6bf9ea191be4ab0caea75 +9e2f773a1f9029c73ecb8d5735b9321d +b085f1b8e2d8038fe2941992548cee0d +67dd4547e11dd63af9c9fc1c5466fb68 +4cf009d7197c2cf79e792ab501e6a8a1 +ca519af2cb9b5f6367e94c0d47502451 +357be1b5000000210000060001000000 +000016000000000cd300000000000000 +0000000000000000000000011f00fffd +00010000000001146058e4a0598e0a83 +000000000101030803010001acffb409 +bcc939f831f7a1e5ec88f7a59255ec53 +040be432027390a4ce896d6f9086f3c5 +e177fbfe118163aaec7af1462c479459 +44c4e2c026be5e98bbcded25978272e1 +e3e079c5094d573f0e83c92f02b32d35 +13b1550b826929c80dd0f92cac966d17 +769fd5867b647c3f38029abdc48152eb +8f207159ecc5d232c7c1537c79f4b7ac +28ff11682f21681bf6d6aba555032bf6 +f9f036beb2aaa5b3778d6eebfba6bf9e +a191be4ab0caea759e2f773a1f9029c7 +3ecb8d5735b9321db085f1b8e2d8038f +e2941992548cee0d67dd4547e11dd63a +f9c9fc1c5466fb684cf009d7197c2cf7 +9e792ab501e6a8a1ca519af2cb9b5f63 +67e94c0d47502451357be1b500000290 +00000cd300000cd40000002100000600 +01000000000016000000000cd3000000 +00000000000000000000000000000001 +1f00fffd00010000000001146058e4a0 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd40000000000000000000000 +00000000000000011f00fffd00010000 +000001146059f642598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd4 +00000cd5000000000000002100000600 +01000000000016000000000cd4000000 +00000000000000000000000000000001 +1f00fffd00010000000001146059f642 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd50000000000000000000000 +00000000000000011f00fffd00010000 +00000114605a283e598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd5 +00000cd6000000000000002100000600 +01000000000016000000000cd5000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605a283e +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd60000000000000000000000 +00000000000000011f00fffd00010000 +00000114605b47c2598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd6 +00000cd7000000000000002100000600 +01000000000016000000000cd6000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605b47c2 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd70000000000000000000000 +00000000000000011f00fffd00010000 +00000114605b79bf598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd7 +00000cd8000000000000002100000600 +01000000000016000000000cd7000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605b79bf +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd80000000000000000000000 +00000000000000011f00fffd00010000 +00000114605c9943598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd8 +00000cd9000000000000002100000600 +01000000000016000000000cd8000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605c9943 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cd90000000000000000000000 +00000000000000011f00fffd00010000 +00000114605ccb40598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cd9 +00000cda000000000000002100000600 +01000000000016000000000cd9000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605ccb40 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cda0000000000000000000000 +00000000000000011f00fffd00010000 +00000114605deac4598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cda +00000cdb000000000000002100000600 +01000000000016000000000cda000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605deac4 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cdb0000000000000000000000 +00000000000000011f00fffd00010000 +00000114605e1cc0598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cdb +00000cdc000000000000002100000600 +01000000000016000000000cdb000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605e1cc0 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cdc0000000000000000000000 +00000000000000011f00fffd00010000 +00000114605efb3a598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cdc +00000cdd000000000000002100000600 +01000000000016000000000cdc000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605efb3a +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cdd0000000000000000000000 +00000000000000011f00fffd00010000 +00000114605f6e40598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cdd +00000cde000000000000002100000600 +01000000000016000000000cdd000000 +00000000000000000000000000000001 +1f00fffd0001000000000114605f6e40 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cde0000000000000000000000 +00000000000000011f00fffd00010000 +0000011460604cbb598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cde +00000cdf000000000000002100000600 +01000000000016000000000cde000000 +00000000000000000000000000000001 +1f00fffd000100000000011460604cbb +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000cdf0000000000000000000000 +00000000000000011f00fffd00010000 +000001146060bfc0598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000cdf +00000ce0000000000000002100000600 +01000000000016000000000cdf000000 +00000000000000000000000000000001 +1f00fffd00010000000001146060bfc0 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000ce00000000000000000000000 +00000000000000011f00fffd00010000 +0000011460619e3b598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000ce0 +00000ce1000000000000002100000600 +01000000000016000000000ce0000000 +00000000000000000000000000000001 +1f00fffd000100000000011460619e3b +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000ce10000000000000000000000 +00000000000000011f00fffd00010000 +0000011460621140598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b50000029000000ce1 +00000ce2000000000000002100000600 +01000000000016000000000ce1000000 +00000000000000000000000000000001 +1f00fffd000100000000011460621140 +598e0a83000000000101030803010001 +acffb409bcc939f831f7a1e5ec88f7a5 +9255ec53040be432027390a4ce896d6f +9086f3c5e177fbfe118163aaec7af146 +2c47945944c4e2c026be5e98bbcded25 +978272e1e3e079c5094d573f0e83c92f +02b32d3513b1550b826929c80dd0f92c +ac966d17769fd5867b647c3f38029abd +c48152eb8f207159ecc5d232c7c1537c +79f4b7ac28ff11682f21681bf6d6aba5 +55032bf6f9f036beb2aaa5b3778d6eeb +fba6bf9ea191be4ab0caea759e2f773a +1f9029c73ecb8d5735b9321db085f1b8 +e2d8038fe2941992548cee0d67dd4547 +e11dd63af9c9fc1c5466fb684cf009d7 +197c2cf79e792ab501e6a8a1ca519af2 +cb9b5f6367e94c0d47502451357be1b5 +00000021000006000100000000001600 +0000000ce20000000000000000000000 +00000000000000011f00fffd00010000 +000001146062efbb598e0a8300000000 +0101030803010001acffb409bcc939f8 +31f7a1e5ec88f7a59255ec53040be432 +027390a4ce896d6f9086f3c5e177fbfe +118163aaec7af1462c47945944c4e2c0 +26be5e98bbcded25978272e1e3e079c5 +094d573f0e83c92f02b32d3513b1550b +826929c80dd0f92cac966d17769fd586 +7b647c3f38029abdc48152eb8f207159 +ecc5d232c7c1537c79f4b7ac28ff1168 +2f21681bf6d6aba555032bf6f9f036be +b2aaa5b3778d6eebfba6bf9ea191be4a +b0caea759e2f773a1f9029c73ecb8d57 +35b9321db085f1b8e2d8038fe2941992 +548cee0d67dd4547e11dd63af9c9fc1c +5466fb684cf009d7197c2cf79e792ab5 +01e6a8a1ca519af2cb9b5f6367e94c0d +47502451357be1b5 diff --git a/bin/tests/system/journal/ns1/maxjournal.jnl.saved b/bin/tests/system/journal/ns1/maxjournal.jnl.saved new file mode 100644 index 0000000..7c79e5c Binary files /dev/null and b/bin/tests/system/journal/ns1/maxjournal.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/maxjournal2.jnl.saved b/bin/tests/system/journal/ns1/maxjournal2.jnl.saved new file mode 100644 index 0000000..e200905 Binary files /dev/null and b/bin/tests/system/journal/ns1/maxjournal2.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/named.conf.in b/bin/tests/system/journal/ns1/named.conf.in new file mode 100644 index 0000000..fc16127 --- /dev/null +++ b/bin/tests/system/journal/ns1/named.conf.in @@ -0,0 +1,98 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation auto; + bindkeys-file "../../../../../bind.keys"; + minimal-responses no; + recursion no; + notify yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone . { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +zone changed { + type primary; + update-policy local; + file "changed.db"; +}; + +zone unchanged { + type primary; + update-policy local; + file "unchanged.db"; +}; + +zone changed2 { + type primary; + update-policy local; + file "changed2.db"; +}; + +zone unchanged2 { + type primary; + update-policy local; + file "unchanged2.db"; +}; + +zone hdr1d1d2d1d2 { + type primary; + update-policy local; + file "d1212.db"; +}; + +zone hdr1d2d1d2d1 { + type primary; + update-policy local; + file "d2121.db"; +}; + +zone ixfr { + type primary; + ixfr-from-differences yes; + file "ixfr.db"; +}; + +zone maxjournal { + type primary; + max-journal-size 1k; + update-policy local; + file "maxjournal.db"; +}; + +zone maxjournal2 { + type primary; + max-journal-size 1k; + update-policy local; + file "maxjournal2.db"; +}; diff --git a/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved b/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved new file mode 100644 index 0000000..f7885d9 Binary files /dev/null and b/bin/tests/system/journal/ns1/unchanged.ver1.jnl.saved differ diff --git a/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved b/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved new file mode 100644 index 0000000..d974be4 Binary files /dev/null and b/bin/tests/system/journal/ns1/unchanged.ver2.jnl.saved differ diff --git a/bin/tests/system/journal/ns2/managed-keys.bind.in b/bin/tests/system/journal/ns2/managed-keys.bind.in new file mode 100644 index 0000000..2139706 --- /dev/null +++ b/bin/tests/system/journal/ns2/managed-keys.bind.in @@ -0,0 +1,14 @@ +$ORIGIN . +$TTL 0 ; 0 seconds +@ IN SOA . . ( + 29 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + KEYDATA 20210611104535 19700101000000 19700101000000 0 0 0 ( + + ) ; ZSK; alg = 0; key id = 0 + ; next refresh: Fri, 11 Jun 2021 10:45:35 GMT + ; no trust diff --git a/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in b/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in new file mode 100644 index 0000000..01c1d47 Binary files /dev/null and b/bin/tests/system/journal/ns2/managed-keys.bind.jnl.in differ diff --git a/bin/tests/system/journal/ns2/named.conf.in b/bin/tests/system/journal/ns2/named.conf.in new file mode 100644 index 0000000..e0fd9d8 --- /dev/null +++ b/bin/tests/system/journal/ns2/named.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + dnssec-validation auto; + bindkeys-file "../../../../../bind.keys"; + minimal-responses no; + recursion no; + notify yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone . { + type hint; + file "../../_common/root.hint.blackhole"; +}; diff --git a/bin/tests/system/journal/setup.sh b/bin/tests/system/journal/setup.sh new file mode 100644 index 0000000..e50cd82 --- /dev/null +++ b/bin/tests/system/journal/setup.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +cp ns1/generic.db.in ns1/changed.db +cp ns1/changed.ver1.jnl.saved ns1/changed.db.jnl + +cp ns1/generic.db.in ns1/unchanged.db +cp ns1/unchanged.ver1.jnl.saved ns1/unchanged.db.jnl + +cp ns1/generic.db.in ns1/changed2.db +cp ns1/changed.ver2.jnl.saved ns1/changed2.db.jnl + +cp ns1/generic.db.in ns1/unchanged2.db +cp ns1/unchanged.ver2.jnl.saved ns1/unchanged2.db.jnl + +cp ns1/ixfr.db.in ns1/ixfr.db +cp ns1/ixfr.ver1.jnl.saved ns1/ixfr.db.jnl + +cp ns1/generic.db.in ns1/d1212.db +cp ns1/d1212.jnl.saved ns1/d1212.db.jnl + +cp ns1/generic.db.in ns1/d2121.db +cp ns1/d2121.jnl.saved ns1/d2121.db.jnl + +cp ns1/generic.db.in ns1/maxjournal.db +cp ns1/maxjournal.jnl.saved ns1/maxjournal.db.jnl + +cp ns1/generic.db.in ns1/maxjournal2.db +cp ns1/maxjournal2.jnl.saved ns1/maxjournal2.db.jnl + +cp ns1/managed-keys.bind.in ns1/managed-keys.bind +$PERL ../fromhex.pl ns1/managed-keys.bind.jnl + +copy_setports ns2/named.conf.in ns2/named.conf +cp ns2/managed-keys.bind.in ns2/managed-keys.bind +cp ns2/managed-keys.bind.jnl.in ns2/managed-keys.bind.jnl diff --git a/bin/tests/system/journal/tests.sh b/bin/tests/system/journal/tests.sh new file mode 100644 index 0000000..79b90ba --- /dev/null +++ b/bin/tests/system/journal/tests.sh @@ -0,0 +1,255 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +dig_with_opts() { + "$DIG" @10.53.0.1 -p "$PORT" +tcp "$@" +} + +rndc_with_opts() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +status=0 +n=0 + +n=$((n + 1)) +echo_i "check outdated journal rolled forward (dynamic) ($n)" +ret=0 +dig_with_opts changed soa >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010902' dig.out.test$n >/dev/null || ret=1 +grep 'zone changed/IN: journal rollforward completed successfully using old journal format' ns1/named.run >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check outdated empty journal did not cause an error (dynamic) ($n)" +ret=0 +dig_with_opts unchanged soa >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010901' dig.out.test$n >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check outdated journals were updated or removed (dynamic) ($n)" +ret=0 +cat -v ns1/changed.db.jnl | grep "BIND LOG V9.2" >/dev/null || ret=1 +[ -f ns1/unchanged.db.jnl ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check updated journal has correct RR count (dynamic) ($n)" +ret=0 +$JOURNALPRINT -x ns1/changed.db.jnl | grep "rrcount 3 " >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check new-format journal rolled forward (dynamic) ($n)" +ret=0 +dig_with_opts changed2 soa >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010902' dig.out.test$n >/dev/null || ret=1 +grep 'zone changed2/IN: journal rollforward completed successfully: success' ns1/named.run >/dev/null || ret=1 +grep 'zone changed2/IN: journal rollforward completed successfully using old journal format' ns1/named.run >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check new-format empty journal did not cause error (dynamic) ($n)" +ret=0 +dig_with_opts unchanged2 soa >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010901' dig.out.test$n >/dev/null || ret=1 +grep 'zone unchanged2/IN: journal rollforward completed successfully' ns1/named.run >/dev/null && ret=1 +grep 'zone unchanged2/IN: journal rollforward completed successfully using old journal format' ns1/named.run >/dev/null && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check new-format journals were updated or removed (dynamic) ($n)" +ret=0 +cat -v ns1/changed2.db.jnl | grep "BIND LOG V9.2" >/dev/null || ret=1 +[ -f ns1/unchanged2.db.jnl ] && ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check outdated up-to-date journal succeeded (ixfr-from-differences) ($n)" +ret=0 +dig_with_opts -t soa ixfr >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010902' dig.out.test$n >/dev/null || ret=1 +grep 'zone ixfr/IN: journal rollforward completed successfully using old journal format: up to date' ns1/named.run >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check outdated journal was updated (ixfr-from-differences) ($n)" +ret=0 +cat -v ns1/ixfr.db.jnl | grep "BIND LOG V9.2" >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check journal with mixed headers succeeded (version 1,2,1,2) ($n)" +ret=0 +dig_with_opts -t soa hdr1d1d2d1d2 >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010905' dig.out.test$n >/dev/null || ret=1 +grep 'zone hdr1d1d2d1d2/IN: journal rollforward completed successfully using old journal format: success' ns1/named.run >/dev/null || ret=1 +grep 'zone_journal_compact: zone hdr1d1d2d1d2/IN: repair full journal' ns1/named.run >/dev/null || ret=1 +grep 'hdr1d1d2d1d2/IN: dns_journal_compact: success' ns1/named.run >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check journal with mixed headers was updated (version 1,2,1,2) ($n)" +ret=0 +[ $($JOURNALPRINT -x ns1/d1212.jnl.saved | grep -c "version 1") -eq 2 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d1212.jnl.saved | grep -c "version 2") -eq 2 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d1212.db.jnl | grep -c "version 1") -eq 0 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d1212.db.jnl | grep -c "version 2") -eq 4 ] || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check journal with mixed headers succeeded (version 2,1,2,1) ($n)" +ret=0 +dig_with_opts -t soa hdr1d2d1d2d1 >dig.out.test$n +grep 'status: NOERROR' dig.out.test$n >/dev/null || ret=1 +grep '2012010905' dig.out.test$n >/dev/null || ret=1 +grep 'zone hdr1d2d1d2d1/IN: journal rollforward completed successfully using old journal format: success' ns1/named.run >/dev/null || ret=1 +grep 'zone_journal_compact: zone hdr1d2d1d2d1/IN: repair full journal' ns1/named.run >/dev/null || ret=1 +grep 'zone hdr1d2d1d2d1/IN: dns_journal_compact: success' ns1/named.run >/dev/null || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check journal with mixed headers was updated (version 2,1,2,1) ($n)" +ret=0 +[ $($JOURNALPRINT -x ns1/d2121.jnl.saved | grep -c "version 1") -eq 2 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d2121.jnl.saved | grep -c "version 2") -eq 2 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d2121.db.jnl | grep -c "version 1") -eq 0 ] || ret=1 +[ $($JOURNALPRINT -x ns1/d2121.db.jnl | grep -c "version 2") -eq 4 ] || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check there are no journals left un-updated ($n)" +ret=0 +c1=$(cat -v ns1/*.jnl | grep -c "BIND LOG V9") +c2=$(cat -v ns1/*.jnl | grep -c "BIND LOG V9.2") +[ ${c1} -eq ${c2} ] || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check that journal with mixed headers can be compacted (version 1,2,1,2) ($n)" +ret=0 +journal=ns1/d1212.jnl.saved +seriallist=$($JOURNALPRINT -x $journal | awk '$1 == "Transaction:" { print $11 }') +for serial in $seriallist; do + cp $journal tmp.jnl + $JOURNALPRINT -c $serial tmp.jnl || ret=1 +done +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check that journal with mixed headers can be compacted (version 2,1,2,1) ($n)" +ret=0 +journal=ns1/d2121.jnl.saved +seriallist=$($JOURNALPRINT -x $journal | awk '$1 == "Transaction:" { print $11 }') +for serial in $seriallist; do + cp ns1/d1212.jnl.saved tmp.jnl + $JOURNALPRINT -c $serial tmp.jnl || ret=1 +done +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check upgrade of managed-keys.bind.jnl succeeded($n)" +ret=0 +$JOURNALPRINT ns1/managed-keys.bind.jnl >journalprint.out.test$n +lines=$(awk '$1 == "add" && $5 == "SOA" && $8 == "3297" { print }' journalprint.out.test$n | wc -l) +test $lines -eq 1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check journal downgrade/upgrade ($n)" +ret=0 +cp ns1/changed.db.jnl ns1/temp.jnl +$JOURNALPRINT -d ns1/temp.jnl +[ $($JOURNALPRINT -x ns1/temp.jnl | grep -c "version 1") -eq 1 ] || ret=1 +$JOURNALPRINT -x ns1/temp.jnl | grep -q "Header version = 1" || ret=1 +$JOURNALPRINT -u ns1/temp.jnl +$JOURNALPRINT -x ns1/temp.jnl | grep -q "Header version = 2" || ret=1 +[ $($JOURNALPRINT -x ns1/temp.jnl | grep -c "version 2") -eq 1 ] || ret=1 +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check max-journal-size works after journal update ($n)" +ret=0 +# journal was repaired, it should still be big +[ $(wc -c &1 | grep -q "Offset mismatch" && ret=1 +done +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that journal is applied to zone with keydata placeholder record" +ret=0 +grep 'managed-keys-zone: journal rollforward completed successfully: up to date' ns2/named.run >/dev/null 2>&1 || ret=1 +[ $ret -eq 0 ] || echo_i "failed" + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/journal/tests_sh_journal.py b/bin/tests/system/journal/tests_sh_journal.py new file mode 100644 index 0000000..3f506ef --- /dev/null +++ b/bin/tests/system/journal/tests_sh_journal.py @@ -0,0 +1,28 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "journalprint.out.*", + "tmp.jnl", + "ns*/*.db", + "ns*/*.jnl", + "ns1/managed-keys.bind", + "ns2/managed-keys.bind", + ] +) + + +def test_journal(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/kasp.sh b/bin/tests/system/kasp.sh new file mode 100644 index 0000000..636d3c4 --- /dev/null +++ b/bin/tests/system/kasp.sh @@ -0,0 +1,1304 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Common configuration data for kasp system tests, to be sourced into +# other shell scripts. +# + +# shellcheck source=conf.sh +. ../conf.sh + +############################################################################### +# Constants # +############################################################################### +DEFAULT_TTL=300 + +############################################################################### +# Query properties # +############################################################################### +TSIG="" +SHA1="FrSt77yPTFx6hTs4i2tKLB9LmE0=" +SHA224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==" +SHA256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=" +VIEW1="YPfMoAk6h+3iN8MDRQC004iSNHY=" +VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8=" +VIEW3="C1Azf+gGPMmxrUg/WQINP6eV9Y0=" +MINDEPTH=1 +MAXDEPTH=3 + +############################################################################### +# Key properties # +############################################################################### +# ID +# BASEFILE +# EXPECT +# ROLE +# KSK +# ZSK +# FLAGS +# LIFETIME +# ALG_NUM +# ALG_STR +# ALG_LEN +# CREATED +# PUBLISHED +# ACTIVE +# RETIRED +# REVOKED +# REMOVED +# GOAL +# STATE_DNSKEY +# STATE_ZRRSIG +# STATE_KRRSIG +# STATE_DS +# EXPECT_ZRRSIG +# EXPECT_KRRSIG +# LEGACY +# PRIVATE +# PRIVKEY_STAT +# PUBKEY_STAT +# STATE_STAT +# FLAGS +# KEYDIR + +key_key() { + echo "${1}__${2}" +} + +key_get() { + eval "echo \${$(key_key "$1" "$2")}" +} + +key_set() { + eval "$(key_key "$1" "$2")='$3'" +} + +key_stat() { + $PERL -e 'print((stat @ARGV[0])[9] . "\n");' "$1" +} + +# Save certain values in the KEY array. +key_save() { + # Save key id. + key_set "$1" ID "$KEY_ID" + key_set "$1" RID "$KEY_RID" + # Save base filename. + key_set "$1" BASEFILE "$BASE_FILE" + # Save creation date. + key_set "$1" CREATED "${KEY_CREATED}" + # Save key change time. + key_set "$1" PRIVKEY_STAT $(key_stat "${BASE_FILE}.private") + key_set "$1" PUBKEY_STAT $(key_stat "${BASE_FILE}.key") + key_set "$1" STATE_STAT $(key_stat "${BASE_FILE}.state") +} + +# Clear key state. +# +# This will update either the KEY1, KEY2, or KEY3 array. +key_clear() { + key_set "$1" "ID" 'no' + key_set "$1" "RID" 'no' + key_set "$1" "IDPAD" 'no' + key_set "$1" "EXPECT" 'no' + key_set "$1" "ROLE" 'none' + key_set "$1" "KSK" 'no' + key_set "$1" "ZSK" 'no' + key_set "$1" "FLAGS" '0' + key_set "$1" "LIFETIME" 'none' + key_set "$1" "ALG_NUM" '0' + key_set "$1" "ALG_STR" 'none' + key_set "$1" "ALG_LEN" '0' + key_set "$1" "CREATED" '0' + key_set "$1" "PUBLISHED" 'none' + key_set "$1" "SYNCPUBLISH" 'none' + key_set "$1" "ACTIVE" 'none' + key_set "$1" "RETIRED" 'none' + key_set "$1" "REVOKED" 'none' + key_set "$1" "REMOVED" 'none' + key_set "$1" "GOAL" 'none' + key_set "$1" "STATE_DNSKEY" 'none' + key_set "$1" "STATE_KRRSIG" 'none' + key_set "$1" "STATE_ZRRSIG" 'none' + key_set "$1" "STATE_DS" 'none' + key_set "$1" "EXPECT_ZRRSIG" 'no' + key_set "$1" "EXPECT_KRRSIG" 'no' + key_set "$1" "LEGACY" 'no' + key_set "$1" "PRIVATE" 'yes' + key_set "$1" "PRIVKEY_STAT" '0' + key_set "$1" "PUBKEY_STAT" '0' + key_set "$1" "STATE_STAT" '0' + key_set "$1" "KEYDIR" 'none' +} + +# Start clear. +# There can be at most 4 keys at the same time during a rollover: +# 2x KSK, 2x ZSK +key_clear "KEY1" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +############################################################################### +# Utilities # +############################################################################### + +# Call dig with default options. +_dig_with_opts() { + + if [ -n "$TSIG" ]; then + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@" + else + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" + fi +} + +# RNDC. +_rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +# Print IDs of keys used for generating RRSIG records for RRsets of type $1, +# matching algorithm number $2, found in dig output file $3. +# If $2 is equal to 0, any algorithm matches. +get_keys_which_signed() { + _qtype=$1 + _alg=$2 + _output=$3 + # The key ID is the 11th column of the RRSIG record line. + if [ "$_alg" = "0" ]; then + awk -v qt="$_qtype" '$4 == "RRSIG" && $5 == qt {print $11}' <"$_output" + else + awk -v alg="$_alg" -v qt="$_qtype" '$4 == "RRSIG" && $5 == qt && $6 == alg {print $11}' <"$_output" + fi +} + +# Get the key ids from key files for zone $2 in directory $1. +get_keyids() { + _dir=$1 + _zone=$2 + _regex="K${_zone}.+*+*.key" + + find "${_dir}" -mindepth $MINDEPTH -maxdepth $MAXDEPTH -name "${_regex}" | sed "s,.*/K${_zone}.+\([0-9]\{3\}\)+\([0-9]\{5\}\).key,\2," +} + +# By default log errors and don't quit immediately. +_log=1 +_log_error() { + test $_log -eq 1 && echo_i "error: $1" + ret=$((ret + 1)) +} +disable_logerror() { + _log=0 +} +enable_logerror() { + _log=1 +} + +# Set server key-directory ($1) and address ($2) for testing keys. +set_server() { + DIR=$1 + SERVER=$2 +} +# Set zone name for testing keys. +set_zone() { + ZONE=$1 + DYNAMIC="no" +} +# By default zones are considered static. +# When testing dynamic zones, call 'set_dynamic' after 'set_zone'. +set_dynamic() { + DYNAMIC="yes" +} + +# Set policy settings (name $1, number of keys $2, dnskey ttl $3). +set_policy() { + POLICY=$1 + NUM_KEYS=$2 + DNSKEY_TTL=$3 + KEYFILE_TTL=$3 + CDS_DELETE="no" + CDS_SHA256="yes" + CDS_SHA384="no" + CDNSKEY="yes" +} +# By default policies are considered to be secure. +# If a zone sets its policy to "insecure", call 'set_cdsdelete' to tell the +# system test to expect a CDS and CDNSKEY Delete record. +set_cdsdelete() { + CDS_DELETE="yes" +} + +# Set key properties for testing keys. +# $1: Key to update (KEY1, KEY2, ...) +# $2: Value +set_keyrole() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "ROLE" "$2" + key_set "$1" "KSK" "no" + key_set "$1" "ZSK" "no" + key_set "$1" "FLAGS" "0" + + test "$2" = "ksk" && key_set "$1" "KSK" "yes" + test "$2" = "ksk" && key_set "$1" "FLAGS" "257" + + test "$2" = "zsk" && key_set "$1" "ZSK" "yes" + test "$2" = "zsk" && key_set "$1" "FLAGS" "256" + + test "$2" = "csk" && key_set "$1" "KSK" "yes" + test "$2" = "csk" && key_set "$1" "ZSK" "yes" + test "$2" = "csk" && key_set "$1" "FLAGS" "257" + + return 0 +} +set_keylifetime() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "LIFETIME" "$2" +} +# The algorithm value consists of three parts: +# $2: Algorithm (number) +# $3: Algorithm (string-format) +# $4: Algorithm length +set_keyalgorithm() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "ALG_NUM" "$2" + key_set "$1" "ALG_STR" "$3" + key_set "$1" "ALG_LEN" "$4" +} +set_keysigning() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "EXPECT_KRRSIG" "$2" +} +set_zonesigning() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "EXPECT_ZRRSIG" "$2" +} + +# Set key timing metadata. Set to "none" to unset. +# $1: Key to update (KEY1, KEY2, ...) +# $2: Time to update (PUBLISHED, SYNCPUBLISH, ACTIVE, RETIRED, REVOKED, or REMOVED). +# $3: Value +set_keytime() { + key_set "$1" "EXPECT" "yes" + key_set "$1" "$2" "$3" +} + +# Set key timing metadata to a value plus additional time. +# $1: Key to update (KEY1, KEY2, ...) +# $2: Time to update (PUBLISHED, SYNCPUBLISH, ACTIVE, RETIRED, REVOKED, or REMOVED). +# $3: Value +# $4: Additional time. +set_addkeytime() { + if [ -x "$PYTHON" ]; then + # Convert "%Y%m%d%H%M%S" format to epoch seconds. + # Then, add the additional time (can be negative). + _value=$3 + _plus=$4 + $PYTHON >python.out.$ZONE.$1.$2 <"${ZONE}.${KEY_ID}.${_alg_num}.created" || _log_error "mismatch created comment in $KEY_FILE" + KEY_CREATED=$(awk '{print $3}' <"${ZONE}.${KEY_ID}.${_alg_num}.created") + + if [ "$_private" = "yes" ]; then + grep "Created: ${KEY_CREATED}" "$PRIVATE_FILE" >/dev/null || _log_error "mismatch created in $PRIVATE_FILE" + fi + if [ "$_legacy" = "no" ]; then + grep "Generated: ${KEY_CREATED}" "$STATE_FILE" >/dev/null || _log_error "mismatch generated in $STATE_FILE" + fi + + test $_log -eq 1 && echo_i "check key file $BASE_FILE" + + # Check the public key file. + grep "This is a ${_role2} key, keyid ${_key_id}, for ${_zone}." "$KEY_FILE" >/dev/null || _log_error "mismatch top comment in $KEY_FILE" + grep "${_zone}\. ${_dnskey_ttl} IN DNSKEY ${_flags} 3 ${_alg_num}" "$KEY_FILE" >/dev/null || _log_error "mismatch DNSKEY record in $KEY_FILE" + # Now check the private key file. + if [ "$_private" = "yes" ]; then + grep "Private-key-format: v1.3" "$PRIVATE_FILE" >/dev/null || _log_error "mismatch private key format in $PRIVATE_FILE" + grep "Algorithm: ${_alg_num} (${_alg_string})" "$PRIVATE_FILE" >/dev/null || _log_error "mismatch algorithm in $PRIVATE_FILE" + fi + # Now check the key state file. + if [ "$_legacy" = "no" ]; then + grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" >/dev/null || _log_error "mismatch top comment in $STATE_FILE" + if [ "$_lifetime" = "none" ]; then + grep "Lifetime: " "$STATE_FILE" >/dev/null && _log_error "unexpected lifetime in $STATE_FILE" + else + grep "Lifetime: ${_lifetime}" "$STATE_FILE" >/dev/null || _log_error "mismatch lifetime in $STATE_FILE" + fi + grep "Algorithm: ${_alg_num}" "$STATE_FILE" >/dev/null || _log_error "mismatch algorithm in $STATE_FILE" + grep "Length: ${_length}" "$STATE_FILE" >/dev/null || _log_error "mismatch length in $STATE_FILE" + grep "KSK: ${_ksk}" "$STATE_FILE" >/dev/null || _log_error "mismatch ksk in $STATE_FILE" + grep "ZSK: ${_zsk}" "$STATE_FILE" >/dev/null || _log_error "mismatch zsk in $STATE_FILE" + + # Check key states. + if [ "$_goal" = "none" ]; then + grep "GoalState: " "$STATE_FILE" >/dev/null && _log_error "unexpected goal state in $STATE_FILE" + else + grep "GoalState: ${_goal}" "$STATE_FILE" >/dev/null || _log_error "mismatch goal state in $STATE_FILE" + fi + + if [ "$_state_dnskey" = "none" ]; then + grep "DNSKEYState: " "$STATE_FILE" >/dev/null && _log_error "unexpected dnskey state in $STATE_FILE" + grep "DNSKEYChange: " "$STATE_FILE" >/dev/null && _log_error "unexpected dnskey change in $STATE_FILE" + else + grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" >/dev/null || _log_error "mismatch dnskey state in $STATE_FILE" + grep "DNSKEYChange: " "$STATE_FILE" >/dev/null || _log_error "mismatch dnskey change in $STATE_FILE" + fi + + if [ "$_state_zrrsig" = "none" ]; then + grep "ZRRSIGState: " "$STATE_FILE" >/dev/null && _log_error "unexpected zrrsig state in $STATE_FILE" + grep "ZRRSIGChange: " "$STATE_FILE" >/dev/null && _log_error "unexpected zrrsig change in $STATE_FILE" + else + grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" >/dev/null || _log_error "mismatch zrrsig state in $STATE_FILE" + grep "ZRRSIGChange: " "$STATE_FILE" >/dev/null || _log_error "mismatch zrrsig change in $STATE_FILE" + fi + + if [ "$_state_krrsig" = "none" ]; then + grep "KRRSIGState: " "$STATE_FILE" >/dev/null && _log_error "unexpected krrsig state in $STATE_FILE" + grep "KRRSIGChange: " "$STATE_FILE" >/dev/null && _log_error "unexpected krrsig change in $STATE_FILE" + else + grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" >/dev/null || _log_error "mismatch krrsig state in $STATE_FILE" + grep "KRRSIGChange: " "$STATE_FILE" >/dev/null || _log_error "mismatch krrsig change in $STATE_FILE" + fi + + if [ "$_state_ds" = "none" ]; then + grep "DSState: " "$STATE_FILE" >/dev/null && _log_error "unexpected ds state in $STATE_FILE" + grep "DSChange: " "$STATE_FILE" >/dev/null && _log_error "unexpected ds change in $STATE_FILE" + else + grep "DSState: ${_state_ds}" "$STATE_FILE" >/dev/null || _log_error "mismatch ds state in $STATE_FILE" + grep "DSChange: " "$STATE_FILE" >/dev/null || _log_error "mismatch ds change in $STATE_FILE" + fi + fi + + return 0 +} + +# Check the key timing metadata for key $1. +check_timingmetadata() { + _dir=$(key_get "$1" KEYDIR) + if [ "$_dir" = "none" ]; then + _dir="$DIR" + fi + _zone="$ZONE" + _key_idpad=$(key_get "$1" ID) + _key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//') + _alg_num=$(key_get "$1" ALG_NUM) + _alg_numpad=$(printf "%03d" "$_alg_num") + + _published=$(key_get "$1" PUBLISHED) + _active=$(key_get "$1" ACTIVE) + _retired=$(key_get "$1" RETIRED) + _revoked=$(key_get "$1" REVOKED) + _removed=$(key_get "$1" REMOVED) + + _goal=$(key_get "$1" GOAL) + _state_dnskey=$(key_get "$1" STATE_DNSKEY) + _state_zrrsig=$(key_get "$1" STATE_ZRRSIG) + _state_krrsig=$(key_get "$1" STATE_KRRSIG) + _state_ds=$(key_get "$1" STATE_DS) + + _base_file=$(key_get "$1" BASEFILE) + _key_file="${_base_file}.key" + _private_file="${_base_file}.private" + _state_file="${_base_file}.state" + _legacy=$(key_get "$1" LEGACY) + _private=$(key_get "$1" PRIVATE) + + _published=$(key_get "$1" PUBLISHED) + _syncpublish=$(key_get "$1" SYNCPUBLISH) + _active=$(key_get "$1" ACTIVE) + _retired=$(key_get "$1" RETIRED) + _revoked=$(key_get "$1" REVOKED) + _removed=$(key_get "$1" REMOVED) + + # Check timing metadata. + n=$((n + 1)) + echo_i "check key timing metadata for key $1 id ${_key_id} zone ${ZONE} ($n)" + ret=0 + + if [ "$_published" = "none" ]; then + grep "; Publish:" "${_key_file}" >/dev/null && _log_error "unexpected publish comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "Publish:" "${_private_file}" >/dev/null && _log_error "unexpected publish in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "Published: " "${_state_file}" >/dev/null && _log_error "unexpected publish in ${_state_file}" + fi + else + grep "; Publish: $_published" "${_key_file}" >/dev/null || _log_error "mismatch publish comment in ${_key_file} (expected ${_published})" + if [ "$_private" = "yes" ]; then + grep "Publish: $_published" "${_private_file}" >/dev/null || _log_error "mismatch publish in ${_private_file} (expected ${_published})" + fi + if [ "$_legacy" = "no" ]; then + grep "Published: $_published" "${_state_file}" >/dev/null || _log_error "mismatch publish in ${_state_file} (expected ${_published})" + fi + fi + + if [ "$_syncpublish" = "none" ]; then + grep "; SyncPublish:" "${_key_file}" >/dev/null && _log_error "unexpected syncpublish comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "SyncPublish:" "${_private_file}" >/dev/null && _log_error "unexpected syncpublish in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "PublishCDS: " "${_state_file}" >/dev/null && _log_error "unexpected syncpublish in ${_state_file}" + fi + else + grep "; SyncPublish: $_syncpublish" "${_key_file}" >/dev/null || _log_error "mismatch syncpublish comment in ${_key_file} (expected ${_syncpublish})" + if [ "$_private" = "yes" ]; then + grep "SyncPublish: $_syncpublish" "${_private_file}" >/dev/null || _log_error "mismatch syncpublish in ${_private_file} (expected ${_syncpublish})" + fi + if [ "$_legacy" = "no" ]; then + grep "PublishCDS: $_syncpublish" "${_state_file}" >/dev/null || _log_error "mismatch syncpublish in ${_state_file} (expected ${_syncpublish})" + fi + fi + + if [ "$_active" = "none" ]; then + grep "; Activate:" "${_key_file}" >/dev/null && _log_error "unexpected active comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "Activate:" "${_private_file}" >/dev/null && _log_error "unexpected active in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "Active: " "${_state_file}" >/dev/null && _log_error "unexpected active in ${_state_file}" + fi + else + grep "; Activate: $_active" "${_key_file}" >/dev/null || _log_error "mismatch active comment in ${_key_file} (expected ${_active})" + if [ "$_private" = "yes" ]; then + grep "Activate: $_active" "${_private_file}" >/dev/null || _log_error "mismatch active in ${_private_file} (expected ${_active})" + fi + if [ "$_legacy" = "no" ]; then + grep "Active: $_active" "${_state_file}" >/dev/null || _log_error "mismatch active in ${_state_file} (expected ${_active})" + fi + fi + + if [ "$_retired" = "none" ]; then + grep "; Inactive:" "${_key_file}" >/dev/null && _log_error "unexpected retired comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "Inactive:" "${_private_file}" >/dev/null && _log_error "unexpected retired in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "Retired: " "${_state_file}" >/dev/null && _log_error "unexpected retired in ${_state_file}" + fi + else + grep "; Inactive: $_retired" "${_key_file}" >/dev/null || _log_error "mismatch retired comment in ${_key_file} (expected ${_retired})" + if [ "$_private" = "yes" ]; then + grep "Inactive: $_retired" "${_private_file}" >/dev/null || _log_error "mismatch retired in ${_private_file} (expected ${_retired})" + fi + if [ "$_legacy" = "no" ]; then + grep "Retired: $_retired" "${_state_file}" >/dev/null || _log_error "mismatch retired in ${_state_file} (expected ${_retired})" + fi + fi + + if [ "$_revoked" = "none" ]; then + grep "; Revoke:" "${_key_file}" >/dev/null && _log_error "unexpected revoked comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "Revoke:" "${_private_file}" >/dev/null && _log_error "unexpected revoked in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "Revoked: " "${_state_file}" >/dev/null && _log_error "unexpected revoked in ${_state_file}" + fi + else + grep "; Revoke: $_revoked" "${_key_file}" >/dev/null || _log_error "mismatch revoked comment in ${_key_file} (expected ${_revoked})" + if [ "$_private" = "yes" ]; then + grep "Revoke: $_revoked" "${_private_file}" >/dev/null || _log_error "mismatch revoked in ${_private_file} (expected ${_revoked})" + fi + if [ "$_legacy" = "no" ]; then + grep "Revoked: $_revoked" "${_state_file}" >/dev/null || _log_error "mismatch revoked in ${_state_file} (expected ${_revoked})" + fi + fi + + if [ "$_removed" = "none" ]; then + grep "; Delete:" "${_key_file}" >/dev/null && _log_error "unexpected removed comment in ${_key_file}" + if [ "$_private" = "yes" ]; then + grep "Delete:" "${_private_file}" >/dev/null && _log_error "unexpected removed in ${_private_file}" + fi + if [ "$_legacy" = "no" ]; then + grep "Removed: " "${_state_file}" >/dev/null && _log_error "unexpected removed in ${_state_file}" + fi + else + grep "; Delete: $_removed" "${_key_file}" >/dev/null || _log_error "mismatch removed comment in ${_key_file} (expected ${_removed})" + if [ "$_private" = "yes" ]; then + grep "Delete: $_removed" "${_private_file}" >/dev/null || _log_error "mismatch removed in ${_private_file} (expected ${_removed})" + fi + if [ "$_legacy" = "no" ]; then + grep "Removed: $_removed" "${_state_file}" >/dev/null || _log_error "mismatch removed in ${_state_file} (expected ${_removed})" + fi + fi + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +check_keytimes() { + # The script relies on Python to set keytimes. + if [ -x "$PYTHON" ]; then + + if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + check_timingmetadata "KEY1" + fi + if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + check_timingmetadata "KEY2" + fi + if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + check_timingmetadata "KEY3" + fi + if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + check_timingmetadata "KEY4" + fi + fi +} + +# Check the key with key id $1 and see if it is unused. +# This requires environment variables to be set. +# +# This will set the following environment variables for testing: +# BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}" +# KEY_FILE="${BASE_FILE}.key" +# PRIVATE_FILE="${BASE_FILE}.private" +# STATE_FILE="${BASE_FILE}.state" +# KEY_ID=$(echo $1 | sed 's/^0\{0,4\}//') +key_unused() { + _dir="$DIR" + _zone="$ZONE" + _key_idpad="$1" + _key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//') + _alg_num="$2" + _alg_numpad=$(printf "%03d" "$_alg_num") + + BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}" + KEY_FILE="${BASE_FILE}.key" + PRIVATE_FILE="${BASE_FILE}.private" + STATE_FILE="${BASE_FILE}.state" + KEY_ID="${_key_id}" + + test $_log -eq 1 && echo_i "key unused $KEY_ID?" + + # Check file existence. + [ -s "$KEY_FILE" ] || ret=1 + [ -s "$PRIVATE_FILE" ] || ret=1 + [ -s "$STATE_FILE" ] || ret=1 + [ "$ret" -eq 0 ] || return 0 + + # Treat keys that have been removed from the zone as unused. + _check_removed=1 + grep "; Created:" "$KEY_FILE" >created.key-${KEY_ID}.test${n} || _check_removed=0 + grep "; Delete:" "$KEY_FILE" >unused.key-${KEY_ID}.test${n} || _check_removed=0 + if [ "$_check_removed" -eq 1 ]; then + _created=$(awk '{print $3}' /dev/null && _log_error "unexpected publish comment in $KEY_FILE" + grep "; Activate:" "$KEY_FILE" >/dev/null && _log_error "unexpected active comment in $KEY_FILE" + grep "; Inactive:" "$KEY_FILE" >/dev/null && _log_error "unexpected retired comment in $KEY_FILE" + grep "; Revoke:" "$KEY_FILE" >/dev/null && _log_error "unexpected revoked comment in $KEY_FILE" + grep "; Delete:" "$KEY_FILE" >/dev/null && _log_error "unexpected removed comment in $KEY_FILE" + + grep "Publish:" "$PRIVATE_FILE" >/dev/null && _log_error "unexpected publish in $PRIVATE_FILE" + grep "Activate:" "$PRIVATE_FILE" >/dev/null && _log_error "unexpected active in $PRIVATE_FILE" + grep "Inactive:" "$PRIVATE_FILE" >/dev/null && _log_error "unexpected retired in $PRIVATE_FILE" + grep "Revoke:" "$PRIVATE_FILE" >/dev/null && _log_error "unexpected revoked in $PRIVATE_FILE" + grep "Delete:" "$PRIVATE_FILE" >/dev/null && _log_error "unexpected removed in $PRIVATE_FILE" + + grep "Published: " "$STATE_FILE" >/dev/null && _log_error "unexpected publish in $STATE_FILE" + grep "Active: " "$STATE_FILE" >/dev/null && _log_error "unexpected active in $STATE_FILE" + grep "Retired: " "$STATE_FILE" >/dev/null && _log_error "unexpected retired in $STATE_FILE" + grep "Revoked: " "$STATE_FILE" >/dev/null && _log_error "unexpected revoked in $STATE_FILE" + grep "Removed: " "$STATE_FILE" >/dev/null && _log_error "unexpected removed in $STATE_FILE" + + return 0 +} + +# Test: dnssec-verify zone $1. +dnssec_verify() { + n=$((n + 1)) + echo_i "dnssec-verify zone ${ZONE} ($n)" + ret=0 + _dig_with_opts "$ZONE" "@${SERVER}" AXFR >dig.out.axfr.test$n || _log_error "dig ${ZONE} AXFR failed" + $VERIFY -z -o "$ZONE" dig.out.axfr.test$n >verify.out.$ZONE.test$n || _log_error "dnssec verify zone $ZONE failed" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Wait for the zone to be signed. +# The apex NSEC record indicates that it is signed. +_wait_for_nsec() { + _dig_with_opts "@${SERVER}" "$ZONE" NSEC >"dig.out.nsec.test$n" || return 1 + grep "NS SOA" "dig.out.nsec.test$n" >/dev/null || return 1 + grep "${ZONE}\..*IN.*RRSIG" "dig.out.nsec.test$n" >/dev/null || return 1 + return 0 +} +wait_for_nsec() { + n=$((n + 1)) + ret=0 + echo_i "wait for ${ZONE} to be signed ($n)" + retry_quiet 10 _wait_for_nsec || _log_error "wait for ${ZONE} to be signed failed" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +check_numkeys() { + _numkeys=$(get_keyids "$DIR" "$ZONE" | wc -l) + test "$_numkeys" -eq "$NUM_KEYS" || return 1 + return 0 +} + +_check_keys() { + ret=0 + _ret=0 + + # Clear key ids. + if [ "$1" != "keep" ]; then + key_set KEY1 ID "no" + key_set KEY2 ID "no" + key_set KEY3 ID "no" + key_set KEY4 ID "no" + fi + + # Check key files. + _ids=$(get_keyids "$DIR" "$ZONE") + for _id in $_ids; do + # There are multiple key files with the same algorithm. + # Check them until a match is found. + ret=0 + echo_i "check key id $_id" + + if [ "no" = "$(key_get KEY1 ID)" ] && [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + ret=0 + check_key "KEY1" "$_id" + test "$ret" -eq 0 && key_save KEY1 && continue + fi + if [ "no" = "$(key_get KEY2 ID)" ] && [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + ret=0 + check_key "KEY2" "$_id" + test "$ret" -eq 0 && key_save KEY2 && continue + fi + if [ "no" = "$(key_get KEY3 ID)" ] && [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + ret=0 + check_key "KEY3" "$_id" + test "$ret" -eq 0 && key_save KEY3 && continue + fi + if [ "no" = "$(key_get KEY4 ID)" ] && [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + ret=0 + check_key "KEY4" "$_id" + test "$ret" -eq 0 && key_save KEY4 && continue + fi + + # This may be an unused key. Assume algorithm of KEY1. + ret=0 && key_unused "$_id" "$(key_get KEY1 ALG_NUM)" + test "$ret" -eq 0 && continue + + # If ret is still non-zero, none of the files matched. + echo_i "failed" + _ret=1 + done + + return $_ret +} + +# Check keys for a configured zone. This verifies: +# 1. The right number of keys exist in the key pool ($1). +# 2. The right number of keys is active. Checks KEY1, KEY2, KEY3, and KEY4. +# +# It is expected that KEY1, KEY2, KEY3, and KEY4 arrays are set correctly. +# Found key identifiers are stored in the right key array. +# Keys are found if they are stored inside $DIR or in a subdirectory up to +# three levels deeper. +# +# If $1 is set, we keep keys that are already found and don't look for them +# again. +check_keys() { + n=$((n + 1)) + echo_i "check keys are created for zone ${ZONE} ($n)" + ret=0 + + echo_i "check number of keys for zone ${ZONE} in dir ${DIR} ($n)" + retry_quiet 10 check_numkeys || ret=1 + if [ $ret -ne 0 ]; then + _numkeys=$(get_keyids "$DIR" "$ZONE" | wc -l) + _log_error "bad number of key files ($_numkeys) for zone $ZONE (expected $NUM_KEYS)" + status=$((status + ret)) + fi + + # Temporarily don't log errors because we are searching multiple files. + disable_logerror + + retry_quiet 3 _check_keys $1 || ret=1 + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + # Turn error logs on again. + enable_logerror + + ret=0 + if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + echo_i "KEY1 ID $(key_get KEY1 ID) ALG $(key_get KEY1 ALG_STR)" + test "no" = "$(key_get KEY1 ID)" && _log_error "No KEY1 found for zone ${ZONE}" + fi + if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + echo_i "KEY2 ID $(key_get KEY2 ID) ALG $(key_get KEY2 ALG_STR)" + test "no" = "$(key_get KEY2 ID)" && _log_error "No KEY2 found for zone ${ZONE}" + fi + if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + echo_i "KEY3 ID $(key_get KEY3 ID) ALG $(key_get KEY3 ALG_STR)" + test "no" = "$(key_get KEY3 ID)" && _log_error "No KEY3 found for zone ${ZONE}" + fi + if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + echo_i "KEY4 ID $(key_get KEY4 ID) ALG $(key_get KEY4 ALG_STR)" + test "no" = "$(key_get KEY4 ID)" && _log_error "No KEY4 found for zone ${ZONE}" + fi + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Call rndc dnssec -status on server $1 for zone $3 in view $4 with policy $2 +# and check output. This is a loose verification, it just tests if the right +# policy name is returned, and if all expected keys are listed. The rndc +# dnssec -status output also lists whether a key is published, +# used for signing, is retired, or is removed, and if not when +# it is scheduled to do so, and it shows the states for the various +# DNSSEC records. +check_dnssecstatus() { + _server=$1 + _policy=$2 + _zone=$3 + _view=$4 + + n=$((n + 1)) + echo_i "check rndc dnssec -status output for ${_zone} (policy: $_policy) ($n)" + ret=0 + + _rndccmd $_server dnssec -status $_zone in $_view >rndc.dnssec.status.out.$_zone.$n || _log_error "rndc dnssec -status zone ${_zone} failed" + + if [ "$_policy" = "none" ]; then + grep "Zone does not have dnssec-policy" rndc.dnssec.status.out.$_zone.$n >/dev/null || log_error "bad dnssec status for unsigned zone ${_zone}" + else + grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n >/dev/null || _log_error "bad dnssec status for signed zone ${_zone}" + if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n >/dev/null || _log_error "missing key $(key_get KEY1 ID) from dnssec status" + fi + if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n >/dev/null || _log_error "missing key $(key_get KEY2 ID) from dnssec status" + fi + if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n >/dev/null || _log_error "missing key $(key_get KEY3 ID) from dnssec status" + fi + if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n >/dev/null || _log_error "missing key $(key_get KEY4 ID) from dnssec status" + fi + fi + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Call rndc zonestatus on server $1 for zone $2 in view $3 and check output if +# inline-signing is enabled. +check_inlinesigning() { + _server=$1 + _zone=$2 + _view=$3 + + _rndccmd $_server zonestatus $_zone in $_view >rndc.zonestatus.out.$_zone.$n || return 1 + grep "inline signing: yes" rndc.zonestatus.out.$_zone.$n >/dev/null || return 1 +} + +# Call rndc zonestatus on server $1 for zone $2 in view $3 and check output if +# the zone is dynamic. +check_isdynamic() { + _server=$1 + _zone=$2 + _view=$3 + + _rndccmd $_server zonestatus $_zone in $_view >rndc.zonestatus.out.$_zone.$n || return 1 + grep "dynamic: yes" rndc.zonestatus.out.$_zone.$n >/dev/null || return 1 +} + +# Check if RRset of type $1 in file $2 is signed with the right keys. +# The right keys are the ones that expect a signature and matches the role $3. +_check_signatures() { + _qtype=$1 + _file=$2 + _role=$3 + + numsigs=0 + + if [ "$_role" = "KSK" ]; then + _expect_type=EXPECT_KRRSIG + elif [ "$_role" = "ZSK" ]; then + _expect_type=EXPECT_ZRRSIG + fi + + if [ "$(key_get KEY1 "$_expect_type")" = "yes" ] && [ "$(key_get KEY1 "$_role")" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY1 ALG_NUM)" "$_file" | grep "^$(key_get KEY1 ID)$" >/dev/null || return 1 + numsigs=$((numsigs + 1)) + elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY1 ALG_NUM)" "$_file" | grep "^$(key_get KEY1 ID)$" >/dev/null && return 1 + fi + + if [ "$(key_get KEY2 "$_expect_type")" = "yes" ] && [ "$(key_get KEY2 "$_role")" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY2 ALG_NUM)" "$_file" | grep "^$(key_get KEY2 ID)$" >/dev/null || return 1 + numsigs=$((numsigs + 1)) + elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY2 ALG_NUM)" "$_file" | grep "^$(key_get KEY2 ID)$" >/dev/null && return 1 + fi + + if [ "$(key_get KEY3 "$_expect_type")" = "yes" ] && [ "$(key_get KEY3 "$_role")" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY3 ALG_NUM)" "$_file" | grep "^$(key_get KEY3 ID)$" >/dev/null || return 1 + numsigs=$((numsigs + 1)) + elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY3 ALG_NUM)" "$_file" | grep "^$(key_get KEY3 ID)$" >/dev/null && return 1 + fi + + if [ "$(key_get KEY4 "$_expect_type")" = "yes" ] && [ "$(key_get KEY4 "$_role")" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY4 ALG_NUM)" "$_file" | grep "^$(key_get KEY4 ID)$" >/dev/null || return 1 + numsigs=$((numsigs + 1)) + elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + get_keys_which_signed "$_qtype" "$(key_get KEY4 ALG_NUM)" "$_file" | grep "^$(key_get KEY4 ID)$" >/dev/null && return 1 + fi + + lines=$(get_keys_which_signed "${_qtype}" "0" "${_file}" | wc -l) + test "$lines" -eq "$numsigs" || echo_i "bad number of signatures for $_qtype (got $lines, expected $numsigs)" + test "$lines" -eq "$numsigs" || return 1 + + return 0 +} +check_signatures() { + retry_quiet 3 _check_signatures $1 $2 $3 || _log_error "RRset $1 in zone $ZONE incorrectly signed" +} + +response_has_cds_for_key() { + awk -v zone="${ZONE%%.}." \ + -v ttl="${DNSKEY_TTL}" \ + -v qtype="CDS" \ + -v keyid="$(key_get "${2}" ID)" \ + -v keyalg="$(key_get "${2}" ALG_NUM)" \ + -v hashalg="$1" \ + 'BEGIN { ret=1; } + $1 == zone && $2 == ttl && $4 == qtype && $5 == keyid && $6 == keyalg && $7 == hashalg { ret=0; exit; } + END { exit ret; }' \ + "$3" +} + +response_has_cdnskey_for_key() ( + + awk -v zone="${ZONE%%.}." \ + -v ttl="${DNSKEY_TTL}" \ + -v qtype="CDNSKEY" \ + -v flags="$(key_get "${1}" FLAGS)" \ + -v keyalg="$(key_get "${1}" ALG_NUM)" \ + 'BEGIN { ret=1; } + $1 == zone && $2 == ttl && $4 == qtype && $5 == flags && $7 == keyalg { ret=0; exit; } + END { exit ret; }' \ + "$2" +) + +check_cds_digests() { + if [ "$CDS_SHA256" = "yes" ]; then + response_has_cds_for_key 2 $1 "${2}.cds" || _log_error "missing CDS 2 record in response for key $(key_get $1 ID)" + else + response_has_cds_for_key 2 $1 "${2}.cds" && _log_error "unexpected CDS 2 record in response for key $(key_get $1 ID)" + fi + + if [ "$CDS_SHA384" = "yes" ]; then + response_has_cds_for_key 4 $1 "${2}.cds" || _log_error "missing CDS 4 record in response for key $(key_get $1 ID)" + else + response_has_cds_for_key 4 $1 "${2}.cds" && _log_error "unexpected CDS 4 record in response for key $(key_get $1 ID)" + fi + + if [ "$CDNSKEY" = "yes" ]; then + response_has_cdnskey_for_key $1 "${2}.cdnskey" || _log_error "missing CDNSKEY record in response for key $(key_get $1 ID)" + else + response_has_cdnskey_for_key $1 "${2}.cdnskey" && _log_error "unexpected CDNSKEY record in response for key $(key_get $1 ID)" + fi + + return 0 +} + +check_cds_digests_invert() { + response_has_cds_for_key 2 $1 "${2}.cds" && _log_error "unexpected CDS 2 record in response for key $(key_get $1 ID)" + response_has_cds_for_key 4 $1 "${2}.cds" && _log_error "unexpected CDS 4 record in response for key $(key_get $1 ID)" + # The key should not have an associated CDNSKEY, but there may be + # one for another key. Since the CDNSKEY has no field for key + # id, it is hard to check what key the CDNSKEY may belong to + # so let's skip this check for now. + + return 0 +} + +# Test CDS and CDNSKEY publication. +check_cds() { + + n=$((n + 1)) + echo_i "check CDS and CDNSKEY rrset are signed correctly for zone ${ZONE} ($n)" + ret=0 + + _checksig=0 + + _dig_with_opts "$ZONE" "@${SERVER}" "CDS" >"dig.out.$DIR.test$n.cds" || _log_error "dig ${ZONE} CDS failed" + grep "status: NOERROR" "dig.out.$DIR.test$n.cds" >/dev/null || _log_error "mismatch status in DNS response" + + _dig_with_opts "$ZONE" "@${SERVER}" "CDNSKEY" >"dig.out.$DIR.test$n.cdnskey" || _log_error "dig ${ZONE} CDNSKEY failed" + grep "status: NOERROR" "dig.out.$DIR.test$n.cdnskey" >/dev/null || _log_error "mismatch status in DNS response" + + if [ "$CDS_DELETE" = "no" ]; then + grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" >/dev/null && _log_error "unexpected CDS DELETE record in DNS response" + grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" >/dev/null && _log_error "unexpected CDNSKEY DELETE record in DNS response" + else + grep "CDS.*0 0 0 00" "dig.out.$DIR.test$n.cds" >/dev/null || _log_error "missing CDS DELETE record in DNS response" + grep "CDNSKEY.*0 3 0 AA==" "dig.out.$DIR.test$n.cdnskey" >/dev/null || _log_error "missing CDNSKEY DELETE record in DNS response" + _checksig=1 + fi + + if [ "$(key_get KEY1 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DS)" = "omnipresent" ]; then + check_cds_digests KEY1 "dig.out.$DIR.test$n" + _checksig=1 + elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + check_cds_digests_invert KEY1 "dig.out.$DIR.test$n" + fi + + if [ "$(key_get KEY2 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DS)" = "omnipresent" ]; then + check_cds_digests KEY2 "dig.out.$DIR.test$n" + _checksig=1 + elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + check_cds_digests_invert KEY2 "dig.out.$DIR.test$n" + fi + + if [ "$(key_get KEY3 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DS)" = "omnipresent" ]; then + check_cds_digests KEY3 "dig.out.$DIR.test$n" + _checksig=1 + elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + check_cds_digests_invert KEY3 "dig.out.$DIR.test$n" + fi + + if [ "$(key_get KEY4 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY4 STATE_DS)" = "omnipresent" ]; then + check_cds_digests KEY4 "dig.out.$DIR.test$n" + _checksig=1 + elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + check_cds_digests_invert KEY4 "dig.out.$DIR.test$n" + fi + + test "$_checksig" -eq 0 || check_signatures "CDS" "dig.out.$DIR.test$n.cds" "KSK" + + if [ "$CDNSKEY" = "yes" ]; then + test "$_checksig" -eq 0 || check_signatures "CDNSKEY" "dig.out.$DIR.test$n.cdnskey" "KSK" + fi + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +_find_dnskey() { + _owner="${ZONE}." + _alg="$(key_get $1 ALG_NUM)" + _flags="$(key_get $1 FLAGS)" + _key_file="$(key_get $1 BASEFILE).key" + + awk '$1 == "'"$_owner"'" && $2 == "'"$KEYFILE_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' <"$_key_file" +} + +# Test DNSKEY query. +_check_apex_dnskey() { + _dig_with_opts "$ZONE" "@${SERVER}" "DNSKEY" >"dig.out.$DIR.test$n" || return 1 + grep "status: NOERROR" "dig.out.$DIR.test$n" >/dev/null || return 1 + + _checksig=0 + + if [ "$(key_get KEY1 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DNSKEY)" = "omnipresent" ]; then + _pubkey=$(_find_dnskey KEY1) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null || return 1 + _checksig=1 + elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then + _pubkey=$(_find_dnskey KEY1) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null && return 1 + fi + + if [ "$(key_get KEY2 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DNSKEY)" = "omnipresent" ]; then + _pubkey=$(_find_dnskey KEY2) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null || return 1 + _checksig=1 + elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then + _pubkey=$(_find_dnskey KEY2) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null && return 1 + fi + + if [ "$(key_get KEY3 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DNSKEY)" = "omnipresent" ]; then + _pubkey=$(_find_dnskey KEY3) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null || return 1 + _checksig=1 + elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then + _pubkey=$(_find_dnskey KEY3) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null && return 1 + fi + + if [ "$(key_get KEY4 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY4 STATE_DNSKEY)" = "omnipresent" ]; then + _pubkey=$(_find_dnskey KEY4) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null || return 1 + _checksig=1 + elif [ "$(key_get KEY4 EXPECT)" = "yes" ]; then + _pubkey=$(_find_dnskey KEY4) + test -z "$_pubkey" && return 1 + grep -F "$_pubkey" "dig.out.$DIR.test$n" >/dev/null && return 1 + fi + + test "$_checksig" -eq 0 && return 0 + + _check_signatures "DNSKEY" "dig.out.$DIR.test$n" "KSK" || return 1 + + return 0 +} + +# Test the apex of a configured zone. This checks that the SOA and DNSKEY +# RRsets are signed correctly and with the appropriate keys. +check_apex() { + + # Test DNSKEY query. + n=$((n + 1)) + echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_apex_dnskey || ret=1 + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + # We retry the DNSKEY query for at most ten seconds to avoid test + # failures due to timing issues. If the DNSKEY query check passes this + # means the zone is resigned and further apex checks (SOA, CDS, CDNSKEY) + # don't need to be retried quietly. + + # Test SOA query. + n=$((n + 1)) + echo_i "check SOA rrset is signed correctly for zone ${ZONE} ($n)" + ret=0 + _dig_with_opts "$ZONE" "@${SERVER}" "SOA" >"dig.out.$DIR.test$n" || _log_error "dig ${ZONE} SOA failed" + grep "status: NOERROR" "dig.out.$DIR.test$n" >/dev/null || _log_error "mismatch status in DNS response" + grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*SOA.*" "dig.out.$DIR.test$n" >/dev/null || _log_error "missing SOA record in response" + check_signatures "SOA" "dig.out.$DIR.test$n" "ZSK" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + # Test CDS and CDNSKEY publication. + check_cds +} + +# Test an RRset below the apex and verify it is signed correctly. +check_subdomain() { + _qtype="A" + n=$((n + 1)) + echo_i "check ${_qtype} a.${ZONE} rrset is signed correctly for zone ${ZONE} ($n)" + ret=0 + _dig_with_opts "a.$ZONE" "@${SERVER}" $_qtype >"dig.out.$DIR.test$n" || _log_error "dig a.${ZONE} ${_qtype} failed" + grep "status: NOERROR" "dig.out.$DIR.test$n" >/dev/null || _log_error "mismatch status in DNS response" + grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*${_qtype}.*10\.0\.0\.1" "dig.out.$DIR.test$n" >/dev/null || _log_error "missing a.${ZONE} ${_qtype} record in response" + lines=$(get_keys_which_signed $_qtype 0 "dig.out.$DIR.test$n" | wc -l) + check_signatures $_qtype "dig.out.$DIR.test$n" "ZSK" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Check if "CDS/CDNSKEY Published" is logged. +check_cdslog() { + _dir=$1 + _zone=$2 + _key=$3 + + _alg=$(key_get $_key ALG_STR) + _id=$(key_get $_key ID) + + n=$((n + 1)) + echo_i "check CDS/CDNSKEY publication is logged in ${_dir}/named.run for key ${_zone}/${_alg}/${_id} ($n)" + ret=0 + + if [ "$CDS_SHA256" = "yes" ]; then + grep "CDS (SHA-256) for key ${_zone}/${_alg}/${_id} is now published" "${_dir}/named.run" >/dev/null || ret=1 + fi + if [ "$CDS_SHA384" = "yes" ]; then + grep "CDS (SHA-384) for key ${_zone}/${_alg}/${_id} is now published" "${_dir}/named.run" >/dev/null || ret=1 + fi + if [ "$CDNSKEY" = "yes" ]; then + grep "CDNSKEY for key ${_zone}/${_alg}/${_id} is now published" "${_dir}/named.run" >/dev/null || ret=1 + fi + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Tell named that the DS for the key in given zone has been seen in the +# parent (this does not actually has to be true, we just issue the command +# to make named believe it can continue with the rollover). +rndc_checkds() { + _server=$1 + _dir=$2 + _key=$3 + _when=$4 + _what=$5 + _zone=$6 + _view=$7 + + _keycmd="" + if [ "${_key}" != "-" ]; then + _keyid=$(key_get $_key ID) + _keycmd=" -key ${_keyid}" + fi + + _whencmd="" + if [ "${_when}" != "now" ]; then + _whencmd=" -when ${_when}" + fi + + n=$((n + 1)) + echo_i "calling rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} in ${_view} ($n)" + ret=0 + + _rndccmd $_server dnssec -checkds $_keycmd $_whencmd $_what $_zone in $_view >rndc.dnssec.checkds.out.$_zone.$n || _log_error "rndc dnssec -checkds${_keycmd}${_whencmd} ${_what} zone ${_zone} failed" + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Tell named to schedule a key rollover. +rndc_rollover() { + _server=$1 + _dir=$2 + _keyid=$3 + _when=$4 + _zone=$5 + _view=$6 + + _whencmd="" + if [ "${_when}" != "now" ]; then + _whencmd="-when ${_when}" + fi + + n=$((n + 1)) + echo_i "calling rndc dnssec -rollover key ${_keyid} ${_whencmd} zone ${_zone} ($n)" + ret=0 + + _rndccmd $_server dnssec -rollover -key $_keyid $_whencmd $_zone in $_view >rndc.dnssec.rollover.out.$_zone.$n || _log_error "rndc dnssec -rollover (key ${_keyid} when ${_when}) zone ${_zone} failed" + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} diff --git a/bin/tests/system/kasp/README b/bin/tests/system/kasp/README new file mode 100644 index 0000000..96b0ef7 --- /dev/null +++ b/bin/tests/system/kasp/README @@ -0,0 +1,23 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The test setup for the KASP tests. + +ns1 is reserved for the root server. + +ns2 is running primary service for ns3. + +ns3 is an authoritative server for the various test domains. + +ns4 and ns5 are authoritative servers for various test domains related to views. + +ns6 is an authoritative server that tests changes in dnssec-policy (algorithm +rollover). diff --git a/bin/tests/system/kasp/kasp.conf b/bin/tests/system/kasp/kasp.conf new file mode 100644 index 0000000..e7a2eab --- /dev/null +++ b/bin/tests/system/kasp/kasp.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * This is just a random selection of configuration options. + */ + +dnssec-policy "kasp" { + dnskey-ttl 200; + + keys { + csk key-directory lifetime P1Y algorithm 13; + ksk key-directory lifetime P1Y algorithm 8; + zsk key-directory lifetime P30D algorithm 8 2048; + zsk key-directory lifetime P6M algorithm 8 3072; + }; +}; diff --git a/bin/tests/system/kasp/ns2/named.conf.in b/bin/tests/system/kasp/ns2/named.conf.in new file mode 100644 index 0000000..b23b9d5 --- /dev/null +++ b/bin/tests/system/kasp/ns2/named.conf.in @@ -0,0 +1,61 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-policy "none"; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* Inherit dnssec-policy (which is none) */ + +zone "unsigned.tld" { + type primary; + file "unsigned.tld.db"; +}; + +/* Override dnssec-policy */ + +zone "signed.tld" { + type primary; + file "signed.tld.db"; + dnssec-policy "default"; +}; + +/* Primary service for ns3 */ + +zone "secondary.kasp" { + type primary; + file "secondary.kasp.db"; + allow-transfer { 10.53.0.3; }; + notify yes; +}; diff --git a/bin/tests/system/kasp/ns2/secondary.kasp.db.in b/bin/tests/system/kasp/ns2/secondary.kasp.db.in new file mode 100644 index 0000000..3c8d124 --- /dev/null +++ b/bin/tests/system/kasp/ns2/secondary.kasp.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.kasp. hostmaster.kasp. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/ns2/secondary.kasp.db.in2 b/bin/tests/system/kasp/ns2/secondary.kasp.db.in2 new file mode 100644 index 0000000..9289831 --- /dev/null +++ b/bin/tests/system/kasp/ns2/secondary.kasp.db.in2 @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.kasp. hostmaster.kasp. ( + 2 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.11 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 + diff --git a/bin/tests/system/kasp/ns2/setup.sh b/bin/tests/system/kasp/ns2/setup.sh new file mode 100644 index 0000000..cdf0f26 --- /dev/null +++ b/bin/tests/system/kasp/ns2/setup.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns2/setup.sh" + +zone="secondary.kasp" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +infile="${zonefile}.in" +cp $infile $zonefile + +zone="signed.tld" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +infile="template.tld.db.in" +cp $infile $zonefile + +zone="unsigned.tld" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +infile="template.tld.db.in" +cp $infile $zonefile diff --git a/bin/tests/system/kasp/ns2/template.tld.db.in b/bin/tests/system/kasp/ns2/template.tld.db.in new file mode 100644 index 0000000..400dc34 --- /dev/null +++ b/bin/tests/system/kasp/ns2/template.tld.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA secondary.kasp. hostmaster.kasp. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/ns3/ed25519.conf b/bin/tests/system/kasp/ns3/ed25519.conf new file mode 100644 index 0000000..b64c0c8 --- /dev/null +++ b/bin/tests/system/kasp/ns3/ed25519.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "ed25519" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 15; + zsk key-directory lifetime P5Y algorithm 15; + zsk key-directory lifetime P1Y algorithm 15 256; + }; +}; + +zone "ed25519.kasp" { + type primary; + file "ed25519.kasp.db"; + dnssec-policy "ed25519"; +}; diff --git a/bin/tests/system/kasp/ns3/ed448.conf b/bin/tests/system/kasp/ns3/ed448.conf new file mode 100644 index 0000000..ee4c494 --- /dev/null +++ b/bin/tests/system/kasp/ns3/ed448.conf @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "ed448" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 16; + zsk key-directory lifetime P5Y algorithm 16; + zsk key-directory lifetime P1Y algorithm 16 456; + }; +}; + +zone "ed448.kasp" { + type primary; + file "ed448.kasp.db"; + dnssec-policy "ed448"; +}; diff --git a/bin/tests/system/kasp/ns3/named-fips.conf.in b/bin/tests/system/kasp/ns3/named-fips.conf.in new file mode 100644 index 0000000..33cfaa9 --- /dev/null +++ b/bin/tests/system/kasp/ns3/named-fips.conf.in @@ -0,0 +1,523 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "policies/kasp.conf"; +include "policies/autosign.conf"; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-policy "rsasha256"; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +/* Zones that are getting initially signed */ + +/* The default case: No keys created, using default policy. */ +zone "default.kasp" { + type primary; + file "default.kasp.db"; + dnssec-policy "default"; +}; + +/* A zone with special characters. */ +zone "i-am.\":\;?&[]\@!\$*+,|=\.\(\)special.kasp." { + type primary; + file "i-am.special.kasp.db"; + check-names ignore; + dnssec-policy "default"; +}; + +/* checkds: Zone with one KSK. */ +zone "checkds-ksk.kasp" { + type primary; + file "checkds-ksk.kasp.db"; + dnssec-policy "checkds-ksk"; +}; + +/* checkds: Zone with two KSKs. */ +zone "checkds-doubleksk.kasp" { + type primary; + file "checkds-doubleksk.kasp.db"; + dnssec-policy "checkds-doubleksk"; +}; + +/* checkds: Zone with one CSK. */ +zone "checkds-csk.kasp" { + type primary; + file "checkds-csk.kasp.db"; + dnssec-policy "checkds-csk"; +}; + +/* Key lifetime unlimited. */ +zone "unlimited.kasp" { + type primary; + file "unlimited.kasp.db"; + dnssec-policy "unlimited"; +}; + +/* Manual rollover. */ +zone "manual-rollover.kasp" { + type primary; + file "manual-rollover.kasp.db"; + dnssec-policy "manual-rollover"; +}; + +/* A zone that inherits dnssec-policy. */ +zone "inherit.kasp" { + type primary; + file "inherit.kasp.db"; +}; + +/* A zone that overrides dnssec-policy. */ +zone "unsigned.kasp" { + type primary; + file "unsigned.kasp.db"; + dnssec-policy "none"; +}; + +/* A zone that is initially set to insecure. */ +zone "insecure.kasp" { + type primary; + file "insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +/* A primary zone with dnssec-policy but keys already created. */ +zone "dnssec-keygen.kasp" { + type primary; + file "dnssec-keygen.kasp.db"; + dnssec-policy "rsasha256"; +}; + +/* A secondary zone with dnssec-policy. */ +zone "secondary.kasp" { + type secondary; + primaries { 10.53.0.2; }; + file "secondary.kasp.db"; + dnssec-policy "rsasha256"; +}; + +/* A dynamic zone with dnssec-policy. */ +zone "dynamic.kasp" { + type primary; + file "dynamic.kasp.db"; + dnssec-policy "default-dynamic"; + allow-update { any; }; +}; + +/* A dynamic inline-signed zone with dnssec-policy. */ +zone "dynamic-inline-signing.kasp" { + type primary; + file "dynamic-inline-signing.kasp.db"; + dnssec-policy "default"; + allow-update { any; }; +}; + +/* + * A dynamic inline-signed zone with dnssec-policy with DNSSEC records in the + * raw version of the zone. + */ +zone "dynamic-signed-inline-signing.kasp" { + type primary; + file "dynamic-signed-inline-signing.kasp.db.signed"; + key-directory "keys"; + dnssec-policy "default"; + allow-update { any; }; +}; + +/* An inline-signed zone with dnssec-policy. */ +zone "inline-signing.kasp" { + type primary; + file "inline-signing.kasp.db"; + dnssec-policy "default"; +}; + +/* A zone that uses dnssec-policy with key stores. */ +zone "keystore.kasp" { + type primary; + file "keystore.kasp.db"; + inline-signing yes; + dnssec-policy "keystore"; +}; + +/* + * A configured dnssec-policy but some keys already created. + */ +zone "some-keys.kasp" { + type primary; + file "some-keys.kasp.db"; + dnssec-policy "rsasha256"; +}; + +/* + * A configured dnssec-policy but some keys already in use. + */ +zone "legacy-keys.kasp" { + type primary; + file "legacy-keys.kasp.db"; + dnssec-policy "migrate-to-dnssec-policy"; +}; + +/* + * A configured dnssec-policy with (too) many keys pregenerated. + */ +zone "pregenerated.kasp" { + type primary; + file "pregenerated.kasp.db"; + dnssec-policy "rsasha256"; +}; + +/* + * A configured dnssec-policy with one rumoured key. + * Bugfix case for GL #1593. + */ +zone "rumoured.kasp" { + type primary; + file "rumoured.kasp.db"; + dnssec-policy "rsasha256"; +}; + +/* RFC 8901 Multi-signer Model 2. */ +zone "multisigner-model2.kasp" { + type primary; + file "multisigner-model2.kasp.db"; + dnssec-policy "multisigner-model2"; + allow-update { any; }; +}; + +/* + * A zone that starts with keys that have tags that are + * outside of the desired multi-signer key tag range. + */ +zone "single-to-multisigner.kasp" { + type primary; + file "single-to-multisigner.kasp.db"; + dnssec-policy "multisigner-model2"; + allow-update { any; }; +}; + +/* + * Different algorithms. + */ +zone "rsasha256.kasp" { + type primary; + file "rsasha256.kasp.db"; + dnssec-policy "rsasha256"; +}; +zone "rsasha512.kasp" { + type primary; + file "rsasha512.kasp.db"; + dnssec-policy "rsasha512"; +}; +zone "ecdsa256.kasp" { + type primary; + file "ecdsa256.kasp.db"; + dnssec-policy "ecdsa256"; +}; +zone "ecdsa384.kasp" { + type primary; + file "ecdsa384.kasp.db"; + dnssec-policy "ecdsa384"; +}; + +/* + * Zone with too high TTL. + */ +zone "max-zone-ttl.kasp" { + type primary; + file "max-zone-ttl.kasp.db"; + dnssec-policy "ttl"; +}; + +/* + * Zone for testing GL #2375: Three is a crowd. + */ +zone "three-is-a-crowd.kasp" { + type primary; + file "three-is-a-crowd.kasp.db"; + inline-signing yes; + /* Use same policy as KSK rollover test zones. */ + dnssec-policy "ksk-doubleksk"; +}; + +/* + * Zones in different signing states. + */ + +/* + * Zone that has expired signatures. + */ +zone "expired-sigs.autosign" { + type primary; + file "expired-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has DNSKEY TTL mismatch with the dnssec-policy. + */ +zone "dnskey-ttl-mismatch.autosign" { + type primary; + file "dnskey-ttl-mismatch.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has valid, fresh signatures. + */ +zone "fresh-sigs.autosign" { + type primary; + file "fresh-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has unfresh signatures. + */ +zone "unfresh-sigs.autosign" { + type primary; + file "unfresh-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has missing key files. + */ +zone "keyfiles-missing.autosign" { + type primary; + file "keyfiles-missing.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has missing private KSK. + */ +zone "ksk-missing.autosign" { + type primary; + file "ksk-missing.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has missing private ZSK. + */ +zone "zsk-missing.autosign" { + type primary; + file "zsk-missing.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has inactive ZSK. + */ +zone "zsk-retired.autosign" { + type primary; + file "zsk-retired.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zones for testing enabling DNSSEC. + */ +zone "step1.enable-dnssec.autosign" { + type primary; + file "step1.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step2.enable-dnssec.autosign" { + type primary; + file "step2.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step3.enable-dnssec.autosign" { + type primary; + file "step3.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step4.enable-dnssec.autosign" { + type primary; + file "step4.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; + +/* + * Zones for testing ZSK Pre-Publication steps. + */ +zone "step1.zsk-prepub.autosign" { + type primary; + file "step1.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step2.zsk-prepub.autosign" { + type primary; + file "step2.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step3.zsk-prepub.autosign" { + type primary; + file "step3.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step4.zsk-prepub.autosign" { + type primary; + file "step4.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step5.zsk-prepub.autosign" { + type primary; + file "step5.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step6.zsk-prepub.autosign" { + type primary; + file "step6.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; + +/* + * Zones for testing KSK Double-KSK steps. + */ +zone "step1.ksk-doubleksk.autosign" { + type primary; + file "step1.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step2.ksk-doubleksk.autosign" { + type primary; + file "step2.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step3.ksk-doubleksk.autosign" { + type primary; + file "step3.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step4.ksk-doubleksk.autosign" { + type primary; + file "step4.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step5.ksk-doubleksk.autosign" { + type primary; + file "step5.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step6.ksk-doubleksk.autosign" { + type primary; + file "step6.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; + +/* + * Zones for testing CSK rollover steps. + */ +zone "step1.csk-roll.autosign" { + type primary; + file "step1.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step2.csk-roll.autosign" { + type primary; + file "step2.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step3.csk-roll.autosign" { + type primary; + file "step3.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step4.csk-roll.autosign" { + type primary; + file "step4.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step5.csk-roll.autosign" { + type primary; + file "step5.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step6.csk-roll.autosign" { + type primary; + file "step6.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step7.csk-roll.autosign" { + type primary; + file "step7.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; +zone "step8.csk-roll.autosign" { + type primary; + file "step8.csk-roll.autosign.db"; + dnssec-policy "csk-roll"; +}; + +zone "step1.csk-roll2.autosign" { + type primary; + file "step1.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step2.csk-roll2.autosign" { + type primary; + file "step2.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step3.csk-roll2.autosign" { + type primary; + file "step3.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step4.csk-roll2.autosign" { + type primary; + file "step4.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step5.csk-roll2.autosign" { + type primary; + file "step5.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step6.csk-roll2.autosign" { + type primary; + file "step6.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; +zone "step7.csk-roll2.autosign" { + type primary; + file "step7.csk-roll2.autosign.db"; + dnssec-policy "csk-roll2"; +}; diff --git a/bin/tests/system/kasp/ns3/named.conf.in b/bin/tests/system/kasp/ns3/named.conf.in new file mode 100644 index 0000000..921ecc8 --- /dev/null +++ b/bin/tests/system/kasp/ns3/named.conf.in @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "named-fips.conf"; + +zone "rsasha1.kasp" { + type primary; + file "rsasha1.kasp.db"; + dnssec-policy "rsasha1"; +}; + +zone "rsasha1-nsec3.kasp" { + type primary; + file "rsasha1-nsec3.kasp.db"; + dnssec-policy "rsasha1-nsec3"; +}; diff --git a/bin/tests/system/kasp/ns3/policies/autosign.conf.in b/bin/tests/system/kasp/ns3/policies/autosign.conf.in new file mode 100644 index 0000000..bc3b7e1 --- /dev/null +++ b/bin/tests/system/kasp/ns3/policies/autosign.conf.in @@ -0,0 +1,136 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "autosign" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 300; + + keys { + ksk key-directory lifetime P2Y algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P1Y algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "enable-dnssec" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 300; + max-zone-ttl PT12H; + zone-propagation-delay PT5M; + retire-safety PT20M; + publish-safety PT5M; + + parent-propagation-delay 1h; + parent-ds-ttl 2h; + + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM_NUMBER@; + }; +}; + +dnssec-policy "zsk-prepub" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 3600; + publish-safety P1D; + retire-safety P2D; + purge-keys PT1H; + + keys { + ksk key-directory lifetime P2Y algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P30D algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay PT1H; + max-zone-ttl 1d; +}; + +dnssec-policy "ksk-doubleksk" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 2h; + publish-safety P1D; + retire-safety P2D; + purge-keys PT1H; + + cdnskey no; + keys { + ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P1Y algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay PT1H; + max-zone-ttl 1d; + + parent-ds-ttl 3600; + parent-propagation-delay PT1H; +}; + +dnssec-policy "csk-roll" { + + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + purge-keys PT1H; + + cds-digest-types { "sha-384"; }; // use a different digest type for testing purposes + keys { + csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay 1h; + max-zone-ttl P1D; + + parent-ds-ttl 1h; + parent-propagation-delay 1h; +}; + +dnssec-policy "csk-roll2" { + + signatures-refresh 12h; + signatures-validity P1D; + signatures-validity-dnskey P1D; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 1h; + purge-keys 0; + + cds-digest-types { "sha-256"; "sha-384"; }; // use two digest type for testing purposes + keys { + csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay PT1H; + max-zone-ttl 1d; + + parent-ds-ttl PT1H; + parent-propagation-delay P1W; +}; diff --git a/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in new file mode 100644 index 0000000..93ca729 --- /dev/null +++ b/bin/tests/system/kasp/ns3/policies/kasp-fips.conf.in @@ -0,0 +1,140 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "unlimited" { + dnskey-ttl 1234; + + keys { + csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "default-dynamic" { + inline-signing no; +}; + +dnssec-policy "manual-rollover" { + dnskey-ttl 3600; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "multisigner-model2" { + dnskey-ttl 3600; + inline-signing no; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535; + }; +}; + +dnssec-policy "migrate-to-dnssec-policy" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P6M algorithm 8; + zsk key-directory lifetime P6M algorithm 8; + }; +}; + +dnssec-policy "rsasha256" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 8; + zsk key-directory lifetime P5Y algorithm 8; + zsk key-directory lifetime P1Y algorithm 8 3072; + }; +}; + +dnssec-policy "rsasha512" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 10; + zsk key-directory lifetime P5Y algorithm 10; + zsk key-directory lifetime P1Y algorithm 10 3072; + }; +}; + +dnssec-policy "ecdsa256" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 13; + zsk key-directory lifetime P5Y algorithm 13; + zsk key-directory lifetime P1Y algorithm 13 256; + }; +}; + +dnssec-policy "ecdsa384" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 14; + zsk key-directory lifetime P5Y algorithm 14; + zsk key-directory lifetime P1Y algorithm 14 384; + }; +}; + +dnssec-policy "checkds-ksk" { + dnskey-ttl 303; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "checkds-doubleksk" { + dnskey-ttl 303; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "checkds-csk" { + dnskey-ttl 303; + + keys { + csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "ttl" { + max-zone-ttl 299; +}; + +key-store "ksk" { + directory "ksk"; +}; + +key-store "zsk" { + directory "zsk"; +}; + +dnssec-policy "keystore" { + dnskey-ttl 303; + + keys { + ksk key-store "ksk" lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-store "zsk" lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; diff --git a/bin/tests/system/kasp/ns3/policies/kasp.conf.in b/bin/tests/system/kasp/ns3/policies/kasp.conf.in new file mode 100644 index 0000000..cb045bc --- /dev/null +++ b/bin/tests/system/kasp/ns3/policies/kasp.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "policies/kasp-fips.conf"; + +dnssec-policy "rsasha1" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 5; + zsk key-directory lifetime P5Y algorithm 5; + zsk key-directory lifetime P1Y algorithm 5 2000; + }; +}; + +dnssec-policy "rsasha1-nsec3" { + dnskey-ttl 1234; + + keys { + ksk key-directory lifetime P10Y algorithm 7; + zsk key-directory lifetime P5Y algorithm 7; + zsk key-directory lifetime P1Y algorithm 7 2000; + }; +}; diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh new file mode 100644 index 0000000..731ba06 --- /dev/null +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -0,0 +1,1529 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns3/setup.sh" + +# Create key store directories. +mkdir ksk +mkdir zsk + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" + echo "$zone" >>zones +} + +# Set in the key state files the Predecessor/Successor fields. +# Key $1 is the predecessor of key $2. +key_successor() { + id1=$(keyfile_to_key_id "$1") + id2=$(keyfile_to_key_id "$2") + echo "Predecessor: ${id1}" >>"${2}.state" + echo "Successor: ${id2}" >>"${1}.state" +} + +# Make lines shorter by storing key states in environment variables. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" + +# +# Set up zones that will be initially signed. +# +for zn in default dnssec-keygen some-keys legacy-keys pregenerated \ + rumoured rsasha256 rsasha512 ecdsa256 ecdsa384 \ + dynamic dynamic-inline-signing inline-signing \ + checkds-ksk checkds-doubleksk checkds-csk inherit unlimited \ + manual-rollover multisigner-model2 keystore; do + setup "${zn}.kasp" + cp template.db.in "$zonefile" +done + +# +# Setup special zone +# +zone="i-am.\":\;?&[]\@!\$*+,|=\.\(\)special.kasp." +echo_i "setting up zone: $zone" +cp template.db.in "i-am.special.kasp.db" + +# +# Set up RSASHA1 based zones +# +for zn in rsasha1 rsasha1-nsec3; do + if [ $RSASHA1_SUPPORTED = 1 ]; then + setup "${zn}.kasp" + cp template.db.in "$zonefile" + else + # don't add to zones. + echo_i "setting up zone: ${zn}.kasp" + cp template.db.in "${zn}.kasp.db" + fi +done + +if [ $ED25519_SUPPORTED = 1 ]; then + setup "ed25519.kasp" + cp template.db.in "$zonefile" + cat ed25519.conf >>named.conf +fi + +if [ $ED448_SUPPORTED = 1 ]; then + setup "ed448.kasp" + cp template.db.in "$zonefile" + cat ed448.conf >>named.conf +fi + +# Set up zones that stay unsigned. +for zn in unsigned insecure max-zone-ttl; do + zone="${zn}.kasp" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" + cp template.db.in $infile + cp template.db.in $zonefile +done + +# Some of these zones already have keys. +zone="dnssec-keygen.kasp" +echo_i "setting up zone: $zone" +$KEYGEN -k rsasha256 -l policies/kasp.conf $zone >keygen.out.$zone.1 2>&1 + +zone="some-keys.kasp" +echo_i "setting up zone: $zone" +$KEYGEN -G -a RSASHA256 -b 2048 -L 1234 $zone >keygen.out.$zone.1 2>&1 +$KEYGEN -G -a RSASHA256 -f KSK -L 1234 $zone >keygen.out.$zone.2 2>&1 + +zone="legacy-keys.kasp" +echo_i "setting up zone: $zone" +ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 1234 $zone 2>keygen.out.$zone.1) +KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $zone 2>keygen.out.$zone.2) +echo $ZSK >legacy-keys.kasp.zsk +echo $KSK >legacy-keys.kasp.ksk +# Predecessor keys: +Tact="now-9mo" +Tret="now-3mo" +ZSK=$($KEYGEN -a RSASHA256 -b 2048 -L 1234 $zone 2>keygen.out.$zone.3) +KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $zone 2>keygen.out.$zone.4) +$SETTIME -P $Tact -A $Tact -I $Tret -D $Tret "$ZSK" >settime.out.$zone.1 2>&1 +$SETTIME -P $Tact -A $Tact -I $Tret -D $Tret "$KSK" >settime.out.$zone.2 2>&1 + +zone="pregenerated.kasp" +echo_i "setting up zone: $zone" +$KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone >keygen.out.$zone.1 2>&1 +$KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone >keygen.out.$zone.2 2>&1 + +zone="multisigner-model2.kasp" +echo_i "setting up zone: $zone" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.2) +cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db" +cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db" +# Import the ZSK sets of the other providers into their DNSKEY RRset. +# ZSK1 is from a different provider and is added to the unsigned zonefile. +# ZSK2 is also from a different provider and is added with a Dynamic Update. +ZSK1=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 -M 0:32767 $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 -M 0:32767 $zone 2>keygen.out.$zone.4) +cat "../${ZSK1}.key" | grep -v ";.*" >>"${zone}.db" +cat "../${ZSK1}.key" | grep -v ";.*" >"${zone}.zsk1" +cat "../${ZSK2}.key" | grep -v ";.*" >"${zone}.zsk2" +rm -f "../${ZSK1}.*" +rm -f "../${ZSK2}.*" + +zone="rumoured.kasp" +echo_i "setting up zone: $zone" +Tpub="now" +Tact="now+1d" +keytimes="-P ${Tpub} -A ${Tact}" +KSK=$($KEYGEN -a RSASHA256 -f KSK -L 1234 $keytimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -b 3072 -L 1234 $keytimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a RSASHA256 -L 1234 $keytimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $R $Tpub -r $R $Tpub -d $H $Tpub "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $Tpub -z $R $Tpub "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $R $Tpub -z $R $Tpub "$ZSK2" >settime.out.$zone.2 2>&1 + +# +# Set up zones that are already signed. +# + +# Zone to test manual rollover. +setup manual-rollover.kasp +T="now-1d" +ksktimes="-P $T -A $T -P sync $T" +zsktimes="-P $T -A $T" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# We are signing the raw version of the zone here. This is unusual and not +# common operation, but want to make sure that in such a case BIND 9 does not +# schedule a resigning operation on the raw version. Add expired signatures so +# a resign is imminent. +setup dynamic-signed-inline-signing.kasp +T="now-1d" +csktimes="-P $T -A $T -P sync $T" +CSK=$($KEYGEN -K keys -a $DEFAULT_ALGORITHM -L 3600 -f KSK $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -d $O $T -k $O $T -z $O $T -r $O $T "keys/$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "keys/${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "keys/$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -PS -K keys -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# We are changing an existing single-signed zone to multi-signed +# zone where the key tags do not match the dnssec-policy key tag range +setup single-to-multisigner.kasp +T="now-1d" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +$SIGNER -PS -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}" $infile >signer.out.$zone.1 2>&1 + +# Treat the next zones as if they were signed six months ago. +T="now-6mo" +keytimes="-P $T -A $T" + +# These signatures are set to expire long in the past, update immediately. +setup expired-sigs.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# The DNSKEY's TTLs do not match the policy. +setup dnskey-ttl-mismatch.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK " >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +cp $infile $zonefile +$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# These signatures are still good, and can be reused. +setup fresh-sigs.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# These signatures are still good, but not fresh enough, update immediately. +setup unfresh-sigs.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# These signatures are still good, but the private KSK is missing. +setup ksk-missing.autosign +# KSK file will be gone missing, so we set expected times during setup. +TI="now+550d" # Lifetime of 2 years minus 6 months equals 550 days +TD="now+13226h" # 550 days plus retire time of 1 day 2 hours equals 13226 hours +TS="now-257755mi" # 6 months minus 1 day, 5 minutes equals 257695 minutes +ksktimes="$keytimes -P sync $TS -I $TI -D $TD" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +echo "KSK: yes" >>"${KSK}".state +echo "ZSK: no" >>"${KSK}".state +echo "Lifetime: 63072000" >>"${KSK}".state # PT2Y +rm -f "${KSK}".private + +# These signatures are still good, but the private ZSK is missing. +setup zsk-missing.autosign +# ZSK file will be gone missing, so we set expected times during setup. +TI="now+185d" # Lifetime of 1 year minus 6 months equals 185 days +TD="now+277985mi" # 185 days plus retire time (sign delay, retire safety, propagation, zone TTL) +zsktimes="$keytimes -I $TI -D $TD" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +echo "KSK: no" >>"${ZSK}".state +echo "ZSK: yes" >>"${ZSK}".state +echo "Lifetime: 31536000" >>"${ZSK}".state # PT1Y +rm -f "${ZSK}".private + +# These signatures are still good, but the key files will be removed +# before a second run of reconfiguring keys. +setup keyfiles-missing.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# These signatures are already expired, and the private ZSK is retired. +setup zsk-retired.autosign +zsktimes="$keytimes -I now" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +$SETTIME -s -g HIDDEN "$ZSK" >settime.out.$zone.3 2>&1 +# An old key that is being purged should not prevent keymgr to be run. +T1="now-1y" +T2="now-2y" +oldtimes="-P $T2 -A $T2 -I $T1 -D $T1" +OLD=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $oldtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $H $T1 -z $H $T1 "$OLD" >settime.out.$zone.3 2>&1 + +# +# The zones at enable-dnssec.autosign represent the various steps of the +# initial signing of a zone. +# + +# Step 1: +# This is an unsigned zone and named should perform the initial steps of +# introducing the DNSSEC records in the right order. +setup step1.enable-dnssec.autosign +cp template.db.in $zonefile + +# Step 2: +# The DNSKEY has been published long enough to become OMNIPRESENT. +setup step2.enable-dnssec.autosign +# DNSKEY TTL: 300 seconds +# zone-propagation-delay: 5 minutes (300 seconds) +# publish-safety: 5 minutes (300 seconds) +# Total: 900 seconds +TpubN="now-900s" +# RRSIG TTL: 12 hour (43200 seconds) +# zone-propagation-delay: 5 minutes (300 seconds) +# Already passed time: -900 seconds +# Total: 42600 seconds +TsbmN="now+42600s" +keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" +CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures have been published long enough to become OMNIPRESENT. +setup step3.enable-dnssec.autosign +# Passed time since publications: 42600 + 900 = 43500 seconds. +TpubN="now-43500s" +# The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT. +TcotN="now-42600s" +# We can submit the DS now. +TsbmN="now" +keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" +CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TcotN -r $O $TcotN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS has been submitted long enough ago to become OMNIPRESENT. +setup step4.enable-dnssec.autosign +# DS TTL: 2 hour (7200 seconds) +# parent-propagation-delay: 1 hour (3600 seconds) +# retire-safety: 20 minutes (1200 seconds) +# Total aditional time: 12000 seconds +# 44700 + 12000 = 56700 +TpubN="now-56700s" +# 43800 + 12000 = 55800 +TcotN="now-55800s" +TsbmN="now-12000s" +keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" +CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -P ds $TsbmN -k $O $TcotN -r $O $TcotN -d $R $TsbmN -z $O $TsbmN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at zsk-prepub.autosign represent the various steps of a ZSK +# Pre-Publication rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.zsk-prepub.autosign +TactN="now" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to pre-publish the successor ZSK. +setup step2.zsk-prepub.autosign +# According to RFC 7583: +# +# Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# Ipub = Dprp + TTLkey (+publish-safety) +# +# |3| |4| |5| |6| +# | | | | +# Key N |<-------Lzsk------>| +# | | | | +# Key N+1 | |<-Ipub->|<-->| +# | | | | +# Key N Tact +# Key N+1 Tpub Trdy Tact +# +# Tnow +# +# Lzsk: 30d +# Dprp: 1h +# TTLkey: 1h +# publish-safety: 1d +# Ipub: 26h +# +# Tact(N) = Tnow + Ipub - Lzsk = now + 26h - 30d +# = now + 26h - 30d = now − 694h +TactN="now-694h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# After the publication interval has passed the DNSKEY of the successor ZSK +# is OMNIPRESENT and the zone can thus be signed with the successor ZSK. +setup step3.zsk-prepub.autosign +# According to RFC 7583: +# +# Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# Tret(N) = Tact(N+1) = Tact(N) + Lzsk +# Trem(N) = Tret(N) + Iret +# Iret = Dsgn + Dprp + TTLsig (+retire-safety) +# +# |3| |4| |5| |6| |7| |8| +# | | | | | | +# Key N |<-------Lzsk------>|<-Iret->|<--->| +# | | | | | | +# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - - +# | | | | | | +# Key N Tact Tret Tdea Trem +# Key N+1 Tpub Trdy Tact +# +# Tnow +# +# Lzsk: 30d +# Ipub: 26h +# Dsgn: 1w +# Dprp: 1h +# TTLsig: 1d +# retire-safety: 2d +# Iret: 10d1h = 241h +# +# Tact(N) = Tnow - Lzsk = now - 30d +# Tret(N) = now +# Trem(N) = Tnow + Iret = now + 241h +# Tpub(N+1) = Tnow - Ipub = now - 26h +# Tret(N+1) = Tnow + Lzsk = now + 30d +# Trem(N+1) = Tnow + Lzsk + Iret = now + 30d + 241h +# = now + 961h +TactN="now-30d" +TretN="now" +TremN="now+241h" +TpubN1="now-26h" +TactN1="now" +TretN1="now+30d" +TremN1="now+961h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -z $H $TpubN1 "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# After the retire interval has passed the predecessor DNSKEY can be +# removed from the zone. +setup step4.zsk-prepub.autosign +# According to RFC 7583: +# +# Tret(N) = Tact(N) + Lzsk +# Tdea(N) = Tret(N) + Iret +# +# |3| |4| |5| |6| |7| |8| +# | | | | | | +# Key N |<-------Lzsk------>|<-Iret->|<--->| +# | | | | | | +# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - - +# | | | | | | +# Key N Tact Tret Tdea Trem +# Key N+1 Tpub Trdy Tact +# +# Tnow +# +# Lzsk: 30d +# Ipub: 26h +# Iret: 241h +# +# Tact(N) = Tnow - Iret - Lzsk +# = now - 241h - 30d = now - 241h - 720h +# = now - 961h +# Tret(N) = Tnow - Iret = now - 241h +# Trem(N) = Tnow +# Tpub(N+1) = Tnow - Iret - Ipub +# = now - 241h - 26h +# = now - 267h +# Tact(N+1) = Tnow - Iret = Tret(N) +# Tret(N+1) = Tnow - Iret + Lzsk +# = now - 241h + 30d = now - 241h + 720h +# = now + 479h +# Trem(N+1) = Tnow + Lzsk = now + 30d +TactN="now-961h" +TretN="now-241h" +TremN="now" +TpubN1="now-267h" +TactN1="${TretN}" +TretN1="now+479h" +TremN1="now+30d" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $U $TretN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $R $TactN1 "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +cp $infile $zonefile +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The predecessor DNSKEY is removed long enough that is has become HIDDEN. +setup step5.zsk-prepub.autosign +# Subtract DNSKEY TTL from all the times (1h). +# Tact(N) = now - 961h - 1h = now - 962h +# Tret(N) = now - 241h - 1h = now - 242h +# Tdea(N) = now - 2d - 1h = now - 49h +# Trem(N) = now - 1h +# Tpub(N+1) = now - 267h - 1h = now - 268h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 479h - 1h = now + 478h +# Trem(N+1) = now + 30d - 1h = now + 719h +TactN="now-962h" +TretN="now-242h" +TremN="now-1h" +TdeaN="now-49h" +TpubN1="now-268h" +TactN1="${TretN}" +TretN1="now+478h" +TremN1="now+719h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $U $TdeaN -z $H $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The predecessor DNSKEY can be purged. +setup step6.zsk-prepub.autosign +# Subtract purge-keys interval from all the times (1h). +# Tact(N) = now - 962h - 1h = now - 963h +# Tret(N) = now - 242h - 1h = now - 243h +# Tdea(N) = now - 49h - 1h = now - 50h +# Trem(N) = now - 1h - 1h = now - 2h +# Tpub(N+1) = now - 268h - 1h = now - 269h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 478h - 1h = now + 477h +# Trem(N+1) = now + 719h - 1h = now + 718h +TactN="now-963h" +TretN="now-243h" +TremN="now-2h" +TdeaN="now-50h" +TpubN1="now-269h" +TactN1="${TretN}" +TretN1="now+477h" +TremN1="now+718h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $H $TdeaN -z $H $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at ksk-doubleksk.autosign represent the various steps of a KSK +# Double-KSK rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.ksk-doubleksk.autosign +TactN="now" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to submit the introduce the new KSK. +setup step2.ksk-doubleksk.autosign +# According to RFC 7583: +# +# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC +# IpubC = DprpC + TTLkey (+publish-safety) +# +# |1| |2| |3| |4| +# | | | | +# Key N |<-IpubC->|<--->|<-Dreg->|<-----Lksk--- - - +# | | | | +# Key N+1 | | | | +# | | | | +# Key N Tpub Trdy Tsbm Tact +# Key N+1 +# +# (continued ...) +# +# |5| |6| |7| |8| |9| |10| +# | | | | | | +# Key N - - --------------Lksk------->|<-Iret->|<----->| +# | | | | | | +# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - +# | | | | | | +# Key N Tret Tdea Trem +# Key N+1 Tpub Trdy Tsbm Tact +# +# Tnow +# +# Lksk: 60d +# Dreg: 1d +# DprpC: 1h +# TTLkey: 2h +# publish-safety: 1d +# IpubC: 27h +# +# Tact(N) = Tnow - Lksk + Dreg + IpubC = now - 60d + 27h +# = now - 1440h + 27h = now - 1413h +TactN="now-1413h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS. +setup step3.ksk-doubleksk.autosign +# According to RFC 7583: +# +# Tsbm(N+1) >= Trdy(N+1) +# Tact(N+1) = Tsbm(N+1) + Dreg +# Iret = DprpP + TTLds (+retire-safety) +# +# |5| |6| |7| |8| |9| |10| +# | | | | | | +# Key N - - --------------Lksk------->|<-Iret->|<----->| +# | | | | | | +# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - +# | | | | | | +# Key N Tret Tdea Trem +# Key N+1 Tpub Trdy Tsbm Tact +# +# Tnow +# +# Lksk: 60d +# Dreg: N/A +# DprpP: 1h +# TTLds: 1h +# retire-safety: 2d +# Iret: 50h +# DprpC: 1h +# TTLkey: 2h +# publish-safety: 1d +# IpubC: 27h +# +# Tact(N) = Tnow + Lksk = now - 60d = now - 60d +# Tret(N) = now +# Trem(N) = Tnow + Iret = now + 50h +# Tpub(N+1) = Tnow - IpubC = now - 27h +# Tsbm(N+1) = now +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow + Lksk = now + 60d +# Trem(N+1) = Tnow + Lksk + Iret = now + 60d + 50h +# = now + 1440h + 50h = 1490h +TactN="now-60d" +TretN="now" +TremN="now+50h" +TpubN1="now-27h" +TsbmN1="now" +TactN1="${TretN}" +TretN1="now+60d" +TremN1="now+1490h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS should be swapped now. +setup step4.ksk-doubleksk.autosign +# According to RFC 7583: +# +# Tret(N) = Tsbm(N+1) +# Tdea(N) = Tret(N) + Iret +# Tact(N+1) = Tret(N) +# +# |5| |6| |7| |8| |9| |10| +# | | | | | | +# Key N - - --------------Lksk------->|<-Iret->|<----->| +# | | | | | | +# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - +# | | | | | | +# Key N Tret Tdea Trem +# Key N+1 Tpub Trdy Tsbm Tact +# +# Tnow +# +# Lksk: 60d +# Dreg: N/A +# Iret: 50h +# +# Tact(N) = Tnow - Lksk - Iret = now - 60d - 50h +# = now - 1440h - 50h = now - 1490h +# Tret(N) = Tnow - Iret = now - 50h +# Trem(N) = Tnow +# Tpub(N+1) = Tnow - Iret - IpubC = now - 50h - 27h +# = now - 77h +# Tsbm(N+1) = Tnow - Iret = now - 50h +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow + Lksk - Iret = now + 60d - 50h = now + 1390h +# Trem(N+1) = Tnow + Lksk = now + 60d +TactN="now-1490h" +TretN="now-50h" +TremN="now" +TpubN1="now-77h" +TsbmN1="now-50h" +TactN1="${TretN}" +TretN1="now+1390h" +TremN1="now+60d" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -D ds $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -P ds $TsbmN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The predecessor DNSKEY is removed long enough that is has become HIDDEN. +setup step5.ksk-doubleksk.autosign +# Subtract DNSKEY TTL from all the times (2h). +# Tact(N) = now - 1490h - 2h = now - 1492h +# Tret(N) = now - 50h - 2h = now - 52h +# Trem(N) = now - 2h +# Tpub(N+1) = now - 77h - 2h = now - 79h +# Tsbm(N+1) = now - 50h - 2h = now - 52h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 1390h - 2h = now + 1388h +# Trem(N+1) = now + 60d - 2h = now + 1442h +TactN="now-1492h" +TretN="now-52h" +TremN="now-2h" +TpubN1="now-79h" +TsbmN1="now-52h" +TactN1="${TretN}" +TretN1="now+1388h" +TremN1="now+1442h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The predecessor DNSKEY can be purged. +setup step6.ksk-doubleksk.autosign +# Subtract purge-keys interval from all the times (1h). +# Tact(N) = now - 1492h - 1h = now - 1493h +# Tret(N) = now - 52h - 1h = now - 53h +# Trem(N) = now - 2h - 1h = now - 3h +# Tpub(N+1) = now - 79h - 1h = now - 80h +# Tsbm(N+1) = now - 52h - 1h = now - 53h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 1388h - 1h = now + 1387h +# Trem(N+1) = now + 1442h - 1h = now + 1441h +TactN="now-1493h" +TretN="now-53h" +TremN="now-3h" +TpubN1="now-80h" +TsbmN1="now-53h" +TactN1="${TretN}" +TretN1="now+1387h" +TremN1="now+1441h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at csk-roll.autosign represent the various steps of a CSK rollover +# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.csk-roll.autosign +TactN="now" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to introduce the new CSK. +setup step2.csk-roll.autosign +# According to RFC 7583: +# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC +# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# IpubC = DprpC + TTLkey (+publish-safety) +# Ipub = IpubC +# Lcsk = Lksk = Lzsk +# +# Lcsk: 6mo (186d, 4464h) +# Dreg: N/A +# DprpC: 1h +# TTLkey: 1h +# publish-safety: 1h +# Ipub: 3h +# +# Tact(N) = Tnow - Lcsk + Ipub = now - 186d + 3h +# = now - 4464h + 3h = now - 4461h +TactN="now-4461h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS and to roll signatures. +setup step3.csk-roll.autosign +# According to RFC 7583: +# +# Tsbm(N+1) >= Trdy(N+1) +# KSK: Tact(N+1) = Tsbm(N+1) +# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1) +# KSK: Iret = DprpP + TTLds (+retire-safety) +# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety) +# +# Lcsk: 186d +# Dprp: 1h +# DprpP: 1h +# Dreg: N/A +# Dsgn: 25d +# TTLds: 1h +# TTLsig: 1d +# retire-safety: 2h +# Iret: 4h +# IretZ: 26d3h +# Ipub: 3h +# +# Tact(N) = Tnow - Lcsk = now - 186d +# Tret(N) = now +# Trem(N) = Tnow + IretZ = now + 26d3h = now + 627h +# Tpub(N+1) = Tnow - Ipub = now - 3h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow + Lcsk = now + 186d = now + 186d +# Trem(N+1) = Tnow + Lcsk + IretZ = now + 186d + 26d3h = +# = now + 5091h +TactN="now-186d" +TretN="now" +TremN="now+627h" +TpubN1="now-3h" +TsbmN1="now" +TactN1="${TretN}" +TretN1="now+186d" +TremN1="now+5091h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# Some time later all the ZRRSIG records should be from the new CSK, and the +# DS should be swapped. The ZRRSIG records are all replaced after IretZ +# (which is 26d3h). The DS is swapped after Iret (which is 4h). +# In other words, the DS is swapped before all zone signatures are replaced. +setup step4.csk-roll.autosign +# According to RFC 7583: +# Trem(N) = Tret(N) - Iret + IretZ +# Tnow = Tsbm(N+1) + Iret +# +# Lcsk: 186d +# Iret: 4h +# IretZ: 26d3h +# +# Tact(N) = Tnow - Iret - Lcsk = now - 4h - 186d = now - 4468h +# Tret(N) = Tnow - Iret = now - 4h = now - 4h +# Trem(N) = Tnow - Iret + IretZ = now - 4h + 26d3h +# = now + 623h +# Tpub(N+1) = Tnow - Iret - IpubC = now - 4h - 3h = now - 7h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow - Iret + Lcsk = now - 4h + 186d = now + 4460h +# Trem(N+1) = Tnow - Iret + Lcsk + IretZ = now - 4h + 186d + 26d3h +# = now + 5087h +TactN="now-4468h" +TretN="now-4h" +TremN="now+623h" +TpubN1="now-7h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+4460h" +TremN1="now+5087h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -z $U $TsbmN1 -D ds $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -z $R $TsbmN1 -P ds $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# After the DS is swapped in step 4, also the KRRSIG records can be removed. +# At this time these have all become hidden. +setup step5.csk-roll.autosign +# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). +# Tact(N) = now - 4468h - 2h = now - 4470h +# Tret(N) = now - 4h - 2h = now - 6h +# Trem(N) = now + 623h - 2h = now + 621h +# Tpub(N+1) = now - 7h - 2h = now - 9h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 4460h - 2h = now + 4458h +# Trem(N+1) = now + 5087h - 2h = now + 5085h +TactN="now-4470h" +TretN="now-6h" +TremN="now+621h" +TpubN1="now-9h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+4458h" +TremN1="now+5085h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $U now-2h -d $H now-2h -z $U $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O now-2h -z $R $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# After the retire interval has passed the predecessor DNSKEY can be +# removed from the zone. +setup step6.csk-roll.autosign +# According to RFC 7583: +# Trem(N) = Tret(N) + IretZ +# Tret(N) = Tact(N) + Lcsk +# +# Lcsk: 186d +# Iret: 4h +# IretZ: 26d3h +# +# Tact(N) = Tnow - IretZ - Lcsk = now - 627h - 186d +# = now - 627h - 4464h = now - 5091h +# Tret(N) = Tnow - IretZ = now - 627h +# Trem(N) = Tnow +# Tpub(N+1) = Tnow - IretZ - Ipub = now - 627h - 3h = now - 630h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow - IretZ + Lcsk = now - 627h + 186d = now + 3837h +# Trem(N+1) = Tnow + Lcsk = now + 186d +TactN="now-5091h" +TretN="now-627h" +TremN="now" +TpubN1="now-630h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+3837h" +TremN1="now+186d" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $H $TremN -d $H $TremN -z $U $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $R $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 7: +# Some time later the predecessor DNSKEY enters the HIDDEN state. +setup step7.csk-roll.autosign +# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). +# Tact(N) = now - 5091h - 2h = now - 5093h +# Tret(N) = now - 627h - 2h = now - 629h +# Trem(N) = now - 2h +# Tpub(N+1) = now - 630h - 2h = now - 632h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 3837h - 2h = now + 3835h +# Trem(N+1) = now + 186d - 2h = now + 4462h +TactN="now-5093h" +TretN="now-629h" +TremN="now-2h" +TpubN1="now-632h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+3835h" +TremN1="now+4462h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 8: +# The predecessor DNSKEY can be purged. +setup step8.csk-roll.autosign +# Subtract purge-keys interval from all the times (1h). +# Tact(N) = now - 5093h - 1h = now - 5094h +# Tret(N) = now - 629h - 1h = now - 630h +# Trem(N) = now - 2h - 1h = now - 3h +# Tpub(N+1) = now - 632h - 1h = now - 633h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 3835h - 1h = now + 3834h +# Trem(N+1) = now + 4462h - 1h = now + 4461h +TactN="now-5094h" +TretN="now-630h" +TremN="now-3h" +TpubN1="now-633h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+3834h" +TremN1="now+4461h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $H $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at csk-roll2.autosign represent the various steps of a CSK rollover +# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). +# This scenario differs from the above one because the zone signatures (ZRRSIG) +# are replaced with the new key sooner than the DS is swapped. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.csk-roll2.autosign +TactN="now" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to introduce the new CSK. +setup step2.csk-roll2.autosign +# According to RFC 7583: +# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC +# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# IpubC = DprpC + TTLkey (+publish-safety) +# Ipub = IpubC +# Lcsk = Lksk = Lzsk +# +# Lcsk: 6mo (186d, 4464h) +# Dreg: N/A +# DprpC: 1h +# TTLkey: 1h +# publish-safety: 1h +# Ipub: 3h +# +# Tact(N) = Tnow - Lcsk + Ipub = now - 186d + 3h +# = now - 4464h + 3h = now - 4461h +TactN="now-4461h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS and to roll signatures. +setup step3.csk-roll2.autosign +# According to RFC 7583: +# +# Tsbm(N+1) >= Trdy(N+1) +# KSK: Tact(N+1) = Tsbm(N+1) +# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1) +# KSK: Iret = DprpP + TTLds (+retire-safety) +# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety) +# +# Lcsk: 186d +# Dprp: 1h +# DprpP: 1w +# Dreg: N/A +# Dsgn: 12h +# TTLds: 1h +# TTLsig: 1d +# retire-safety: 1h +# Iret: 170h +# IretZ: 38h +# Ipub: 3h +# +# Tact(N) = Tnow - Lcsk = now - 186d +# Tret(N) = now +# Trem(N) = Tnow + Iret = now + 170h +# Tpub(N+1) = Tnow - Ipub = now - 3h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow + Lcsk = now + 186d +# Trem(N+1) = Tnow + Lcsk + Iret = now + 186d + 170h = +# = now + 4464h + 170h = now + 4634h +TactN="now-186d" +TretN="now" +TremN="now+170h" +TpubN1="now-3h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+186d" +TremN1="now+4634h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# Some time later all the ZRRSIG records should be from the new CSK, and the +# DS should be swapped. The ZRRSIG records are all replaced after IretZ (38h). +# The DS is swapped after Dreg + Iret (1w3h). In other words, the zone +# signatures are replaced before the DS is swapped. +setup step4.csk-roll2.autosign +# According to RFC 7583: +# Trem(N) = Tret(N) + IretZ +# +# Lcsk: 186d +# Dreg: N/A +# Iret: 170h +# IretZ: 38h +# +# Tact(N) = Tnow - IretZ = Lcsk = now - 38h - 186d +# = now - 38h - 4464h = now - 4502h +# Tret(N) = Tnow - IretZ = now - 38h +# Trem(N) = Tnow - IretZ + Iret = now - 38h + 170h = now + 132h +# Tpub(N+1) = Tnow - IretZ - IpubC = now - 38h - 3h = now - 41h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = Tnow - IretZ + Lcsk = now - 38h + 186d +# = now + 4426h +# Trem(N+1) = Tnow - IretZ + Lcsk + Iret +# = now + 4426h + 3h = now + 4429h +TactN="now-4502h" +TretN="now-38h" +TremN="now+132h" +TpubN1="now-41h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+4426h" +TremN1="now+4429h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $U $TretN -d $U $TsbmN1 -D ds $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -z $R $TactN1 -d $R $TsbmN1 -P ds $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# Some time later the DS can be swapped and the old DNSKEY can be removed from +# the zone. +setup step5.csk-roll2.autosign +# Subtract Iret (170h) - IretZ (38h) = 132h. +# +# Tact(N) = now - 4502h - 132h = now - 4634h +# Tret(N) = now - 38h - 132h = now - 170h +# Trem(N) = now + 132h - 132h = now +# Tpub(N+1) = now - 41h - 132h = now - 173h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 4426h - 132h = now + 4294h +# Trem(N+1) = now + 4492h - 132h = now + 4360h +TactN="now-4634h" +TretN="now-170h" +TremN="now" +TpubN1="now-173h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+4294h" +TremN1="now+4360h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $H now-133h -d $U $TsbmN1 -D ds $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -z $O now-133h -d $R $TsbmN1 -P ds $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# Some time later the predecessor DNSKEY enters the HIDDEN state. +setup step6.csk-roll2.autosign +# Subtract DNSKEY TTL plus zone propagation delay (2h). +# +# Tact(N) = now - 4634h - 2h = now - 4636h +# Tret(N) = now - 170h - 2h = now - 172h +# Trem(N) = now - 2h +# Tpub(N+1) = now - 173h - 2h = now - 175h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 4294h - 2h = now + 4292h +# Trem(N+1) = now + 4360h - 2h = now + 4358h +TactN="now-4636h" +TretN="now-172h" +TremN="now-2h" +TpubN1="now-175h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+4292h" +TremN1="now+4358h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TremN -z $H now-135h "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $O now-135h "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 7: +# The predecessor DNSKEY can be purged, but purge-keys is disabled. +setup step7.csk-roll2.autosign +# Subtract 90 days (default, 2160h) from all the times. +# Tact(N) = now - 4636h - 2160h = now - 6796h +# Tret(N) = now - 172h - 2160h = now - 2332h +# Trem(N) = now - 2h - 2160h = now - 2162h +# Tpub(N+1) = now - 175h - 2160h = now - 2335h +# Tsbm(N+1) = Tret(N) +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 4294h - 2160h = now + 2134h +# Trem(N+1) = now + 4360h - 2160h = now + 2200h +TactN="now-6796h" +TretN="now-2332h" +TremN="now-2162h" +TpubN1="now-2335h" +TsbmN1="${TretN}" +TactN1="${TretN}" +TretN1="now+2134h" +TremN1="now+2200h" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -P sync ${TsbmN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll2 -l policies/autosign.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TremN -z $H now-135h "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $O $TremN -z $O now-135h "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-256,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Test #2375, the "three is a crowd" bug, where a new key is introduced but the +# previous rollover has not finished yet. In other words, we have a key KEY2 +# that is the successor of key KEY1, and we introduce a new key KEY3 that is +# the successor of key KEY2: +# +# KEY1 < KEY2 < KEY3. +# +# The expected behavior is that all three keys remain in the zone, and not +# the bug behavior where KEY2 is removed and immediately replaced with KEY3. +# +# Set up a zone that has a KSK (KEY1) and have the successor key (KEY2) +# published as well. +setup three-is-a-crowd.kasp +# These times are the same as step3.ksk-doubleksk.autosign. +TactN="now-60d" +TretN="now" +TremN="now+50h" +TpubN1="now-27h" +TsbmN1="now" +TactN1="${TretN}" +TretN1="now+60d" +TremN1="now+1490h" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/kasp/ns3/template.db.in b/bin/tests/system/kasp/ns3/template.db.in new file mode 100644 index 0000000..010b05b --- /dev/null +++ b/bin/tests/system/kasp/ns3/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/ns3/template2.db.in b/bin/tests/system/kasp/ns3/template2.db.in new file mode 100644 index 0000000..7b94ace --- /dev/null +++ b/bin/tests/system/kasp/ns3/template2.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 2 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.11 +b A 10.0.0.22 +c A 10.0.0.33 +d A 10.0.0.44 diff --git a/bin/tests/system/kasp/ns4/example1.db.in b/bin/tests/system/kasp/ns4/example1.db.in new file mode 100644 index 0000000..c9e537f --- /dev/null +++ b/bin/tests/system/kasp/ns4/example1.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns4 +ns4 A 10.53.0.4 + +view TXT "view1" diff --git a/bin/tests/system/kasp/ns4/example2.db.in b/bin/tests/system/kasp/ns4/example2.db.in new file mode 100644 index 0000000..c1f16a2 --- /dev/null +++ b/bin/tests/system/kasp/ns4/example2.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns4 +ns4 A 10.53.0.4 + +view TXT "view2" diff --git a/bin/tests/system/kasp/ns4/named.conf.in b/bin/tests/system/kasp/ns4/named.conf.in new file mode 100644 index 0000000..df02b2d --- /dev/null +++ b/bin/tests/system/kasp/ns4/named.conf.in @@ -0,0 +1,173 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key "sha1" { + algorithm "hmac-sha1"; + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +}; + +key "sha224" { + algorithm "hmac-sha224"; + secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="; +}; + +key "sha256" { + algorithm "hmac-sha256"; + secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="; +}; + +key "keyforview1" { + algorithm @DEFAULT_HMAC@; + secret "YPfMoAk6h+3iN8MDRQC004iSNHY="; +}; + +key "keyforview2" { + algorithm @DEFAULT_HMAC@; + secret "4xILSZQnuO1UKubXHkYUsvBRPu8="; +}; + +key "keyforview3" { + algorithm @DEFAULT_HMAC@; + secret "C1Azf+gGPMmxrUg/WQINP6eV9Y0="; +}; + +dnssec-policy "test" { + keys { + csk key-directory lifetime 0 algorithm 14; + }; +}; + +options { + query-source address 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-policy "test"; + dnssec-validation no; +}; + +view "inherit" { + match-clients { key "sha1"; }; + + /* Inherit dnssec-policy 'test' */ + zone "inherit.inherit.signed" { + type primary; + file "inherit.inherit.signed.db"; + }; + + /* Override dnssec-policy */ + zone "override.inherit.signed" { + type primary; + file "override.inherit.signed.db"; + dnssec-policy "default"; + }; + + /* Unset dnssec-policy */ + zone "none.inherit.signed" { + type primary; + file "none.inherit.signed.db"; + dnssec-policy "none"; + }; +}; + +view "override" { + match-clients { key "sha224"; }; + dnssec-policy "default"; + + /* Inherit dnssec-policy 'test' */ + zone "inherit.override.signed" { + type primary; + file "inherit.override.signed.db"; + }; + + /* Override dnssec-policy */ + zone "override.override.signed" { + type primary; + file "override.override.signed.db"; + dnssec-policy "test"; + }; + + /* Unset dnssec-policy */ + zone "none.override.signed" { + type primary; + file "none.override.signed.db"; + dnssec-policy "none"; + }; +}; + +view "none" { + match-clients { key "sha256"; }; + dnssec-policy "none"; + + /* Inherit dnssec-policy 'none' */ + zone "inherit.none.signed" { + type primary; + file "inherit.none.signed.db"; + }; + + /* Override dnssec-policy */ + zone "override.none.signed" { + type primary; + file "override.none.signed.db"; + dnssec-policy "test"; + }; + + /* Unset dnssec-policy */ + zone "none.none.signed" { + type primary; + file "none.none.signed.db"; + dnssec-policy "none"; + }; +}; + +view "example1" { + match-clients { key "keyforview1"; }; + + allow-update { any; }; + + zone "example.net" { + type primary; + inline-signing no; + file "example1.db"; + }; +}; + +view "example2" { + match-clients { key "keyforview2"; }; + + zone "example.net" { + type primary; + file "example2.db"; + }; +}; + +view "example3" { + match-clients { key "keyforview3"; }; + zone "example.net" { + in-view example2; + }; +}; diff --git a/bin/tests/system/kasp/ns4/setup.sh b/bin/tests/system/kasp/ns4/setup.sh new file mode 100644 index 0000000..c488bc4 --- /dev/null +++ b/bin/tests/system/kasp/ns4/setup.sh @@ -0,0 +1,32 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns4/setup.sh" + +# +# Set up zones that potentially will be initially signed. +# +for zn in inherit.inherit override.inherit none.inherit \ + inherit.override override.override none.override \ + inherit.none override.none none.none; do + zone="$zn.signed" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + cp template.db.in $zonefile +done + +cp example1.db.in example1.db +cp example2.db.in example2.db diff --git a/bin/tests/system/kasp/ns4/template.db.in b/bin/tests/system/kasp/ns4/template.db.in new file mode 100644 index 0000000..0f72e9c --- /dev/null +++ b/bin/tests/system/kasp/ns4/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns4 +ns4 A 10.53.0.4 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/ns5/named.conf.in b/bin/tests/system/kasp/ns5/named.conf.in new file mode 100644 index 0000000..9585103 --- /dev/null +++ b/bin/tests/system/kasp/ns5/named.conf.in @@ -0,0 +1,130 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +key "sha1" { + algorithm "hmac-sha1"; + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +}; + +key "sha224" { + algorithm "hmac-sha224"; + secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="; +}; + +key "sha256" { + algorithm "hmac-sha256"; + secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="; +}; + +dnssec-policy "test" { + keys { + csk key-directory lifetime 0 algorithm 14; + }; +}; + +options { + query-source address 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-policy "none"; + dnssec-validation no; +}; + +view "inherit" { + match-clients { key "sha1"; }; + + /* Inherit dnssec-policy 'none' */ + zone "inherit.inherit.unsigned" { + type primary; + file "inherit.inherit.unsigned.db"; + }; + + /* Override dnssec-policy */ + zone "override.inherit.unsigned" { + type primary; + file "override.inherit.unsigned.db"; + dnssec-policy "default"; + }; + + /* Unset dnssec-policy */ + zone "none.inherit.unsigned" { + type primary; + file "none.inherit.unsigned.db"; + dnssec-policy "none"; + }; +}; + +view "override" { + match-clients { key "sha224"; }; + dnssec-policy "default"; + + /* Inherit dnssec-policy 'default' */ + zone "inherit.override.unsigned" { + type primary; + file "inherit.override.unsigned.db"; + }; + + /* Override dnssec-policy */ + zone "override.override.unsigned" { + type primary; + file "override.override.unsigned.db"; + dnssec-policy "test"; + }; + + /* Unset dnssec-policy */ + zone "none.override.unsigned" { + type primary; + file "none.override.unsigned.db"; + dnssec-policy "none"; + }; +}; + +view "none" { + match-clients { key "sha256"; }; + dnssec-policy "none"; + + /* Inherit dnssec-policy 'none' */ + zone "inherit.none.unsigned" { + type primary; + file "inherit.none.unsigned.db"; + }; + + /* Override dnssec-policy */ + zone "override.none.unsigned" { + type primary; + file "override.none.unsigned.db"; + dnssec-policy "test"; + }; + + /* Unset dnssec-policy */ + zone "none.none.unsigned" { + type primary; + file "none.none.unsigned.db"; + dnssec-policy "none"; + }; +}; diff --git a/bin/tests/system/kasp/ns5/setup.sh b/bin/tests/system/kasp/ns5/setup.sh new file mode 100644 index 0000000..47d2870 --- /dev/null +++ b/bin/tests/system/kasp/ns5/setup.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns5/setup.sh" + +# +# Set up zones that potentially will be initially signed. +# +for zn in inherit.inherit override.inherit none.inherit \ + inherit.override override.override none.override \ + inherit.none override.none none.none; do + zone="$zn.unsigned" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + cp template.db.in $zonefile +done diff --git a/bin/tests/system/kasp/ns5/template.db.in b/bin/tests/system/kasp/ns5/template.db.in new file mode 100644 index 0000000..6cb07a4 --- /dev/null +++ b/bin/tests/system/kasp/ns5/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 +ns5 A 10.53.0.5 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/ns6/example.db.in b/bin/tests/system/kasp/ns6/example.db.in new file mode 100644 index 0000000..d6b912c --- /dev/null +++ b/bin/tests/system/kasp/ns6/example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/kasp/ns6/example2.db.in b/bin/tests/system/kasp/ns6/example2.db.in new file mode 100644 index 0000000..46aed9b --- /dev/null +++ b/bin/tests/system/kasp/ns6/example2.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 2 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/kasp/ns6/example3.db.in b/bin/tests/system/kasp/ns6/example3.db.in new file mode 100644 index 0000000..ccbd96a --- /dev/null +++ b/bin/tests/system/kasp/ns6/example3.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 400 +@ IN SOA mname1. . ( + 3 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in new file mode 100644 index 0000000..b8d36dc --- /dev/null +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -0,0 +1,125 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +include "policies/kasp.conf"; +include "policies/csk1.conf"; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + key-directory "."; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +/* This zone switch from dynamic to inline-signing. */ +zone "dynamic2inline.kasp" { + type primary; + file "dynamic2inline.kasp.db"; + allow-update { any; }; + dnssec-policy "default"; +}; + +/* These zones are going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "unsigning"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + dnssec-policy "unsigning"; + inline-signing no; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "default"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "default"; + allow-update { any; }; +}; + +/* These are alorithm rollover test zones. */ +zone "step1.algorithm-roll.kasp" { + type primary; + file "step1.algorithm-roll.kasp.db"; + dnssec-policy "rsasha256"; +}; + +zone "step1.csk-algorithm-roll.kasp" { + type primary; + file "step1.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone example { + type primary; + file "example.db"; + dnssec-policy modified; +}; + +zone longer-lifetime { + type primary; + file "longer-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone shorter-lifetime { + type primary; + file "shorter-lifetime.db"; + dnssec-policy long-lifetime; +}; + +zone limit-lifetime { + type primary; + file "limit-lifetime.db"; + dnssec-policy unlimited-lifetime; +}; + +zone unlimit-lifetime { + type primary; + file "unlimit-lifetime.db"; + dnssec-policy short-lifetime; +}; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in new file mode 100644 index 0000000..0c9d6b0 --- /dev/null +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -0,0 +1,203 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +include "policies/kasp.conf"; +include "policies/csk2.conf"; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +/* This zone switch from dynamic to inline-signing. */ +zone "dynamic2inline.kasp" { + type primary; + file "dynamic2inline.kasp.db"; + allow-update { any; }; + dnssec-policy "default"; +}; + +/* Zones for testing going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step2.going-insecure.kasp" { + type primary; + file "step2.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step2.going-insecure-dynamic.kasp" { + type primary; + file "step2.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "none"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "none"; + allow-update { any; }; +}; + +/* + * Zones for testing KSK/ZSK algorithm roll. + */ +zone "step1.algorithm-roll.kasp" { + type primary; + file "step1.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +zone "step2.algorithm-roll.kasp" { + type primary; + file "step2.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +zone "step3.algorithm-roll.kasp" { + type primary; + file "step3.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +zone "step4.algorithm-roll.kasp" { + type primary; + file "step4.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +zone "step5.algorithm-roll.kasp" { + type primary; + file "step5.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +zone "step6.algorithm-roll.kasp" { + type primary; + file "step6.algorithm-roll.kasp.db"; + dnssec-policy "ecdsa256"; +}; + +/* + * Zones for testing CSK algorithm roll. + */ +zone "step1.csk-algorithm-roll.kasp" { + type primary; + file "step1.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone "step2.csk-algorithm-roll.kasp" { + type primary; + file "step2.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone "step3.csk-algorithm-roll.kasp" { + type primary; + file "step3.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone "step4.csk-algorithm-roll.kasp" { + type primary; + file "step4.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone "step5.csk-algorithm-roll.kasp" { + type primary; + file "step5.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone "step6.csk-algorithm-roll.kasp" { + type primary; + file "step6.csk-algorithm-roll.kasp.db"; + dnssec-policy "csk-algoroll"; +}; + +zone example { + type primary; + file "example.db"; + dnssec-policy modified; +}; + +zone longer-lifetime { + type primary; + file "longer-lifetime.db"; + dnssec-policy long-lifetime; +}; + +zone shorter-lifetime { + type primary; + file "shorter-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone limit-lifetime { + type primary; + file "limit-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone unlimit-lifetime { + type primary; + file "unlimit-lifetime.db"; + dnssec-policy unlimited-lifetime; +}; diff --git a/bin/tests/system/kasp/ns6/policies/csk1.conf.in b/bin/tests/system/kasp/ns6/policies/csk1.conf.in new file mode 100644 index 0000000..a5ff042 --- /dev/null +++ b/bin/tests/system/kasp/ns6/policies/csk1.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "csk-algoroll" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + csk lifetime unlimited algorithm rsasha256; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/kasp/ns6/policies/csk2.conf.in b/bin/tests/system/kasp/ns6/policies/csk2.conf.in new file mode 100644 index 0000000..6d290c3 --- /dev/null +++ b/bin/tests/system/kasp/ns6/policies/csk2.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "csk-algoroll" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in new file mode 100644 index 0000000..51c4d88 --- /dev/null +++ b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in @@ -0,0 +1,86 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "unsigning" { + dnskey-ttl 7200; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "nsec3" { + nsec3param iterations 0 optout no salt-length 0; +}; + +dnssec-policy "modified" { + keys { + csk lifetime unlimited algorithm rsasha256 2048; + }; +}; + +dnssec-policy "unlimited-lifetime" { + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; +dnssec-policy "short-lifetime" { + keys { + csk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "long-lifetime" { + keys { + csk lifetime P1Y algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "rsasha256" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + ksk lifetime unlimited algorithm rsasha256; + zsk lifetime unlimited algorithm rsasha256; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; + +dnssec-policy "ecdsa256" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + ksk lifetime unlimited algorithm ecdsa256; + zsk lifetime unlimited algorithm ecdsa256; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/kasp/ns6/policies/kasp.conf.in b/bin/tests/system/kasp/ns6/policies/kasp.conf.in new file mode 100644 index 0000000..d634b76 --- /dev/null +++ b/bin/tests/system/kasp/ns6/policies/kasp.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "policies/kasp-fips.conf"; + +dnssec-policy "rsasha1" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + ksk lifetime unlimited algorithm rsasha1; + zsk lifetime unlimited algorithm rsasha1; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh new file mode 100644 index 0000000..fcdabad --- /dev/null +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -0,0 +1,425 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns6/setup.sh" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" +} + +# Make lines shorter by storing key states in environment variables. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" + +for zn in shorter-lifetime longer-lifetime limit-lifetime unlimit-lifetime; do + setup $zn + cp template.db.in $zonefile +done + +# The child zones (step1, step2) beneath these zones represent the various +# steps of unsigning a zone. +for zn in going-insecure.kasp going-insecure-dynamic.kasp; do + # Step 1: + # Set up a zone with dnssec-policy that is going insecure. + setup step1.$zn + echo "$zone" >>zones + T="now-10d" + ksktimes="-P $T -A $T -P sync $T" + zsktimes="-P $T -A $T" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + + # Step 2: + # Set up a zone with dnssec-policy that is going insecure. Don't add + # this zone to the zones file, because this zone is no longer expected + # to be fully signed. + setup step2.$zn + # The DS was withdrawn from the parent zone 26 hours ago. + Trem="now-26h" + ksktimes="-P $T -A $T -P sync $T" + zsktimes="-P $T -A $T" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) + $SETTIME -s -g $H -k $O $T -r $O $T -d $U $Trem -D ds $Trem "$KSK" >settime.out.$zone.1 2>&1 + $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 + # Fake lifetime of old algorithm keys. + echo "Lifetime: 0" >>"${KSK}.state" + echo "Lifetime: 5184000" >>"${ZSK}.state" + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +done + +# This zone is going straight to "none" policy. This is undefined behavior. +setup step1.going-straight-to-none.kasp +echo "$zone" >>zones +TactN="now" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# This zone is going straight to "none" policy. This is undefined behavior. +setup step1.going-straight-to-none-dynamic.kasp +echo "$zone" >>zones +TactN="now" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O full -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK +# algorithm rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.algorithm-roll.kasp +echo "$zone" >>zones +TactN="now" +ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a RSASHA256 -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone 8 "$KSK" >>"$infile" +private_type_record $zone 8 "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# After the publication interval has passed the DNSKEY is OMNIPRESENT. +setup step2.algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 3 hours. +TactN="now-3h" +TpubN1="now-3h" +# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = +# now - 3h + 6h + 1h = now + 4h +TsbmN1="now+4h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now" +zsk1times="-P ${TactN} -A ${TactN} -I now" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures are also OMNIPRESENT. +setup step3.algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 7 hours. +TactN="now-7h" +TretN="now-3h" +TpubN1="now-7h" +TsbmN1="now" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS is swapped and can become OMNIPRESENT. +setup step4.algorithm-roll.kasp +# The time passed since the DS has been swapped is 29 hours. +TactN="now-36h" +TretN="now-33h" +TpubN1="now-36h" +TsbmN1="now-29h" +TactN1="now-27h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TactN1 -D ds $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $R $TactN1 -P ds $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The DNSKEY is removed long enough to be HIDDEN. +setup step5.algorithm-roll.kasp +# The time passed since the DNSKEY has been removed is 2 hours. +TactN="now-38h" +TretN="now-35h" +TremN="now-2h" +TpubN1="now-38h" +TsbmN1="now-31h" +TactN1="now-29h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $U $TremN -z $U $TremN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The RRSIGs have been removed long enough to be HIDDEN. +setup step6.algorithm-roll.kasp +# Additional time passed: 7h. +TactN="now-45h" +TretN="now-42h" +TremN="now-7h" +TpubN1="now-45h" +TsbmN1="now-38h" +TactN1="now-36h" +TdeaN="now-7h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -d $H $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $H $TremN -z $U $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at csk-algorithm-roll.kasp represent the various steps of a CSK +# algorithm rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.csk-algorithm-roll.kasp +echo "$zone" >>zones +TactN="now" +csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone 5 "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# After the publication interval has passed the DNSKEY is OMNIPRESENT. +setup step2.csk-algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 3 hours. +TactN="now-3h" +TpubN1="now-3h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures are also OMNIPRESENT. +setup step3.csk-algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 7 hours. +TactN="now-7h" +TretN="now-3h" +TpubN1="now-7h" +TactN1="now-3h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS is swapped and can become OMNIPRESENT. +setup step4.csk-algorithm-roll.kasp +# The time passed since the DS has been swapped is 29 hours. +TactN="now-36h" +TretN="now-33h" +TpubN1="now-36h" +TactN1="now-33h" +TsubN1="now-29h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $U $TactN1 -D ds $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $R $TsubN1 -P ds $TsubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The DNSKEY is removed long enough to be HIDDEN. +setup step5.csk-algorithm-roll.kasp +# The time passed since the DNSKEY has been removed is 2 hours. +TactN="now-38h" +TretN="now-35h" +TremN="now-2h" +TpubN1="now-38h" +TactN1="now-35h" +TsubN1="now-31h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TremN -r $U $TremN -z $U $TremN -d $H $TremN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TremN "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The RRSIGs have been removed long enough to be HIDDEN. +setup step6.csk-algorithm-roll.kasp +# Additional time passed: 7h. +TactN="now-45h" +TretN="now-42h" +TdeaN="now-9h" +TremN="now-7h" +TpubN1="now-45h" +TactN1="now-42h" +TsubN1="now-38h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -z $U $TdeaN -d $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# Reload testing +# +echo "example" >>zones +cp example.db.in example.db + +setup "dynamic2inline.kasp" +cp template.db.in $zonefile diff --git a/bin/tests/system/kasp/ns6/template.db.in b/bin/tests/system/kasp/ns6/template.db.in new file mode 100644 index 0000000..f1d8b94 --- /dev/null +++ b/bin/tests/system/kasp/ns6/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/kasp/setup.sh b/bin/tests/system/kasp/setup.sh new file mode 100644 index 0000000..ccc4533 --- /dev/null +++ b/bin/tests/system/kasp/setup.sh @@ -0,0 +1,68 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +mkdir keys +mkdir ns3/keys + +copy_setports ns2/named.conf.in ns2/named.conf +if [ $RSASHA1_SUPPORTED = 0 ]; then + copy_setports ns3/named-fips.conf.in ns3/named.conf +else + copy_setports ns3/named-fips.conf.in ns3/named-fips.conf + copy_setports ns3/named.conf.in ns3/named.conf +fi +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf + +copy_setports ns3/policies/autosign.conf.in ns3/policies/autosign.conf +copy_setports ns3/policies/kasp-fips.conf.in ns3/policies/kasp-fips.conf +copy_setports ns3/policies/kasp.conf.in ns3/policies/kasp.conf +if [ $RSASHA1_SUPPORTED = 0 ]; then + cp ns3/policies/kasp-fips.conf ns3/policies/kasp.conf +fi + +copy_setports ns6/policies/csk1.conf.in ns6/policies/csk1.conf +copy_setports ns6/policies/csk2.conf.in ns6/policies/csk2.conf +copy_setports ns6/policies/kasp-fips.conf.in ns6/policies/kasp-fips.conf +copy_setports ns6/policies/kasp.conf.in ns6/policies/kasp.conf +if [ $RSASHA1_SUPPORTED = 0 ]; then + cp ns6/policies/kasp-fips.conf ns6/policies/kasp.conf +fi + +# Setup zones +( + cd ns2 + $SHELL setup.sh +) +( + cd ns3 + $SHELL setup.sh +) +( + cd ns4 + $SHELL setup.sh +) +( + cd ns5 + $SHELL setup.sh +) +( + cd ns6 + $SHELL setup.sh +) diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh new file mode 100644 index 0000000..441faaa --- /dev/null +++ b/bin/tests/system/kasp/tests.sh @@ -0,0 +1,3316 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh +# shellcheck source=kasp.sh +. ../kasp.sh + +start_time="$(TZ=UTC date +%s)" +status=0 +n=0 + +############################################################################### +# Utilities # +############################################################################### + +# Call dig with default options. +dig_with_opts() { + + if [ -n "$TSIG" ]; then + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@" + else + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" + fi +} + +# RNDC. +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +# Log error and increment failure rate. +log_error() { + echo_i "error: $1" + ret=$((ret + 1)) +} + +# Default next key event threshold. May be extended by wait periods. +next_key_event_threshold=100 + +############################################################################### +# Tests # +############################################################################### + +# +# named +# + +# The NSEC record at the apex of the zone and its RRSIG records are +# added as part of the last step in signing a zone. We wait for the +# NSEC records to appear before proceeding with a counter to prevent +# infinite loops if there is an error. +n=$((n + 1)) +echo_i "waiting for kasp signing changes to take effect ($n)" +ret=0 + +_wait_for_done_apexnsec() { + while read -r zone; do + dig_with_opts "$zone" @10.53.0.3 nsec >"dig.out.ns3.test$n.$zone" || return 1 + grep "NS SOA" "dig.out.ns3.test$n.$zone" >/dev/null || return 1 + grep "$zone\..*IN.*RRSIG" "dig.out.ns3.test$n.$zone" >/dev/null || return 1 + done "dig.out.ns6.test$n.$zone" || return 1 + grep "NS SOA" "dig.out.ns6.test$n.$zone" >/dev/null || return 1 + grep "$zone\..*IN.*RRSIG" "dig.out.ns6.test$n.$zone" >/dev/null || return 1 + done published.test${n}.key1 + published=$(awk '{print $3}' published.test${n}.key2 + published=$(awk '{print $3}' published.test${n}.key3 + published=$(awk '{print $3}' "dig.out.$DIR.test$n" || return 1 + # We should have three ZSKs. + lines=$(grep "256 3 13" dig.out.$DIR.test$n | wc -l) + test "$lines" -eq $num || return 1 + # And one KSK. + lines=$(grep "257 3 13" dig.out.$DIR.test$n | wc -l) + test "$lines" -eq 1 || return 1 +} +n=$((n + 1)) +echo_i "check initial number of ZSKs (one from us and one from another provider) for zone ${ZONE} ($n)" +ret=0 +retry_quiet 10 zsks_are_published 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "update zone with ZSK from another provider for zone ${ZONE} ($n)" +ret=0 +( + echo zone ${ZONE} + echo server 10.53.0.3 "$PORT" + echo update add $(cat "${DIR}/${ZONE}.zsk2") + echo send +) | $NSUPDATE +retry_quiet 10 zsks_are_published 3 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove ZSKs from the other providers for zone ${ZONE} ($n)" +ret=0 +( + echo zone ${ZONE} + echo server 10.53.0.3 "$PORT" + echo update del $(cat "${DIR}/${ZONE}.zsk1") + echo update del $(cat "${DIR}/${ZONE}.zsk2") + echo send +) | $NSUPDATE +retry_quiet 10 zsks_are_published 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# A zone transitioning from single-signed to multi-signed. +# We should have the old omnipresent keys outside of the +# desired key range and the new keys in the desired key range +# KEY1 and KEY2 are the new keys. KEY3 and KEY4 are the old keys. +# +set_zone "single-to-multisigner.kasp" +set_policy "multisigner-model2" "4" "3600" +set_server "ns3" "10.53.0.3" +key_clear "KEY1" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Key properties. +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "0" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "no" # waiting for DNSKEY to be omnipresent + +set_keyrole "KEY3" "ksk" +set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" + +set_keyrole "KEY4" "zsk" +set_keyalgorithm "KEY4" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY4" "no" +set_zonesigning "KEY4" "yes" + +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "rumoured" +set_keystate "KEY1" "STATE_KRRSIG" "rumoured" +set_keystate "KEY1" "STATE_DS" "hidden" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "rumoured" +set_keystate "KEY2" "STATE_ZRRSIG" "hidden" # waiting for DNSKEY to be omnipresent + +set_keystate "KEY3" "GOAL" "hidden" +set_keystate "KEY3" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY3" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY3" "STATE_DS" "omnipresent" + +set_keystate "KEY4" "GOAL" "hidden" +set_keystate "KEY4" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY4" "STATE_ZRRSIG" "omnipresent" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# KEY1 tag range 32768 65535 +# KEY2 tag range 32768 65535 +# KEY3 tag range 0 32767 +# KEY4 tag range 0 32767 +n=$((n + 1)) +echo_i "check that the key IDs are in the expected ranges ($n)" +ret=0 +test $(key_get KEY1 ID) -ge 32768 -a $(key_get KEY1 ID) -le 65535 || ret=1 +test $(key_get KEY2 ID) -ge 32768 -a $(key_get KEY2 ID) -le 65535 || ret=1 +test $(key_get KEY3 ID) -ge 0 -a $(key_get KEY3 ID) -le 32767 || ret=1 +test $(key_get KEY4 ID) -ge 0 -a $(key_get KEY4 ID) -le 32767 || ret=1 + +test $(key_get KEY1 RID) -ge 32768 -a $(key_get KEY1 RID) -le 65535 || ret=1 +test $(key_get KEY2 RID) -ge 32768 -a $(key_get KEY2 RID) -le 65535 || ret=1 +test $(key_get KEY3 RID) -ge 0 -a $(key_get KEY3 RID) -le 32767 || ret=1 +test $(key_get KEY4 RID) -ge 0 -a $(key_get KEY4 RID) -le 32767 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# Testing manual rollover. +# +set_zone "manual-rollover.kasp" +set_policy "manual-rollover" "2" "3600" +set_server "ns3" "10.53.0.3" +key_clear "KEY1" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" +# Key properties. +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "0" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +# During set up everything was set to OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# The first keys were published and activated a day ago. +created=$(key_get KEY1 CREATED) +set_addkeytime "KEY1" "PUBLISHED" "${created}" -86400 +set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -86400 +set_addkeytime "KEY1" "ACTIVE" "${created}" -86400 +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" -86400 +set_addkeytime "KEY2" "ACTIVE" "${created}" -86400 +# Key lifetimes are unlimited, so not setting RETIRED and REMOVED. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Schedule KSK rollover in six months (15552000 seconds). +active=$(key_get KEY1 ACTIVE) +set_addkeytime "KEY1" "RETIRED" "${active}" 15552000 +retired=$(key_get KEY1 RETIRED) +rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${retired}" "$ZONE" +set_addkeytime "KEY1" "RETIRED" "${active}" 15559500 +retired=$(key_get KEY1 RETIRED) +# Retire interval of this policy is 26h (93600 seconds). +set_addkeytime "KEY1" "REMOVED" "${retired}" 93600 + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Schedule KSK rollover now. +set_policy "manual-rollover" "3" "3600" +set_keystate "KEY1" "GOAL" "hidden" +created=$(key_get KEY1 CREATED) +set_keytime "KEY1" "RETIRED" "${created}" +rndc_rollover "$SERVER" "$DIR" $(key_get KEY1 ID) "${created}" "$ZONE" +# New key is introduced. +set_keyrole "KEY3" "ksk" +set_keylifetime "KEY3" "0" +set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" + +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_KRRSIG" "rumoured" +set_keystate "KEY3" "STATE_DS" "hidden" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Schedule ZSK rollover now. +set_policy "manual-rollover" "4" "3600" +set_keystate "KEY2" "GOAL" "hidden" +created=$(key_get KEY2 CREATED) +set_keytime "KEY2" "RETIRED" "${created}" +rndc_rollover "$SERVER" "$DIR" $(key_get KEY2 ID) "${created}" "$ZONE" +# New key is introduced. +set_keyrole "KEY4" "zsk" +set_keylifetime "KEY4" "0" +set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY4" "no" +set_zonesigning "KEY4" "no" # not yet, first prepublish DNSKEY. + +set_keystate "KEY4" "GOAL" "omnipresent" +set_keystate "KEY4" "STATE_DNSKEY" "rumoured" +set_keystate "KEY4" "STATE_ZRRSIG" "hidden" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Try to schedule a ZSK rollover for an inactive key (should fail). +n=$((n + 1)) +echo_i "check that rndc dnssec -rollover fails if key is inactive ($n)" +ret=0 +rndccmd "$SERVER" dnssec -rollover -key $(key_get KEY4 ID) "$ZONE" >rndc.dnssec.rollover.out.$ZONE.$n || ret=1 +grep "key is not actively signing" rndc.dnssec.rollover.out.$ZONE.$n >/dev/null || log_error "bad error message" +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# +# Testing DNSSEC introduction. +# + +# +# Zone: step1.enable-dnssec.autosign. +# +set_zone "step1.enable-dnssec.autosign" +set_policy "enable-dnssec" "1" "300" +set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# The DNSKEY and signatures are introduced first, the DS remains hidden. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "rumoured" +set_keystate "KEY1" "STATE_KRRSIG" "rumoured" +set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" +set_keystate "KEY1" "STATE_DS" "hidden" +# This policy lists only one key (CSK). +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The first key is immediately published and activated. +created=$(key_get KEY1 CREATED) +set_keytime "KEY1" "PUBLISHED" "${created}" +set_keytime "KEY1" "ACTIVE" "${created}" +# - The DS can be published if the DNSKEY and RRSIG records are +# OMNIPRESENT. This happens after max-zone-ttl (12h) plus +# plus zone-propagation-delay (5m) = +# 43200 + 300 = 43500. +set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43500 +# - Key lifetime is unlimited, so not setting RETIRED and REMOVED. + +# Various signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +_check_next_key_event() { + _expect=$1 + + grep "zone ${ZONE}.*: next key event in .* seconds" "${DIR}/named.run" >"keyevent.out.$ZONE.test$n" || return 1 + + # Get the latest next key event. + if [ "${DYNAMIC}" = "yes" ]; then + _time=$(awk '{print $9}' <"keyevent.out.$ZONE.test$n" | tail -1) + else + # inline-signing zone adds "(signed)" + _time=$(awk '{print $10}' <"keyevent.out.$ZONE.test$n" | tail -1) + fi + + # The next key event time must within threshold of the + # expected time. + _expectmin=$((_expect - next_key_event_threshold)) + _expectmax=$((_expect + next_key_event_threshold)) + + test $_expectmin -le "$_time" || return 1 + test $_expectmax -ge "$_time" || return 1 + + return 0 +} + +check_next_key_event() { + n=$((n + 1)) + echo_i "check next key event for zone ${ZONE} ($n)" + ret=0 + + retry_quiet 3 _check_next_key_event $1 || log_error "bad next key event time for zone ${ZONE} (expect ${_expect})" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + +} + +# Next key event is when the DNSKEY RRset becomes OMNIPRESENT: DNSKEY TTL plus +# publish safety plus the zone propagation delay: 900 seconds. +check_next_key_event 900 + +# +# Zone: step2.enable-dnssec.autosign. +# +set_zone "step2.enable-dnssec.autosign" +set_policy "enable-dnssec" "1" "300" +set_server "ns3" "10.53.0.3" +# The DNSKEY is omnipresent, but the zone signatures not yet. +# Thus, the DS remains hidden. +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The key was published and activated 900 seconds ago (with settime). +created=$(key_get KEY1 CREATED) +set_addkeytime "KEY1" "PUBLISHED" "${created}" -900 +set_addkeytime "KEY1" "ACTIVE" "${created}" -900 +set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 42600 + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl +# plus zone propagation delay plus retire safety minus the already elapsed +# 900 seconds: 12h + 300s + 20m - 900 = 43500 - 900 = 42600 seconds +check_next_key_event 42600 + +# +# Zone: step3.enable-dnssec.autosign. +# +set_zone "step3.enable-dnssec.autosign" +set_policy "enable-dnssec" "1" "300" +set_server "ns3" "10.53.0.3" +# All signatures should be omnipresent, so the DS can be submitted. +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "rumoured" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The key was published and activated 43500 seconds ago (with settime). +created=$(key_get KEY1 CREATED) +set_addkeytime "KEY1" "PUBLISHED" "${created}" -43500 +set_addkeytime "KEY1" "ACTIVE" "${created}" -43500 +set_keytime "KEY1" "SYNCPUBLISH" "${created}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify +# Check that CDS publication is logged. +check_cdslog "$DIR" "$ZONE" KEY1 + +# The DS can be introduced. We ignore any parent registration delay, so set +# the DS publish time to now. +rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE" +# Next key event is when the DS can move to the OMNIPRESENT state. This occurs +# when the parent propagation delay have passed, plus the DS TTL and retire +# safety delay: 1h + 2h = 3h = 10800 seconds +check_next_key_event 10800 + +# +# Zone: step4.enable-dnssec.autosign. +# +set_zone "step4.enable-dnssec.autosign" +set_policy "enable-dnssec" "1" "300" +set_server "ns3" "10.53.0.3" +# The DS is omnipresent. +set_keystate "KEY1" "STATE_DS" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The key was published and activated 56700 seconds ago (with settime). +created=$(key_get KEY1 CREATED) +set_addkeytime "KEY1" "PUBLISHED" "${created}" -56700 +set_addkeytime "KEY1" "ACTIVE" "${created}" -56700 +set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -12000 + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is never, the zone dnssec-policy has been established. So we +# fall back to the default loadkeys interval. +check_next_key_event 3600 + +# +# Testing ZSK Pre-Publication rollover. +# + +# Policy parameters. +# Lksk: 2 years (63072000 seconds) +# Lzsk: 30 days (2592000 seconds) +# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (2d) +# Iret(KSK): 3d1h (262800 seconds) +# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d) +# Iret(ZSK): 10d1h (867600 seconds) +Lksk=63072000 +Lzsk=2592000 +IretKSK=262800 +IretZSK=867600 + +# +# Zone: step1.zsk-prepub.autosign. +# +set_zone "step1.zsk-prepub.autosign" +set_policy "zsk-prepub" "2" "3600" +set_server "ns3" "10.53.0.3" + +set_retired_removed() { + _Lkey=$2 + _Iret=$3 + + _active=$(key_get $1 ACTIVE) + set_addkeytime "${1}" "RETIRED" "${_active}" "${_Lkey}" + _retired=$(key_get $1 RETIRED) + set_addkeytime "${1}" "REMOVED" "${_retired}" "${_Iret}" +} + +rollover_predecessor_keytimes() { + _addtime=$1 + + _created=$(key_get KEY1 CREATED) + set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}" + set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}" + set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}" + [ "$Lksk" = 0 ] || set_retired_removed "KEY1" "${Lksk}" "${IretKSK}" + + _created=$(key_get KEY2 CREATED) + set_addkeytime "KEY2" "PUBLISHED" "${_created}" "${_addtime}" + set_addkeytime "KEY2" "ACTIVE" "${_created}" "${_addtime}" + [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}" +} + +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "${Lksk}" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "${Lzsk}" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" +# Initially only two keys. +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# These keys are immediately published and activated. +rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor ZSK needs to be published. That is +# the ZSK lifetime - prepublication time. The prepublication time is DNSKEY +# TTL plus publish safety plus the zone propagation delay. For the +# zsk-prepub policy that means: 30d - 3600s + 1d + 1h = 2498400 seconds. +check_next_key_event 2498400 + +# +# Zone: step2.zsk-prepub.autosign. +# +set_zone "step2.zsk-prepub.autosign" +set_policy "zsk-prepub" "3" "3600" +set_server "ns3" "10.53.0.3" +# New ZSK (KEY3) is prepublished, but not yet signing. +key_clear "KEY3" +set_keyrole "KEY3" "zsk" +set_keylifetime "KEY3" "${Lzsk}" +set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY3" "no" +set_zonesigning "KEY3" "no" +# Key states. +set_keystate "KEY2" "GOAL" "hidden" +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_ZRRSIG" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys were activated 694 hours ago (2498400 seconds). +rollover_predecessor_keytimes -2498400 +# - The new ZSK is published now. +created=$(key_get KEY3 CREATED) +set_keytime "KEY3" "PUBLISHED" "${created}" +# - The new ZSK becomes active when the DNSKEY is OMNIPRESENT. +# Ipub: TTLkey (1h) + Dprp (1h) + publish-safety (1d) +# Ipub: 26 hour (93600 seconds). +IpubZSK=93600 +set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubZSK}" +set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor ZSK becomes OMNIPRESENT. That is the +# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For +# the zsk-prepub policy, this means: 3600s + 1h + 1d = 93600 seconds. +check_next_key_event 93600 + +# +# Zone: step3.zsk-prepub.autosign. +# +set_zone "step3.zsk-prepub.autosign" +set_policy "zsk-prepub" "3" "3600" +set_server "ns3" "10.53.0.3" +# ZSK (KEY2) no longer is actively signing, RRSIG state in UNRETENTIVE. +# New ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. +set_zonesigning "KEY2" "no" +set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" +set_zonesigning "KEY3" "yes" +set_keystate "KEY3" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY3" "STATE_ZRRSIG" "rumoured" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys are activated 30 days ago (2592000 seconds). +rollover_predecessor_keytimes -2592000 +# - The new ZSK is published 26 hours ago (93600 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -93600 +set_keytime "KEY3" "ACTIVE" "${created}" +set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +# Subdomain still has good signatures of ZSK (KEY2). +# Set expected zone signing on for KEY2 and off for KEY3, +# testing whether signatures which are still valid are being reused. +set_zonesigning "KEY2" "yes" +set_zonesigning "KEY3" "no" +check_subdomain +# Restore the expected zone signing properties. +set_zonesigning "KEY2" "no" +set_zonesigning "KEY3" "yes" +dnssec_verify + +# Next key event is when all the RRSIG records have been replaced with +# signatures of the new ZSK, in other words when ZRRSIG becomes OMNIPRESENT. +# That is Dsgn plus the maximum zone TTL plus the zone propagation delay plus +# retire-safety. For the zsk-prepub policy that means: 1w (because 2w validity +# and refresh within a week) + 1d + 1h + 2d = 10d1h = 867600 seconds. +check_next_key_event 867600 + +# +# Zone: step4.zsk-prepub.autosign. +# +set_zone "step4.zsk-prepub.autosign" +set_policy "zsk-prepub" "3" "3600" +set_server "ns3" "10.53.0.3" +# ZSK (KEY2) DNSKEY is no longer needed. +# ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. +set_keystate "KEY2" "STATE_DNSKEY" "unretentive" +set_keystate "KEY2" "STATE_ZRRSIG" "hidden" +set_keystate "KEY3" "STATE_ZRRSIG" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys are activated 961 hours ago (3459600 seconds). +rollover_predecessor_keytimes -3459600 +# - The new ZSK is published 267 hours ago (961200 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -961200 +published=$(key_get KEY3 PUBLISHED) +set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}" +set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DNSKEY enters the HIDDEN state. This is the +# DNSKEY TTL plus zone propagation delay. For the zsk-prepub policy this is: +# 3600s + 1h = 7200s +check_next_key_event 7200 + +# +# Zone: step5.zsk-prepub.autosign. +# +set_zone "step5.zsk-prepub.autosign" +set_policy "zsk-prepub" "3" "3600" +set_server "ns3" "10.53.0.3" +# ZSK (KEY2) DNSKEY is now completely HIDDEN and removed. +set_keystate "KEY2" "STATE_DNSKEY" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys are activated 962 hours ago (3463200 seconds). +rollover_predecessor_keytimes -3463200 +# - The new ZSK is published 268 hours ago (964800 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -964800 +published=$(key_get KEY3 PUBLISHED) +set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}" +set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the new successor needs to be published. This is the +# ZSK lifetime minus Iret minus Ipub minus DNSKEY TTL. For the zsk-prepub +# policy this is: 30d - 867600s - 93600s - 3600s = 1627200 seconds. +check_next_key_event 1627200 + +# +# Zone: step6.zsk-prepub.autosign. +# +set_zone "step6.zsk-prepub.autosign" +set_policy "zsk-prepub" "2" "3600" +set_server "ns3" "10.53.0.3" +# ZSK (KEY2) DNSKEY is purged. +key_clear "KEY2" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# +# Testing KSK Double-KSK rollover. +# + +# Policy parameters. +# Lksk: 60 days (16070400 seconds) +# Lzsk: 1 year (31536000 seconds) +# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2d) +# Iret(KSK): 50h (180000 seconds) +# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d) +# Iret(ZSK): 10d1h (867600 seconds) +Lksk=5184000 +Lzsk=31536000 +IretKSK=180000 +IretZSK=867600 + +# +# Zone: step1.ksk-doubleksk.autosign. +# +set_zone "step1.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "2" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "${Lksk}" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "${Lzsk}" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" +# Initially only two keys. +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# These keys are immediately published and activated. +rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor KSK needs to be published. That is +# the KSK lifetime - prepublication time. The prepublication time is +# DNSKEY TTL plus publish safety plus the zone propagation delay. +# For the ksk-doubleksk policy that means: 60d - (1d3h) = 5086800 seconds. +check_next_key_event 5086800 + +# +# Zone: step2.ksk-doubleksk.autosign. +# +set_zone "step2.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "3" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" +# New KSK (KEY3) is prepublished (and signs DNSKEY RRset). +key_clear "KEY3" +set_keyrole "KEY3" "ksk" +set_keylifetime "KEY3" "${Lksk}" +set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" +# Key states. +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_KRRSIG" "rumoured" +set_keystate "KEY3" "STATE_DS" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys were activated 1413 hours ago (5086800 seconds). +rollover_predecessor_keytimes -5086800 +# - The new KSK is published now. +created=$(key_get KEY3 CREATED) +set_keytime "KEY3" "PUBLISHED" "${created}" +# The new KSK should publish the CDS after the prepublication time. +# TTLkey: 2h +# DprpC: 1h +# publish-safety: 1d +# IpubC: 27h (97200 seconds) +IpubC=97200 +set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${IpubC}" +set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubC}" +set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor KSK becomes OMNIPRESENT. That is the +# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For +# the ksk-doubleksk policy, this means: 7200s + 1h + 1d = 97200 seconds. +check_next_key_event 97200 + +# +# Zone: step3.ksk-doubleksk.autosign. +# +set_zone "step3.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "3" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" + +# The DNSKEY RRset has become omnipresent. +# Check keys before we tell named that we saw the DS has been replaced. +set_keystate "KEY3" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY3" "STATE_KRRSIG" "omnipresent" +# The old DS (KEY1) can be withdrawn and the new DS (KEY3) can be introduced. +set_keystate "KEY1" "STATE_DS" "unretentive" +set_keystate "KEY3" "STATE_DS" "rumoured" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# Check that CDS publication is logged. +check_cdslog "$DIR" "$ZONE" KEY3 + +# Set expected key times: +# - The old keys were activated 60 days ago (5184000 seconds). +rollover_predecessor_keytimes -5184000 +# - The new KSK is published 27 hours ago (97200 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -97200 +# - The new KSK CDS is published now. +set_keytime "KEY3" "SYNCPUBLISH" "${created}" +syncpub=$(key_get KEY3 SYNCPUBLISH) +set_keytime "KEY3" "ACTIVE" "${syncpub}" +set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# We ignore any parent registration delay, so set the DS publish time to now. +rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" +rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE" +# Next key event is when the predecessor DS has been replaced with the +# successor DS and enough time has passed such that the all validators that +# have this DS RRset cached only know about the successor DS. This is the +# the retire interval, which is the parent propagation delay plus the DS TTL +# plus the retire-safety. For the ksk-double-ksk policy this means: +# 1h + 3600s + 2d = 2d2h = 180000 seconds. +check_next_key_event 180000 + +# +# Zone: step4.ksk-doubleksk.autosign. +# +set_zone "step4.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "3" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" +# KSK (KEY1) DNSKEY can be removed. +set_keysigning "KEY1" "no" +set_keystate "KEY1" "STATE_DNSKEY" "unretentive" +set_keystate "KEY1" "STATE_KRRSIG" "unretentive" +set_keystate "KEY1" "STATE_DS" "hidden" +# New KSK (KEY3) DS is now OMNIPRESENT. +set_keystate "KEY3" "STATE_DS" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys were activated 1490 hours ago (5364000 seconds). +rollover_predecessor_keytimes -5364000 +# - The new KSK is published 77 hours ago (277200 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -277200 +published=$(key_get KEY3 PUBLISHED) +set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}" +syncpub=$(key_get KEY3 SYNCPUBLISH) +set_keytime "KEY3" "ACTIVE" "${syncpub}" +set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DNSKEY enters the HIDDEN state. This is the +# DNSKEY TTL plus zone propagation delay. For the ksk-doubleksk policy this is: +# 7200s + 1h = 10800s +check_next_key_event 10800 + +# +# Zone: step5.ksk-doubleksk.autosign. +# +set_zone "step5.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "3" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" +# KSK (KEY1) DNSKEY is now HIDDEN. +set_keystate "KEY1" "STATE_DNSKEY" "hidden" +set_keystate "KEY1" "STATE_KRRSIG" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old KSK is activated 1492 hours ago (5371200 seconds). +rollover_predecessor_keytimes -5371200 +# - The new KSK is published 79 hours ago (284400 seconds). +created=$(key_get KEY3 CREATED) +set_addkeytime "KEY3" "PUBLISHED" "${created}" -284400 +published=$(key_get KEY3 PUBLISHED) +set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}" +syncpub=$(key_get KEY3 SYNCPUBLISH) +set_keytime "KEY3" "ACTIVE" "${syncpub}" +set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" + +# Various signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the new successor needs to be published. This is the +# KSK lifetime minus Ipub minus Iret minus DNSKEY TTL. For the +# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h = +# 5184000 - 97200 - 180000 - 7200 = 4813200 seconds. +check_next_key_event 4899600 + +# +# Zone: step6.ksk-doubleksk.autosign. +# +set_zone "step6.ksk-doubleksk.autosign" +set_policy "ksk-doubleksk" "2" "7200" +CDNSKEY="no" +set_server "ns3" "10.53.0.3" +# KSK (KEY1) DNSKEY is purged. +key_clear "KEY1" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# +# Testing CSK key rollover (1). +# + +# Policy parameters. +# Lcsk: 186 days (5184000 seconds) +# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2h) +# Iret(KSK): 4h (14400 seconds) +# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (25d) + retire-safety (2h) +# Iret(ZSK): 26d3h (2257200 seconds) +Lcsk=16070400 +IretKSK=14400 +IretZSK=2257200 +IretCSK=$IretZSK + +csk_rollover_predecessor_keytimes() { + _addtime=$1 + + _created=$(key_get KEY1 CREATED) + set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}" + set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}" + set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}" + [ "$Lcsk" = 0 ] || set_retired_removed "KEY1" "${Lcsk}" "${IretCSK}" +} + +# +# Zone: step1.csk-roll.autosign. +# +set_zone "step1.csk-roll.autosign" +set_policy "csk-roll" "1" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "${Lcsk}" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# The CSK (KEY1) starts in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# Initially only one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# This key is immediately published and activated. +csk_rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor CSK needs to be published. +# This is Lcsk - Ipub - Dreg. +# Lcsk: 186d (16070400 seconds) +# Ipub: 3h (10800 seconds) +check_next_key_event 16059600 + +# +# Zone: step2.csk-roll.autosign. +# +set_zone "step2.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# New CSK (KEY2) is prepublished (signs DNSKEY RRset, but not yet other RRsets). +key_clear "KEY2" +set_keyrole "KEY2" "csk" +set_keylifetime "KEY2" "16070400" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "yes" +set_zonesigning "KEY2" "no" +# Key states. +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "rumoured" +set_keystate "KEY2" "STATE_KRRSIG" "rumoured" +set_keystate "KEY2" "STATE_ZRRSIG" "hidden" +set_keystate "KEY2" "STATE_DS" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4461 hours ago (16059600 seconds). +csk_rollover_predecessor_keytimes -16059600 +# - The new CSK is published now. +created=$(key_get KEY2 CREATED) +set_keytime "KEY2" "PUBLISHED" "${created}" +# - The new CSK should publish the CDS after the prepublication time. +# Ipub: 3 hour (10800 seconds) +Ipub="10800" +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}" +set_addkeytime "KEY2" "ACTIVE" "${created}" "${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor CSK becomes OMNIPRESENT. That is the +# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For +# the csk-roll policy, this means 3 hours = 10800 seconds. +check_next_key_event 10800 + +# +# Zone: step3.csk-roll.autosign. +# +set_zone "step3.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# Swap zone signing role. +set_zonesigning "KEY1" "no" +set_zonesigning "KEY2" "yes" +# CSK (KEY1) will be removed, so moving to UNRETENTIVE. +set_keystate "KEY1" "STATE_ZRRSIG" "unretentive" +# New CSK (KEY2) DNSKEY is OMNIPRESENT, so moving ZRRSIG to RUMOURED. +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" +# The old DS (KEY1) can be withdrawn and the new DS (KEY2) can be introduced. +set_keystate "KEY1" "STATE_DS" "unretentive" +set_keystate "KEY2" "STATE_DS" "rumoured" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# Check that CDS publication is logged. +check_cdslog "$DIR" "$ZONE" KEY2 + +# Set expected key times: +# - This key was activated 186 days ago (16070400 seconds). +csk_rollover_predecessor_keytimes -16070400 +# - The new CSK is published three hours ago, CDS must be published now. +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" "-${Ipub}" +set_keytime "KEY2" "SYNCPUBLISH" "${created}" +# - Also signatures are being introduced now. +set_keytime "KEY2" "ACTIVE" "${created}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +# Subdomain still has good signatures of old CSK (KEY1). +# Set expected zone signing on for KEY1 and off for KEY2, +# testing whether signatures which are still valid are being reused. +set_zonesigning "KEY1" "yes" +set_zonesigning "KEY2" "no" +check_subdomain +# Restore the expected zone signing properties. +set_zonesigning "KEY1" "no" +set_zonesigning "KEY2" "yes" +dnssec_verify + +# We ignore any parent registration delay, so set the DS publish time to now. +rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" +rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE" +# Next key event is when the predecessor DS has been replaced with the +# successor DS and enough time has passed such that the all validators that +# have this DS RRset cached only know about the successor DS. This is the +# the retire interval, which is the parent propagation delay plus the DS TTL +# plus the retire-safety. For the csk-roll policy this means: +# 1h + 1h + 2h = 4h = 14400 seconds. +check_next_key_event 14400 + +# +# Zone: step4.csk-roll.autosign. +# +set_zone "step4.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) is no longer signing the DNSKEY RRset. +set_keysigning "KEY1" "no" +# The old CSK (KEY1) DS is hidden. We still need to keep the DNSKEY public +# but can remove the KRRSIG records. +set_keystate "KEY1" "STATE_KRRSIG" "unretentive" +set_keystate "KEY1" "STATE_DS" "hidden" +# The new CSK (KEY2) DS is now OMNIPRESENT. +set_keystate "KEY2" "STATE_DS" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4468 hours ago (16084800 seconds). +csk_rollover_predecessor_keytimes -16084800 +# - The new CSK started signing 4h ago (14400 seconds). +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "ACTIVE" "${created}" -14400 +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -14400 +syncpub=$(key_get KEY2 SYNCPUBLISH) +set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the KRRSIG enters the HIDDEN state. This is the +# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is: +# 1h + 1h = 7200 seconds. +check_next_key_event 7200 + +# +# Zone: step5.csk-roll.autosign. +# +set_zone "step5.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) KRRSIG records are now all hidden. +set_keystate "KEY1" "STATE_KRRSIG" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4470 hours ago (16092000 seconds). +csk_rollover_predecessor_keytimes -16092000 +# - The new CSK started signing 6h ago (21600 seconds). +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "ACTIVE" "${created}" -21600 +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -21600 +syncpub=$(key_get KEY2 SYNCPUBLISH) +set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DNSKEY can be removed. This is when all ZRRSIG +# records have been replaced with signatures of the new CSK. We have +# calculated the interval to be 26d3h of which 4h (Iret(KSK)) plus +# 2h (DNSKEY TTL + Dprp) have already passed. So next key event is in +# 26d3h - 4h - 2h = 621h = 2235600 seconds. +check_next_key_event 2235600 + +# +# Zone: step6.csk-roll.autosign. +# +set_zone "step6.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) ZRRSIG records are now all hidden (so the DNSKEY can +# be removed). +set_keystate "KEY1" "STATE_DNSKEY" "unretentive" +set_keystate "KEY1" "STATE_ZRRSIG" "hidden" +# The new CSK (KEY2) is now fully OMNIPRESENT. +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times +# - This key was activated 5091 hours ago (18327600 seconds). +csk_rollover_predecessor_keytimes -18327600 +# - The new CSK is activated 627 hours ago (2257200 seconds). +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "ACTIVE" "${created}" -2257200 +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -2257200 +syncpub=$(key_get KEY2 SYNCPUBLISH) +set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DNSKEY enters the HIDDEN state. This is the +# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is: +# 1h + 1h = 7200 seconds. +check_next_key_event 7200 + +# +# Zone: step7.csk-roll.autosign. +# +set_zone "step7.csk-roll.autosign" +set_policy "csk-roll" "2" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) is now completely HIDDEN. +set_keystate "KEY1" "STATE_DNSKEY" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 5093 hours ago (18334800 seconds). +csk_rollover_predecessor_keytimes -18334800 +# - The new CSK is activated 629 hours ago (2264400 seconds). +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "ACTIVE" "${created}" -2264400 +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" -2264400 +syncpub=$(key_get KEY2 SYNCPUBLISH) +set_addkeytime "KEY2" "PUBLISHED" "${syncpub}" "-${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the new successor needs to be published. +# This is the Lcsk, minus time passed since the key started signing, +# minus the prepublication time. +# Lcsk: 186d (16070400 seconds) +# Time passed: 629h (2264400 seconds) +# Ipub: 3h (10800 seconds) +check_next_key_event 13795200 + +# +# Zone: step8.csk-roll.autosign. +# +set_zone "step8.csk-roll.autosign" +set_policy "csk-roll" "1" "3600" +CDS_SHA256="no" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) is purged. +key_clear "KEY1" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# +# Testing CSK key rollover (2). +# + +# Policy parameters. +# Lcsk: 186 days (16070400 seconds) +# Dreg: N/A +# Iret(KSK): DS TTL (1h) + DprpP (1w) + retire-safety (1h) +# Iret(KSK): 170h (61200 seconds) +# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (12h) + retire-safety (1h) +# Iret(ZSK): 38h (136800 seconds) +Lcsk=16070400 +IretKSK=612000 +IretZSK=136800 +IretCSK=$IretKSK + +# +# Zone: step1.csk-roll2.autosign. +# +set_zone "step1.csk-roll2.autosign" +set_policy "csk-roll2" "1" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "16070400" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# The CSK (KEY1) starts in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# Initially only one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# This key is immediately published and activated. +csk_rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor CSK needs to be published. +# This is Lcsk - Ipub. +# Lcsk: 186d (16070400 seconds) +# Ipub: 3h (10800 seconds) +# Total: 186d3h (16059600 seconds) +check_next_key_event 16059600 + +# +# Zone: step2.csk-roll2.autosign. +# +set_zone "step2.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# New CSK (KEY2) is prepublished (signs DNSKEY RRset, but not yet other RRsets). +key_clear "KEY2" +set_keyrole "KEY2" "csk" +set_keylifetime "KEY2" "16070400" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "yes" +set_zonesigning "KEY2" "no" +# Key states. +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "rumoured" +set_keystate "KEY2" "STATE_KRRSIG" "rumoured" +set_keystate "KEY2" "STATE_ZRRSIG" "hidden" +set_keystate "KEY2" "STATE_DS" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4461 hours ago (16059600 seconds). +csk_rollover_predecessor_keytimes -16059600 +# - The new CSK is published now. +created=$(key_get KEY2 CREATED) +set_keytime "KEY2" "PUBLISHED" "${created}" +# - The new CSK should publish the CDS after the prepublication time. +# - Ipub: 3 hour (10800 seconds) +Ipub="10800" +set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}" +set_addkeytime "KEY2" "ACTIVE" "${created}" "${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor CSK becomes OMNIPRESENT. That is the +# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For +# the csk-roll2 policy, this means 3h hours = 10800 seconds. +check_next_key_event 10800 + +# +# Zone: step3.csk-roll2.autosign. +# +set_zone "step3.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# CSK (KEY1) can be removed, so move to UNRETENTIVE. +set_zonesigning "KEY1" "no" +set_keystate "KEY1" "STATE_ZRRSIG" "unretentive" +# New CSK (KEY2) DNSKEY is OMNIPRESENT, so move ZRRSIG to RUMOURED state. +set_zonesigning "KEY2" "yes" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" +# The old DS (KEY1) can be withdrawn and the new DS (KEY2) can be introduced. +set_keystate "KEY1" "STATE_DS" "unretentive" +set_keystate "KEY2" "STATE_DS" "rumoured" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# Check that CDS publication is logged. +check_cdslog "$DIR" "$ZONE" KEY2 + +# Set expected key times: +# - This key was activated 186 days ago (16070400 seconds). +csk_rollover_predecessor_keytimes -16070400 +# - The new CSK is published three hours ago, CDS must be published now. +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" "-${Ipub}" +set_keytime "KEY2" "SYNCPUBLISH" "${created}" +# - Also signatures are being introduced now. +set_keytime "KEY2" "ACTIVE" "${created}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +# Subdomain still has good signatures of old CSK (KEY1). +# Set expected zone signing on for KEY1 and off for KEY2, +# testing whether signatures which are still valid are being reused. +set_zonesigning "KEY1" "yes" +set_zonesigning "KEY2" "no" +check_subdomain +# Restore the expected zone signing properties. +set_zonesigning "KEY1" "no" +set_zonesigning "KEY2" "yes" +dnssec_verify + +# We ignore any parent registration delay, so set the DS publish time to now. +rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" +rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE" +# Next key event is when the predecessor ZRRSIG records have been replaced +# with that of the successor and enough time has passed such that the all +# validators that have such signed RRsets in cache only know about the +# successor signatures. This is the retire interval: Dsgn plus the +# maximum zone TTL plus the zone propagation delay plus retire-safety. For the +# csk-roll2 policy that means: 12h (because 1d validity and refresh within +# 12 hours) + 1d + 1h + 1h = 38h = 136800 seconds. Prevent intermittent false +# positives on slow platforms by subtracting the number of seconds which +# passed between key creation and invoking 'rndc dnssec -checkds'. +now="$(TZ=UTC date +%s)" +time_passed=$((now - start_time)) +next_time=$((136800 - time_passed)) +check_next_key_event $next_time + +# +# Zone: step4.csk-roll2.autosign. +# +set_zone "step4.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) ZRRSIG is now HIDDEN. +set_keystate "KEY1" "STATE_ZRRSIG" "hidden" +# The new CSK (KEY2) ZRRSIG is now OMNIPRESENT. +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4502 hours ago (16207200 seconds). +csk_rollover_predecessor_keytimes -16207200 +# - The new CSK was published 41 hours (147600 seconds) ago. +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" -147600 +published=$(key_get KEY2 PUBLISHED) +set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}" +set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the predecessor DS has been replaced with the +# successor DS and enough time has passed such that the all validators that +# have this DS RRset cached only know about the successor DS. This is the +# registration delay plus the retire interval, which is the parent +# propagation delay plus the DS TTL plus the retire-safety. For the +# csk-roll2 policy this means: 1w + 1h + 1h = 170h = 612000 seconds. +# However, 136800 seconds have passed already, so 478800 seconds left. +check_next_key_event 475200 + +# +# Zone: step5.csk-roll2.autosign. +# +set_zone "step5.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) DNSKEY can be removed. +set_keysigning "KEY1" "no" +set_keystate "KEY1" "STATE_DNSKEY" "unretentive" +set_keystate "KEY1" "STATE_KRRSIG" "unretentive" +set_keystate "KEY1" "STATE_DS" "hidden" +# The new CSK (KEY2) is now fully OMNIPRESENT. +set_keystate "KEY2" "STATE_DS" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4634 hours ago (16682400 seconds). +csk_rollover_predecessor_keytimes -16682400 +# - The new CSK was published 173 hours (622800 seconds) ago. +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" -622800 +published=$(key_get KEY2 PUBLISHED) +set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}" +set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DNSKEY enters the HIDDEN state. This is the +# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is: +# 1h + 1h = 7200 seconds. +check_next_key_event 7200 + +# +# Zone: step6.csk-roll2.autosign. +# +set_zone "step6.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) is now completely HIDDEN. +set_keystate "KEY1" "STATE_DNSKEY" "hidden" +set_keystate "KEY1" "STATE_KRRSIG" "hidden" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - This key was activated 4636 hours ago (16689600 seconds). +csk_rollover_predecessor_keytimes -16689600 +# - The new CSK was published 175 hours (630000 seconds) ago. +created=$(key_get KEY2 CREATED) +set_addkeytime "KEY2" "PUBLISHED" "${created}" -630000 +published=$(key_get KEY2 PUBLISHED) +set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}" +set_addkeytime "KEY2" "ACTIVE" "${published}" "${Ipub}" +set_retired_removed "KEY2" "${Lcsk}" "${IretCSK}" + +# Continue signing policy checks. +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the new successor needs to be published. +# This is the Lcsk, minus time passed since the key was published. +# Lcsk: 186d (16070400 seconds) +# Time passed: 175h (630000 seconds) +check_next_key_event 15440400 + +# +# Zone: step7.csk-roll2.autosign. +# +set_zone "step7.csk-roll2.autosign" +set_policy "csk-roll2" "2" "3600" +CDS_SHA384="yes" +set_server "ns3" "10.53.0.3" +# The old CSK (KEY1) could have been purged, but purge-keys is disabled. + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# +# Test #2375: Scheduled rollovers are happening faster than they can finish +# +set_zone "three-is-a-crowd.kasp" +set_policy "ksk-doubleksk" "3" "7200" +set_server "ns3" "10.53.0.3" +CDNSKEY="no" +# These are the same time values as calculated for ksk-doubleksk. +Lksk=5184000 +Lzsk=31536000 +IretKSK=180000 +IretZSK=867600 +# KSK (KEY1) is outgoing. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "${Lksk}" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "unretentive" +# KSK (KEY2) is incoming. +key_clear "KEY2" +set_keyrole "KEY2" "ksk" +set_keylifetime "KEY2" "${Lksk}" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "yes" +set_zonesigning "KEY2" "no" +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY2" "STATE_DS" "rumoured" +# We will introduce the third KSK shortly. +key_clear "KEY3" +# ZSK (KEY4). +key_clear "KEY4" +set_keyrole "KEY4" "zsk" +set_keylifetime "KEY4" "${Lzsk}" +set_keyalgorithm "KEY4" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY4" "no" +set_zonesigning "KEY4" "yes" +set_keystate "KEY4" "GOAL" "omnipresent" +set_keystate "KEY4" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY4" "STATE_ZRRSIG" "omnipresent" +# Run preliminary tests. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify +# Roll over KEY2. +created=$(key_get KEY2 CREATED) +rndc_rollover "$SERVER" "$DIR" $(key_get KEY2 ID) "${created}" "$ZONE" +# Update expected number of keys and key states. +set_keystate "KEY2" "GOAL" "hidden" +set_policy "ksk-doubleksk" "4" "7200" +CDNSKEY="no" +# New KSK (KEY3) is introduced. +set_keyrole "KEY3" "ksk" +set_keylifetime "KEY3" "${Lksk}" +set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_KRRSIG" "rumoured" +set_keystate "KEY3" "STATE_DS" "hidden" +# Run tests again. We now expect four keys (3x KSK, 1x ZSK). +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Test dynamic zones that switch to inline-signing. +set_zone "dynamic2inline.kasp" +set_policy "default" "1" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# The CSK is rumoured. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "rumoured" +set_keystate "KEY1" "STATE_KRRSIG" "rumoured" +set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" +set_keystate "KEY1" "STATE_DS" "hidden" +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Test key lifetime changes +set_keytimes_lifetime_update() { + if [ $1 -eq 0 ]; then + set_keytime "KEY1" "RETIRED" "none" + set_keytime "KEY1" "REMOVED" "none" + else + active=$(key_get KEY1 ACTIVE) + set_addkeytime "KEY1" "RETIRED" "${active}" $1 + # The key is removed after the retire time plus max-zone-ttl (1d), + # sign delay (9d), zone propagation delay (5m), retire safety (1h) = + # 777600 + 86400 + 300 + 3600 = 867900 + retired=$(key_get KEY1 RETIRED) + set_addkeytime "KEY1" "REMOVED" "${retired}" 867900 + fi +} + +check_key_lifetime() { + zone=$1 + policy=$2 + lifetime=$3 + + set_zone "$zone" + set_policy "$policy" "1" "3600" + set_server "ns6" "10.53.0.6" + # Key properties. + key_clear "KEY1" + set_keyrole "KEY1" "csk" + set_keylifetime "KEY1" "$lifetime" + set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" + set_keysigning "KEY1" "yes" + set_zonesigning "KEY1" "yes" + key_clear "KEY2" + key_clear "KEY3" + key_clear "KEY4" + + # The CSK is rumoured. + set_keystate "KEY1" "GOAL" "omnipresent" + set_keystate "KEY1" "STATE_DNSKEY" "rumoured" + set_keystate "KEY1" "STATE_KRRSIG" "rumoured" + set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" + set_keystate "KEY1" "STATE_DS" "hidden" + check_keys + + # Key timings. + set_keytimes_csk_policy + set_keytimes_lifetime_update $lifetime + + # Variuous checks. + check_keytimes + check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + check_apex + check_subdomain + dnssec_verify +} +check_key_lifetime "shorter-lifetime" "long-lifetime" "31536000" +check_key_lifetime "longer-lifetime" "short-lifetime" "16070400" +check_key_lifetime "limit-lifetime" "unlimited-lifetime" "0" +check_key_lifetime "unlimit-lifetime" "short-lifetime" "16070400" + +# +# Testing algorithm rollover. +# +Lksk=0 +Lzsk=0 +IretKSK=0 +IretZSK=0 + +# +# Zone: step1.algorithm-roll.kasp +# +set_zone "step1.algorithm-roll.kasp" +set_policy "rsasha256" "2" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "0" +set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +key_clear "KEY3" +key_clear "KEY4" + +# The KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# These keys are immediately published and activated. +rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor keys need to be published. +# Since the lifetime of the keys are unlimited, so default to loadkeys +# interval. +check_next_key_event 3600 + +# +# Zone: step1.csk-algorithm-roll.kasp +# +set_zone "step1.csk-algorithm-roll.kasp" +set_policy "csk-algoroll" "1" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" +# The CSK (KEY1) starts in OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +# This key is immediately published and activated. +Lcsk=0 +IretCSK=0 +csk_rollover_predecessor_keytimes 0 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the successor keys need to be published. +# Since the lifetime of the keys are unlimited, so default to loadkeys +# interval. +check_next_key_event 3600 + +# +# Testing going insecure. +# + +# +# Zone step1.going-insecure.kasp +# +set_zone "step1.going-insecure.kasp" +set_policy "unsigning" "2" "7200" +set_server "ns6" "10.53.0.6" + +# Policy parameters. +# Lksk: 0 +# Lzsk: 60 days (5184000 seconds) +# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (1h) +# Iret(KSK): 1d2h (93600 seconds) +# Iret(ZSK): RRSIG TTL (1d) + Dprp (5m) + Dsgn (9d) + retire-safety (1h) +# Iret(ZSK): 10d1h5m (867900 seconds) +Lksk=0 +Lzsk=5184000 +IretKSK=93600 +IretZSK=867900 + +init_migration_insecure() { + key_clear "KEY1" + set_keyrole "KEY1" "ksk" + set_keylifetime "KEY1" "${Lksk}" + set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" + set_keysigning "KEY1" "yes" + set_zonesigning "KEY1" "no" + + set_keystate "KEY1" "GOAL" "omnipresent" + set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" + set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" + set_keystate "KEY1" "STATE_DS" "omnipresent" + + key_clear "KEY2" + set_keyrole "KEY2" "zsk" + set_keylifetime "KEY2" "${Lzsk}" + set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" + set_keysigning "KEY2" "no" + set_zonesigning "KEY2" "yes" + + set_keystate "KEY2" "GOAL" "omnipresent" + set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" + set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + + key_clear "KEY3" + key_clear "KEY4" +} +init_migration_insecure + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# We have set the timing metadata to now - 10 days (864000 seconds). +rollover_predecessor_keytimes -864000 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# +# Zone step1.going-insecure-dynamic.kasp +# + +set_zone "step1.going-insecure-dynamic.kasp" +set_dynamic +set_policy "unsigning" "2" "7200" +set_server "ns6" "10.53.0.6" +init_migration_insecure + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# We have set the timing metadata to now - 10 days (864000 seconds). +rollover_predecessor_keytimes -864000 +check_keytimes +check_apex +check_subdomain +dnssec_verify + +# +# Zone step1.going-straight-to-none.kasp +# +set_zone "step1.going-straight-to-none.kasp" +set_policy "default" "1" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# This policy only has one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# The first key is immediately published and activated. +created=$(key_get KEY1 CREATED) +set_keytime "KEY1" "PUBLISHED" "${created}" +set_keytime "KEY1" "ACTIVE" "${created}" +set_keytime "KEY1" "SYNCPUBLISH" "${created}" +# Key lifetime is unlimited, so not setting RETIRED and REMOVED. +check_keytimes + +check_apex +check_subdomain +dnssec_verify + +# +# Zone step1.going-straight-to-none-dynamic.kasp +# +set_zone "step1.going-straight-to-none-dynamic.kasp" +set_policy "default" "1" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# This policy only has one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# The first key is immediately published and activated. +created=$(key_get KEY1 CREATED) +set_keytime "KEY1" "PUBLISHED" "${created}" +set_keytime "KEY1" "ACTIVE" "${created}" +set_keytime "KEY1" "SYNCPUBLISH" "${created}" +# Key lifetime is unlimited, so not setting RETIRED and REMOVED. +check_keytimes + +check_apex +check_subdomain +dnssec_verify + +# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy +# changes). +echo_i "reconfig dnssec-policy to trigger algorithm rollover" +copy_setports ns6/named2.conf.in ns6/named.conf +rndc_reconfig ns6 10.53.0.6 + +# Calculate time passed to correctly check for next key events. +now="$(TZ=UTC date +%s)" +time_passed=$((now - start_time)) +echo_i "${time_passed} seconds passed between start of tests and reconfig" + +# Wait until we have seen "zone_rekey done:" message for this key. +_wait_for_done_signing() { + _zone=$1 + + _ksk=$(key_get $2 KSK) + _zsk=$(key_get $2 ZSK) + if [ "$_ksk" = "yes" ]; then + _role="KSK" + _expect_type=EXPECT_KRRSIG + elif [ "$_zsk" = "yes" ]; then + _role="ZSK" + _expect_type=EXPECT_ZRRSIG + fi + + if [ "$(key_get ${2} $_expect_type)" = "yes" ] && [ "$(key_get $2 $_role)" = "yes" ]; then + _keyid=$(key_get $2 ID) + _keyalg=$(key_get $2 ALG_STR) + echo_i "wait for zone ${_zone} is done signing with $2 ${_zone}/${_keyalg}/${_keyid}" + grep "zone_rekey done: key ${_keyid}/${_keyalg}" "${DIR}/named.run" >/dev/null || return 1 + fi + + return 0 +} + +wait_for_done_signing() { + n=$((n + 1)) + echo_i "wait for zone ${ZONE} is done signing ($n)" + ret=0 + + retry_quiet 30 _wait_for_done_signing ${ZONE} KEY1 || ret=1 + retry_quiet 30 _wait_for_done_signing ${ZONE} KEY2 || ret=1 + retry_quiet 30 _wait_for_done_signing ${ZONE} KEY3 || ret=1 + retry_quiet 30 _wait_for_done_signing ${ZONE} KEY4 || ret=1 + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Test dynamic zones that switch to inline-signing. +set_zone "dynamic2inline.kasp" +set_policy "default" "1" "3600" +set_server "ns6" "10.53.0.6" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# The CSK is rumoured. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "rumoured" +set_keystate "KEY1" "STATE_KRRSIG" "rumoured" +set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" +set_keystate "KEY1" "STATE_DS" "hidden" +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Test key lifetime updates. +check_key_lifetime "shorter-lifetime" "short-lifetime" "16070400" +check_key_lifetime "longer-lifetime" "long-lifetime" "31536000" +check_key_lifetime "limit-lifetime" "short-lifetime" "16070400" +check_key_lifetime "unlimit-lifetime" "unlimited-lifetime" "0" + +# +# Testing going insecure. +# + +# +# Zone: step1.going-insecure.kasp +# +set_zone "step1.going-insecure.kasp" +set_policy "insecure" "2" "3600" +set_server "ns6" "10.53.0.6" +# Expect a CDS/CDNSKEY Delete Record. +set_cdsdelete + +# Key goal states should be HIDDEN. +init_migration_insecure +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY2" "GOAL" "hidden" +# The DS may be removed if we are going insecure. +set_keystate "KEY1" "STATE_DS" "unretentive" + +# Various signing policy checks. +check_keys +wait_for_done_signing +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Tell named that the DS has been removed. +rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" +wait_for_done_signing +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DS becomes HIDDEN. This happens after the +# parent propagation delay, and DS TTL: +# 1h + 1d = 25h = 90000 seconds. +check_next_key_event 90000 + +# +# Zone: step2.going-insecure.kasp +# +set_zone "step2.going-insecure.kasp" +set_policy "insecure" "2" "3600" +set_server "ns6" "10.53.0.6" + +# The DS is long enough removed from the zone to be considered HIDDEN. +# This means the DNSKEY and the KSK signatures can be removed. +set_keystate "KEY1" "STATE_DS" "hidden" +set_keystate "KEY1" "STATE_DNSKEY" "unretentive" +set_keystate "KEY1" "STATE_KRRSIG" "unretentive" +set_keysigning "KEY1" "no" + +set_keystate "KEY2" "STATE_DNSKEY" "unretentive" +set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" +set_zonesigning "KEY2" "no" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain + +# Next key event is when the DNSKEY becomes HIDDEN. This happens after the +# propagation delay, plus DNSKEY TTL: +# 5m + 2h = 125m = 7500 seconds. +check_next_key_event 7500 + +# +# Zone: step1.going-insecure-dynamic.kasp +# +set_zone "step1.going-insecure-dynamic.kasp" +set_dynamic +set_policy "insecure" "2" "3600" +set_server "ns6" "10.53.0.6" +# Expect a CDS/CDNSKEY Delete Record. +set_cdsdelete + +# Key goal states should be HIDDEN. +init_migration_insecure +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY2" "GOAL" "hidden" +# The DS may be removed if we are going insecure. +set_keystate "KEY1" "STATE_DS" "unretentive" + +# Various signing policy checks. +check_keys +wait_for_done_signing +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Tell named that the DS has been removed. +rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" +wait_for_done_signing +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain +dnssec_verify + +# Next key event is when the DS becomes HIDDEN. This happens after the +# parent propagation delay, retire safety delay, and DS TTL: +# 1h + 1d = 25h = 90000 seconds. +check_next_key_event 90000 + +# +# Zone: step2.going-insecure-dynamic.kasp +# +set_zone "step2.going-insecure-dynamic.kasp" +set_dynamic +set_policy "insecure" "2" "3600" +set_server "ns6" "10.53.0.6" + +# The DS is long enough removed from the zone to be considered HIDDEN. +# This means the DNSKEY and the KSK signatures can be removed. +set_keystate "KEY1" "STATE_DS" "hidden" +set_keystate "KEY1" "STATE_DNSKEY" "unretentive" +set_keystate "KEY1" "STATE_KRRSIG" "unretentive" +set_keysigning "KEY1" "no" + +set_keystate "KEY2" "STATE_DNSKEY" "unretentive" +set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" +set_zonesigning "KEY2" "no" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +check_apex +check_subdomain + +# Next key event is when the DNSKEY becomes HIDDEN. This happens after the +# propagation delay, plus DNSKEY TTL: +# 5m + 2h = 125m = 7500 seconds. +check_next_key_event 7500 + +# +# Zone: step1.going-straight-to-none.kasp +# +set_zone "step1.going-straight-to-none.kasp" +set_policy "none" "1" "3600" +set_server "ns6" "10.53.0.6" + +# The zone will go bogus after signatures expire, but remains validly signed for now. + +# Key properties. +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# This policy only has one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +dnssec_verify + +# +# Zone: step1.going-straight-to-none-dynamic.kasp +# +set_zone "step1.going-straight-to-none-dynamic.kasp" +set_policy "none" "1" "3600" +set_server "ns6" "10.53.0.6" + +# The zone will go bogus after signatures expire, but remains validly signed for now. + +# Key properties. +set_keyrole "KEY1" "csk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "yes" +# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +# This policy only has one key. +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Various signing policy checks. +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +dnssec_verify + +# +# Testing KSK/ZSK algorithm rollover. +# + +# Policy parameters. +# Lksk: unlimited +# Lzsk: unlimited +Lksk=0 +Lzsk=0 + +# +# Zone: step1.algorithm-roll.kasp +# +set_zone "step1.algorithm-roll.kasp" +set_policy "ecdsa256" "4" "3600" +set_server "ns6" "10.53.0.6" +# Old RSASHA1 keys. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "0" +set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +# New ECDSAP256SHA256 keys. +key_clear "KEY3" +set_keyrole "KEY3" "ksk" +set_keylifetime "KEY3" "0" +set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY3" "yes" +set_zonesigning "KEY3" "no" + +key_clear "KEY4" +set_keyrole "KEY4" "zsk" +set_keylifetime "KEY4" "0" +set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY4" "no" +set_zonesigning "KEY4" "yes" +# The RSAHSHA1 keys are outroducing. +set_keystate "KEY1" "GOAL" "hidden" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" +set_keystate "KEY2" "GOAL" "hidden" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" +# The ECDSAP256SHA256 keys are introducing. +set_keystate "KEY3" "GOAL" "omnipresent" +set_keystate "KEY3" "STATE_DNSKEY" "rumoured" +set_keystate "KEY3" "STATE_KRRSIG" "rumoured" +set_keystate "KEY3" "STATE_DS" "hidden" +set_keystate "KEY4" "GOAL" "omnipresent" +set_keystate "KEY4" "STATE_DNSKEY" "rumoured" +set_keystate "KEY4" "STATE_ZRRSIG" "rumoured" + +# Various signing policy checks. +check_keys +wait_for_done_signing +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" + +# Set expected key times: +# - The old keys are published and activated. +rollover_predecessor_keytimes 0 +# - KSK must be retired since it no longer matches the policy. +keyfile=$(key_get KEY1 BASEFILE) +grep "; Inactive:" "${keyfile}.key" >retired.test${n}.ksk +retired=$(awk '{print $3}' retired.test${n}.zsk +retired=$(awk '{print $3}' retired.test${n}.ksk +retired=$(awk '{print $3}' 0 + isctest.kasp.check_signatures(rrsigs, qtype, fqdn, keys, []) + + +def test_kasp_default(servers): + server = servers["ns3"] + + # check the zone with default kasp policy has loaded and is signed. + isctest.log.info("check a zone with the default policy is signed") + zone = "default.kasp" + policy = "default" + + # Key properties. + # DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. + keyprops = [ + "csk 0 13 256 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ] + expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + set_keytimes_default_policy(expected[0]) + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, keys, []) + + # Trigger a keymgr run. Make sure the key files are not touched if there + # are no modifications to the key metadata. + isctest.log.info( + "check that key files are untouched if there are no metadata changes" + ) + key = keys[0] + privkey_stat = os.stat(key.privatefile) + pubkey_stat = os.stat(key.keyfile) + state_stat = os.stat(key.statefile) + + with server.watch_log_from_here() as watcher: + server.rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line(f"keymgr: {zone} done") + + assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime + assert pubkey_stat.st_mtime == os.stat(key.keyfile).st_mtime + assert state_stat.st_mtime == os.stat(key.statefile).st_mtime + + # again + with server.watch_log_from_here() as watcher: + server.rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line(f"keymgr: {zone} done") + + assert privkey_stat.st_mtime == os.stat(key.privatefile).st_mtime + assert pubkey_stat.st_mtime == os.stat(key.keyfile).st_mtime + assert state_stat.st_mtime == os.stat(key.statefile).st_mtime + + # modify unsigned zone file and check that new record is signed. + isctest.log.info("check that an updated zone signs the new record") + shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db") + server.rndc(f"reload {zone}", log=False) + + def update_is_signed(): + parts = update.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + rdata = parts[2] + return isctest.kasp.verify_update_is_signed( + server, zone, qname, qtype, rdata, keys, [] + ) + + expected_updates = [f"a.{zone}. A 10.0.0.11", f"d.{zone}. A 10.0.0.44"] + for update in expected_updates: + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + # Move the private key file, a rekey event should not introduce + # replacement keys. + isctest.log.info("check that missing private key doesn't trigger rollover") + shutil.move(f"{key.privatefile}", f"{key.path}.offline") + expectmsg = "zone_rekey:zone_verifykeys failed: some key files are missing" + with server.watch_log_from_here() as watcher: + server.rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line(f"zone {zone}/IN (signed): {expectmsg}") + # Nothing has changed. + expected[0].properties["private"] = False + isctest.kasp.check_keys(zone, keys, expected) + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, keys, []) + + # A zone that uses inline-signing. + isctest.log.info("check an inline-signed zone with the default policy is signed") + zone = "inline-signing.kasp" + # Key properties. + key1 = KeyProperties.default() + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + expected = [key1] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + set_keytimes_default_policy(key1) + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, keys, []) + + +def test_kasp_dynamic(servers): + # Dynamic update test cases. + server = servers["ns3"] + + # Standard dynamic zone. + isctest.log.info("check dynamic zone is updated and signed after update") + zone = "dynamic.kasp" + policy = "default" + # Key properties. + key1 = KeyProperties.default() + expected = [key1] + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + set_keytimes_default_policy(key1) + expected = [key1] + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, keys, []) + + # Update zone with nsupdate. + def nsupdate(updates): + message = dns.update.UpdateMessage(zone) + for update in updates: + if update[0] == "del": + message.delete(update[1], update[2], update[3]) + else: + assert update[0] == "add" + message.add(update[1], update[2], update[3], update[4]) + + try: + response = isctest.query.udp( + message, server.ip, server.ports.dns, timeout=3 + ) + assert response.rcode() == dns.rcode.NOERROR + except dns.exception.Timeout: + assert False, f"update timeout for {zone}" + + isctest.log.debug(f"update of zone {zone} to server {server.ip} successful") + + def update_is_signed(): + parts = update.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + rdata = parts[2] + return isctest.kasp.verify_update_is_signed( + server, zone, qname, qtype, rdata, keys, [] + ) + + updates = [ + ["del", f"a.{zone}.", "A", "10.0.0.1"], + ["add", f"a.{zone}.", 300, "A", "10.0.0.101"], + ["add", f"d.{zone}.", 300, "A", "10.0.0.4"], + ] + nsupdate(updates) + + expected_updates = [f"a.{zone}. A 10.0.0.101", f"d.{zone}. A 10.0.0.4"] + for update in expected_updates: + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + # Update zone with nsupdate (reverting the above change). + updates = [ + ["add", f"a.{zone}.", 300, "A", "10.0.0.1"], + ["del", f"a.{zone}.", "A", "10.0.0.101"], + ["del", f"d.{zone}.", "A", "10.0.0.4"], + ] + nsupdate(updates) + + update = f"a.{zone}. A 10.0.0.1" + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + # Update zone with freeze/thaw. + isctest.log.info("check dynamic zone is updated and signed after freeze and thaw") + with server.watch_log_from_here() as watcher: + server.rndc(f"freeze {zone}", log=False) + watcher.wait_for_line(f"freezing zone '{zone}/IN': success") + + time.sleep(1) + with open(f"ns3/{zone}.db", "a", encoding="utf-8") as zonefile: + zonefile.write(f"d.{zone}. 300 A 10.0.0.44\n") + time.sleep(1) + + with server.watch_log_from_here() as watcher: + server.rndc(f"thaw {zone}", log=False) + watcher.wait_for_line(f"thawing zone '{zone}/IN': success") + + expected_updates = [f"a.{zone}. A 10.0.0.1", f"d.{zone}. A 10.0.0.44"] + + for update in expected_updates: + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + # Dynamic, and inline-signing. + zone = "dynamic-inline-signing.kasp" + # Key properties. + key1 = KeyProperties.default() + expected = [key1] + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + set_keytimes_default_policy(key1) + expected = [key1] + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, keys, []) + + # Update zone with freeze/thaw. + isctest.log.info( + "check dynamic inline-signed zone is updated and signed after freeze and thaw" + ) + with server.watch_log_from_here() as watcher: + server.rndc(f"freeze {zone}", log=False) + watcher.wait_for_line(f"freezing zone '{zone}/IN': success") + + time.sleep(1) + shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db") + time.sleep(1) + + with server.watch_log_from_here() as watcher: + server.rndc(f"thaw {zone}", log=False) + watcher.wait_for_line(f"thawing zone '{zone}/IN': success") + + expected_updates = [f"a.{zone}. A 10.0.0.11", f"d.{zone}. A 10.0.0.44"] + for update in expected_updates: + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + # Dynamic, signed, and inline-signing. + isctest.log.info("check dynamic signed, and inline-signed zone") + zone = "dynamic-signed-inline-signing.kasp" + # Key properties. + key1 = KeyProperties.default() + # The ns3/setup.sh script sets all states to omnipresent. + key1.metadata["DNSKEYState"] = "omnipresent" + key1.metadata["KRRSIGState"] = "omnipresent" + key1.metadata["ZRRSIGState"] = "omnipresent" + key1.metadata["DSState"] = "omnipresent" + expected = [key1] + keys = isctest.kasp.keydir_to_keylist(zone, "ns3/keys") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, keys, []) + # Ensure no zone_resigninc for the unsigned version of the zone is triggered. + assert f"zone_resigninc: zone {zone}/IN (unsigned): enter" not in "ns3/named.run" + + +def test_kasp_checkds(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-ksk.kasp. + zone = "checkds-ksk.kasp" + policy = "checkds-ksk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if k.is_zsk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, ksks, zsks) + + now = KeyTimingMetadata.now() + ksk = ksks[0] + + isctest.log.info("check if checkds -publish correctly sets DSPublish") + server.rndc(f"dnssec -checkds -when {now} published {zone}", log=False) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn correctly sets DSRemoved") + server.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "unretentive" + expected[0].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + +def test_kasp_checkds_doubleksk(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-doubleksk.kasp. + zone = "checkds-doubleksk.kasp" + policy = "checkds-doubleksk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if k.is_zsk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, ksks, zsks) + + now = KeyTimingMetadata.now() + ksk = ksks[0] + + badalg = os.environ["ALTERNATIVE_ALGORITHM_NUMBER"] + isctest.log.info("check invalid checkds commands") + + def check_error(): + response = server.rndc(test["command"], log=False) + assert test["error"] in response + + test_cases = [ + { + "command": f"dnssec -checkds -when {now} published {zone}", + "error": "multiple possible keys found, retry command with -key id", + }, + { + "command": f"dnssec -checkds -when {now} withdrawn {zone}", + "error": "multiple possible keys found, retry command with -key id", + }, + { + "command": f"dnssec -checkds -when {now} -key {ksks[0].tag} -alg {badalg} published {zone}", + "error": "Error executing checkds command: no matching key found", + }, + { + "command": f"dnssec -checkds -when {now} -key {ksks[0].tag} -alg {badalg} withdrawn {zone}", + "error": "Error executing checkds command: no matching key found", + }, + ] + for test in test_cases: + check_error() + + isctest.log.info("check if checkds -publish -key correctly sets DSPublish") + server.rndc( + f"dnssec -checkds -when {now} -key {ksk.tag} published {zone}", log=False + ) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn -key correctly sets DSRemoved") + ksk = ksks[1] + server.rndc( + f"dnssec -checkds -when {now} -key {ksk.tag} withdrawn {zone}", log=False + ) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[1].metadata["DSState"] = "unretentive" + expected[1].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + +def test_kasp_checkds_csk(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-csk.kasp. + zone = "checkds-csk.kasp" + policy = "checkds-csk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, keys, []) + + now = KeyTimingMetadata.now() + ksk = keys[0] + + isctest.log.info("check if checkds -publish csk correctly sets DSPublish") + server.rndc(f"dnssec -checkds -when {now} published {zone}", log=False) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn csk correctly sets DSRemoved") + server.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "unretentive" + expected[0].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + +def test_kasp_special_characters(servers): + server = servers["ns3"] + + # A zone with special characters. + isctest.log.info("check special characters") + + zone = r'i-am.":\;?&[]\@!\$*+,|=\.\(\)special.kasp' + # It is non-trivial to adapt the tests to deal with all possible different + # escaping characters, so we will just try to verify the zone. + isctest.kasp.check_dnssec_verify(server, zone) + + +def test_kasp_insecure(servers): + server = servers["ns3"] + + # Insecure zones. + isctest.log.info("check insecure zones") + + zone = "insecure.kasp" + expected = [] + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_keys(zone, keys, expected) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy="insecure") + isctest.kasp.check_apex(server, zone, keys, []) + isctest.kasp.check_subdomain(server, zone, keys, []) + + zone = "unsigned.kasp" + expected = [] + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_keys(zone, keys, expected) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy=None) + isctest.kasp.check_apex(server, zone, keys, []) + isctest.kasp.check_subdomain(server, zone, keys, []) + # Make sure the zone file is untouched. + isctest.check.file_contents_equal(f"ns3/{zone}.db.infile", f"ns3/{zone}.db") + + +def test_kasp_bad_maxzonettl(servers): + server = servers["ns3"] + + # check that max-zone-ttl rejects zones with too high TTL. + isctest.log.info("check max-zone-ttl rejects zones with too high TTL") + zone = "max-zone-ttl.kasp" + assert f"loading from master file {zone}.db failed: out of range" in server.log + + +def test_kasp_dnssec_keygen(): + def keygen(zone, policy, keydir=None): + if keydir is None: + keydir = "." + + keygen_command = [ + os.environ.get("KEYGEN"), + "-K", + keydir, + "-k", + policy, + "-l", + "kasp.conf", + zone, + ] + + return isctest.run.cmd(keygen_command, log_stdout=True).stdout.decode("utf-8") + + # check that 'dnssec-keygen -k' (configured policy) creates valid files. + keyprops = [ + f"csk {lifetime['P1Y']} 13 256", + f"ksk {lifetime['P1Y']} 8 2048", + f"zsk {lifetime['P30D']} 8 2048", + f"zsk {lifetime['P6M']} 8 3072", + ] + keydir = "keys" + out = keygen("kasp", "kasp", keydir) + keys = isctest.kasp.keystr_to_keylist(out, keydir) + expected = isctest.kasp.policy_to_properties(ttl=200, keys=keyprops) + isctest.kasp.check_keys("kasp", keys, expected) + + # check that 'dnssec-keygen -k' (default policy) creates valid files. + keyprops = ["csk 0 13 256"] + out = keygen("kasp", "default") + keys = isctest.kasp.keystr_to_keylist(out) + expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops) + isctest.kasp.check_keys("kasp", keys, expected) + + # check that 'dnssec-settime' by default does not edit key state file. + key = keys[0] + shutil.copyfile(key.privatefile, f"{key.privatefile}.backup") + shutil.copyfile(key.keyfile, f"{key.keyfile}.backup") + shutil.copyfile(key.statefile, f"{key.statefile}.backup") + + created = key.get_timing("Created") + publish = key.get_timing("Publish") + timedelta(hours=1) + settime = [ + os.environ.get("SETTIME"), + "-P", + str(publish), + key.path, + ] + out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8") + + isctest.check.file_contents_equal(f"{key.statefile}", f"{key.statefile}.backup") + assert key.get_metadata("Publish", file=key.privatefile) == str(publish) + assert key.get_metadata("Publish", file=key.keyfile, comment=True) == str(publish) + + # check that 'dnssec-settime -s' also sets publish time metadata and + # states in key state file. + now = KeyTimingMetadata.now() + goal = "omnipresent" + dnskey = "rumoured" + krrsig = "rumoured" + zrrsig = "omnipresent" + ds = "hidden" + keyprops = [ + f"csk 0 13 256 goal:{goal} dnskey:{dnskey} krrsig:{krrsig} zrrsig:{zrrsig} ds:{ds}", + ] + expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops) + expected[0].timing = { + "Generated": created, + "Published": now, + "Active": created, + "DNSKEYChange": now, + "KRRSIGChange": now, + "ZRRSIGChange": now, + "DSChange": now, + } + + settime = [ + os.environ.get("SETTIME"), + "-s", + "-P", + str(now), + "-g", + goal, + "-k", + dnskey, + str(now), + "-r", + krrsig, + str(now), + "-z", + zrrsig, + str(now), + "-d", + ds, + str(now), + key.path, + ] + out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8") + isctest.kasp.check_keys("kasp", keys, expected) + isctest.kasp.check_keytimes(keys, expected) + + # check that 'dnssec-settime -s' also unsets publish time metadata and + # states in key state file. + now = KeyTimingMetadata.now() + keyprops = ["csk 0 13 256"] + expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops) + expected[0].timing = { + "Generated": created, + "Active": created, + } + + settime = [ + os.environ.get("SETTIME"), + "-s", + "-P", + "none", + "-g", + "none", + "-k", + "none", + str(now), + "-z", + "none", + str(now), + "-r", + "none", + str(now), + "-d", + "none", + str(now), + key.path, + ] + out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8") + isctest.kasp.check_keys("kasp", keys, expected) + isctest.kasp.check_keytimes(keys, expected) + + # check that 'dnssec-settime -s' also sets active time metadata and states in key state file (uppercase) + soon = now + timedelta(hours=2) + goal = "hidden" + dnskey = "unretentive" + krrsig = "omnipresent" + zrrsig = "unretentive" + ds = "omnipresent" + keyprops = [ + f"csk 0 13 256 goal:{goal} dnskey:{dnskey} krrsig:{krrsig} zrrsig:{zrrsig} ds:{ds}", + ] + expected = isctest.kasp.policy_to_properties(ttl=3600, keys=keyprops) + expected[0].timing = { + "Generated": created, + "Active": soon, + "DNSKEYChange": soon, + "KRRSIGChange": soon, + "ZRRSIGChange": soon, + "DSChange": soon, + } + + settime = [ + os.environ.get("SETTIME"), + "-s", + "-A", + str(soon), + "-g", + "HIDDEN", + "-k", + "UNRETENTIVE", + str(soon), + "-z", + "UNRETENTIVE", + str(soon), + "-r", + "OMNIPRESENT", + str(soon), + "-d", + "OMNIPRESENT", + str(soon), + key.path, + ] + out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8") + isctest.kasp.check_keys("kasp", keys, expected) + isctest.kasp.check_keytimes(keys, expected) + + +def test_kasp_zsk_retired(servers): + server = servers["ns3"] + + config = { + "dnskey-ttl": timedelta(seconds=300), + "ds-ttl": timedelta(days=1), + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=7), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), + } + + zone = "zsk-retired.autosign" + policy = "autosign" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + key_properties = [ + f"ksk 63072000 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + # zsk predecessor + f"zsk 31536000 {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + # zsk successor + f"zsk 31536000 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden", + ] + expected = isctest.kasp.policy_to_properties(300, key_properties) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + + offset = -timedelta(days=30 * 6) + sign_delay = config["signatures-validity"] - config["signatures-refresh"] + + def sumvars(variables): + result = timedelta(0) + for var in variables: + result = result + config[var] + return result + + # KSK Key Timings: + # IpubC = DprpC + TTLkey + # Note: Also need to wait until the signatures are omnipresent. + # That's why we use max-zone-ttl instead of dnskey-ttl here. + Ipub_KSK = sumvars(["zone-propagation-delay", "max-zone-ttl"]) + # Iret = DprpP + TTLds + Iret_KSK = sumvars(["parent-propagation-delay", "retire-safety", "ds-ttl"]) + + # ZSK Key Timings: + # Ipub = Dprp + TTLkey + Ipub_ZSK = sumvars(["zone-propagation-delay", "publish-safety", "dnskey-ttl"]) + # Iret = Dsgn + Dprp + TTLsig + Iret_ZSK = sumvars(["zone-propagation-delay", "retire-safety", "max-zone-ttl"]) + Iret_ZSK = Iret_ZSK + sign_delay + + # KSK + expected[0].timing["Generated"] = expected[0].key.get_timing("Created") + expected[0].timing["Published"] = expected[0].timing["Generated"] + expected[0].timing["Published"] = expected[0].timing["Published"] + offset + expected[0].timing["Active"] = expected[0].timing["Published"] + expected[0].timing["Retired"] = expected[0].timing["Published"] + int( + expected[0].metadata["Lifetime"] + ) + # Trdy(N) = Tpub(N) + IpubC + expected[0].timing["PublishCDS"] = expected[0].timing["Published"] + Ipub_KSK + # Tdea(N) = Tret(N) + Iret + expected[0].timing["Removed"] = expected[0].timing["Retired"] + Iret_KSK + expected[0].timing["DNSKEYChange"] = None + expected[0].timing["DSChange"] = None + expected[0].timing["KRRSIGChange"] = None + + # ZSK (predecessor) + expected[1].timing["Generated"] = expected[1].key.get_timing("Created") + expected[1].timing["Published"] = expected[1].timing["Generated"] + offset + expected[1].timing["Active"] = expected[1].timing["Published"] + expected[1].timing["Retired"] = expected[1].timing["Generated"] + # Tdea(N) = Tret(N) + Iret + expected[1].timing["Removed"] = expected[1].timing["Retired"] + Iret_ZSK + expected[1].timing["DNSKEYChange"] = None + expected[1].timing["ZRRSIGChange"] = None + + # ZSK (successor) + expected[2].timing["Generated"] = expected[2].key.get_timing("Created") + expected[2].timing["Published"] = expected[2].timing["Generated"] + # Trdy(N) = Tpub(N) + Ipub + expected[2].timing["Active"] = expected[2].timing["Published"] + Ipub_ZSK + # Tret(N) = Tact(N) + Lzsk + expected[2].timing["Retired"] = expected[2].timing["Active"] + int( + expected[2].metadata["Lifetime"] + ) + # Tdea(N) = Tret(N) + Iret + expected[2].timing["Removed"] = expected[2].timing["Retired"] + Iret_ZSK + expected[2].timing["DNSKEYChange"] = None + expected[2].timing["ZRRSIGChange"] = None + + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, ksks, zsks) + + queries = [ + f"{zone} DNSKEY", + f"{zone} SOA", + f"{zone} NS", + f"{zone} NSEC", + f"a.{zone} A", + f"a.{zone} NSEC", + f"b.{zone} A", + f"b.{zone} NSEC", + f"c.{zone} A", + f"c.{zone} NSEC", + f"ns3.{zone} A", + f"ns3.{zone} NSEC", + ] + + def rrsig_is_refreshed(): + parts = query.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + return isctest.kasp.verify_rrsig_is_refreshed( + server, zone, f"ns3/{zone}.db.signed", qname, qtype, ksks, zsks + ) + + for query in queries: + isctest.run.retry_with_timeout(rrsig_is_refreshed, timeout=5) + + # Load again, make sure the purged key is not an issue when verifying keys. + with server.watch_log_from_here() as watcher: + server.rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line(f"keymgr: {zone} done") + + msg = f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" + server.log.prohibit(msg) + + +def test_kasp_reload_restart(servers): + server = servers["ns6"] + zone = "example" + + def query_soa(qname): + fqdn = dns.name.from_text(qname) + qtype = dns.rdatatype.SOA + query = dns.message.make_query(fqdn, qtype, use_edns=True, want_dnssec=True) + try: + response = isctest.query.tcp(query, server.ip, server.ports.dns, timeout=3) + except dns.exception.Timeout: + isctest.log.debug(f"query timeout for query {qname} SOA to {server.ip}") + return 0, 0 + + assert response.rcode() == dns.rcode.NOERROR + + for rr in response.answer: + if rr.match(fqdn, dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype): + continue + + assert rr.match(fqdn, dns.rdataclass.IN, qtype, dns.rdatatype.NONE) + assert len(rr) == 1 + return rr[0].serial, rr.ttl + + return 0, 0 + + def check_soa_ttl(): + soa2, ttl2 = query_soa(zone) + return soa1 < soa2 and ttl2 == newttl + + # Check that the SOA SERIAL increases and check the TTLs (should be 300 as + # defined in ns6/example2.db.in). + soa1, ttl1 = query_soa(zone) + assert ttl1 == 300 + + shutil.copyfile(f"ns6/{zone}2.db.in", f"ns6/{zone}.db") + with server.watch_log_from_here() as watcher: + server.rndc("reload", log=False) + watcher.wait_for_line("all zones loaded") + + newttl = 300 + isctest.run.retry_with_timeout(check_soa_ttl, timeout=10) + + # Check that the SOA SERIAL increases and check the TTLs (should be changed + # from 300 to 400 as defined in ns6/example3.db.in). + soa1, ttl1 = query_soa(zone) + assert ttl1 == 300 + + server.stop() + shutil.copyfile(f"ns6/{zone}3.db.in", f"ns6/{zone}.db") + os.unlink(f"ns6/{zone}.db.jnl") + with server.watch_log_from_here() as watcher: + server.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + watcher.wait_for_line("all zones loaded") + + newttl = 400 + isctest.run.retry_with_timeout(check_soa_ttl, timeout=10) diff --git a/bin/tests/system/kasp/tests_sh_kasp.py b/bin/tests/system/kasp/tests_sh_kasp.py new file mode 100644 index 0000000..64b9eac --- /dev/null +++ b/bin/tests/system/kasp/tests_sh_kasp.py @@ -0,0 +1,65 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "K*.private", + "K*.key", + "K*.state", + "K*.cmp", + "*.created", + "dig.out*", + "keyevent.out.*", + "keygen.out.*", + "keys", + "published.test*", + "python.out.*", + "retired.test*", + "rndc.dnssec.*.out.*", + "rndc.zonestatus.out.*", + "rrsig.out.*", + "created.key-*", + "unused.key-*", + "verify.out.*", + "zone.out.*", + "ns*/K*.private", + "ns*/K*.key", + "ns*/K*.state", + "ns*/*.db", + "ns*/*.db.infile", + "ns*/*.db.signed", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/dsset-*", + "ns*/keygen.out.*", + "ns*/keys", + "ns*/ksk", + "ns*/ksk/K*", + "ns*/zsk", + "ns*/zsk", + "ns*/zsk/K*", + "ns*/named-fips.conf", + "ns*/settime.out.*", + "ns*/signer.out.*", + "ns*/zones", + "ns*/policies/*.conf", + "ns*/*.zsk1", + "ns*/*.zsk2", + "ns3/legacy-keys.*", + "ns3/dynamic-signed-inline-signing.kasp.db.signed.signed", + ] +) + + +def test_kasp(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/keepalive/ns1/named.conf.j2 b/bin/tests/system/keepalive/ns1/named.conf.j2 new file mode 100644 index 0000000..32dbf90 --- /dev/null +++ b/bin/tests/system/keepalive/ns1/named.conf.j2 @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/keepalive/ns1/root.db b/bin/tests/system/keepalive/ns1/root.db new file mode 100644 index 0000000..17780d1 --- /dev/null +++ b/bin/tests/system/keepalive/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/keepalive/ns2/example.db b/bin/tests/system/keepalive/ns2/example.db new file mode 100644 index 0000000..ccc6ef9 --- /dev/null +++ b/bin/tests/system/keepalive/ns2/example.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns2 hostmaster.isc.org. 1 600 600 1200 600 +@ NS ns2 +ns2 A 10.53.0.2 +foo A 10.53.1.1 +bar A 10.53.2.2 diff --git a/bin/tests/system/keepalive/ns2/named.conf.j2 b/bin/tests/system/keepalive/ns2/named.conf.j2 new file mode 100644 index 0000000..011e1d0 --- /dev/null +++ b/bin/tests/system/keepalive/ns2/named.conf.j2 @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + send-cookie yes; + tcp-advertised-timeout 150; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/keepalive/ns3/named.conf.j2 b/bin/tests/system/keepalive/ns3/named.conf.j2 new file mode 100644 index 0000000..76e5a5b --- /dev/null +++ b/bin/tests/system/keepalive/ns3/named.conf.j2 @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +server 10.53.0.2 { + tcp-only yes; + tcp-keepalive yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/keepalive/tests_keepalive.py b/bin/tests/system/keepalive/tests_keepalive.py new file mode 100644 index 0000000..c815c3e --- /dev/null +++ b/bin/tests/system/keepalive/tests_keepalive.py @@ -0,0 +1,69 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import isctest +import pytest + + +pytestmark = pytest.mark.extra_artifacts( + ["ns2/named.stats"], +) + + +def test_dig_tcp_keepalive_handling(named_port, servers): + def get_keepalive_options_received(): + servers["ns2"].rndc("stats", log=False) + options_received = 0 + with open("ns2/named.stats", "r", encoding="utf-8") as ns2_stats_file: + for line in ns2_stats_file: + if "EDNS TCP keepalive option received" in line: + options_received = line.split()[0] + return int(options_received) + + dig = isctest.run.Dig(f"-p {str(named_port)}") + + isctest.log.info("check that dig handles TCP keepalive in query") + assert "; TCP-KEEPALIVE" in dig("+qr +keepalive foo.example. @10.53.0.2") + + isctest.log.info("check that dig added TCP keepalive was received") + assert get_keepalive_options_received() == 1 + + isctest.log.info("check that TCP keepalive is added for TCP responses") + assert "; TCP-KEEPALIVE" in dig("+tcp +keepalive foo.example. @10.53.0.2") + + isctest.log.info("check that TCP keepalive requires TCP") + assert "; TCP-KEEPALIVE" not in dig("+keepalive foo.example. @10.53.0.2") + + isctest.log.info("check the default keepalive value") + assert "; TCP-KEEPALIVE: 30.0 secs" in dig( + "+tcp +keepalive foo.example. @10.53.0.3" + ) + + isctest.log.info("check a keepalive configured value") + assert "; TCP-KEEPALIVE: 15.0 secs" in dig( + "+tcp +keepalive foo.example. @10.53.0.2" + ) + + isctest.log.info("check a re-configured keepalive value") + response = servers["ns2"].rndc("tcp-timeouts 300 300 300 200", log=False) + assert "tcp-initial-timeout=300" in response + assert "tcp-idle-timeout=300" in response + assert "tcp-keepalive-timeout=300" in response + assert "tcp-advertised-timeout=200" in response + assert "; TCP-KEEPALIVE: 20.0 secs" in dig( + "+tcp +keepalive foo.example. @10.53.0.2" + ) + + isctest.log.info("check server config entry") + base_options_received = get_keepalive_options_received() + dig("bar.example. @10.53.0.3") + next_options_received = get_keepalive_options_received() + assert base_options_received < next_options_received diff --git a/bin/tests/system/keyfromlabel/template.db.in b/bin/tests/system/keyfromlabel/template.db.in new file mode 100644 index 0000000..f2baaa7 --- /dev/null +++ b/bin/tests/system/keyfromlabel/template.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns root ( + 2000082401 ; serial + 1800 ; refresh (30 minutes) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.1 + +txt TXT "test" + diff --git a/bin/tests/system/keyfromlabel/tests_keyfromlabel.py b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py new file mode 100644 index 0000000..f531915 --- /dev/null +++ b/bin/tests/system/keyfromlabel/tests_keyfromlabel.py @@ -0,0 +1,190 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import hashlib +import os +import re +import shutil + +import pytest + +import isctest.mark + + +pytestmark = [ + isctest.mark.softhsm2_environment, + pytest.mark.extra_artifacts( + [ + "*.example.db", + "*.example.db.signed", + "K*", + "dsset-*", + "keyfromlabel.out.*", + "pin", + "pkcs11-tool.out.*", + "signer.out.*", + ], + ), +] + + +EMPTY_OPENSSL_CONF_ENV = {**os.environ, "OPENSSL_CONF": ""} + +HSMPIN = "1234" + + +@pytest.fixture(autouse=True) +def token_init_and_cleanup(): + + # Create pin file for the $KEYFRLAB command + with open("pin", "w", encoding="utf-8") as pinfile: + pinfile.write(HSMPIN) + + token_init_command = [ + "softhsm2-util", + "--init-token", + "--free", + "--pin", + HSMPIN, + "--so-pin", + HSMPIN, + "--label", + "softhsm2-keyfromlabel", + ] + + token_cleanup_command = [ + "softhsm2-util", + "--delete-token", + "--token", + "softhsm2-keyfromlabel", + ] + + isctest.run.cmd( + token_cleanup_command, + env=EMPTY_OPENSSL_CONF_ENV, + log_stderr=False, + raise_on_exception=False, + ) + + try: + output = isctest.run.cmd( + token_init_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True + ).stdout.decode("utf-8") + assert "The token has been initialized and is reassigned to slot" in output + yield + finally: + output = isctest.run.cmd( + token_cleanup_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True + ).stdout.decode("utf-8") + assert re.search("Found token (.*) with matching token label", output) + assert re.search("The token (.*) has been deleted", output) + + +# pylint: disable-msg=too-many-locals +@pytest.mark.parametrize( + "alg_name,alg_type,alg_bits", + [ + ("rsasha256", "rsa", "2048"), + ("rsasha512", "rsa", "2048"), + ("ecdsap256sha256", "EC", "prime256v1"), + ("ecdsap384sha384", "EC", "prime384v1"), + # Edwards curves are not yet supported by OpenSC + # ("ed25519","EC","edwards25519"), + # ("ed448","EC","edwards448") + ], +) +def test_keyfromlabel(alg_name, alg_type, alg_bits): + + def keygen(alg_type, alg_bits, zone, key_id): + label = f"{key_id}-{zone}" + p11_id = hashlib.sha1(label.encode("utf-8")).hexdigest() + + pkcs11_command = [ + "pkcs11-tool", + "--module", + os.environ.get("SOFTHSM2_MODULE"), + "--token-label", + "softhsm2-keyfromlabel", + "-l", + "-k", + "--key-type", + f"{alg_type}:{alg_bits}", + "--label", + label, + "--id", + p11_id, + "--pin", + HSMPIN, + ] + + output = isctest.run.cmd( + pkcs11_command, env=EMPTY_OPENSSL_CONF_ENV, log_stdout=True + ).stdout.decode("utf-8") + + assert "Key pair generated" in output + + def keyfromlabel(alg_name, zone, key_id, key_flag): + key_flag = key_flag.split() if key_flag else [] + + keyfrlab_command = [ + os.environ["KEYFRLAB"], + *os.environ.get("ENGINE_ARG", "").split(), + "-a", + alg_name, + "-l", + f"pkcs11:token=softhsm2-keyfromlabel;object={key_id}-{zone};pin-source=pin", + *key_flag, + zone, + ] + + output = isctest.run.cmd(keyfrlab_command, log_stdout=True) + output_decoded = output.stdout.decode("utf-8").rstrip() + ".key" + + assert os.path.exists(output_decoded) + + return output_decoded + + if f"{alg_name.upper()}_SUPPORTED" not in os.environ: + pytest.skip(f"{alg_name} is not supported") + + # Generate keys for the $zone zone + zone = f"{alg_name}.example" + + keygen(alg_type, alg_bits, zone, "keyfromlabel-zsk") + keygen(alg_type, alg_bits, zone, "keyfromlabel-ksk") + + # Get ZSK + zsk_file = keyfromlabel(alg_name, zone, "keyfromlabel-zsk", "") + + # Get KSK + ksk_file = keyfromlabel(alg_name, zone, "keyfromlabel-ksk", "-f KSK") + + # Sign zone with KSK and ZSK + zone_file = f"zone.{alg_name}.example.db" + + with open(zone_file, "w", encoding="utf-8") as outfile: + for f in ["template.db.in", ksk_file, zsk_file]: + with open(f, "r", encoding="utf-8") as fd: + shutil.copyfileobj(fd, outfile) + + signer_command = [ + os.environ["SIGNER"], + *os.environ.get("ENGINE_ARG", "").split(), + "-S", + "-a", + "-g", + "-o", + zone, + zone_file, + ] + isctest.run.cmd(signer_command, log_stdout=True) + + assert os.path.exists(f"{zone_file}.signed") diff --git a/bin/tests/system/ksr/ns1/named.conf.in b/bin/tests/system/ksr/ns1/named.conf.in new file mode 100644 index 0000000..7283069 --- /dev/null +++ b/bin/tests/system/ksr/ns1/named.conf.in @@ -0,0 +1,95 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; + allow-new-zones yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "common" { + offline-ksk yes; + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "csk" { + offline-ksk no; + keys { + csk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "unlimited" { + offline-ksk yes; + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "no-cdnskey" { + offline-ksk yes; + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + cdnskey no; + cds-digest-types { SHA-1; SHA-256; SHA-384; }; +}; + +dnssec-policy "no-cds" { + offline-ksk yes; + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + cds-digest-types { }; +}; + +dnssec-policy "two-tone" { + offline-ksk yes; + keys { + ksk lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + zsk lifetime P5M algorithm @ALTERNATIVE_ALGORITHM@; + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime P3M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "ksk-roll" { + offline-ksk yes; + keys { + ksk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; diff --git a/bin/tests/system/ksr/ns1/setup.sh b/bin/tests/system/ksr/ns1/setup.sh new file mode 100644 index 0000000..2179ab2 --- /dev/null +++ b/bin/tests/system/ksr/ns1/setup.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +# Key directories +mkdir keydir +mkdir offline + +# Zone files +cp template.db.in common.test.db +cp template.db.in past.test.db +cp template.db.in future.test.db +cp template.db.in last-bundle.test.db +cp template.db.in in-the-middle.test.db +cp template.db.in unlimited.test.db +cp template.db.in two-tone.test.db +cp template.db.in ksk-roll.test.db diff --git a/bin/tests/system/ksr/ns1/template.db.in b/bin/tests/system/ksr/ns1/template.db.in new file mode 100644 index 0000000..d00a6f4 --- /dev/null +++ b/bin/tests/system/ksr/ns1/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns1 +ns1 A 10.53.0.1 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/ksr/setup.sh b/bin/tests/system/ksr/setup.sh new file mode 100644 index 0000000..e200a4d --- /dev/null +++ b/bin/tests/system/ksr/setup.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns1/named.conf.in ns1/named.conf + +( + cd ns1 + $SHELL setup.sh +) diff --git a/bin/tests/system/ksr/tests_ksr.py b/bin/tests/system/ksr/tests_ksr.py new file mode 100644 index 0000000..15ccc02 --- /dev/null +++ b/bin/tests/system/ksr/tests_ksr.py @@ -0,0 +1,1310 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from datetime import timedelta +import os +import shutil +import time + +import pytest + +import isctest +from isctest.kasp import KeyTimingMetadata + +pytestmark = pytest.mark.extra_artifacts( + [ + "K*", + "common.test.*", + "future.test.*", + "in-the-middle.test.*", + "ksk-roll.test.*", + "last-bundle.test.*", + "past.test.*", + "two-tone.test.*", + "unlimited.test.*", + "ns1/K*", + "ns1/_default.nzd", + "ns1/_default.nzf", + "ns1/common.test.db", + "ns1/common.test.db.jbk", + "ns1/common.test.db.signed", + "ns1/common.test.db.signed.jnl", + "ns1/common.test.skr.2", + "ns1/future.test.db", + "ns1/future.test.db.jbk", + "ns1/future.test.db.signed", + "ns1/future.test.skr.1", + "ns1/in-the-middle.test.db", + "ns1/in-the-middle.test.db.jbk", + "ns1/in-the-middle.test.db.signed", + "ns1/in-the-middle.test.db.signed.jnl", + "ns1/in-the-middle.test.skr.1", + "ns1/keydir", + "ns1/ksk-roll.test.db", + "ns1/ksk-roll.test.db.jbk", + "ns1/ksk-roll.test.db.signed", + "ns1/ksk-roll.test.db.signed.jnl", + "ns1/ksk-roll.test.skr.1", + "ns1/last-bundle.test.db", + "ns1/last-bundle.test.db.jbk", + "ns1/last-bundle.test.db.signed", + "ns1/last-bundle.test.db.signed.jnl", + "ns1/last-bundle.test.skr.1", + "ns1/offline", + "ns1/past.test.db", + "ns1/past.test.db.jbk", + "ns1/past.test.db.signed", + "ns1/past.test.skr.1", + "ns1/two-tone.test.db", + "ns1/two-tone.test.db.jbk", + "ns1/two-tone.test.db.signed", + "ns1/two-tone.test.db.signed.jnl", + "ns1/two-tone.test.skr.1", + "ns1/unlimited.test.db", + "ns1/unlimited.test.db.jbk", + "ns1/unlimited.test.db.signed", + "ns1/unlimited.test.db.signed.jnl", + "ns1/unlimited.test.unlimited.skr.1", + ] +) + + +def between(value, start, end): + if value is None or start is None or end is None: + return False + + return start < value < end + + +def ksr(zone, policy, action, options="", raise_on_exception=True): + ksr_command = [ + os.environ.get("KSR"), + "-l", + "ns1/named.conf", + "-k", + policy, + *options.split(), + action, + zone, + ] + + out = isctest.run.cmd( + ksr_command, log_stdout=True, raise_on_exception=raise_on_exception + ) + return out.stdout.decode("utf-8"), out.stderr.decode("utf-8") + + +def check_keys( + keys, + lifetime, + alg=os.environ["DEFAULT_ALGORITHM_NUMBER"], + size=os.environ["DEFAULT_BITS"], + offset=0, + with_state=False, +): + # Check keys that were created. + num = 0 + + now = KeyTimingMetadata.now() + + for key in keys: + # created: from keyfile plus offset + created = key.get_timing("Created") + offset + + # active: retired previous key + active = created + if num > 0 and retired is not None: + active = retired + + # published: dnskey-ttl + publish-safety + propagation + published = active - timedelta(hours=2, minutes=5) + + # retired: zsk-lifetime + if lifetime is not None: + retired = active + lifetime + + if key.is_ksk(): + # removed: ttlds + retire-safety + parent-propagation + removed = retired + timedelta(days=1, hours=2) + else: + # removed: ttlsig + retire-safety + sign-delay + propagation + removed = retired + timedelta(days=10, hours=1, minutes=5) + else: + retired = None + removed = None + + goal = "hidden" + state_dnskey = "hidden" + state_zrrsig = "hidden" + state_krrsig = "hidden" + state_ds = "hidden" + if retired is None or between(now, published, retired): + goal = "omnipresent" + pubdelay = published + timedelta(hours=2, minutes=5) + signdelay = active + timedelta(days=10, hours=1, minutes=5) + + if between(now, published, pubdelay): + state_dnskey = "rumoured" + state_krrsig = "rumoured" + else: + state_dnskey = "omnipresent" + state_krrsig = "omnipresent" + + if key.is_ksk(): + state_ds = "hidden" + else: + if between(now, active, signdelay): + state_zrrsig = "rumoured" + else: + state_zrrsig = "omnipresent" + + with open(key.statefile, "r", encoding="utf-8") as file: + metadata = file.read() + assert f"Algorithm: {alg}" in metadata + assert f"Length: {size}" in metadata + + if key.is_ksk(): + assert "KSK: yes" in metadata + else: + assert "KSK: no" in metadata + + if key.is_zsk(): + assert "ZSK: yes" in metadata + else: + assert "ZSK: no" in metadata + + assert f"Published: {published}" in metadata + assert f"Active: {active}" in metadata + + if lifetime is not None: + assert f"Retired: {retired}" in metadata + assert f"Removed: {removed}" in metadata + assert f"Lifetime: {int(lifetime.total_seconds())}" in metadata + else: + assert "Lifetime: 0" in metadata + assert "Retired:" not in metadata + assert "Removed:" not in metadata + + if with_state: + assert f"GoalState: {goal}" in metadata + assert f"DNSKEYState: {state_dnskey}" in metadata + + if key.is_ksk(): + assert f"KRRSIGState: {state_krrsig}" in metadata + assert f"DSState: {state_ds}" in metadata + else: + assert "KRRSIGState:" not in metadata + assert "DSState:" not in metadata + + if key.is_zsk(): + assert f"ZRRSIGState: {state_zrrsig}" in metadata + else: + assert "ZRRSIGState:" not in metadata + + num += 1 + + +def check_key_bundle(bundle_keys, bundle_lines, cdnskey=False): + count = 0 + for key in bundle_keys: + found = False + for line in bundle_lines: + if key.dnskey_equals(line, cdnskey): + found = True + count += 1 + assert found + + assert count == len(bundle_keys) + assert count == len(bundle_lines) + + +def check_cds_bundle(bundle_keys, bundle_lines, expected_cds): + count = 0 + for key in bundle_keys: + found = False + # the cds of this ksk must be in the ksr + for line in bundle_lines: + for alg in expected_cds: + if key.cds_equals(line, alg.strip()): + found = True + count += 1 + assert found + + assert count == len(expected_cds) * len(bundle_keys) + assert count == len(bundle_lines) + + +def check_rrsig_bundle(bundle_keys, bundle_lines, zone, rrtype, sigend, sigstart): + count = 0 + for key in bundle_keys: + found = False + alg = key.get_metadata("Algorithm") + expect = f"{zone}. 3600 IN RRSIG {rrtype} {alg} 2 3600 {sigend} {sigstart} {key.tag} {zone}." + # there must be a signature of this ksk + for line in bundle_lines: + rrsig = " ".join(line.split()) + if expect in rrsig: + found = True + count += 1 + assert found + + assert count == len(bundle_keys) + assert count == len(bundle_lines) + + +def check_keysigningrequest(out, zsks, start, end): + lines = out.split("\n") + line_no = 0 + + inception = start + while inception < end: + next_bundle = end + 1 + # expect bundle header + assert f";; KeySigningRequest 1.0 {inception}" in lines[line_no] + line_no += 1 + bundle_keys = [] + bundle_lines = [] + # expect zsks + for key in zsks: + published = key.get_timing("Publish") + if between(published, inception, next_bundle): + next_bundle = published + + removed = key.get_timing("Delete", must_exist=False) + if between(removed, inception, next_bundle): + next_bundle = removed + + if published > inception: + continue + if removed is not None and inception >= removed: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_key_bundle(bundle_keys, bundle_lines) + + inception = next_bundle + + # ksr footer + assert ";; KeySigningRequest 1.0 generated at" in lines[line_no] + line_no += 1 + + # trailing empty lines + while line_no < len(lines): + assert lines[line_no] == "" + line_no += 1 + + assert line_no == len(lines) + + +def check_signedkeyresponse( + out, + zone, + ksks, + zsks, + start, + end, + refresh, + cdnskey=True, + cds="SHA-256", +): + lines = out.split("\n") + line_no = 0 + next_bundle = end + 1 + + inception = start + while inception < end: + # A single signed key response may consist of: + # ;; SignedKeyResponse (header) + # ;; DNSKEY 257 (one per published key in ksks) + # ;; DNSKEY 256 (one per published key in zsks) + # ;; RRSIG(DNSKEY) (one per active key in ksks) + # ;; CDNSKEY (one per published key in ksks) + # ;; RRSIG(CDNSKEY) (one per active key in ksks) + # ;; CDS (one per published key in ksks) + # ;; RRSIG(CDS) (one per active key in ksks) + + sigstart = inception - timedelta(hours=1) # clockskew + sigend = inception + timedelta(days=14) # sig-validity + next_bundle = sigend + refresh + + # ignore empty lines + while line_no < len(lines): + if lines[line_no] == "": + line_no += 1 + else: + break + + # expect bundle header + assert f";; SignedKeyResponse 1.0 {inception}" in lines[line_no] + line_no += 1 + + # expect ksks + bundle_keys = [] + bundle_lines = [] + for key in ksks: + published = key.get_timing("Publish") + if between(published, inception, next_bundle): + next_bundle = published + + removed = key.get_timing("Delete", must_exist=False) + + if published > inception: + continue + if removed is not None and inception >= removed: + continue + + if between(removed, inception, next_bundle): + next_bundle = removed + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_key_bundle(bundle_keys, bundle_lines) + + # expect zsks + bundle_keys = [] + bundle_lines = [] + for key in zsks: + published = key.get_timing("Publish") + if between(published, inception, next_bundle): + next_bundle = published + + removed = key.get_timing("Delete", must_exist=False) + if between(removed, inception, next_bundle): + next_bundle = removed + + if published > inception: + continue + if removed is not None and inception >= removed: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_key_bundle(bundle_keys, bundle_lines) + + # expect rrsig(dnskey) + bundle_keys = [] + bundle_lines = [] + for key in ksks: + active = key.get_timing("Activate") + inactive = key.get_timing("Inactive", must_exist=False) + if active > inception: + continue + if inactive is not None and inception >= inactive: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_rrsig_bundle(bundle_keys, bundle_lines, zone, "DNSKEY", sigend, sigstart) + + # expect cdnskey + have_cdnskey = False + if cdnskey: + bundle_keys = [] + bundle_lines = [] + for key in ksks: + published = key.get_timing("SyncPublish") + if between(published, inception, next_bundle): + next_bundle = published + + removed = key.get_timing("SyncDelete", must_exist=False) + if between(removed, inception, next_bundle): + next_bundle = removed + + if published > inception: + continue + if removed is not None and inception >= removed: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + have_cdnskey = True + + check_key_bundle(bundle_keys, bundle_lines, cdnskey=True) + + if have_cdnskey: + # expect rrsig(cdnskey) + bundle_keys = [] + bundle_lines = [] + for key in ksks: + active = key.get_timing("Activate") + inactive = key.get_timing("Inactive", must_exist=False) + if active > inception: + continue + if inactive is not None and inception >= inactive: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_rrsig_bundle( + bundle_keys, bundle_lines, zone, "CDNSKEY", sigend, sigstart + ) + + # expect cds + have_cds = False + if cds != "": + bundle_keys = [] + bundle_lines = [] + expected_cds = cds.split(",") + for key in ksks: + published = key.get_timing("SyncPublish") + if between(published, inception, next_bundle): + next_bundle = published + + removed = key.get_timing("SyncDelete", must_exist=False) + if between(removed, inception, next_bundle): + next_bundle = removed + + if published > inception: + continue + if removed is not None and inception >= removed: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + # pylint: disable=unused-variable + for _arg in expected_cds: + bundle_lines.append(lines[line_no]) + line_no += 1 + have_cds = True + + check_cds_bundle(bundle_keys, bundle_lines, expected_cds) + + if have_cds: + # expect rrsig(cds) + bundle_keys = [] + bundle_lines = [] + for key in ksks: + active = key.get_timing("Activate") + inactive = key.get_timing("Inactive", must_exist=False) + if active > inception: + continue + if inactive is not None and inception >= inactive: + continue + + # collect keys that should be in this bundle + # collect lines that should be in this bundle + bundle_keys.append(key) + bundle_lines.append(lines[line_no]) + line_no += 1 + + check_rrsig_bundle(bundle_keys, bundle_lines, zone, "CDS", sigend, sigstart) + + inception = next_bundle + + # skr footer + assert ";; SignedKeyResponse 1.0 generated at" in lines[line_no] + line_no += 1 + + # trailing empty lines + while line_no < len(lines): + assert lines[line_no] == "" + line_no += 1 + + assert line_no == len(lines) + + +def test_ksr_errors(): + # check that 'dnssec-ksr' errors on unknown action + _, err = ksr("common.test", "common", "foobar", raise_on_exception=False) + assert "dnssec-ksr: fatal: unknown command 'foobar'" in err + + # check that 'dnssec-ksr keygen' errors on missing end date + _, err = ksr("common.test", "common", "keygen", raise_on_exception=False) + assert "dnssec-ksr: fatal: keygen requires an end date" in err + + # check that 'dnssec-ksr keygen' errors on zone with csk + _, err = ksr( + "csk.test", "csk", "keygen", options="-K ns1 -e +2y", raise_on_exception=False + ) + assert "dnssec-ksr: fatal: no keys created for policy 'csk'" in err + + # check that 'dnssec-ksr request' errors on missing end date + _, err = ksr("common.test", "common", "request", raise_on_exception=False) + assert "dnssec-ksr: fatal: request requires an end date" in err + + # check that 'dnssec-ksr sign' errors on missing ksr file + _, err = ksr( + "common.test", + "common", + "sign", + options="-K ns1/offline -i now -e +1y", + raise_on_exception=False, + ) + assert "dnssec-ksr: fatal: 'sign' requires a KSR file" in err + + +def test_ksr_common(servers): + # common test cases (1) + zone = "common.test" + policy = "common" + n = 1 + + # create ksk + kskdir = "ns1/offline" + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 1 + + check_keys(ksks, None) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + out, _ = ksr(zone, policy, "keygen", options="-i now -e +1y") + zsks = isctest.kasp.keystr_to_keylist(out) + assert len(zsks) == 2 + + lifetime = timedelta(days=31 * 6) + check_keys(zsks, lifetime) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + # in the given key directory + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 2 + + lifetime = timedelta(days=31 * 6) + check_keys(zsks, lifetime) + + for key in zsks: + privatefile = f"{key.path}.private" + keyfile = f"{key.path}.key" + statefile = f"{key.path}.state" + shutil.copyfile(privatefile, f"{privatefile}.backup") + shutil.copyfile(keyfile, f"{keyfile}.backup") + shutil.copyfile(statefile, f"{statefile}.backup") + + # check that 'dnssec-ksr request' creates correct ksr + now = zsks[0].get_timing("Created") + until = now + timedelta(days=365) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {now} -e +1y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, now, until) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +1y" + ) + + fname = f"{zone}.skr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse(out, zone, ksks, zsks, now, until, refresh) + + # common test cases (2) + n = 2 + + # check that 'dnssec-ksr keygen' selects pregenerated keys for + # the same time bundle + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +1y") + selected_zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(selected_zsks) == 2 + for index, key in enumerate(selected_zsks): + assert zsks[index] == key + isctest.check.file_contents_equal( + f"{key.path}.private", f"{key.path}.private.backup" + ) + isctest.check.file_contents_equal(f"{key.path}.key", f"{key.path}.key.backup") + isctest.check.file_contents_equal( + f"{key.path}.state", f"{key.path}.state.backup" + ) + + # check that 'dnssec-ksr keygen' generates only necessary keys for + # overlapping time bundle + out, err = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +2y -v 1") + overlapping_zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(overlapping_zsks) == 4 + + verbose = err.split() + selected = 0 + generated = 0 + for output in verbose: + if "Selecting" in output: + selected += 1 + if "Generating" in output: + generated += 1 + # Subtract if there was a key collision. + if "collide" in output: + generated -= 1 + + assert selected == 2 + assert generated == 2 + for index, key in enumerate(overlapping_zsks): + if index < 2: + assert zsks[index] == key + isctest.check.file_contents_equal( + f"{key.path}.private", f"{key.path}.private.backup" + ) + isctest.check.file_contents_equal( + f"{key.path}.key", f"{key.path}.key.backup" + ) + isctest.check.file_contents_equal( + f"{key.path}.state", f"{key.path}.state.backup" + ) + + # run 'dnssec-ksr keygen' again with verbosity 0 + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {now} -e +2y") + overlapping_zsks2 = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(overlapping_zsks2) == 4 + check_keys(overlapping_zsks2, lifetime) + for index, key in enumerate(overlapping_zsks2): + assert overlapping_zsks[index] == key + + # check that 'dnssec-ksr request' creates correct ksr if the + # interval is shorter + out, _ = ksr(zone, policy, "request", options=f"-K ns1 -i {now} -e +1y") + + fname = f"{zone}.ksr.{n}.shorter" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, now, until) + + # check that 'dnssec-ksr request' creates correct ksr with new interval + out, _ = ksr(zone, policy, "request", options=f"-K ns1 -i {now} -e +2y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + until = now + timedelta(days=365 * 2) + check_keysigningrequest(out, overlapping_zsks, now, until) + + # check that 'dnssec-ksr request' errors if there are not enough keys + _, err = ksr( + zone, + policy, + "request", + options=f"-K ns1 -i {now} -e +3y", + raise_on_exception=False, + ) + error = f"no {zone}/ECDSAP256SHA256 zsk key pair found for bundle" + assert f"dnssec-ksr: fatal: {error}" in err + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K ns1/offline -f {fname} -i {now} -e +2y" + ) + + fname = f"{zone}.skr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse( + out, + zone, + ksks, + overlapping_zsks, + now, + until, + refresh, + ) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(fname, f"ns1/{fname}") + ns1.rndc(f"skr -import {fname} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, overlapping_zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + check_keys(overlapping_zsks, lifetime, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, overlapping_zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, overlapping_zsks, offline_ksk=True) + + +def test_ksr_lastbundle(servers): + zone = "last-bundle.test" + policy = "common" + n = 1 + + # create ksk + kskdir = "ns1/offline" + offset = -timedelta(days=365) + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1d -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 1 + + check_keys(ksks, None, offset=offset) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1d") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 2 + + lifetime = timedelta(days=31 * 6) + check_keys(zsks, lifetime, offset=offset) + + # check that 'dnssec-ksr request' creates correct ksr + then = zsks[0].get_timing("Created") + offset + until = then + timedelta(days=366) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {then} -e +1d") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, then, until) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {then} -e +1d" + ) + + fname = f"{zone}.skr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse(out, zone, ksks, zsks, then, until, refresh) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(fname, f"ns1/{fname}") + ns1.rndc(f"skr -import {fname} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + check_keys(zsks, lifetime, offset=offset, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) + + # check that last bundle warning is logged + warning = "last bundle in skr, please import new skr file" + assert f"zone {zone}/IN (signed): zone_rekey: {warning}" in ns1.log + + +def test_ksr_inthemiddle(servers): + zone = "in-the-middle.test" + policy = "common" + n = 1 + + # create ksk + kskdir = "ns1/offline" + offset = -timedelta(days=365) + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i -1y -e +1y -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 1 + + check_keys(ksks, None, offset=offset) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i -1y -e +1y") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 4 + + lifetime = timedelta(days=31 * 6) + check_keys(zsks, lifetime, offset=offset) + + # check that 'dnssec-ksr request' creates correct ksr + then = zsks[0].get_timing("Created") + then = then + offset + until = then + timedelta(days=365 * 2) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {then} -e +1y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, then, until) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {then} -e +1y" + ) + + fname = f"{zone}.skr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse(out, zone, ksks, zsks, then, until, refresh) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(fname, f"ns1/{fname}") + ns1.rndc(f"skr -import {fname} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + check_keys(zsks, lifetime, offset=offset, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) + + # check that no last bundle warning is logged + warning = "last bundle in skr, please import new skr file" + assert f"zone {zone}/IN (signed): zone_rekey: {warning}" not in ns1.log + + +def check_ksr_rekey_logs_error(server, zone, policy, offset, end): + n = 1 + + # create ksk + kskdir = "ns1/offline" + now = KeyTimingMetadata.now() + then = now + offset + until = now + end + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i {then} -e {until} -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 1 + + # key generation + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i {then} -e {until}") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 2 + + # create request + now = zsks[0].get_timing("Created") + then = now + offset + until = now + end + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {then} -e {until}") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + # sign request + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {then} -e {until}" + ) + + fname = f"{zone}.skr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + # add zone + server.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(fname, f"ns1/{fname}") + server.rndc(f"skr -import {fname} {zone}", log=False) + + # test that rekey logs error + time_remaining = 10 + warning = "no available SKR bundle" + line = f"zone {zone}/IN (signed): zone_rekey failure: {warning}" + while time_remaining > 0: + if line not in server.log: + time_remaining -= 1 + time.sleep(1) + else: + break + assert line in server.log + + +def test_ksr_rekey_logs_error(servers): + # check that an SKR that is too old logs error + check_ksr_rekey_logs_error( + servers["ns1"], "past.test", "common", -63072000, -31536000 + ) + # check that an SKR that is too new logs error + check_ksr_rekey_logs_error( + servers["ns1"], "future.test", "common", 2592000, 31536000 + ) + + +def test_ksr_unlimited(servers): + zone = "unlimited.test" + policy = "unlimited" + n = 1 + + # create ksk + kskdir = "ns1/offline" + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +2y -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 1 + + check_keys(ksks, None) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +2y") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 1 + + lifetime = None + check_keys(zsks, lifetime) + + # check that 'dnssec-ksr request' creates correct ksr + now = zsks[0].get_timing("Created") + until = now + timedelta(days=365 * 4) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {now} -e +4y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, now, until) + + # check that 'dnssec-ksr sign' creates correct skr without cdnskey + out, _ = ksr( + zone, "no-cdnskey", "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +4y" + ) + + skrfile = f"{zone}.no-cdnskey.skr.{n}" + with open(skrfile, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse( + out, + zone, + ksks, + zsks, + now, + until, + refresh, + cdnskey=False, + cds="SHA-1, SHA-256, SHA-384", + ) + + # check that 'dnssec-ksr sign' creates correct skr without cds + out, _ = ksr( + zone, "no-cds", "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +4y" + ) + + skrfile = f"{zone}.no-cds.skr.{n}" + with open(skrfile, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse( + out, + zone, + ksks, + zsks, + now, + until, + refresh, + cds="", + ) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +4y" + ) + + skrfile = f"{zone}.{policy}.skr.{n}" + with open(skrfile, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse(out, zone, ksks, zsks, now, until, refresh) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(skrfile, f"ns1/{skrfile}") + ns1.rndc(f"skr -import {skrfile} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + check_keys(zsks, lifetime, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) + + +def test_ksr_twotone(servers): + zone = "two-tone.test" + policy = "two-tone" + n = 1 + + # create ksk + kskdir = "ns1/offline" + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 2 + + ksks_defalg = [] + ksks_altalg = [] + for ksk in ksks: + alg = ksk.get_metadata("Algorithm") + if alg == os.environ.get("DEFAULT_ALGORITHM_NUMBER"): + ksks_defalg.append(ksk) + elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER"): + ksks_altalg.append(ksk) + + assert len(ksks_defalg) == 1 + assert len(ksks_altalg) == 1 + + check_keys(ksks_defalg, None) + + alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER") + size = os.environ.get("ALTERNATIVE_BITS") + check_keys(ksks_altalg, None, alg, size) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + # First algorithm keys have a lifetime of 3 months, so there should + # be 4 created keys. Second algorithm keys have a lifetime of 5 + # months, so there should be 3 created keys. While only two time + # bundles of 5 months fit into one year, we need to create an extra + # key for the remainder of the bundle. So 7 in total. + assert len(zsks) == 7 + + zsks_defalg = [] + zsks_altalg = [] + for zsk in zsks: + alg = zsk.get_metadata("Algorithm") + if alg == os.environ.get("DEFAULT_ALGORITHM_NUMBER"): + zsks_defalg.append(zsk) + elif alg == os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER"): + zsks_altalg.append(zsk) + + assert len(zsks_defalg) == 4 + assert len(zsks_altalg) == 3 + + lifetime = timedelta(days=31 * 3) + check_keys(zsks_defalg, lifetime) + + alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER") + size = os.environ.get("ALTERNATIVE_BITS") + lifetime = timedelta(days=31 * 5) + check_keys(zsks_altalg, lifetime, alg, size) + + # check that 'dnssec-ksr request' creates correct ksr + now = zsks[0].get_timing("Created") + until = now + timedelta(days=365) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {now} -e +1y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, now, until) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +1y" + ) + + skrfile = f"{zone}.skr.{n}" + with open(skrfile, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -timedelta(days=5) + check_signedkeyresponse(out, zone, ksks, zsks, now, until, refresh) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(skrfile, f"ns1/{skrfile}") + ns1.rndc(f"skr -import {skrfile} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + lifetime = timedelta(days=31 * 3) + check_keys(zsks_defalg, lifetime, with_state=True) + + alg = os.environ.get("ALTERNATIVE_ALGORITHM_NUMBER") + size = os.environ.get("ALTERNATIVE_BITS") + lifetime = timedelta(days=31 * 5) + check_keys(zsks_altalg, lifetime, alg, size, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) + + +def test_ksr_kskroll(servers): + zone = "ksk-roll.test" + policy = "ksk-roll" + n = 1 + + # create ksk + kskdir = "ns1/offline" + out, _ = ksr(zone, policy, "keygen", options=f"-K {kskdir} -i now -e +1y -o") + ksks = isctest.kasp.keystr_to_keylist(out, kskdir) + assert len(ksks) == 2 + + lifetime = timedelta(days=31 * 6) + check_keys(ksks, lifetime) + + # check that 'dnssec-ksr keygen' pregenerates right amount of keys + zskdir = "ns1" + out, _ = ksr(zone, policy, "keygen", options=f"-K {zskdir} -i now -e +1y") + zsks = isctest.kasp.keystr_to_keylist(out, zskdir) + assert len(zsks) == 1 + + check_keys(zsks, None) + + # check that 'dnssec-ksr request' creates correct ksr + now = zsks[0].get_timing("Created") + until = now + timedelta(days=365) + out, _ = ksr(zone, policy, "request", options=f"-K {zskdir} -i {now} -e +1y") + + fname = f"{zone}.ksr.{n}" + with open(fname, "w", encoding="utf-8") as file: + file.write(out) + + check_keysigningrequest(out, zsks, now, until) + + # check that 'dnssec-ksr sign' creates correct skr + out, _ = ksr( + zone, policy, "sign", options=f"-K {kskdir} -f {fname} -i {now} -e +1y" + ) + + skrfile = f"{zone}.skr.{n}" + with open(skrfile, "w", encoding="utf-8") as file: + file.write(out) + + refresh = -432000 # 5 days + check_signedkeyresponse(out, zone, ksks, zsks, now, until, refresh) + + # add zone + ns1 = servers["ns1"] + ns1.rndc( + f"addzone {zone} " + + "{ type primary; file " + + f'"{zone}.db"; dnssec-policy {policy}; ' + + "};", + log=False, + ) + + # import skr + shutil.copyfile(skrfile, f"ns1/{skrfile}") + ns1.rndc(f"skr -import {skrfile} {zone}", log=False) + + # test zone is correctly signed + # - check rndc dnssec -status output + isctest.kasp.check_dnssecstatus(ns1, zone, zsks, policy=policy) + # - zone is signed + isctest.kasp.check_zone_is_signed(ns1, zone) + # - dnssec_verify + isctest.kasp.check_dnssec_verify(ns1, zone) + # - check keys + check_keys(zsks, None, with_state=True) + # - check apex + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) + # - check subdomain + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) diff --git a/bin/tests/system/legacy/build.sh b/bin/tests/system/legacy/build.sh new file mode 100644 index 0000000..2460fd7 --- /dev/null +++ b/bin/tests/system/legacy/build.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +(cd ns6 && $SHELL -e sign.sh) +(cd ns7 && $SHELL -e sign.sh) diff --git a/bin/tests/system/legacy/ns1/named1.conf.in b/bin/tests/system/legacy/ns1/named1.conf.in new file mode 100644 index 0000000..bada7eb --- /dev/null +++ b/bin/tests/system/legacy/ns1/named1.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/legacy/ns1/named2.conf.in b/bin/tests/system/legacy/ns1/named2.conf.in new file mode 100644 index 0000000..239e58f --- /dev/null +++ b/bin/tests/system/legacy/ns1/named2.conf.in @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/legacy/ns1/root.db b/bin/tests/system/legacy/ns1/root.db new file mode 100644 index 0000000..175847a --- /dev/null +++ b/bin/tests/system/legacy/ns1/root.db @@ -0,0 +1,33 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +. SOA ns1. marka.isc.org 1 0 0 0 0 +. NS ns1. +ns1. A 10.53.0.1 +dropedns. NS ns.dropedns. +ns.dropedns. A 10.53.0.2 +dropedns-notcp. NS ns.dropedns-notcp. +ns.dropedns-notcp. A 10.53.0.3 +plain. NS ns.plain. +ns.plain. A 10.53.0.4 +plain-notcp. NS ns.plain-notcp. +ns.plain-notcp. A 10.53.0.5 +edns512. NS ns.edns512. +ns.edns512. A 10.53.0.6 +edns512-notcp. NS ns.edns512-notcp. +ns.edns512-notcp. A 10.53.0.7 +ednsformerr. NS ns.ednsformerr. +ns.ednsformerr. A 10.53.0.8 +ednsnotimp. NS ns.ednsnotimp. +ns.ednsnotimp. A 10.53.0.9 +ednsrefused. NS ns.ednsrefused. +ns.ednsrefused. A 10.53.0.10 diff --git a/bin/tests/system/legacy/ns1/trusted.conf b/bin/tests/system/legacy/ns1/trusted.conf new file mode 100644 index 0000000..a54b6aa --- /dev/null +++ b/bin/tests/system/legacy/ns1/trusted.conf @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +trust-anchors { + "edns512-notcp." static-ds 8161 10 2 "19147C5BF59BED075AC26CE73DDA875438FB5AC61BCF31F081AD5BDA1AA7C236"; +}; diff --git a/bin/tests/system/legacy/ns10/ednsrefused.db b/bin/tests/system/legacy/ns10/ednsrefused.db new file mode 100644 index 0000000..9aa3a4a --- /dev/null +++ b/bin/tests/system/legacy/ns10/ednsrefused.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.8 diff --git a/bin/tests/system/legacy/ns10/named.conf.in b/bin/tests/system/legacy/ns10/named.conf.in new file mode 100644 index 0000000..628c51a --- /dev/null +++ b/bin/tests/system/legacy/ns10/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.10; + notify-source 10.53.0.10; + transfer-source 10.53.0.10; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.10; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "ednsrefused" { + type primary; + file "ednsrefused.db"; +}; diff --git a/bin/tests/system/legacy/ns10/named.ednsrefused b/bin/tests/system/legacy/ns10/named.ednsrefused new file mode 100644 index 0000000..6b43ac0 --- /dev/null +++ b/bin/tests/system/legacy/ns10/named.ednsrefused @@ -0,0 +1 @@ +ednsrefused diff --git a/bin/tests/system/legacy/ns2/dropedns.db b/bin/tests/system/legacy/ns2/dropedns.db new file mode 100644 index 0000000..06c023c --- /dev/null +++ b/bin/tests/system/legacy/ns2/dropedns.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.2 diff --git a/bin/tests/system/legacy/ns2/named.conf.in b/bin/tests/system/legacy/ns2/named.conf.in new file mode 100644 index 0000000..e570ffe --- /dev/null +++ b/bin/tests/system/legacy/ns2/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "dropedns" { + type primary; + file "dropedns.db"; +}; diff --git a/bin/tests/system/legacy/ns2/named.dropedns b/bin/tests/system/legacy/ns2/named.dropedns new file mode 100644 index 0000000..37dd9cf --- /dev/null +++ b/bin/tests/system/legacy/ns2/named.dropedns @@ -0,0 +1 @@ +dropedns diff --git a/bin/tests/system/legacy/ns3/dropedns-notcp.db b/bin/tests/system/legacy/ns3/dropedns-notcp.db new file mode 100644 index 0000000..0ac44bc --- /dev/null +++ b/bin/tests/system/legacy/ns3/dropedns-notcp.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.3 diff --git a/bin/tests/system/legacy/ns3/named.conf.in b/bin/tests/system/legacy/ns3/named.conf.in new file mode 100644 index 0000000..3d89554 --- /dev/null +++ b/bin/tests/system/legacy/ns3/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "dropedns-notcp" { + type primary; + file "dropedns-notcp.db"; +}; diff --git a/bin/tests/system/legacy/ns3/named.dropedns b/bin/tests/system/legacy/ns3/named.dropedns new file mode 100644 index 0000000..37dd9cf --- /dev/null +++ b/bin/tests/system/legacy/ns3/named.dropedns @@ -0,0 +1 @@ +dropedns diff --git a/bin/tests/system/legacy/ns3/named.notcp b/bin/tests/system/legacy/ns3/named.notcp new file mode 100644 index 0000000..e25c3a8 --- /dev/null +++ b/bin/tests/system/legacy/ns3/named.notcp @@ -0,0 +1 @@ +notcp diff --git a/bin/tests/system/legacy/ns4/named.args b/bin/tests/system/legacy/ns4/named.args new file mode 100644 index 0000000..03dce0f --- /dev/null +++ b/bin/tests/system/legacy/ns4/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D legacy-ns4 -g -T maxcachesize=2097152 -T noedns diff --git a/bin/tests/system/legacy/ns4/named.conf.in b/bin/tests/system/legacy/ns4/named.conf.in new file mode 100644 index 0000000..32bdb05 --- /dev/null +++ b/bin/tests/system/legacy/ns4/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "plain" { + type primary; + file "plain.db"; +}; diff --git a/bin/tests/system/legacy/ns4/plain.db b/bin/tests/system/legacy/ns4/plain.db new file mode 100644 index 0000000..2c20a70 --- /dev/null +++ b/bin/tests/system/legacy/ns4/plain.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.4 diff --git a/bin/tests/system/legacy/ns5/named.args b/bin/tests/system/legacy/ns5/named.args new file mode 100644 index 0000000..e1311c8 --- /dev/null +++ b/bin/tests/system/legacy/ns5/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D legacy-ns5 -g -T maxcachesize=2097152 -T noedns diff --git a/bin/tests/system/legacy/ns5/named.conf.in b/bin/tests/system/legacy/ns5/named.conf.in new file mode 100644 index 0000000..92e754f --- /dev/null +++ b/bin/tests/system/legacy/ns5/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "plain-notcp" { + type primary; + file "plain-notcp.db"; +}; diff --git a/bin/tests/system/legacy/ns5/named.notcp b/bin/tests/system/legacy/ns5/named.notcp new file mode 100644 index 0000000..e25c3a8 --- /dev/null +++ b/bin/tests/system/legacy/ns5/named.notcp @@ -0,0 +1 @@ +notcp diff --git a/bin/tests/system/legacy/ns5/plain-notcp.db b/bin/tests/system/legacy/ns5/plain-notcp.db new file mode 100644 index 0000000..9c1a96b --- /dev/null +++ b/bin/tests/system/legacy/ns5/plain-notcp.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.5 diff --git a/bin/tests/system/legacy/ns6/edns512.db.in b/bin/tests/system/legacy/ns6/edns512.db.in new file mode 100644 index 0000000..485ec8e --- /dev/null +++ b/bin/tests/system/legacy/ns6/edns512.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +@ 60 TXT a txt record +ns 60 A 10.53.0.6 diff --git a/bin/tests/system/legacy/ns6/edns512.db.signed b/bin/tests/system/legacy/ns6/edns512.db.signed new file mode 100644 index 0000000..f193a09 --- /dev/null +++ b/bin/tests/system/legacy/ns6/edns512.db.signed @@ -0,0 +1,226 @@ +; File written on Fri Oct 23 13:08:55 2020 +; dnssec_signzone version 9.17.6 +edns512. 60 IN SOA ns.edns512. marka.isc.org. ( + 1 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + 60 RRSIG SOA 10 1 60 ( + 20501016010855 20201023010855 53333 edns512. + De3f+wPXopHUPSD2z6Ak5oWhk7AOqqCGU/Z7 + iCHR+9SCTaDRyGQarIGoCrlc2hhrkxOsYWB1 + X01E0Zx+iKrzjbK8aJi1JoigvWvi+XogBfWR + g7P2LnRnriJfBtsFdKEQSHFo3dmVX4XCqyJX + xkJZG2+if+HedaYkrW2izH6PRUsXf3sQWdm4 + +k1jy+4m4m6bVM/QeHbX/u6KwEZlNuWy64lL + 2CXtRpjc2W0oX5Fqoz5GWKI6T038IEawLhP3 + g/SnC021ub89U5sWRY3s3c1vNrZBjtdnGkOr + V5xqBkVwl9RVJwmrMZ4Sa4JaPbd6eV25d+R+ + +yoCJu3mLwL3q7zBT/Du5N23sTeVeIQmmrj/ + PxaaX8YIsGH8cCDaverEAJsveuzpYuZjy8G8 + ZiZagWrA5DQwwy4t+XrhZkUYjxX51t6l367V + 8stKcY/SGEmuEpOuYlaTV0/EikZyWQFoq/iv + 2eyt/CS+vbD9Bz6v/EXI30rNIdSrYlA1/Vnb + hJmb/k13Nlf6ZeybSWLFDYYSXz//FObZ81Zi + 7mUB8nZaMtadOnaf7cmsEDUeDbOd9JkiMsmY + XDnJPN04hOlCpnwVs8gfLPexD+iDwGLc8rkB + hGcAOQRXw22QI7OkBlyaXCHwPpniahmK2wtB + Pb7wmdlIVz2lcbtdNz1e2Jfp2rlxcz7e74w= ) + 60 NS ns.edns512. + 60 RRSIG NS 10 1 60 ( + 20501016010855 20201023010855 53333 edns512. + n0ZPbouoYSPJO35aT4qUr9dwiHDwpf7tyCKn + 18v9b2UXSGloo5ojUkyA7aJf16vuTrcRR3/b + NFHE+qdUsyquHAqjzfPg6O6wL/1CFtZM4Be9 + SPoaMi1/qYJ51ixep07etIFeQamdSTdwFEFb + 2mowRZ5/6TP2GlQZuO56kLTNZSPzUOSh/keN + W/sqMludYPJ4JUSI/tyXaadyu/oTLxHvqmFg + IHGIVsZs4QGyJax75YKL/tQgpMV8A5w56J5V + 2N+8wcLArfwqSduDE0LCU9BfFt4FZf5Hxdqx + Vh30cQkNzvK+k2Em+dV7NyNUtyeQO+szkMdL + Rkwx9bLGaBExDQZZUvXaAmGcrFPGHgYxBEyN + YCpPETeTyvI/Hlt5ldKFLhBuy5h84VNpZ1et + T4YBoc/v+SLK+QygJTESvS86v3eSnKtTpr7Z + z6MaB0jU5rYc1GsVU/W/Hbw8N4EHtsA4PxP+ + CVHBqRCNT3VZuASJuGRYo5g/JFeoA1MFfvIK + gPR7JEAL9TXxgeCWPpyeF0uLabgusPfbcSaH + H90smjebOP5aN5F31oDyJdT0dj4VJybjkIkq + /DKh4gMUTDLe7XSz7E0V56W5TMjnh6qvJCNr + Lrt3M3su6iCTogCXnGqIyqd0udDjryMr6RX8 + QHdOfb8n9CE2cgbgB3lZ2yTo+wTElCK+QQ8= ) + 60 TXT "a" "txt" "record" + 60 RRSIG TXT 10 1 60 ( + 20501016010855 20201023010855 53333 edns512. + MFRZbRqXwWAL5FivjxPsq02Zn6GGO+v0PKAe + 2FCMrCzIFXqxAuiX3aUg3OXdtSgYKTsgS5X+ + GfTPAGrdH3hsdanqJbnD/pSjSIOuyrwTR4p5 + QS6nLReu6HgYqw38gJXzOL596s5N5PPIz0T2 + 6FmbUsVo0x+PNikUQe6rR68Wfs4T/C689aT7 + ws5e/NHvG/EfyxyAENQHLWjuXG0iyU61xmB9 + b8mzdUwT0TupyE75gBDEMLosbBOqSKp8Etjo + hVzjYkXkIRjp1+KceauOIIi8HnpJWkFDbgst + EFhEydCpf2cfCSooE/ddvjKCgsykL7H3iFBl + 6b1mgQ91mouK+qrJTtF9Vjbtz49Q8x/aPyw5 + YL37y7pXTcELJjE4QDk26OShxnUZYxV7rnp+ + u7AHaGjPpRHG+Tv+/Ovp7LP33ZFK05jCr2jl + KMfi6lPpivY7wF8Eyg+gNlf4Je+7jARYQ6/n + Gk4dD0IHg1Q9f9f9Zuus6EqBY+Hw4tMDrhvq + MFNdgNArN6MgQKpTqcl3RPsW5UmDQh4cyqZm + OsxxCSzwKggTsDSAHCemJp2HhiagRMEE5Jk3 + 8kiBA9CUSgMHu2hh3MeC/+mUWXO7rBl6f+4v + IwlJ5Lc5W+F7acJqpbhVRIW7SsTxC3unJXEu + ZJoIy8/VRRK5sW3y3lPh+kY3M+ibAaweGIc= ) + 0 NSEC ns.edns512. NS SOA TXT RRSIG NSEC DNSKEY + 0 RRSIG NSEC 10 1 0 ( + 20501016010855 20201023010855 53333 edns512. + uUXcf0YI0zxGIGCSoRCC5sY6PqaeiZMkMyEw + RaOmshO0ylGgjSdXDq8aYyfX0Yqk3cNlNws+ + pxc93SHjS5y5AouUJyAmp/DcuWTbb6HI5rUu + Vl5MBU4SaQc2mfNDbJVvkPFSG8L5KddL8AOo + 1C/n4xxtQXmBvxD26lm3Is4V8F0ka5s6Gsx6 + wa+wk/x4tIUXjPs31i9Rm6INMJrjTr0KEpEE + N4NDsiCd8udcQhSDXYSfJ6mL2T4oLBkI2rTb + 63YimpBl0tThlO852iXmGz42LiO4e/7OHEfi + qVbeLo66PAOW50dqxBchTydaUl1ODDbkaT06 + YXrIyO5epPOZcHnKnU+WtXzVGhx1WFYamK+d + YeFxIFT9FH3Ka0CutimVjziMoYzPZZTSBCER + e2Lat4VY3tlKIREo21k83q86KuuEmJsnn3mO + E4h29sJAbqPlJ81/iOPBM6mZOJKQRUYkd3xo + 9VdYMmLc0BPRH8YxbpqQ/2bZwE676/Z5TlzY + Zs4RgG7nxddzwrroD52MfKDvb7TelF0q1hwU + ay481qZkCRFEziRt0veUMTlp8u8tRJbSTOwn + KsgF2hadtzGwNPMcsx03cO6rkGlZXlJPvj2a + A8720jM+1xIKUH1ClDnIM3DLjwBAquJpstO0 + 6GccRya3pRDf/H+1kBodXMylIw7QF/1L91Q= ) + 60 DNSKEY 256 3 10 ( + AwEAAb6wC1T1oWvZUHHTf5er1NKQRzGyu/Rb + r2HgRcnOwqUh4Bv8jCN8zXCKRZ0t2uFFvRrX + HE/NvhxJnZNtwGyfJNNVCQ4jkbPoD/lPYCCc + 8LWeZ9ZLgN7XZpUk3F1EnGkHQCM7WoXe03UA + OCHo6hriB96pgFJV+tCSCIubB99Fyk+dN1gG + dfjbRRYSYi7fgQEEVicmbP1u8Bd/6HZQXE7o + aFdGs1gAkvNNVY+AkFQVdhv5gbDew1vFg9lY + C3wWWdRdJtOpHMYY4Q9LBPSKJe4/C/Qr9JJg + jl/OgfeMPPPw2O50W7j5DVqPAPJaeflJbpCp + EjBhIJAgp2nekWlN2WGqFuQLMfsm8HWftafY + WdGXQpGB+gG4yJTRC6aoAGLQ7Ah2xzwodRYx + 6Hu3VMBOjmbiNeubFmZHtOjND6VAexbuGf4Y + CiRfGbxY2+nQtDU3DPF1s0k6TcIw3HuukFuv + yaK9zjx//YD/+AprMHhvrsXjZwLUYwERe6Ax + CTKtbhPFoYb/Sx9spjMG/yWTJw/cLCen0K3t + JHoDKzmRuCldnCk5ff9ZVoOUvZrOfBicuVW4 + vy1eYdfugDf8Y0Gix00DpA6h0xEVh/pCd7VC + 2N5mi0m9ZX5gaH3Rz8AZy9c3iFG+36kUu7By + kSCAwVUEryxS1uuR4a3a3FTPgIYZAOAEif6Y + 0eFD + ) ; ZSK; alg = RSASHA512 ; key id = 53333 + 60 DNSKEY 257 3 10 ( + AwEAAZVmIZdDKaEpBYzRNZ8sCXLdPBkWvH1l + hRMwYtqQuwvKahA1+m0xHWczNV1m04e2MrI9 + AR2yYFCKi+znm9MS3WPo6fShbKzbzCu04G16 + 334WcmxiFfiKWd71NJoM/Oe7pcWJPiGlm0+z + SE93DD1681/GCJxolquJizZH3N9c9erK4Fzv + v8jSbEiVen89bkdUw8ulAmX/Eeb9x39A7fs+ + acO4BuTrL4vsKZ96D9+qbDnUkDn967jFeKGw + RCDUMa+UGABkkNjmic8WTVITwI84xEcaFEl5 + GQBYLJ/qfou1tPicCQxup/EllF4xgFsTvtgG + BjN+uJXaE6rs171pzIbDcwZVuq0JZfWXCnrp + JZUQbtpwr1nFwT4prg4riDCzmiA3gnXCOLFR + pvqx7iOhS77+7miNqBEBthfu6kEdChOlNWpO + TX1Df77HbLyGHPWpExcg11j1jxH1PUB/ijpL + gUFRORuE6Y8NxUvN8ooQWHIYjd8AEIGlAssy + 9dv91KlyOSfZfZftGelCvm5Hha4PoMXUF1of + 4rqVy346UhVRKIu29ML+Os4+HPTPhXY1/wco + 2q3fvKqix8sI997SOrjYeX39MJ2WImzWZVoc + U2X0sbZlYU0I6yq2zDh4oN98s2r1U4TJPf4G + Kc2A3107n5WHsavLF6DfV9bDU4/ozVE920/5 + KocD + ) ; KSK; alg = RSASHA512 ; key id = 21624 + 60 RRSIG DNSKEY 10 1 60 ( + 20501016010855 20201023010855 53333 edns512. + VFBtgMd79vb3EKirSuX5adFdCVMCQQrQ6ANM + iAMhKSxo9Ic8ICZGANm7jvpg+IEG13+2ehyt + 3EpBIHQYp+Apa1j6lGUDbdmcqP0E34eVy8jJ + brP94Bpo0hP1E0P6pPuIqWrnWYG60bXNztc1 + nJ0ACg7mbcbbnFKHwOcD+js74jGAQdCKpwo3 + SCfjApUMQwLhHVa0MKcxKCtbCz0WJJwGoXOV + U4l0DY/wD/aXTXjguiycjrHEP1dT23JPICFl + ZsaVE/+ra999p8fCZ5Vqy3PRFGqUirrwj8hG + 93dK4R5GxY0OLfIxYVX5Nt1w6qDmpXbVtryU + wgzdO3ZO6+Fz7hltPB19bfCQZQIkqypaPkXT + ltk23Jax9EU1nQ1CXLPgMDd3jjlF/46R/CD0 + H/69/ftwCUdmfX2TZmIWEca4sdj5Za1U1AY4 + pby4uPUncEw4T4WtRxKmrXjd9H2Ml8KRCIPe + Iz/21cUoxdLzlomjnP967H/TR6UFxayQziv/ + LL2R7LIQwQlz9ZCHHhedptCaK+0FUicWHqW4 + SW7Y/AKavvFGkMO3KXkXto2oZQLRL4m1Auv7 + M8rlStuEFBJ5/K0JIp4NCDKTayhXwwvf9jtn + WrsCaLRBJH2nCIO2/1w16G3D5mQdvt0QskM2 + FRtEhi3a7TpwRvCGKw9PuVilH7qXIYpHF54= ) + 60 RRSIG DNSKEY 10 1 60 ( + 20501016010855 20201023010855 21624 edns512. + Nv7YHuTniNFoFtEeF53VG5ERUEBzKY6wTzUe + 34+5hD/GwdxqKq0qQ8VflACrP/JYonCejgj7 + 6K4EWLBnZYk1K53NTetO19CCP9X7uQC5+av9 + D5TMLZUC+nQKzHqvJvR6E9UsaH8/wTfOPf1y + Li0CzNUpIQ1dKiDu4nJV15Vb8maxjsSxSMwB + 8bq6d7sNaa97KIqhhlQp1uJBtS26yp+vP7oJ + dYYuJJDeim3GyS/5SN1uMi0r+k9ZL5ajCcyh + IACupyTdGLmQKVR1QwF+UlLhY66TGuLKvvJB + ygg8W5nguqz8mu9uEmwnVta82itKTKWeXwDm + TvEsmW3otxkllRTnHUGDD5mYQBojblFvd27K + qf5ALNjAsDwqgrp3EkX7wSOjUNa14ndPLvlO + oaeI+ak914WeWrX4s3Pq14BOgeY2dkPX7+MN + J3cVkZF3UHsUzzI8vDu68Lnrr36Io5LLlbx6 + ZzVceeOGvFDz3F949LjYdfBPmIRaC1sKlhEf + VrHILfDQFKd3XUK9aRehj3coARu7Aovve1qO + nBTQKwxBFamDaNLlJOaTSaXF8qolIaaEx5Nf + ymlTsUEkhkB2R1E4LOg1GYziysJSuTYNK5vJ + k4kNVn4H/I+sFcxphy2bpZeVHeyNW7JEzQLy + JibBoojBRlVtYCmxqYMtGggHsG+C/YYF0QA= ) +ns.edns512. 60 IN A 10.53.0.6 + 60 RRSIG A 10 2 60 ( + 20501016010855 20201023010855 53333 edns512. + XL9RRX33pcjPE9x6705G/ztksGQbJ/y7tT+k + Ojr/hVxfm16IppAjqUnQawbpHTak9NQssa8w + 0+edKW5DDMnU6Cnk7rnD2JRNNoXCsQ+HI1oe + I7DAgxPvloELwqKnRFmViTCued13oTbzYYOF + w28oRXC+elYoeK5ee953hm298WJjOwaVFzub + YUf5Tf3DlVLtDeylnokPGTOHMo55IS1h+xni + 0V8+jPLXARA9L4fI590J83XPyDPwNgjt0Imv + ySZJ2WopQf16RLPJAHbqz+xQK/kO61TBzk6x + bqe2o5izwKmg46/5ekOvntjXebvxaC9PnSKw + e0fPlXBs5gwbSRFitRHxFzVS2m9eWLMtcYXP + XW7cVKLiBmlci0gzWkhOlGUSCAF5ZaUX/6EK + 4nHsDthtHa2Y4TGkCOeRZNDLGeO4fdfLSS+o + qR70HuhxYp+FqwYxJFtePx7PeJpSwc6FaWTs + Ol41GBSDVFNomOcUawMdstqj2QRWoi4o8Q4m + SwTdyIBd0gekzkyKheVzfFJxUlE524idgNL2 + fCF/y8G/GGwU8DZ2mXLRTbE+7eZV/BG0m9ih + hs/wqqY6o7ClTDWgWJOQ7bbzZBvy3QEmkMZc + TcuWRhVzbS64QlWlFOVD5EpQO5YM3UNKBgVX + ynqTaHEjDZ8P43szTvel8Og2LLdw13qNBYA= ) + 0 NSEC edns512. A RRSIG NSEC + 0 RRSIG NSEC 10 2 0 ( + 20501016010855 20201023010855 53333 edns512. + FuLjgUgFvqjd7KVC5Qli4TueVtHpJlWul+VT + fSWFW8V+730HaPqo2TvZr9pbU7TKFqNWm1mK + cqlxTg9iYviabIZO7cq5tDvX++CiVBaqbjnC + UM7PHl36mj/+WPkQHxSo+TpOC3zd1uSGoF4h + sg8HjMUuQ9dRpsYWPwGM9dwkcgzfHSrCs/zQ + kW4Ari8JgBLAQ7mqRzAEzZPWG90lFgsElvXu + YeSyeP8nSwRvzxjzfgg9YnWOY/zSqUup2HUm + jf4CSFqyOzJm+o0BhVs7qumFl6Z6DRibWece + 0cV7xdLqeBvHZdmBW1uWNio/7YnK1uF2UCBC + bwtzZKrwmCRWaj5HuhJ4DaftFje/7nPz0Kxl + VXWYqTDW+OFO9yJLc3+NPrZdNxuADnrW0MrR + OgJwd1vTpHAwf14ipOitzf4PyBWE5EyL2VIV + QM8oB3+xgZqG2QwAaGe4ZOrrDXQotQ5BmS1d + Y8SebfcylVUWKJK4kJzAvGjLddZ/1pq2bO2w + awj2UarfydJvH+JnX44cykGZeT3x7Y26jEzn + DL5/2NNPVU3jTl/HKdeyMG2INPxWr6z/+PXs + Wn0IjTRpVrKjoTIl2/hUctsldNgZ/kjKhP+U + VrI3O0cBhUM4BPV01mAU8Cq0nhrkRt0ESgo3 + Bulleb0NLQlhBgo0aiZYQLIA8cDLeAi/dIE= ) diff --git a/bin/tests/system/legacy/ns6/named.args b/bin/tests/system/legacy/ns6/named.args new file mode 100644 index 0000000..1791e8b --- /dev/null +++ b/bin/tests/system/legacy/ns6/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D legacy-ns6 -g -T maxcachesize=2097152 -T maxudp512 diff --git a/bin/tests/system/legacy/ns6/named.conf.in b/bin/tests/system/legacy/ns6/named.conf.in new file mode 100644 index 0000000..17f19d9 --- /dev/null +++ b/bin/tests/system/legacy/ns6/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "edns512" { + type primary; + file "edns512.db.signed"; +}; diff --git a/bin/tests/system/legacy/ns6/sign.sh b/bin/tests/system/legacy/ns6/sign.sh new file mode 100755 index 0000000..49a44bb --- /dev/null +++ b/bin/tests/system/legacy/ns6/sign.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +echo_i "sign edns512" + +zone=edns512 +infile=edns512.db.in +zonefile=edns512.db +outfile=edns512.db.signed + +keyname1=$($KEYGEN -a RSASHA512 -b 4096 -n zone $zone 2>/dev/null) +keyname2=$($KEYGEN -f KSK -a RSASHA512 -b 4096 -n zone $zone 2>/dev/null) + +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -g -o $zone -f $outfile -e +30y $zonefile >/dev/null 2>signer.err || cat signer.err diff --git a/bin/tests/system/legacy/ns7/edns512-notcp.db.in b/bin/tests/system/legacy/ns7/edns512-notcp.db.in new file mode 100644 index 0000000..e181ca4 --- /dev/null +++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +@ 60 TXT a txt record +ns 60 A 10.53.0.7 diff --git a/bin/tests/system/legacy/ns7/edns512-notcp.db.signed b/bin/tests/system/legacy/ns7/edns512-notcp.db.signed new file mode 100644 index 0000000..495d098 --- /dev/null +++ b/bin/tests/system/legacy/ns7/edns512-notcp.db.signed @@ -0,0 +1,226 @@ +; File written on Fri Oct 23 13:08:56 2020 +; dnssec_signzone version 9.17.6 +edns512-notcp. 60 IN SOA ns.edns512-notcp. marka.isc.org. ( + 1 ; serial + 0 ; refresh (0 seconds) + 0 ; retry (0 seconds) + 0 ; expire (0 seconds) + 0 ; minimum (0 seconds) + ) + 60 RRSIG SOA 10 1 60 ( + 20501016010856 20201023010856 22916 edns512-notcp. + oLYJAlTUS8D9FSdgdL+wQVNbWZamSxv+vTx1 + 3zAfTgMV/n3RclAtFfFENe+bNxW5vkt4ADEg + j5ys/MFnLA0pgw3fjziIzR2OwEQpuw76A8S/ + ecLVvon5VcEOvKRhUbDJoAS2PatPPqnGxVyE + bs+fBCqeorUl/noU/6TfiISIeVcOmEgZX9I7 + 9LN//CmDpGeZGMm3q6S3LlmsXnBoaMb6g1SN + xH/aA/xstiHXvwRLy1YwtImJa92WIZPaA9tb + zCX9vVXaVtnLxUVz7PyJOAW/+jsg4IfVmpbz + GboD0FdgENC4KuIHjjA93opAOI3iOuREmGEw + 7kBPAgaVB8EzypYxgKoEuargmw+3TymHipZE + e0/0JeXFdRbaiUQWXtKtYfPcmHcnrY5JO1eo + KjNbAakpDkd1wt5EtMc16TO7+00cY4VtUZNJ + IOLtzXByCy2a5FRWzar1InYhicUIvM6VoP5b + tj9QcYLWT3e1E0aXeBia2Qy+hS/Ut4X+vYvp + gedVySBjk8tSDyAkm7ALDiI1gPjdZfCWO+E3 + 8XI4RbCvaGNlZ4rRH17SKyjxJrgiAPN562bg + NAA2F/S5dzLOQn3wwXgHEwu77WisvMV5yrG+ + 3ef8eVEapJgNGzz1YlPTolpYn9EbAtRMxBcK + 6/CFz0Qf6cfBrHS3lxHj78Dcj53O0+zKenY= ) + 60 NS ns.edns512-notcp. + 60 RRSIG NS 10 1 60 ( + 20501016010856 20201023010856 22916 edns512-notcp. + r+WNvwHqzInk8Q/8bDkT4gUbgtc/ArysbpOC + Cw7LGnAREt4W6sZ3okkeXb8fnN/t8bsgE9IU + Hy7/IuhFu9eMzBYYuc4tzELXVswlCRpUvlVA + 0zUJpNmyAcUuCyesy/pu67X0H7mUJX6Z1MKc + /o9F21lGkbXxSPSEgRYp6Kmr0s6oGxUqfPL8 + KDM6yuLBn9YtXzZl5W95aHFGHSlJrCmOeW8P + 8Y+5PAWN3fqA8Djgxy1EOMswFVZqmdM0K9oE + +oDjTKtj87YmrwdPsUlJLUQTJuoGIpAZxSj8 + 4Vgs0sdfdo0w0ZyqljYnlrNUlj214FdbXBec + CCTSgGcacg7GTW/0yWWeP/cvvVh0MkXWVO37 + SUecD9jeMwyjFLfVFpzxkgbHO3AiBG8Y9rTk + ma18D/hAagbTLGlDhnjz0B/2loVCkRmvWyQp + 4Kgpt807cX5w/mR4a/M+//OUTm4xtdq/Ym6f + VXLK+JOX8Z+RsDfMWBNodT+JgefnfvdfMaiK + FA65Sgq2TIhe75v7ttoN0FaPmIv/g1lgKSxA + sLg9syXSUp6Z08wWy3V0jYhs89s4ZJmjezYc + bZKvszSqmoCm3KXAkrRUyYooPpNVaMK8taQ1 + v9vIiC7bFCap8eAogMrfjz1MImIQ/lsH0SC4 + T+OLiqKK0/uXrqO13FW9EKj5NyBeioURx/k= ) + 60 TXT "a" "txt" "record" + 60 RRSIG TXT 10 1 60 ( + 20501016010856 20201023010856 22916 edns512-notcp. + 06INKYbKaphZUY5Nyc/FuiZolDsQBWnkMB0+ + pwW/nUhCfXbZR+6wFuvmZHwDRUVvBGsLgPMs + WvUw313CsRB35vCb0ncGtFxaKdUahbf/9N2w + 600wINuoRSTdxkuGlFbF2Rm0IjuATXkK0QFJ + /eSuATu2PfmMyy2MVtjTWCNIEcCJNXm6HjKj + KokuKB5YJWdR7pI/ofJD0v8L9Y1uM6uOMSEm + MW3jnrqnItg0CzpdAoJNDKCdv0lVz2SYAMIm + fbbYGbfhjGJnHvU+PZmgX4OI0F0QKXT+AAe1 + fJaMBPFU5vvQo+Q/UYcWW+tc9jUiSMTwCOjW + j+cPJypLx7U3Hx3knUscYsikohQv9gqMTQsB + ylqpwJVbofgR62DWqlUUbgoEnILM18SvZ54A + nOcjfz6wLw3/jG/ONsXqLuyYiqetXGhhQLz3 + DxzQrCts1vXWGCnjWdqHeDGZoPWK9RMcsK46 + nGd+jHlOBvCgpgb0KEwKYBIdwnYgoLXqldVM + VEjJ4yJa0Lt9FDFEjdJmI9pcDkE/zAZSfKHF + cf0U/hHy303QpiL9c+2zzEeYpZzDltZfv1/g + oyVFPFxPxp8iNj2W4B1hYTYCgS3M/S75ylgQ + np/QyDv4PX6nIsVPvZUhslm62LfkRnANpqBe + y/VfZDrEHxsd6/4kpqFVhlCgmnCfvwT1PgU= ) + 0 NSEC ns.edns512-notcp. NS SOA TXT RRSIG NSEC DNSKEY + 0 RRSIG NSEC 10 1 0 ( + 20501016010856 20201023010856 22916 edns512-notcp. + ZuI5yl2PzNehPw4HKsR3G/mN2LWtAr+7xWkE + 2pm/Zr8LhnecYz0wbZkve5EDjLe7/93TH7y6 + n7RD4N4W/jtK80J82Xpjy7xOZ3UX4PVoX/0s + IvJFHCPEmlzuzHiVZglMZS9HQl9aY6J5KIde + T4xRnY8YzhvraHi2E2T7HPIGZLZVccWU1dFe + qAxaIhmVYAbLNixd2TbKr6SeWfLQRvn4aM3H + 90k5kSMwePOieyMtvfapmCsOIOxjG2KpibIX + VWnQrXGig5IQ0nOPkamKde5eTYH+cxkx2AHA + gjHutcrbrvwtW4HomW65BNZzyyknX8kC5eo9 + RdAOWTpEXhDDxoU9QxsI6U8zRIwDEuet63N8 + oESfik7AXDST1kJjLeY9QyX8FYKOQoCjxfIA + o06MTKN5OjtRquQUiCHNyOo3ySwaabEHVsbG + a28Laelo8oaPxEFZpVC02N9c2TW6H4gHijzm + WuyrlTV5T2FEQiWLlizVrDDKfNSbbF5DMw1A + AqYIiWUHTa5FAXT+DwBQaN1rd0FJXXMM4Uk+ + a9Mquw9whK5TOe0BSHOsctPz3rAXVmQ/C6Tk + U0tZAmxEsPQDPiM29VdTx2CfTiTqYDsLVCl5 + HUwHMYj9z5uVTZ8pD5zqI3NFH6KrqPlTB/je + ksrzOGaJrtnyj5oGExNWriYVsZx8FoyPNv0= ) + 60 DNSKEY 256 3 10 ( + AwEAAdnQArhgG2vUoiAvs8zH8Z/+RTBxYUnv + /J3Vd9ierGFvvWonU1Ao/WWspZggXe3I6ZmK + +NCSuVlWb1HmemTobib6jdKWpNOMn8OcJHSE + 4TsbOB0+sOknDdU/C8akwegHG2zgQG5dSKRC + oLVqlsnV27lFQrmpVm+cm0IruorTWJRC2W5t + iXnblVQ0ouR54SYG8+k18UqJDVfg1YBfDkzM + eMvz/wJjFy156yPul982VaRHT/xU+Ol5S/+c + yy91W22Q9ktlIjiIu5NLeH6TTwwfGu0YY+h7 + rMFImDkwPeTX+K28BRdjYY2htH8O+ZfbmYE7 + Ft8+qF9P7Df7YUPBiREs350NVuDMeqcJmbsi + yOFBZ+J/QJU7nM5VHCFeUIDZ873/o2bJN0W2 + MaI+v+WsTmHN+W42EmejonGZqlC4ct9j8KO5 + Z73y1+jdzqDOJfIctxRyqK6cF6PBz0Y1QoLI + Z3fmX4IsdIaiFH7h73R4s3uXYTx8BUzY369p + 95jxpMBqMPeFvOaYzeHc4hSqcXIehGwIIUj2 + XQxZU1wf8ijaDXOBM+Ccei147Njd/VOjhJ0F + MG/5EjCkrVLC2IVUO8VMuvpBtji5RNSal6b8 + 0pIZTgEposeT8dbNP8ojzAG15HclFgzjY/Q8 + 90DErfB8UsCtcOz060UKMYKx+zcoYU9KRo2u + 77b9 + ) ; ZSK; alg = RSASHA512 ; key id = 22916 + 60 DNSKEY 257 3 10 ( + AwEAAZ4bc3CnvoIGDpDOW2+afYCU7pSIFNzW + ueXVOjPRolnxUaJYwLyCIHngpm+9/9stMh+E + LBFozA785zPhfqnRaZz1xWMP1D5bHu6SXmpF + V88BOnSznEbam/kqzQTrowH2hs3SClFI2wFD + QsKytzgnRDFEkysgfbjx8rOQZLRV3HN56z39 + DgWWC4kz++0FQtp4rZRr0TKgpIXDYJbBxgWn + em43xdlCv8qErE2jRfE+gto6bS3Uw71qfFTn + XBuvoI2Tfy/cxCa4oeamWYwrfFKbSC0fEykG + 3YnTrYIqJCEnD8h5191h6GZ0OZ0XGWKD14N3 + NjXYSjjorqbqUSU01vDxS/8UvCKknmLCTTpN + Jm3RvpWM9EIghF3qDDgMgFd/hFlJsBGg1MxQ + vGskBg+PdsPDLQZRbpWy+5umLCZ//3Djmok4 + YnvnaFLeMnRlu0x4vTFtpuEdkwTrGUacOkJu + 53vH1pofl3WqC4PrPVwsQXNHTJcZTiHnyAN5 + wM4h6kD47+VKS2888SP49Bi36ypSnZp5bfM9 + wW3zOgh1oFUKTyknQWOX8Saxr+g3sVBZot7V + EpTEeJOWOwdSSRj/K/2UiXI5QJEX4+4aJYxA + ak8OJCmixLmcSVsY4MYsK2m9I0Sl6brGn0xG + qUa0SBTVw+X3zyybLlsqJV8LX9W7sLeM3OgY + st7t + ) ; KSK; alg = RSASHA512 ; key id = 8161 + 60 RRSIG DNSKEY 10 1 60 ( + 20501016010856 20201023010856 22916 edns512-notcp. + klMRNVbs52XfLa1AZNHlAiQWqzjNjNQ7yuVG + 9o8sxcAqzrxvdcnISC9CNz867Sw2JKs9dMZi + Vv07Jm/f85wN/B9OO63NbxQHgtMAv3lT5isN + 4xC7NJtDQCPIEKrgPjnznJG1/XiWZudPemv0 + dpTIMR9fiQHC5Z0I+xqUsRJjlBc4x1tPrPNC + 9r+YEaQlwKT59pWHTLPpBYZE+0jjNY9wMrhX + 1uP7gS8z0s0iyldhIgIicccjdRrCCc6EoNnc + ToEfWsLMN2HTNCtAAxCHSNTPrC2wriKl4CHi + Pqy2AsztfLLkyT+dR/gBLFbjHasp/5O1Y5M+ + 60WywgNr/tbsNzzuSSfcIZ4RM3JhS7cgoZpP + MEsumXOyJdTLF9oIZK3QKVjT07eai/KA+Vjt + bbkVBvagosE+uCCXhpM4nn0oTfZCZiIoUADr + wQ2PuvujEzPbky2BuX7iQGV90G1bcidpS1B8 + Hm7zrpOjO0mwNyF29YTcJkgelvVOmEaAH3X4 + +Enmji13kQmWkkc0sUYq9tyX0gTiXjZtz/4I + Yl/JOng3/CKS7/In20p1Oea4Sa0GDqtlmK+f + YsgaAkCaN1RbZslNDpphgEIKUF8M9YZVaAlE + XNqj5HFeqzOAoGNN/rUKKgNWcRynJdHP13gd + AoUxJa5FxdxZB4AAk6vfojOFjU7kQyeJlh8= ) + 60 RRSIG DNSKEY 10 1 60 ( + 20501016010856 20201023010856 8161 edns512-notcp. + Y27v9t6VkOZzuEdGZIr33RTGJ+L4QfWkoCvj + 9VGdOsj3dWVATqwYoGmlfRqlm6m2L7yhJVTC + pI8ihj/Tl7aoROTBnJGO9CkuvXKeGt16LIpi + ZBz9FbZ6MPwwjn7uPlm4RR51mscTWdu1Y45e + zs/uPxc2qpafl3NnBwcAw9l1VM9f11Ah7+tu + WA58niT+GMwKVSB2B0+cDQoP5covZmU3DjgE + 8CmqwBUF4cElQ4DcGGy6LkWdO2+Yj8ANCsUS + DTeE8j7XLVGGurwgwL0TNPA1yntibvl+U+ti + vznWlvsV7Mww16j83BrJvEeTVOGthINdtL4P + 7Pm6U6NUSMJNK2lGB3VucJyLDuuUN3CNNfsb + IO+6vBrA/T6UtXaRfv5c5Xnq9dcrbiYW1ar3 + Ysw6cpGi2Ti2YO5EfG8OfGmHeZXK+OqrTNEn + T14ELewVKVEWv4lGiVbddDUq7YmltoYog2Zp + DsyahxOgfFLYj32pYIdNRr5HE9c1FwOZXmnz + wPp/rB1baf5eNddRxJtDaEo/ek5v+CtWC6Y+ + eRwBKWN/ozmc5JnNpoJtKSvRlTuGYlKElct0 + 1cS9BmZsu/zAt4kGuNC71758XnVSd1CcwhwA + WYEAvrJV2+wr7jpjHvq1tGrCEPppBaelrwut + CGfenY08YE/dDMmbFPXMFUHbhtz1qvFiMjU= ) +ns.edns512-notcp. 60 IN A 10.53.0.7 + 60 RRSIG A 10 2 60 ( + 20501016010856 20201023010856 22916 edns512-notcp. + tFjfl9DvT60ko1h9p55T2s5hU4CmmHEYrMUg + 9Iv+tvW9YoCiHESBC7TkDmdVT8YwzaLDjlTf + YxgA5KLhV+04M9m7vUgxK5T4vjiE43VnTq7x + L+hM9cvjQ4sKTBJLHmTrKjrcE5fyd0/F3jvF + MiomX/8p7PLq2fzZWwygjiOrkd0s7ypFEuoX + AjRoxo60q2oV9/8jiKkgiD4+UEIqU/fxURP+ + 1MpNVqks/PXSFVQcyGrQKddiRpp53yYlgcDv + /0ulXnxK53dQ3CqymOflJrf7B5H0rq8LQHjK + ZO3ys54sWq80jxtxRWNMBvygmHl+LFCes5mL + GuB1pFYJq7z026GC6QHbVmOQu5P2pLOr13jW + KBwRisr0/BN/no3goGVAP7hJD47r2fr0E8WL + K1GJZI2McrHgQW12NnZm43AI2z7xjapbRquB + HMeJR8bPfjxEhy555AE0B1AXZobiuZHtycox + XBS+A9URAYx78OWAgAENF94rnkKIoSAmMENJ + KX29TEHrNLG3MCWxX9mRnMzON+5oTZjOxV8R + KIc6Qw/hE93Bho1+3Vdlq8X2Gwu8RswwLBgH + e3AnKRHWGTbv6uUwKCVrTyZOQft+yiKxooBr + Wz0AgEosnuwenxjw4Tim/Z5NhLnzrJBaSyjo + Pt+wguhDW1boaCf/4RYOAZtSNNalGnJNV4k= ) + 0 NSEC edns512-notcp. A RRSIG NSEC + 0 RRSIG NSEC 10 2 0 ( + 20501016010856 20201023010856 22916 edns512-notcp. + hwvmKC/yVOUavH1cty6pg1EyTNBo+MAz+KjY + UmodFwGPv2EuRY/6TcujLTMHdeSbi71e+JQU + +ij6TXcXNZl7CpZbBEfVZd8xvTPYykhO3rr8 + cckPre1p8pGx56x7nVjRA1P/+oyjjr6j1nVZ + RewWOrSo/LPah4WY2iyEJH0JF5H/SVrF2Z86 + XT4YrLqe+1vpeRw0C8VNAJGZbd6H90Qu/Cnd + Xdyj1OOl+RQbvJCVpcw6/fFmcNRy5zbQJFA6 + nsGyCL62OfptdByQKJhSU6gQcaWcMnYeqSgT + I3yBye1whQ/2fdgyKUFAESbPRp7WpzXzNabf + ZNeLRZT8RGsjHD4i0OqCL+R6axXl53wUn7sa + pXWTRBWIKshnTJrzntIkdXLq1qQtxnw7zA6h + kUCVzf1FzjP64cHh928CQBbnfT1MSdJuQe1G + /RGCn0RwOcn+n06O2uiCBmwkGnrZB/+Yytzp + apdULCyUmvByozvKYp73GOK4eTAqNF6igEAc + pSz8oXZy+wmVG1l72yli1Eyunm010Skb3oxe + 23htSPq1MIqETzAWtMJM082F9vAEjTJNSnSo + RFpPnlq6LDjtr7Z6/mRcqVXx5OC1nj4Svaxo + JOebR0igOJcAKG9gCGz6ffDy/1VeUHCnzvKR + vgJZjbvXDuHkOzNB6KYc3N2BglMIxajwVcQ= ) diff --git a/bin/tests/system/legacy/ns7/named.args b/bin/tests/system/legacy/ns7/named.args new file mode 100644 index 0000000..3c90ac1 --- /dev/null +++ b/bin/tests/system/legacy/ns7/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D legacy-ns7 -g -T maxcachesize=2097152 -T maxudp512 diff --git a/bin/tests/system/legacy/ns7/named.conf.in b/bin/tests/system/legacy/ns7/named.conf.in new file mode 100644 index 0000000..30f3ea2 --- /dev/null +++ b/bin/tests/system/legacy/ns7/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "edns512-notcp" { + type primary; + file "edns512-notcp.db.signed"; +}; diff --git a/bin/tests/system/legacy/ns7/named.notcp b/bin/tests/system/legacy/ns7/named.notcp new file mode 100644 index 0000000..e25c3a8 --- /dev/null +++ b/bin/tests/system/legacy/ns7/named.notcp @@ -0,0 +1 @@ +notcp diff --git a/bin/tests/system/legacy/ns7/sign.sh b/bin/tests/system/legacy/ns7/sign.sh new file mode 100755 index 0000000..9dfa9f6 --- /dev/null +++ b/bin/tests/system/legacy/ns7/sign.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +echo_i "sign edns512-notcp" + +zone=edns512-notcp +infile=edns512-notcp.db.in +zonefile=edns512-notcp.db +outfile=edns512-notcp.db.signed + +keyname1=$($KEYGEN -a RSASHA512 -b 4096 -n zone $zone 2>/dev/null) +keyname2=$($KEYGEN -f KSK -a RSASHA512 -b 4096 -n zone $zone 2>/dev/null) + +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -g -o $zone -f $outfile -e +30y $zonefile >/dev/null 2>signer.err || cat signer.err + +keyfile_to_static_ds $keyname2 >trusted.conf +cp trusted.conf ../ns1 diff --git a/bin/tests/system/legacy/ns8/ednsformerr.db b/bin/tests/system/legacy/ns8/ednsformerr.db new file mode 100644 index 0000000..9aa3a4a --- /dev/null +++ b/bin/tests/system/legacy/ns8/ednsformerr.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.8 diff --git a/bin/tests/system/legacy/ns8/named.conf.in b/bin/tests/system/legacy/ns8/named.conf.in new file mode 100644 index 0000000..7431cf8 --- /dev/null +++ b/bin/tests/system/legacy/ns8/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "ednsformerr" { + type primary; + file "ednsformerr.db"; +}; diff --git a/bin/tests/system/legacy/ns8/named.ednsformerr b/bin/tests/system/legacy/ns8/named.ednsformerr new file mode 100644 index 0000000..e35cb02 --- /dev/null +++ b/bin/tests/system/legacy/ns8/named.ednsformerr @@ -0,0 +1 @@ +ednsformerr diff --git a/bin/tests/system/legacy/ns9/ednsnotimp.db b/bin/tests/system/legacy/ns9/ednsnotimp.db new file mode 100644 index 0000000..9aa3a4a --- /dev/null +++ b/bin/tests/system/legacy/ns9/ednsnotimp.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 60 SOA ns marka.isc.org. 1 0 0 0 0 +@ 60 NS ns +ns 60 A 10.53.0.8 diff --git a/bin/tests/system/legacy/ns9/named.conf.in b/bin/tests/system/legacy/ns9/named.conf.in new file mode 100644 index 0000000..385fbfd --- /dev/null +++ b/bin/tests/system/legacy/ns9/named.conf.in @@ -0,0 +1,29 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "ednsnotimp" { + type primary; + file "ednsnotimp.db"; +}; diff --git a/bin/tests/system/legacy/ns9/named.ednsnotimp b/bin/tests/system/legacy/ns9/named.ednsnotimp new file mode 100644 index 0000000..4e6424d --- /dev/null +++ b/bin/tests/system/legacy/ns9/named.ednsnotimp @@ -0,0 +1 @@ +ednsnotimp diff --git a/bin/tests/system/legacy/setup.sh b/bin/tests/system/legacy/setup.sh new file mode 100644 index 0000000..d2a53bb --- /dev/null +++ b/bin/tests/system/legacy/setup.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf +copy_setports ns9/named.conf.in ns9/named.conf +copy_setports ns10/named.conf.in ns10/named.conf diff --git a/bin/tests/system/legacy/tests.sh b/bin/tests/system/legacy/tests.sh new file mode 100755 index 0000000..9504125 --- /dev/null +++ b/bin/tests/system/legacy/tests.sh @@ -0,0 +1,269 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT} +tries=1 +time=2" + +# Check whether the SOA record for the name provided in $1 can be resolved by +# ns1. Return 0 if resolution succeeds as expected; return 1 otherwise. +resolution_succeeds() { + _ret=0 + $DIG $DIGOPTS +tcp +tries=3 +time=5 @10.53.0.1 ${1} SOA >dig.out.test$n || _ret=1 + grep "status: NOERROR" dig.out.test$n >/dev/null || _ret=1 + return $_ret +} + +# Check whether the SOA record for the name provided in $1 can be resolved by +# ns1. Return 0 if resolution fails as expected; return 1 otherwise. Note that +# both a SERVFAIL response and timing out mean resolution failed, so the exit +# code of dig does not influence the result (the exit code for a SERVFAIL +# response is 0 while the exit code for not getting a response at all is not 0). +resolution_fails() { + _servfail=0 + _timeout=0 + $DIG $DIGOPTS +tcp +time=5 @10.53.0.1 ${1} TXT >dig.out.test$n || true + grep -F "status: SERVFAIL" dig.out.test$n >/dev/null && _servfail=1 + grep -F "timed out" dig.out.test$n >/dev/null && _timeout=1 + if [ $_servfail -eq 1 ] || [ $_timeout -eq 1 ]; then + return 0 + else + return 1 + fi +} + +status=0 +n=0 + +n=$((n + 1)) +echo_i "checking formerr edns server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.8 ednsformerr soa >dig.out.1.test$n || ret=1 +grep "status: FORMERR" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +noedns @10.53.0.8 ednsformerr soa >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to formerr edns server succeeds ($n)" +ret=0 +resolution_succeeds ednsformerr. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking notimp edns server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.9 ednsnotimp soa >dig.out.1.test$n || ret=1 +grep "status: NOTIMP" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +noedns @10.53.0.9 ednsnotimp soa >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to notimp edns server fails ($n)" +ret=0 +resolution_fails ednsnotimp. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking refused edns server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.10 ednsrefused soa >dig.out.1.test$n || ret=1 +grep "status: REFUSED" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +noedns @10.53.0.10 ednsrefused soa >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to refused edns server fails ($n)" +ret=0 +resolution_fails ednsrefused. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop edns server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.2 dropedns soa >dig.out.1.test$n && ret=1 +grep "timed out" dig.out.1.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +noedns @10.53.0.2 dropedns soa >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +noedns +tcp @10.53.0.2 dropedns soa >dig.out.3.test$n || ret=1 +grep "status: NOERROR" dig.out.3.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.3.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +edns +tcp @10.53.0.2 dropedns soa >dig.out.4.test$n && ret=1 +grep "timed out" dig.out.4.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to drop edns server fails ($n)" +ret=0 +resolution_fails dropedns. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking drop edns + no tcp server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.3 dropedns-notcp soa >dig.out.1.test$n && ret=1 +grep "timed out" dig.out.1.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +noedns +tcp @10.53.0.3 dropedns-notcp soa >dig.out.2.test$n && ret=1 +grep "connection refused" dig.out.2.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +noedns @10.53.0.3 dropedns-notcp soa >dig.out.3.test$n || ret=1 +grep "status: NOERROR" dig.out.3.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to drop edns + no tcp server fails ($n)" +ret=0 +resolution_fails dropedns-notcp. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking plain dns server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.4 plain soa >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +edns +tcp @10.53.0.4 plain soa >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to plain dns server succeeds ($n)" +ret=0 +resolution_succeeds plain. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking plain dns + no tcp server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.5 plain-notcp soa >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null && ret=1 +$DIG $DIGOPTS +edns +tcp @10.53.0.5 plain-notcp soa >dig.out.2.test$n && ret=1 +grep "connection refused" dig.out.2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to plain dns + no tcp server succeeds ($n)" +ret=0 +resolution_succeeds plain-notcp. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) + +echo_i "checking edns 512 server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.6 edns512 txt >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +tcp @10.53.0.6 edns512 txt >dig.out.2.test$n || ret=1 +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.2.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +dnssec @10.53.0.6 edns512 txt >dig.out.3.test$n && ret=1 +grep "timed out" dig.out.3.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.3.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +dnssec +bufsize=512 +ignore @10.53.0.6 edns512 soa >dig.out.4.test$n || ret=1 +grep "status: NOERROR" dig.out.4.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.4.test$n >/dev/null || ret=1 +grep "flags:.* tc[ ;]" dig.out.4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to edns 512 server succeeds ($n)" +ret=0 +retry_quiet 3 resolution_succeeds edns512. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking edns 512 + no tcp server setup ($n)" +ret=0 +$DIG $DIGOPTS +edns @10.53.0.7 edns512-notcp soa >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.1.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +tcp @10.53.0.7 edns512-notcp soa >dig.out.2.test$n && ret=1 +grep "connection refused" dig.out.2.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +dnssec @10.53.0.7 edns512-notcp soa >dig.out.3.test$n && ret=1 +grep "timed out" dig.out.3.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.3.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +edns +dnssec +bufsize=512 +ignore @10.53.0.7 edns512-notcp soa >dig.out.4.test$n || ret=1 +grep "status: NOERROR" dig.out.4.test$n >/dev/null || ret=1 +grep "EDNS: version:" dig.out.4.test$n >/dev/null || ret=1 +grep "flags:.* tc[ ;]" dig.out.4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to edns 512 + no tcp server fails ($n)" +ret=0 +resolution_fails edns512-notcp. || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking recursive lookup to edns 512 + no tcp server does not cause query loops ($n)" +ret=0 +sent=$(grep -c -F "sending packet to 10.53.0.7" ns1/named.run) +if [ $sent -ge 10 ]; then + echo_i "ns1 sent $sent queries to ns7, expected less than 10" + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +stop_server --use-rndc --port ${CONTROLPORT} ns1 +copy_setports ns1/named2.conf.in ns1/named.conf +start_server --noclean --restart --port ${PORT} ns1 + +n=$((n + 1)) +echo_i "checking recursive lookup to edns 512 + no tcp + trust anchor fails ($n)" +# retry loop in case the server restart above causes transient failure +for try in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + resolution_fails edns512-notcp. || ret=1 + [ "$ret" -eq 0 ] && break + sleep 1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/legacy/tests_sh_legacy.py b/bin/tests/system/legacy/tests_sh_legacy.py new file mode 100644 index 0000000..7d83b06 --- /dev/null +++ b/bin/tests/system/legacy/tests_sh_legacy.py @@ -0,0 +1,22 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + ] +) + + +def test_legacy(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/limits/ns1/example.db b/bin/tests/system/limits/ns1/example.db new file mode 100644 index 0000000..1ce7e11 --- /dev/null +++ b/bin/tests/system/limits/ns1/example.db @@ -0,0 +1,19112 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns1.example. hostmaster.example. ( + 2000042795 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS ns1.example. +ns1 A 10.53.0.1 +1000 A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 +2000 A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 + A 10.0.3.232 + A 10.0.3.233 + A 10.0.3.234 + A 10.0.3.235 + A 10.0.3.236 + A 10.0.3.237 + A 10.0.3.238 + A 10.0.3.239 + A 10.0.3.240 + A 10.0.3.241 + A 10.0.3.242 + A 10.0.3.243 + A 10.0.3.244 + A 10.0.3.245 + A 10.0.3.246 + A 10.0.3.247 + A 10.0.3.248 + A 10.0.3.249 + A 10.0.3.250 + A 10.0.3.251 + A 10.0.3.252 + A 10.0.3.253 + A 10.0.3.254 + A 10.0.3.255 + A 10.0.4.0 + A 10.0.4.1 + A 10.0.4.2 + A 10.0.4.3 + A 10.0.4.4 + A 10.0.4.5 + A 10.0.4.6 + A 10.0.4.7 + A 10.0.4.8 + A 10.0.4.9 + A 10.0.4.10 + A 10.0.4.11 + A 10.0.4.12 + A 10.0.4.13 + A 10.0.4.14 + A 10.0.4.15 + A 10.0.4.16 + A 10.0.4.17 + A 10.0.4.18 + A 10.0.4.19 + A 10.0.4.20 + A 10.0.4.21 + A 10.0.4.22 + A 10.0.4.23 + A 10.0.4.24 + A 10.0.4.25 + A 10.0.4.26 + A 10.0.4.27 + A 10.0.4.28 + A 10.0.4.29 + A 10.0.4.30 + A 10.0.4.31 + A 10.0.4.32 + A 10.0.4.33 + A 10.0.4.34 + A 10.0.4.35 + A 10.0.4.36 + A 10.0.4.37 + A 10.0.4.38 + A 10.0.4.39 + A 10.0.4.40 + A 10.0.4.41 + A 10.0.4.42 + A 10.0.4.43 + A 10.0.4.44 + A 10.0.4.45 + A 10.0.4.46 + A 10.0.4.47 + A 10.0.4.48 + A 10.0.4.49 + A 10.0.4.50 + A 10.0.4.51 + A 10.0.4.52 + A 10.0.4.53 + A 10.0.4.54 + A 10.0.4.55 + A 10.0.4.56 + A 10.0.4.57 + A 10.0.4.58 + A 10.0.4.59 + A 10.0.4.60 + A 10.0.4.61 + A 10.0.4.62 + A 10.0.4.63 + A 10.0.4.64 + A 10.0.4.65 + A 10.0.4.66 + A 10.0.4.67 + A 10.0.4.68 + A 10.0.4.69 + A 10.0.4.70 + A 10.0.4.71 + A 10.0.4.72 + A 10.0.4.73 + A 10.0.4.74 + A 10.0.4.75 + A 10.0.4.76 + A 10.0.4.77 + A 10.0.4.78 + A 10.0.4.79 + A 10.0.4.80 + A 10.0.4.81 + A 10.0.4.82 + A 10.0.4.83 + A 10.0.4.84 + A 10.0.4.85 + A 10.0.4.86 + A 10.0.4.87 + A 10.0.4.88 + A 10.0.4.89 + A 10.0.4.90 + A 10.0.4.91 + A 10.0.4.92 + A 10.0.4.93 + A 10.0.4.94 + A 10.0.4.95 + A 10.0.4.96 + A 10.0.4.97 + A 10.0.4.98 + A 10.0.4.99 + A 10.0.4.100 + A 10.0.4.101 + A 10.0.4.102 + A 10.0.4.103 + A 10.0.4.104 + A 10.0.4.105 + A 10.0.4.106 + A 10.0.4.107 + A 10.0.4.108 + A 10.0.4.109 + A 10.0.4.110 + A 10.0.4.111 + A 10.0.4.112 + A 10.0.4.113 + A 10.0.4.114 + A 10.0.4.115 + A 10.0.4.116 + A 10.0.4.117 + A 10.0.4.118 + A 10.0.4.119 + A 10.0.4.120 + A 10.0.4.121 + A 10.0.4.122 + A 10.0.4.123 + A 10.0.4.124 + A 10.0.4.125 + A 10.0.4.126 + A 10.0.4.127 + A 10.0.4.128 + A 10.0.4.129 + A 10.0.4.130 + A 10.0.4.131 + A 10.0.4.132 + A 10.0.4.133 + A 10.0.4.134 + A 10.0.4.135 + A 10.0.4.136 + A 10.0.4.137 + A 10.0.4.138 + A 10.0.4.139 + A 10.0.4.140 + A 10.0.4.141 + A 10.0.4.142 + A 10.0.4.143 + A 10.0.4.144 + A 10.0.4.145 + A 10.0.4.146 + A 10.0.4.147 + A 10.0.4.148 + A 10.0.4.149 + A 10.0.4.150 + A 10.0.4.151 + A 10.0.4.152 + A 10.0.4.153 + A 10.0.4.154 + A 10.0.4.155 + A 10.0.4.156 + A 10.0.4.157 + A 10.0.4.158 + A 10.0.4.159 + A 10.0.4.160 + A 10.0.4.161 + A 10.0.4.162 + A 10.0.4.163 + A 10.0.4.164 + A 10.0.4.165 + A 10.0.4.166 + A 10.0.4.167 + A 10.0.4.168 + A 10.0.4.169 + A 10.0.4.170 + A 10.0.4.171 + A 10.0.4.172 + A 10.0.4.173 + A 10.0.4.174 + A 10.0.4.175 + A 10.0.4.176 + A 10.0.4.177 + A 10.0.4.178 + A 10.0.4.179 + A 10.0.4.180 + A 10.0.4.181 + A 10.0.4.182 + A 10.0.4.183 + A 10.0.4.184 + A 10.0.4.185 + A 10.0.4.186 + A 10.0.4.187 + A 10.0.4.188 + A 10.0.4.189 + A 10.0.4.190 + A 10.0.4.191 + A 10.0.4.192 + A 10.0.4.193 + A 10.0.4.194 + A 10.0.4.195 + A 10.0.4.196 + A 10.0.4.197 + A 10.0.4.198 + A 10.0.4.199 + A 10.0.4.200 + A 10.0.4.201 + A 10.0.4.202 + A 10.0.4.203 + A 10.0.4.204 + A 10.0.4.205 + A 10.0.4.206 + A 10.0.4.207 + A 10.0.4.208 + A 10.0.4.209 + A 10.0.4.210 + A 10.0.4.211 + A 10.0.4.212 + A 10.0.4.213 + A 10.0.4.214 + A 10.0.4.215 + A 10.0.4.216 + A 10.0.4.217 + A 10.0.4.218 + A 10.0.4.219 + A 10.0.4.220 + A 10.0.4.221 + A 10.0.4.222 + A 10.0.4.223 + A 10.0.4.224 + A 10.0.4.225 + A 10.0.4.226 + A 10.0.4.227 + A 10.0.4.228 + A 10.0.4.229 + A 10.0.4.230 + A 10.0.4.231 + A 10.0.4.232 + A 10.0.4.233 + A 10.0.4.234 + A 10.0.4.235 + A 10.0.4.236 + A 10.0.4.237 + A 10.0.4.238 + A 10.0.4.239 + A 10.0.4.240 + A 10.0.4.241 + A 10.0.4.242 + A 10.0.4.243 + A 10.0.4.244 + A 10.0.4.245 + A 10.0.4.246 + A 10.0.4.247 + A 10.0.4.248 + A 10.0.4.249 + A 10.0.4.250 + A 10.0.4.251 + A 10.0.4.252 + A 10.0.4.253 + A 10.0.4.254 + A 10.0.4.255 + A 10.0.5.0 + A 10.0.5.1 + A 10.0.5.2 + A 10.0.5.3 + A 10.0.5.4 + A 10.0.5.5 + A 10.0.5.6 + A 10.0.5.7 + A 10.0.5.8 + A 10.0.5.9 + A 10.0.5.10 + A 10.0.5.11 + A 10.0.5.12 + A 10.0.5.13 + A 10.0.5.14 + A 10.0.5.15 + A 10.0.5.16 + A 10.0.5.17 + A 10.0.5.18 + A 10.0.5.19 + A 10.0.5.20 + A 10.0.5.21 + A 10.0.5.22 + A 10.0.5.23 + A 10.0.5.24 + A 10.0.5.25 + A 10.0.5.26 + A 10.0.5.27 + A 10.0.5.28 + A 10.0.5.29 + A 10.0.5.30 + A 10.0.5.31 + A 10.0.5.32 + A 10.0.5.33 + A 10.0.5.34 + A 10.0.5.35 + A 10.0.5.36 + A 10.0.5.37 + A 10.0.5.38 + A 10.0.5.39 + A 10.0.5.40 + A 10.0.5.41 + A 10.0.5.42 + A 10.0.5.43 + A 10.0.5.44 + A 10.0.5.45 + A 10.0.5.46 + A 10.0.5.47 + A 10.0.5.48 + A 10.0.5.49 + A 10.0.5.50 + A 10.0.5.51 + A 10.0.5.52 + A 10.0.5.53 + A 10.0.5.54 + A 10.0.5.55 + A 10.0.5.56 + A 10.0.5.57 + A 10.0.5.58 + A 10.0.5.59 + A 10.0.5.60 + A 10.0.5.61 + A 10.0.5.62 + A 10.0.5.63 + A 10.0.5.64 + A 10.0.5.65 + A 10.0.5.66 + A 10.0.5.67 + A 10.0.5.68 + A 10.0.5.69 + A 10.0.5.70 + A 10.0.5.71 + A 10.0.5.72 + A 10.0.5.73 + A 10.0.5.74 + A 10.0.5.75 + A 10.0.5.76 + A 10.0.5.77 + A 10.0.5.78 + A 10.0.5.79 + A 10.0.5.80 + A 10.0.5.81 + A 10.0.5.82 + A 10.0.5.83 + A 10.0.5.84 + A 10.0.5.85 + A 10.0.5.86 + A 10.0.5.87 + A 10.0.5.88 + A 10.0.5.89 + A 10.0.5.90 + A 10.0.5.91 + A 10.0.5.92 + A 10.0.5.93 + A 10.0.5.94 + A 10.0.5.95 + A 10.0.5.96 + A 10.0.5.97 + A 10.0.5.98 + A 10.0.5.99 + A 10.0.5.100 + A 10.0.5.101 + A 10.0.5.102 + A 10.0.5.103 + A 10.0.5.104 + A 10.0.5.105 + A 10.0.5.106 + A 10.0.5.107 + A 10.0.5.108 + A 10.0.5.109 + A 10.0.5.110 + A 10.0.5.111 + A 10.0.5.112 + A 10.0.5.113 + A 10.0.5.114 + A 10.0.5.115 + A 10.0.5.116 + A 10.0.5.117 + A 10.0.5.118 + A 10.0.5.119 + A 10.0.5.120 + A 10.0.5.121 + A 10.0.5.122 + A 10.0.5.123 + A 10.0.5.124 + A 10.0.5.125 + A 10.0.5.126 + A 10.0.5.127 + A 10.0.5.128 + A 10.0.5.129 + A 10.0.5.130 + A 10.0.5.131 + A 10.0.5.132 + A 10.0.5.133 + A 10.0.5.134 + A 10.0.5.135 + A 10.0.5.136 + A 10.0.5.137 + A 10.0.5.138 + A 10.0.5.139 + A 10.0.5.140 + A 10.0.5.141 + A 10.0.5.142 + A 10.0.5.143 + A 10.0.5.144 + A 10.0.5.145 + A 10.0.5.146 + A 10.0.5.147 + A 10.0.5.148 + A 10.0.5.149 + A 10.0.5.150 + A 10.0.5.151 + A 10.0.5.152 + A 10.0.5.153 + A 10.0.5.154 + A 10.0.5.155 + A 10.0.5.156 + A 10.0.5.157 + A 10.0.5.158 + A 10.0.5.159 + A 10.0.5.160 + A 10.0.5.161 + A 10.0.5.162 + A 10.0.5.163 + A 10.0.5.164 + A 10.0.5.165 + A 10.0.5.166 + A 10.0.5.167 + A 10.0.5.168 + A 10.0.5.169 + A 10.0.5.170 + A 10.0.5.171 + A 10.0.5.172 + A 10.0.5.173 + A 10.0.5.174 + A 10.0.5.175 + A 10.0.5.176 + A 10.0.5.177 + A 10.0.5.178 + A 10.0.5.179 + A 10.0.5.180 + A 10.0.5.181 + A 10.0.5.182 + A 10.0.5.183 + A 10.0.5.184 + A 10.0.5.185 + A 10.0.5.186 + A 10.0.5.187 + A 10.0.5.188 + A 10.0.5.189 + A 10.0.5.190 + A 10.0.5.191 + A 10.0.5.192 + A 10.0.5.193 + A 10.0.5.194 + A 10.0.5.195 + A 10.0.5.196 + A 10.0.5.197 + A 10.0.5.198 + A 10.0.5.199 + A 10.0.5.200 + A 10.0.5.201 + A 10.0.5.202 + A 10.0.5.203 + A 10.0.5.204 + A 10.0.5.205 + A 10.0.5.206 + A 10.0.5.207 + A 10.0.5.208 + A 10.0.5.209 + A 10.0.5.210 + A 10.0.5.211 + A 10.0.5.212 + A 10.0.5.213 + A 10.0.5.214 + A 10.0.5.215 + A 10.0.5.216 + A 10.0.5.217 + A 10.0.5.218 + A 10.0.5.219 + A 10.0.5.220 + A 10.0.5.221 + A 10.0.5.222 + A 10.0.5.223 + A 10.0.5.224 + A 10.0.5.225 + A 10.0.5.226 + A 10.0.5.227 + A 10.0.5.228 + A 10.0.5.229 + A 10.0.5.230 + A 10.0.5.231 + A 10.0.5.232 + A 10.0.5.233 + A 10.0.5.234 + A 10.0.5.235 + A 10.0.5.236 + A 10.0.5.237 + A 10.0.5.238 + A 10.0.5.239 + A 10.0.5.240 + A 10.0.5.241 + A 10.0.5.242 + A 10.0.5.243 + A 10.0.5.244 + A 10.0.5.245 + A 10.0.5.246 + A 10.0.5.247 + A 10.0.5.248 + A 10.0.5.249 + A 10.0.5.250 + A 10.0.5.251 + A 10.0.5.252 + A 10.0.5.253 + A 10.0.5.254 + A 10.0.5.255 + A 10.0.6.0 + A 10.0.6.1 + A 10.0.6.2 + A 10.0.6.3 + A 10.0.6.4 + A 10.0.6.5 + A 10.0.6.6 + A 10.0.6.7 + A 10.0.6.8 + A 10.0.6.9 + A 10.0.6.10 + A 10.0.6.11 + A 10.0.6.12 + A 10.0.6.13 + A 10.0.6.14 + A 10.0.6.15 + A 10.0.6.16 + A 10.0.6.17 + A 10.0.6.18 + A 10.0.6.19 + A 10.0.6.20 + A 10.0.6.21 + A 10.0.6.22 + A 10.0.6.23 + A 10.0.6.24 + A 10.0.6.25 + A 10.0.6.26 + A 10.0.6.27 + A 10.0.6.28 + A 10.0.6.29 + A 10.0.6.30 + A 10.0.6.31 + A 10.0.6.32 + A 10.0.6.33 + A 10.0.6.34 + A 10.0.6.35 + A 10.0.6.36 + A 10.0.6.37 + A 10.0.6.38 + A 10.0.6.39 + A 10.0.6.40 + A 10.0.6.41 + A 10.0.6.42 + A 10.0.6.43 + A 10.0.6.44 + A 10.0.6.45 + A 10.0.6.46 + A 10.0.6.47 + A 10.0.6.48 + A 10.0.6.49 + A 10.0.6.50 + A 10.0.6.51 + A 10.0.6.52 + A 10.0.6.53 + A 10.0.6.54 + A 10.0.6.55 + A 10.0.6.56 + A 10.0.6.57 + A 10.0.6.58 + A 10.0.6.59 + A 10.0.6.60 + A 10.0.6.61 + A 10.0.6.62 + A 10.0.6.63 + A 10.0.6.64 + A 10.0.6.65 + A 10.0.6.66 + A 10.0.6.67 + A 10.0.6.68 + A 10.0.6.69 + A 10.0.6.70 + A 10.0.6.71 + A 10.0.6.72 + A 10.0.6.73 + A 10.0.6.74 + A 10.0.6.75 + A 10.0.6.76 + A 10.0.6.77 + A 10.0.6.78 + A 10.0.6.79 + A 10.0.6.80 + A 10.0.6.81 + A 10.0.6.82 + A 10.0.6.83 + A 10.0.6.84 + A 10.0.6.85 + A 10.0.6.86 + A 10.0.6.87 + A 10.0.6.88 + A 10.0.6.89 + A 10.0.6.90 + A 10.0.6.91 + A 10.0.6.92 + A 10.0.6.93 + A 10.0.6.94 + A 10.0.6.95 + A 10.0.6.96 + A 10.0.6.97 + A 10.0.6.98 + A 10.0.6.99 + A 10.0.6.100 + A 10.0.6.101 + A 10.0.6.102 + A 10.0.6.103 + A 10.0.6.104 + A 10.0.6.105 + A 10.0.6.106 + A 10.0.6.107 + A 10.0.6.108 + A 10.0.6.109 + A 10.0.6.110 + A 10.0.6.111 + A 10.0.6.112 + A 10.0.6.113 + A 10.0.6.114 + A 10.0.6.115 + A 10.0.6.116 + A 10.0.6.117 + A 10.0.6.118 + A 10.0.6.119 + A 10.0.6.120 + A 10.0.6.121 + A 10.0.6.122 + A 10.0.6.123 + A 10.0.6.124 + A 10.0.6.125 + A 10.0.6.126 + A 10.0.6.127 + A 10.0.6.128 + A 10.0.6.129 + A 10.0.6.130 + A 10.0.6.131 + A 10.0.6.132 + A 10.0.6.133 + A 10.0.6.134 + A 10.0.6.135 + A 10.0.6.136 + A 10.0.6.137 + A 10.0.6.138 + A 10.0.6.139 + A 10.0.6.140 + A 10.0.6.141 + A 10.0.6.142 + A 10.0.6.143 + A 10.0.6.144 + A 10.0.6.145 + A 10.0.6.146 + A 10.0.6.147 + A 10.0.6.148 + A 10.0.6.149 + A 10.0.6.150 + A 10.0.6.151 + A 10.0.6.152 + A 10.0.6.153 + A 10.0.6.154 + A 10.0.6.155 + A 10.0.6.156 + A 10.0.6.157 + A 10.0.6.158 + A 10.0.6.159 + A 10.0.6.160 + A 10.0.6.161 + A 10.0.6.162 + A 10.0.6.163 + A 10.0.6.164 + A 10.0.6.165 + A 10.0.6.166 + A 10.0.6.167 + A 10.0.6.168 + A 10.0.6.169 + A 10.0.6.170 + A 10.0.6.171 + A 10.0.6.172 + A 10.0.6.173 + A 10.0.6.174 + A 10.0.6.175 + A 10.0.6.176 + A 10.0.6.177 + A 10.0.6.178 + A 10.0.6.179 + A 10.0.6.180 + A 10.0.6.181 + A 10.0.6.182 + A 10.0.6.183 + A 10.0.6.184 + A 10.0.6.185 + A 10.0.6.186 + A 10.0.6.187 + A 10.0.6.188 + A 10.0.6.189 + A 10.0.6.190 + A 10.0.6.191 + A 10.0.6.192 + A 10.0.6.193 + A 10.0.6.194 + A 10.0.6.195 + A 10.0.6.196 + A 10.0.6.197 + A 10.0.6.198 + A 10.0.6.199 + A 10.0.6.200 + A 10.0.6.201 + A 10.0.6.202 + A 10.0.6.203 + A 10.0.6.204 + A 10.0.6.205 + A 10.0.6.206 + A 10.0.6.207 + A 10.0.6.208 + A 10.0.6.209 + A 10.0.6.210 + A 10.0.6.211 + A 10.0.6.212 + A 10.0.6.213 + A 10.0.6.214 + A 10.0.6.215 + A 10.0.6.216 + A 10.0.6.217 + A 10.0.6.218 + A 10.0.6.219 + A 10.0.6.220 + A 10.0.6.221 + A 10.0.6.222 + A 10.0.6.223 + A 10.0.6.224 + A 10.0.6.225 + A 10.0.6.226 + A 10.0.6.227 + A 10.0.6.228 + A 10.0.6.229 + A 10.0.6.230 + A 10.0.6.231 + A 10.0.6.232 + A 10.0.6.233 + A 10.0.6.234 + A 10.0.6.235 + A 10.0.6.236 + A 10.0.6.237 + A 10.0.6.238 + A 10.0.6.239 + A 10.0.6.240 + A 10.0.6.241 + A 10.0.6.242 + A 10.0.6.243 + A 10.0.6.244 + A 10.0.6.245 + A 10.0.6.246 + A 10.0.6.247 + A 10.0.6.248 + A 10.0.6.249 + A 10.0.6.250 + A 10.0.6.251 + A 10.0.6.252 + A 10.0.6.253 + A 10.0.6.254 + A 10.0.6.255 + A 10.0.7.0 + A 10.0.7.1 + A 10.0.7.2 + A 10.0.7.3 + A 10.0.7.4 + A 10.0.7.5 + A 10.0.7.6 + A 10.0.7.7 + A 10.0.7.8 + A 10.0.7.9 + A 10.0.7.10 + A 10.0.7.11 + A 10.0.7.12 + A 10.0.7.13 + A 10.0.7.14 + A 10.0.7.15 + A 10.0.7.16 + A 10.0.7.17 + A 10.0.7.18 + A 10.0.7.19 + A 10.0.7.20 + A 10.0.7.21 + A 10.0.7.22 + A 10.0.7.23 + A 10.0.7.24 + A 10.0.7.25 + A 10.0.7.26 + A 10.0.7.27 + A 10.0.7.28 + A 10.0.7.29 + A 10.0.7.30 + A 10.0.7.31 + A 10.0.7.32 + A 10.0.7.33 + A 10.0.7.34 + A 10.0.7.35 + A 10.0.7.36 + A 10.0.7.37 + A 10.0.7.38 + A 10.0.7.39 + A 10.0.7.40 + A 10.0.7.41 + A 10.0.7.42 + A 10.0.7.43 + A 10.0.7.44 + A 10.0.7.45 + A 10.0.7.46 + A 10.0.7.47 + A 10.0.7.48 + A 10.0.7.49 + A 10.0.7.50 + A 10.0.7.51 + A 10.0.7.52 + A 10.0.7.53 + A 10.0.7.54 + A 10.0.7.55 + A 10.0.7.56 + A 10.0.7.57 + A 10.0.7.58 + A 10.0.7.59 + A 10.0.7.60 + A 10.0.7.61 + A 10.0.7.62 + A 10.0.7.63 + A 10.0.7.64 + A 10.0.7.65 + A 10.0.7.66 + A 10.0.7.67 + A 10.0.7.68 + A 10.0.7.69 + A 10.0.7.70 + A 10.0.7.71 + A 10.0.7.72 + A 10.0.7.73 + A 10.0.7.74 + A 10.0.7.75 + A 10.0.7.76 + A 10.0.7.77 + A 10.0.7.78 + A 10.0.7.79 + A 10.0.7.80 + A 10.0.7.81 + A 10.0.7.82 + A 10.0.7.83 + A 10.0.7.84 + A 10.0.7.85 + A 10.0.7.86 + A 10.0.7.87 + A 10.0.7.88 + A 10.0.7.89 + A 10.0.7.90 + A 10.0.7.91 + A 10.0.7.92 + A 10.0.7.93 + A 10.0.7.94 + A 10.0.7.95 + A 10.0.7.96 + A 10.0.7.97 + A 10.0.7.98 + A 10.0.7.99 + A 10.0.7.100 + A 10.0.7.101 + A 10.0.7.102 + A 10.0.7.103 + A 10.0.7.104 + A 10.0.7.105 + A 10.0.7.106 + A 10.0.7.107 + A 10.0.7.108 + A 10.0.7.109 + A 10.0.7.110 + A 10.0.7.111 + A 10.0.7.112 + A 10.0.7.113 + A 10.0.7.114 + A 10.0.7.115 + A 10.0.7.116 + A 10.0.7.117 + A 10.0.7.118 + A 10.0.7.119 + A 10.0.7.120 + A 10.0.7.121 + A 10.0.7.122 + A 10.0.7.123 + A 10.0.7.124 + A 10.0.7.125 + A 10.0.7.126 + A 10.0.7.127 + A 10.0.7.128 + A 10.0.7.129 + A 10.0.7.130 + A 10.0.7.131 + A 10.0.7.132 + A 10.0.7.133 + A 10.0.7.134 + A 10.0.7.135 + A 10.0.7.136 + A 10.0.7.137 + A 10.0.7.138 + A 10.0.7.139 + A 10.0.7.140 + A 10.0.7.141 + A 10.0.7.142 + A 10.0.7.143 + A 10.0.7.144 + A 10.0.7.145 + A 10.0.7.146 + A 10.0.7.147 + A 10.0.7.148 + A 10.0.7.149 + A 10.0.7.150 + A 10.0.7.151 + A 10.0.7.152 + A 10.0.7.153 + A 10.0.7.154 + A 10.0.7.155 + A 10.0.7.156 + A 10.0.7.157 + A 10.0.7.158 + A 10.0.7.159 + A 10.0.7.160 + A 10.0.7.161 + A 10.0.7.162 + A 10.0.7.163 + A 10.0.7.164 + A 10.0.7.165 + A 10.0.7.166 + A 10.0.7.167 + A 10.0.7.168 + A 10.0.7.169 + A 10.0.7.170 + A 10.0.7.171 + A 10.0.7.172 + A 10.0.7.173 + A 10.0.7.174 + A 10.0.7.175 + A 10.0.7.176 + A 10.0.7.177 + A 10.0.7.178 + A 10.0.7.179 + A 10.0.7.180 + A 10.0.7.181 + A 10.0.7.182 + A 10.0.7.183 + A 10.0.7.184 + A 10.0.7.185 + A 10.0.7.186 + A 10.0.7.187 + A 10.0.7.188 + A 10.0.7.189 + A 10.0.7.190 + A 10.0.7.191 + A 10.0.7.192 + A 10.0.7.193 + A 10.0.7.194 + A 10.0.7.195 + A 10.0.7.196 + A 10.0.7.197 + A 10.0.7.198 + A 10.0.7.199 + A 10.0.7.200 + A 10.0.7.201 + A 10.0.7.202 + A 10.0.7.203 + A 10.0.7.204 + A 10.0.7.205 + A 10.0.7.206 + A 10.0.7.207 +3000 A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 + A 10.0.3.232 + A 10.0.3.233 + A 10.0.3.234 + A 10.0.3.235 + A 10.0.3.236 + A 10.0.3.237 + A 10.0.3.238 + A 10.0.3.239 + A 10.0.3.240 + A 10.0.3.241 + A 10.0.3.242 + A 10.0.3.243 + A 10.0.3.244 + A 10.0.3.245 + A 10.0.3.246 + A 10.0.3.247 + A 10.0.3.248 + A 10.0.3.249 + A 10.0.3.250 + A 10.0.3.251 + A 10.0.3.252 + A 10.0.3.253 + A 10.0.3.254 + A 10.0.3.255 + A 10.0.4.0 + A 10.0.4.1 + A 10.0.4.2 + A 10.0.4.3 + A 10.0.4.4 + A 10.0.4.5 + A 10.0.4.6 + A 10.0.4.7 + A 10.0.4.8 + A 10.0.4.9 + A 10.0.4.10 + A 10.0.4.11 + A 10.0.4.12 + A 10.0.4.13 + A 10.0.4.14 + A 10.0.4.15 + A 10.0.4.16 + A 10.0.4.17 + A 10.0.4.18 + A 10.0.4.19 + A 10.0.4.20 + A 10.0.4.21 + A 10.0.4.22 + A 10.0.4.23 + A 10.0.4.24 + A 10.0.4.25 + A 10.0.4.26 + A 10.0.4.27 + A 10.0.4.28 + A 10.0.4.29 + A 10.0.4.30 + A 10.0.4.31 + A 10.0.4.32 + A 10.0.4.33 + A 10.0.4.34 + A 10.0.4.35 + A 10.0.4.36 + A 10.0.4.37 + A 10.0.4.38 + A 10.0.4.39 + A 10.0.4.40 + A 10.0.4.41 + A 10.0.4.42 + A 10.0.4.43 + A 10.0.4.44 + A 10.0.4.45 + A 10.0.4.46 + A 10.0.4.47 + A 10.0.4.48 + A 10.0.4.49 + A 10.0.4.50 + A 10.0.4.51 + A 10.0.4.52 + A 10.0.4.53 + A 10.0.4.54 + A 10.0.4.55 + A 10.0.4.56 + A 10.0.4.57 + A 10.0.4.58 + A 10.0.4.59 + A 10.0.4.60 + A 10.0.4.61 + A 10.0.4.62 + A 10.0.4.63 + A 10.0.4.64 + A 10.0.4.65 + A 10.0.4.66 + A 10.0.4.67 + A 10.0.4.68 + A 10.0.4.69 + A 10.0.4.70 + A 10.0.4.71 + A 10.0.4.72 + A 10.0.4.73 + A 10.0.4.74 + A 10.0.4.75 + A 10.0.4.76 + A 10.0.4.77 + A 10.0.4.78 + A 10.0.4.79 + A 10.0.4.80 + A 10.0.4.81 + A 10.0.4.82 + A 10.0.4.83 + A 10.0.4.84 + A 10.0.4.85 + A 10.0.4.86 + A 10.0.4.87 + A 10.0.4.88 + A 10.0.4.89 + A 10.0.4.90 + A 10.0.4.91 + A 10.0.4.92 + A 10.0.4.93 + A 10.0.4.94 + A 10.0.4.95 + A 10.0.4.96 + A 10.0.4.97 + A 10.0.4.98 + A 10.0.4.99 + A 10.0.4.100 + A 10.0.4.101 + A 10.0.4.102 + A 10.0.4.103 + A 10.0.4.104 + A 10.0.4.105 + A 10.0.4.106 + A 10.0.4.107 + A 10.0.4.108 + A 10.0.4.109 + A 10.0.4.110 + A 10.0.4.111 + A 10.0.4.112 + A 10.0.4.113 + A 10.0.4.114 + A 10.0.4.115 + A 10.0.4.116 + A 10.0.4.117 + A 10.0.4.118 + A 10.0.4.119 + A 10.0.4.120 + A 10.0.4.121 + A 10.0.4.122 + A 10.0.4.123 + A 10.0.4.124 + A 10.0.4.125 + A 10.0.4.126 + A 10.0.4.127 + A 10.0.4.128 + A 10.0.4.129 + A 10.0.4.130 + A 10.0.4.131 + A 10.0.4.132 + A 10.0.4.133 + A 10.0.4.134 + A 10.0.4.135 + A 10.0.4.136 + A 10.0.4.137 + A 10.0.4.138 + A 10.0.4.139 + A 10.0.4.140 + A 10.0.4.141 + A 10.0.4.142 + A 10.0.4.143 + A 10.0.4.144 + A 10.0.4.145 + A 10.0.4.146 + A 10.0.4.147 + A 10.0.4.148 + A 10.0.4.149 + A 10.0.4.150 + A 10.0.4.151 + A 10.0.4.152 + A 10.0.4.153 + A 10.0.4.154 + A 10.0.4.155 + A 10.0.4.156 + A 10.0.4.157 + A 10.0.4.158 + A 10.0.4.159 + A 10.0.4.160 + A 10.0.4.161 + A 10.0.4.162 + A 10.0.4.163 + A 10.0.4.164 + A 10.0.4.165 + A 10.0.4.166 + A 10.0.4.167 + A 10.0.4.168 + A 10.0.4.169 + A 10.0.4.170 + A 10.0.4.171 + A 10.0.4.172 + A 10.0.4.173 + A 10.0.4.174 + A 10.0.4.175 + A 10.0.4.176 + A 10.0.4.177 + A 10.0.4.178 + A 10.0.4.179 + A 10.0.4.180 + A 10.0.4.181 + A 10.0.4.182 + A 10.0.4.183 + A 10.0.4.184 + A 10.0.4.185 + A 10.0.4.186 + A 10.0.4.187 + A 10.0.4.188 + A 10.0.4.189 + A 10.0.4.190 + A 10.0.4.191 + A 10.0.4.192 + A 10.0.4.193 + A 10.0.4.194 + A 10.0.4.195 + A 10.0.4.196 + A 10.0.4.197 + A 10.0.4.198 + A 10.0.4.199 + A 10.0.4.200 + A 10.0.4.201 + A 10.0.4.202 + A 10.0.4.203 + A 10.0.4.204 + A 10.0.4.205 + A 10.0.4.206 + A 10.0.4.207 + A 10.0.4.208 + A 10.0.4.209 + A 10.0.4.210 + A 10.0.4.211 + A 10.0.4.212 + A 10.0.4.213 + A 10.0.4.214 + A 10.0.4.215 + A 10.0.4.216 + A 10.0.4.217 + A 10.0.4.218 + A 10.0.4.219 + A 10.0.4.220 + A 10.0.4.221 + A 10.0.4.222 + A 10.0.4.223 + A 10.0.4.224 + A 10.0.4.225 + A 10.0.4.226 + A 10.0.4.227 + A 10.0.4.228 + A 10.0.4.229 + A 10.0.4.230 + A 10.0.4.231 + A 10.0.4.232 + A 10.0.4.233 + A 10.0.4.234 + A 10.0.4.235 + A 10.0.4.236 + A 10.0.4.237 + A 10.0.4.238 + A 10.0.4.239 + A 10.0.4.240 + A 10.0.4.241 + A 10.0.4.242 + A 10.0.4.243 + A 10.0.4.244 + A 10.0.4.245 + A 10.0.4.246 + A 10.0.4.247 + A 10.0.4.248 + A 10.0.4.249 + A 10.0.4.250 + A 10.0.4.251 + A 10.0.4.252 + A 10.0.4.253 + A 10.0.4.254 + A 10.0.4.255 + A 10.0.5.0 + A 10.0.5.1 + A 10.0.5.2 + A 10.0.5.3 + A 10.0.5.4 + A 10.0.5.5 + A 10.0.5.6 + A 10.0.5.7 + A 10.0.5.8 + A 10.0.5.9 + A 10.0.5.10 + A 10.0.5.11 + A 10.0.5.12 + A 10.0.5.13 + A 10.0.5.14 + A 10.0.5.15 + A 10.0.5.16 + A 10.0.5.17 + A 10.0.5.18 + A 10.0.5.19 + A 10.0.5.20 + A 10.0.5.21 + A 10.0.5.22 + A 10.0.5.23 + A 10.0.5.24 + A 10.0.5.25 + A 10.0.5.26 + A 10.0.5.27 + A 10.0.5.28 + A 10.0.5.29 + A 10.0.5.30 + A 10.0.5.31 + A 10.0.5.32 + A 10.0.5.33 + A 10.0.5.34 + A 10.0.5.35 + A 10.0.5.36 + A 10.0.5.37 + A 10.0.5.38 + A 10.0.5.39 + A 10.0.5.40 + A 10.0.5.41 + A 10.0.5.42 + A 10.0.5.43 + A 10.0.5.44 + A 10.0.5.45 + A 10.0.5.46 + A 10.0.5.47 + A 10.0.5.48 + A 10.0.5.49 + A 10.0.5.50 + A 10.0.5.51 + A 10.0.5.52 + A 10.0.5.53 + A 10.0.5.54 + A 10.0.5.55 + A 10.0.5.56 + A 10.0.5.57 + A 10.0.5.58 + A 10.0.5.59 + A 10.0.5.60 + A 10.0.5.61 + A 10.0.5.62 + A 10.0.5.63 + A 10.0.5.64 + A 10.0.5.65 + A 10.0.5.66 + A 10.0.5.67 + A 10.0.5.68 + A 10.0.5.69 + A 10.0.5.70 + A 10.0.5.71 + A 10.0.5.72 + A 10.0.5.73 + A 10.0.5.74 + A 10.0.5.75 + A 10.0.5.76 + A 10.0.5.77 + A 10.0.5.78 + A 10.0.5.79 + A 10.0.5.80 + A 10.0.5.81 + A 10.0.5.82 + A 10.0.5.83 + A 10.0.5.84 + A 10.0.5.85 + A 10.0.5.86 + A 10.0.5.87 + A 10.0.5.88 + A 10.0.5.89 + A 10.0.5.90 + A 10.0.5.91 + A 10.0.5.92 + A 10.0.5.93 + A 10.0.5.94 + A 10.0.5.95 + A 10.0.5.96 + A 10.0.5.97 + A 10.0.5.98 + A 10.0.5.99 + A 10.0.5.100 + A 10.0.5.101 + A 10.0.5.102 + A 10.0.5.103 + A 10.0.5.104 + A 10.0.5.105 + A 10.0.5.106 + A 10.0.5.107 + A 10.0.5.108 + A 10.0.5.109 + A 10.0.5.110 + A 10.0.5.111 + A 10.0.5.112 + A 10.0.5.113 + A 10.0.5.114 + A 10.0.5.115 + A 10.0.5.116 + A 10.0.5.117 + A 10.0.5.118 + A 10.0.5.119 + A 10.0.5.120 + A 10.0.5.121 + A 10.0.5.122 + A 10.0.5.123 + A 10.0.5.124 + A 10.0.5.125 + A 10.0.5.126 + A 10.0.5.127 + A 10.0.5.128 + A 10.0.5.129 + A 10.0.5.130 + A 10.0.5.131 + A 10.0.5.132 + A 10.0.5.133 + A 10.0.5.134 + A 10.0.5.135 + A 10.0.5.136 + A 10.0.5.137 + A 10.0.5.138 + A 10.0.5.139 + A 10.0.5.140 + A 10.0.5.141 + A 10.0.5.142 + A 10.0.5.143 + A 10.0.5.144 + A 10.0.5.145 + A 10.0.5.146 + A 10.0.5.147 + A 10.0.5.148 + A 10.0.5.149 + A 10.0.5.150 + A 10.0.5.151 + A 10.0.5.152 + A 10.0.5.153 + A 10.0.5.154 + A 10.0.5.155 + A 10.0.5.156 + A 10.0.5.157 + A 10.0.5.158 + A 10.0.5.159 + A 10.0.5.160 + A 10.0.5.161 + A 10.0.5.162 + A 10.0.5.163 + A 10.0.5.164 + A 10.0.5.165 + A 10.0.5.166 + A 10.0.5.167 + A 10.0.5.168 + A 10.0.5.169 + A 10.0.5.170 + A 10.0.5.171 + A 10.0.5.172 + A 10.0.5.173 + A 10.0.5.174 + A 10.0.5.175 + A 10.0.5.176 + A 10.0.5.177 + A 10.0.5.178 + A 10.0.5.179 + A 10.0.5.180 + A 10.0.5.181 + A 10.0.5.182 + A 10.0.5.183 + A 10.0.5.184 + A 10.0.5.185 + A 10.0.5.186 + A 10.0.5.187 + A 10.0.5.188 + A 10.0.5.189 + A 10.0.5.190 + A 10.0.5.191 + A 10.0.5.192 + A 10.0.5.193 + A 10.0.5.194 + A 10.0.5.195 + A 10.0.5.196 + A 10.0.5.197 + A 10.0.5.198 + A 10.0.5.199 + A 10.0.5.200 + A 10.0.5.201 + A 10.0.5.202 + A 10.0.5.203 + A 10.0.5.204 + A 10.0.5.205 + A 10.0.5.206 + A 10.0.5.207 + A 10.0.5.208 + A 10.0.5.209 + A 10.0.5.210 + A 10.0.5.211 + A 10.0.5.212 + A 10.0.5.213 + A 10.0.5.214 + A 10.0.5.215 + A 10.0.5.216 + A 10.0.5.217 + A 10.0.5.218 + A 10.0.5.219 + A 10.0.5.220 + A 10.0.5.221 + A 10.0.5.222 + A 10.0.5.223 + A 10.0.5.224 + A 10.0.5.225 + A 10.0.5.226 + A 10.0.5.227 + A 10.0.5.228 + A 10.0.5.229 + A 10.0.5.230 + A 10.0.5.231 + A 10.0.5.232 + A 10.0.5.233 + A 10.0.5.234 + A 10.0.5.235 + A 10.0.5.236 + A 10.0.5.237 + A 10.0.5.238 + A 10.0.5.239 + A 10.0.5.240 + A 10.0.5.241 + A 10.0.5.242 + A 10.0.5.243 + A 10.0.5.244 + A 10.0.5.245 + A 10.0.5.246 + A 10.0.5.247 + A 10.0.5.248 + A 10.0.5.249 + A 10.0.5.250 + A 10.0.5.251 + A 10.0.5.252 + A 10.0.5.253 + A 10.0.5.254 + A 10.0.5.255 + A 10.0.6.0 + A 10.0.6.1 + A 10.0.6.2 + A 10.0.6.3 + A 10.0.6.4 + A 10.0.6.5 + A 10.0.6.6 + A 10.0.6.7 + A 10.0.6.8 + A 10.0.6.9 + A 10.0.6.10 + A 10.0.6.11 + A 10.0.6.12 + A 10.0.6.13 + A 10.0.6.14 + A 10.0.6.15 + A 10.0.6.16 + A 10.0.6.17 + A 10.0.6.18 + A 10.0.6.19 + A 10.0.6.20 + A 10.0.6.21 + A 10.0.6.22 + A 10.0.6.23 + A 10.0.6.24 + A 10.0.6.25 + A 10.0.6.26 + A 10.0.6.27 + A 10.0.6.28 + A 10.0.6.29 + A 10.0.6.30 + A 10.0.6.31 + A 10.0.6.32 + A 10.0.6.33 + A 10.0.6.34 + A 10.0.6.35 + A 10.0.6.36 + A 10.0.6.37 + A 10.0.6.38 + A 10.0.6.39 + A 10.0.6.40 + A 10.0.6.41 + A 10.0.6.42 + A 10.0.6.43 + A 10.0.6.44 + A 10.0.6.45 + A 10.0.6.46 + A 10.0.6.47 + A 10.0.6.48 + A 10.0.6.49 + A 10.0.6.50 + A 10.0.6.51 + A 10.0.6.52 + A 10.0.6.53 + A 10.0.6.54 + A 10.0.6.55 + A 10.0.6.56 + A 10.0.6.57 + A 10.0.6.58 + A 10.0.6.59 + A 10.0.6.60 + A 10.0.6.61 + A 10.0.6.62 + A 10.0.6.63 + A 10.0.6.64 + A 10.0.6.65 + A 10.0.6.66 + A 10.0.6.67 + A 10.0.6.68 + A 10.0.6.69 + A 10.0.6.70 + A 10.0.6.71 + A 10.0.6.72 + A 10.0.6.73 + A 10.0.6.74 + A 10.0.6.75 + A 10.0.6.76 + A 10.0.6.77 + A 10.0.6.78 + A 10.0.6.79 + A 10.0.6.80 + A 10.0.6.81 + A 10.0.6.82 + A 10.0.6.83 + A 10.0.6.84 + A 10.0.6.85 + A 10.0.6.86 + A 10.0.6.87 + A 10.0.6.88 + A 10.0.6.89 + A 10.0.6.90 + A 10.0.6.91 + A 10.0.6.92 + A 10.0.6.93 + A 10.0.6.94 + A 10.0.6.95 + A 10.0.6.96 + A 10.0.6.97 + A 10.0.6.98 + A 10.0.6.99 + A 10.0.6.100 + A 10.0.6.101 + A 10.0.6.102 + A 10.0.6.103 + A 10.0.6.104 + A 10.0.6.105 + A 10.0.6.106 + A 10.0.6.107 + A 10.0.6.108 + A 10.0.6.109 + A 10.0.6.110 + A 10.0.6.111 + A 10.0.6.112 + A 10.0.6.113 + A 10.0.6.114 + A 10.0.6.115 + A 10.0.6.116 + A 10.0.6.117 + A 10.0.6.118 + A 10.0.6.119 + A 10.0.6.120 + A 10.0.6.121 + A 10.0.6.122 + A 10.0.6.123 + A 10.0.6.124 + A 10.0.6.125 + A 10.0.6.126 + A 10.0.6.127 + A 10.0.6.128 + A 10.0.6.129 + A 10.0.6.130 + A 10.0.6.131 + A 10.0.6.132 + A 10.0.6.133 + A 10.0.6.134 + A 10.0.6.135 + A 10.0.6.136 + A 10.0.6.137 + A 10.0.6.138 + A 10.0.6.139 + A 10.0.6.140 + A 10.0.6.141 + A 10.0.6.142 + A 10.0.6.143 + A 10.0.6.144 + A 10.0.6.145 + A 10.0.6.146 + A 10.0.6.147 + A 10.0.6.148 + A 10.0.6.149 + A 10.0.6.150 + A 10.0.6.151 + A 10.0.6.152 + A 10.0.6.153 + A 10.0.6.154 + A 10.0.6.155 + A 10.0.6.156 + A 10.0.6.157 + A 10.0.6.158 + A 10.0.6.159 + A 10.0.6.160 + A 10.0.6.161 + A 10.0.6.162 + A 10.0.6.163 + A 10.0.6.164 + A 10.0.6.165 + A 10.0.6.166 + A 10.0.6.167 + A 10.0.6.168 + A 10.0.6.169 + A 10.0.6.170 + A 10.0.6.171 + A 10.0.6.172 + A 10.0.6.173 + A 10.0.6.174 + A 10.0.6.175 + A 10.0.6.176 + A 10.0.6.177 + A 10.0.6.178 + A 10.0.6.179 + A 10.0.6.180 + A 10.0.6.181 + A 10.0.6.182 + A 10.0.6.183 + A 10.0.6.184 + A 10.0.6.185 + A 10.0.6.186 + A 10.0.6.187 + A 10.0.6.188 + A 10.0.6.189 + A 10.0.6.190 + A 10.0.6.191 + A 10.0.6.192 + A 10.0.6.193 + A 10.0.6.194 + A 10.0.6.195 + A 10.0.6.196 + A 10.0.6.197 + A 10.0.6.198 + A 10.0.6.199 + A 10.0.6.200 + A 10.0.6.201 + A 10.0.6.202 + A 10.0.6.203 + A 10.0.6.204 + A 10.0.6.205 + A 10.0.6.206 + A 10.0.6.207 + A 10.0.6.208 + A 10.0.6.209 + A 10.0.6.210 + A 10.0.6.211 + A 10.0.6.212 + A 10.0.6.213 + A 10.0.6.214 + A 10.0.6.215 + A 10.0.6.216 + A 10.0.6.217 + A 10.0.6.218 + A 10.0.6.219 + A 10.0.6.220 + A 10.0.6.221 + A 10.0.6.222 + A 10.0.6.223 + A 10.0.6.224 + A 10.0.6.225 + A 10.0.6.226 + A 10.0.6.227 + A 10.0.6.228 + A 10.0.6.229 + A 10.0.6.230 + A 10.0.6.231 + A 10.0.6.232 + A 10.0.6.233 + A 10.0.6.234 + A 10.0.6.235 + A 10.0.6.236 + A 10.0.6.237 + A 10.0.6.238 + A 10.0.6.239 + A 10.0.6.240 + A 10.0.6.241 + A 10.0.6.242 + A 10.0.6.243 + A 10.0.6.244 + A 10.0.6.245 + A 10.0.6.246 + A 10.0.6.247 + A 10.0.6.248 + A 10.0.6.249 + A 10.0.6.250 + A 10.0.6.251 + A 10.0.6.252 + A 10.0.6.253 + A 10.0.6.254 + A 10.0.6.255 + A 10.0.7.0 + A 10.0.7.1 + A 10.0.7.2 + A 10.0.7.3 + A 10.0.7.4 + A 10.0.7.5 + A 10.0.7.6 + A 10.0.7.7 + A 10.0.7.8 + A 10.0.7.9 + A 10.0.7.10 + A 10.0.7.11 + A 10.0.7.12 + A 10.0.7.13 + A 10.0.7.14 + A 10.0.7.15 + A 10.0.7.16 + A 10.0.7.17 + A 10.0.7.18 + A 10.0.7.19 + A 10.0.7.20 + A 10.0.7.21 + A 10.0.7.22 + A 10.0.7.23 + A 10.0.7.24 + A 10.0.7.25 + A 10.0.7.26 + A 10.0.7.27 + A 10.0.7.28 + A 10.0.7.29 + A 10.0.7.30 + A 10.0.7.31 + A 10.0.7.32 + A 10.0.7.33 + A 10.0.7.34 + A 10.0.7.35 + A 10.0.7.36 + A 10.0.7.37 + A 10.0.7.38 + A 10.0.7.39 + A 10.0.7.40 + A 10.0.7.41 + A 10.0.7.42 + A 10.0.7.43 + A 10.0.7.44 + A 10.0.7.45 + A 10.0.7.46 + A 10.0.7.47 + A 10.0.7.48 + A 10.0.7.49 + A 10.0.7.50 + A 10.0.7.51 + A 10.0.7.52 + A 10.0.7.53 + A 10.0.7.54 + A 10.0.7.55 + A 10.0.7.56 + A 10.0.7.57 + A 10.0.7.58 + A 10.0.7.59 + A 10.0.7.60 + A 10.0.7.61 + A 10.0.7.62 + A 10.0.7.63 + A 10.0.7.64 + A 10.0.7.65 + A 10.0.7.66 + A 10.0.7.67 + A 10.0.7.68 + A 10.0.7.69 + A 10.0.7.70 + A 10.0.7.71 + A 10.0.7.72 + A 10.0.7.73 + A 10.0.7.74 + A 10.0.7.75 + A 10.0.7.76 + A 10.0.7.77 + A 10.0.7.78 + A 10.0.7.79 + A 10.0.7.80 + A 10.0.7.81 + A 10.0.7.82 + A 10.0.7.83 + A 10.0.7.84 + A 10.0.7.85 + A 10.0.7.86 + A 10.0.7.87 + A 10.0.7.88 + A 10.0.7.89 + A 10.0.7.90 + A 10.0.7.91 + A 10.0.7.92 + A 10.0.7.93 + A 10.0.7.94 + A 10.0.7.95 + A 10.0.7.96 + A 10.0.7.97 + A 10.0.7.98 + A 10.0.7.99 + A 10.0.7.100 + A 10.0.7.101 + A 10.0.7.102 + A 10.0.7.103 + A 10.0.7.104 + A 10.0.7.105 + A 10.0.7.106 + A 10.0.7.107 + A 10.0.7.108 + A 10.0.7.109 + A 10.0.7.110 + A 10.0.7.111 + A 10.0.7.112 + A 10.0.7.113 + A 10.0.7.114 + A 10.0.7.115 + A 10.0.7.116 + A 10.0.7.117 + A 10.0.7.118 + A 10.0.7.119 + A 10.0.7.120 + A 10.0.7.121 + A 10.0.7.122 + A 10.0.7.123 + A 10.0.7.124 + A 10.0.7.125 + A 10.0.7.126 + A 10.0.7.127 + A 10.0.7.128 + A 10.0.7.129 + A 10.0.7.130 + A 10.0.7.131 + A 10.0.7.132 + A 10.0.7.133 + A 10.0.7.134 + A 10.0.7.135 + A 10.0.7.136 + A 10.0.7.137 + A 10.0.7.138 + A 10.0.7.139 + A 10.0.7.140 + A 10.0.7.141 + A 10.0.7.142 + A 10.0.7.143 + A 10.0.7.144 + A 10.0.7.145 + A 10.0.7.146 + A 10.0.7.147 + A 10.0.7.148 + A 10.0.7.149 + A 10.0.7.150 + A 10.0.7.151 + A 10.0.7.152 + A 10.0.7.153 + A 10.0.7.154 + A 10.0.7.155 + A 10.0.7.156 + A 10.0.7.157 + A 10.0.7.158 + A 10.0.7.159 + A 10.0.7.160 + A 10.0.7.161 + A 10.0.7.162 + A 10.0.7.163 + A 10.0.7.164 + A 10.0.7.165 + A 10.0.7.166 + A 10.0.7.167 + A 10.0.7.168 + A 10.0.7.169 + A 10.0.7.170 + A 10.0.7.171 + A 10.0.7.172 + A 10.0.7.173 + A 10.0.7.174 + A 10.0.7.175 + A 10.0.7.176 + A 10.0.7.177 + A 10.0.7.178 + A 10.0.7.179 + A 10.0.7.180 + A 10.0.7.181 + A 10.0.7.182 + A 10.0.7.183 + A 10.0.7.184 + A 10.0.7.185 + A 10.0.7.186 + A 10.0.7.187 + A 10.0.7.188 + A 10.0.7.189 + A 10.0.7.190 + A 10.0.7.191 + A 10.0.7.192 + A 10.0.7.193 + A 10.0.7.194 + A 10.0.7.195 + A 10.0.7.196 + A 10.0.7.197 + A 10.0.7.198 + A 10.0.7.199 + A 10.0.7.200 + A 10.0.7.201 + A 10.0.7.202 + A 10.0.7.203 + A 10.0.7.204 + A 10.0.7.205 + A 10.0.7.206 + A 10.0.7.207 + A 10.0.7.208 + A 10.0.7.209 + A 10.0.7.210 + A 10.0.7.211 + A 10.0.7.212 + A 10.0.7.213 + A 10.0.7.214 + A 10.0.7.215 + A 10.0.7.216 + A 10.0.7.217 + A 10.0.7.218 + A 10.0.7.219 + A 10.0.7.220 + A 10.0.7.221 + A 10.0.7.222 + A 10.0.7.223 + A 10.0.7.224 + A 10.0.7.225 + A 10.0.7.226 + A 10.0.7.227 + A 10.0.7.228 + A 10.0.7.229 + A 10.0.7.230 + A 10.0.7.231 + A 10.0.7.232 + A 10.0.7.233 + A 10.0.7.234 + A 10.0.7.235 + A 10.0.7.236 + A 10.0.7.237 + A 10.0.7.238 + A 10.0.7.239 + A 10.0.7.240 + A 10.0.7.241 + A 10.0.7.242 + A 10.0.7.243 + A 10.0.7.244 + A 10.0.7.245 + A 10.0.7.246 + A 10.0.7.247 + A 10.0.7.248 + A 10.0.7.249 + A 10.0.7.250 + A 10.0.7.251 + A 10.0.7.252 + A 10.0.7.253 + A 10.0.7.254 + A 10.0.7.255 + A 10.0.8.0 + A 10.0.8.1 + A 10.0.8.2 + A 10.0.8.3 + A 10.0.8.4 + A 10.0.8.5 + A 10.0.8.6 + A 10.0.8.7 + A 10.0.8.8 + A 10.0.8.9 + A 10.0.8.10 + A 10.0.8.11 + A 10.0.8.12 + A 10.0.8.13 + A 10.0.8.14 + A 10.0.8.15 + A 10.0.8.16 + A 10.0.8.17 + A 10.0.8.18 + A 10.0.8.19 + A 10.0.8.20 + A 10.0.8.21 + A 10.0.8.22 + A 10.0.8.23 + A 10.0.8.24 + A 10.0.8.25 + A 10.0.8.26 + A 10.0.8.27 + A 10.0.8.28 + A 10.0.8.29 + A 10.0.8.30 + A 10.0.8.31 + A 10.0.8.32 + A 10.0.8.33 + A 10.0.8.34 + A 10.0.8.35 + A 10.0.8.36 + A 10.0.8.37 + A 10.0.8.38 + A 10.0.8.39 + A 10.0.8.40 + A 10.0.8.41 + A 10.0.8.42 + A 10.0.8.43 + A 10.0.8.44 + A 10.0.8.45 + A 10.0.8.46 + A 10.0.8.47 + A 10.0.8.48 + A 10.0.8.49 + A 10.0.8.50 + A 10.0.8.51 + A 10.0.8.52 + A 10.0.8.53 + A 10.0.8.54 + A 10.0.8.55 + A 10.0.8.56 + A 10.0.8.57 + A 10.0.8.58 + A 10.0.8.59 + A 10.0.8.60 + A 10.0.8.61 + A 10.0.8.62 + A 10.0.8.63 + A 10.0.8.64 + A 10.0.8.65 + A 10.0.8.66 + A 10.0.8.67 + A 10.0.8.68 + A 10.0.8.69 + A 10.0.8.70 + A 10.0.8.71 + A 10.0.8.72 + A 10.0.8.73 + A 10.0.8.74 + A 10.0.8.75 + A 10.0.8.76 + A 10.0.8.77 + A 10.0.8.78 + A 10.0.8.79 + A 10.0.8.80 + A 10.0.8.81 + A 10.0.8.82 + A 10.0.8.83 + A 10.0.8.84 + A 10.0.8.85 + A 10.0.8.86 + A 10.0.8.87 + A 10.0.8.88 + A 10.0.8.89 + A 10.0.8.90 + A 10.0.8.91 + A 10.0.8.92 + A 10.0.8.93 + A 10.0.8.94 + A 10.0.8.95 + A 10.0.8.96 + A 10.0.8.97 + A 10.0.8.98 + A 10.0.8.99 + A 10.0.8.100 + A 10.0.8.101 + A 10.0.8.102 + A 10.0.8.103 + A 10.0.8.104 + A 10.0.8.105 + A 10.0.8.106 + A 10.0.8.107 + A 10.0.8.108 + A 10.0.8.109 + A 10.0.8.110 + A 10.0.8.111 + A 10.0.8.112 + A 10.0.8.113 + A 10.0.8.114 + A 10.0.8.115 + A 10.0.8.116 + A 10.0.8.117 + A 10.0.8.118 + A 10.0.8.119 + A 10.0.8.120 + A 10.0.8.121 + A 10.0.8.122 + A 10.0.8.123 + A 10.0.8.124 + A 10.0.8.125 + A 10.0.8.126 + A 10.0.8.127 + A 10.0.8.128 + A 10.0.8.129 + A 10.0.8.130 + A 10.0.8.131 + A 10.0.8.132 + A 10.0.8.133 + A 10.0.8.134 + A 10.0.8.135 + A 10.0.8.136 + A 10.0.8.137 + A 10.0.8.138 + A 10.0.8.139 + A 10.0.8.140 + A 10.0.8.141 + A 10.0.8.142 + A 10.0.8.143 + A 10.0.8.144 + A 10.0.8.145 + A 10.0.8.146 + A 10.0.8.147 + A 10.0.8.148 + A 10.0.8.149 + A 10.0.8.150 + A 10.0.8.151 + A 10.0.8.152 + A 10.0.8.153 + A 10.0.8.154 + A 10.0.8.155 + A 10.0.8.156 + A 10.0.8.157 + A 10.0.8.158 + A 10.0.8.159 + A 10.0.8.160 + A 10.0.8.161 + A 10.0.8.162 + A 10.0.8.163 + A 10.0.8.164 + A 10.0.8.165 + A 10.0.8.166 + A 10.0.8.167 + A 10.0.8.168 + A 10.0.8.169 + A 10.0.8.170 + A 10.0.8.171 + A 10.0.8.172 + A 10.0.8.173 + A 10.0.8.174 + A 10.0.8.175 + A 10.0.8.176 + A 10.0.8.177 + A 10.0.8.178 + A 10.0.8.179 + A 10.0.8.180 + A 10.0.8.181 + A 10.0.8.182 + A 10.0.8.183 + A 10.0.8.184 + A 10.0.8.185 + A 10.0.8.186 + A 10.0.8.187 + A 10.0.8.188 + A 10.0.8.189 + A 10.0.8.190 + A 10.0.8.191 + A 10.0.8.192 + A 10.0.8.193 + A 10.0.8.194 + A 10.0.8.195 + A 10.0.8.196 + A 10.0.8.197 + A 10.0.8.198 + A 10.0.8.199 + A 10.0.8.200 + A 10.0.8.201 + A 10.0.8.202 + A 10.0.8.203 + A 10.0.8.204 + A 10.0.8.205 + A 10.0.8.206 + A 10.0.8.207 + A 10.0.8.208 + A 10.0.8.209 + A 10.0.8.210 + A 10.0.8.211 + A 10.0.8.212 + A 10.0.8.213 + A 10.0.8.214 + A 10.0.8.215 + A 10.0.8.216 + A 10.0.8.217 + A 10.0.8.218 + A 10.0.8.219 + A 10.0.8.220 + A 10.0.8.221 + A 10.0.8.222 + A 10.0.8.223 + A 10.0.8.224 + A 10.0.8.225 + A 10.0.8.226 + A 10.0.8.227 + A 10.0.8.228 + A 10.0.8.229 + A 10.0.8.230 + A 10.0.8.231 + A 10.0.8.232 + A 10.0.8.233 + A 10.0.8.234 + A 10.0.8.235 + A 10.0.8.236 + A 10.0.8.237 + A 10.0.8.238 + A 10.0.8.239 + A 10.0.8.240 + A 10.0.8.241 + A 10.0.8.242 + A 10.0.8.243 + A 10.0.8.244 + A 10.0.8.245 + A 10.0.8.246 + A 10.0.8.247 + A 10.0.8.248 + A 10.0.8.249 + A 10.0.8.250 + A 10.0.8.251 + A 10.0.8.252 + A 10.0.8.253 + A 10.0.8.254 + A 10.0.8.255 + A 10.0.9.0 + A 10.0.9.1 + A 10.0.9.2 + A 10.0.9.3 + A 10.0.9.4 + A 10.0.9.5 + A 10.0.9.6 + A 10.0.9.7 + A 10.0.9.8 + A 10.0.9.9 + A 10.0.9.10 + A 10.0.9.11 + A 10.0.9.12 + A 10.0.9.13 + A 10.0.9.14 + A 10.0.9.15 + A 10.0.9.16 + A 10.0.9.17 + A 10.0.9.18 + A 10.0.9.19 + A 10.0.9.20 + A 10.0.9.21 + A 10.0.9.22 + A 10.0.9.23 + A 10.0.9.24 + A 10.0.9.25 + A 10.0.9.26 + A 10.0.9.27 + A 10.0.9.28 + A 10.0.9.29 + A 10.0.9.30 + A 10.0.9.31 + A 10.0.9.32 + A 10.0.9.33 + A 10.0.9.34 + A 10.0.9.35 + A 10.0.9.36 + A 10.0.9.37 + A 10.0.9.38 + A 10.0.9.39 + A 10.0.9.40 + A 10.0.9.41 + A 10.0.9.42 + A 10.0.9.43 + A 10.0.9.44 + A 10.0.9.45 + A 10.0.9.46 + A 10.0.9.47 + A 10.0.9.48 + A 10.0.9.49 + A 10.0.9.50 + A 10.0.9.51 + A 10.0.9.52 + A 10.0.9.53 + A 10.0.9.54 + A 10.0.9.55 + A 10.0.9.56 + A 10.0.9.57 + A 10.0.9.58 + A 10.0.9.59 + A 10.0.9.60 + A 10.0.9.61 + A 10.0.9.62 + A 10.0.9.63 + A 10.0.9.64 + A 10.0.9.65 + A 10.0.9.66 + A 10.0.9.67 + A 10.0.9.68 + A 10.0.9.69 + A 10.0.9.70 + A 10.0.9.71 + A 10.0.9.72 + A 10.0.9.73 + A 10.0.9.74 + A 10.0.9.75 + A 10.0.9.76 + A 10.0.9.77 + A 10.0.9.78 + A 10.0.9.79 + A 10.0.9.80 + A 10.0.9.81 + A 10.0.9.82 + A 10.0.9.83 + A 10.0.9.84 + A 10.0.9.85 + A 10.0.9.86 + A 10.0.9.87 + A 10.0.9.88 + A 10.0.9.89 + A 10.0.9.90 + A 10.0.9.91 + A 10.0.9.92 + A 10.0.9.93 + A 10.0.9.94 + A 10.0.9.95 + A 10.0.9.96 + A 10.0.9.97 + A 10.0.9.98 + A 10.0.9.99 + A 10.0.9.100 + A 10.0.9.101 + A 10.0.9.102 + A 10.0.9.103 + A 10.0.9.104 + A 10.0.9.105 + A 10.0.9.106 + A 10.0.9.107 + A 10.0.9.108 + A 10.0.9.109 + A 10.0.9.110 + A 10.0.9.111 + A 10.0.9.112 + A 10.0.9.113 + A 10.0.9.114 + A 10.0.9.115 + A 10.0.9.116 + A 10.0.9.117 + A 10.0.9.118 + A 10.0.9.119 + A 10.0.9.120 + A 10.0.9.121 + A 10.0.9.122 + A 10.0.9.123 + A 10.0.9.124 + A 10.0.9.125 + A 10.0.9.126 + A 10.0.9.127 + A 10.0.9.128 + A 10.0.9.129 + A 10.0.9.130 + A 10.0.9.131 + A 10.0.9.132 + A 10.0.9.133 + A 10.0.9.134 + A 10.0.9.135 + A 10.0.9.136 + A 10.0.9.137 + A 10.0.9.138 + A 10.0.9.139 + A 10.0.9.140 + A 10.0.9.141 + A 10.0.9.142 + A 10.0.9.143 + A 10.0.9.144 + A 10.0.9.145 + A 10.0.9.146 + A 10.0.9.147 + A 10.0.9.148 + A 10.0.9.149 + A 10.0.9.150 + A 10.0.9.151 + A 10.0.9.152 + A 10.0.9.153 + A 10.0.9.154 + A 10.0.9.155 + A 10.0.9.156 + A 10.0.9.157 + A 10.0.9.158 + A 10.0.9.159 + A 10.0.9.160 + A 10.0.9.161 + A 10.0.9.162 + A 10.0.9.163 + A 10.0.9.164 + A 10.0.9.165 + A 10.0.9.166 + A 10.0.9.167 + A 10.0.9.168 + A 10.0.9.169 + A 10.0.9.170 + A 10.0.9.171 + A 10.0.9.172 + A 10.0.9.173 + A 10.0.9.174 + A 10.0.9.175 + A 10.0.9.176 + A 10.0.9.177 + A 10.0.9.178 + A 10.0.9.179 + A 10.0.9.180 + A 10.0.9.181 + A 10.0.9.182 + A 10.0.9.183 + A 10.0.9.184 + A 10.0.9.185 + A 10.0.9.186 + A 10.0.9.187 + A 10.0.9.188 + A 10.0.9.189 + A 10.0.9.190 + A 10.0.9.191 + A 10.0.9.192 + A 10.0.9.193 + A 10.0.9.194 + A 10.0.9.195 + A 10.0.9.196 + A 10.0.9.197 + A 10.0.9.198 + A 10.0.9.199 + A 10.0.9.200 + A 10.0.9.201 + A 10.0.9.202 + A 10.0.9.203 + A 10.0.9.204 + A 10.0.9.205 + A 10.0.9.206 + A 10.0.9.207 + A 10.0.9.208 + A 10.0.9.209 + A 10.0.9.210 + A 10.0.9.211 + A 10.0.9.212 + A 10.0.9.213 + A 10.0.9.214 + A 10.0.9.215 + A 10.0.9.216 + A 10.0.9.217 + A 10.0.9.218 + A 10.0.9.219 + A 10.0.9.220 + A 10.0.9.221 + A 10.0.9.222 + A 10.0.9.223 + A 10.0.9.224 + A 10.0.9.225 + A 10.0.9.226 + A 10.0.9.227 + A 10.0.9.228 + A 10.0.9.229 + A 10.0.9.230 + A 10.0.9.231 + A 10.0.9.232 + A 10.0.9.233 + A 10.0.9.234 + A 10.0.9.235 + A 10.0.9.236 + A 10.0.9.237 + A 10.0.9.238 + A 10.0.9.239 + A 10.0.9.240 + A 10.0.9.241 + A 10.0.9.242 + A 10.0.9.243 + A 10.0.9.244 + A 10.0.9.245 + A 10.0.9.246 + A 10.0.9.247 + A 10.0.9.248 + A 10.0.9.249 + A 10.0.9.250 + A 10.0.9.251 + A 10.0.9.252 + A 10.0.9.253 + A 10.0.9.254 + A 10.0.9.255 + A 10.0.10.0 + A 10.0.10.1 + A 10.0.10.2 + A 10.0.10.3 + A 10.0.10.4 + A 10.0.10.5 + A 10.0.10.6 + A 10.0.10.7 + A 10.0.10.8 + A 10.0.10.9 + A 10.0.10.10 + A 10.0.10.11 + A 10.0.10.12 + A 10.0.10.13 + A 10.0.10.14 + A 10.0.10.15 + A 10.0.10.16 + A 10.0.10.17 + A 10.0.10.18 + A 10.0.10.19 + A 10.0.10.20 + A 10.0.10.21 + A 10.0.10.22 + A 10.0.10.23 + A 10.0.10.24 + A 10.0.10.25 + A 10.0.10.26 + A 10.0.10.27 + A 10.0.10.28 + A 10.0.10.29 + A 10.0.10.30 + A 10.0.10.31 + A 10.0.10.32 + A 10.0.10.33 + A 10.0.10.34 + A 10.0.10.35 + A 10.0.10.36 + A 10.0.10.37 + A 10.0.10.38 + A 10.0.10.39 + A 10.0.10.40 + A 10.0.10.41 + A 10.0.10.42 + A 10.0.10.43 + A 10.0.10.44 + A 10.0.10.45 + A 10.0.10.46 + A 10.0.10.47 + A 10.0.10.48 + A 10.0.10.49 + A 10.0.10.50 + A 10.0.10.51 + A 10.0.10.52 + A 10.0.10.53 + A 10.0.10.54 + A 10.0.10.55 + A 10.0.10.56 + A 10.0.10.57 + A 10.0.10.58 + A 10.0.10.59 + A 10.0.10.60 + A 10.0.10.61 + A 10.0.10.62 + A 10.0.10.63 + A 10.0.10.64 + A 10.0.10.65 + A 10.0.10.66 + A 10.0.10.67 + A 10.0.10.68 + A 10.0.10.69 + A 10.0.10.70 + A 10.0.10.71 + A 10.0.10.72 + A 10.0.10.73 + A 10.0.10.74 + A 10.0.10.75 + A 10.0.10.76 + A 10.0.10.77 + A 10.0.10.78 + A 10.0.10.79 + A 10.0.10.80 + A 10.0.10.81 + A 10.0.10.82 + A 10.0.10.83 + A 10.0.10.84 + A 10.0.10.85 + A 10.0.10.86 + A 10.0.10.87 + A 10.0.10.88 + A 10.0.10.89 + A 10.0.10.90 + A 10.0.10.91 + A 10.0.10.92 + A 10.0.10.93 + A 10.0.10.94 + A 10.0.10.95 + A 10.0.10.96 + A 10.0.10.97 + A 10.0.10.98 + A 10.0.10.99 + A 10.0.10.100 + A 10.0.10.101 + A 10.0.10.102 + A 10.0.10.103 + A 10.0.10.104 + A 10.0.10.105 + A 10.0.10.106 + A 10.0.10.107 + A 10.0.10.108 + A 10.0.10.109 + A 10.0.10.110 + A 10.0.10.111 + A 10.0.10.112 + A 10.0.10.113 + A 10.0.10.114 + A 10.0.10.115 + A 10.0.10.116 + A 10.0.10.117 + A 10.0.10.118 + A 10.0.10.119 + A 10.0.10.120 + A 10.0.10.121 + A 10.0.10.122 + A 10.0.10.123 + A 10.0.10.124 + A 10.0.10.125 + A 10.0.10.126 + A 10.0.10.127 + A 10.0.10.128 + A 10.0.10.129 + A 10.0.10.130 + A 10.0.10.131 + A 10.0.10.132 + A 10.0.10.133 + A 10.0.10.134 + A 10.0.10.135 + A 10.0.10.136 + A 10.0.10.137 + A 10.0.10.138 + A 10.0.10.139 + A 10.0.10.140 + A 10.0.10.141 + A 10.0.10.142 + A 10.0.10.143 + A 10.0.10.144 + A 10.0.10.145 + A 10.0.10.146 + A 10.0.10.147 + A 10.0.10.148 + A 10.0.10.149 + A 10.0.10.150 + A 10.0.10.151 + A 10.0.10.152 + A 10.0.10.153 + A 10.0.10.154 + A 10.0.10.155 + A 10.0.10.156 + A 10.0.10.157 + A 10.0.10.158 + A 10.0.10.159 + A 10.0.10.160 + A 10.0.10.161 + A 10.0.10.162 + A 10.0.10.163 + A 10.0.10.164 + A 10.0.10.165 + A 10.0.10.166 + A 10.0.10.167 + A 10.0.10.168 + A 10.0.10.169 + A 10.0.10.170 + A 10.0.10.171 + A 10.0.10.172 + A 10.0.10.173 + A 10.0.10.174 + A 10.0.10.175 + A 10.0.10.176 + A 10.0.10.177 + A 10.0.10.178 + A 10.0.10.179 + A 10.0.10.180 + A 10.0.10.181 + A 10.0.10.182 + A 10.0.10.183 + A 10.0.10.184 + A 10.0.10.185 + A 10.0.10.186 + A 10.0.10.187 + A 10.0.10.188 + A 10.0.10.189 + A 10.0.10.190 + A 10.0.10.191 + A 10.0.10.192 + A 10.0.10.193 + A 10.0.10.194 + A 10.0.10.195 + A 10.0.10.196 + A 10.0.10.197 + A 10.0.10.198 + A 10.0.10.199 + A 10.0.10.200 + A 10.0.10.201 + A 10.0.10.202 + A 10.0.10.203 + A 10.0.10.204 + A 10.0.10.205 + A 10.0.10.206 + A 10.0.10.207 + A 10.0.10.208 + A 10.0.10.209 + A 10.0.10.210 + A 10.0.10.211 + A 10.0.10.212 + A 10.0.10.213 + A 10.0.10.214 + A 10.0.10.215 + A 10.0.10.216 + A 10.0.10.217 + A 10.0.10.218 + A 10.0.10.219 + A 10.0.10.220 + A 10.0.10.221 + A 10.0.10.222 + A 10.0.10.223 + A 10.0.10.224 + A 10.0.10.225 + A 10.0.10.226 + A 10.0.10.227 + A 10.0.10.228 + A 10.0.10.229 + A 10.0.10.230 + A 10.0.10.231 + A 10.0.10.232 + A 10.0.10.233 + A 10.0.10.234 + A 10.0.10.235 + A 10.0.10.236 + A 10.0.10.237 + A 10.0.10.238 + A 10.0.10.239 + A 10.0.10.240 + A 10.0.10.241 + A 10.0.10.242 + A 10.0.10.243 + A 10.0.10.244 + A 10.0.10.245 + A 10.0.10.246 + A 10.0.10.247 + A 10.0.10.248 + A 10.0.10.249 + A 10.0.10.250 + A 10.0.10.251 + A 10.0.10.252 + A 10.0.10.253 + A 10.0.10.254 + A 10.0.10.255 + A 10.0.11.0 + A 10.0.11.1 + A 10.0.11.2 + A 10.0.11.3 + A 10.0.11.4 + A 10.0.11.5 + A 10.0.11.6 + A 10.0.11.7 + A 10.0.11.8 + A 10.0.11.9 + A 10.0.11.10 + A 10.0.11.11 + A 10.0.11.12 + A 10.0.11.13 + A 10.0.11.14 + A 10.0.11.15 + A 10.0.11.16 + A 10.0.11.17 + A 10.0.11.18 + A 10.0.11.19 + A 10.0.11.20 + A 10.0.11.21 + A 10.0.11.22 + A 10.0.11.23 + A 10.0.11.24 + A 10.0.11.25 + A 10.0.11.26 + A 10.0.11.27 + A 10.0.11.28 + A 10.0.11.29 + A 10.0.11.30 + A 10.0.11.31 + A 10.0.11.32 + A 10.0.11.33 + A 10.0.11.34 + A 10.0.11.35 + A 10.0.11.36 + A 10.0.11.37 + A 10.0.11.38 + A 10.0.11.39 + A 10.0.11.40 + A 10.0.11.41 + A 10.0.11.42 + A 10.0.11.43 + A 10.0.11.44 + A 10.0.11.45 + A 10.0.11.46 + A 10.0.11.47 + A 10.0.11.48 + A 10.0.11.49 + A 10.0.11.50 + A 10.0.11.51 + A 10.0.11.52 + A 10.0.11.53 + A 10.0.11.54 + A 10.0.11.55 + A 10.0.11.56 + A 10.0.11.57 + A 10.0.11.58 + A 10.0.11.59 + A 10.0.11.60 + A 10.0.11.61 + A 10.0.11.62 + A 10.0.11.63 + A 10.0.11.64 + A 10.0.11.65 + A 10.0.11.66 + A 10.0.11.67 + A 10.0.11.68 + A 10.0.11.69 + A 10.0.11.70 + A 10.0.11.71 + A 10.0.11.72 + A 10.0.11.73 + A 10.0.11.74 + A 10.0.11.75 + A 10.0.11.76 + A 10.0.11.77 + A 10.0.11.78 + A 10.0.11.79 + A 10.0.11.80 + A 10.0.11.81 + A 10.0.11.82 + A 10.0.11.83 + A 10.0.11.84 + A 10.0.11.85 + A 10.0.11.86 + A 10.0.11.87 + A 10.0.11.88 + A 10.0.11.89 + A 10.0.11.90 + A 10.0.11.91 + A 10.0.11.92 + A 10.0.11.93 + A 10.0.11.94 + A 10.0.11.95 + A 10.0.11.96 + A 10.0.11.97 + A 10.0.11.98 + A 10.0.11.99 + A 10.0.11.100 + A 10.0.11.101 + A 10.0.11.102 + A 10.0.11.103 + A 10.0.11.104 + A 10.0.11.105 + A 10.0.11.106 + A 10.0.11.107 + A 10.0.11.108 + A 10.0.11.109 + A 10.0.11.110 + A 10.0.11.111 + A 10.0.11.112 + A 10.0.11.113 + A 10.0.11.114 + A 10.0.11.115 + A 10.0.11.116 + A 10.0.11.117 + A 10.0.11.118 + A 10.0.11.119 + A 10.0.11.120 + A 10.0.11.121 + A 10.0.11.122 + A 10.0.11.123 + A 10.0.11.124 + A 10.0.11.125 + A 10.0.11.126 + A 10.0.11.127 + A 10.0.11.128 + A 10.0.11.129 + A 10.0.11.130 + A 10.0.11.131 + A 10.0.11.132 + A 10.0.11.133 + A 10.0.11.134 + A 10.0.11.135 + A 10.0.11.136 + A 10.0.11.137 + A 10.0.11.138 + A 10.0.11.139 + A 10.0.11.140 + A 10.0.11.141 + A 10.0.11.142 + A 10.0.11.143 + A 10.0.11.144 + A 10.0.11.145 + A 10.0.11.146 + A 10.0.11.147 + A 10.0.11.148 + A 10.0.11.149 + A 10.0.11.150 + A 10.0.11.151 + A 10.0.11.152 + A 10.0.11.153 + A 10.0.11.154 + A 10.0.11.155 + A 10.0.11.156 + A 10.0.11.157 + A 10.0.11.158 + A 10.0.11.159 + A 10.0.11.160 + A 10.0.11.161 + A 10.0.11.162 + A 10.0.11.163 + A 10.0.11.164 + A 10.0.11.165 + A 10.0.11.166 + A 10.0.11.167 + A 10.0.11.168 + A 10.0.11.169 + A 10.0.11.170 + A 10.0.11.171 + A 10.0.11.172 + A 10.0.11.173 + A 10.0.11.174 + A 10.0.11.175 + A 10.0.11.176 + A 10.0.11.177 + A 10.0.11.178 + A 10.0.11.179 + A 10.0.11.180 + A 10.0.11.181 + A 10.0.11.182 + A 10.0.11.183 +4000 A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 + A 10.0.3.232 + A 10.0.3.233 + A 10.0.3.234 + A 10.0.3.235 + A 10.0.3.236 + A 10.0.3.237 + A 10.0.3.238 + A 10.0.3.239 + A 10.0.3.240 + A 10.0.3.241 + A 10.0.3.242 + A 10.0.3.243 + A 10.0.3.244 + A 10.0.3.245 + A 10.0.3.246 + A 10.0.3.247 + A 10.0.3.248 + A 10.0.3.249 + A 10.0.3.250 + A 10.0.3.251 + A 10.0.3.252 + A 10.0.3.253 + A 10.0.3.254 + A 10.0.3.255 + A 10.0.4.0 + A 10.0.4.1 + A 10.0.4.2 + A 10.0.4.3 + A 10.0.4.4 + A 10.0.4.5 + A 10.0.4.6 + A 10.0.4.7 + A 10.0.4.8 + A 10.0.4.9 + A 10.0.4.10 + A 10.0.4.11 + A 10.0.4.12 + A 10.0.4.13 + A 10.0.4.14 + A 10.0.4.15 + A 10.0.4.16 + A 10.0.4.17 + A 10.0.4.18 + A 10.0.4.19 + A 10.0.4.20 + A 10.0.4.21 + A 10.0.4.22 + A 10.0.4.23 + A 10.0.4.24 + A 10.0.4.25 + A 10.0.4.26 + A 10.0.4.27 + A 10.0.4.28 + A 10.0.4.29 + A 10.0.4.30 + A 10.0.4.31 + A 10.0.4.32 + A 10.0.4.33 + A 10.0.4.34 + A 10.0.4.35 + A 10.0.4.36 + A 10.0.4.37 + A 10.0.4.38 + A 10.0.4.39 + A 10.0.4.40 + A 10.0.4.41 + A 10.0.4.42 + A 10.0.4.43 + A 10.0.4.44 + A 10.0.4.45 + A 10.0.4.46 + A 10.0.4.47 + A 10.0.4.48 + A 10.0.4.49 + A 10.0.4.50 + A 10.0.4.51 + A 10.0.4.52 + A 10.0.4.53 + A 10.0.4.54 + A 10.0.4.55 + A 10.0.4.56 + A 10.0.4.57 + A 10.0.4.58 + A 10.0.4.59 + A 10.0.4.60 + A 10.0.4.61 + A 10.0.4.62 + A 10.0.4.63 + A 10.0.4.64 + A 10.0.4.65 + A 10.0.4.66 + A 10.0.4.67 + A 10.0.4.68 + A 10.0.4.69 + A 10.0.4.70 + A 10.0.4.71 + A 10.0.4.72 + A 10.0.4.73 + A 10.0.4.74 + A 10.0.4.75 + A 10.0.4.76 + A 10.0.4.77 + A 10.0.4.78 + A 10.0.4.79 + A 10.0.4.80 + A 10.0.4.81 + A 10.0.4.82 + A 10.0.4.83 + A 10.0.4.84 + A 10.0.4.85 + A 10.0.4.86 + A 10.0.4.87 + A 10.0.4.88 + A 10.0.4.89 + A 10.0.4.90 + A 10.0.4.91 + A 10.0.4.92 + A 10.0.4.93 + A 10.0.4.94 + A 10.0.4.95 + A 10.0.4.96 + A 10.0.4.97 + A 10.0.4.98 + A 10.0.4.99 + A 10.0.4.100 + A 10.0.4.101 + A 10.0.4.102 + A 10.0.4.103 + A 10.0.4.104 + A 10.0.4.105 + A 10.0.4.106 + A 10.0.4.107 + A 10.0.4.108 + A 10.0.4.109 + A 10.0.4.110 + A 10.0.4.111 + A 10.0.4.112 + A 10.0.4.113 + A 10.0.4.114 + A 10.0.4.115 + A 10.0.4.116 + A 10.0.4.117 + A 10.0.4.118 + A 10.0.4.119 + A 10.0.4.120 + A 10.0.4.121 + A 10.0.4.122 + A 10.0.4.123 + A 10.0.4.124 + A 10.0.4.125 + A 10.0.4.126 + A 10.0.4.127 + A 10.0.4.128 + A 10.0.4.129 + A 10.0.4.130 + A 10.0.4.131 + A 10.0.4.132 + A 10.0.4.133 + A 10.0.4.134 + A 10.0.4.135 + A 10.0.4.136 + A 10.0.4.137 + A 10.0.4.138 + A 10.0.4.139 + A 10.0.4.140 + A 10.0.4.141 + A 10.0.4.142 + A 10.0.4.143 + A 10.0.4.144 + A 10.0.4.145 + A 10.0.4.146 + A 10.0.4.147 + A 10.0.4.148 + A 10.0.4.149 + A 10.0.4.150 + A 10.0.4.151 + A 10.0.4.152 + A 10.0.4.153 + A 10.0.4.154 + A 10.0.4.155 + A 10.0.4.156 + A 10.0.4.157 + A 10.0.4.158 + A 10.0.4.159 + A 10.0.4.160 + A 10.0.4.161 + A 10.0.4.162 + A 10.0.4.163 + A 10.0.4.164 + A 10.0.4.165 + A 10.0.4.166 + A 10.0.4.167 + A 10.0.4.168 + A 10.0.4.169 + A 10.0.4.170 + A 10.0.4.171 + A 10.0.4.172 + A 10.0.4.173 + A 10.0.4.174 + A 10.0.4.175 + A 10.0.4.176 + A 10.0.4.177 + A 10.0.4.178 + A 10.0.4.179 + A 10.0.4.180 + A 10.0.4.181 + A 10.0.4.182 + A 10.0.4.183 + A 10.0.4.184 + A 10.0.4.185 + A 10.0.4.186 + A 10.0.4.187 + A 10.0.4.188 + A 10.0.4.189 + A 10.0.4.190 + A 10.0.4.191 + A 10.0.4.192 + A 10.0.4.193 + A 10.0.4.194 + A 10.0.4.195 + A 10.0.4.196 + A 10.0.4.197 + A 10.0.4.198 + A 10.0.4.199 + A 10.0.4.200 + A 10.0.4.201 + A 10.0.4.202 + A 10.0.4.203 + A 10.0.4.204 + A 10.0.4.205 + A 10.0.4.206 + A 10.0.4.207 + A 10.0.4.208 + A 10.0.4.209 + A 10.0.4.210 + A 10.0.4.211 + A 10.0.4.212 + A 10.0.4.213 + A 10.0.4.214 + A 10.0.4.215 + A 10.0.4.216 + A 10.0.4.217 + A 10.0.4.218 + A 10.0.4.219 + A 10.0.4.220 + A 10.0.4.221 + A 10.0.4.222 + A 10.0.4.223 + A 10.0.4.224 + A 10.0.4.225 + A 10.0.4.226 + A 10.0.4.227 + A 10.0.4.228 + A 10.0.4.229 + A 10.0.4.230 + A 10.0.4.231 + A 10.0.4.232 + A 10.0.4.233 + A 10.0.4.234 + A 10.0.4.235 + A 10.0.4.236 + A 10.0.4.237 + A 10.0.4.238 + A 10.0.4.239 + A 10.0.4.240 + A 10.0.4.241 + A 10.0.4.242 + A 10.0.4.243 + A 10.0.4.244 + A 10.0.4.245 + A 10.0.4.246 + A 10.0.4.247 + A 10.0.4.248 + A 10.0.4.249 + A 10.0.4.250 + A 10.0.4.251 + A 10.0.4.252 + A 10.0.4.253 + A 10.0.4.254 + A 10.0.4.255 + A 10.0.5.0 + A 10.0.5.1 + A 10.0.5.2 + A 10.0.5.3 + A 10.0.5.4 + A 10.0.5.5 + A 10.0.5.6 + A 10.0.5.7 + A 10.0.5.8 + A 10.0.5.9 + A 10.0.5.10 + A 10.0.5.11 + A 10.0.5.12 + A 10.0.5.13 + A 10.0.5.14 + A 10.0.5.15 + A 10.0.5.16 + A 10.0.5.17 + A 10.0.5.18 + A 10.0.5.19 + A 10.0.5.20 + A 10.0.5.21 + A 10.0.5.22 + A 10.0.5.23 + A 10.0.5.24 + A 10.0.5.25 + A 10.0.5.26 + A 10.0.5.27 + A 10.0.5.28 + A 10.0.5.29 + A 10.0.5.30 + A 10.0.5.31 + A 10.0.5.32 + A 10.0.5.33 + A 10.0.5.34 + A 10.0.5.35 + A 10.0.5.36 + A 10.0.5.37 + A 10.0.5.38 + A 10.0.5.39 + A 10.0.5.40 + A 10.0.5.41 + A 10.0.5.42 + A 10.0.5.43 + A 10.0.5.44 + A 10.0.5.45 + A 10.0.5.46 + A 10.0.5.47 + A 10.0.5.48 + A 10.0.5.49 + A 10.0.5.50 + A 10.0.5.51 + A 10.0.5.52 + A 10.0.5.53 + A 10.0.5.54 + A 10.0.5.55 + A 10.0.5.56 + A 10.0.5.57 + A 10.0.5.58 + A 10.0.5.59 + A 10.0.5.60 + A 10.0.5.61 + A 10.0.5.62 + A 10.0.5.63 + A 10.0.5.64 + A 10.0.5.65 + A 10.0.5.66 + A 10.0.5.67 + A 10.0.5.68 + A 10.0.5.69 + A 10.0.5.70 + A 10.0.5.71 + A 10.0.5.72 + A 10.0.5.73 + A 10.0.5.74 + A 10.0.5.75 + A 10.0.5.76 + A 10.0.5.77 + A 10.0.5.78 + A 10.0.5.79 + A 10.0.5.80 + A 10.0.5.81 + A 10.0.5.82 + A 10.0.5.83 + A 10.0.5.84 + A 10.0.5.85 + A 10.0.5.86 + A 10.0.5.87 + A 10.0.5.88 + A 10.0.5.89 + A 10.0.5.90 + A 10.0.5.91 + A 10.0.5.92 + A 10.0.5.93 + A 10.0.5.94 + A 10.0.5.95 + A 10.0.5.96 + A 10.0.5.97 + A 10.0.5.98 + A 10.0.5.99 + A 10.0.5.100 + A 10.0.5.101 + A 10.0.5.102 + A 10.0.5.103 + A 10.0.5.104 + A 10.0.5.105 + A 10.0.5.106 + A 10.0.5.107 + A 10.0.5.108 + A 10.0.5.109 + A 10.0.5.110 + A 10.0.5.111 + A 10.0.5.112 + A 10.0.5.113 + A 10.0.5.114 + A 10.0.5.115 + A 10.0.5.116 + A 10.0.5.117 + A 10.0.5.118 + A 10.0.5.119 + A 10.0.5.120 + A 10.0.5.121 + A 10.0.5.122 + A 10.0.5.123 + A 10.0.5.124 + A 10.0.5.125 + A 10.0.5.126 + A 10.0.5.127 + A 10.0.5.128 + A 10.0.5.129 + A 10.0.5.130 + A 10.0.5.131 + A 10.0.5.132 + A 10.0.5.133 + A 10.0.5.134 + A 10.0.5.135 + A 10.0.5.136 + A 10.0.5.137 + A 10.0.5.138 + A 10.0.5.139 + A 10.0.5.140 + A 10.0.5.141 + A 10.0.5.142 + A 10.0.5.143 + A 10.0.5.144 + A 10.0.5.145 + A 10.0.5.146 + A 10.0.5.147 + A 10.0.5.148 + A 10.0.5.149 + A 10.0.5.150 + A 10.0.5.151 + A 10.0.5.152 + A 10.0.5.153 + A 10.0.5.154 + A 10.0.5.155 + A 10.0.5.156 + A 10.0.5.157 + A 10.0.5.158 + A 10.0.5.159 + A 10.0.5.160 + A 10.0.5.161 + A 10.0.5.162 + A 10.0.5.163 + A 10.0.5.164 + A 10.0.5.165 + A 10.0.5.166 + A 10.0.5.167 + A 10.0.5.168 + A 10.0.5.169 + A 10.0.5.170 + A 10.0.5.171 + A 10.0.5.172 + A 10.0.5.173 + A 10.0.5.174 + A 10.0.5.175 + A 10.0.5.176 + A 10.0.5.177 + A 10.0.5.178 + A 10.0.5.179 + A 10.0.5.180 + A 10.0.5.181 + A 10.0.5.182 + A 10.0.5.183 + A 10.0.5.184 + A 10.0.5.185 + A 10.0.5.186 + A 10.0.5.187 + A 10.0.5.188 + A 10.0.5.189 + A 10.0.5.190 + A 10.0.5.191 + A 10.0.5.192 + A 10.0.5.193 + A 10.0.5.194 + A 10.0.5.195 + A 10.0.5.196 + A 10.0.5.197 + A 10.0.5.198 + A 10.0.5.199 + A 10.0.5.200 + A 10.0.5.201 + A 10.0.5.202 + A 10.0.5.203 + A 10.0.5.204 + A 10.0.5.205 + A 10.0.5.206 + A 10.0.5.207 + A 10.0.5.208 + A 10.0.5.209 + A 10.0.5.210 + A 10.0.5.211 + A 10.0.5.212 + A 10.0.5.213 + A 10.0.5.214 + A 10.0.5.215 + A 10.0.5.216 + A 10.0.5.217 + A 10.0.5.218 + A 10.0.5.219 + A 10.0.5.220 + A 10.0.5.221 + A 10.0.5.222 + A 10.0.5.223 + A 10.0.5.224 + A 10.0.5.225 + A 10.0.5.226 + A 10.0.5.227 + A 10.0.5.228 + A 10.0.5.229 + A 10.0.5.230 + A 10.0.5.231 + A 10.0.5.232 + A 10.0.5.233 + A 10.0.5.234 + A 10.0.5.235 + A 10.0.5.236 + A 10.0.5.237 + A 10.0.5.238 + A 10.0.5.239 + A 10.0.5.240 + A 10.0.5.241 + A 10.0.5.242 + A 10.0.5.243 + A 10.0.5.244 + A 10.0.5.245 + A 10.0.5.246 + A 10.0.5.247 + A 10.0.5.248 + A 10.0.5.249 + A 10.0.5.250 + A 10.0.5.251 + A 10.0.5.252 + A 10.0.5.253 + A 10.0.5.254 + A 10.0.5.255 + A 10.0.6.0 + A 10.0.6.1 + A 10.0.6.2 + A 10.0.6.3 + A 10.0.6.4 + A 10.0.6.5 + A 10.0.6.6 + A 10.0.6.7 + A 10.0.6.8 + A 10.0.6.9 + A 10.0.6.10 + A 10.0.6.11 + A 10.0.6.12 + A 10.0.6.13 + A 10.0.6.14 + A 10.0.6.15 + A 10.0.6.16 + A 10.0.6.17 + A 10.0.6.18 + A 10.0.6.19 + A 10.0.6.20 + A 10.0.6.21 + A 10.0.6.22 + A 10.0.6.23 + A 10.0.6.24 + A 10.0.6.25 + A 10.0.6.26 + A 10.0.6.27 + A 10.0.6.28 + A 10.0.6.29 + A 10.0.6.30 + A 10.0.6.31 + A 10.0.6.32 + A 10.0.6.33 + A 10.0.6.34 + A 10.0.6.35 + A 10.0.6.36 + A 10.0.6.37 + A 10.0.6.38 + A 10.0.6.39 + A 10.0.6.40 + A 10.0.6.41 + A 10.0.6.42 + A 10.0.6.43 + A 10.0.6.44 + A 10.0.6.45 + A 10.0.6.46 + A 10.0.6.47 + A 10.0.6.48 + A 10.0.6.49 + A 10.0.6.50 + A 10.0.6.51 + A 10.0.6.52 + A 10.0.6.53 + A 10.0.6.54 + A 10.0.6.55 + A 10.0.6.56 + A 10.0.6.57 + A 10.0.6.58 + A 10.0.6.59 + A 10.0.6.60 + A 10.0.6.61 + A 10.0.6.62 + A 10.0.6.63 + A 10.0.6.64 + A 10.0.6.65 + A 10.0.6.66 + A 10.0.6.67 + A 10.0.6.68 + A 10.0.6.69 + A 10.0.6.70 + A 10.0.6.71 + A 10.0.6.72 + A 10.0.6.73 + A 10.0.6.74 + A 10.0.6.75 + A 10.0.6.76 + A 10.0.6.77 + A 10.0.6.78 + A 10.0.6.79 + A 10.0.6.80 + A 10.0.6.81 + A 10.0.6.82 + A 10.0.6.83 + A 10.0.6.84 + A 10.0.6.85 + A 10.0.6.86 + A 10.0.6.87 + A 10.0.6.88 + A 10.0.6.89 + A 10.0.6.90 + A 10.0.6.91 + A 10.0.6.92 + A 10.0.6.93 + A 10.0.6.94 + A 10.0.6.95 + A 10.0.6.96 + A 10.0.6.97 + A 10.0.6.98 + A 10.0.6.99 + A 10.0.6.100 + A 10.0.6.101 + A 10.0.6.102 + A 10.0.6.103 + A 10.0.6.104 + A 10.0.6.105 + A 10.0.6.106 + A 10.0.6.107 + A 10.0.6.108 + A 10.0.6.109 + A 10.0.6.110 + A 10.0.6.111 + A 10.0.6.112 + A 10.0.6.113 + A 10.0.6.114 + A 10.0.6.115 + A 10.0.6.116 + A 10.0.6.117 + A 10.0.6.118 + A 10.0.6.119 + A 10.0.6.120 + A 10.0.6.121 + A 10.0.6.122 + A 10.0.6.123 + A 10.0.6.124 + A 10.0.6.125 + A 10.0.6.126 + A 10.0.6.127 + A 10.0.6.128 + A 10.0.6.129 + A 10.0.6.130 + A 10.0.6.131 + A 10.0.6.132 + A 10.0.6.133 + A 10.0.6.134 + A 10.0.6.135 + A 10.0.6.136 + A 10.0.6.137 + A 10.0.6.138 + A 10.0.6.139 + A 10.0.6.140 + A 10.0.6.141 + A 10.0.6.142 + A 10.0.6.143 + A 10.0.6.144 + A 10.0.6.145 + A 10.0.6.146 + A 10.0.6.147 + A 10.0.6.148 + A 10.0.6.149 + A 10.0.6.150 + A 10.0.6.151 + A 10.0.6.152 + A 10.0.6.153 + A 10.0.6.154 + A 10.0.6.155 + A 10.0.6.156 + A 10.0.6.157 + A 10.0.6.158 + A 10.0.6.159 + A 10.0.6.160 + A 10.0.6.161 + A 10.0.6.162 + A 10.0.6.163 + A 10.0.6.164 + A 10.0.6.165 + A 10.0.6.166 + A 10.0.6.167 + A 10.0.6.168 + A 10.0.6.169 + A 10.0.6.170 + A 10.0.6.171 + A 10.0.6.172 + A 10.0.6.173 + A 10.0.6.174 + A 10.0.6.175 + A 10.0.6.176 + A 10.0.6.177 + A 10.0.6.178 + A 10.0.6.179 + A 10.0.6.180 + A 10.0.6.181 + A 10.0.6.182 + A 10.0.6.183 + A 10.0.6.184 + A 10.0.6.185 + A 10.0.6.186 + A 10.0.6.187 + A 10.0.6.188 + A 10.0.6.189 + A 10.0.6.190 + A 10.0.6.191 + A 10.0.6.192 + A 10.0.6.193 + A 10.0.6.194 + A 10.0.6.195 + A 10.0.6.196 + A 10.0.6.197 + A 10.0.6.198 + A 10.0.6.199 + A 10.0.6.200 + A 10.0.6.201 + A 10.0.6.202 + A 10.0.6.203 + A 10.0.6.204 + A 10.0.6.205 + A 10.0.6.206 + A 10.0.6.207 + A 10.0.6.208 + A 10.0.6.209 + A 10.0.6.210 + A 10.0.6.211 + A 10.0.6.212 + A 10.0.6.213 + A 10.0.6.214 + A 10.0.6.215 + A 10.0.6.216 + A 10.0.6.217 + A 10.0.6.218 + A 10.0.6.219 + A 10.0.6.220 + A 10.0.6.221 + A 10.0.6.222 + A 10.0.6.223 + A 10.0.6.224 + A 10.0.6.225 + A 10.0.6.226 + A 10.0.6.227 + A 10.0.6.228 + A 10.0.6.229 + A 10.0.6.230 + A 10.0.6.231 + A 10.0.6.232 + A 10.0.6.233 + A 10.0.6.234 + A 10.0.6.235 + A 10.0.6.236 + A 10.0.6.237 + A 10.0.6.238 + A 10.0.6.239 + A 10.0.6.240 + A 10.0.6.241 + A 10.0.6.242 + A 10.0.6.243 + A 10.0.6.244 + A 10.0.6.245 + A 10.0.6.246 + A 10.0.6.247 + A 10.0.6.248 + A 10.0.6.249 + A 10.0.6.250 + A 10.0.6.251 + A 10.0.6.252 + A 10.0.6.253 + A 10.0.6.254 + A 10.0.6.255 + A 10.0.7.0 + A 10.0.7.1 + A 10.0.7.2 + A 10.0.7.3 + A 10.0.7.4 + A 10.0.7.5 + A 10.0.7.6 + A 10.0.7.7 + A 10.0.7.8 + A 10.0.7.9 + A 10.0.7.10 + A 10.0.7.11 + A 10.0.7.12 + A 10.0.7.13 + A 10.0.7.14 + A 10.0.7.15 + A 10.0.7.16 + A 10.0.7.17 + A 10.0.7.18 + A 10.0.7.19 + A 10.0.7.20 + A 10.0.7.21 + A 10.0.7.22 + A 10.0.7.23 + A 10.0.7.24 + A 10.0.7.25 + A 10.0.7.26 + A 10.0.7.27 + A 10.0.7.28 + A 10.0.7.29 + A 10.0.7.30 + A 10.0.7.31 + A 10.0.7.32 + A 10.0.7.33 + A 10.0.7.34 + A 10.0.7.35 + A 10.0.7.36 + A 10.0.7.37 + A 10.0.7.38 + A 10.0.7.39 + A 10.0.7.40 + A 10.0.7.41 + A 10.0.7.42 + A 10.0.7.43 + A 10.0.7.44 + A 10.0.7.45 + A 10.0.7.46 + A 10.0.7.47 + A 10.0.7.48 + A 10.0.7.49 + A 10.0.7.50 + A 10.0.7.51 + A 10.0.7.52 + A 10.0.7.53 + A 10.0.7.54 + A 10.0.7.55 + A 10.0.7.56 + A 10.0.7.57 + A 10.0.7.58 + A 10.0.7.59 + A 10.0.7.60 + A 10.0.7.61 + A 10.0.7.62 + A 10.0.7.63 + A 10.0.7.64 + A 10.0.7.65 + A 10.0.7.66 + A 10.0.7.67 + A 10.0.7.68 + A 10.0.7.69 + A 10.0.7.70 + A 10.0.7.71 + A 10.0.7.72 + A 10.0.7.73 + A 10.0.7.74 + A 10.0.7.75 + A 10.0.7.76 + A 10.0.7.77 + A 10.0.7.78 + A 10.0.7.79 + A 10.0.7.80 + A 10.0.7.81 + A 10.0.7.82 + A 10.0.7.83 + A 10.0.7.84 + A 10.0.7.85 + A 10.0.7.86 + A 10.0.7.87 + A 10.0.7.88 + A 10.0.7.89 + A 10.0.7.90 + A 10.0.7.91 + A 10.0.7.92 + A 10.0.7.93 + A 10.0.7.94 + A 10.0.7.95 + A 10.0.7.96 + A 10.0.7.97 + A 10.0.7.98 + A 10.0.7.99 + A 10.0.7.100 + A 10.0.7.101 + A 10.0.7.102 + A 10.0.7.103 + A 10.0.7.104 + A 10.0.7.105 + A 10.0.7.106 + A 10.0.7.107 + A 10.0.7.108 + A 10.0.7.109 + A 10.0.7.110 + A 10.0.7.111 + A 10.0.7.112 + A 10.0.7.113 + A 10.0.7.114 + A 10.0.7.115 + A 10.0.7.116 + A 10.0.7.117 + A 10.0.7.118 + A 10.0.7.119 + A 10.0.7.120 + A 10.0.7.121 + A 10.0.7.122 + A 10.0.7.123 + A 10.0.7.124 + A 10.0.7.125 + A 10.0.7.126 + A 10.0.7.127 + A 10.0.7.128 + A 10.0.7.129 + A 10.0.7.130 + A 10.0.7.131 + A 10.0.7.132 + A 10.0.7.133 + A 10.0.7.134 + A 10.0.7.135 + A 10.0.7.136 + A 10.0.7.137 + A 10.0.7.138 + A 10.0.7.139 + A 10.0.7.140 + A 10.0.7.141 + A 10.0.7.142 + A 10.0.7.143 + A 10.0.7.144 + A 10.0.7.145 + A 10.0.7.146 + A 10.0.7.147 + A 10.0.7.148 + A 10.0.7.149 + A 10.0.7.150 + A 10.0.7.151 + A 10.0.7.152 + A 10.0.7.153 + A 10.0.7.154 + A 10.0.7.155 + A 10.0.7.156 + A 10.0.7.157 + A 10.0.7.158 + A 10.0.7.159 + A 10.0.7.160 + A 10.0.7.161 + A 10.0.7.162 + A 10.0.7.163 + A 10.0.7.164 + A 10.0.7.165 + A 10.0.7.166 + A 10.0.7.167 + A 10.0.7.168 + A 10.0.7.169 + A 10.0.7.170 + A 10.0.7.171 + A 10.0.7.172 + A 10.0.7.173 + A 10.0.7.174 + A 10.0.7.175 + A 10.0.7.176 + A 10.0.7.177 + A 10.0.7.178 + A 10.0.7.179 + A 10.0.7.180 + A 10.0.7.181 + A 10.0.7.182 + A 10.0.7.183 + A 10.0.7.184 + A 10.0.7.185 + A 10.0.7.186 + A 10.0.7.187 + A 10.0.7.188 + A 10.0.7.189 + A 10.0.7.190 + A 10.0.7.191 + A 10.0.7.192 + A 10.0.7.193 + A 10.0.7.194 + A 10.0.7.195 + A 10.0.7.196 + A 10.0.7.197 + A 10.0.7.198 + A 10.0.7.199 + A 10.0.7.200 + A 10.0.7.201 + A 10.0.7.202 + A 10.0.7.203 + A 10.0.7.204 + A 10.0.7.205 + A 10.0.7.206 + A 10.0.7.207 + A 10.0.7.208 + A 10.0.7.209 + A 10.0.7.210 + A 10.0.7.211 + A 10.0.7.212 + A 10.0.7.213 + A 10.0.7.214 + A 10.0.7.215 + A 10.0.7.216 + A 10.0.7.217 + A 10.0.7.218 + A 10.0.7.219 + A 10.0.7.220 + A 10.0.7.221 + A 10.0.7.222 + A 10.0.7.223 + A 10.0.7.224 + A 10.0.7.225 + A 10.0.7.226 + A 10.0.7.227 + A 10.0.7.228 + A 10.0.7.229 + A 10.0.7.230 + A 10.0.7.231 + A 10.0.7.232 + A 10.0.7.233 + A 10.0.7.234 + A 10.0.7.235 + A 10.0.7.236 + A 10.0.7.237 + A 10.0.7.238 + A 10.0.7.239 + A 10.0.7.240 + A 10.0.7.241 + A 10.0.7.242 + A 10.0.7.243 + A 10.0.7.244 + A 10.0.7.245 + A 10.0.7.246 + A 10.0.7.247 + A 10.0.7.248 + A 10.0.7.249 + A 10.0.7.250 + A 10.0.7.251 + A 10.0.7.252 + A 10.0.7.253 + A 10.0.7.254 + A 10.0.7.255 + A 10.0.8.0 + A 10.0.8.1 + A 10.0.8.2 + A 10.0.8.3 + A 10.0.8.4 + A 10.0.8.5 + A 10.0.8.6 + A 10.0.8.7 + A 10.0.8.8 + A 10.0.8.9 + A 10.0.8.10 + A 10.0.8.11 + A 10.0.8.12 + A 10.0.8.13 + A 10.0.8.14 + A 10.0.8.15 + A 10.0.8.16 + A 10.0.8.17 + A 10.0.8.18 + A 10.0.8.19 + A 10.0.8.20 + A 10.0.8.21 + A 10.0.8.22 + A 10.0.8.23 + A 10.0.8.24 + A 10.0.8.25 + A 10.0.8.26 + A 10.0.8.27 + A 10.0.8.28 + A 10.0.8.29 + A 10.0.8.30 + A 10.0.8.31 + A 10.0.8.32 + A 10.0.8.33 + A 10.0.8.34 + A 10.0.8.35 + A 10.0.8.36 + A 10.0.8.37 + A 10.0.8.38 + A 10.0.8.39 + A 10.0.8.40 + A 10.0.8.41 + A 10.0.8.42 + A 10.0.8.43 + A 10.0.8.44 + A 10.0.8.45 + A 10.0.8.46 + A 10.0.8.47 + A 10.0.8.48 + A 10.0.8.49 + A 10.0.8.50 + A 10.0.8.51 + A 10.0.8.52 + A 10.0.8.53 + A 10.0.8.54 + A 10.0.8.55 + A 10.0.8.56 + A 10.0.8.57 + A 10.0.8.58 + A 10.0.8.59 + A 10.0.8.60 + A 10.0.8.61 + A 10.0.8.62 + A 10.0.8.63 + A 10.0.8.64 + A 10.0.8.65 + A 10.0.8.66 + A 10.0.8.67 + A 10.0.8.68 + A 10.0.8.69 + A 10.0.8.70 + A 10.0.8.71 + A 10.0.8.72 + A 10.0.8.73 + A 10.0.8.74 + A 10.0.8.75 + A 10.0.8.76 + A 10.0.8.77 + A 10.0.8.78 + A 10.0.8.79 + A 10.0.8.80 + A 10.0.8.81 + A 10.0.8.82 + A 10.0.8.83 + A 10.0.8.84 + A 10.0.8.85 + A 10.0.8.86 + A 10.0.8.87 + A 10.0.8.88 + A 10.0.8.89 + A 10.0.8.90 + A 10.0.8.91 + A 10.0.8.92 + A 10.0.8.93 + A 10.0.8.94 + A 10.0.8.95 + A 10.0.8.96 + A 10.0.8.97 + A 10.0.8.98 + A 10.0.8.99 + A 10.0.8.100 + A 10.0.8.101 + A 10.0.8.102 + A 10.0.8.103 + A 10.0.8.104 + A 10.0.8.105 + A 10.0.8.106 + A 10.0.8.107 + A 10.0.8.108 + A 10.0.8.109 + A 10.0.8.110 + A 10.0.8.111 + A 10.0.8.112 + A 10.0.8.113 + A 10.0.8.114 + A 10.0.8.115 + A 10.0.8.116 + A 10.0.8.117 + A 10.0.8.118 + A 10.0.8.119 + A 10.0.8.120 + A 10.0.8.121 + A 10.0.8.122 + A 10.0.8.123 + A 10.0.8.124 + A 10.0.8.125 + A 10.0.8.126 + A 10.0.8.127 + A 10.0.8.128 + A 10.0.8.129 + A 10.0.8.130 + A 10.0.8.131 + A 10.0.8.132 + A 10.0.8.133 + A 10.0.8.134 + A 10.0.8.135 + A 10.0.8.136 + A 10.0.8.137 + A 10.0.8.138 + A 10.0.8.139 + A 10.0.8.140 + A 10.0.8.141 + A 10.0.8.142 + A 10.0.8.143 + A 10.0.8.144 + A 10.0.8.145 + A 10.0.8.146 + A 10.0.8.147 + A 10.0.8.148 + A 10.0.8.149 + A 10.0.8.150 + A 10.0.8.151 + A 10.0.8.152 + A 10.0.8.153 + A 10.0.8.154 + A 10.0.8.155 + A 10.0.8.156 + A 10.0.8.157 + A 10.0.8.158 + A 10.0.8.159 + A 10.0.8.160 + A 10.0.8.161 + A 10.0.8.162 + A 10.0.8.163 + A 10.0.8.164 + A 10.0.8.165 + A 10.0.8.166 + A 10.0.8.167 + A 10.0.8.168 + A 10.0.8.169 + A 10.0.8.170 + A 10.0.8.171 + A 10.0.8.172 + A 10.0.8.173 + A 10.0.8.174 + A 10.0.8.175 + A 10.0.8.176 + A 10.0.8.177 + A 10.0.8.178 + A 10.0.8.179 + A 10.0.8.180 + A 10.0.8.181 + A 10.0.8.182 + A 10.0.8.183 + A 10.0.8.184 + A 10.0.8.185 + A 10.0.8.186 + A 10.0.8.187 + A 10.0.8.188 + A 10.0.8.189 + A 10.0.8.190 + A 10.0.8.191 + A 10.0.8.192 + A 10.0.8.193 + A 10.0.8.194 + A 10.0.8.195 + A 10.0.8.196 + A 10.0.8.197 + A 10.0.8.198 + A 10.0.8.199 + A 10.0.8.200 + A 10.0.8.201 + A 10.0.8.202 + A 10.0.8.203 + A 10.0.8.204 + A 10.0.8.205 + A 10.0.8.206 + A 10.0.8.207 + A 10.0.8.208 + A 10.0.8.209 + A 10.0.8.210 + A 10.0.8.211 + A 10.0.8.212 + A 10.0.8.213 + A 10.0.8.214 + A 10.0.8.215 + A 10.0.8.216 + A 10.0.8.217 + A 10.0.8.218 + A 10.0.8.219 + A 10.0.8.220 + A 10.0.8.221 + A 10.0.8.222 + A 10.0.8.223 + A 10.0.8.224 + A 10.0.8.225 + A 10.0.8.226 + A 10.0.8.227 + A 10.0.8.228 + A 10.0.8.229 + A 10.0.8.230 + A 10.0.8.231 + A 10.0.8.232 + A 10.0.8.233 + A 10.0.8.234 + A 10.0.8.235 + A 10.0.8.236 + A 10.0.8.237 + A 10.0.8.238 + A 10.0.8.239 + A 10.0.8.240 + A 10.0.8.241 + A 10.0.8.242 + A 10.0.8.243 + A 10.0.8.244 + A 10.0.8.245 + A 10.0.8.246 + A 10.0.8.247 + A 10.0.8.248 + A 10.0.8.249 + A 10.0.8.250 + A 10.0.8.251 + A 10.0.8.252 + A 10.0.8.253 + A 10.0.8.254 + A 10.0.8.255 + A 10.0.9.0 + A 10.0.9.1 + A 10.0.9.2 + A 10.0.9.3 + A 10.0.9.4 + A 10.0.9.5 + A 10.0.9.6 + A 10.0.9.7 + A 10.0.9.8 + A 10.0.9.9 + A 10.0.9.10 + A 10.0.9.11 + A 10.0.9.12 + A 10.0.9.13 + A 10.0.9.14 + A 10.0.9.15 + A 10.0.9.16 + A 10.0.9.17 + A 10.0.9.18 + A 10.0.9.19 + A 10.0.9.20 + A 10.0.9.21 + A 10.0.9.22 + A 10.0.9.23 + A 10.0.9.24 + A 10.0.9.25 + A 10.0.9.26 + A 10.0.9.27 + A 10.0.9.28 + A 10.0.9.29 + A 10.0.9.30 + A 10.0.9.31 + A 10.0.9.32 + A 10.0.9.33 + A 10.0.9.34 + A 10.0.9.35 + A 10.0.9.36 + A 10.0.9.37 + A 10.0.9.38 + A 10.0.9.39 + A 10.0.9.40 + A 10.0.9.41 + A 10.0.9.42 + A 10.0.9.43 + A 10.0.9.44 + A 10.0.9.45 + A 10.0.9.46 + A 10.0.9.47 + A 10.0.9.48 + A 10.0.9.49 + A 10.0.9.50 + A 10.0.9.51 + A 10.0.9.52 + A 10.0.9.53 + A 10.0.9.54 + A 10.0.9.55 + A 10.0.9.56 + A 10.0.9.57 + A 10.0.9.58 + A 10.0.9.59 + A 10.0.9.60 + A 10.0.9.61 + A 10.0.9.62 + A 10.0.9.63 + A 10.0.9.64 + A 10.0.9.65 + A 10.0.9.66 + A 10.0.9.67 + A 10.0.9.68 + A 10.0.9.69 + A 10.0.9.70 + A 10.0.9.71 + A 10.0.9.72 + A 10.0.9.73 + A 10.0.9.74 + A 10.0.9.75 + A 10.0.9.76 + A 10.0.9.77 + A 10.0.9.78 + A 10.0.9.79 + A 10.0.9.80 + A 10.0.9.81 + A 10.0.9.82 + A 10.0.9.83 + A 10.0.9.84 + A 10.0.9.85 + A 10.0.9.86 + A 10.0.9.87 + A 10.0.9.88 + A 10.0.9.89 + A 10.0.9.90 + A 10.0.9.91 + A 10.0.9.92 + A 10.0.9.93 + A 10.0.9.94 + A 10.0.9.95 + A 10.0.9.96 + A 10.0.9.97 + A 10.0.9.98 + A 10.0.9.99 + A 10.0.9.100 + A 10.0.9.101 + A 10.0.9.102 + A 10.0.9.103 + A 10.0.9.104 + A 10.0.9.105 + A 10.0.9.106 + A 10.0.9.107 + A 10.0.9.108 + A 10.0.9.109 + A 10.0.9.110 + A 10.0.9.111 + A 10.0.9.112 + A 10.0.9.113 + A 10.0.9.114 + A 10.0.9.115 + A 10.0.9.116 + A 10.0.9.117 + A 10.0.9.118 + A 10.0.9.119 + A 10.0.9.120 + A 10.0.9.121 + A 10.0.9.122 + A 10.0.9.123 + A 10.0.9.124 + A 10.0.9.125 + A 10.0.9.126 + A 10.0.9.127 + A 10.0.9.128 + A 10.0.9.129 + A 10.0.9.130 + A 10.0.9.131 + A 10.0.9.132 + A 10.0.9.133 + A 10.0.9.134 + A 10.0.9.135 + A 10.0.9.136 + A 10.0.9.137 + A 10.0.9.138 + A 10.0.9.139 + A 10.0.9.140 + A 10.0.9.141 + A 10.0.9.142 + A 10.0.9.143 + A 10.0.9.144 + A 10.0.9.145 + A 10.0.9.146 + A 10.0.9.147 + A 10.0.9.148 + A 10.0.9.149 + A 10.0.9.150 + A 10.0.9.151 + A 10.0.9.152 + A 10.0.9.153 + A 10.0.9.154 + A 10.0.9.155 + A 10.0.9.156 + A 10.0.9.157 + A 10.0.9.158 + A 10.0.9.159 + A 10.0.9.160 + A 10.0.9.161 + A 10.0.9.162 + A 10.0.9.163 + A 10.0.9.164 + A 10.0.9.165 + A 10.0.9.166 + A 10.0.9.167 + A 10.0.9.168 + A 10.0.9.169 + A 10.0.9.170 + A 10.0.9.171 + A 10.0.9.172 + A 10.0.9.173 + A 10.0.9.174 + A 10.0.9.175 + A 10.0.9.176 + A 10.0.9.177 + A 10.0.9.178 + A 10.0.9.179 + A 10.0.9.180 + A 10.0.9.181 + A 10.0.9.182 + A 10.0.9.183 + A 10.0.9.184 + A 10.0.9.185 + A 10.0.9.186 + A 10.0.9.187 + A 10.0.9.188 + A 10.0.9.189 + A 10.0.9.190 + A 10.0.9.191 + A 10.0.9.192 + A 10.0.9.193 + A 10.0.9.194 + A 10.0.9.195 + A 10.0.9.196 + A 10.0.9.197 + A 10.0.9.198 + A 10.0.9.199 + A 10.0.9.200 + A 10.0.9.201 + A 10.0.9.202 + A 10.0.9.203 + A 10.0.9.204 + A 10.0.9.205 + A 10.0.9.206 + A 10.0.9.207 + A 10.0.9.208 + A 10.0.9.209 + A 10.0.9.210 + A 10.0.9.211 + A 10.0.9.212 + A 10.0.9.213 + A 10.0.9.214 + A 10.0.9.215 + A 10.0.9.216 + A 10.0.9.217 + A 10.0.9.218 + A 10.0.9.219 + A 10.0.9.220 + A 10.0.9.221 + A 10.0.9.222 + A 10.0.9.223 + A 10.0.9.224 + A 10.0.9.225 + A 10.0.9.226 + A 10.0.9.227 + A 10.0.9.228 + A 10.0.9.229 + A 10.0.9.230 + A 10.0.9.231 + A 10.0.9.232 + A 10.0.9.233 + A 10.0.9.234 + A 10.0.9.235 + A 10.0.9.236 + A 10.0.9.237 + A 10.0.9.238 + A 10.0.9.239 + A 10.0.9.240 + A 10.0.9.241 + A 10.0.9.242 + A 10.0.9.243 + A 10.0.9.244 + A 10.0.9.245 + A 10.0.9.246 + A 10.0.9.247 + A 10.0.9.248 + A 10.0.9.249 + A 10.0.9.250 + A 10.0.9.251 + A 10.0.9.252 + A 10.0.9.253 + A 10.0.9.254 + A 10.0.9.255 + A 10.0.10.0 + A 10.0.10.1 + A 10.0.10.2 + A 10.0.10.3 + A 10.0.10.4 + A 10.0.10.5 + A 10.0.10.6 + A 10.0.10.7 + A 10.0.10.8 + A 10.0.10.9 + A 10.0.10.10 + A 10.0.10.11 + A 10.0.10.12 + A 10.0.10.13 + A 10.0.10.14 + A 10.0.10.15 + A 10.0.10.16 + A 10.0.10.17 + A 10.0.10.18 + A 10.0.10.19 + A 10.0.10.20 + A 10.0.10.21 + A 10.0.10.22 + A 10.0.10.23 + A 10.0.10.24 + A 10.0.10.25 + A 10.0.10.26 + A 10.0.10.27 + A 10.0.10.28 + A 10.0.10.29 + A 10.0.10.30 + A 10.0.10.31 + A 10.0.10.32 + A 10.0.10.33 + A 10.0.10.34 + A 10.0.10.35 + A 10.0.10.36 + A 10.0.10.37 + A 10.0.10.38 + A 10.0.10.39 + A 10.0.10.40 + A 10.0.10.41 + A 10.0.10.42 + A 10.0.10.43 + A 10.0.10.44 + A 10.0.10.45 + A 10.0.10.46 + A 10.0.10.47 + A 10.0.10.48 + A 10.0.10.49 + A 10.0.10.50 + A 10.0.10.51 + A 10.0.10.52 + A 10.0.10.53 + A 10.0.10.54 + A 10.0.10.55 + A 10.0.10.56 + A 10.0.10.57 + A 10.0.10.58 + A 10.0.10.59 + A 10.0.10.60 + A 10.0.10.61 + A 10.0.10.62 + A 10.0.10.63 + A 10.0.10.64 + A 10.0.10.65 + A 10.0.10.66 + A 10.0.10.67 + A 10.0.10.68 + A 10.0.10.69 + A 10.0.10.70 + A 10.0.10.71 + A 10.0.10.72 + A 10.0.10.73 + A 10.0.10.74 + A 10.0.10.75 + A 10.0.10.76 + A 10.0.10.77 + A 10.0.10.78 + A 10.0.10.79 + A 10.0.10.80 + A 10.0.10.81 + A 10.0.10.82 + A 10.0.10.83 + A 10.0.10.84 + A 10.0.10.85 + A 10.0.10.86 + A 10.0.10.87 + A 10.0.10.88 + A 10.0.10.89 + A 10.0.10.90 + A 10.0.10.91 + A 10.0.10.92 + A 10.0.10.93 + A 10.0.10.94 + A 10.0.10.95 + A 10.0.10.96 + A 10.0.10.97 + A 10.0.10.98 + A 10.0.10.99 + A 10.0.10.100 + A 10.0.10.101 + A 10.0.10.102 + A 10.0.10.103 + A 10.0.10.104 + A 10.0.10.105 + A 10.0.10.106 + A 10.0.10.107 + A 10.0.10.108 + A 10.0.10.109 + A 10.0.10.110 + A 10.0.10.111 + A 10.0.10.112 + A 10.0.10.113 + A 10.0.10.114 + A 10.0.10.115 + A 10.0.10.116 + A 10.0.10.117 + A 10.0.10.118 + A 10.0.10.119 + A 10.0.10.120 + A 10.0.10.121 + A 10.0.10.122 + A 10.0.10.123 + A 10.0.10.124 + A 10.0.10.125 + A 10.0.10.126 + A 10.0.10.127 + A 10.0.10.128 + A 10.0.10.129 + A 10.0.10.130 + A 10.0.10.131 + A 10.0.10.132 + A 10.0.10.133 + A 10.0.10.134 + A 10.0.10.135 + A 10.0.10.136 + A 10.0.10.137 + A 10.0.10.138 + A 10.0.10.139 + A 10.0.10.140 + A 10.0.10.141 + A 10.0.10.142 + A 10.0.10.143 + A 10.0.10.144 + A 10.0.10.145 + A 10.0.10.146 + A 10.0.10.147 + A 10.0.10.148 + A 10.0.10.149 + A 10.0.10.150 + A 10.0.10.151 + A 10.0.10.152 + A 10.0.10.153 + A 10.0.10.154 + A 10.0.10.155 + A 10.0.10.156 + A 10.0.10.157 + A 10.0.10.158 + A 10.0.10.159 + A 10.0.10.160 + A 10.0.10.161 + A 10.0.10.162 + A 10.0.10.163 + A 10.0.10.164 + A 10.0.10.165 + A 10.0.10.166 + A 10.0.10.167 + A 10.0.10.168 + A 10.0.10.169 + A 10.0.10.170 + A 10.0.10.171 + A 10.0.10.172 + A 10.0.10.173 + A 10.0.10.174 + A 10.0.10.175 + A 10.0.10.176 + A 10.0.10.177 + A 10.0.10.178 + A 10.0.10.179 + A 10.0.10.180 + A 10.0.10.181 + A 10.0.10.182 + A 10.0.10.183 + A 10.0.10.184 + A 10.0.10.185 + A 10.0.10.186 + A 10.0.10.187 + A 10.0.10.188 + A 10.0.10.189 + A 10.0.10.190 + A 10.0.10.191 + A 10.0.10.192 + A 10.0.10.193 + A 10.0.10.194 + A 10.0.10.195 + A 10.0.10.196 + A 10.0.10.197 + A 10.0.10.198 + A 10.0.10.199 + A 10.0.10.200 + A 10.0.10.201 + A 10.0.10.202 + A 10.0.10.203 + A 10.0.10.204 + A 10.0.10.205 + A 10.0.10.206 + A 10.0.10.207 + A 10.0.10.208 + A 10.0.10.209 + A 10.0.10.210 + A 10.0.10.211 + A 10.0.10.212 + A 10.0.10.213 + A 10.0.10.214 + A 10.0.10.215 + A 10.0.10.216 + A 10.0.10.217 + A 10.0.10.218 + A 10.0.10.219 + A 10.0.10.220 + A 10.0.10.221 + A 10.0.10.222 + A 10.0.10.223 + A 10.0.10.224 + A 10.0.10.225 + A 10.0.10.226 + A 10.0.10.227 + A 10.0.10.228 + A 10.0.10.229 + A 10.0.10.230 + A 10.0.10.231 + A 10.0.10.232 + A 10.0.10.233 + A 10.0.10.234 + A 10.0.10.235 + A 10.0.10.236 + A 10.0.10.237 + A 10.0.10.238 + A 10.0.10.239 + A 10.0.10.240 + A 10.0.10.241 + A 10.0.10.242 + A 10.0.10.243 + A 10.0.10.244 + A 10.0.10.245 + A 10.0.10.246 + A 10.0.10.247 + A 10.0.10.248 + A 10.0.10.249 + A 10.0.10.250 + A 10.0.10.251 + A 10.0.10.252 + A 10.0.10.253 + A 10.0.10.254 + A 10.0.10.255 + A 10.0.11.0 + A 10.0.11.1 + A 10.0.11.2 + A 10.0.11.3 + A 10.0.11.4 + A 10.0.11.5 + A 10.0.11.6 + A 10.0.11.7 + A 10.0.11.8 + A 10.0.11.9 + A 10.0.11.10 + A 10.0.11.11 + A 10.0.11.12 + A 10.0.11.13 + A 10.0.11.14 + A 10.0.11.15 + A 10.0.11.16 + A 10.0.11.17 + A 10.0.11.18 + A 10.0.11.19 + A 10.0.11.20 + A 10.0.11.21 + A 10.0.11.22 + A 10.0.11.23 + A 10.0.11.24 + A 10.0.11.25 + A 10.0.11.26 + A 10.0.11.27 + A 10.0.11.28 + A 10.0.11.29 + A 10.0.11.30 + A 10.0.11.31 + A 10.0.11.32 + A 10.0.11.33 + A 10.0.11.34 + A 10.0.11.35 + A 10.0.11.36 + A 10.0.11.37 + A 10.0.11.38 + A 10.0.11.39 + A 10.0.11.40 + A 10.0.11.41 + A 10.0.11.42 + A 10.0.11.43 + A 10.0.11.44 + A 10.0.11.45 + A 10.0.11.46 + A 10.0.11.47 + A 10.0.11.48 + A 10.0.11.49 + A 10.0.11.50 + A 10.0.11.51 + A 10.0.11.52 + A 10.0.11.53 + A 10.0.11.54 + A 10.0.11.55 + A 10.0.11.56 + A 10.0.11.57 + A 10.0.11.58 + A 10.0.11.59 + A 10.0.11.60 + A 10.0.11.61 + A 10.0.11.62 + A 10.0.11.63 + A 10.0.11.64 + A 10.0.11.65 + A 10.0.11.66 + A 10.0.11.67 + A 10.0.11.68 + A 10.0.11.69 + A 10.0.11.70 + A 10.0.11.71 + A 10.0.11.72 + A 10.0.11.73 + A 10.0.11.74 + A 10.0.11.75 + A 10.0.11.76 + A 10.0.11.77 + A 10.0.11.78 + A 10.0.11.79 + A 10.0.11.80 + A 10.0.11.81 + A 10.0.11.82 + A 10.0.11.83 + A 10.0.11.84 + A 10.0.11.85 + A 10.0.11.86 + A 10.0.11.87 + A 10.0.11.88 + A 10.0.11.89 + A 10.0.11.90 + A 10.0.11.91 + A 10.0.11.92 + A 10.0.11.93 + A 10.0.11.94 + A 10.0.11.95 + A 10.0.11.96 + A 10.0.11.97 + A 10.0.11.98 + A 10.0.11.99 + A 10.0.11.100 + A 10.0.11.101 + A 10.0.11.102 + A 10.0.11.103 + A 10.0.11.104 + A 10.0.11.105 + A 10.0.11.106 + A 10.0.11.107 + A 10.0.11.108 + A 10.0.11.109 + A 10.0.11.110 + A 10.0.11.111 + A 10.0.11.112 + A 10.0.11.113 + A 10.0.11.114 + A 10.0.11.115 + A 10.0.11.116 + A 10.0.11.117 + A 10.0.11.118 + A 10.0.11.119 + A 10.0.11.120 + A 10.0.11.121 + A 10.0.11.122 + A 10.0.11.123 + A 10.0.11.124 + A 10.0.11.125 + A 10.0.11.126 + A 10.0.11.127 + A 10.0.11.128 + A 10.0.11.129 + A 10.0.11.130 + A 10.0.11.131 + A 10.0.11.132 + A 10.0.11.133 + A 10.0.11.134 + A 10.0.11.135 + A 10.0.11.136 + A 10.0.11.137 + A 10.0.11.138 + A 10.0.11.139 + A 10.0.11.140 + A 10.0.11.141 + A 10.0.11.142 + A 10.0.11.143 + A 10.0.11.144 + A 10.0.11.145 + A 10.0.11.146 + A 10.0.11.147 + A 10.0.11.148 + A 10.0.11.149 + A 10.0.11.150 + A 10.0.11.151 + A 10.0.11.152 + A 10.0.11.153 + A 10.0.11.154 + A 10.0.11.155 + A 10.0.11.156 + A 10.0.11.157 + A 10.0.11.158 + A 10.0.11.159 + A 10.0.11.160 + A 10.0.11.161 + A 10.0.11.162 + A 10.0.11.163 + A 10.0.11.164 + A 10.0.11.165 + A 10.0.11.166 + A 10.0.11.167 + A 10.0.11.168 + A 10.0.11.169 + A 10.0.11.170 + A 10.0.11.171 + A 10.0.11.172 + A 10.0.11.173 + A 10.0.11.174 + A 10.0.11.175 + A 10.0.11.176 + A 10.0.11.177 + A 10.0.11.178 + A 10.0.11.179 + A 10.0.11.180 + A 10.0.11.181 + A 10.0.11.182 + A 10.0.11.183 + A 10.0.11.184 + A 10.0.11.185 + A 10.0.11.186 + A 10.0.11.187 + A 10.0.11.188 + A 10.0.11.189 + A 10.0.11.190 + A 10.0.11.191 + A 10.0.11.192 + A 10.0.11.193 + A 10.0.11.194 + A 10.0.11.195 + A 10.0.11.196 + A 10.0.11.197 + A 10.0.11.198 + A 10.0.11.199 + A 10.0.11.200 + A 10.0.11.201 + A 10.0.11.202 + A 10.0.11.203 + A 10.0.11.204 + A 10.0.11.205 + A 10.0.11.206 + A 10.0.11.207 + A 10.0.11.208 + A 10.0.11.209 + A 10.0.11.210 + A 10.0.11.211 + A 10.0.11.212 + A 10.0.11.213 + A 10.0.11.214 + A 10.0.11.215 + A 10.0.11.216 + A 10.0.11.217 + A 10.0.11.218 + A 10.0.11.219 + A 10.0.11.220 + A 10.0.11.221 + A 10.0.11.222 + A 10.0.11.223 + A 10.0.11.224 + A 10.0.11.225 + A 10.0.11.226 + A 10.0.11.227 + A 10.0.11.228 + A 10.0.11.229 + A 10.0.11.230 + A 10.0.11.231 + A 10.0.11.232 + A 10.0.11.233 + A 10.0.11.234 + A 10.0.11.235 + A 10.0.11.236 + A 10.0.11.237 + A 10.0.11.238 + A 10.0.11.239 + A 10.0.11.240 + A 10.0.11.241 + A 10.0.11.242 + A 10.0.11.243 + A 10.0.11.244 + A 10.0.11.245 + A 10.0.11.246 + A 10.0.11.247 + A 10.0.11.248 + A 10.0.11.249 + A 10.0.11.250 + A 10.0.11.251 + A 10.0.11.252 + A 10.0.11.253 + A 10.0.11.254 + A 10.0.11.255 + A 10.0.12.0 + A 10.0.12.1 + A 10.0.12.2 + A 10.0.12.3 + A 10.0.12.4 + A 10.0.12.5 + A 10.0.12.6 + A 10.0.12.7 + A 10.0.12.8 + A 10.0.12.9 + A 10.0.12.10 + A 10.0.12.11 + A 10.0.12.12 + A 10.0.12.13 + A 10.0.12.14 + A 10.0.12.15 + A 10.0.12.16 + A 10.0.12.17 + A 10.0.12.18 + A 10.0.12.19 + A 10.0.12.20 + A 10.0.12.21 + A 10.0.12.22 + A 10.0.12.23 + A 10.0.12.24 + A 10.0.12.25 + A 10.0.12.26 + A 10.0.12.27 + A 10.0.12.28 + A 10.0.12.29 + A 10.0.12.30 + A 10.0.12.31 + A 10.0.12.32 + A 10.0.12.33 + A 10.0.12.34 + A 10.0.12.35 + A 10.0.12.36 + A 10.0.12.37 + A 10.0.12.38 + A 10.0.12.39 + A 10.0.12.40 + A 10.0.12.41 + A 10.0.12.42 + A 10.0.12.43 + A 10.0.12.44 + A 10.0.12.45 + A 10.0.12.46 + A 10.0.12.47 + A 10.0.12.48 + A 10.0.12.49 + A 10.0.12.50 + A 10.0.12.51 + A 10.0.12.52 + A 10.0.12.53 + A 10.0.12.54 + A 10.0.12.55 + A 10.0.12.56 + A 10.0.12.57 + A 10.0.12.58 + A 10.0.12.59 + A 10.0.12.60 + A 10.0.12.61 + A 10.0.12.62 + A 10.0.12.63 + A 10.0.12.64 + A 10.0.12.65 + A 10.0.12.66 + A 10.0.12.67 + A 10.0.12.68 + A 10.0.12.69 + A 10.0.12.70 + A 10.0.12.71 + A 10.0.12.72 + A 10.0.12.73 + A 10.0.12.74 + A 10.0.12.75 + A 10.0.12.76 + A 10.0.12.77 + A 10.0.12.78 + A 10.0.12.79 + A 10.0.12.80 + A 10.0.12.81 + A 10.0.12.82 + A 10.0.12.83 + A 10.0.12.84 + A 10.0.12.85 + A 10.0.12.86 + A 10.0.12.87 + A 10.0.12.88 + A 10.0.12.89 + A 10.0.12.90 + A 10.0.12.91 + A 10.0.12.92 + A 10.0.12.93 + A 10.0.12.94 + A 10.0.12.95 + A 10.0.12.96 + A 10.0.12.97 + A 10.0.12.98 + A 10.0.12.99 + A 10.0.12.100 + A 10.0.12.101 + A 10.0.12.102 + A 10.0.12.103 + A 10.0.12.104 + A 10.0.12.105 + A 10.0.12.106 + A 10.0.12.107 + A 10.0.12.108 + A 10.0.12.109 + A 10.0.12.110 + A 10.0.12.111 + A 10.0.12.112 + A 10.0.12.113 + A 10.0.12.114 + A 10.0.12.115 + A 10.0.12.116 + A 10.0.12.117 + A 10.0.12.118 + A 10.0.12.119 + A 10.0.12.120 + A 10.0.12.121 + A 10.0.12.122 + A 10.0.12.123 + A 10.0.12.124 + A 10.0.12.125 + A 10.0.12.126 + A 10.0.12.127 + A 10.0.12.128 + A 10.0.12.129 + A 10.0.12.130 + A 10.0.12.131 + A 10.0.12.132 + A 10.0.12.133 + A 10.0.12.134 + A 10.0.12.135 + A 10.0.12.136 + A 10.0.12.137 + A 10.0.12.138 + A 10.0.12.139 + A 10.0.12.140 + A 10.0.12.141 + A 10.0.12.142 + A 10.0.12.143 + A 10.0.12.144 + A 10.0.12.145 + A 10.0.12.146 + A 10.0.12.147 + A 10.0.12.148 + A 10.0.12.149 + A 10.0.12.150 + A 10.0.12.151 + A 10.0.12.152 + A 10.0.12.153 + A 10.0.12.154 + A 10.0.12.155 + A 10.0.12.156 + A 10.0.12.157 + A 10.0.12.158 + A 10.0.12.159 + A 10.0.12.160 + A 10.0.12.161 + A 10.0.12.162 + A 10.0.12.163 + A 10.0.12.164 + A 10.0.12.165 + A 10.0.12.166 + A 10.0.12.167 + A 10.0.12.168 + A 10.0.12.169 + A 10.0.12.170 + A 10.0.12.171 + A 10.0.12.172 + A 10.0.12.173 + A 10.0.12.174 + A 10.0.12.175 + A 10.0.12.176 + A 10.0.12.177 + A 10.0.12.178 + A 10.0.12.179 + A 10.0.12.180 + A 10.0.12.181 + A 10.0.12.182 + A 10.0.12.183 + A 10.0.12.184 + A 10.0.12.185 + A 10.0.12.186 + A 10.0.12.187 + A 10.0.12.188 + A 10.0.12.189 + A 10.0.12.190 + A 10.0.12.191 + A 10.0.12.192 + A 10.0.12.193 + A 10.0.12.194 + A 10.0.12.195 + A 10.0.12.196 + A 10.0.12.197 + A 10.0.12.198 + A 10.0.12.199 + A 10.0.12.200 + A 10.0.12.201 + A 10.0.12.202 + A 10.0.12.203 + A 10.0.12.204 + A 10.0.12.205 + A 10.0.12.206 + A 10.0.12.207 + A 10.0.12.208 + A 10.0.12.209 + A 10.0.12.210 + A 10.0.12.211 + A 10.0.12.212 + A 10.0.12.213 + A 10.0.12.214 + A 10.0.12.215 + A 10.0.12.216 + A 10.0.12.217 + A 10.0.12.218 + A 10.0.12.219 + A 10.0.12.220 + A 10.0.12.221 + A 10.0.12.222 + A 10.0.12.223 + A 10.0.12.224 + A 10.0.12.225 + A 10.0.12.226 + A 10.0.12.227 + A 10.0.12.228 + A 10.0.12.229 + A 10.0.12.230 + A 10.0.12.231 + A 10.0.12.232 + A 10.0.12.233 + A 10.0.12.234 + A 10.0.12.235 + A 10.0.12.236 + A 10.0.12.237 + A 10.0.12.238 + A 10.0.12.239 + A 10.0.12.240 + A 10.0.12.241 + A 10.0.12.242 + A 10.0.12.243 + A 10.0.12.244 + A 10.0.12.245 + A 10.0.12.246 + A 10.0.12.247 + A 10.0.12.248 + A 10.0.12.249 + A 10.0.12.250 + A 10.0.12.251 + A 10.0.12.252 + A 10.0.12.253 + A 10.0.12.254 + A 10.0.12.255 + A 10.0.13.0 + A 10.0.13.1 + A 10.0.13.2 + A 10.0.13.3 + A 10.0.13.4 + A 10.0.13.5 + A 10.0.13.6 + A 10.0.13.7 + A 10.0.13.8 + A 10.0.13.9 + A 10.0.13.10 + A 10.0.13.11 + A 10.0.13.12 + A 10.0.13.13 + A 10.0.13.14 + A 10.0.13.15 + A 10.0.13.16 + A 10.0.13.17 + A 10.0.13.18 + A 10.0.13.19 + A 10.0.13.20 + A 10.0.13.21 + A 10.0.13.22 + A 10.0.13.23 + A 10.0.13.24 + A 10.0.13.25 + A 10.0.13.26 + A 10.0.13.27 + A 10.0.13.28 + A 10.0.13.29 + A 10.0.13.30 + A 10.0.13.31 + A 10.0.13.32 + A 10.0.13.33 + A 10.0.13.34 + A 10.0.13.35 + A 10.0.13.36 + A 10.0.13.37 + A 10.0.13.38 + A 10.0.13.39 + A 10.0.13.40 + A 10.0.13.41 + A 10.0.13.42 + A 10.0.13.43 + A 10.0.13.44 + A 10.0.13.45 + A 10.0.13.46 + A 10.0.13.47 + A 10.0.13.48 + A 10.0.13.49 + A 10.0.13.50 + A 10.0.13.51 + A 10.0.13.52 + A 10.0.13.53 + A 10.0.13.54 + A 10.0.13.55 + A 10.0.13.56 + A 10.0.13.57 + A 10.0.13.58 + A 10.0.13.59 + A 10.0.13.60 + A 10.0.13.61 + A 10.0.13.62 + A 10.0.13.63 + A 10.0.13.64 + A 10.0.13.65 + A 10.0.13.66 + A 10.0.13.67 + A 10.0.13.68 + A 10.0.13.69 + A 10.0.13.70 + A 10.0.13.71 + A 10.0.13.72 + A 10.0.13.73 + A 10.0.13.74 + A 10.0.13.75 + A 10.0.13.76 + A 10.0.13.77 + A 10.0.13.78 + A 10.0.13.79 + A 10.0.13.80 + A 10.0.13.81 + A 10.0.13.82 + A 10.0.13.83 + A 10.0.13.84 + A 10.0.13.85 + A 10.0.13.86 + A 10.0.13.87 + A 10.0.13.88 + A 10.0.13.89 + A 10.0.13.90 + A 10.0.13.91 + A 10.0.13.92 + A 10.0.13.93 + A 10.0.13.94 + A 10.0.13.95 + A 10.0.13.96 + A 10.0.13.97 + A 10.0.13.98 + A 10.0.13.99 + A 10.0.13.100 + A 10.0.13.101 + A 10.0.13.102 + A 10.0.13.103 + A 10.0.13.104 + A 10.0.13.105 + A 10.0.13.106 + A 10.0.13.107 + A 10.0.13.108 + A 10.0.13.109 + A 10.0.13.110 + A 10.0.13.111 + A 10.0.13.112 + A 10.0.13.113 + A 10.0.13.114 + A 10.0.13.115 + A 10.0.13.116 + A 10.0.13.117 + A 10.0.13.118 + A 10.0.13.119 + A 10.0.13.120 + A 10.0.13.121 + A 10.0.13.122 + A 10.0.13.123 + A 10.0.13.124 + A 10.0.13.125 + A 10.0.13.126 + A 10.0.13.127 + A 10.0.13.128 + A 10.0.13.129 + A 10.0.13.130 + A 10.0.13.131 + A 10.0.13.132 + A 10.0.13.133 + A 10.0.13.134 + A 10.0.13.135 + A 10.0.13.136 + A 10.0.13.137 + A 10.0.13.138 + A 10.0.13.139 + A 10.0.13.140 + A 10.0.13.141 + A 10.0.13.142 + A 10.0.13.143 + A 10.0.13.144 + A 10.0.13.145 + A 10.0.13.146 + A 10.0.13.147 + A 10.0.13.148 + A 10.0.13.149 + A 10.0.13.150 + A 10.0.13.151 + A 10.0.13.152 + A 10.0.13.153 + A 10.0.13.154 + A 10.0.13.155 + A 10.0.13.156 + A 10.0.13.157 + A 10.0.13.158 + A 10.0.13.159 + A 10.0.13.160 + A 10.0.13.161 + A 10.0.13.162 + A 10.0.13.163 + A 10.0.13.164 + A 10.0.13.165 + A 10.0.13.166 + A 10.0.13.167 + A 10.0.13.168 + A 10.0.13.169 + A 10.0.13.170 + A 10.0.13.171 + A 10.0.13.172 + A 10.0.13.173 + A 10.0.13.174 + A 10.0.13.175 + A 10.0.13.176 + A 10.0.13.177 + A 10.0.13.178 + A 10.0.13.179 + A 10.0.13.180 + A 10.0.13.181 + A 10.0.13.182 + A 10.0.13.183 + A 10.0.13.184 + A 10.0.13.185 + A 10.0.13.186 + A 10.0.13.187 + A 10.0.13.188 + A 10.0.13.189 + A 10.0.13.190 + A 10.0.13.191 + A 10.0.13.192 + A 10.0.13.193 + A 10.0.13.194 + A 10.0.13.195 + A 10.0.13.196 + A 10.0.13.197 + A 10.0.13.198 + A 10.0.13.199 + A 10.0.13.200 + A 10.0.13.201 + A 10.0.13.202 + A 10.0.13.203 + A 10.0.13.204 + A 10.0.13.205 + A 10.0.13.206 + A 10.0.13.207 + A 10.0.13.208 + A 10.0.13.209 + A 10.0.13.210 + A 10.0.13.211 + A 10.0.13.212 + A 10.0.13.213 + A 10.0.13.214 + A 10.0.13.215 + A 10.0.13.216 + A 10.0.13.217 + A 10.0.13.218 + A 10.0.13.219 + A 10.0.13.220 + A 10.0.13.221 + A 10.0.13.222 + A 10.0.13.223 + A 10.0.13.224 + A 10.0.13.225 + A 10.0.13.226 + A 10.0.13.227 + A 10.0.13.228 + A 10.0.13.229 + A 10.0.13.230 + A 10.0.13.231 + A 10.0.13.232 + A 10.0.13.233 + A 10.0.13.234 + A 10.0.13.235 + A 10.0.13.236 + A 10.0.13.237 + A 10.0.13.238 + A 10.0.13.239 + A 10.0.13.240 + A 10.0.13.241 + A 10.0.13.242 + A 10.0.13.243 + A 10.0.13.244 + A 10.0.13.245 + A 10.0.13.246 + A 10.0.13.247 + A 10.0.13.248 + A 10.0.13.249 + A 10.0.13.250 + A 10.0.13.251 + A 10.0.13.252 + A 10.0.13.253 + A 10.0.13.254 + A 10.0.13.255 + A 10.0.14.0 + A 10.0.14.1 + A 10.0.14.2 + A 10.0.14.3 + A 10.0.14.4 + A 10.0.14.5 + A 10.0.14.6 + A 10.0.14.7 + A 10.0.14.8 + A 10.0.14.9 + A 10.0.14.10 + A 10.0.14.11 + A 10.0.14.12 + A 10.0.14.13 + A 10.0.14.14 + A 10.0.14.15 + A 10.0.14.16 + A 10.0.14.17 + A 10.0.14.18 + A 10.0.14.19 + A 10.0.14.20 + A 10.0.14.21 + A 10.0.14.22 + A 10.0.14.23 + A 10.0.14.24 + A 10.0.14.25 + A 10.0.14.26 + A 10.0.14.27 + A 10.0.14.28 + A 10.0.14.29 + A 10.0.14.30 + A 10.0.14.31 + A 10.0.14.32 + A 10.0.14.33 + A 10.0.14.34 + A 10.0.14.35 + A 10.0.14.36 + A 10.0.14.37 + A 10.0.14.38 + A 10.0.14.39 + A 10.0.14.40 + A 10.0.14.41 + A 10.0.14.42 + A 10.0.14.43 + A 10.0.14.44 + A 10.0.14.45 + A 10.0.14.46 + A 10.0.14.47 + A 10.0.14.48 + A 10.0.14.49 + A 10.0.14.50 + A 10.0.14.51 + A 10.0.14.52 + A 10.0.14.53 + A 10.0.14.54 + A 10.0.14.55 + A 10.0.14.56 + A 10.0.14.57 + A 10.0.14.58 + A 10.0.14.59 + A 10.0.14.60 + A 10.0.14.61 + A 10.0.14.62 + A 10.0.14.63 + A 10.0.14.64 + A 10.0.14.65 + A 10.0.14.66 + A 10.0.14.67 + A 10.0.14.68 + A 10.0.14.69 + A 10.0.14.70 + A 10.0.14.71 + A 10.0.14.72 + A 10.0.14.73 + A 10.0.14.74 + A 10.0.14.75 + A 10.0.14.76 + A 10.0.14.77 + A 10.0.14.78 + A 10.0.14.79 + A 10.0.14.80 + A 10.0.14.81 + A 10.0.14.82 + A 10.0.14.83 + A 10.0.14.84 + A 10.0.14.85 + A 10.0.14.86 + A 10.0.14.87 + A 10.0.14.88 + A 10.0.14.89 + A 10.0.14.90 + A 10.0.14.91 + A 10.0.14.92 + A 10.0.14.93 + A 10.0.14.94 + A 10.0.14.95 + A 10.0.14.96 + A 10.0.14.97 + A 10.0.14.98 + A 10.0.14.99 + A 10.0.14.100 + A 10.0.14.101 + A 10.0.14.102 + A 10.0.14.103 + A 10.0.14.104 + A 10.0.14.105 + A 10.0.14.106 + A 10.0.14.107 + A 10.0.14.108 + A 10.0.14.109 + A 10.0.14.110 + A 10.0.14.111 + A 10.0.14.112 + A 10.0.14.113 + A 10.0.14.114 + A 10.0.14.115 + A 10.0.14.116 + A 10.0.14.117 + A 10.0.14.118 + A 10.0.14.119 + A 10.0.14.120 + A 10.0.14.121 + A 10.0.14.122 + A 10.0.14.123 + A 10.0.14.124 + A 10.0.14.125 + A 10.0.14.126 + A 10.0.14.127 + A 10.0.14.128 + A 10.0.14.129 + A 10.0.14.130 + A 10.0.14.131 + A 10.0.14.132 + A 10.0.14.133 + A 10.0.14.134 + A 10.0.14.135 + A 10.0.14.136 + A 10.0.14.137 + A 10.0.14.138 + A 10.0.14.139 + A 10.0.14.140 + A 10.0.14.141 + A 10.0.14.142 + A 10.0.14.143 + A 10.0.14.144 + A 10.0.14.145 + A 10.0.14.146 + A 10.0.14.147 + A 10.0.14.148 + A 10.0.14.149 + A 10.0.14.150 + A 10.0.14.151 + A 10.0.14.152 + A 10.0.14.153 + A 10.0.14.154 + A 10.0.14.155 + A 10.0.14.156 + A 10.0.14.157 + A 10.0.14.158 + A 10.0.14.159 + A 10.0.14.160 + A 10.0.14.161 + A 10.0.14.162 + A 10.0.14.163 + A 10.0.14.164 + A 10.0.14.165 + A 10.0.14.166 + A 10.0.14.167 + A 10.0.14.168 + A 10.0.14.169 + A 10.0.14.170 + A 10.0.14.171 + A 10.0.14.172 + A 10.0.14.173 + A 10.0.14.174 + A 10.0.14.175 + A 10.0.14.176 + A 10.0.14.177 + A 10.0.14.178 + A 10.0.14.179 + A 10.0.14.180 + A 10.0.14.181 + A 10.0.14.182 + A 10.0.14.183 + A 10.0.14.184 + A 10.0.14.185 + A 10.0.14.186 + A 10.0.14.187 + A 10.0.14.188 + A 10.0.14.189 + A 10.0.14.190 + A 10.0.14.191 + A 10.0.14.192 + A 10.0.14.193 + A 10.0.14.194 + A 10.0.14.195 + A 10.0.14.196 + A 10.0.14.197 + A 10.0.14.198 + A 10.0.14.199 + A 10.0.14.200 + A 10.0.14.201 + A 10.0.14.202 + A 10.0.14.203 + A 10.0.14.204 + A 10.0.14.205 + A 10.0.14.206 + A 10.0.14.207 + A 10.0.14.208 + A 10.0.14.209 + A 10.0.14.210 + A 10.0.14.211 + A 10.0.14.212 + A 10.0.14.213 + A 10.0.14.214 + A 10.0.14.215 + A 10.0.14.216 + A 10.0.14.217 + A 10.0.14.218 + A 10.0.14.219 + A 10.0.14.220 + A 10.0.14.221 + A 10.0.14.222 + A 10.0.14.223 + A 10.0.14.224 + A 10.0.14.225 + A 10.0.14.226 + A 10.0.14.227 + A 10.0.14.228 + A 10.0.14.229 + A 10.0.14.230 + A 10.0.14.231 + A 10.0.14.232 + A 10.0.14.233 + A 10.0.14.234 + A 10.0.14.235 + A 10.0.14.236 + A 10.0.14.237 + A 10.0.14.238 + A 10.0.14.239 + A 10.0.14.240 + A 10.0.14.241 + A 10.0.14.242 + A 10.0.14.243 + A 10.0.14.244 + A 10.0.14.245 + A 10.0.14.246 + A 10.0.14.247 + A 10.0.14.248 + A 10.0.14.249 + A 10.0.14.250 + A 10.0.14.251 + A 10.0.14.252 + A 10.0.14.253 + A 10.0.14.254 + A 10.0.14.255 + A 10.0.15.0 + A 10.0.15.1 + A 10.0.15.2 + A 10.0.15.3 + A 10.0.15.4 + A 10.0.15.5 + A 10.0.15.6 + A 10.0.15.7 + A 10.0.15.8 + A 10.0.15.9 + A 10.0.15.10 + A 10.0.15.11 + A 10.0.15.12 + A 10.0.15.13 + A 10.0.15.14 + A 10.0.15.15 + A 10.0.15.16 + A 10.0.15.17 + A 10.0.15.18 + A 10.0.15.19 + A 10.0.15.20 + A 10.0.15.21 + A 10.0.15.22 + A 10.0.15.23 + A 10.0.15.24 + A 10.0.15.25 + A 10.0.15.26 + A 10.0.15.27 + A 10.0.15.28 + A 10.0.15.29 + A 10.0.15.30 + A 10.0.15.31 + A 10.0.15.32 + A 10.0.15.33 + A 10.0.15.34 + A 10.0.15.35 + A 10.0.15.36 + A 10.0.15.37 + A 10.0.15.38 + A 10.0.15.39 + A 10.0.15.40 + A 10.0.15.41 + A 10.0.15.42 + A 10.0.15.43 + A 10.0.15.44 + A 10.0.15.45 + A 10.0.15.46 + A 10.0.15.47 + A 10.0.15.48 + A 10.0.15.49 + A 10.0.15.50 + A 10.0.15.51 + A 10.0.15.52 + A 10.0.15.53 + A 10.0.15.54 + A 10.0.15.55 + A 10.0.15.56 + A 10.0.15.57 + A 10.0.15.58 + A 10.0.15.59 + A 10.0.15.60 + A 10.0.15.61 + A 10.0.15.62 + A 10.0.15.63 + A 10.0.15.64 + A 10.0.15.65 + A 10.0.15.66 + A 10.0.15.67 + A 10.0.15.68 + A 10.0.15.69 + A 10.0.15.70 + A 10.0.15.71 + A 10.0.15.72 + A 10.0.15.73 + A 10.0.15.74 + A 10.0.15.75 + A 10.0.15.76 + A 10.0.15.77 + A 10.0.15.78 + A 10.0.15.79 + A 10.0.15.80 + A 10.0.15.81 + A 10.0.15.82 + A 10.0.15.83 + A 10.0.15.84 + A 10.0.15.85 + A 10.0.15.86 + A 10.0.15.87 + A 10.0.15.88 + A 10.0.15.89 + A 10.0.15.90 + A 10.0.15.91 + A 10.0.15.92 + A 10.0.15.93 + A 10.0.15.94 + A 10.0.15.95 + A 10.0.15.96 + A 10.0.15.97 + A 10.0.15.98 + A 10.0.15.99 + A 10.0.15.100 + A 10.0.15.101 + A 10.0.15.102 + A 10.0.15.103 + A 10.0.15.104 + A 10.0.15.105 + A 10.0.15.106 + A 10.0.15.107 + A 10.0.15.108 + A 10.0.15.109 + A 10.0.15.110 + A 10.0.15.111 + A 10.0.15.112 + A 10.0.15.113 + A 10.0.15.114 + A 10.0.15.115 + A 10.0.15.116 + A 10.0.15.117 + A 10.0.15.118 + A 10.0.15.119 + A 10.0.15.120 + A 10.0.15.121 + A 10.0.15.122 + A 10.0.15.123 + A 10.0.15.124 + A 10.0.15.125 + A 10.0.15.126 + A 10.0.15.127 + A 10.0.15.128 + A 10.0.15.129 + A 10.0.15.130 + A 10.0.15.131 + A 10.0.15.132 + A 10.0.15.133 + A 10.0.15.134 + A 10.0.15.135 + A 10.0.15.136 + A 10.0.15.137 + A 10.0.15.138 + A 10.0.15.139 + A 10.0.15.140 + A 10.0.15.141 + A 10.0.15.142 + A 10.0.15.143 + A 10.0.15.144 + A 10.0.15.145 + A 10.0.15.146 + A 10.0.15.147 + A 10.0.15.148 + A 10.0.15.149 + A 10.0.15.150 + A 10.0.15.151 + A 10.0.15.152 + A 10.0.15.153 + A 10.0.15.154 + A 10.0.15.155 + A 10.0.15.156 + A 10.0.15.157 + A 10.0.15.158 + A 10.0.15.159 +5000 A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 + A 10.0.3.232 + A 10.0.3.233 + A 10.0.3.234 + A 10.0.3.235 + A 10.0.3.236 + A 10.0.3.237 + A 10.0.3.238 + A 10.0.3.239 + A 10.0.3.240 + A 10.0.3.241 + A 10.0.3.242 + A 10.0.3.243 + A 10.0.3.244 + A 10.0.3.245 + A 10.0.3.246 + A 10.0.3.247 + A 10.0.3.248 + A 10.0.3.249 + A 10.0.3.250 + A 10.0.3.251 + A 10.0.3.252 + A 10.0.3.253 + A 10.0.3.254 + A 10.0.3.255 + A 10.0.4.0 + A 10.0.4.1 + A 10.0.4.2 + A 10.0.4.3 + A 10.0.4.4 + A 10.0.4.5 + A 10.0.4.6 + A 10.0.4.7 + A 10.0.4.8 + A 10.0.4.9 + A 10.0.4.10 + A 10.0.4.11 + A 10.0.4.12 + A 10.0.4.13 + A 10.0.4.14 + A 10.0.4.15 + A 10.0.4.16 + A 10.0.4.17 + A 10.0.4.18 + A 10.0.4.19 + A 10.0.4.20 + A 10.0.4.21 + A 10.0.4.22 + A 10.0.4.23 + A 10.0.4.24 + A 10.0.4.25 + A 10.0.4.26 + A 10.0.4.27 + A 10.0.4.28 + A 10.0.4.29 + A 10.0.4.30 + A 10.0.4.31 + A 10.0.4.32 + A 10.0.4.33 + A 10.0.4.34 + A 10.0.4.35 + A 10.0.4.36 + A 10.0.4.37 + A 10.0.4.38 + A 10.0.4.39 + A 10.0.4.40 + A 10.0.4.41 + A 10.0.4.42 + A 10.0.4.43 + A 10.0.4.44 + A 10.0.4.45 + A 10.0.4.46 + A 10.0.4.47 + A 10.0.4.48 + A 10.0.4.49 + A 10.0.4.50 + A 10.0.4.51 + A 10.0.4.52 + A 10.0.4.53 + A 10.0.4.54 + A 10.0.4.55 + A 10.0.4.56 + A 10.0.4.57 + A 10.0.4.58 + A 10.0.4.59 + A 10.0.4.60 + A 10.0.4.61 + A 10.0.4.62 + A 10.0.4.63 + A 10.0.4.64 + A 10.0.4.65 + A 10.0.4.66 + A 10.0.4.67 + A 10.0.4.68 + A 10.0.4.69 + A 10.0.4.70 + A 10.0.4.71 + A 10.0.4.72 + A 10.0.4.73 + A 10.0.4.74 + A 10.0.4.75 + A 10.0.4.76 + A 10.0.4.77 + A 10.0.4.78 + A 10.0.4.79 + A 10.0.4.80 + A 10.0.4.81 + A 10.0.4.82 + A 10.0.4.83 + A 10.0.4.84 + A 10.0.4.85 + A 10.0.4.86 + A 10.0.4.87 + A 10.0.4.88 + A 10.0.4.89 + A 10.0.4.90 + A 10.0.4.91 + A 10.0.4.92 + A 10.0.4.93 + A 10.0.4.94 + A 10.0.4.95 + A 10.0.4.96 + A 10.0.4.97 + A 10.0.4.98 + A 10.0.4.99 + A 10.0.4.100 + A 10.0.4.101 + A 10.0.4.102 + A 10.0.4.103 + A 10.0.4.104 + A 10.0.4.105 + A 10.0.4.106 + A 10.0.4.107 + A 10.0.4.108 + A 10.0.4.109 + A 10.0.4.110 + A 10.0.4.111 + A 10.0.4.112 + A 10.0.4.113 + A 10.0.4.114 + A 10.0.4.115 + A 10.0.4.116 + A 10.0.4.117 + A 10.0.4.118 + A 10.0.4.119 + A 10.0.4.120 + A 10.0.4.121 + A 10.0.4.122 + A 10.0.4.123 + A 10.0.4.124 + A 10.0.4.125 + A 10.0.4.126 + A 10.0.4.127 + A 10.0.4.128 + A 10.0.4.129 + A 10.0.4.130 + A 10.0.4.131 + A 10.0.4.132 + A 10.0.4.133 + A 10.0.4.134 + A 10.0.4.135 + A 10.0.4.136 + A 10.0.4.137 + A 10.0.4.138 + A 10.0.4.139 + A 10.0.4.140 + A 10.0.4.141 + A 10.0.4.142 + A 10.0.4.143 + A 10.0.4.144 + A 10.0.4.145 + A 10.0.4.146 + A 10.0.4.147 + A 10.0.4.148 + A 10.0.4.149 + A 10.0.4.150 + A 10.0.4.151 + A 10.0.4.152 + A 10.0.4.153 + A 10.0.4.154 + A 10.0.4.155 + A 10.0.4.156 + A 10.0.4.157 + A 10.0.4.158 + A 10.0.4.159 + A 10.0.4.160 + A 10.0.4.161 + A 10.0.4.162 + A 10.0.4.163 + A 10.0.4.164 + A 10.0.4.165 + A 10.0.4.166 + A 10.0.4.167 + A 10.0.4.168 + A 10.0.4.169 + A 10.0.4.170 + A 10.0.4.171 + A 10.0.4.172 + A 10.0.4.173 + A 10.0.4.174 + A 10.0.4.175 + A 10.0.4.176 + A 10.0.4.177 + A 10.0.4.178 + A 10.0.4.179 + A 10.0.4.180 + A 10.0.4.181 + A 10.0.4.182 + A 10.0.4.183 + A 10.0.4.184 + A 10.0.4.185 + A 10.0.4.186 + A 10.0.4.187 + A 10.0.4.188 + A 10.0.4.189 + A 10.0.4.190 + A 10.0.4.191 + A 10.0.4.192 + A 10.0.4.193 + A 10.0.4.194 + A 10.0.4.195 + A 10.0.4.196 + A 10.0.4.197 + A 10.0.4.198 + A 10.0.4.199 + A 10.0.4.200 + A 10.0.4.201 + A 10.0.4.202 + A 10.0.4.203 + A 10.0.4.204 + A 10.0.4.205 + A 10.0.4.206 + A 10.0.4.207 + A 10.0.4.208 + A 10.0.4.209 + A 10.0.4.210 + A 10.0.4.211 + A 10.0.4.212 + A 10.0.4.213 + A 10.0.4.214 + A 10.0.4.215 + A 10.0.4.216 + A 10.0.4.217 + A 10.0.4.218 + A 10.0.4.219 + A 10.0.4.220 + A 10.0.4.221 + A 10.0.4.222 + A 10.0.4.223 + A 10.0.4.224 + A 10.0.4.225 + A 10.0.4.226 + A 10.0.4.227 + A 10.0.4.228 + A 10.0.4.229 + A 10.0.4.230 + A 10.0.4.231 + A 10.0.4.232 + A 10.0.4.233 + A 10.0.4.234 + A 10.0.4.235 + A 10.0.4.236 + A 10.0.4.237 + A 10.0.4.238 + A 10.0.4.239 + A 10.0.4.240 + A 10.0.4.241 + A 10.0.4.242 + A 10.0.4.243 + A 10.0.4.244 + A 10.0.4.245 + A 10.0.4.246 + A 10.0.4.247 + A 10.0.4.248 + A 10.0.4.249 + A 10.0.4.250 + A 10.0.4.251 + A 10.0.4.252 + A 10.0.4.253 + A 10.0.4.254 + A 10.0.4.255 + A 10.0.5.0 + A 10.0.5.1 + A 10.0.5.2 + A 10.0.5.3 + A 10.0.5.4 + A 10.0.5.5 + A 10.0.5.6 + A 10.0.5.7 + A 10.0.5.8 + A 10.0.5.9 + A 10.0.5.10 + A 10.0.5.11 + A 10.0.5.12 + A 10.0.5.13 + A 10.0.5.14 + A 10.0.5.15 + A 10.0.5.16 + A 10.0.5.17 + A 10.0.5.18 + A 10.0.5.19 + A 10.0.5.20 + A 10.0.5.21 + A 10.0.5.22 + A 10.0.5.23 + A 10.0.5.24 + A 10.0.5.25 + A 10.0.5.26 + A 10.0.5.27 + A 10.0.5.28 + A 10.0.5.29 + A 10.0.5.30 + A 10.0.5.31 + A 10.0.5.32 + A 10.0.5.33 + A 10.0.5.34 + A 10.0.5.35 + A 10.0.5.36 + A 10.0.5.37 + A 10.0.5.38 + A 10.0.5.39 + A 10.0.5.40 + A 10.0.5.41 + A 10.0.5.42 + A 10.0.5.43 + A 10.0.5.44 + A 10.0.5.45 + A 10.0.5.46 + A 10.0.5.47 + A 10.0.5.48 + A 10.0.5.49 + A 10.0.5.50 + A 10.0.5.51 + A 10.0.5.52 + A 10.0.5.53 + A 10.0.5.54 + A 10.0.5.55 + A 10.0.5.56 + A 10.0.5.57 + A 10.0.5.58 + A 10.0.5.59 + A 10.0.5.60 + A 10.0.5.61 + A 10.0.5.62 + A 10.0.5.63 + A 10.0.5.64 + A 10.0.5.65 + A 10.0.5.66 + A 10.0.5.67 + A 10.0.5.68 + A 10.0.5.69 + A 10.0.5.70 + A 10.0.5.71 + A 10.0.5.72 + A 10.0.5.73 + A 10.0.5.74 + A 10.0.5.75 + A 10.0.5.76 + A 10.0.5.77 + A 10.0.5.78 + A 10.0.5.79 + A 10.0.5.80 + A 10.0.5.81 + A 10.0.5.82 + A 10.0.5.83 + A 10.0.5.84 + A 10.0.5.85 + A 10.0.5.86 + A 10.0.5.87 + A 10.0.5.88 + A 10.0.5.89 + A 10.0.5.90 + A 10.0.5.91 + A 10.0.5.92 + A 10.0.5.93 + A 10.0.5.94 + A 10.0.5.95 + A 10.0.5.96 + A 10.0.5.97 + A 10.0.5.98 + A 10.0.5.99 + A 10.0.5.100 + A 10.0.5.101 + A 10.0.5.102 + A 10.0.5.103 + A 10.0.5.104 + A 10.0.5.105 + A 10.0.5.106 + A 10.0.5.107 + A 10.0.5.108 + A 10.0.5.109 + A 10.0.5.110 + A 10.0.5.111 + A 10.0.5.112 + A 10.0.5.113 + A 10.0.5.114 + A 10.0.5.115 + A 10.0.5.116 + A 10.0.5.117 + A 10.0.5.118 + A 10.0.5.119 + A 10.0.5.120 + A 10.0.5.121 + A 10.0.5.122 + A 10.0.5.123 + A 10.0.5.124 + A 10.0.5.125 + A 10.0.5.126 + A 10.0.5.127 + A 10.0.5.128 + A 10.0.5.129 + A 10.0.5.130 + A 10.0.5.131 + A 10.0.5.132 + A 10.0.5.133 + A 10.0.5.134 + A 10.0.5.135 + A 10.0.5.136 + A 10.0.5.137 + A 10.0.5.138 + A 10.0.5.139 + A 10.0.5.140 + A 10.0.5.141 + A 10.0.5.142 + A 10.0.5.143 + A 10.0.5.144 + A 10.0.5.145 + A 10.0.5.146 + A 10.0.5.147 + A 10.0.5.148 + A 10.0.5.149 + A 10.0.5.150 + A 10.0.5.151 + A 10.0.5.152 + A 10.0.5.153 + A 10.0.5.154 + A 10.0.5.155 + A 10.0.5.156 + A 10.0.5.157 + A 10.0.5.158 + A 10.0.5.159 + A 10.0.5.160 + A 10.0.5.161 + A 10.0.5.162 + A 10.0.5.163 + A 10.0.5.164 + A 10.0.5.165 + A 10.0.5.166 + A 10.0.5.167 + A 10.0.5.168 + A 10.0.5.169 + A 10.0.5.170 + A 10.0.5.171 + A 10.0.5.172 + A 10.0.5.173 + A 10.0.5.174 + A 10.0.5.175 + A 10.0.5.176 + A 10.0.5.177 + A 10.0.5.178 + A 10.0.5.179 + A 10.0.5.180 + A 10.0.5.181 + A 10.0.5.182 + A 10.0.5.183 + A 10.0.5.184 + A 10.0.5.185 + A 10.0.5.186 + A 10.0.5.187 + A 10.0.5.188 + A 10.0.5.189 + A 10.0.5.190 + A 10.0.5.191 + A 10.0.5.192 + A 10.0.5.193 + A 10.0.5.194 + A 10.0.5.195 + A 10.0.5.196 + A 10.0.5.197 + A 10.0.5.198 + A 10.0.5.199 + A 10.0.5.200 + A 10.0.5.201 + A 10.0.5.202 + A 10.0.5.203 + A 10.0.5.204 + A 10.0.5.205 + A 10.0.5.206 + A 10.0.5.207 + A 10.0.5.208 + A 10.0.5.209 + A 10.0.5.210 + A 10.0.5.211 + A 10.0.5.212 + A 10.0.5.213 + A 10.0.5.214 + A 10.0.5.215 + A 10.0.5.216 + A 10.0.5.217 + A 10.0.5.218 + A 10.0.5.219 + A 10.0.5.220 + A 10.0.5.221 + A 10.0.5.222 + A 10.0.5.223 + A 10.0.5.224 + A 10.0.5.225 + A 10.0.5.226 + A 10.0.5.227 + A 10.0.5.228 + A 10.0.5.229 + A 10.0.5.230 + A 10.0.5.231 + A 10.0.5.232 + A 10.0.5.233 + A 10.0.5.234 + A 10.0.5.235 + A 10.0.5.236 + A 10.0.5.237 + A 10.0.5.238 + A 10.0.5.239 + A 10.0.5.240 + A 10.0.5.241 + A 10.0.5.242 + A 10.0.5.243 + A 10.0.5.244 + A 10.0.5.245 + A 10.0.5.246 + A 10.0.5.247 + A 10.0.5.248 + A 10.0.5.249 + A 10.0.5.250 + A 10.0.5.251 + A 10.0.5.252 + A 10.0.5.253 + A 10.0.5.254 + A 10.0.5.255 + A 10.0.6.0 + A 10.0.6.1 + A 10.0.6.2 + A 10.0.6.3 + A 10.0.6.4 + A 10.0.6.5 + A 10.0.6.6 + A 10.0.6.7 + A 10.0.6.8 + A 10.0.6.9 + A 10.0.6.10 + A 10.0.6.11 + A 10.0.6.12 + A 10.0.6.13 + A 10.0.6.14 + A 10.0.6.15 + A 10.0.6.16 + A 10.0.6.17 + A 10.0.6.18 + A 10.0.6.19 + A 10.0.6.20 + A 10.0.6.21 + A 10.0.6.22 + A 10.0.6.23 + A 10.0.6.24 + A 10.0.6.25 + A 10.0.6.26 + A 10.0.6.27 + A 10.0.6.28 + A 10.0.6.29 + A 10.0.6.30 + A 10.0.6.31 + A 10.0.6.32 + A 10.0.6.33 + A 10.0.6.34 + A 10.0.6.35 + A 10.0.6.36 + A 10.0.6.37 + A 10.0.6.38 + A 10.0.6.39 + A 10.0.6.40 + A 10.0.6.41 + A 10.0.6.42 + A 10.0.6.43 + A 10.0.6.44 + A 10.0.6.45 + A 10.0.6.46 + A 10.0.6.47 + A 10.0.6.48 + A 10.0.6.49 + A 10.0.6.50 + A 10.0.6.51 + A 10.0.6.52 + A 10.0.6.53 + A 10.0.6.54 + A 10.0.6.55 + A 10.0.6.56 + A 10.0.6.57 + A 10.0.6.58 + A 10.0.6.59 + A 10.0.6.60 + A 10.0.6.61 + A 10.0.6.62 + A 10.0.6.63 + A 10.0.6.64 + A 10.0.6.65 + A 10.0.6.66 + A 10.0.6.67 + A 10.0.6.68 + A 10.0.6.69 + A 10.0.6.70 + A 10.0.6.71 + A 10.0.6.72 + A 10.0.6.73 + A 10.0.6.74 + A 10.0.6.75 + A 10.0.6.76 + A 10.0.6.77 + A 10.0.6.78 + A 10.0.6.79 + A 10.0.6.80 + A 10.0.6.81 + A 10.0.6.82 + A 10.0.6.83 + A 10.0.6.84 + A 10.0.6.85 + A 10.0.6.86 + A 10.0.6.87 + A 10.0.6.88 + A 10.0.6.89 + A 10.0.6.90 + A 10.0.6.91 + A 10.0.6.92 + A 10.0.6.93 + A 10.0.6.94 + A 10.0.6.95 + A 10.0.6.96 + A 10.0.6.97 + A 10.0.6.98 + A 10.0.6.99 + A 10.0.6.100 + A 10.0.6.101 + A 10.0.6.102 + A 10.0.6.103 + A 10.0.6.104 + A 10.0.6.105 + A 10.0.6.106 + A 10.0.6.107 + A 10.0.6.108 + A 10.0.6.109 + A 10.0.6.110 + A 10.0.6.111 + A 10.0.6.112 + A 10.0.6.113 + A 10.0.6.114 + A 10.0.6.115 + A 10.0.6.116 + A 10.0.6.117 + A 10.0.6.118 + A 10.0.6.119 + A 10.0.6.120 + A 10.0.6.121 + A 10.0.6.122 + A 10.0.6.123 + A 10.0.6.124 + A 10.0.6.125 + A 10.0.6.126 + A 10.0.6.127 + A 10.0.6.128 + A 10.0.6.129 + A 10.0.6.130 + A 10.0.6.131 + A 10.0.6.132 + A 10.0.6.133 + A 10.0.6.134 + A 10.0.6.135 + A 10.0.6.136 + A 10.0.6.137 + A 10.0.6.138 + A 10.0.6.139 + A 10.0.6.140 + A 10.0.6.141 + A 10.0.6.142 + A 10.0.6.143 + A 10.0.6.144 + A 10.0.6.145 + A 10.0.6.146 + A 10.0.6.147 + A 10.0.6.148 + A 10.0.6.149 + A 10.0.6.150 + A 10.0.6.151 + A 10.0.6.152 + A 10.0.6.153 + A 10.0.6.154 + A 10.0.6.155 + A 10.0.6.156 + A 10.0.6.157 + A 10.0.6.158 + A 10.0.6.159 + A 10.0.6.160 + A 10.0.6.161 + A 10.0.6.162 + A 10.0.6.163 + A 10.0.6.164 + A 10.0.6.165 + A 10.0.6.166 + A 10.0.6.167 + A 10.0.6.168 + A 10.0.6.169 + A 10.0.6.170 + A 10.0.6.171 + A 10.0.6.172 + A 10.0.6.173 + A 10.0.6.174 + A 10.0.6.175 + A 10.0.6.176 + A 10.0.6.177 + A 10.0.6.178 + A 10.0.6.179 + A 10.0.6.180 + A 10.0.6.181 + A 10.0.6.182 + A 10.0.6.183 + A 10.0.6.184 + A 10.0.6.185 + A 10.0.6.186 + A 10.0.6.187 + A 10.0.6.188 + A 10.0.6.189 + A 10.0.6.190 + A 10.0.6.191 + A 10.0.6.192 + A 10.0.6.193 + A 10.0.6.194 + A 10.0.6.195 + A 10.0.6.196 + A 10.0.6.197 + A 10.0.6.198 + A 10.0.6.199 + A 10.0.6.200 + A 10.0.6.201 + A 10.0.6.202 + A 10.0.6.203 + A 10.0.6.204 + A 10.0.6.205 + A 10.0.6.206 + A 10.0.6.207 + A 10.0.6.208 + A 10.0.6.209 + A 10.0.6.210 + A 10.0.6.211 + A 10.0.6.212 + A 10.0.6.213 + A 10.0.6.214 + A 10.0.6.215 + A 10.0.6.216 + A 10.0.6.217 + A 10.0.6.218 + A 10.0.6.219 + A 10.0.6.220 + A 10.0.6.221 + A 10.0.6.222 + A 10.0.6.223 + A 10.0.6.224 + A 10.0.6.225 + A 10.0.6.226 + A 10.0.6.227 + A 10.0.6.228 + A 10.0.6.229 + A 10.0.6.230 + A 10.0.6.231 + A 10.0.6.232 + A 10.0.6.233 + A 10.0.6.234 + A 10.0.6.235 + A 10.0.6.236 + A 10.0.6.237 + A 10.0.6.238 + A 10.0.6.239 + A 10.0.6.240 + A 10.0.6.241 + A 10.0.6.242 + A 10.0.6.243 + A 10.0.6.244 + A 10.0.6.245 + A 10.0.6.246 + A 10.0.6.247 + A 10.0.6.248 + A 10.0.6.249 + A 10.0.6.250 + A 10.0.6.251 + A 10.0.6.252 + A 10.0.6.253 + A 10.0.6.254 + A 10.0.6.255 + A 10.0.7.0 + A 10.0.7.1 + A 10.0.7.2 + A 10.0.7.3 + A 10.0.7.4 + A 10.0.7.5 + A 10.0.7.6 + A 10.0.7.7 + A 10.0.7.8 + A 10.0.7.9 + A 10.0.7.10 + A 10.0.7.11 + A 10.0.7.12 + A 10.0.7.13 + A 10.0.7.14 + A 10.0.7.15 + A 10.0.7.16 + A 10.0.7.17 + A 10.0.7.18 + A 10.0.7.19 + A 10.0.7.20 + A 10.0.7.21 + A 10.0.7.22 + A 10.0.7.23 + A 10.0.7.24 + A 10.0.7.25 + A 10.0.7.26 + A 10.0.7.27 + A 10.0.7.28 + A 10.0.7.29 + A 10.0.7.30 + A 10.0.7.31 + A 10.0.7.32 + A 10.0.7.33 + A 10.0.7.34 + A 10.0.7.35 + A 10.0.7.36 + A 10.0.7.37 + A 10.0.7.38 + A 10.0.7.39 + A 10.0.7.40 + A 10.0.7.41 + A 10.0.7.42 + A 10.0.7.43 + A 10.0.7.44 + A 10.0.7.45 + A 10.0.7.46 + A 10.0.7.47 + A 10.0.7.48 + A 10.0.7.49 + A 10.0.7.50 + A 10.0.7.51 + A 10.0.7.52 + A 10.0.7.53 + A 10.0.7.54 + A 10.0.7.55 + A 10.0.7.56 + A 10.0.7.57 + A 10.0.7.58 + A 10.0.7.59 + A 10.0.7.60 + A 10.0.7.61 + A 10.0.7.62 + A 10.0.7.63 + A 10.0.7.64 + A 10.0.7.65 + A 10.0.7.66 + A 10.0.7.67 + A 10.0.7.68 + A 10.0.7.69 + A 10.0.7.70 + A 10.0.7.71 + A 10.0.7.72 + A 10.0.7.73 + A 10.0.7.74 + A 10.0.7.75 + A 10.0.7.76 + A 10.0.7.77 + A 10.0.7.78 + A 10.0.7.79 + A 10.0.7.80 + A 10.0.7.81 + A 10.0.7.82 + A 10.0.7.83 + A 10.0.7.84 + A 10.0.7.85 + A 10.0.7.86 + A 10.0.7.87 + A 10.0.7.88 + A 10.0.7.89 + A 10.0.7.90 + A 10.0.7.91 + A 10.0.7.92 + A 10.0.7.93 + A 10.0.7.94 + A 10.0.7.95 + A 10.0.7.96 + A 10.0.7.97 + A 10.0.7.98 + A 10.0.7.99 + A 10.0.7.100 + A 10.0.7.101 + A 10.0.7.102 + A 10.0.7.103 + A 10.0.7.104 + A 10.0.7.105 + A 10.0.7.106 + A 10.0.7.107 + A 10.0.7.108 + A 10.0.7.109 + A 10.0.7.110 + A 10.0.7.111 + A 10.0.7.112 + A 10.0.7.113 + A 10.0.7.114 + A 10.0.7.115 + A 10.0.7.116 + A 10.0.7.117 + A 10.0.7.118 + A 10.0.7.119 + A 10.0.7.120 + A 10.0.7.121 + A 10.0.7.122 + A 10.0.7.123 + A 10.0.7.124 + A 10.0.7.125 + A 10.0.7.126 + A 10.0.7.127 + A 10.0.7.128 + A 10.0.7.129 + A 10.0.7.130 + A 10.0.7.131 + A 10.0.7.132 + A 10.0.7.133 + A 10.0.7.134 + A 10.0.7.135 + A 10.0.7.136 + A 10.0.7.137 + A 10.0.7.138 + A 10.0.7.139 + A 10.0.7.140 + A 10.0.7.141 + A 10.0.7.142 + A 10.0.7.143 + A 10.0.7.144 + A 10.0.7.145 + A 10.0.7.146 + A 10.0.7.147 + A 10.0.7.148 + A 10.0.7.149 + A 10.0.7.150 + A 10.0.7.151 + A 10.0.7.152 + A 10.0.7.153 + A 10.0.7.154 + A 10.0.7.155 + A 10.0.7.156 + A 10.0.7.157 + A 10.0.7.158 + A 10.0.7.159 + A 10.0.7.160 + A 10.0.7.161 + A 10.0.7.162 + A 10.0.7.163 + A 10.0.7.164 + A 10.0.7.165 + A 10.0.7.166 + A 10.0.7.167 + A 10.0.7.168 + A 10.0.7.169 + A 10.0.7.170 + A 10.0.7.171 + A 10.0.7.172 + A 10.0.7.173 + A 10.0.7.174 + A 10.0.7.175 + A 10.0.7.176 + A 10.0.7.177 + A 10.0.7.178 + A 10.0.7.179 + A 10.0.7.180 + A 10.0.7.181 + A 10.0.7.182 + A 10.0.7.183 + A 10.0.7.184 + A 10.0.7.185 + A 10.0.7.186 + A 10.0.7.187 + A 10.0.7.188 + A 10.0.7.189 + A 10.0.7.190 + A 10.0.7.191 + A 10.0.7.192 + A 10.0.7.193 + A 10.0.7.194 + A 10.0.7.195 + A 10.0.7.196 + A 10.0.7.197 + A 10.0.7.198 + A 10.0.7.199 + A 10.0.7.200 + A 10.0.7.201 + A 10.0.7.202 + A 10.0.7.203 + A 10.0.7.204 + A 10.0.7.205 + A 10.0.7.206 + A 10.0.7.207 + A 10.0.7.208 + A 10.0.7.209 + A 10.0.7.210 + A 10.0.7.211 + A 10.0.7.212 + A 10.0.7.213 + A 10.0.7.214 + A 10.0.7.215 + A 10.0.7.216 + A 10.0.7.217 + A 10.0.7.218 + A 10.0.7.219 + A 10.0.7.220 + A 10.0.7.221 + A 10.0.7.222 + A 10.0.7.223 + A 10.0.7.224 + A 10.0.7.225 + A 10.0.7.226 + A 10.0.7.227 + A 10.0.7.228 + A 10.0.7.229 + A 10.0.7.230 + A 10.0.7.231 + A 10.0.7.232 + A 10.0.7.233 + A 10.0.7.234 + A 10.0.7.235 + A 10.0.7.236 + A 10.0.7.237 + A 10.0.7.238 + A 10.0.7.239 + A 10.0.7.240 + A 10.0.7.241 + A 10.0.7.242 + A 10.0.7.243 + A 10.0.7.244 + A 10.0.7.245 + A 10.0.7.246 + A 10.0.7.247 + A 10.0.7.248 + A 10.0.7.249 + A 10.0.7.250 + A 10.0.7.251 + A 10.0.7.252 + A 10.0.7.253 + A 10.0.7.254 + A 10.0.7.255 + A 10.0.8.0 + A 10.0.8.1 + A 10.0.8.2 + A 10.0.8.3 + A 10.0.8.4 + A 10.0.8.5 + A 10.0.8.6 + A 10.0.8.7 + A 10.0.8.8 + A 10.0.8.9 + A 10.0.8.10 + A 10.0.8.11 + A 10.0.8.12 + A 10.0.8.13 + A 10.0.8.14 + A 10.0.8.15 + A 10.0.8.16 + A 10.0.8.17 + A 10.0.8.18 + A 10.0.8.19 + A 10.0.8.20 + A 10.0.8.21 + A 10.0.8.22 + A 10.0.8.23 + A 10.0.8.24 + A 10.0.8.25 + A 10.0.8.26 + A 10.0.8.27 + A 10.0.8.28 + A 10.0.8.29 + A 10.0.8.30 + A 10.0.8.31 + A 10.0.8.32 + A 10.0.8.33 + A 10.0.8.34 + A 10.0.8.35 + A 10.0.8.36 + A 10.0.8.37 + A 10.0.8.38 + A 10.0.8.39 + A 10.0.8.40 + A 10.0.8.41 + A 10.0.8.42 + A 10.0.8.43 + A 10.0.8.44 + A 10.0.8.45 + A 10.0.8.46 + A 10.0.8.47 + A 10.0.8.48 + A 10.0.8.49 + A 10.0.8.50 + A 10.0.8.51 + A 10.0.8.52 + A 10.0.8.53 + A 10.0.8.54 + A 10.0.8.55 + A 10.0.8.56 + A 10.0.8.57 + A 10.0.8.58 + A 10.0.8.59 + A 10.0.8.60 + A 10.0.8.61 + A 10.0.8.62 + A 10.0.8.63 + A 10.0.8.64 + A 10.0.8.65 + A 10.0.8.66 + A 10.0.8.67 + A 10.0.8.68 + A 10.0.8.69 + A 10.0.8.70 + A 10.0.8.71 + A 10.0.8.72 + A 10.0.8.73 + A 10.0.8.74 + A 10.0.8.75 + A 10.0.8.76 + A 10.0.8.77 + A 10.0.8.78 + A 10.0.8.79 + A 10.0.8.80 + A 10.0.8.81 + A 10.0.8.82 + A 10.0.8.83 + A 10.0.8.84 + A 10.0.8.85 + A 10.0.8.86 + A 10.0.8.87 + A 10.0.8.88 + A 10.0.8.89 + A 10.0.8.90 + A 10.0.8.91 + A 10.0.8.92 + A 10.0.8.93 + A 10.0.8.94 + A 10.0.8.95 + A 10.0.8.96 + A 10.0.8.97 + A 10.0.8.98 + A 10.0.8.99 + A 10.0.8.100 + A 10.0.8.101 + A 10.0.8.102 + A 10.0.8.103 + A 10.0.8.104 + A 10.0.8.105 + A 10.0.8.106 + A 10.0.8.107 + A 10.0.8.108 + A 10.0.8.109 + A 10.0.8.110 + A 10.0.8.111 + A 10.0.8.112 + A 10.0.8.113 + A 10.0.8.114 + A 10.0.8.115 + A 10.0.8.116 + A 10.0.8.117 + A 10.0.8.118 + A 10.0.8.119 + A 10.0.8.120 + A 10.0.8.121 + A 10.0.8.122 + A 10.0.8.123 + A 10.0.8.124 + A 10.0.8.125 + A 10.0.8.126 + A 10.0.8.127 + A 10.0.8.128 + A 10.0.8.129 + A 10.0.8.130 + A 10.0.8.131 + A 10.0.8.132 + A 10.0.8.133 + A 10.0.8.134 + A 10.0.8.135 + A 10.0.8.136 + A 10.0.8.137 + A 10.0.8.138 + A 10.0.8.139 + A 10.0.8.140 + A 10.0.8.141 + A 10.0.8.142 + A 10.0.8.143 + A 10.0.8.144 + A 10.0.8.145 + A 10.0.8.146 + A 10.0.8.147 + A 10.0.8.148 + A 10.0.8.149 + A 10.0.8.150 + A 10.0.8.151 + A 10.0.8.152 + A 10.0.8.153 + A 10.0.8.154 + A 10.0.8.155 + A 10.0.8.156 + A 10.0.8.157 + A 10.0.8.158 + A 10.0.8.159 + A 10.0.8.160 + A 10.0.8.161 + A 10.0.8.162 + A 10.0.8.163 + A 10.0.8.164 + A 10.0.8.165 + A 10.0.8.166 + A 10.0.8.167 + A 10.0.8.168 + A 10.0.8.169 + A 10.0.8.170 + A 10.0.8.171 + A 10.0.8.172 + A 10.0.8.173 + A 10.0.8.174 + A 10.0.8.175 + A 10.0.8.176 + A 10.0.8.177 + A 10.0.8.178 + A 10.0.8.179 + A 10.0.8.180 + A 10.0.8.181 + A 10.0.8.182 + A 10.0.8.183 + A 10.0.8.184 + A 10.0.8.185 + A 10.0.8.186 + A 10.0.8.187 + A 10.0.8.188 + A 10.0.8.189 + A 10.0.8.190 + A 10.0.8.191 + A 10.0.8.192 + A 10.0.8.193 + A 10.0.8.194 + A 10.0.8.195 + A 10.0.8.196 + A 10.0.8.197 + A 10.0.8.198 + A 10.0.8.199 + A 10.0.8.200 + A 10.0.8.201 + A 10.0.8.202 + A 10.0.8.203 + A 10.0.8.204 + A 10.0.8.205 + A 10.0.8.206 + A 10.0.8.207 + A 10.0.8.208 + A 10.0.8.209 + A 10.0.8.210 + A 10.0.8.211 + A 10.0.8.212 + A 10.0.8.213 + A 10.0.8.214 + A 10.0.8.215 + A 10.0.8.216 + A 10.0.8.217 + A 10.0.8.218 + A 10.0.8.219 + A 10.0.8.220 + A 10.0.8.221 + A 10.0.8.222 + A 10.0.8.223 + A 10.0.8.224 + A 10.0.8.225 + A 10.0.8.226 + A 10.0.8.227 + A 10.0.8.228 + A 10.0.8.229 + A 10.0.8.230 + A 10.0.8.231 + A 10.0.8.232 + A 10.0.8.233 + A 10.0.8.234 + A 10.0.8.235 + A 10.0.8.236 + A 10.0.8.237 + A 10.0.8.238 + A 10.0.8.239 + A 10.0.8.240 + A 10.0.8.241 + A 10.0.8.242 + A 10.0.8.243 + A 10.0.8.244 + A 10.0.8.245 + A 10.0.8.246 + A 10.0.8.247 + A 10.0.8.248 + A 10.0.8.249 + A 10.0.8.250 + A 10.0.8.251 + A 10.0.8.252 + A 10.0.8.253 + A 10.0.8.254 + A 10.0.8.255 + A 10.0.9.0 + A 10.0.9.1 + A 10.0.9.2 + A 10.0.9.3 + A 10.0.9.4 + A 10.0.9.5 + A 10.0.9.6 + A 10.0.9.7 + A 10.0.9.8 + A 10.0.9.9 + A 10.0.9.10 + A 10.0.9.11 + A 10.0.9.12 + A 10.0.9.13 + A 10.0.9.14 + A 10.0.9.15 + A 10.0.9.16 + A 10.0.9.17 + A 10.0.9.18 + A 10.0.9.19 + A 10.0.9.20 + A 10.0.9.21 + A 10.0.9.22 + A 10.0.9.23 + A 10.0.9.24 + A 10.0.9.25 + A 10.0.9.26 + A 10.0.9.27 + A 10.0.9.28 + A 10.0.9.29 + A 10.0.9.30 + A 10.0.9.31 + A 10.0.9.32 + A 10.0.9.33 + A 10.0.9.34 + A 10.0.9.35 + A 10.0.9.36 + A 10.0.9.37 + A 10.0.9.38 + A 10.0.9.39 + A 10.0.9.40 + A 10.0.9.41 + A 10.0.9.42 + A 10.0.9.43 + A 10.0.9.44 + A 10.0.9.45 + A 10.0.9.46 + A 10.0.9.47 + A 10.0.9.48 + A 10.0.9.49 + A 10.0.9.50 + A 10.0.9.51 + A 10.0.9.52 + A 10.0.9.53 + A 10.0.9.54 + A 10.0.9.55 + A 10.0.9.56 + A 10.0.9.57 + A 10.0.9.58 + A 10.0.9.59 + A 10.0.9.60 + A 10.0.9.61 + A 10.0.9.62 + A 10.0.9.63 + A 10.0.9.64 + A 10.0.9.65 + A 10.0.9.66 + A 10.0.9.67 + A 10.0.9.68 + A 10.0.9.69 + A 10.0.9.70 + A 10.0.9.71 + A 10.0.9.72 + A 10.0.9.73 + A 10.0.9.74 + A 10.0.9.75 + A 10.0.9.76 + A 10.0.9.77 + A 10.0.9.78 + A 10.0.9.79 + A 10.0.9.80 + A 10.0.9.81 + A 10.0.9.82 + A 10.0.9.83 + A 10.0.9.84 + A 10.0.9.85 + A 10.0.9.86 + A 10.0.9.87 + A 10.0.9.88 + A 10.0.9.89 + A 10.0.9.90 + A 10.0.9.91 + A 10.0.9.92 + A 10.0.9.93 + A 10.0.9.94 + A 10.0.9.95 + A 10.0.9.96 + A 10.0.9.97 + A 10.0.9.98 + A 10.0.9.99 + A 10.0.9.100 + A 10.0.9.101 + A 10.0.9.102 + A 10.0.9.103 + A 10.0.9.104 + A 10.0.9.105 + A 10.0.9.106 + A 10.0.9.107 + A 10.0.9.108 + A 10.0.9.109 + A 10.0.9.110 + A 10.0.9.111 + A 10.0.9.112 + A 10.0.9.113 + A 10.0.9.114 + A 10.0.9.115 + A 10.0.9.116 + A 10.0.9.117 + A 10.0.9.118 + A 10.0.9.119 + A 10.0.9.120 + A 10.0.9.121 + A 10.0.9.122 + A 10.0.9.123 + A 10.0.9.124 + A 10.0.9.125 + A 10.0.9.126 + A 10.0.9.127 + A 10.0.9.128 + A 10.0.9.129 + A 10.0.9.130 + A 10.0.9.131 + A 10.0.9.132 + A 10.0.9.133 + A 10.0.9.134 + A 10.0.9.135 + A 10.0.9.136 + A 10.0.9.137 + A 10.0.9.138 + A 10.0.9.139 + A 10.0.9.140 + A 10.0.9.141 + A 10.0.9.142 + A 10.0.9.143 + A 10.0.9.144 + A 10.0.9.145 + A 10.0.9.146 + A 10.0.9.147 + A 10.0.9.148 + A 10.0.9.149 + A 10.0.9.150 + A 10.0.9.151 + A 10.0.9.152 + A 10.0.9.153 + A 10.0.9.154 + A 10.0.9.155 + A 10.0.9.156 + A 10.0.9.157 + A 10.0.9.158 + A 10.0.9.159 + A 10.0.9.160 + A 10.0.9.161 + A 10.0.9.162 + A 10.0.9.163 + A 10.0.9.164 + A 10.0.9.165 + A 10.0.9.166 + A 10.0.9.167 + A 10.0.9.168 + A 10.0.9.169 + A 10.0.9.170 + A 10.0.9.171 + A 10.0.9.172 + A 10.0.9.173 + A 10.0.9.174 + A 10.0.9.175 + A 10.0.9.176 + A 10.0.9.177 + A 10.0.9.178 + A 10.0.9.179 + A 10.0.9.180 + A 10.0.9.181 + A 10.0.9.182 + A 10.0.9.183 + A 10.0.9.184 + A 10.0.9.185 + A 10.0.9.186 + A 10.0.9.187 + A 10.0.9.188 + A 10.0.9.189 + A 10.0.9.190 + A 10.0.9.191 + A 10.0.9.192 + A 10.0.9.193 + A 10.0.9.194 + A 10.0.9.195 + A 10.0.9.196 + A 10.0.9.197 + A 10.0.9.198 + A 10.0.9.199 + A 10.0.9.200 + A 10.0.9.201 + A 10.0.9.202 + A 10.0.9.203 + A 10.0.9.204 + A 10.0.9.205 + A 10.0.9.206 + A 10.0.9.207 + A 10.0.9.208 + A 10.0.9.209 + A 10.0.9.210 + A 10.0.9.211 + A 10.0.9.212 + A 10.0.9.213 + A 10.0.9.214 + A 10.0.9.215 + A 10.0.9.216 + A 10.0.9.217 + A 10.0.9.218 + A 10.0.9.219 + A 10.0.9.220 + A 10.0.9.221 + A 10.0.9.222 + A 10.0.9.223 + A 10.0.9.224 + A 10.0.9.225 + A 10.0.9.226 + A 10.0.9.227 + A 10.0.9.228 + A 10.0.9.229 + A 10.0.9.230 + A 10.0.9.231 + A 10.0.9.232 + A 10.0.9.233 + A 10.0.9.234 + A 10.0.9.235 + A 10.0.9.236 + A 10.0.9.237 + A 10.0.9.238 + A 10.0.9.239 + A 10.0.9.240 + A 10.0.9.241 + A 10.0.9.242 + A 10.0.9.243 + A 10.0.9.244 + A 10.0.9.245 + A 10.0.9.246 + A 10.0.9.247 + A 10.0.9.248 + A 10.0.9.249 + A 10.0.9.250 + A 10.0.9.251 + A 10.0.9.252 + A 10.0.9.253 + A 10.0.9.254 + A 10.0.9.255 + A 10.0.10.0 + A 10.0.10.1 + A 10.0.10.2 + A 10.0.10.3 + A 10.0.10.4 + A 10.0.10.5 + A 10.0.10.6 + A 10.0.10.7 + A 10.0.10.8 + A 10.0.10.9 + A 10.0.10.10 + A 10.0.10.11 + A 10.0.10.12 + A 10.0.10.13 + A 10.0.10.14 + A 10.0.10.15 + A 10.0.10.16 + A 10.0.10.17 + A 10.0.10.18 + A 10.0.10.19 + A 10.0.10.20 + A 10.0.10.21 + A 10.0.10.22 + A 10.0.10.23 + A 10.0.10.24 + A 10.0.10.25 + A 10.0.10.26 + A 10.0.10.27 + A 10.0.10.28 + A 10.0.10.29 + A 10.0.10.30 + A 10.0.10.31 + A 10.0.10.32 + A 10.0.10.33 + A 10.0.10.34 + A 10.0.10.35 + A 10.0.10.36 + A 10.0.10.37 + A 10.0.10.38 + A 10.0.10.39 + A 10.0.10.40 + A 10.0.10.41 + A 10.0.10.42 + A 10.0.10.43 + A 10.0.10.44 + A 10.0.10.45 + A 10.0.10.46 + A 10.0.10.47 + A 10.0.10.48 + A 10.0.10.49 + A 10.0.10.50 + A 10.0.10.51 + A 10.0.10.52 + A 10.0.10.53 + A 10.0.10.54 + A 10.0.10.55 + A 10.0.10.56 + A 10.0.10.57 + A 10.0.10.58 + A 10.0.10.59 + A 10.0.10.60 + A 10.0.10.61 + A 10.0.10.62 + A 10.0.10.63 + A 10.0.10.64 + A 10.0.10.65 + A 10.0.10.66 + A 10.0.10.67 + A 10.0.10.68 + A 10.0.10.69 + A 10.0.10.70 + A 10.0.10.71 + A 10.0.10.72 + A 10.0.10.73 + A 10.0.10.74 + A 10.0.10.75 + A 10.0.10.76 + A 10.0.10.77 + A 10.0.10.78 + A 10.0.10.79 + A 10.0.10.80 + A 10.0.10.81 + A 10.0.10.82 + A 10.0.10.83 + A 10.0.10.84 + A 10.0.10.85 + A 10.0.10.86 + A 10.0.10.87 + A 10.0.10.88 + A 10.0.10.89 + A 10.0.10.90 + A 10.0.10.91 + A 10.0.10.92 + A 10.0.10.93 + A 10.0.10.94 + A 10.0.10.95 + A 10.0.10.96 + A 10.0.10.97 + A 10.0.10.98 + A 10.0.10.99 + A 10.0.10.100 + A 10.0.10.101 + A 10.0.10.102 + A 10.0.10.103 + A 10.0.10.104 + A 10.0.10.105 + A 10.0.10.106 + A 10.0.10.107 + A 10.0.10.108 + A 10.0.10.109 + A 10.0.10.110 + A 10.0.10.111 + A 10.0.10.112 + A 10.0.10.113 + A 10.0.10.114 + A 10.0.10.115 + A 10.0.10.116 + A 10.0.10.117 + A 10.0.10.118 + A 10.0.10.119 + A 10.0.10.120 + A 10.0.10.121 + A 10.0.10.122 + A 10.0.10.123 + A 10.0.10.124 + A 10.0.10.125 + A 10.0.10.126 + A 10.0.10.127 + A 10.0.10.128 + A 10.0.10.129 + A 10.0.10.130 + A 10.0.10.131 + A 10.0.10.132 + A 10.0.10.133 + A 10.0.10.134 + A 10.0.10.135 + A 10.0.10.136 + A 10.0.10.137 + A 10.0.10.138 + A 10.0.10.139 + A 10.0.10.140 + A 10.0.10.141 + A 10.0.10.142 + A 10.0.10.143 + A 10.0.10.144 + A 10.0.10.145 + A 10.0.10.146 + A 10.0.10.147 + A 10.0.10.148 + A 10.0.10.149 + A 10.0.10.150 + A 10.0.10.151 + A 10.0.10.152 + A 10.0.10.153 + A 10.0.10.154 + A 10.0.10.155 + A 10.0.10.156 + A 10.0.10.157 + A 10.0.10.158 + A 10.0.10.159 + A 10.0.10.160 + A 10.0.10.161 + A 10.0.10.162 + A 10.0.10.163 + A 10.0.10.164 + A 10.0.10.165 + A 10.0.10.166 + A 10.0.10.167 + A 10.0.10.168 + A 10.0.10.169 + A 10.0.10.170 + A 10.0.10.171 + A 10.0.10.172 + A 10.0.10.173 + A 10.0.10.174 + A 10.0.10.175 + A 10.0.10.176 + A 10.0.10.177 + A 10.0.10.178 + A 10.0.10.179 + A 10.0.10.180 + A 10.0.10.181 + A 10.0.10.182 + A 10.0.10.183 + A 10.0.10.184 + A 10.0.10.185 + A 10.0.10.186 + A 10.0.10.187 + A 10.0.10.188 + A 10.0.10.189 + A 10.0.10.190 + A 10.0.10.191 + A 10.0.10.192 + A 10.0.10.193 + A 10.0.10.194 + A 10.0.10.195 + A 10.0.10.196 + A 10.0.10.197 + A 10.0.10.198 + A 10.0.10.199 + A 10.0.10.200 + A 10.0.10.201 + A 10.0.10.202 + A 10.0.10.203 + A 10.0.10.204 + A 10.0.10.205 + A 10.0.10.206 + A 10.0.10.207 + A 10.0.10.208 + A 10.0.10.209 + A 10.0.10.210 + A 10.0.10.211 + A 10.0.10.212 + A 10.0.10.213 + A 10.0.10.214 + A 10.0.10.215 + A 10.0.10.216 + A 10.0.10.217 + A 10.0.10.218 + A 10.0.10.219 + A 10.0.10.220 + A 10.0.10.221 + A 10.0.10.222 + A 10.0.10.223 + A 10.0.10.224 + A 10.0.10.225 + A 10.0.10.226 + A 10.0.10.227 + A 10.0.10.228 + A 10.0.10.229 + A 10.0.10.230 + A 10.0.10.231 + A 10.0.10.232 + A 10.0.10.233 + A 10.0.10.234 + A 10.0.10.235 + A 10.0.10.236 + A 10.0.10.237 + A 10.0.10.238 + A 10.0.10.239 + A 10.0.10.240 + A 10.0.10.241 + A 10.0.10.242 + A 10.0.10.243 + A 10.0.10.244 + A 10.0.10.245 + A 10.0.10.246 + A 10.0.10.247 + A 10.0.10.248 + A 10.0.10.249 + A 10.0.10.250 + A 10.0.10.251 + A 10.0.10.252 + A 10.0.10.253 + A 10.0.10.254 + A 10.0.10.255 + A 10.0.11.0 + A 10.0.11.1 + A 10.0.11.2 + A 10.0.11.3 + A 10.0.11.4 + A 10.0.11.5 + A 10.0.11.6 + A 10.0.11.7 + A 10.0.11.8 + A 10.0.11.9 + A 10.0.11.10 + A 10.0.11.11 + A 10.0.11.12 + A 10.0.11.13 + A 10.0.11.14 + A 10.0.11.15 + A 10.0.11.16 + A 10.0.11.17 + A 10.0.11.18 + A 10.0.11.19 + A 10.0.11.20 + A 10.0.11.21 + A 10.0.11.22 + A 10.0.11.23 + A 10.0.11.24 + A 10.0.11.25 + A 10.0.11.26 + A 10.0.11.27 + A 10.0.11.28 + A 10.0.11.29 + A 10.0.11.30 + A 10.0.11.31 + A 10.0.11.32 + A 10.0.11.33 + A 10.0.11.34 + A 10.0.11.35 + A 10.0.11.36 + A 10.0.11.37 + A 10.0.11.38 + A 10.0.11.39 + A 10.0.11.40 + A 10.0.11.41 + A 10.0.11.42 + A 10.0.11.43 + A 10.0.11.44 + A 10.0.11.45 + A 10.0.11.46 + A 10.0.11.47 + A 10.0.11.48 + A 10.0.11.49 + A 10.0.11.50 + A 10.0.11.51 + A 10.0.11.52 + A 10.0.11.53 + A 10.0.11.54 + A 10.0.11.55 + A 10.0.11.56 + A 10.0.11.57 + A 10.0.11.58 + A 10.0.11.59 + A 10.0.11.60 + A 10.0.11.61 + A 10.0.11.62 + A 10.0.11.63 + A 10.0.11.64 + A 10.0.11.65 + A 10.0.11.66 + A 10.0.11.67 + A 10.0.11.68 + A 10.0.11.69 + A 10.0.11.70 + A 10.0.11.71 + A 10.0.11.72 + A 10.0.11.73 + A 10.0.11.74 + A 10.0.11.75 + A 10.0.11.76 + A 10.0.11.77 + A 10.0.11.78 + A 10.0.11.79 + A 10.0.11.80 + A 10.0.11.81 + A 10.0.11.82 + A 10.0.11.83 + A 10.0.11.84 + A 10.0.11.85 + A 10.0.11.86 + A 10.0.11.87 + A 10.0.11.88 + A 10.0.11.89 + A 10.0.11.90 + A 10.0.11.91 + A 10.0.11.92 + A 10.0.11.93 + A 10.0.11.94 + A 10.0.11.95 + A 10.0.11.96 + A 10.0.11.97 + A 10.0.11.98 + A 10.0.11.99 + A 10.0.11.100 + A 10.0.11.101 + A 10.0.11.102 + A 10.0.11.103 + A 10.0.11.104 + A 10.0.11.105 + A 10.0.11.106 + A 10.0.11.107 + A 10.0.11.108 + A 10.0.11.109 + A 10.0.11.110 + A 10.0.11.111 + A 10.0.11.112 + A 10.0.11.113 + A 10.0.11.114 + A 10.0.11.115 + A 10.0.11.116 + A 10.0.11.117 + A 10.0.11.118 + A 10.0.11.119 + A 10.0.11.120 + A 10.0.11.121 + A 10.0.11.122 + A 10.0.11.123 + A 10.0.11.124 + A 10.0.11.125 + A 10.0.11.126 + A 10.0.11.127 + A 10.0.11.128 + A 10.0.11.129 + A 10.0.11.130 + A 10.0.11.131 + A 10.0.11.132 + A 10.0.11.133 + A 10.0.11.134 + A 10.0.11.135 + A 10.0.11.136 + A 10.0.11.137 + A 10.0.11.138 + A 10.0.11.139 + A 10.0.11.140 + A 10.0.11.141 + A 10.0.11.142 + A 10.0.11.143 + A 10.0.11.144 + A 10.0.11.145 + A 10.0.11.146 + A 10.0.11.147 + A 10.0.11.148 + A 10.0.11.149 + A 10.0.11.150 + A 10.0.11.151 + A 10.0.11.152 + A 10.0.11.153 + A 10.0.11.154 + A 10.0.11.155 + A 10.0.11.156 + A 10.0.11.157 + A 10.0.11.158 + A 10.0.11.159 + A 10.0.11.160 + A 10.0.11.161 + A 10.0.11.162 + A 10.0.11.163 + A 10.0.11.164 + A 10.0.11.165 + A 10.0.11.166 + A 10.0.11.167 + A 10.0.11.168 + A 10.0.11.169 + A 10.0.11.170 + A 10.0.11.171 + A 10.0.11.172 + A 10.0.11.173 + A 10.0.11.174 + A 10.0.11.175 + A 10.0.11.176 + A 10.0.11.177 + A 10.0.11.178 + A 10.0.11.179 + A 10.0.11.180 + A 10.0.11.181 + A 10.0.11.182 + A 10.0.11.183 + A 10.0.11.184 + A 10.0.11.185 + A 10.0.11.186 + A 10.0.11.187 + A 10.0.11.188 + A 10.0.11.189 + A 10.0.11.190 + A 10.0.11.191 + A 10.0.11.192 + A 10.0.11.193 + A 10.0.11.194 + A 10.0.11.195 + A 10.0.11.196 + A 10.0.11.197 + A 10.0.11.198 + A 10.0.11.199 + A 10.0.11.200 + A 10.0.11.201 + A 10.0.11.202 + A 10.0.11.203 + A 10.0.11.204 + A 10.0.11.205 + A 10.0.11.206 + A 10.0.11.207 + A 10.0.11.208 + A 10.0.11.209 + A 10.0.11.210 + A 10.0.11.211 + A 10.0.11.212 + A 10.0.11.213 + A 10.0.11.214 + A 10.0.11.215 + A 10.0.11.216 + A 10.0.11.217 + A 10.0.11.218 + A 10.0.11.219 + A 10.0.11.220 + A 10.0.11.221 + A 10.0.11.222 + A 10.0.11.223 + A 10.0.11.224 + A 10.0.11.225 + A 10.0.11.226 + A 10.0.11.227 + A 10.0.11.228 + A 10.0.11.229 + A 10.0.11.230 + A 10.0.11.231 + A 10.0.11.232 + A 10.0.11.233 + A 10.0.11.234 + A 10.0.11.235 + A 10.0.11.236 + A 10.0.11.237 + A 10.0.11.238 + A 10.0.11.239 + A 10.0.11.240 + A 10.0.11.241 + A 10.0.11.242 + A 10.0.11.243 + A 10.0.11.244 + A 10.0.11.245 + A 10.0.11.246 + A 10.0.11.247 + A 10.0.11.248 + A 10.0.11.249 + A 10.0.11.250 + A 10.0.11.251 + A 10.0.11.252 + A 10.0.11.253 + A 10.0.11.254 + A 10.0.11.255 + A 10.0.12.0 + A 10.0.12.1 + A 10.0.12.2 + A 10.0.12.3 + A 10.0.12.4 + A 10.0.12.5 + A 10.0.12.6 + A 10.0.12.7 + A 10.0.12.8 + A 10.0.12.9 + A 10.0.12.10 + A 10.0.12.11 + A 10.0.12.12 + A 10.0.12.13 + A 10.0.12.14 + A 10.0.12.15 + A 10.0.12.16 + A 10.0.12.17 + A 10.0.12.18 + A 10.0.12.19 + A 10.0.12.20 + A 10.0.12.21 + A 10.0.12.22 + A 10.0.12.23 + A 10.0.12.24 + A 10.0.12.25 + A 10.0.12.26 + A 10.0.12.27 + A 10.0.12.28 + A 10.0.12.29 + A 10.0.12.30 + A 10.0.12.31 + A 10.0.12.32 + A 10.0.12.33 + A 10.0.12.34 + A 10.0.12.35 + A 10.0.12.36 + A 10.0.12.37 + A 10.0.12.38 + A 10.0.12.39 + A 10.0.12.40 + A 10.0.12.41 + A 10.0.12.42 + A 10.0.12.43 + A 10.0.12.44 + A 10.0.12.45 + A 10.0.12.46 + A 10.0.12.47 + A 10.0.12.48 + A 10.0.12.49 + A 10.0.12.50 + A 10.0.12.51 + A 10.0.12.52 + A 10.0.12.53 + A 10.0.12.54 + A 10.0.12.55 + A 10.0.12.56 + A 10.0.12.57 + A 10.0.12.58 + A 10.0.12.59 + A 10.0.12.60 + A 10.0.12.61 + A 10.0.12.62 + A 10.0.12.63 + A 10.0.12.64 + A 10.0.12.65 + A 10.0.12.66 + A 10.0.12.67 + A 10.0.12.68 + A 10.0.12.69 + A 10.0.12.70 + A 10.0.12.71 + A 10.0.12.72 + A 10.0.12.73 + A 10.0.12.74 + A 10.0.12.75 + A 10.0.12.76 + A 10.0.12.77 + A 10.0.12.78 + A 10.0.12.79 + A 10.0.12.80 + A 10.0.12.81 + A 10.0.12.82 + A 10.0.12.83 + A 10.0.12.84 + A 10.0.12.85 + A 10.0.12.86 + A 10.0.12.87 + A 10.0.12.88 + A 10.0.12.89 + A 10.0.12.90 + A 10.0.12.91 + A 10.0.12.92 + A 10.0.12.93 + A 10.0.12.94 + A 10.0.12.95 + A 10.0.12.96 + A 10.0.12.97 + A 10.0.12.98 + A 10.0.12.99 + A 10.0.12.100 + A 10.0.12.101 + A 10.0.12.102 + A 10.0.12.103 + A 10.0.12.104 + A 10.0.12.105 + A 10.0.12.106 + A 10.0.12.107 + A 10.0.12.108 + A 10.0.12.109 + A 10.0.12.110 + A 10.0.12.111 + A 10.0.12.112 + A 10.0.12.113 + A 10.0.12.114 + A 10.0.12.115 + A 10.0.12.116 + A 10.0.12.117 + A 10.0.12.118 + A 10.0.12.119 + A 10.0.12.120 + A 10.0.12.121 + A 10.0.12.122 + A 10.0.12.123 + A 10.0.12.124 + A 10.0.12.125 + A 10.0.12.126 + A 10.0.12.127 + A 10.0.12.128 + A 10.0.12.129 + A 10.0.12.130 + A 10.0.12.131 + A 10.0.12.132 + A 10.0.12.133 + A 10.0.12.134 + A 10.0.12.135 + A 10.0.12.136 + A 10.0.12.137 + A 10.0.12.138 + A 10.0.12.139 + A 10.0.12.140 + A 10.0.12.141 + A 10.0.12.142 + A 10.0.12.143 + A 10.0.12.144 + A 10.0.12.145 + A 10.0.12.146 + A 10.0.12.147 + A 10.0.12.148 + A 10.0.12.149 + A 10.0.12.150 + A 10.0.12.151 + A 10.0.12.152 + A 10.0.12.153 + A 10.0.12.154 + A 10.0.12.155 + A 10.0.12.156 + A 10.0.12.157 + A 10.0.12.158 + A 10.0.12.159 + A 10.0.12.160 + A 10.0.12.161 + A 10.0.12.162 + A 10.0.12.163 + A 10.0.12.164 + A 10.0.12.165 + A 10.0.12.166 + A 10.0.12.167 + A 10.0.12.168 + A 10.0.12.169 + A 10.0.12.170 + A 10.0.12.171 + A 10.0.12.172 + A 10.0.12.173 + A 10.0.12.174 + A 10.0.12.175 + A 10.0.12.176 + A 10.0.12.177 + A 10.0.12.178 + A 10.0.12.179 + A 10.0.12.180 + A 10.0.12.181 + A 10.0.12.182 + A 10.0.12.183 + A 10.0.12.184 + A 10.0.12.185 + A 10.0.12.186 + A 10.0.12.187 + A 10.0.12.188 + A 10.0.12.189 + A 10.0.12.190 + A 10.0.12.191 + A 10.0.12.192 + A 10.0.12.193 + A 10.0.12.194 + A 10.0.12.195 + A 10.0.12.196 + A 10.0.12.197 + A 10.0.12.198 + A 10.0.12.199 + A 10.0.12.200 + A 10.0.12.201 + A 10.0.12.202 + A 10.0.12.203 + A 10.0.12.204 + A 10.0.12.205 + A 10.0.12.206 + A 10.0.12.207 + A 10.0.12.208 + A 10.0.12.209 + A 10.0.12.210 + A 10.0.12.211 + A 10.0.12.212 + A 10.0.12.213 + A 10.0.12.214 + A 10.0.12.215 + A 10.0.12.216 + A 10.0.12.217 + A 10.0.12.218 + A 10.0.12.219 + A 10.0.12.220 + A 10.0.12.221 + A 10.0.12.222 + A 10.0.12.223 + A 10.0.12.224 + A 10.0.12.225 + A 10.0.12.226 + A 10.0.12.227 + A 10.0.12.228 + A 10.0.12.229 + A 10.0.12.230 + A 10.0.12.231 + A 10.0.12.232 + A 10.0.12.233 + A 10.0.12.234 + A 10.0.12.235 + A 10.0.12.236 + A 10.0.12.237 + A 10.0.12.238 + A 10.0.12.239 + A 10.0.12.240 + A 10.0.12.241 + A 10.0.12.242 + A 10.0.12.243 + A 10.0.12.244 + A 10.0.12.245 + A 10.0.12.246 + A 10.0.12.247 + A 10.0.12.248 + A 10.0.12.249 + A 10.0.12.250 + A 10.0.12.251 + A 10.0.12.252 + A 10.0.12.253 + A 10.0.12.254 + A 10.0.12.255 + A 10.0.13.0 + A 10.0.13.1 + A 10.0.13.2 + A 10.0.13.3 + A 10.0.13.4 + A 10.0.13.5 + A 10.0.13.6 + A 10.0.13.7 + A 10.0.13.8 + A 10.0.13.9 + A 10.0.13.10 + A 10.0.13.11 + A 10.0.13.12 + A 10.0.13.13 + A 10.0.13.14 + A 10.0.13.15 + A 10.0.13.16 + A 10.0.13.17 + A 10.0.13.18 + A 10.0.13.19 + A 10.0.13.20 + A 10.0.13.21 + A 10.0.13.22 + A 10.0.13.23 + A 10.0.13.24 + A 10.0.13.25 + A 10.0.13.26 + A 10.0.13.27 + A 10.0.13.28 + A 10.0.13.29 + A 10.0.13.30 + A 10.0.13.31 + A 10.0.13.32 + A 10.0.13.33 + A 10.0.13.34 + A 10.0.13.35 + A 10.0.13.36 + A 10.0.13.37 + A 10.0.13.38 + A 10.0.13.39 + A 10.0.13.40 + A 10.0.13.41 + A 10.0.13.42 + A 10.0.13.43 + A 10.0.13.44 + A 10.0.13.45 + A 10.0.13.46 + A 10.0.13.47 + A 10.0.13.48 + A 10.0.13.49 + A 10.0.13.50 + A 10.0.13.51 + A 10.0.13.52 + A 10.0.13.53 + A 10.0.13.54 + A 10.0.13.55 + A 10.0.13.56 + A 10.0.13.57 + A 10.0.13.58 + A 10.0.13.59 + A 10.0.13.60 + A 10.0.13.61 + A 10.0.13.62 + A 10.0.13.63 + A 10.0.13.64 + A 10.0.13.65 + A 10.0.13.66 + A 10.0.13.67 + A 10.0.13.68 + A 10.0.13.69 + A 10.0.13.70 + A 10.0.13.71 + A 10.0.13.72 + A 10.0.13.73 + A 10.0.13.74 + A 10.0.13.75 + A 10.0.13.76 + A 10.0.13.77 + A 10.0.13.78 + A 10.0.13.79 + A 10.0.13.80 + A 10.0.13.81 + A 10.0.13.82 + A 10.0.13.83 + A 10.0.13.84 + A 10.0.13.85 + A 10.0.13.86 + A 10.0.13.87 + A 10.0.13.88 + A 10.0.13.89 + A 10.0.13.90 + A 10.0.13.91 + A 10.0.13.92 + A 10.0.13.93 + A 10.0.13.94 + A 10.0.13.95 + A 10.0.13.96 + A 10.0.13.97 + A 10.0.13.98 + A 10.0.13.99 + A 10.0.13.100 + A 10.0.13.101 + A 10.0.13.102 + A 10.0.13.103 + A 10.0.13.104 + A 10.0.13.105 + A 10.0.13.106 + A 10.0.13.107 + A 10.0.13.108 + A 10.0.13.109 + A 10.0.13.110 + A 10.0.13.111 + A 10.0.13.112 + A 10.0.13.113 + A 10.0.13.114 + A 10.0.13.115 + A 10.0.13.116 + A 10.0.13.117 + A 10.0.13.118 + A 10.0.13.119 + A 10.0.13.120 + A 10.0.13.121 + A 10.0.13.122 + A 10.0.13.123 + A 10.0.13.124 + A 10.0.13.125 + A 10.0.13.126 + A 10.0.13.127 + A 10.0.13.128 + A 10.0.13.129 + A 10.0.13.130 + A 10.0.13.131 + A 10.0.13.132 + A 10.0.13.133 + A 10.0.13.134 + A 10.0.13.135 + A 10.0.13.136 + A 10.0.13.137 + A 10.0.13.138 + A 10.0.13.139 + A 10.0.13.140 + A 10.0.13.141 + A 10.0.13.142 + A 10.0.13.143 + A 10.0.13.144 + A 10.0.13.145 + A 10.0.13.146 + A 10.0.13.147 + A 10.0.13.148 + A 10.0.13.149 + A 10.0.13.150 + A 10.0.13.151 + A 10.0.13.152 + A 10.0.13.153 + A 10.0.13.154 + A 10.0.13.155 + A 10.0.13.156 + A 10.0.13.157 + A 10.0.13.158 + A 10.0.13.159 + A 10.0.13.160 + A 10.0.13.161 + A 10.0.13.162 + A 10.0.13.163 + A 10.0.13.164 + A 10.0.13.165 + A 10.0.13.166 + A 10.0.13.167 + A 10.0.13.168 + A 10.0.13.169 + A 10.0.13.170 + A 10.0.13.171 + A 10.0.13.172 + A 10.0.13.173 + A 10.0.13.174 + A 10.0.13.175 + A 10.0.13.176 + A 10.0.13.177 + A 10.0.13.178 + A 10.0.13.179 + A 10.0.13.180 + A 10.0.13.181 + A 10.0.13.182 + A 10.0.13.183 + A 10.0.13.184 + A 10.0.13.185 + A 10.0.13.186 + A 10.0.13.187 + A 10.0.13.188 + A 10.0.13.189 + A 10.0.13.190 + A 10.0.13.191 + A 10.0.13.192 + A 10.0.13.193 + A 10.0.13.194 + A 10.0.13.195 + A 10.0.13.196 + A 10.0.13.197 + A 10.0.13.198 + A 10.0.13.199 + A 10.0.13.200 + A 10.0.13.201 + A 10.0.13.202 + A 10.0.13.203 + A 10.0.13.204 + A 10.0.13.205 + A 10.0.13.206 + A 10.0.13.207 + A 10.0.13.208 + A 10.0.13.209 + A 10.0.13.210 + A 10.0.13.211 + A 10.0.13.212 + A 10.0.13.213 + A 10.0.13.214 + A 10.0.13.215 + A 10.0.13.216 + A 10.0.13.217 + A 10.0.13.218 + A 10.0.13.219 + A 10.0.13.220 + A 10.0.13.221 + A 10.0.13.222 + A 10.0.13.223 + A 10.0.13.224 + A 10.0.13.225 + A 10.0.13.226 + A 10.0.13.227 + A 10.0.13.228 + A 10.0.13.229 + A 10.0.13.230 + A 10.0.13.231 + A 10.0.13.232 + A 10.0.13.233 + A 10.0.13.234 + A 10.0.13.235 + A 10.0.13.236 + A 10.0.13.237 + A 10.0.13.238 + A 10.0.13.239 + A 10.0.13.240 + A 10.0.13.241 + A 10.0.13.242 + A 10.0.13.243 + A 10.0.13.244 + A 10.0.13.245 + A 10.0.13.246 + A 10.0.13.247 + A 10.0.13.248 + A 10.0.13.249 + A 10.0.13.250 + A 10.0.13.251 + A 10.0.13.252 + A 10.0.13.253 + A 10.0.13.254 + A 10.0.13.255 + A 10.0.14.0 + A 10.0.14.1 + A 10.0.14.2 + A 10.0.14.3 + A 10.0.14.4 + A 10.0.14.5 + A 10.0.14.6 + A 10.0.14.7 + A 10.0.14.8 + A 10.0.14.9 + A 10.0.14.10 + A 10.0.14.11 + A 10.0.14.12 + A 10.0.14.13 + A 10.0.14.14 + A 10.0.14.15 + A 10.0.14.16 + A 10.0.14.17 + A 10.0.14.18 + A 10.0.14.19 + A 10.0.14.20 + A 10.0.14.21 + A 10.0.14.22 + A 10.0.14.23 + A 10.0.14.24 + A 10.0.14.25 + A 10.0.14.26 + A 10.0.14.27 + A 10.0.14.28 + A 10.0.14.29 + A 10.0.14.30 + A 10.0.14.31 + A 10.0.14.32 + A 10.0.14.33 + A 10.0.14.34 + A 10.0.14.35 + A 10.0.14.36 + A 10.0.14.37 + A 10.0.14.38 + A 10.0.14.39 + A 10.0.14.40 + A 10.0.14.41 + A 10.0.14.42 + A 10.0.14.43 + A 10.0.14.44 + A 10.0.14.45 + A 10.0.14.46 + A 10.0.14.47 + A 10.0.14.48 + A 10.0.14.49 + A 10.0.14.50 + A 10.0.14.51 + A 10.0.14.52 + A 10.0.14.53 + A 10.0.14.54 + A 10.0.14.55 + A 10.0.14.56 + A 10.0.14.57 + A 10.0.14.58 + A 10.0.14.59 + A 10.0.14.60 + A 10.0.14.61 + A 10.0.14.62 + A 10.0.14.63 + A 10.0.14.64 + A 10.0.14.65 + A 10.0.14.66 + A 10.0.14.67 + A 10.0.14.68 + A 10.0.14.69 + A 10.0.14.70 + A 10.0.14.71 + A 10.0.14.72 + A 10.0.14.73 + A 10.0.14.74 + A 10.0.14.75 + A 10.0.14.76 + A 10.0.14.77 + A 10.0.14.78 + A 10.0.14.79 + A 10.0.14.80 + A 10.0.14.81 + A 10.0.14.82 + A 10.0.14.83 + A 10.0.14.84 + A 10.0.14.85 + A 10.0.14.86 + A 10.0.14.87 + A 10.0.14.88 + A 10.0.14.89 + A 10.0.14.90 + A 10.0.14.91 + A 10.0.14.92 + A 10.0.14.93 + A 10.0.14.94 + A 10.0.14.95 + A 10.0.14.96 + A 10.0.14.97 + A 10.0.14.98 + A 10.0.14.99 + A 10.0.14.100 + A 10.0.14.101 + A 10.0.14.102 + A 10.0.14.103 + A 10.0.14.104 + A 10.0.14.105 + A 10.0.14.106 + A 10.0.14.107 + A 10.0.14.108 + A 10.0.14.109 + A 10.0.14.110 + A 10.0.14.111 + A 10.0.14.112 + A 10.0.14.113 + A 10.0.14.114 + A 10.0.14.115 + A 10.0.14.116 + A 10.0.14.117 + A 10.0.14.118 + A 10.0.14.119 + A 10.0.14.120 + A 10.0.14.121 + A 10.0.14.122 + A 10.0.14.123 + A 10.0.14.124 + A 10.0.14.125 + A 10.0.14.126 + A 10.0.14.127 + A 10.0.14.128 + A 10.0.14.129 + A 10.0.14.130 + A 10.0.14.131 + A 10.0.14.132 + A 10.0.14.133 + A 10.0.14.134 + A 10.0.14.135 + A 10.0.14.136 + A 10.0.14.137 + A 10.0.14.138 + A 10.0.14.139 + A 10.0.14.140 + A 10.0.14.141 + A 10.0.14.142 + A 10.0.14.143 + A 10.0.14.144 + A 10.0.14.145 + A 10.0.14.146 + A 10.0.14.147 + A 10.0.14.148 + A 10.0.14.149 + A 10.0.14.150 + A 10.0.14.151 + A 10.0.14.152 + A 10.0.14.153 + A 10.0.14.154 + A 10.0.14.155 + A 10.0.14.156 + A 10.0.14.157 + A 10.0.14.158 + A 10.0.14.159 + A 10.0.14.160 + A 10.0.14.161 + A 10.0.14.162 + A 10.0.14.163 + A 10.0.14.164 + A 10.0.14.165 + A 10.0.14.166 + A 10.0.14.167 + A 10.0.14.168 + A 10.0.14.169 + A 10.0.14.170 + A 10.0.14.171 + A 10.0.14.172 + A 10.0.14.173 + A 10.0.14.174 + A 10.0.14.175 + A 10.0.14.176 + A 10.0.14.177 + A 10.0.14.178 + A 10.0.14.179 + A 10.0.14.180 + A 10.0.14.181 + A 10.0.14.182 + A 10.0.14.183 + A 10.0.14.184 + A 10.0.14.185 + A 10.0.14.186 + A 10.0.14.187 + A 10.0.14.188 + A 10.0.14.189 + A 10.0.14.190 + A 10.0.14.191 + A 10.0.14.192 + A 10.0.14.193 + A 10.0.14.194 + A 10.0.14.195 + A 10.0.14.196 + A 10.0.14.197 + A 10.0.14.198 + A 10.0.14.199 + A 10.0.14.200 + A 10.0.14.201 + A 10.0.14.202 + A 10.0.14.203 + A 10.0.14.204 + A 10.0.14.205 + A 10.0.14.206 + A 10.0.14.207 + A 10.0.14.208 + A 10.0.14.209 + A 10.0.14.210 + A 10.0.14.211 + A 10.0.14.212 + A 10.0.14.213 + A 10.0.14.214 + A 10.0.14.215 + A 10.0.14.216 + A 10.0.14.217 + A 10.0.14.218 + A 10.0.14.219 + A 10.0.14.220 + A 10.0.14.221 + A 10.0.14.222 + A 10.0.14.223 + A 10.0.14.224 + A 10.0.14.225 + A 10.0.14.226 + A 10.0.14.227 + A 10.0.14.228 + A 10.0.14.229 + A 10.0.14.230 + A 10.0.14.231 + A 10.0.14.232 + A 10.0.14.233 + A 10.0.14.234 + A 10.0.14.235 + A 10.0.14.236 + A 10.0.14.237 + A 10.0.14.238 + A 10.0.14.239 + A 10.0.14.240 + A 10.0.14.241 + A 10.0.14.242 + A 10.0.14.243 + A 10.0.14.244 + A 10.0.14.245 + A 10.0.14.246 + A 10.0.14.247 + A 10.0.14.248 + A 10.0.14.249 + A 10.0.14.250 + A 10.0.14.251 + A 10.0.14.252 + A 10.0.14.253 + A 10.0.14.254 + A 10.0.14.255 + A 10.0.15.0 + A 10.0.15.1 + A 10.0.15.2 + A 10.0.15.3 + A 10.0.15.4 + A 10.0.15.5 + A 10.0.15.6 + A 10.0.15.7 + A 10.0.15.8 + A 10.0.15.9 + A 10.0.15.10 + A 10.0.15.11 + A 10.0.15.12 + A 10.0.15.13 + A 10.0.15.14 + A 10.0.15.15 + A 10.0.15.16 + A 10.0.15.17 + A 10.0.15.18 + A 10.0.15.19 + A 10.0.15.20 + A 10.0.15.21 + A 10.0.15.22 + A 10.0.15.23 + A 10.0.15.24 + A 10.0.15.25 + A 10.0.15.26 + A 10.0.15.27 + A 10.0.15.28 + A 10.0.15.29 + A 10.0.15.30 + A 10.0.15.31 + A 10.0.15.32 + A 10.0.15.33 + A 10.0.15.34 + A 10.0.15.35 + A 10.0.15.36 + A 10.0.15.37 + A 10.0.15.38 + A 10.0.15.39 + A 10.0.15.40 + A 10.0.15.41 + A 10.0.15.42 + A 10.0.15.43 + A 10.0.15.44 + A 10.0.15.45 + A 10.0.15.46 + A 10.0.15.47 + A 10.0.15.48 + A 10.0.15.49 + A 10.0.15.50 + A 10.0.15.51 + A 10.0.15.52 + A 10.0.15.53 + A 10.0.15.54 + A 10.0.15.55 + A 10.0.15.56 + A 10.0.15.57 + A 10.0.15.58 + A 10.0.15.59 + A 10.0.15.60 + A 10.0.15.61 + A 10.0.15.62 + A 10.0.15.63 + A 10.0.15.64 + A 10.0.15.65 + A 10.0.15.66 + A 10.0.15.67 + A 10.0.15.68 + A 10.0.15.69 + A 10.0.15.70 + A 10.0.15.71 + A 10.0.15.72 + A 10.0.15.73 + A 10.0.15.74 + A 10.0.15.75 + A 10.0.15.76 + A 10.0.15.77 + A 10.0.15.78 + A 10.0.15.79 + A 10.0.15.80 + A 10.0.15.81 + A 10.0.15.82 + A 10.0.15.83 + A 10.0.15.84 + A 10.0.15.85 + A 10.0.15.86 + A 10.0.15.87 + A 10.0.15.88 + A 10.0.15.89 + A 10.0.15.90 + A 10.0.15.91 + A 10.0.15.92 + A 10.0.15.93 + A 10.0.15.94 + A 10.0.15.95 + A 10.0.15.96 + A 10.0.15.97 + A 10.0.15.98 + A 10.0.15.99 + A 10.0.15.100 + A 10.0.15.101 + A 10.0.15.102 + A 10.0.15.103 + A 10.0.15.104 + A 10.0.15.105 + A 10.0.15.106 + A 10.0.15.107 + A 10.0.15.108 + A 10.0.15.109 + A 10.0.15.110 + A 10.0.15.111 + A 10.0.15.112 + A 10.0.15.113 + A 10.0.15.114 + A 10.0.15.115 + A 10.0.15.116 + A 10.0.15.117 + A 10.0.15.118 + A 10.0.15.119 + A 10.0.15.120 + A 10.0.15.121 + A 10.0.15.122 + A 10.0.15.123 + A 10.0.15.124 + A 10.0.15.125 + A 10.0.15.126 + A 10.0.15.127 + A 10.0.15.128 + A 10.0.15.129 + A 10.0.15.130 + A 10.0.15.131 + A 10.0.15.132 + A 10.0.15.133 + A 10.0.15.134 + A 10.0.15.135 + A 10.0.15.136 + A 10.0.15.137 + A 10.0.15.138 + A 10.0.15.139 + A 10.0.15.140 + A 10.0.15.141 + A 10.0.15.142 + A 10.0.15.143 + A 10.0.15.144 + A 10.0.15.145 + A 10.0.15.146 + A 10.0.15.147 + A 10.0.15.148 + A 10.0.15.149 + A 10.0.15.150 + A 10.0.15.151 + A 10.0.15.152 + A 10.0.15.153 + A 10.0.15.154 + A 10.0.15.155 + A 10.0.15.156 + A 10.0.15.157 + A 10.0.15.158 + A 10.0.15.159 + A 10.0.15.160 + A 10.0.15.161 + A 10.0.15.162 + A 10.0.15.163 + A 10.0.15.164 + A 10.0.15.165 + A 10.0.15.166 + A 10.0.15.167 + A 10.0.15.168 + A 10.0.15.169 + A 10.0.15.170 + A 10.0.15.171 + A 10.0.15.172 + A 10.0.15.173 + A 10.0.15.174 + A 10.0.15.175 + A 10.0.15.176 + A 10.0.15.177 + A 10.0.15.178 + A 10.0.15.179 + A 10.0.15.180 + A 10.0.15.181 + A 10.0.15.182 + A 10.0.15.183 + A 10.0.15.184 + A 10.0.15.185 + A 10.0.15.186 + A 10.0.15.187 + A 10.0.15.188 + A 10.0.15.189 + A 10.0.15.190 + A 10.0.15.191 + A 10.0.15.192 + A 10.0.15.193 + A 10.0.15.194 + A 10.0.15.195 + A 10.0.15.196 + A 10.0.15.197 + A 10.0.15.198 + A 10.0.15.199 + A 10.0.15.200 + A 10.0.15.201 + A 10.0.15.202 + A 10.0.15.203 + A 10.0.15.204 + A 10.0.15.205 + A 10.0.15.206 + A 10.0.15.207 + A 10.0.15.208 + A 10.0.15.209 + A 10.0.15.210 + A 10.0.15.211 + A 10.0.15.212 + A 10.0.15.213 + A 10.0.15.214 + A 10.0.15.215 + A 10.0.15.216 + A 10.0.15.217 + A 10.0.15.218 + A 10.0.15.219 + A 10.0.15.220 + A 10.0.15.221 + A 10.0.15.222 + A 10.0.15.223 + A 10.0.15.224 + A 10.0.15.225 + A 10.0.15.226 + A 10.0.15.227 + A 10.0.15.228 + A 10.0.15.229 + A 10.0.15.230 + A 10.0.15.231 + A 10.0.15.232 + A 10.0.15.233 + A 10.0.15.234 + A 10.0.15.235 + A 10.0.15.236 + A 10.0.15.237 + A 10.0.15.238 + A 10.0.15.239 + A 10.0.15.240 + A 10.0.15.241 + A 10.0.15.242 + A 10.0.15.243 + A 10.0.15.244 + A 10.0.15.245 + A 10.0.15.246 + A 10.0.15.247 + A 10.0.15.248 + A 10.0.15.249 + A 10.0.15.250 + A 10.0.15.251 + A 10.0.15.252 + A 10.0.15.253 + A 10.0.15.254 + A 10.0.15.255 + A 10.0.16.0 + A 10.0.16.1 + A 10.0.16.2 + A 10.0.16.3 + A 10.0.16.4 + A 10.0.16.5 + A 10.0.16.6 + A 10.0.16.7 + A 10.0.16.8 + A 10.0.16.9 + A 10.0.16.10 + A 10.0.16.11 + A 10.0.16.12 + A 10.0.16.13 + A 10.0.16.14 + A 10.0.16.15 + A 10.0.16.16 + A 10.0.16.17 + A 10.0.16.18 + A 10.0.16.19 + A 10.0.16.20 + A 10.0.16.21 + A 10.0.16.22 + A 10.0.16.23 + A 10.0.16.24 + A 10.0.16.25 + A 10.0.16.26 + A 10.0.16.27 + A 10.0.16.28 + A 10.0.16.29 + A 10.0.16.30 + A 10.0.16.31 + A 10.0.16.32 + A 10.0.16.33 + A 10.0.16.34 + A 10.0.16.35 + A 10.0.16.36 + A 10.0.16.37 + A 10.0.16.38 + A 10.0.16.39 + A 10.0.16.40 + A 10.0.16.41 + A 10.0.16.42 + A 10.0.16.43 + A 10.0.16.44 + A 10.0.16.45 + A 10.0.16.46 + A 10.0.16.47 + A 10.0.16.48 + A 10.0.16.49 + A 10.0.16.50 + A 10.0.16.51 + A 10.0.16.52 + A 10.0.16.53 + A 10.0.16.54 + A 10.0.16.55 + A 10.0.16.56 + A 10.0.16.57 + A 10.0.16.58 + A 10.0.16.59 + A 10.0.16.60 + A 10.0.16.61 + A 10.0.16.62 + A 10.0.16.63 + A 10.0.16.64 + A 10.0.16.65 + A 10.0.16.66 + A 10.0.16.67 + A 10.0.16.68 + A 10.0.16.69 + A 10.0.16.70 + A 10.0.16.71 + A 10.0.16.72 + A 10.0.16.73 + A 10.0.16.74 + A 10.0.16.75 + A 10.0.16.76 + A 10.0.16.77 + A 10.0.16.78 + A 10.0.16.79 + A 10.0.16.80 + A 10.0.16.81 + A 10.0.16.82 + A 10.0.16.83 + A 10.0.16.84 + A 10.0.16.85 + A 10.0.16.86 + A 10.0.16.87 + A 10.0.16.88 + A 10.0.16.89 + A 10.0.16.90 + A 10.0.16.91 + A 10.0.16.92 + A 10.0.16.93 + A 10.0.16.94 + A 10.0.16.95 + A 10.0.16.96 + A 10.0.16.97 + A 10.0.16.98 + A 10.0.16.99 + A 10.0.16.100 + A 10.0.16.101 + A 10.0.16.102 + A 10.0.16.103 + A 10.0.16.104 + A 10.0.16.105 + A 10.0.16.106 + A 10.0.16.107 + A 10.0.16.108 + A 10.0.16.109 + A 10.0.16.110 + A 10.0.16.111 + A 10.0.16.112 + A 10.0.16.113 + A 10.0.16.114 + A 10.0.16.115 + A 10.0.16.116 + A 10.0.16.117 + A 10.0.16.118 + A 10.0.16.119 + A 10.0.16.120 + A 10.0.16.121 + A 10.0.16.122 + A 10.0.16.123 + A 10.0.16.124 + A 10.0.16.125 + A 10.0.16.126 + A 10.0.16.127 + A 10.0.16.128 + A 10.0.16.129 + A 10.0.16.130 + A 10.0.16.131 + A 10.0.16.132 + A 10.0.16.133 + A 10.0.16.134 + A 10.0.16.135 + A 10.0.16.136 + A 10.0.16.137 + A 10.0.16.138 + A 10.0.16.139 + A 10.0.16.140 + A 10.0.16.141 + A 10.0.16.142 + A 10.0.16.143 + A 10.0.16.144 + A 10.0.16.145 + A 10.0.16.146 + A 10.0.16.147 + A 10.0.16.148 + A 10.0.16.149 + A 10.0.16.150 + A 10.0.16.151 + A 10.0.16.152 + A 10.0.16.153 + A 10.0.16.154 + A 10.0.16.155 + A 10.0.16.156 + A 10.0.16.157 + A 10.0.16.158 + A 10.0.16.159 + A 10.0.16.160 + A 10.0.16.161 + A 10.0.16.162 + A 10.0.16.163 + A 10.0.16.164 + A 10.0.16.165 + A 10.0.16.166 + A 10.0.16.167 + A 10.0.16.168 + A 10.0.16.169 + A 10.0.16.170 + A 10.0.16.171 + A 10.0.16.172 + A 10.0.16.173 + A 10.0.16.174 + A 10.0.16.175 + A 10.0.16.176 + A 10.0.16.177 + A 10.0.16.178 + A 10.0.16.179 + A 10.0.16.180 + A 10.0.16.181 + A 10.0.16.182 + A 10.0.16.183 + A 10.0.16.184 + A 10.0.16.185 + A 10.0.16.186 + A 10.0.16.187 + A 10.0.16.188 + A 10.0.16.189 + A 10.0.16.190 + A 10.0.16.191 + A 10.0.16.192 + A 10.0.16.193 + A 10.0.16.194 + A 10.0.16.195 + A 10.0.16.196 + A 10.0.16.197 + A 10.0.16.198 + A 10.0.16.199 + A 10.0.16.200 + A 10.0.16.201 + A 10.0.16.202 + A 10.0.16.203 + A 10.0.16.204 + A 10.0.16.205 + A 10.0.16.206 + A 10.0.16.207 + A 10.0.16.208 + A 10.0.16.209 + A 10.0.16.210 + A 10.0.16.211 + A 10.0.16.212 + A 10.0.16.213 + A 10.0.16.214 + A 10.0.16.215 + A 10.0.16.216 + A 10.0.16.217 + A 10.0.16.218 + A 10.0.16.219 + A 10.0.16.220 + A 10.0.16.221 + A 10.0.16.222 + A 10.0.16.223 + A 10.0.16.224 + A 10.0.16.225 + A 10.0.16.226 + A 10.0.16.227 + A 10.0.16.228 + A 10.0.16.229 + A 10.0.16.230 + A 10.0.16.231 + A 10.0.16.232 + A 10.0.16.233 + A 10.0.16.234 + A 10.0.16.235 + A 10.0.16.236 + A 10.0.16.237 + A 10.0.16.238 + A 10.0.16.239 + A 10.0.16.240 + A 10.0.16.241 + A 10.0.16.242 + A 10.0.16.243 + A 10.0.16.244 + A 10.0.16.245 + A 10.0.16.246 + A 10.0.16.247 + A 10.0.16.248 + A 10.0.16.249 + A 10.0.16.250 + A 10.0.16.251 + A 10.0.16.252 + A 10.0.16.253 + A 10.0.16.254 + A 10.0.16.255 + A 10.0.17.0 + A 10.0.17.1 + A 10.0.17.2 + A 10.0.17.3 + A 10.0.17.4 + A 10.0.17.5 + A 10.0.17.6 + A 10.0.17.7 + A 10.0.17.8 + A 10.0.17.9 + A 10.0.17.10 + A 10.0.17.11 + A 10.0.17.12 + A 10.0.17.13 + A 10.0.17.14 + A 10.0.17.15 + A 10.0.17.16 + A 10.0.17.17 + A 10.0.17.18 + A 10.0.17.19 + A 10.0.17.20 + A 10.0.17.21 + A 10.0.17.22 + A 10.0.17.23 + A 10.0.17.24 + A 10.0.17.25 + A 10.0.17.26 + A 10.0.17.27 + A 10.0.17.28 + A 10.0.17.29 + A 10.0.17.30 + A 10.0.17.31 + A 10.0.17.32 + A 10.0.17.33 + A 10.0.17.34 + A 10.0.17.35 + A 10.0.17.36 + A 10.0.17.37 + A 10.0.17.38 + A 10.0.17.39 + A 10.0.17.40 + A 10.0.17.41 + A 10.0.17.42 + A 10.0.17.43 + A 10.0.17.44 + A 10.0.17.45 + A 10.0.17.46 + A 10.0.17.47 + A 10.0.17.48 + A 10.0.17.49 + A 10.0.17.50 + A 10.0.17.51 + A 10.0.17.52 + A 10.0.17.53 + A 10.0.17.54 + A 10.0.17.55 + A 10.0.17.56 + A 10.0.17.57 + A 10.0.17.58 + A 10.0.17.59 + A 10.0.17.60 + A 10.0.17.61 + A 10.0.17.62 + A 10.0.17.63 + A 10.0.17.64 + A 10.0.17.65 + A 10.0.17.66 + A 10.0.17.67 + A 10.0.17.68 + A 10.0.17.69 + A 10.0.17.70 + A 10.0.17.71 + A 10.0.17.72 + A 10.0.17.73 + A 10.0.17.74 + A 10.0.17.75 + A 10.0.17.76 + A 10.0.17.77 + A 10.0.17.78 + A 10.0.17.79 + A 10.0.17.80 + A 10.0.17.81 + A 10.0.17.82 + A 10.0.17.83 + A 10.0.17.84 + A 10.0.17.85 + A 10.0.17.86 + A 10.0.17.87 + A 10.0.17.88 + A 10.0.17.89 + A 10.0.17.90 + A 10.0.17.91 + A 10.0.17.92 + A 10.0.17.93 + A 10.0.17.94 + A 10.0.17.95 + A 10.0.17.96 + A 10.0.17.97 + A 10.0.17.98 + A 10.0.17.99 + A 10.0.17.100 + A 10.0.17.101 + A 10.0.17.102 + A 10.0.17.103 + A 10.0.17.104 + A 10.0.17.105 + A 10.0.17.106 + A 10.0.17.107 + A 10.0.17.108 + A 10.0.17.109 + A 10.0.17.110 + A 10.0.17.111 + A 10.0.17.112 + A 10.0.17.113 + A 10.0.17.114 + A 10.0.17.115 + A 10.0.17.116 + A 10.0.17.117 + A 10.0.17.118 + A 10.0.17.119 + A 10.0.17.120 + A 10.0.17.121 + A 10.0.17.122 + A 10.0.17.123 + A 10.0.17.124 + A 10.0.17.125 + A 10.0.17.126 + A 10.0.17.127 + A 10.0.17.128 + A 10.0.17.129 + A 10.0.17.130 + A 10.0.17.131 + A 10.0.17.132 + A 10.0.17.133 + A 10.0.17.134 + A 10.0.17.135 + A 10.0.17.136 + A 10.0.17.137 + A 10.0.17.138 + A 10.0.17.139 + A 10.0.17.140 + A 10.0.17.141 + A 10.0.17.142 + A 10.0.17.143 + A 10.0.17.144 + A 10.0.17.145 + A 10.0.17.146 + A 10.0.17.147 + A 10.0.17.148 + A 10.0.17.149 + A 10.0.17.150 + A 10.0.17.151 + A 10.0.17.152 + A 10.0.17.153 + A 10.0.17.154 + A 10.0.17.155 + A 10.0.17.156 + A 10.0.17.157 + A 10.0.17.158 + A 10.0.17.159 + A 10.0.17.160 + A 10.0.17.161 + A 10.0.17.162 + A 10.0.17.163 + A 10.0.17.164 + A 10.0.17.165 + A 10.0.17.166 + A 10.0.17.167 + A 10.0.17.168 + A 10.0.17.169 + A 10.0.17.170 + A 10.0.17.171 + A 10.0.17.172 + A 10.0.17.173 + A 10.0.17.174 + A 10.0.17.175 + A 10.0.17.176 + A 10.0.17.177 + A 10.0.17.178 + A 10.0.17.179 + A 10.0.17.180 + A 10.0.17.181 + A 10.0.17.182 + A 10.0.17.183 + A 10.0.17.184 + A 10.0.17.185 + A 10.0.17.186 + A 10.0.17.187 + A 10.0.17.188 + A 10.0.17.189 + A 10.0.17.190 + A 10.0.17.191 + A 10.0.17.192 + A 10.0.17.193 + A 10.0.17.194 + A 10.0.17.195 + A 10.0.17.196 + A 10.0.17.197 + A 10.0.17.198 + A 10.0.17.199 + A 10.0.17.200 + A 10.0.17.201 + A 10.0.17.202 + A 10.0.17.203 + A 10.0.17.204 + A 10.0.17.205 + A 10.0.17.206 + A 10.0.17.207 + A 10.0.17.208 + A 10.0.17.209 + A 10.0.17.210 + A 10.0.17.211 + A 10.0.17.212 + A 10.0.17.213 + A 10.0.17.214 + A 10.0.17.215 + A 10.0.17.216 + A 10.0.17.217 + A 10.0.17.218 + A 10.0.17.219 + A 10.0.17.220 + A 10.0.17.221 + A 10.0.17.222 + A 10.0.17.223 + A 10.0.17.224 + A 10.0.17.225 + A 10.0.17.226 + A 10.0.17.227 + A 10.0.17.228 + A 10.0.17.229 + A 10.0.17.230 + A 10.0.17.231 + A 10.0.17.232 + A 10.0.17.233 + A 10.0.17.234 + A 10.0.17.235 + A 10.0.17.236 + A 10.0.17.237 + A 10.0.17.238 + A 10.0.17.239 + A 10.0.17.240 + A 10.0.17.241 + A 10.0.17.242 + A 10.0.17.243 + A 10.0.17.244 + A 10.0.17.245 + A 10.0.17.246 + A 10.0.17.247 + A 10.0.17.248 + A 10.0.17.249 + A 10.0.17.250 + A 10.0.17.251 + A 10.0.17.252 + A 10.0.17.253 + A 10.0.17.254 + A 10.0.17.255 + A 10.0.18.0 + A 10.0.18.1 + A 10.0.18.2 + A 10.0.18.3 + A 10.0.18.4 + A 10.0.18.5 + A 10.0.18.6 + A 10.0.18.7 + A 10.0.18.8 + A 10.0.18.9 + A 10.0.18.10 + A 10.0.18.11 + A 10.0.18.12 + A 10.0.18.13 + A 10.0.18.14 + A 10.0.18.15 + A 10.0.18.16 + A 10.0.18.17 + A 10.0.18.18 + A 10.0.18.19 + A 10.0.18.20 + A 10.0.18.21 + A 10.0.18.22 + A 10.0.18.23 + A 10.0.18.24 + A 10.0.18.25 + A 10.0.18.26 + A 10.0.18.27 + A 10.0.18.28 + A 10.0.18.29 + A 10.0.18.30 + A 10.0.18.31 + A 10.0.18.32 + A 10.0.18.33 + A 10.0.18.34 + A 10.0.18.35 + A 10.0.18.36 + A 10.0.18.37 + A 10.0.18.38 + A 10.0.18.39 + A 10.0.18.40 + A 10.0.18.41 + A 10.0.18.42 + A 10.0.18.43 + A 10.0.18.44 + A 10.0.18.45 + A 10.0.18.46 + A 10.0.18.47 + A 10.0.18.48 + A 10.0.18.49 + A 10.0.18.50 + A 10.0.18.51 + A 10.0.18.52 + A 10.0.18.53 + A 10.0.18.54 + A 10.0.18.55 + A 10.0.18.56 + A 10.0.18.57 + A 10.0.18.58 + A 10.0.18.59 + A 10.0.18.60 + A 10.0.18.61 + A 10.0.18.62 + A 10.0.18.63 + A 10.0.18.64 + A 10.0.18.65 + A 10.0.18.66 + A 10.0.18.67 + A 10.0.18.68 + A 10.0.18.69 + A 10.0.18.70 + A 10.0.18.71 + A 10.0.18.72 + A 10.0.18.73 + A 10.0.18.74 + A 10.0.18.75 + A 10.0.18.76 + A 10.0.18.77 + A 10.0.18.78 + A 10.0.18.79 + A 10.0.18.80 + A 10.0.18.81 + A 10.0.18.82 + A 10.0.18.83 + A 10.0.18.84 + A 10.0.18.85 + A 10.0.18.86 + A 10.0.18.87 + A 10.0.18.88 + A 10.0.18.89 + A 10.0.18.90 + A 10.0.18.91 + A 10.0.18.92 + A 10.0.18.93 + A 10.0.18.94 + A 10.0.18.95 + A 10.0.18.96 + A 10.0.18.97 + A 10.0.18.98 + A 10.0.18.99 + A 10.0.18.100 + A 10.0.18.101 + A 10.0.18.102 + A 10.0.18.103 + A 10.0.18.104 + A 10.0.18.105 + A 10.0.18.106 + A 10.0.18.107 + A 10.0.18.108 + A 10.0.18.109 + A 10.0.18.110 + A 10.0.18.111 + A 10.0.18.112 + A 10.0.18.113 + A 10.0.18.114 + A 10.0.18.115 + A 10.0.18.116 + A 10.0.18.117 + A 10.0.18.118 + A 10.0.18.119 + A 10.0.18.120 + A 10.0.18.121 + A 10.0.18.122 + A 10.0.18.123 + A 10.0.18.124 + A 10.0.18.125 + A 10.0.18.126 + A 10.0.18.127 + A 10.0.18.128 + A 10.0.18.129 + A 10.0.18.130 + A 10.0.18.131 + A 10.0.18.132 + A 10.0.18.133 + A 10.0.18.134 + A 10.0.18.135 + A 10.0.18.136 + A 10.0.18.137 + A 10.0.18.138 + A 10.0.18.139 + A 10.0.18.140 + A 10.0.18.141 + A 10.0.18.142 + A 10.0.18.143 + A 10.0.18.144 + A 10.0.18.145 + A 10.0.18.146 + A 10.0.18.147 + A 10.0.18.148 + A 10.0.18.149 + A 10.0.18.150 + A 10.0.18.151 + A 10.0.18.152 + A 10.0.18.153 + A 10.0.18.154 + A 10.0.18.155 + A 10.0.18.156 + A 10.0.18.157 + A 10.0.18.158 + A 10.0.18.159 + A 10.0.18.160 + A 10.0.18.161 + A 10.0.18.162 + A 10.0.18.163 + A 10.0.18.164 + A 10.0.18.165 + A 10.0.18.166 + A 10.0.18.167 + A 10.0.18.168 + A 10.0.18.169 + A 10.0.18.170 + A 10.0.18.171 + A 10.0.18.172 + A 10.0.18.173 + A 10.0.18.174 + A 10.0.18.175 + A 10.0.18.176 + A 10.0.18.177 + A 10.0.18.178 + A 10.0.18.179 + A 10.0.18.180 + A 10.0.18.181 + A 10.0.18.182 + A 10.0.18.183 + A 10.0.18.184 + A 10.0.18.185 + A 10.0.18.186 + A 10.0.18.187 + A 10.0.18.188 + A 10.0.18.189 + A 10.0.18.190 + A 10.0.18.191 + A 10.0.18.192 + A 10.0.18.193 + A 10.0.18.194 + A 10.0.18.195 + A 10.0.18.196 + A 10.0.18.197 + A 10.0.18.198 + A 10.0.18.199 + A 10.0.18.200 + A 10.0.18.201 + A 10.0.18.202 + A 10.0.18.203 + A 10.0.18.204 + A 10.0.18.205 + A 10.0.18.206 + A 10.0.18.207 + A 10.0.18.208 + A 10.0.18.209 + A 10.0.18.210 + A 10.0.18.211 + A 10.0.18.212 + A 10.0.18.213 + A 10.0.18.214 + A 10.0.18.215 + A 10.0.18.216 + A 10.0.18.217 + A 10.0.18.218 + A 10.0.18.219 + A 10.0.18.220 + A 10.0.18.221 + A 10.0.18.222 + A 10.0.18.223 + A 10.0.18.224 + A 10.0.18.225 + A 10.0.18.226 + A 10.0.18.227 + A 10.0.18.228 + A 10.0.18.229 + A 10.0.18.230 + A 10.0.18.231 + A 10.0.18.232 + A 10.0.18.233 + A 10.0.18.234 + A 10.0.18.235 + A 10.0.18.236 + A 10.0.18.237 + A 10.0.18.238 + A 10.0.18.239 + A 10.0.18.240 + A 10.0.18.241 + A 10.0.18.242 + A 10.0.18.243 + A 10.0.18.244 + A 10.0.18.245 + A 10.0.18.246 + A 10.0.18.247 + A 10.0.18.248 + A 10.0.18.249 + A 10.0.18.250 + A 10.0.18.251 + A 10.0.18.252 + A 10.0.18.253 + A 10.0.18.254 + A 10.0.18.255 + A 10.0.19.0 + A 10.0.19.1 + A 10.0.19.2 + A 10.0.19.3 + A 10.0.19.4 + A 10.0.19.5 + A 10.0.19.6 + A 10.0.19.7 + A 10.0.19.8 + A 10.0.19.9 + A 10.0.19.10 + A 10.0.19.11 + A 10.0.19.12 + A 10.0.19.13 + A 10.0.19.14 + A 10.0.19.15 + A 10.0.19.16 + A 10.0.19.17 + A 10.0.19.18 + A 10.0.19.19 + A 10.0.19.20 + A 10.0.19.21 + A 10.0.19.22 + A 10.0.19.23 + A 10.0.19.24 + A 10.0.19.25 + A 10.0.19.26 + A 10.0.19.27 + A 10.0.19.28 + A 10.0.19.29 + A 10.0.19.30 + A 10.0.19.31 + A 10.0.19.32 + A 10.0.19.33 + A 10.0.19.34 + A 10.0.19.35 + A 10.0.19.36 + A 10.0.19.37 + A 10.0.19.38 + A 10.0.19.39 + A 10.0.19.40 + A 10.0.19.41 + A 10.0.19.42 + A 10.0.19.43 + A 10.0.19.44 + A 10.0.19.45 + A 10.0.19.46 + A 10.0.19.47 + A 10.0.19.48 + A 10.0.19.49 + A 10.0.19.50 + A 10.0.19.51 + A 10.0.19.52 + A 10.0.19.53 + A 10.0.19.54 + A 10.0.19.55 + A 10.0.19.56 + A 10.0.19.57 + A 10.0.19.58 + A 10.0.19.59 + A 10.0.19.60 + A 10.0.19.61 + A 10.0.19.62 + A 10.0.19.63 + A 10.0.19.64 + A 10.0.19.65 + A 10.0.19.66 + A 10.0.19.67 + A 10.0.19.68 + A 10.0.19.69 + A 10.0.19.70 + A 10.0.19.71 + A 10.0.19.72 + A 10.0.19.73 + A 10.0.19.74 + A 10.0.19.75 + A 10.0.19.76 + A 10.0.19.77 + A 10.0.19.78 + A 10.0.19.79 + A 10.0.19.80 + A 10.0.19.81 + A 10.0.19.82 + A 10.0.19.83 + A 10.0.19.84 + A 10.0.19.85 + A 10.0.19.86 + A 10.0.19.87 + A 10.0.19.88 + A 10.0.19.89 + A 10.0.19.90 + A 10.0.19.91 + A 10.0.19.92 + A 10.0.19.93 + A 10.0.19.94 + A 10.0.19.95 + A 10.0.19.96 + A 10.0.19.97 + A 10.0.19.98 + A 10.0.19.99 + A 10.0.19.100 + A 10.0.19.101 + A 10.0.19.102 + A 10.0.19.103 + A 10.0.19.104 + A 10.0.19.105 + A 10.0.19.106 + A 10.0.19.107 + A 10.0.19.108 + A 10.0.19.109 + A 10.0.19.110 + A 10.0.19.111 + A 10.0.19.112 + A 10.0.19.113 + A 10.0.19.114 + A 10.0.19.115 + A 10.0.19.116 + A 10.0.19.117 + A 10.0.19.118 + A 10.0.19.119 + A 10.0.19.120 + A 10.0.19.121 + A 10.0.19.122 + A 10.0.19.123 + A 10.0.19.124 + A 10.0.19.125 + A 10.0.19.126 + A 10.0.19.127 + A 10.0.19.128 + A 10.0.19.129 + A 10.0.19.130 + A 10.0.19.131 + A 10.0.19.132 + A 10.0.19.133 + A 10.0.19.134 + A 10.0.19.135 +a-maximum-rrset A 10.0.0.0 + A 10.0.0.1 + A 10.0.0.2 + A 10.0.0.3 + A 10.0.0.4 + A 10.0.0.5 + A 10.0.0.6 + A 10.0.0.7 + A 10.0.0.8 + A 10.0.0.9 + A 10.0.0.10 + A 10.0.0.11 + A 10.0.0.12 + A 10.0.0.13 + A 10.0.0.14 + A 10.0.0.15 + A 10.0.0.16 + A 10.0.0.17 + A 10.0.0.18 + A 10.0.0.19 + A 10.0.0.20 + A 10.0.0.21 + A 10.0.0.22 + A 10.0.0.23 + A 10.0.0.24 + A 10.0.0.25 + A 10.0.0.26 + A 10.0.0.27 + A 10.0.0.28 + A 10.0.0.29 + A 10.0.0.30 + A 10.0.0.31 + A 10.0.0.32 + A 10.0.0.33 + A 10.0.0.34 + A 10.0.0.35 + A 10.0.0.36 + A 10.0.0.37 + A 10.0.0.38 + A 10.0.0.39 + A 10.0.0.40 + A 10.0.0.41 + A 10.0.0.42 + A 10.0.0.43 + A 10.0.0.44 + A 10.0.0.45 + A 10.0.0.46 + A 10.0.0.47 + A 10.0.0.48 + A 10.0.0.49 + A 10.0.0.50 + A 10.0.0.51 + A 10.0.0.52 + A 10.0.0.53 + A 10.0.0.54 + A 10.0.0.55 + A 10.0.0.56 + A 10.0.0.57 + A 10.0.0.58 + A 10.0.0.59 + A 10.0.0.60 + A 10.0.0.61 + A 10.0.0.62 + A 10.0.0.63 + A 10.0.0.64 + A 10.0.0.65 + A 10.0.0.66 + A 10.0.0.67 + A 10.0.0.68 + A 10.0.0.69 + A 10.0.0.70 + A 10.0.0.71 + A 10.0.0.72 + A 10.0.0.73 + A 10.0.0.74 + A 10.0.0.75 + A 10.0.0.76 + A 10.0.0.77 + A 10.0.0.78 + A 10.0.0.79 + A 10.0.0.80 + A 10.0.0.81 + A 10.0.0.82 + A 10.0.0.83 + A 10.0.0.84 + A 10.0.0.85 + A 10.0.0.86 + A 10.0.0.87 + A 10.0.0.88 + A 10.0.0.89 + A 10.0.0.90 + A 10.0.0.91 + A 10.0.0.92 + A 10.0.0.93 + A 10.0.0.94 + A 10.0.0.95 + A 10.0.0.96 + A 10.0.0.97 + A 10.0.0.98 + A 10.0.0.99 + A 10.0.0.100 + A 10.0.0.101 + A 10.0.0.102 + A 10.0.0.103 + A 10.0.0.104 + A 10.0.0.105 + A 10.0.0.106 + A 10.0.0.107 + A 10.0.0.108 + A 10.0.0.109 + A 10.0.0.110 + A 10.0.0.111 + A 10.0.0.112 + A 10.0.0.113 + A 10.0.0.114 + A 10.0.0.115 + A 10.0.0.116 + A 10.0.0.117 + A 10.0.0.118 + A 10.0.0.119 + A 10.0.0.120 + A 10.0.0.121 + A 10.0.0.122 + A 10.0.0.123 + A 10.0.0.124 + A 10.0.0.125 + A 10.0.0.126 + A 10.0.0.127 + A 10.0.0.128 + A 10.0.0.129 + A 10.0.0.130 + A 10.0.0.131 + A 10.0.0.132 + A 10.0.0.133 + A 10.0.0.134 + A 10.0.0.135 + A 10.0.0.136 + A 10.0.0.137 + A 10.0.0.138 + A 10.0.0.139 + A 10.0.0.140 + A 10.0.0.141 + A 10.0.0.142 + A 10.0.0.143 + A 10.0.0.144 + A 10.0.0.145 + A 10.0.0.146 + A 10.0.0.147 + A 10.0.0.148 + A 10.0.0.149 + A 10.0.0.150 + A 10.0.0.151 + A 10.0.0.152 + A 10.0.0.153 + A 10.0.0.154 + A 10.0.0.155 + A 10.0.0.156 + A 10.0.0.157 + A 10.0.0.158 + A 10.0.0.159 + A 10.0.0.160 + A 10.0.0.161 + A 10.0.0.162 + A 10.0.0.163 + A 10.0.0.164 + A 10.0.0.165 + A 10.0.0.166 + A 10.0.0.167 + A 10.0.0.168 + A 10.0.0.169 + A 10.0.0.170 + A 10.0.0.171 + A 10.0.0.172 + A 10.0.0.173 + A 10.0.0.174 + A 10.0.0.175 + A 10.0.0.176 + A 10.0.0.177 + A 10.0.0.178 + A 10.0.0.179 + A 10.0.0.180 + A 10.0.0.181 + A 10.0.0.182 + A 10.0.0.183 + A 10.0.0.184 + A 10.0.0.185 + A 10.0.0.186 + A 10.0.0.187 + A 10.0.0.188 + A 10.0.0.189 + A 10.0.0.190 + A 10.0.0.191 + A 10.0.0.192 + A 10.0.0.193 + A 10.0.0.194 + A 10.0.0.195 + A 10.0.0.196 + A 10.0.0.197 + A 10.0.0.198 + A 10.0.0.199 + A 10.0.0.200 + A 10.0.0.201 + A 10.0.0.202 + A 10.0.0.203 + A 10.0.0.204 + A 10.0.0.205 + A 10.0.0.206 + A 10.0.0.207 + A 10.0.0.208 + A 10.0.0.209 + A 10.0.0.210 + A 10.0.0.211 + A 10.0.0.212 + A 10.0.0.213 + A 10.0.0.214 + A 10.0.0.215 + A 10.0.0.216 + A 10.0.0.217 + A 10.0.0.218 + A 10.0.0.219 + A 10.0.0.220 + A 10.0.0.221 + A 10.0.0.222 + A 10.0.0.223 + A 10.0.0.224 + A 10.0.0.225 + A 10.0.0.226 + A 10.0.0.227 + A 10.0.0.228 + A 10.0.0.229 + A 10.0.0.230 + A 10.0.0.231 + A 10.0.0.232 + A 10.0.0.233 + A 10.0.0.234 + A 10.0.0.235 + A 10.0.0.236 + A 10.0.0.237 + A 10.0.0.238 + A 10.0.0.239 + A 10.0.0.240 + A 10.0.0.241 + A 10.0.0.242 + A 10.0.0.243 + A 10.0.0.244 + A 10.0.0.245 + A 10.0.0.246 + A 10.0.0.247 + A 10.0.0.248 + A 10.0.0.249 + A 10.0.0.250 + A 10.0.0.251 + A 10.0.0.252 + A 10.0.0.253 + A 10.0.0.254 + A 10.0.0.255 + A 10.0.1.0 + A 10.0.1.1 + A 10.0.1.2 + A 10.0.1.3 + A 10.0.1.4 + A 10.0.1.5 + A 10.0.1.6 + A 10.0.1.7 + A 10.0.1.8 + A 10.0.1.9 + A 10.0.1.10 + A 10.0.1.11 + A 10.0.1.12 + A 10.0.1.13 + A 10.0.1.14 + A 10.0.1.15 + A 10.0.1.16 + A 10.0.1.17 + A 10.0.1.18 + A 10.0.1.19 + A 10.0.1.20 + A 10.0.1.21 + A 10.0.1.22 + A 10.0.1.23 + A 10.0.1.24 + A 10.0.1.25 + A 10.0.1.26 + A 10.0.1.27 + A 10.0.1.28 + A 10.0.1.29 + A 10.0.1.30 + A 10.0.1.31 + A 10.0.1.32 + A 10.0.1.33 + A 10.0.1.34 + A 10.0.1.35 + A 10.0.1.36 + A 10.0.1.37 + A 10.0.1.38 + A 10.0.1.39 + A 10.0.1.40 + A 10.0.1.41 + A 10.0.1.42 + A 10.0.1.43 + A 10.0.1.44 + A 10.0.1.45 + A 10.0.1.46 + A 10.0.1.47 + A 10.0.1.48 + A 10.0.1.49 + A 10.0.1.50 + A 10.0.1.51 + A 10.0.1.52 + A 10.0.1.53 + A 10.0.1.54 + A 10.0.1.55 + A 10.0.1.56 + A 10.0.1.57 + A 10.0.1.58 + A 10.0.1.59 + A 10.0.1.60 + A 10.0.1.61 + A 10.0.1.62 + A 10.0.1.63 + A 10.0.1.64 + A 10.0.1.65 + A 10.0.1.66 + A 10.0.1.67 + A 10.0.1.68 + A 10.0.1.69 + A 10.0.1.70 + A 10.0.1.71 + A 10.0.1.72 + A 10.0.1.73 + A 10.0.1.74 + A 10.0.1.75 + A 10.0.1.76 + A 10.0.1.77 + A 10.0.1.78 + A 10.0.1.79 + A 10.0.1.80 + A 10.0.1.81 + A 10.0.1.82 + A 10.0.1.83 + A 10.0.1.84 + A 10.0.1.85 + A 10.0.1.86 + A 10.0.1.87 + A 10.0.1.88 + A 10.0.1.89 + A 10.0.1.90 + A 10.0.1.91 + A 10.0.1.92 + A 10.0.1.93 + A 10.0.1.94 + A 10.0.1.95 + A 10.0.1.96 + A 10.0.1.97 + A 10.0.1.98 + A 10.0.1.99 + A 10.0.1.100 + A 10.0.1.101 + A 10.0.1.102 + A 10.0.1.103 + A 10.0.1.104 + A 10.0.1.105 + A 10.0.1.106 + A 10.0.1.107 + A 10.0.1.108 + A 10.0.1.109 + A 10.0.1.110 + A 10.0.1.111 + A 10.0.1.112 + A 10.0.1.113 + A 10.0.1.114 + A 10.0.1.115 + A 10.0.1.116 + A 10.0.1.117 + A 10.0.1.118 + A 10.0.1.119 + A 10.0.1.120 + A 10.0.1.121 + A 10.0.1.122 + A 10.0.1.123 + A 10.0.1.124 + A 10.0.1.125 + A 10.0.1.126 + A 10.0.1.127 + A 10.0.1.128 + A 10.0.1.129 + A 10.0.1.130 + A 10.0.1.131 + A 10.0.1.132 + A 10.0.1.133 + A 10.0.1.134 + A 10.0.1.135 + A 10.0.1.136 + A 10.0.1.137 + A 10.0.1.138 + A 10.0.1.139 + A 10.0.1.140 + A 10.0.1.141 + A 10.0.1.142 + A 10.0.1.143 + A 10.0.1.144 + A 10.0.1.145 + A 10.0.1.146 + A 10.0.1.147 + A 10.0.1.148 + A 10.0.1.149 + A 10.0.1.150 + A 10.0.1.151 + A 10.0.1.152 + A 10.0.1.153 + A 10.0.1.154 + A 10.0.1.155 + A 10.0.1.156 + A 10.0.1.157 + A 10.0.1.158 + A 10.0.1.159 + A 10.0.1.160 + A 10.0.1.161 + A 10.0.1.162 + A 10.0.1.163 + A 10.0.1.164 + A 10.0.1.165 + A 10.0.1.166 + A 10.0.1.167 + A 10.0.1.168 + A 10.0.1.169 + A 10.0.1.170 + A 10.0.1.171 + A 10.0.1.172 + A 10.0.1.173 + A 10.0.1.174 + A 10.0.1.175 + A 10.0.1.176 + A 10.0.1.177 + A 10.0.1.178 + A 10.0.1.179 + A 10.0.1.180 + A 10.0.1.181 + A 10.0.1.182 + A 10.0.1.183 + A 10.0.1.184 + A 10.0.1.185 + A 10.0.1.186 + A 10.0.1.187 + A 10.0.1.188 + A 10.0.1.189 + A 10.0.1.190 + A 10.0.1.191 + A 10.0.1.192 + A 10.0.1.193 + A 10.0.1.194 + A 10.0.1.195 + A 10.0.1.196 + A 10.0.1.197 + A 10.0.1.198 + A 10.0.1.199 + A 10.0.1.200 + A 10.0.1.201 + A 10.0.1.202 + A 10.0.1.203 + A 10.0.1.204 + A 10.0.1.205 + A 10.0.1.206 + A 10.0.1.207 + A 10.0.1.208 + A 10.0.1.209 + A 10.0.1.210 + A 10.0.1.211 + A 10.0.1.212 + A 10.0.1.213 + A 10.0.1.214 + A 10.0.1.215 + A 10.0.1.216 + A 10.0.1.217 + A 10.0.1.218 + A 10.0.1.219 + A 10.0.1.220 + A 10.0.1.221 + A 10.0.1.222 + A 10.0.1.223 + A 10.0.1.224 + A 10.0.1.225 + A 10.0.1.226 + A 10.0.1.227 + A 10.0.1.228 + A 10.0.1.229 + A 10.0.1.230 + A 10.0.1.231 + A 10.0.1.232 + A 10.0.1.233 + A 10.0.1.234 + A 10.0.1.235 + A 10.0.1.236 + A 10.0.1.237 + A 10.0.1.238 + A 10.0.1.239 + A 10.0.1.240 + A 10.0.1.241 + A 10.0.1.242 + A 10.0.1.243 + A 10.0.1.244 + A 10.0.1.245 + A 10.0.1.246 + A 10.0.1.247 + A 10.0.1.248 + A 10.0.1.249 + A 10.0.1.250 + A 10.0.1.251 + A 10.0.1.252 + A 10.0.1.253 + A 10.0.1.254 + A 10.0.1.255 + A 10.0.2.0 + A 10.0.2.1 + A 10.0.2.2 + A 10.0.2.3 + A 10.0.2.4 + A 10.0.2.5 + A 10.0.2.6 + A 10.0.2.7 + A 10.0.2.8 + A 10.0.2.9 + A 10.0.2.10 + A 10.0.2.11 + A 10.0.2.12 + A 10.0.2.13 + A 10.0.2.14 + A 10.0.2.15 + A 10.0.2.16 + A 10.0.2.17 + A 10.0.2.18 + A 10.0.2.19 + A 10.0.2.20 + A 10.0.2.21 + A 10.0.2.22 + A 10.0.2.23 + A 10.0.2.24 + A 10.0.2.25 + A 10.0.2.26 + A 10.0.2.27 + A 10.0.2.28 + A 10.0.2.29 + A 10.0.2.30 + A 10.0.2.31 + A 10.0.2.32 + A 10.0.2.33 + A 10.0.2.34 + A 10.0.2.35 + A 10.0.2.36 + A 10.0.2.37 + A 10.0.2.38 + A 10.0.2.39 + A 10.0.2.40 + A 10.0.2.41 + A 10.0.2.42 + A 10.0.2.43 + A 10.0.2.44 + A 10.0.2.45 + A 10.0.2.46 + A 10.0.2.47 + A 10.0.2.48 + A 10.0.2.49 + A 10.0.2.50 + A 10.0.2.51 + A 10.0.2.52 + A 10.0.2.53 + A 10.0.2.54 + A 10.0.2.55 + A 10.0.2.56 + A 10.0.2.57 + A 10.0.2.58 + A 10.0.2.59 + A 10.0.2.60 + A 10.0.2.61 + A 10.0.2.62 + A 10.0.2.63 + A 10.0.2.64 + A 10.0.2.65 + A 10.0.2.66 + A 10.0.2.67 + A 10.0.2.68 + A 10.0.2.69 + A 10.0.2.70 + A 10.0.2.71 + A 10.0.2.72 + A 10.0.2.73 + A 10.0.2.74 + A 10.0.2.75 + A 10.0.2.76 + A 10.0.2.77 + A 10.0.2.78 + A 10.0.2.79 + A 10.0.2.80 + A 10.0.2.81 + A 10.0.2.82 + A 10.0.2.83 + A 10.0.2.84 + A 10.0.2.85 + A 10.0.2.86 + A 10.0.2.87 + A 10.0.2.88 + A 10.0.2.89 + A 10.0.2.90 + A 10.0.2.91 + A 10.0.2.92 + A 10.0.2.93 + A 10.0.2.94 + A 10.0.2.95 + A 10.0.2.96 + A 10.0.2.97 + A 10.0.2.98 + A 10.0.2.99 + A 10.0.2.100 + A 10.0.2.101 + A 10.0.2.102 + A 10.0.2.103 + A 10.0.2.104 + A 10.0.2.105 + A 10.0.2.106 + A 10.0.2.107 + A 10.0.2.108 + A 10.0.2.109 + A 10.0.2.110 + A 10.0.2.111 + A 10.0.2.112 + A 10.0.2.113 + A 10.0.2.114 + A 10.0.2.115 + A 10.0.2.116 + A 10.0.2.117 + A 10.0.2.118 + A 10.0.2.119 + A 10.0.2.120 + A 10.0.2.121 + A 10.0.2.122 + A 10.0.2.123 + A 10.0.2.124 + A 10.0.2.125 + A 10.0.2.126 + A 10.0.2.127 + A 10.0.2.128 + A 10.0.2.129 + A 10.0.2.130 + A 10.0.2.131 + A 10.0.2.132 + A 10.0.2.133 + A 10.0.2.134 + A 10.0.2.135 + A 10.0.2.136 + A 10.0.2.137 + A 10.0.2.138 + A 10.0.2.139 + A 10.0.2.140 + A 10.0.2.141 + A 10.0.2.142 + A 10.0.2.143 + A 10.0.2.144 + A 10.0.2.145 + A 10.0.2.146 + A 10.0.2.147 + A 10.0.2.148 + A 10.0.2.149 + A 10.0.2.150 + A 10.0.2.151 + A 10.0.2.152 + A 10.0.2.153 + A 10.0.2.154 + A 10.0.2.155 + A 10.0.2.156 + A 10.0.2.157 + A 10.0.2.158 + A 10.0.2.159 + A 10.0.2.160 + A 10.0.2.161 + A 10.0.2.162 + A 10.0.2.163 + A 10.0.2.164 + A 10.0.2.165 + A 10.0.2.166 + A 10.0.2.167 + A 10.0.2.168 + A 10.0.2.169 + A 10.0.2.170 + A 10.0.2.171 + A 10.0.2.172 + A 10.0.2.173 + A 10.0.2.174 + A 10.0.2.175 + A 10.0.2.176 + A 10.0.2.177 + A 10.0.2.178 + A 10.0.2.179 + A 10.0.2.180 + A 10.0.2.181 + A 10.0.2.182 + A 10.0.2.183 + A 10.0.2.184 + A 10.0.2.185 + A 10.0.2.186 + A 10.0.2.187 + A 10.0.2.188 + A 10.0.2.189 + A 10.0.2.190 + A 10.0.2.191 + A 10.0.2.192 + A 10.0.2.193 + A 10.0.2.194 + A 10.0.2.195 + A 10.0.2.196 + A 10.0.2.197 + A 10.0.2.198 + A 10.0.2.199 + A 10.0.2.200 + A 10.0.2.201 + A 10.0.2.202 + A 10.0.2.203 + A 10.0.2.204 + A 10.0.2.205 + A 10.0.2.206 + A 10.0.2.207 + A 10.0.2.208 + A 10.0.2.209 + A 10.0.2.210 + A 10.0.2.211 + A 10.0.2.212 + A 10.0.2.213 + A 10.0.2.214 + A 10.0.2.215 + A 10.0.2.216 + A 10.0.2.217 + A 10.0.2.218 + A 10.0.2.219 + A 10.0.2.220 + A 10.0.2.221 + A 10.0.2.222 + A 10.0.2.223 + A 10.0.2.224 + A 10.0.2.225 + A 10.0.2.226 + A 10.0.2.227 + A 10.0.2.228 + A 10.0.2.229 + A 10.0.2.230 + A 10.0.2.231 + A 10.0.2.232 + A 10.0.2.233 + A 10.0.2.234 + A 10.0.2.235 + A 10.0.2.236 + A 10.0.2.237 + A 10.0.2.238 + A 10.0.2.239 + A 10.0.2.240 + A 10.0.2.241 + A 10.0.2.242 + A 10.0.2.243 + A 10.0.2.244 + A 10.0.2.245 + A 10.0.2.246 + A 10.0.2.247 + A 10.0.2.248 + A 10.0.2.249 + A 10.0.2.250 + A 10.0.2.251 + A 10.0.2.252 + A 10.0.2.253 + A 10.0.2.254 + A 10.0.2.255 + A 10.0.3.0 + A 10.0.3.1 + A 10.0.3.2 + A 10.0.3.3 + A 10.0.3.4 + A 10.0.3.5 + A 10.0.3.6 + A 10.0.3.7 + A 10.0.3.8 + A 10.0.3.9 + A 10.0.3.10 + A 10.0.3.11 + A 10.0.3.12 + A 10.0.3.13 + A 10.0.3.14 + A 10.0.3.15 + A 10.0.3.16 + A 10.0.3.17 + A 10.0.3.18 + A 10.0.3.19 + A 10.0.3.20 + A 10.0.3.21 + A 10.0.3.22 + A 10.0.3.23 + A 10.0.3.24 + A 10.0.3.25 + A 10.0.3.26 + A 10.0.3.27 + A 10.0.3.28 + A 10.0.3.29 + A 10.0.3.30 + A 10.0.3.31 + A 10.0.3.32 + A 10.0.3.33 + A 10.0.3.34 + A 10.0.3.35 + A 10.0.3.36 + A 10.0.3.37 + A 10.0.3.38 + A 10.0.3.39 + A 10.0.3.40 + A 10.0.3.41 + A 10.0.3.42 + A 10.0.3.43 + A 10.0.3.44 + A 10.0.3.45 + A 10.0.3.46 + A 10.0.3.47 + A 10.0.3.48 + A 10.0.3.49 + A 10.0.3.50 + A 10.0.3.51 + A 10.0.3.52 + A 10.0.3.53 + A 10.0.3.54 + A 10.0.3.55 + A 10.0.3.56 + A 10.0.3.57 + A 10.0.3.58 + A 10.0.3.59 + A 10.0.3.60 + A 10.0.3.61 + A 10.0.3.62 + A 10.0.3.63 + A 10.0.3.64 + A 10.0.3.65 + A 10.0.3.66 + A 10.0.3.67 + A 10.0.3.68 + A 10.0.3.69 + A 10.0.3.70 + A 10.0.3.71 + A 10.0.3.72 + A 10.0.3.73 + A 10.0.3.74 + A 10.0.3.75 + A 10.0.3.76 + A 10.0.3.77 + A 10.0.3.78 + A 10.0.3.79 + A 10.0.3.80 + A 10.0.3.81 + A 10.0.3.82 + A 10.0.3.83 + A 10.0.3.84 + A 10.0.3.85 + A 10.0.3.86 + A 10.0.3.87 + A 10.0.3.88 + A 10.0.3.89 + A 10.0.3.90 + A 10.0.3.91 + A 10.0.3.92 + A 10.0.3.93 + A 10.0.3.94 + A 10.0.3.95 + A 10.0.3.96 + A 10.0.3.97 + A 10.0.3.98 + A 10.0.3.99 + A 10.0.3.100 + A 10.0.3.101 + A 10.0.3.102 + A 10.0.3.103 + A 10.0.3.104 + A 10.0.3.105 + A 10.0.3.106 + A 10.0.3.107 + A 10.0.3.108 + A 10.0.3.109 + A 10.0.3.110 + A 10.0.3.111 + A 10.0.3.112 + A 10.0.3.113 + A 10.0.3.114 + A 10.0.3.115 + A 10.0.3.116 + A 10.0.3.117 + A 10.0.3.118 + A 10.0.3.119 + A 10.0.3.120 + A 10.0.3.121 + A 10.0.3.122 + A 10.0.3.123 + A 10.0.3.124 + A 10.0.3.125 + A 10.0.3.126 + A 10.0.3.127 + A 10.0.3.128 + A 10.0.3.129 + A 10.0.3.130 + A 10.0.3.131 + A 10.0.3.132 + A 10.0.3.133 + A 10.0.3.134 + A 10.0.3.135 + A 10.0.3.136 + A 10.0.3.137 + A 10.0.3.138 + A 10.0.3.139 + A 10.0.3.140 + A 10.0.3.141 + A 10.0.3.142 + A 10.0.3.143 + A 10.0.3.144 + A 10.0.3.145 + A 10.0.3.146 + A 10.0.3.147 + A 10.0.3.148 + A 10.0.3.149 + A 10.0.3.150 + A 10.0.3.151 + A 10.0.3.152 + A 10.0.3.153 + A 10.0.3.154 + A 10.0.3.155 + A 10.0.3.156 + A 10.0.3.157 + A 10.0.3.158 + A 10.0.3.159 + A 10.0.3.160 + A 10.0.3.161 + A 10.0.3.162 + A 10.0.3.163 + A 10.0.3.164 + A 10.0.3.165 + A 10.0.3.166 + A 10.0.3.167 + A 10.0.3.168 + A 10.0.3.169 + A 10.0.3.170 + A 10.0.3.171 + A 10.0.3.172 + A 10.0.3.173 + A 10.0.3.174 + A 10.0.3.175 + A 10.0.3.176 + A 10.0.3.177 + A 10.0.3.178 + A 10.0.3.179 + A 10.0.3.180 + A 10.0.3.181 + A 10.0.3.182 + A 10.0.3.183 + A 10.0.3.184 + A 10.0.3.185 + A 10.0.3.186 + A 10.0.3.187 + A 10.0.3.188 + A 10.0.3.189 + A 10.0.3.190 + A 10.0.3.191 + A 10.0.3.192 + A 10.0.3.193 + A 10.0.3.194 + A 10.0.3.195 + A 10.0.3.196 + A 10.0.3.197 + A 10.0.3.198 + A 10.0.3.199 + A 10.0.3.200 + A 10.0.3.201 + A 10.0.3.202 + A 10.0.3.203 + A 10.0.3.204 + A 10.0.3.205 + A 10.0.3.206 + A 10.0.3.207 + A 10.0.3.208 + A 10.0.3.209 + A 10.0.3.210 + A 10.0.3.211 + A 10.0.3.212 + A 10.0.3.213 + A 10.0.3.214 + A 10.0.3.215 + A 10.0.3.216 + A 10.0.3.217 + A 10.0.3.218 + A 10.0.3.219 + A 10.0.3.220 + A 10.0.3.221 + A 10.0.3.222 + A 10.0.3.223 + A 10.0.3.224 + A 10.0.3.225 + A 10.0.3.226 + A 10.0.3.227 + A 10.0.3.228 + A 10.0.3.229 + A 10.0.3.230 + A 10.0.3.231 + A 10.0.3.232 + A 10.0.3.233 + A 10.0.3.234 + A 10.0.3.235 + A 10.0.3.236 + A 10.0.3.237 + A 10.0.3.238 + A 10.0.3.239 + A 10.0.3.240 + A 10.0.3.241 + A 10.0.3.242 + A 10.0.3.243 + A 10.0.3.244 + A 10.0.3.245 + A 10.0.3.246 + A 10.0.3.247 + A 10.0.3.248 + A 10.0.3.249 + A 10.0.3.250 + A 10.0.3.251 + A 10.0.3.252 + A 10.0.3.253 + A 10.0.3.254 + A 10.0.3.255 + A 10.0.4.0 + A 10.0.4.1 + A 10.0.4.2 + A 10.0.4.3 + A 10.0.4.4 + A 10.0.4.5 + A 10.0.4.6 + A 10.0.4.7 + A 10.0.4.8 + A 10.0.4.9 + A 10.0.4.10 + A 10.0.4.11 + A 10.0.4.12 + A 10.0.4.13 + A 10.0.4.14 + A 10.0.4.15 + A 10.0.4.16 + A 10.0.4.17 + A 10.0.4.18 + A 10.0.4.19 + A 10.0.4.20 + A 10.0.4.21 + A 10.0.4.22 + A 10.0.4.23 + A 10.0.4.24 + A 10.0.4.25 + A 10.0.4.26 + A 10.0.4.27 + A 10.0.4.28 + A 10.0.4.29 + A 10.0.4.30 + A 10.0.4.31 + A 10.0.4.32 + A 10.0.4.33 + A 10.0.4.34 + A 10.0.4.35 + A 10.0.4.36 + A 10.0.4.37 + A 10.0.4.38 + A 10.0.4.39 + A 10.0.4.40 + A 10.0.4.41 + A 10.0.4.42 + A 10.0.4.43 + A 10.0.4.44 + A 10.0.4.45 + A 10.0.4.46 + A 10.0.4.47 + A 10.0.4.48 + A 10.0.4.49 + A 10.0.4.50 + A 10.0.4.51 + A 10.0.4.52 + A 10.0.4.53 + A 10.0.4.54 + A 10.0.4.55 + A 10.0.4.56 + A 10.0.4.57 + A 10.0.4.58 + A 10.0.4.59 + A 10.0.4.60 + A 10.0.4.61 + A 10.0.4.62 + A 10.0.4.63 + A 10.0.4.64 + A 10.0.4.65 + A 10.0.4.66 + A 10.0.4.67 + A 10.0.4.68 + A 10.0.4.69 + A 10.0.4.70 + A 10.0.4.71 + A 10.0.4.72 + A 10.0.4.73 + A 10.0.4.74 + A 10.0.4.75 + A 10.0.4.76 + A 10.0.4.77 + A 10.0.4.78 + A 10.0.4.79 + A 10.0.4.80 + A 10.0.4.81 + A 10.0.4.82 + A 10.0.4.83 + A 10.0.4.84 + A 10.0.4.85 + A 10.0.4.86 + A 10.0.4.87 + A 10.0.4.88 + A 10.0.4.89 + A 10.0.4.90 + A 10.0.4.91 + A 10.0.4.92 + A 10.0.4.93 + A 10.0.4.94 + A 10.0.4.95 + A 10.0.4.96 + A 10.0.4.97 + A 10.0.4.98 + A 10.0.4.99 + A 10.0.4.100 + A 10.0.4.101 + A 10.0.4.102 + A 10.0.4.103 + A 10.0.4.104 + A 10.0.4.105 + A 10.0.4.106 + A 10.0.4.107 + A 10.0.4.108 + A 10.0.4.109 + A 10.0.4.110 + A 10.0.4.111 + A 10.0.4.112 + A 10.0.4.113 + A 10.0.4.114 + A 10.0.4.115 + A 10.0.4.116 + A 10.0.4.117 + A 10.0.4.118 + A 10.0.4.119 + A 10.0.4.120 + A 10.0.4.121 + A 10.0.4.122 + A 10.0.4.123 + A 10.0.4.124 + A 10.0.4.125 + A 10.0.4.126 + A 10.0.4.127 + A 10.0.4.128 + A 10.0.4.129 + A 10.0.4.130 + A 10.0.4.131 + A 10.0.4.132 + A 10.0.4.133 + A 10.0.4.134 + A 10.0.4.135 + A 10.0.4.136 + A 10.0.4.137 + A 10.0.4.138 + A 10.0.4.139 + A 10.0.4.140 + A 10.0.4.141 + A 10.0.4.142 + A 10.0.4.143 + A 10.0.4.144 + A 10.0.4.145 + A 10.0.4.146 + A 10.0.4.147 + A 10.0.4.148 + A 10.0.4.149 + A 10.0.4.150 + A 10.0.4.151 + A 10.0.4.152 + A 10.0.4.153 + A 10.0.4.154 + A 10.0.4.155 + A 10.0.4.156 + A 10.0.4.157 + A 10.0.4.158 + A 10.0.4.159 + A 10.0.4.160 + A 10.0.4.161 + A 10.0.4.162 + A 10.0.4.163 + A 10.0.4.164 + A 10.0.4.165 + A 10.0.4.166 + A 10.0.4.167 + A 10.0.4.168 + A 10.0.4.169 + A 10.0.4.170 + A 10.0.4.171 + A 10.0.4.172 + A 10.0.4.173 + A 10.0.4.174 + A 10.0.4.175 + A 10.0.4.176 + A 10.0.4.177 + A 10.0.4.178 + A 10.0.4.179 + A 10.0.4.180 + A 10.0.4.181 + A 10.0.4.182 + A 10.0.4.183 + A 10.0.4.184 + A 10.0.4.185 + A 10.0.4.186 + A 10.0.4.187 + A 10.0.4.188 + A 10.0.4.189 + A 10.0.4.190 + A 10.0.4.191 + A 10.0.4.192 + A 10.0.4.193 + A 10.0.4.194 + A 10.0.4.195 + A 10.0.4.196 + A 10.0.4.197 + A 10.0.4.198 + A 10.0.4.199 + A 10.0.4.200 + A 10.0.4.201 + A 10.0.4.202 + A 10.0.4.203 + A 10.0.4.204 + A 10.0.4.205 + A 10.0.4.206 + A 10.0.4.207 + A 10.0.4.208 + A 10.0.4.209 + A 10.0.4.210 + A 10.0.4.211 + A 10.0.4.212 + A 10.0.4.213 + A 10.0.4.214 + A 10.0.4.215 + A 10.0.4.216 + A 10.0.4.217 + A 10.0.4.218 + A 10.0.4.219 + A 10.0.4.220 + A 10.0.4.221 + A 10.0.4.222 + A 10.0.4.223 + A 10.0.4.224 + A 10.0.4.225 + A 10.0.4.226 + A 10.0.4.227 + A 10.0.4.228 + A 10.0.4.229 + A 10.0.4.230 + A 10.0.4.231 + A 10.0.4.232 + A 10.0.4.233 + A 10.0.4.234 + A 10.0.4.235 + A 10.0.4.236 + A 10.0.4.237 + A 10.0.4.238 + A 10.0.4.239 + A 10.0.4.240 + A 10.0.4.241 + A 10.0.4.242 + A 10.0.4.243 + A 10.0.4.244 + A 10.0.4.245 + A 10.0.4.246 + A 10.0.4.247 + A 10.0.4.248 + A 10.0.4.249 + A 10.0.4.250 + A 10.0.4.251 + A 10.0.4.252 + A 10.0.4.253 + A 10.0.4.254 + A 10.0.4.255 + A 10.0.5.0 + A 10.0.5.1 + A 10.0.5.2 + A 10.0.5.3 + A 10.0.5.4 + A 10.0.5.5 + A 10.0.5.6 + A 10.0.5.7 + A 10.0.5.8 + A 10.0.5.9 + A 10.0.5.10 + A 10.0.5.11 + A 10.0.5.12 + A 10.0.5.13 + A 10.0.5.14 + A 10.0.5.15 + A 10.0.5.16 + A 10.0.5.17 + A 10.0.5.18 + A 10.0.5.19 + A 10.0.5.20 + A 10.0.5.21 + A 10.0.5.22 + A 10.0.5.23 + A 10.0.5.24 + A 10.0.5.25 + A 10.0.5.26 + A 10.0.5.27 + A 10.0.5.28 + A 10.0.5.29 + A 10.0.5.30 + A 10.0.5.31 + A 10.0.5.32 + A 10.0.5.33 + A 10.0.5.34 + A 10.0.5.35 + A 10.0.5.36 + A 10.0.5.37 + A 10.0.5.38 + A 10.0.5.39 + A 10.0.5.40 + A 10.0.5.41 + A 10.0.5.42 + A 10.0.5.43 + A 10.0.5.44 + A 10.0.5.45 + A 10.0.5.46 + A 10.0.5.47 + A 10.0.5.48 + A 10.0.5.49 + A 10.0.5.50 + A 10.0.5.51 + A 10.0.5.52 + A 10.0.5.53 + A 10.0.5.54 + A 10.0.5.55 + A 10.0.5.56 + A 10.0.5.57 + A 10.0.5.58 + A 10.0.5.59 + A 10.0.5.60 + A 10.0.5.61 + A 10.0.5.62 + A 10.0.5.63 + A 10.0.5.64 + A 10.0.5.65 + A 10.0.5.66 + A 10.0.5.67 + A 10.0.5.68 + A 10.0.5.69 + A 10.0.5.70 + A 10.0.5.71 + A 10.0.5.72 + A 10.0.5.73 + A 10.0.5.74 + A 10.0.5.75 + A 10.0.5.76 + A 10.0.5.77 + A 10.0.5.78 + A 10.0.5.79 + A 10.0.5.80 + A 10.0.5.81 + A 10.0.5.82 + A 10.0.5.83 + A 10.0.5.84 + A 10.0.5.85 + A 10.0.5.86 + A 10.0.5.87 + A 10.0.5.88 + A 10.0.5.89 + A 10.0.5.90 + A 10.0.5.91 + A 10.0.5.92 + A 10.0.5.93 + A 10.0.5.94 + A 10.0.5.95 + A 10.0.5.96 + A 10.0.5.97 + A 10.0.5.98 + A 10.0.5.99 + A 10.0.5.100 + A 10.0.5.101 + A 10.0.5.102 + A 10.0.5.103 + A 10.0.5.104 + A 10.0.5.105 + A 10.0.5.106 + A 10.0.5.107 + A 10.0.5.108 + A 10.0.5.109 + A 10.0.5.110 + A 10.0.5.111 + A 10.0.5.112 + A 10.0.5.113 + A 10.0.5.114 + A 10.0.5.115 + A 10.0.5.116 + A 10.0.5.117 + A 10.0.5.118 + A 10.0.5.119 + A 10.0.5.120 + A 10.0.5.121 + A 10.0.5.122 + A 10.0.5.123 + A 10.0.5.124 + A 10.0.5.125 + A 10.0.5.126 + A 10.0.5.127 + A 10.0.5.128 + A 10.0.5.129 + A 10.0.5.130 + A 10.0.5.131 + A 10.0.5.132 + A 10.0.5.133 + A 10.0.5.134 + A 10.0.5.135 + A 10.0.5.136 + A 10.0.5.137 + A 10.0.5.138 + A 10.0.5.139 + A 10.0.5.140 + A 10.0.5.141 + A 10.0.5.142 + A 10.0.5.143 + A 10.0.5.144 + A 10.0.5.145 + A 10.0.5.146 + A 10.0.5.147 + A 10.0.5.148 + A 10.0.5.149 + A 10.0.5.150 + A 10.0.5.151 + A 10.0.5.152 + A 10.0.5.153 + A 10.0.5.154 + A 10.0.5.155 + A 10.0.5.156 + A 10.0.5.157 + A 10.0.5.158 + A 10.0.5.159 + A 10.0.5.160 + A 10.0.5.161 + A 10.0.5.162 + A 10.0.5.163 + A 10.0.5.164 + A 10.0.5.165 + A 10.0.5.166 + A 10.0.5.167 + A 10.0.5.168 + A 10.0.5.169 + A 10.0.5.170 + A 10.0.5.171 + A 10.0.5.172 + A 10.0.5.173 + A 10.0.5.174 + A 10.0.5.175 + A 10.0.5.176 + A 10.0.5.177 + A 10.0.5.178 + A 10.0.5.179 + A 10.0.5.180 + A 10.0.5.181 + A 10.0.5.182 + A 10.0.5.183 + A 10.0.5.184 + A 10.0.5.185 + A 10.0.5.186 + A 10.0.5.187 + A 10.0.5.188 + A 10.0.5.189 + A 10.0.5.190 + A 10.0.5.191 + A 10.0.5.192 + A 10.0.5.193 + A 10.0.5.194 + A 10.0.5.195 + A 10.0.5.196 + A 10.0.5.197 + A 10.0.5.198 + A 10.0.5.199 + A 10.0.5.200 + A 10.0.5.201 + A 10.0.5.202 + A 10.0.5.203 + A 10.0.5.204 + A 10.0.5.205 + A 10.0.5.206 + A 10.0.5.207 + A 10.0.5.208 + A 10.0.5.209 + A 10.0.5.210 + A 10.0.5.211 + A 10.0.5.212 + A 10.0.5.213 + A 10.0.5.214 + A 10.0.5.215 + A 10.0.5.216 + A 10.0.5.217 + A 10.0.5.218 + A 10.0.5.219 + A 10.0.5.220 + A 10.0.5.221 + A 10.0.5.222 + A 10.0.5.223 + A 10.0.5.224 + A 10.0.5.225 + A 10.0.5.226 + A 10.0.5.227 + A 10.0.5.228 + A 10.0.5.229 + A 10.0.5.230 + A 10.0.5.231 + A 10.0.5.232 + A 10.0.5.233 + A 10.0.5.234 + A 10.0.5.235 + A 10.0.5.236 + A 10.0.5.237 + A 10.0.5.238 + A 10.0.5.239 + A 10.0.5.240 + A 10.0.5.241 + A 10.0.5.242 + A 10.0.5.243 + A 10.0.5.244 + A 10.0.5.245 + A 10.0.5.246 + A 10.0.5.247 + A 10.0.5.248 + A 10.0.5.249 + A 10.0.5.250 + A 10.0.5.251 + A 10.0.5.252 + A 10.0.5.253 + A 10.0.5.254 + A 10.0.5.255 + A 10.0.6.0 + A 10.0.6.1 + A 10.0.6.2 + A 10.0.6.3 + A 10.0.6.4 + A 10.0.6.5 + A 10.0.6.6 + A 10.0.6.7 + A 10.0.6.8 + A 10.0.6.9 + A 10.0.6.10 + A 10.0.6.11 + A 10.0.6.12 + A 10.0.6.13 + A 10.0.6.14 + A 10.0.6.15 + A 10.0.6.16 + A 10.0.6.17 + A 10.0.6.18 + A 10.0.6.19 + A 10.0.6.20 + A 10.0.6.21 + A 10.0.6.22 + A 10.0.6.23 + A 10.0.6.24 + A 10.0.6.25 + A 10.0.6.26 + A 10.0.6.27 + A 10.0.6.28 + A 10.0.6.29 + A 10.0.6.30 + A 10.0.6.31 + A 10.0.6.32 + A 10.0.6.33 + A 10.0.6.34 + A 10.0.6.35 + A 10.0.6.36 + A 10.0.6.37 + A 10.0.6.38 + A 10.0.6.39 + A 10.0.6.40 + A 10.0.6.41 + A 10.0.6.42 + A 10.0.6.43 + A 10.0.6.44 + A 10.0.6.45 + A 10.0.6.46 + A 10.0.6.47 + A 10.0.6.48 + A 10.0.6.49 + A 10.0.6.50 + A 10.0.6.51 + A 10.0.6.52 + A 10.0.6.53 + A 10.0.6.54 + A 10.0.6.55 + A 10.0.6.56 + A 10.0.6.57 + A 10.0.6.58 + A 10.0.6.59 + A 10.0.6.60 + A 10.0.6.61 + A 10.0.6.62 + A 10.0.6.63 + A 10.0.6.64 + A 10.0.6.65 + A 10.0.6.66 + A 10.0.6.67 + A 10.0.6.68 + A 10.0.6.69 + A 10.0.6.70 + A 10.0.6.71 + A 10.0.6.72 + A 10.0.6.73 + A 10.0.6.74 + A 10.0.6.75 + A 10.0.6.76 + A 10.0.6.77 + A 10.0.6.78 + A 10.0.6.79 + A 10.0.6.80 + A 10.0.6.81 + A 10.0.6.82 + A 10.0.6.83 + A 10.0.6.84 + A 10.0.6.85 + A 10.0.6.86 + A 10.0.6.87 + A 10.0.6.88 + A 10.0.6.89 + A 10.0.6.90 + A 10.0.6.91 + A 10.0.6.92 + A 10.0.6.93 + A 10.0.6.94 + A 10.0.6.95 + A 10.0.6.96 + A 10.0.6.97 + A 10.0.6.98 + A 10.0.6.99 + A 10.0.6.100 + A 10.0.6.101 + A 10.0.6.102 + A 10.0.6.103 + A 10.0.6.104 + A 10.0.6.105 + A 10.0.6.106 + A 10.0.6.107 + A 10.0.6.108 + A 10.0.6.109 + A 10.0.6.110 + A 10.0.6.111 + A 10.0.6.112 + A 10.0.6.113 + A 10.0.6.114 + A 10.0.6.115 + A 10.0.6.116 + A 10.0.6.117 + A 10.0.6.118 + A 10.0.6.119 + A 10.0.6.120 + A 10.0.6.121 + A 10.0.6.122 + A 10.0.6.123 + A 10.0.6.124 + A 10.0.6.125 + A 10.0.6.126 + A 10.0.6.127 + A 10.0.6.128 + A 10.0.6.129 + A 10.0.6.130 + A 10.0.6.131 + A 10.0.6.132 + A 10.0.6.133 + A 10.0.6.134 + A 10.0.6.135 + A 10.0.6.136 + A 10.0.6.137 + A 10.0.6.138 + A 10.0.6.139 + A 10.0.6.140 + A 10.0.6.141 + A 10.0.6.142 + A 10.0.6.143 + A 10.0.6.144 + A 10.0.6.145 + A 10.0.6.146 + A 10.0.6.147 + A 10.0.6.148 + A 10.0.6.149 + A 10.0.6.150 + A 10.0.6.151 + A 10.0.6.152 + A 10.0.6.153 + A 10.0.6.154 + A 10.0.6.155 + A 10.0.6.156 + A 10.0.6.157 + A 10.0.6.158 + A 10.0.6.159 + A 10.0.6.160 + A 10.0.6.161 + A 10.0.6.162 + A 10.0.6.163 + A 10.0.6.164 + A 10.0.6.165 + A 10.0.6.166 + A 10.0.6.167 + A 10.0.6.168 + A 10.0.6.169 + A 10.0.6.170 + A 10.0.6.171 + A 10.0.6.172 + A 10.0.6.173 + A 10.0.6.174 + A 10.0.6.175 + A 10.0.6.176 + A 10.0.6.177 + A 10.0.6.178 + A 10.0.6.179 + A 10.0.6.180 + A 10.0.6.181 + A 10.0.6.182 + A 10.0.6.183 + A 10.0.6.184 + A 10.0.6.185 + A 10.0.6.186 + A 10.0.6.187 + A 10.0.6.188 + A 10.0.6.189 + A 10.0.6.190 + A 10.0.6.191 + A 10.0.6.192 + A 10.0.6.193 + A 10.0.6.194 + A 10.0.6.195 + A 10.0.6.196 + A 10.0.6.197 + A 10.0.6.198 + A 10.0.6.199 + A 10.0.6.200 + A 10.0.6.201 + A 10.0.6.202 + A 10.0.6.203 + A 10.0.6.204 + A 10.0.6.205 + A 10.0.6.206 + A 10.0.6.207 + A 10.0.6.208 + A 10.0.6.209 + A 10.0.6.210 + A 10.0.6.211 + A 10.0.6.212 + A 10.0.6.213 + A 10.0.6.214 + A 10.0.6.215 + A 10.0.6.216 + A 10.0.6.217 + A 10.0.6.218 + A 10.0.6.219 + A 10.0.6.220 + A 10.0.6.221 + A 10.0.6.222 + A 10.0.6.223 + A 10.0.6.224 + A 10.0.6.225 + A 10.0.6.226 + A 10.0.6.227 + A 10.0.6.228 + A 10.0.6.229 + A 10.0.6.230 + A 10.0.6.231 + A 10.0.6.232 + A 10.0.6.233 + A 10.0.6.234 + A 10.0.6.235 + A 10.0.6.236 + A 10.0.6.237 + A 10.0.6.238 + A 10.0.6.239 + A 10.0.6.240 + A 10.0.6.241 + A 10.0.6.242 + A 10.0.6.243 + A 10.0.6.244 + A 10.0.6.245 + A 10.0.6.246 + A 10.0.6.247 + A 10.0.6.248 + A 10.0.6.249 + A 10.0.6.250 + A 10.0.6.251 + A 10.0.6.252 + A 10.0.6.253 + A 10.0.6.254 + A 10.0.6.255 + A 10.0.7.0 + A 10.0.7.1 + A 10.0.7.2 + A 10.0.7.3 + A 10.0.7.4 + A 10.0.7.5 + A 10.0.7.6 + A 10.0.7.7 + A 10.0.7.8 + A 10.0.7.9 + A 10.0.7.10 + A 10.0.7.11 + A 10.0.7.12 + A 10.0.7.13 + A 10.0.7.14 + A 10.0.7.15 + A 10.0.7.16 + A 10.0.7.17 + A 10.0.7.18 + A 10.0.7.19 + A 10.0.7.20 + A 10.0.7.21 + A 10.0.7.22 + A 10.0.7.23 + A 10.0.7.24 + A 10.0.7.25 + A 10.0.7.26 + A 10.0.7.27 + A 10.0.7.28 + A 10.0.7.29 + A 10.0.7.30 + A 10.0.7.31 + A 10.0.7.32 + A 10.0.7.33 + A 10.0.7.34 + A 10.0.7.35 + A 10.0.7.36 + A 10.0.7.37 + A 10.0.7.38 + A 10.0.7.39 + A 10.0.7.40 + A 10.0.7.41 + A 10.0.7.42 + A 10.0.7.43 + A 10.0.7.44 + A 10.0.7.45 + A 10.0.7.46 + A 10.0.7.47 + A 10.0.7.48 + A 10.0.7.49 + A 10.0.7.50 + A 10.0.7.51 + A 10.0.7.52 + A 10.0.7.53 + A 10.0.7.54 + A 10.0.7.55 + A 10.0.7.56 + A 10.0.7.57 + A 10.0.7.58 + A 10.0.7.59 + A 10.0.7.60 + A 10.0.7.61 + A 10.0.7.62 + A 10.0.7.63 + A 10.0.7.64 + A 10.0.7.65 + A 10.0.7.66 + A 10.0.7.67 + A 10.0.7.68 + A 10.0.7.69 + A 10.0.7.70 + A 10.0.7.71 + A 10.0.7.72 + A 10.0.7.73 + A 10.0.7.74 + A 10.0.7.75 + A 10.0.7.76 + A 10.0.7.77 + A 10.0.7.78 + A 10.0.7.79 + A 10.0.7.80 + A 10.0.7.81 + A 10.0.7.82 + A 10.0.7.83 + A 10.0.7.84 + A 10.0.7.85 + A 10.0.7.86 + A 10.0.7.87 + A 10.0.7.88 + A 10.0.7.89 + A 10.0.7.90 + A 10.0.7.91 + A 10.0.7.92 + A 10.0.7.93 + A 10.0.7.94 + A 10.0.7.95 + A 10.0.7.96 + A 10.0.7.97 + A 10.0.7.98 + A 10.0.7.99 + A 10.0.7.100 + A 10.0.7.101 + A 10.0.7.102 + A 10.0.7.103 + A 10.0.7.104 + A 10.0.7.105 + A 10.0.7.106 + A 10.0.7.107 + A 10.0.7.108 + A 10.0.7.109 + A 10.0.7.110 + A 10.0.7.111 + A 10.0.7.112 + A 10.0.7.113 + A 10.0.7.114 + A 10.0.7.115 + A 10.0.7.116 + A 10.0.7.117 + A 10.0.7.118 + A 10.0.7.119 + A 10.0.7.120 + A 10.0.7.121 + A 10.0.7.122 + A 10.0.7.123 + A 10.0.7.124 + A 10.0.7.125 + A 10.0.7.126 + A 10.0.7.127 + A 10.0.7.128 + A 10.0.7.129 + A 10.0.7.130 + A 10.0.7.131 + A 10.0.7.132 + A 10.0.7.133 + A 10.0.7.134 + A 10.0.7.135 + A 10.0.7.136 + A 10.0.7.137 + A 10.0.7.138 + A 10.0.7.139 + A 10.0.7.140 + A 10.0.7.141 + A 10.0.7.142 + A 10.0.7.143 + A 10.0.7.144 + A 10.0.7.145 + A 10.0.7.146 + A 10.0.7.147 + A 10.0.7.148 + A 10.0.7.149 + A 10.0.7.150 + A 10.0.7.151 + A 10.0.7.152 + A 10.0.7.153 + A 10.0.7.154 + A 10.0.7.155 + A 10.0.7.156 + A 10.0.7.157 + A 10.0.7.158 + A 10.0.7.159 + A 10.0.7.160 + A 10.0.7.161 + A 10.0.7.162 + A 10.0.7.163 + A 10.0.7.164 + A 10.0.7.165 + A 10.0.7.166 + A 10.0.7.167 + A 10.0.7.168 + A 10.0.7.169 + A 10.0.7.170 + A 10.0.7.171 + A 10.0.7.172 + A 10.0.7.173 + A 10.0.7.174 + A 10.0.7.175 + A 10.0.7.176 + A 10.0.7.177 + A 10.0.7.178 + A 10.0.7.179 + A 10.0.7.180 + A 10.0.7.181 + A 10.0.7.182 + A 10.0.7.183 + A 10.0.7.184 + A 10.0.7.185 + A 10.0.7.186 + A 10.0.7.187 + A 10.0.7.188 + A 10.0.7.189 + A 10.0.7.190 + A 10.0.7.191 + A 10.0.7.192 + A 10.0.7.193 + A 10.0.7.194 + A 10.0.7.195 + A 10.0.7.196 + A 10.0.7.197 + A 10.0.7.198 + A 10.0.7.199 + A 10.0.7.200 + A 10.0.7.201 + A 10.0.7.202 + A 10.0.7.203 + A 10.0.7.204 + A 10.0.7.205 + A 10.0.7.206 + A 10.0.7.207 + A 10.0.7.208 + A 10.0.7.209 + A 10.0.7.210 + A 10.0.7.211 + A 10.0.7.212 + A 10.0.7.213 + A 10.0.7.214 + A 10.0.7.215 + A 10.0.7.216 + A 10.0.7.217 + A 10.0.7.218 + A 10.0.7.219 + A 10.0.7.220 + A 10.0.7.221 + A 10.0.7.222 + A 10.0.7.223 + A 10.0.7.224 + A 10.0.7.225 + A 10.0.7.226 + A 10.0.7.227 + A 10.0.7.228 + A 10.0.7.229 + A 10.0.7.230 + A 10.0.7.231 + A 10.0.7.232 + A 10.0.7.233 + A 10.0.7.234 + A 10.0.7.235 + A 10.0.7.236 + A 10.0.7.237 + A 10.0.7.238 + A 10.0.7.239 + A 10.0.7.240 + A 10.0.7.241 + A 10.0.7.242 + A 10.0.7.243 + A 10.0.7.244 + A 10.0.7.245 + A 10.0.7.246 + A 10.0.7.247 + A 10.0.7.248 + A 10.0.7.249 + A 10.0.7.250 + A 10.0.7.251 + A 10.0.7.252 + A 10.0.7.253 + A 10.0.7.254 + A 10.0.7.255 + A 10.0.8.0 + A 10.0.8.1 + A 10.0.8.2 + A 10.0.8.3 + A 10.0.8.4 + A 10.0.8.5 + A 10.0.8.6 + A 10.0.8.7 + A 10.0.8.8 + A 10.0.8.9 + A 10.0.8.10 + A 10.0.8.11 + A 10.0.8.12 + A 10.0.8.13 + A 10.0.8.14 + A 10.0.8.15 + A 10.0.8.16 + A 10.0.8.17 + A 10.0.8.18 + A 10.0.8.19 + A 10.0.8.20 + A 10.0.8.21 + A 10.0.8.22 + A 10.0.8.23 + A 10.0.8.24 + A 10.0.8.25 + A 10.0.8.26 + A 10.0.8.27 + A 10.0.8.28 + A 10.0.8.29 + A 10.0.8.30 + A 10.0.8.31 + A 10.0.8.32 + A 10.0.8.33 + A 10.0.8.34 + A 10.0.8.35 + A 10.0.8.36 + A 10.0.8.37 + A 10.0.8.38 + A 10.0.8.39 + A 10.0.8.40 + A 10.0.8.41 + A 10.0.8.42 + A 10.0.8.43 + A 10.0.8.44 + A 10.0.8.45 + A 10.0.8.46 + A 10.0.8.47 + A 10.0.8.48 + A 10.0.8.49 + A 10.0.8.50 + A 10.0.8.51 + A 10.0.8.52 + A 10.0.8.53 + A 10.0.8.54 + A 10.0.8.55 + A 10.0.8.56 + A 10.0.8.57 + A 10.0.8.58 + A 10.0.8.59 + A 10.0.8.60 + A 10.0.8.61 + A 10.0.8.62 + A 10.0.8.63 + A 10.0.8.64 + A 10.0.8.65 + A 10.0.8.66 + A 10.0.8.67 + A 10.0.8.68 + A 10.0.8.69 + A 10.0.8.70 + A 10.0.8.71 + A 10.0.8.72 + A 10.0.8.73 + A 10.0.8.74 + A 10.0.8.75 + A 10.0.8.76 + A 10.0.8.77 + A 10.0.8.78 + A 10.0.8.79 + A 10.0.8.80 + A 10.0.8.81 + A 10.0.8.82 + A 10.0.8.83 + A 10.0.8.84 + A 10.0.8.85 + A 10.0.8.86 + A 10.0.8.87 + A 10.0.8.88 + A 10.0.8.89 + A 10.0.8.90 + A 10.0.8.91 + A 10.0.8.92 + A 10.0.8.93 + A 10.0.8.94 + A 10.0.8.95 + A 10.0.8.96 + A 10.0.8.97 + A 10.0.8.98 + A 10.0.8.99 + A 10.0.8.100 + A 10.0.8.101 + A 10.0.8.102 + A 10.0.8.103 + A 10.0.8.104 + A 10.0.8.105 + A 10.0.8.106 + A 10.0.8.107 + A 10.0.8.108 + A 10.0.8.109 + A 10.0.8.110 + A 10.0.8.111 + A 10.0.8.112 + A 10.0.8.113 + A 10.0.8.114 + A 10.0.8.115 + A 10.0.8.116 + A 10.0.8.117 + A 10.0.8.118 + A 10.0.8.119 + A 10.0.8.120 + A 10.0.8.121 + A 10.0.8.122 + A 10.0.8.123 + A 10.0.8.124 + A 10.0.8.125 + A 10.0.8.126 + A 10.0.8.127 + A 10.0.8.128 + A 10.0.8.129 + A 10.0.8.130 + A 10.0.8.131 + A 10.0.8.132 + A 10.0.8.133 + A 10.0.8.134 + A 10.0.8.135 + A 10.0.8.136 + A 10.0.8.137 + A 10.0.8.138 + A 10.0.8.139 + A 10.0.8.140 + A 10.0.8.141 + A 10.0.8.142 + A 10.0.8.143 + A 10.0.8.144 + A 10.0.8.145 + A 10.0.8.146 + A 10.0.8.147 + A 10.0.8.148 + A 10.0.8.149 + A 10.0.8.150 + A 10.0.8.151 + A 10.0.8.152 + A 10.0.8.153 + A 10.0.8.154 + A 10.0.8.155 + A 10.0.8.156 + A 10.0.8.157 + A 10.0.8.158 + A 10.0.8.159 + A 10.0.8.160 + A 10.0.8.161 + A 10.0.8.162 + A 10.0.8.163 + A 10.0.8.164 + A 10.0.8.165 + A 10.0.8.166 + A 10.0.8.167 + A 10.0.8.168 + A 10.0.8.169 + A 10.0.8.170 + A 10.0.8.171 + A 10.0.8.172 + A 10.0.8.173 + A 10.0.8.174 + A 10.0.8.175 + A 10.0.8.176 + A 10.0.8.177 + A 10.0.8.178 + A 10.0.8.179 + A 10.0.8.180 + A 10.0.8.181 + A 10.0.8.182 + A 10.0.8.183 + A 10.0.8.184 + A 10.0.8.185 + A 10.0.8.186 + A 10.0.8.187 + A 10.0.8.188 + A 10.0.8.189 + A 10.0.8.190 + A 10.0.8.191 + A 10.0.8.192 + A 10.0.8.193 + A 10.0.8.194 + A 10.0.8.195 + A 10.0.8.196 + A 10.0.8.197 + A 10.0.8.198 + A 10.0.8.199 + A 10.0.8.200 + A 10.0.8.201 + A 10.0.8.202 + A 10.0.8.203 + A 10.0.8.204 + A 10.0.8.205 + A 10.0.8.206 + A 10.0.8.207 + A 10.0.8.208 + A 10.0.8.209 + A 10.0.8.210 + A 10.0.8.211 + A 10.0.8.212 + A 10.0.8.213 + A 10.0.8.214 + A 10.0.8.215 + A 10.0.8.216 + A 10.0.8.217 + A 10.0.8.218 + A 10.0.8.219 + A 10.0.8.220 + A 10.0.8.221 + A 10.0.8.222 + A 10.0.8.223 + A 10.0.8.224 + A 10.0.8.225 + A 10.0.8.226 + A 10.0.8.227 + A 10.0.8.228 + A 10.0.8.229 + A 10.0.8.230 + A 10.0.8.231 + A 10.0.8.232 + A 10.0.8.233 + A 10.0.8.234 + A 10.0.8.235 + A 10.0.8.236 + A 10.0.8.237 + A 10.0.8.238 + A 10.0.8.239 + A 10.0.8.240 + A 10.0.8.241 + A 10.0.8.242 + A 10.0.8.243 + A 10.0.8.244 + A 10.0.8.245 + A 10.0.8.246 + A 10.0.8.247 + A 10.0.8.248 + A 10.0.8.249 + A 10.0.8.250 + A 10.0.8.251 + A 10.0.8.252 + A 10.0.8.253 + A 10.0.8.254 + A 10.0.8.255 + A 10.0.9.0 + A 10.0.9.1 + A 10.0.9.2 + A 10.0.9.3 + A 10.0.9.4 + A 10.0.9.5 + A 10.0.9.6 + A 10.0.9.7 + A 10.0.9.8 + A 10.0.9.9 + A 10.0.9.10 + A 10.0.9.11 + A 10.0.9.12 + A 10.0.9.13 + A 10.0.9.14 + A 10.0.9.15 + A 10.0.9.16 + A 10.0.9.17 + A 10.0.9.18 + A 10.0.9.19 + A 10.0.9.20 + A 10.0.9.21 + A 10.0.9.22 + A 10.0.9.23 + A 10.0.9.24 + A 10.0.9.25 + A 10.0.9.26 + A 10.0.9.27 + A 10.0.9.28 + A 10.0.9.29 + A 10.0.9.30 + A 10.0.9.31 + A 10.0.9.32 + A 10.0.9.33 + A 10.0.9.34 + A 10.0.9.35 + A 10.0.9.36 + A 10.0.9.37 + A 10.0.9.38 + A 10.0.9.39 + A 10.0.9.40 + A 10.0.9.41 + A 10.0.9.42 + A 10.0.9.43 + A 10.0.9.44 + A 10.0.9.45 + A 10.0.9.46 + A 10.0.9.47 + A 10.0.9.48 + A 10.0.9.49 + A 10.0.9.50 + A 10.0.9.51 + A 10.0.9.52 + A 10.0.9.53 + A 10.0.9.54 + A 10.0.9.55 + A 10.0.9.56 + A 10.0.9.57 + A 10.0.9.58 + A 10.0.9.59 + A 10.0.9.60 + A 10.0.9.61 + A 10.0.9.62 + A 10.0.9.63 + A 10.0.9.64 + A 10.0.9.65 + A 10.0.9.66 + A 10.0.9.67 + A 10.0.9.68 + A 10.0.9.69 + A 10.0.9.70 + A 10.0.9.71 + A 10.0.9.72 + A 10.0.9.73 + A 10.0.9.74 + A 10.0.9.75 + A 10.0.9.76 + A 10.0.9.77 + A 10.0.9.78 + A 10.0.9.79 + A 10.0.9.80 + A 10.0.9.81 + A 10.0.9.82 + A 10.0.9.83 + A 10.0.9.84 + A 10.0.9.85 + A 10.0.9.86 + A 10.0.9.87 + A 10.0.9.88 + A 10.0.9.89 + A 10.0.9.90 + A 10.0.9.91 + A 10.0.9.92 + A 10.0.9.93 + A 10.0.9.94 + A 10.0.9.95 + A 10.0.9.96 + A 10.0.9.97 + A 10.0.9.98 + A 10.0.9.99 + A 10.0.9.100 + A 10.0.9.101 + A 10.0.9.102 + A 10.0.9.103 + A 10.0.9.104 + A 10.0.9.105 + A 10.0.9.106 + A 10.0.9.107 + A 10.0.9.108 + A 10.0.9.109 + A 10.0.9.110 + A 10.0.9.111 + A 10.0.9.112 + A 10.0.9.113 + A 10.0.9.114 + A 10.0.9.115 + A 10.0.9.116 + A 10.0.9.117 + A 10.0.9.118 + A 10.0.9.119 + A 10.0.9.120 + A 10.0.9.121 + A 10.0.9.122 + A 10.0.9.123 + A 10.0.9.124 + A 10.0.9.125 + A 10.0.9.126 + A 10.0.9.127 + A 10.0.9.128 + A 10.0.9.129 + A 10.0.9.130 + A 10.0.9.131 + A 10.0.9.132 + A 10.0.9.133 + A 10.0.9.134 + A 10.0.9.135 + A 10.0.9.136 + A 10.0.9.137 + A 10.0.9.138 + A 10.0.9.139 + A 10.0.9.140 + A 10.0.9.141 + A 10.0.9.142 + A 10.0.9.143 + A 10.0.9.144 + A 10.0.9.145 + A 10.0.9.146 + A 10.0.9.147 + A 10.0.9.148 + A 10.0.9.149 + A 10.0.9.150 + A 10.0.9.151 + A 10.0.9.152 + A 10.0.9.153 + A 10.0.9.154 + A 10.0.9.155 + A 10.0.9.156 + A 10.0.9.157 + A 10.0.9.158 + A 10.0.9.159 + A 10.0.9.160 + A 10.0.9.161 + A 10.0.9.162 + A 10.0.9.163 + A 10.0.9.164 + A 10.0.9.165 + A 10.0.9.166 + A 10.0.9.167 + A 10.0.9.168 + A 10.0.9.169 + A 10.0.9.170 + A 10.0.9.171 + A 10.0.9.172 + A 10.0.9.173 + A 10.0.9.174 + A 10.0.9.175 + A 10.0.9.176 + A 10.0.9.177 + A 10.0.9.178 + A 10.0.9.179 + A 10.0.9.180 + A 10.0.9.181 + A 10.0.9.182 + A 10.0.9.183 + A 10.0.9.184 + A 10.0.9.185 + A 10.0.9.186 + A 10.0.9.187 + A 10.0.9.188 + A 10.0.9.189 + A 10.0.9.190 + A 10.0.9.191 + A 10.0.9.192 + A 10.0.9.193 + A 10.0.9.194 + A 10.0.9.195 + A 10.0.9.196 + A 10.0.9.197 + A 10.0.9.198 + A 10.0.9.199 + A 10.0.9.200 + A 10.0.9.201 + A 10.0.9.202 + A 10.0.9.203 + A 10.0.9.204 + A 10.0.9.205 + A 10.0.9.206 + A 10.0.9.207 + A 10.0.9.208 + A 10.0.9.209 + A 10.0.9.210 + A 10.0.9.211 + A 10.0.9.212 + A 10.0.9.213 + A 10.0.9.214 + A 10.0.9.215 + A 10.0.9.216 + A 10.0.9.217 + A 10.0.9.218 + A 10.0.9.219 + A 10.0.9.220 + A 10.0.9.221 + A 10.0.9.222 + A 10.0.9.223 + A 10.0.9.224 + A 10.0.9.225 + A 10.0.9.226 + A 10.0.9.227 + A 10.0.9.228 + A 10.0.9.229 + A 10.0.9.230 + A 10.0.9.231 + A 10.0.9.232 + A 10.0.9.233 + A 10.0.9.234 + A 10.0.9.235 + A 10.0.9.236 + A 10.0.9.237 + A 10.0.9.238 + A 10.0.9.239 + A 10.0.9.240 + A 10.0.9.241 + A 10.0.9.242 + A 10.0.9.243 + A 10.0.9.244 + A 10.0.9.245 + A 10.0.9.246 + A 10.0.9.247 + A 10.0.9.248 + A 10.0.9.249 + A 10.0.9.250 + A 10.0.9.251 + A 10.0.9.252 + A 10.0.9.253 + A 10.0.9.254 + A 10.0.9.255 + A 10.0.10.0 + A 10.0.10.1 + A 10.0.10.2 + A 10.0.10.3 + A 10.0.10.4 + A 10.0.10.5 + A 10.0.10.6 + A 10.0.10.7 + A 10.0.10.8 + A 10.0.10.9 + A 10.0.10.10 + A 10.0.10.11 + A 10.0.10.12 + A 10.0.10.13 + A 10.0.10.14 + A 10.0.10.15 + A 10.0.10.16 + A 10.0.10.17 + A 10.0.10.18 + A 10.0.10.19 + A 10.0.10.20 + A 10.0.10.21 + A 10.0.10.22 + A 10.0.10.23 + A 10.0.10.24 + A 10.0.10.25 + A 10.0.10.26 + A 10.0.10.27 + A 10.0.10.28 + A 10.0.10.29 + A 10.0.10.30 + A 10.0.10.31 + A 10.0.10.32 + A 10.0.10.33 + A 10.0.10.34 + A 10.0.10.35 + A 10.0.10.36 + A 10.0.10.37 + A 10.0.10.38 + A 10.0.10.39 + A 10.0.10.40 + A 10.0.10.41 + A 10.0.10.42 + A 10.0.10.43 + A 10.0.10.44 + A 10.0.10.45 + A 10.0.10.46 + A 10.0.10.47 + A 10.0.10.48 + A 10.0.10.49 + A 10.0.10.50 + A 10.0.10.51 + A 10.0.10.52 + A 10.0.10.53 + A 10.0.10.54 + A 10.0.10.55 + A 10.0.10.56 + A 10.0.10.57 + A 10.0.10.58 + A 10.0.10.59 + A 10.0.10.60 + A 10.0.10.61 + A 10.0.10.62 + A 10.0.10.63 + A 10.0.10.64 + A 10.0.10.65 + A 10.0.10.66 + A 10.0.10.67 + A 10.0.10.68 + A 10.0.10.69 + A 10.0.10.70 + A 10.0.10.71 + A 10.0.10.72 + A 10.0.10.73 + A 10.0.10.74 + A 10.0.10.75 + A 10.0.10.76 + A 10.0.10.77 + A 10.0.10.78 + A 10.0.10.79 + A 10.0.10.80 + A 10.0.10.81 + A 10.0.10.82 + A 10.0.10.83 + A 10.0.10.84 + A 10.0.10.85 + A 10.0.10.86 + A 10.0.10.87 + A 10.0.10.88 + A 10.0.10.89 + A 10.0.10.90 + A 10.0.10.91 + A 10.0.10.92 + A 10.0.10.93 + A 10.0.10.94 + A 10.0.10.95 + A 10.0.10.96 + A 10.0.10.97 + A 10.0.10.98 + A 10.0.10.99 + A 10.0.10.100 + A 10.0.10.101 + A 10.0.10.102 + A 10.0.10.103 + A 10.0.10.104 + A 10.0.10.105 + A 10.0.10.106 + A 10.0.10.107 + A 10.0.10.108 + A 10.0.10.109 + A 10.0.10.110 + A 10.0.10.111 + A 10.0.10.112 + A 10.0.10.113 + A 10.0.10.114 + A 10.0.10.115 + A 10.0.10.116 + A 10.0.10.117 + A 10.0.10.118 + A 10.0.10.119 + A 10.0.10.120 + A 10.0.10.121 + A 10.0.10.122 + A 10.0.10.123 + A 10.0.10.124 + A 10.0.10.125 + A 10.0.10.126 + A 10.0.10.127 + A 10.0.10.128 + A 10.0.10.129 + A 10.0.10.130 + A 10.0.10.131 + A 10.0.10.132 + A 10.0.10.133 + A 10.0.10.134 + A 10.0.10.135 + A 10.0.10.136 + A 10.0.10.137 + A 10.0.10.138 + A 10.0.10.139 + A 10.0.10.140 + A 10.0.10.141 + A 10.0.10.142 + A 10.0.10.143 + A 10.0.10.144 + A 10.0.10.145 + A 10.0.10.146 + A 10.0.10.147 + A 10.0.10.148 + A 10.0.10.149 + A 10.0.10.150 + A 10.0.10.151 + A 10.0.10.152 + A 10.0.10.153 + A 10.0.10.154 + A 10.0.10.155 + A 10.0.10.156 + A 10.0.10.157 + A 10.0.10.158 + A 10.0.10.159 + A 10.0.10.160 + A 10.0.10.161 + A 10.0.10.162 + A 10.0.10.163 + A 10.0.10.164 + A 10.0.10.165 + A 10.0.10.166 + A 10.0.10.167 + A 10.0.10.168 + A 10.0.10.169 + A 10.0.10.170 + A 10.0.10.171 + A 10.0.10.172 + A 10.0.10.173 + A 10.0.10.174 + A 10.0.10.175 + A 10.0.10.176 + A 10.0.10.177 + A 10.0.10.178 + A 10.0.10.179 + A 10.0.10.180 + A 10.0.10.181 + A 10.0.10.182 + A 10.0.10.183 + A 10.0.10.184 + A 10.0.10.185 + A 10.0.10.186 + A 10.0.10.187 + A 10.0.10.188 + A 10.0.10.189 + A 10.0.10.190 + A 10.0.10.191 + A 10.0.10.192 + A 10.0.10.193 + A 10.0.10.194 + A 10.0.10.195 + A 10.0.10.196 + A 10.0.10.197 + A 10.0.10.198 + A 10.0.10.199 + A 10.0.10.200 + A 10.0.10.201 + A 10.0.10.202 + A 10.0.10.203 + A 10.0.10.204 + A 10.0.10.205 + A 10.0.10.206 + A 10.0.10.207 + A 10.0.10.208 + A 10.0.10.209 + A 10.0.10.210 + A 10.0.10.211 + A 10.0.10.212 + A 10.0.10.213 + A 10.0.10.214 + A 10.0.10.215 + A 10.0.10.216 + A 10.0.10.217 + A 10.0.10.218 + A 10.0.10.219 + A 10.0.10.220 + A 10.0.10.221 + A 10.0.10.222 + A 10.0.10.223 + A 10.0.10.224 + A 10.0.10.225 + A 10.0.10.226 + A 10.0.10.227 + A 10.0.10.228 + A 10.0.10.229 + A 10.0.10.230 + A 10.0.10.231 + A 10.0.10.232 + A 10.0.10.233 + A 10.0.10.234 + A 10.0.10.235 + A 10.0.10.236 + A 10.0.10.237 + A 10.0.10.238 + A 10.0.10.239 + A 10.0.10.240 + A 10.0.10.241 + A 10.0.10.242 + A 10.0.10.243 + A 10.0.10.244 + A 10.0.10.245 + A 10.0.10.246 + A 10.0.10.247 + A 10.0.10.248 + A 10.0.10.249 + A 10.0.10.250 + A 10.0.10.251 + A 10.0.10.252 + A 10.0.10.253 + A 10.0.10.254 + A 10.0.10.255 + A 10.0.11.0 + A 10.0.11.1 + A 10.0.11.2 + A 10.0.11.3 + A 10.0.11.4 + A 10.0.11.5 + A 10.0.11.6 + A 10.0.11.7 + A 10.0.11.8 + A 10.0.11.9 + A 10.0.11.10 + A 10.0.11.11 + A 10.0.11.12 + A 10.0.11.13 + A 10.0.11.14 + A 10.0.11.15 + A 10.0.11.16 + A 10.0.11.17 + A 10.0.11.18 + A 10.0.11.19 + A 10.0.11.20 + A 10.0.11.21 + A 10.0.11.22 + A 10.0.11.23 + A 10.0.11.24 + A 10.0.11.25 + A 10.0.11.26 + A 10.0.11.27 + A 10.0.11.28 + A 10.0.11.29 + A 10.0.11.30 + A 10.0.11.31 + A 10.0.11.32 + A 10.0.11.33 + A 10.0.11.34 + A 10.0.11.35 + A 10.0.11.36 + A 10.0.11.37 + A 10.0.11.38 + A 10.0.11.39 + A 10.0.11.40 + A 10.0.11.41 + A 10.0.11.42 + A 10.0.11.43 + A 10.0.11.44 + A 10.0.11.45 + A 10.0.11.46 + A 10.0.11.47 + A 10.0.11.48 + A 10.0.11.49 + A 10.0.11.50 + A 10.0.11.51 + A 10.0.11.52 + A 10.0.11.53 + A 10.0.11.54 + A 10.0.11.55 + A 10.0.11.56 + A 10.0.11.57 + A 10.0.11.58 + A 10.0.11.59 + A 10.0.11.60 + A 10.0.11.61 + A 10.0.11.62 + A 10.0.11.63 + A 10.0.11.64 + A 10.0.11.65 + A 10.0.11.66 + A 10.0.11.67 + A 10.0.11.68 + A 10.0.11.69 + A 10.0.11.70 + A 10.0.11.71 + A 10.0.11.72 + A 10.0.11.73 + A 10.0.11.74 + A 10.0.11.75 + A 10.0.11.76 + A 10.0.11.77 + A 10.0.11.78 + A 10.0.11.79 + A 10.0.11.80 + A 10.0.11.81 + A 10.0.11.82 + A 10.0.11.83 + A 10.0.11.84 + A 10.0.11.85 + A 10.0.11.86 + A 10.0.11.87 + A 10.0.11.88 + A 10.0.11.89 + A 10.0.11.90 + A 10.0.11.91 + A 10.0.11.92 + A 10.0.11.93 + A 10.0.11.94 + A 10.0.11.95 + A 10.0.11.96 + A 10.0.11.97 + A 10.0.11.98 + A 10.0.11.99 + A 10.0.11.100 + A 10.0.11.101 + A 10.0.11.102 + A 10.0.11.103 + A 10.0.11.104 + A 10.0.11.105 + A 10.0.11.106 + A 10.0.11.107 + A 10.0.11.108 + A 10.0.11.109 + A 10.0.11.110 + A 10.0.11.111 + A 10.0.11.112 + A 10.0.11.113 + A 10.0.11.114 + A 10.0.11.115 + A 10.0.11.116 + A 10.0.11.117 + A 10.0.11.118 + A 10.0.11.119 + A 10.0.11.120 + A 10.0.11.121 + A 10.0.11.122 + A 10.0.11.123 + A 10.0.11.124 + A 10.0.11.125 + A 10.0.11.126 + A 10.0.11.127 + A 10.0.11.128 + A 10.0.11.129 + A 10.0.11.130 + A 10.0.11.131 + A 10.0.11.132 + A 10.0.11.133 + A 10.0.11.134 + A 10.0.11.135 + A 10.0.11.136 + A 10.0.11.137 + A 10.0.11.138 + A 10.0.11.139 + A 10.0.11.140 + A 10.0.11.141 + A 10.0.11.142 + A 10.0.11.143 + A 10.0.11.144 + A 10.0.11.145 + A 10.0.11.146 + A 10.0.11.147 + A 10.0.11.148 + A 10.0.11.149 + A 10.0.11.150 + A 10.0.11.151 + A 10.0.11.152 + A 10.0.11.153 + A 10.0.11.154 + A 10.0.11.155 + A 10.0.11.156 + A 10.0.11.157 + A 10.0.11.158 + A 10.0.11.159 + A 10.0.11.160 + A 10.0.11.161 + A 10.0.11.162 + A 10.0.11.163 + A 10.0.11.164 + A 10.0.11.165 + A 10.0.11.166 + A 10.0.11.167 + A 10.0.11.168 + A 10.0.11.169 + A 10.0.11.170 + A 10.0.11.171 + A 10.0.11.172 + A 10.0.11.173 + A 10.0.11.174 + A 10.0.11.175 + A 10.0.11.176 + A 10.0.11.177 + A 10.0.11.178 + A 10.0.11.179 + A 10.0.11.180 + A 10.0.11.181 + A 10.0.11.182 + A 10.0.11.183 + A 10.0.11.184 + A 10.0.11.185 + A 10.0.11.186 + A 10.0.11.187 + A 10.0.11.188 + A 10.0.11.189 + A 10.0.11.190 + A 10.0.11.191 + A 10.0.11.192 + A 10.0.11.193 + A 10.0.11.194 + A 10.0.11.195 + A 10.0.11.196 + A 10.0.11.197 + A 10.0.11.198 + A 10.0.11.199 + A 10.0.11.200 + A 10.0.11.201 + A 10.0.11.202 + A 10.0.11.203 + A 10.0.11.204 + A 10.0.11.205 + A 10.0.11.206 + A 10.0.11.207 + A 10.0.11.208 + A 10.0.11.209 + A 10.0.11.210 + A 10.0.11.211 + A 10.0.11.212 + A 10.0.11.213 + A 10.0.11.214 + A 10.0.11.215 + A 10.0.11.216 + A 10.0.11.217 + A 10.0.11.218 + A 10.0.11.219 + A 10.0.11.220 + A 10.0.11.221 + A 10.0.11.222 + A 10.0.11.223 + A 10.0.11.224 + A 10.0.11.225 + A 10.0.11.226 + A 10.0.11.227 + A 10.0.11.228 + A 10.0.11.229 + A 10.0.11.230 + A 10.0.11.231 + A 10.0.11.232 + A 10.0.11.233 + A 10.0.11.234 + A 10.0.11.235 + A 10.0.11.236 + A 10.0.11.237 + A 10.0.11.238 + A 10.0.11.239 + A 10.0.11.240 + A 10.0.11.241 + A 10.0.11.242 + A 10.0.11.243 + A 10.0.11.244 + A 10.0.11.245 + A 10.0.11.246 + A 10.0.11.247 + A 10.0.11.248 + A 10.0.11.249 + A 10.0.11.250 + A 10.0.11.251 + A 10.0.11.252 + A 10.0.11.253 + A 10.0.11.254 + A 10.0.11.255 + A 10.0.12.0 + A 10.0.12.1 + A 10.0.12.2 + A 10.0.12.3 + A 10.0.12.4 + A 10.0.12.5 + A 10.0.12.6 + A 10.0.12.7 + A 10.0.12.8 + A 10.0.12.9 + A 10.0.12.10 + A 10.0.12.11 + A 10.0.12.12 + A 10.0.12.13 + A 10.0.12.14 + A 10.0.12.15 + A 10.0.12.16 + A 10.0.12.17 + A 10.0.12.18 + A 10.0.12.19 + A 10.0.12.20 + A 10.0.12.21 + A 10.0.12.22 + A 10.0.12.23 + A 10.0.12.24 + A 10.0.12.25 + A 10.0.12.26 + A 10.0.12.27 + A 10.0.12.28 + A 10.0.12.29 + A 10.0.12.30 + A 10.0.12.31 + A 10.0.12.32 + A 10.0.12.33 + A 10.0.12.34 + A 10.0.12.35 + A 10.0.12.36 + A 10.0.12.37 + A 10.0.12.38 + A 10.0.12.39 + A 10.0.12.40 + A 10.0.12.41 + A 10.0.12.42 + A 10.0.12.43 + A 10.0.12.44 + A 10.0.12.45 + A 10.0.12.46 + A 10.0.12.47 + A 10.0.12.48 + A 10.0.12.49 + A 10.0.12.50 + A 10.0.12.51 + A 10.0.12.52 + A 10.0.12.53 + A 10.0.12.54 + A 10.0.12.55 + A 10.0.12.56 + A 10.0.12.57 + A 10.0.12.58 + A 10.0.12.59 + A 10.0.12.60 + A 10.0.12.61 + A 10.0.12.62 + A 10.0.12.63 + A 10.0.12.64 + A 10.0.12.65 + A 10.0.12.66 + A 10.0.12.67 + A 10.0.12.68 + A 10.0.12.69 + A 10.0.12.70 + A 10.0.12.71 + A 10.0.12.72 + A 10.0.12.73 + A 10.0.12.74 + A 10.0.12.75 + A 10.0.12.76 + A 10.0.12.77 + A 10.0.12.78 + A 10.0.12.79 + A 10.0.12.80 + A 10.0.12.81 + A 10.0.12.82 + A 10.0.12.83 + A 10.0.12.84 + A 10.0.12.85 + A 10.0.12.86 + A 10.0.12.87 + A 10.0.12.88 + A 10.0.12.89 + A 10.0.12.90 + A 10.0.12.91 + A 10.0.12.92 + A 10.0.12.93 + A 10.0.12.94 + A 10.0.12.95 + A 10.0.12.96 + A 10.0.12.97 + A 10.0.12.98 + A 10.0.12.99 + A 10.0.12.100 + A 10.0.12.101 + A 10.0.12.102 + A 10.0.12.103 + A 10.0.12.104 + A 10.0.12.105 + A 10.0.12.106 + A 10.0.12.107 + A 10.0.12.108 + A 10.0.12.109 + A 10.0.12.110 + A 10.0.12.111 + A 10.0.12.112 + A 10.0.12.113 + A 10.0.12.114 + A 10.0.12.115 + A 10.0.12.116 + A 10.0.12.117 + A 10.0.12.118 + A 10.0.12.119 + A 10.0.12.120 + A 10.0.12.121 + A 10.0.12.122 + A 10.0.12.123 + A 10.0.12.124 + A 10.0.12.125 + A 10.0.12.126 + A 10.0.12.127 + A 10.0.12.128 + A 10.0.12.129 + A 10.0.12.130 + A 10.0.12.131 + A 10.0.12.132 + A 10.0.12.133 + A 10.0.12.134 + A 10.0.12.135 + A 10.0.12.136 + A 10.0.12.137 + A 10.0.12.138 + A 10.0.12.139 + A 10.0.12.140 + A 10.0.12.141 + A 10.0.12.142 + A 10.0.12.143 + A 10.0.12.144 + A 10.0.12.145 + A 10.0.12.146 + A 10.0.12.147 + A 10.0.12.148 + A 10.0.12.149 + A 10.0.12.150 + A 10.0.12.151 + A 10.0.12.152 + A 10.0.12.153 + A 10.0.12.154 + A 10.0.12.155 + A 10.0.12.156 + A 10.0.12.157 + A 10.0.12.158 + A 10.0.12.159 + A 10.0.12.160 + A 10.0.12.161 + A 10.0.12.162 + A 10.0.12.163 + A 10.0.12.164 + A 10.0.12.165 + A 10.0.12.166 + A 10.0.12.167 + A 10.0.12.168 + A 10.0.12.169 + A 10.0.12.170 + A 10.0.12.171 + A 10.0.12.172 + A 10.0.12.173 + A 10.0.12.174 + A 10.0.12.175 + A 10.0.12.176 + A 10.0.12.177 + A 10.0.12.178 + A 10.0.12.179 + A 10.0.12.180 + A 10.0.12.181 + A 10.0.12.182 + A 10.0.12.183 + A 10.0.12.184 + A 10.0.12.185 + A 10.0.12.186 + A 10.0.12.187 + A 10.0.12.188 + A 10.0.12.189 + A 10.0.12.190 + A 10.0.12.191 + A 10.0.12.192 + A 10.0.12.193 + A 10.0.12.194 + A 10.0.12.195 + A 10.0.12.196 + A 10.0.12.197 + A 10.0.12.198 + A 10.0.12.199 + A 10.0.12.200 + A 10.0.12.201 + A 10.0.12.202 + A 10.0.12.203 + A 10.0.12.204 + A 10.0.12.205 + A 10.0.12.206 + A 10.0.12.207 + A 10.0.12.208 + A 10.0.12.209 + A 10.0.12.210 + A 10.0.12.211 + A 10.0.12.212 + A 10.0.12.213 + A 10.0.12.214 + A 10.0.12.215 + A 10.0.12.216 + A 10.0.12.217 + A 10.0.12.218 + A 10.0.12.219 + A 10.0.12.220 + A 10.0.12.221 + A 10.0.12.222 + A 10.0.12.223 + A 10.0.12.224 + A 10.0.12.225 + A 10.0.12.226 + A 10.0.12.227 + A 10.0.12.228 + A 10.0.12.229 + A 10.0.12.230 + A 10.0.12.231 + A 10.0.12.232 + A 10.0.12.233 + A 10.0.12.234 + A 10.0.12.235 + A 10.0.12.236 + A 10.0.12.237 + A 10.0.12.238 + A 10.0.12.239 + A 10.0.12.240 + A 10.0.12.241 + A 10.0.12.242 + A 10.0.12.243 + A 10.0.12.244 + A 10.0.12.245 + A 10.0.12.246 + A 10.0.12.247 + A 10.0.12.248 + A 10.0.12.249 + A 10.0.12.250 + A 10.0.12.251 + A 10.0.12.252 + A 10.0.12.253 + A 10.0.12.254 + A 10.0.12.255 + A 10.0.13.0 + A 10.0.13.1 + A 10.0.13.2 + A 10.0.13.3 + A 10.0.13.4 + A 10.0.13.5 + A 10.0.13.6 + A 10.0.13.7 + A 10.0.13.8 + A 10.0.13.9 + A 10.0.13.10 + A 10.0.13.11 + A 10.0.13.12 + A 10.0.13.13 + A 10.0.13.14 + A 10.0.13.15 + A 10.0.13.16 + A 10.0.13.17 + A 10.0.13.18 + A 10.0.13.19 + A 10.0.13.20 + A 10.0.13.21 + A 10.0.13.22 + A 10.0.13.23 + A 10.0.13.24 + A 10.0.13.25 + A 10.0.13.26 + A 10.0.13.27 + A 10.0.13.28 + A 10.0.13.29 + A 10.0.13.30 + A 10.0.13.31 + A 10.0.13.32 + A 10.0.13.33 + A 10.0.13.34 + A 10.0.13.35 + A 10.0.13.36 + A 10.0.13.37 + A 10.0.13.38 + A 10.0.13.39 + A 10.0.13.40 + A 10.0.13.41 + A 10.0.13.42 + A 10.0.13.43 + A 10.0.13.44 + A 10.0.13.45 + A 10.0.13.46 + A 10.0.13.47 + A 10.0.13.48 + A 10.0.13.49 + A 10.0.13.50 + A 10.0.13.51 + A 10.0.13.52 + A 10.0.13.53 + A 10.0.13.54 + A 10.0.13.55 + A 10.0.13.56 + A 10.0.13.57 + A 10.0.13.58 + A 10.0.13.59 + A 10.0.13.60 + A 10.0.13.61 + A 10.0.13.62 + A 10.0.13.63 + A 10.0.13.64 + A 10.0.13.65 + A 10.0.13.66 + A 10.0.13.67 + A 10.0.13.68 + A 10.0.13.69 + A 10.0.13.70 + A 10.0.13.71 + A 10.0.13.72 + A 10.0.13.73 + A 10.0.13.74 + A 10.0.13.75 + A 10.0.13.76 + A 10.0.13.77 + A 10.0.13.78 + A 10.0.13.79 + A 10.0.13.80 + A 10.0.13.81 + A 10.0.13.82 + A 10.0.13.83 + A 10.0.13.84 + A 10.0.13.85 + A 10.0.13.86 + A 10.0.13.87 + A 10.0.13.88 + A 10.0.13.89 + A 10.0.13.90 + A 10.0.13.91 + A 10.0.13.92 + A 10.0.13.93 + A 10.0.13.94 + A 10.0.13.95 + A 10.0.13.96 + A 10.0.13.97 + A 10.0.13.98 + A 10.0.13.99 + A 10.0.13.100 + A 10.0.13.101 + A 10.0.13.102 + A 10.0.13.103 + A 10.0.13.104 + A 10.0.13.105 + A 10.0.13.106 + A 10.0.13.107 + A 10.0.13.108 + A 10.0.13.109 + A 10.0.13.110 + A 10.0.13.111 + A 10.0.13.112 + A 10.0.13.113 + A 10.0.13.114 + A 10.0.13.115 + A 10.0.13.116 + A 10.0.13.117 + A 10.0.13.118 + A 10.0.13.119 + A 10.0.13.120 + A 10.0.13.121 + A 10.0.13.122 + A 10.0.13.123 + A 10.0.13.124 + A 10.0.13.125 + A 10.0.13.126 + A 10.0.13.127 + A 10.0.13.128 + A 10.0.13.129 + A 10.0.13.130 + A 10.0.13.131 + A 10.0.13.132 + A 10.0.13.133 + A 10.0.13.134 + A 10.0.13.135 + A 10.0.13.136 + A 10.0.13.137 + A 10.0.13.138 + A 10.0.13.139 + A 10.0.13.140 + A 10.0.13.141 + A 10.0.13.142 + A 10.0.13.143 + A 10.0.13.144 + A 10.0.13.145 + A 10.0.13.146 + A 10.0.13.147 + A 10.0.13.148 + A 10.0.13.149 + A 10.0.13.150 + A 10.0.13.151 + A 10.0.13.152 + A 10.0.13.153 + A 10.0.13.154 + A 10.0.13.155 + A 10.0.13.156 + A 10.0.13.157 + A 10.0.13.158 + A 10.0.13.159 + A 10.0.13.160 + A 10.0.13.161 + A 10.0.13.162 + A 10.0.13.163 + A 10.0.13.164 + A 10.0.13.165 + A 10.0.13.166 + A 10.0.13.167 + A 10.0.13.168 + A 10.0.13.169 + A 10.0.13.170 + A 10.0.13.171 + A 10.0.13.172 + A 10.0.13.173 + A 10.0.13.174 + A 10.0.13.175 + A 10.0.13.176 + A 10.0.13.177 + A 10.0.13.178 + A 10.0.13.179 + A 10.0.13.180 + A 10.0.13.181 + A 10.0.13.182 + A 10.0.13.183 + A 10.0.13.184 + A 10.0.13.185 + A 10.0.13.186 + A 10.0.13.187 + A 10.0.13.188 + A 10.0.13.189 + A 10.0.13.190 + A 10.0.13.191 + A 10.0.13.192 + A 10.0.13.193 + A 10.0.13.194 + A 10.0.13.195 + A 10.0.13.196 + A 10.0.13.197 + A 10.0.13.198 + A 10.0.13.199 + A 10.0.13.200 + A 10.0.13.201 + A 10.0.13.202 + A 10.0.13.203 + A 10.0.13.204 + A 10.0.13.205 + A 10.0.13.206 + A 10.0.13.207 + A 10.0.13.208 + A 10.0.13.209 + A 10.0.13.210 + A 10.0.13.211 + A 10.0.13.212 + A 10.0.13.213 + A 10.0.13.214 + A 10.0.13.215 + A 10.0.13.216 + A 10.0.13.217 + A 10.0.13.218 + A 10.0.13.219 + A 10.0.13.220 + A 10.0.13.221 + A 10.0.13.222 + A 10.0.13.223 + A 10.0.13.224 + A 10.0.13.225 + A 10.0.13.226 + A 10.0.13.227 + A 10.0.13.228 + A 10.0.13.229 + A 10.0.13.230 + A 10.0.13.231 + A 10.0.13.232 + A 10.0.13.233 + A 10.0.13.234 + A 10.0.13.235 + A 10.0.13.236 + A 10.0.13.237 + A 10.0.13.238 + A 10.0.13.239 + A 10.0.13.240 + A 10.0.13.241 + A 10.0.13.242 + A 10.0.13.243 + A 10.0.13.244 + A 10.0.13.245 + A 10.0.13.246 + A 10.0.13.247 + A 10.0.13.248 + A 10.0.13.249 + A 10.0.13.250 + A 10.0.13.251 + A 10.0.13.252 + A 10.0.13.253 + A 10.0.13.254 + A 10.0.13.255 + A 10.0.14.0 + A 10.0.14.1 + A 10.0.14.2 + A 10.0.14.3 + A 10.0.14.4 + A 10.0.14.5 + A 10.0.14.6 + A 10.0.14.7 + A 10.0.14.8 + A 10.0.14.9 + A 10.0.14.10 + A 10.0.14.11 + A 10.0.14.12 + A 10.0.14.13 + A 10.0.14.14 + A 10.0.14.15 + A 10.0.14.16 + A 10.0.14.17 + A 10.0.14.18 + A 10.0.14.19 + A 10.0.14.20 + A 10.0.14.21 + A 10.0.14.22 + A 10.0.14.23 + A 10.0.14.24 + A 10.0.14.25 + A 10.0.14.26 + A 10.0.14.27 + A 10.0.14.28 + A 10.0.14.29 + A 10.0.14.30 + A 10.0.14.31 + A 10.0.14.32 + A 10.0.14.33 + A 10.0.14.34 + A 10.0.14.35 + A 10.0.14.36 + A 10.0.14.37 + A 10.0.14.38 + A 10.0.14.39 + A 10.0.14.40 + A 10.0.14.41 + A 10.0.14.42 + A 10.0.14.43 + A 10.0.14.44 + A 10.0.14.45 + A 10.0.14.46 + A 10.0.14.47 + A 10.0.14.48 + A 10.0.14.49 + A 10.0.14.50 + A 10.0.14.51 + A 10.0.14.52 + A 10.0.14.53 + A 10.0.14.54 + A 10.0.14.55 + A 10.0.14.56 + A 10.0.14.57 + A 10.0.14.58 + A 10.0.14.59 + A 10.0.14.60 + A 10.0.14.61 + A 10.0.14.62 + A 10.0.14.63 + A 10.0.14.64 + A 10.0.14.65 + A 10.0.14.66 + A 10.0.14.67 + A 10.0.14.68 + A 10.0.14.69 + A 10.0.14.70 + A 10.0.14.71 + A 10.0.14.72 + A 10.0.14.73 + A 10.0.14.74 + A 10.0.14.75 + A 10.0.14.76 + A 10.0.14.77 + A 10.0.14.78 + A 10.0.14.79 + A 10.0.14.80 + A 10.0.14.81 + A 10.0.14.82 + A 10.0.14.83 + A 10.0.14.84 + A 10.0.14.85 + A 10.0.14.86 + A 10.0.14.87 + A 10.0.14.88 + A 10.0.14.89 + A 10.0.14.90 + A 10.0.14.91 + A 10.0.14.92 + A 10.0.14.93 + A 10.0.14.94 + A 10.0.14.95 + A 10.0.14.96 + A 10.0.14.97 + A 10.0.14.98 + A 10.0.14.99 + A 10.0.14.100 + A 10.0.14.101 + A 10.0.14.102 + A 10.0.14.103 + A 10.0.14.104 + A 10.0.14.105 + A 10.0.14.106 + A 10.0.14.107 + A 10.0.14.108 + A 10.0.14.109 + A 10.0.14.110 + A 10.0.14.111 + A 10.0.14.112 + A 10.0.14.113 + A 10.0.14.114 + A 10.0.14.115 + A 10.0.14.116 + A 10.0.14.117 + A 10.0.14.118 + A 10.0.14.119 + A 10.0.14.120 + A 10.0.14.121 + A 10.0.14.122 + A 10.0.14.123 + A 10.0.14.124 + A 10.0.14.125 + A 10.0.14.126 + A 10.0.14.127 + A 10.0.14.128 + A 10.0.14.129 + A 10.0.14.130 + A 10.0.14.131 + A 10.0.14.132 + A 10.0.14.133 + A 10.0.14.134 + A 10.0.14.135 + A 10.0.14.136 + A 10.0.14.137 + A 10.0.14.138 + A 10.0.14.139 + A 10.0.14.140 + A 10.0.14.141 + A 10.0.14.142 + A 10.0.14.143 + A 10.0.14.144 + A 10.0.14.145 + A 10.0.14.146 + A 10.0.14.147 + A 10.0.14.148 + A 10.0.14.149 + A 10.0.14.150 + A 10.0.14.151 + A 10.0.14.152 + A 10.0.14.153 + A 10.0.14.154 + A 10.0.14.155 + A 10.0.14.156 + A 10.0.14.157 + A 10.0.14.158 + A 10.0.14.159 + A 10.0.14.160 + A 10.0.14.161 + A 10.0.14.162 + A 10.0.14.163 + A 10.0.14.164 + A 10.0.14.165 + A 10.0.14.166 + A 10.0.14.167 + A 10.0.14.168 + A 10.0.14.169 + A 10.0.14.170 + A 10.0.14.171 + A 10.0.14.172 + A 10.0.14.173 + A 10.0.14.174 + A 10.0.14.175 + A 10.0.14.176 + A 10.0.14.177 + A 10.0.14.178 + A 10.0.14.179 + A 10.0.14.180 + A 10.0.14.181 + A 10.0.14.182 + A 10.0.14.183 + A 10.0.14.184 + A 10.0.14.185 + A 10.0.14.186 + A 10.0.14.187 + A 10.0.14.188 + A 10.0.14.189 + A 10.0.14.190 + A 10.0.14.191 + A 10.0.14.192 + A 10.0.14.193 + A 10.0.14.194 + A 10.0.14.195 + A 10.0.14.196 + A 10.0.14.197 + A 10.0.14.198 + A 10.0.14.199 + A 10.0.14.200 + A 10.0.14.201 + A 10.0.14.202 + A 10.0.14.203 + A 10.0.14.204 + A 10.0.14.205 + A 10.0.14.206 + A 10.0.14.207 + A 10.0.14.208 + A 10.0.14.209 + A 10.0.14.210 + A 10.0.14.211 + A 10.0.14.212 + A 10.0.14.213 + A 10.0.14.214 + A 10.0.14.215 + A 10.0.14.216 + A 10.0.14.217 + A 10.0.14.218 + A 10.0.14.219 + A 10.0.14.220 + A 10.0.14.221 + A 10.0.14.222 + A 10.0.14.223 + A 10.0.14.224 + A 10.0.14.225 + A 10.0.14.226 + A 10.0.14.227 + A 10.0.14.228 + A 10.0.14.229 + A 10.0.14.230 + A 10.0.14.231 + A 10.0.14.232 + A 10.0.14.233 + A 10.0.14.234 + A 10.0.14.235 + A 10.0.14.236 + A 10.0.14.237 + A 10.0.14.238 + A 10.0.14.239 + A 10.0.14.240 + A 10.0.14.241 + A 10.0.14.242 + A 10.0.14.243 + A 10.0.14.244 + A 10.0.14.245 + A 10.0.14.246 + A 10.0.14.247 + A 10.0.14.248 + A 10.0.14.249 + A 10.0.14.250 + A 10.0.14.251 + A 10.0.14.252 + A 10.0.14.253 + A 10.0.14.254 + A 10.0.14.255 + A 10.0.15.0 + A 10.0.15.1 + A 10.0.15.2 + A 10.0.15.3 + A 10.0.15.4 + A 10.0.15.5 + A 10.0.15.6 + A 10.0.15.7 + A 10.0.15.8 + A 10.0.15.9 + A 10.0.15.10 + A 10.0.15.11 + A 10.0.15.12 + A 10.0.15.13 + A 10.0.15.14 + A 10.0.15.15 + A 10.0.15.16 + A 10.0.15.17 + A 10.0.15.18 + A 10.0.15.19 + A 10.0.15.20 + A 10.0.15.21 + A 10.0.15.22 + A 10.0.15.23 + A 10.0.15.24 + A 10.0.15.25 + A 10.0.15.26 + A 10.0.15.27 + A 10.0.15.28 + A 10.0.15.29 + A 10.0.15.30 + A 10.0.15.31 + A 10.0.15.32 + A 10.0.15.33 + A 10.0.15.34 + A 10.0.15.35 + A 10.0.15.36 + A 10.0.15.37 + A 10.0.15.38 + A 10.0.15.39 + A 10.0.15.40 + A 10.0.15.41 + A 10.0.15.42 + A 10.0.15.43 + A 10.0.15.44 + A 10.0.15.45 + A 10.0.15.46 + A 10.0.15.47 + A 10.0.15.48 + A 10.0.15.49 + A 10.0.15.50 + A 10.0.15.51 + A 10.0.15.52 + A 10.0.15.53 + A 10.0.15.54 + A 10.0.15.55 + A 10.0.15.56 + A 10.0.15.57 + A 10.0.15.58 + A 10.0.15.59 + A 10.0.15.60 + A 10.0.15.61 + A 10.0.15.62 + A 10.0.15.63 + A 10.0.15.64 + A 10.0.15.65 + A 10.0.15.66 + A 10.0.15.67 + A 10.0.15.68 + A 10.0.15.69 + A 10.0.15.70 + A 10.0.15.71 + A 10.0.15.72 + A 10.0.15.73 + A 10.0.15.74 + A 10.0.15.75 + A 10.0.15.76 + A 10.0.15.77 + A 10.0.15.78 + A 10.0.15.79 + A 10.0.15.80 + A 10.0.15.81 + A 10.0.15.82 + A 10.0.15.83 + A 10.0.15.84 + A 10.0.15.85 + A 10.0.15.86 + A 10.0.15.87 + A 10.0.15.88 + A 10.0.15.89 + A 10.0.15.90 + A 10.0.15.91 + A 10.0.15.92 + A 10.0.15.93 + A 10.0.15.94 + A 10.0.15.95 + A 10.0.15.96 + A 10.0.15.97 + A 10.0.15.98 + A 10.0.15.99 + A 10.0.15.100 + A 10.0.15.101 + A 10.0.15.102 + A 10.0.15.103 + A 10.0.15.104 + A 10.0.15.105 + A 10.0.15.106 + A 10.0.15.107 + A 10.0.15.108 + A 10.0.15.109 + A 10.0.15.110 + A 10.0.15.111 + A 10.0.15.112 + A 10.0.15.113 + A 10.0.15.114 + A 10.0.15.115 + A 10.0.15.116 + A 10.0.15.117 + A 10.0.15.118 + A 10.0.15.119 + A 10.0.15.120 + A 10.0.15.121 + A 10.0.15.122 + A 10.0.15.123 + A 10.0.15.124 + A 10.0.15.125 + A 10.0.15.126 + A 10.0.15.127 + A 10.0.15.128 + A 10.0.15.129 + A 10.0.15.130 + A 10.0.15.131 + A 10.0.15.132 + A 10.0.15.133 + A 10.0.15.134 + A 10.0.15.135 + A 10.0.15.136 + A 10.0.15.137 + A 10.0.15.138 + A 10.0.15.139 + A 10.0.15.140 + A 10.0.15.141 + A 10.0.15.142 + A 10.0.15.143 + A 10.0.15.144 + A 10.0.15.145 + A 10.0.15.146 + A 10.0.15.147 + A 10.0.15.148 + A 10.0.15.149 + A 10.0.15.150 + A 10.0.15.151 + A 10.0.15.152 + A 10.0.15.153 + A 10.0.15.154 + A 10.0.15.155 + A 10.0.15.156 + A 10.0.15.157 + A 10.0.15.158 + A 10.0.15.159 + A 10.0.15.160 + A 10.0.15.161 + A 10.0.15.162 + A 10.0.15.163 + A 10.0.15.164 + A 10.0.15.165 + A 10.0.15.166 + A 10.0.15.167 + A 10.0.15.168 + A 10.0.15.169 + A 10.0.15.170 + A 10.0.15.171 + A 10.0.15.172 + A 10.0.15.173 + A 10.0.15.174 + A 10.0.15.175 + A 10.0.15.176 + A 10.0.15.177 + A 10.0.15.178 + A 10.0.15.179 + A 10.0.15.180 + A 10.0.15.181 + A 10.0.15.182 + A 10.0.15.183 + A 10.0.15.184 + A 10.0.15.185 + A 10.0.15.186 + A 10.0.15.187 + A 10.0.15.188 + A 10.0.15.189 + A 10.0.15.190 + A 10.0.15.191 + A 10.0.15.192 + A 10.0.15.193 + A 10.0.15.194 + A 10.0.15.195 + A 10.0.15.196 + A 10.0.15.197 + A 10.0.15.198 + A 10.0.15.199 + A 10.0.15.200 + A 10.0.15.201 + A 10.0.15.202 + A 10.0.15.203 + A 10.0.15.204 + A 10.0.15.205 + A 10.0.15.206 + A 10.0.15.207 + A 10.0.15.208 + A 10.0.15.209 + A 10.0.15.210 + A 10.0.15.211 + A 10.0.15.212 + A 10.0.15.213 + A 10.0.15.214 + A 10.0.15.215 + A 10.0.15.216 + A 10.0.15.217 + A 10.0.15.218 + A 10.0.15.219 + A 10.0.15.220 + A 10.0.15.221 + A 10.0.15.222 + A 10.0.15.223 + A 10.0.15.224 + A 10.0.15.225 + A 10.0.15.226 + A 10.0.15.227 + A 10.0.15.228 + A 10.0.15.229 + A 10.0.15.230 + A 10.0.15.231 + A 10.0.15.232 + A 10.0.15.233 + A 10.0.15.234 + A 10.0.15.235 + A 10.0.15.236 + A 10.0.15.237 + A 10.0.15.238 + A 10.0.15.239 + A 10.0.15.240 + A 10.0.15.241 + A 10.0.15.242 + A 10.0.15.243 + A 10.0.15.244 + A 10.0.15.245 + A 10.0.15.246 + A 10.0.15.247 + A 10.0.15.248 + A 10.0.15.249 + A 10.0.15.250 \ No newline at end of file diff --git a/bin/tests/system/limits/ns1/named.conf.j2 b/bin/tests/system/limits/ns1/named.conf.j2 new file mode 100644 index 0000000..2332acf --- /dev/null +++ b/bin/tests/system/limits/ns1/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; + max-records-per-type 0; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/limits/ns1/root.db b/bin/tests/system/limits/ns1/root.db new file mode 100644 index 0000000..b93cf32 --- /dev/null +++ b/bin/tests/system/limits/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns1.example. +ns1.example. A 10.53.0.1 diff --git a/bin/tests/system/limits/tests_limits.py b/bin/tests/system/limits/tests_limits.py new file mode 100644 index 0000000..7d66361 --- /dev/null +++ b/bin/tests/system/limits/tests_limits.py @@ -0,0 +1,52 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import itertools + +import isctest +import pytest + +import dns.message + +# Everything from getting a big answer to creating an RR set with thousands +# of records takes minutes of CPU and real time with dnspython < 2.0.0. +pytest.importorskip("dns", minversion="2.0.0") + + +@pytest.mark.parametrize( + "name,limit", + [ + ("1000", 1000), + ("2000", 2000), + ("3000", 3000), + ("4000", 4000), + ("a-maximum-rrset", 4091), + ], +) +def test_limits(name, limit): + msg_query = dns.message.make_query(f"{name}.example.", "A") + res = isctest.query.tcp(msg_query, "10.53.0.1") + + iplist = [ + f"10.0.{x}.{y}" + for x, y in itertools.islice(itertools.product(range(256), repeat=2), limit) + ] + + msg_rrset = [dns.rrset.from_text_list(f"{name}.example.", "5M", "IN", "A", iplist)] + + assert res.answer == msg_rrset + + +def test_limit_exceeded(): + msg_query = dns.message.make_query("5000.example.", "A") + res = isctest.query.tcp(msg_query, "10.53.0.1") + + assert res.flags & dns.flags.TC, "TC flag was not set" diff --git a/bin/tests/system/logfileconfig/named1.args b/bin/tests/system/logfileconfig/named1.args new file mode 100644 index 0000000..6611904 --- /dev/null +++ b/bin/tests/system/logfileconfig/named1.args @@ -0,0 +1 @@ +-c named.conf -m record -T nosyslog -f -d 99 -D logfileconfig-ns1 diff --git a/bin/tests/system/logfileconfig/named2.args b/bin/tests/system/logfileconfig/named2.args new file mode 100644 index 0000000..e2b5a48 --- /dev/null +++ b/bin/tests/system/logfileconfig/named2.args @@ -0,0 +1 @@ +-c named.conf -m record -T nosyslog -f -d 99 -D logfileconfig-ns1 -L named_deflog diff --git a/bin/tests/system/logfileconfig/ns1/named.abspathconf.in b/bin/tests/system/logfileconfig/ns1/named.abspathconf.in new file mode 100644 index 0000000..fdf8a8a --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.abspathconf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + buffered no; + file "@TMPDIR@/example.log" versions 1 size 1k suffix increment; # small size + severity debug 100; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.dirconf.in b/bin/tests/system/logfileconfig/ns1/named.dirconf.in new file mode 100644 index 0000000..d6ee134 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.dirconf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "/tmp"; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.incconf.in b/bin/tests/system/logfileconfig/ns1/named.incconf.in new file mode 100644 index 0000000..d398c33 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.incconf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + buffered no; + file "named_inc" versions 1 size 1k suffix increment; # small size + severity debug 100; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in b/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in new file mode 100644 index 0000000..6ac14df --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.iso8601-utc.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "named_iso8601_utc"; + print-time iso8601-utc; + severity debug 9; + }; + category default { default_log; default_debug; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.iso8601.in b/bin/tests/system/logfileconfig/ns1/named.iso8601.in new file mode 100644 index 0000000..5a1bd5e --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.iso8601.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "named_iso8601"; + print-time iso8601; + severity debug 9; + }; + category default { default_log; default_debug; }; +}; + + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.pipeconf.in b/bin/tests/system/logfileconfig/ns1/named.pipeconf.in new file mode 100644 index 0000000..8f2ec63 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.pipeconf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "named_pipe"; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.plain.in b/bin/tests/system/logfileconfig/ns1/named.plain.in new file mode 100644 index 0000000..f31906b --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.plain.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "named_log"; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.plainconf.in b/bin/tests/system/logfileconfig/ns1/named.plainconf.in new file mode 100644 index 0000000..d8dd5f5 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.plainconf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.symconf.in b/bin/tests/system/logfileconfig/ns1/named.symconf.in new file mode 100644 index 0000000..9603365 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.symconf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + file "named_sym"; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.tsconf.in b/bin/tests/system/logfileconfig/ns1/named.tsconf.in new file mode 100644 index 0000000..7f76195 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.tsconf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + buffered no; + file "named_ts" versions 3 size 1000 suffix timestamp; # small size + severity debug 100; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.unlimited.in b/bin/tests/system/logfileconfig/ns1/named.unlimited.in new file mode 100644 index 0000000..f806edd --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.unlimited.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + buffered no; + file "named_unlimited" versions unlimited size 1000; + severity debug 100; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/ns1/named.versconf.in b/bin/tests/system/logfileconfig/ns1/named.versconf.in new file mode 100644 index 0000000..c30d8a3 --- /dev/null +++ b/bin/tests/system/logfileconfig/ns1/named.versconf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; + notify yes; +}; + +logging { + channel default_log { + buffered no; + file "named_vers" versions 5 size 1000; // really small size + severity debug 100; + print-time yes; + }; + category default { default_log; default_debug; }; + category lame-servers { null; }; + + channel query_log { + file "query_log"; + print-time yes; + buffered yes; + }; + category queries { query_log; }; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { "rndc-key"; }; +}; + +key rndc-key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/logfileconfig/setup.sh b/bin/tests/system/logfileconfig/setup.sh new file mode 100644 index 0000000..8884af7 --- /dev/null +++ b/bin/tests/system/logfileconfig/setup.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.plain.in ns1/named.conf diff --git a/bin/tests/system/logfileconfig/tests.sh b/bin/tests/system/logfileconfig/tests.sh new file mode 100644 index 0000000..e738dbd --- /dev/null +++ b/bin/tests/system/logfileconfig/tests.sh @@ -0,0 +1,293 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +# Test given condition. If true, test again after a second. Used for testing +# filesystem-dependent conditions in order to prevent false negatives caused by +# directory contents not being synchronized immediately after rename() returns. +test_with_retry() { + if test "$@"; then + sleep 1 + if test "$@"; then + return 0 + fi + fi + return 1 +} + +status=0 +n=0 + +# First run with a known good config. +n=$((n + 1)) +echo_i "testing log file validity (only plain files allowed) ($n)" +ret=0 +cat /dev/null >ns1/named_log +copy_setports ns1/named.plainconf.in ns1/named.conf +nextpart ns1/named.run >/dev/null +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Now try directory, expect failure +n=$((n + 1)) +echo_i "testing directory as log file ($n)" +ret=0 +nextpart ns1/named.run >/dev/null +copy_setports ns1/named.dirconf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Now try pipe file, expect failure +n=$((n + 1)) +echo_i "testing pipe file as log file ($n)" +ret=0 +nextpart ns1/named.run >/dev/null +rm -f ns1/named_pipe +if mkfifo ns1/named_pipe >/dev/null 2>&1; then + copy_setports ns1/named.pipeconf.in ns1/named.conf + rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n + wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1 + if [ "$ret" -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipping pipe test (unable to create pipe)" +fi + +# Now try symlink file to plain file, expect success +n=$((n + 1)) +echo_i "testing symlink to plain file as log file ($n)" +ret=0 +rm -f ns1/named_log ns1/named_sym +touch ns1/named_log +if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then + nextpart ns1/named.run >/dev/null + copy_setports ns1/named.symconf.in ns1/named.conf + rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n + wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1 + if [ "$ret" -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipping symlink test (unable to create symlink)" +fi + +echo_i "repeat previous tests without named -g" +copy_setports ns1/named.plain.in ns1/named.conf +stop_server --use-rndc --port ${CONTROLPORT} ns1 +cp named1.args ns1/named.args +start_server --noclean --restart --port ${PORT} ns1 + +n=$((n + 1)) +echo_i "testing log file validity (only plain files allowed) ($n)" +ret=0 +cat /dev/null >ns1/named_log +copy_setports ns1/named.plainconf.in ns1/named.conf +nextpart ns1/named.run >/dev/null +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Now try directory, expect failure +n=$((n + 1)) +echo_i "testing directory as log file ($n)" +ret=0 +nextpart ns1/named.run >/dev/null +copy_setports ns1/named.dirconf.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Now try pipe file, expect failure +n=$((n + 1)) +echo_i "testing pipe file as log file ($n)" +ret=0 +nextpart ns1/named.run >/dev/null +rm -f ns1/named_pipe +if mkfifo ns1/named_pipe >/dev/null 2>&1; then + copy_setports ns1/named.pipeconf.in ns1/named.conf + rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n + wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1 + if [ "$ret" -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipping pipe test (unable to create pipe)" +fi + +# Now try symlink file to plain file, expect success +n=$((n + 1)) +echo_i "testing symlink to plain file as log file ($n)" +ret=0 +rm -f ns1/named_log ns1/named_sym +touch ns1/named_log +if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then + nextpart ns1/named.run >/dev/null + copy_setports ns1/named.symconf.in ns1/named.conf + rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n + wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1 + if [ "$ret" -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipping symlink test (unable to create symlink)" +fi + +echo_i "testing logging functionality" +n=$((n + 1)) +ret=0 +echo_i "testing iso8601 timestamp ($n)" +copy_setports ns1/named.iso8601.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +grep '^....-..-..T..:..:..\.... ' ns1/named_iso8601 >/dev/null || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing iso8601-utc timestamp ($n)" +ret=0 +copy_setports ns1/named.iso8601-utc.in ns1/named.conf +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +grep '^....-..-..T..:..:..\....Z' ns1/named_iso8601_utc >/dev/null || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing explicit versions ($n)" +ret=0 +copy_setports ns1/named.versconf.in ns1/named.conf +# a seconds since epoch version number +touch ns1/named_vers.1480039317 +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +# we are configured to retain five logfiles (a current file +# and 4 backups). so files with version number 5 or higher +# should be removed. +test_with_retry -f ns1/named_vers.1480039317 && ret=1 +test_with_retry -f ns1/named_vers.5 && ret=1 +test_with_retry -f ns1/named_vers.4 || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing timestamped versions ($n)" +ret=0 +copy_setports ns1/named.tsconf.in ns1/named.conf +# a seconds since epoch version number +touch ns1/named_ts.1480039317 +# a timestamp version number +touch ns1/named_ts.20150101120000120 +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +_found2() ( + $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + + # we are configured to keep three versions, so the oldest + # timestamped versions should be gone, and there should + # be two or three backup ones. + [ -f ns1/named_ts.1480039317 ] && return 1 + [ -f ns1/named_ts.20150101120000120 ] && return 1 + set -- ns1/named_ts.* + [ "$#" -eq 2 -o "$#" -eq 3 ] || return 1 +) +retry_quiet 5 _found2 || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing incremented versions ($n)" +ret=0 +copy_setports ns1/named.incconf.in ns1/named.conf +try=0 +while test $try -lt 12; do + touch ns1/named_inc.$try + try=$((try + 1)) +done +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +_found2() ( + $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + + try=1 + while test $try -lt 12; do + [ -f ns1/named_inc.$try ] && return 1 + try=$((try + 1)) + done + set -- ns1/named_inc.* + [ "$#" -eq 1 ] || return 1 +) +retry_quiet 5 _found2 || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing absolute file path versions ($n)" +ret=0 +copy_setports ns1/named.abspathconf.in ns1/named.conf +try=0 +while test $try -lt 12; do + touch $TMPDIR/example.log.$try + try=$((try + 1)) +done +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +_found2() ( + $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + + try=1 + while test $try -lt 12; do + [ -f $TMPDIR/example.log.$try ] && return 1 + try=$((try + 1)) + done + set -- $TMPDIR/example.log.* + [ "$#" -eq 1 ] || return 1 +) +retry_quiet 5 _found2 || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing unlimited versions ($n)" +ret=0 +copy_setports ns1/named.unlimited.in ns1/named.conf +# a seconds since epoch version number +touch ns1/named_unlimited.1480039317 +rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n +$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +test_with_retry -f ns1/named_unlimited.1480039317 || ret=1 +test_with_retry -f ns1/named_unlimited.4 || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing default logfile using named -L file ($n)" +ret=0 +stop_server ns1 +cp named2.args ns1/named.args +test -f ns1/named.pid && ret=1 +rm -f ns1/named_deflog +copy_setports ns1/named.plainconf.in ns1/named.conf +start_server --noclean --restart --port ${PORT} ns1 +[ -f "ns1/named_deflog" ] || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py b/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py new file mode 100644 index 0000000..dde400b --- /dev/null +++ b/bin/tests/system/logfileconfig/tests_sh_logfileconfig.py @@ -0,0 +1,35 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "ns1/named.args", + "ns1/named_deflog", + "ns1/named_inc*", + "ns1/named_iso8601", + "ns1/named_iso8601_utc", + "ns1/named_log", + "ns1/named_pipe", + "ns1/named_sym", + "ns1/named_ts*", + "ns1/named_unlimited*", + "ns1/named_vers*", + "ns1/query_log*", + ] +) + + +def test_logfileconfig(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/makejournal.c b/bin/tests/system/makejournal.c new file mode 100644 index 0000000..ec1d1b8 --- /dev/null +++ b/bin/tests/system/makejournal.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define CHECK(r) \ + do { \ + result = (r); \ + if (result != ISC_R_SUCCESS) \ + goto cleanup; \ + } while (0) + +isc_mem_t *mctx = NULL; +isc_log_t *lctx = NULL; + +static bool dst_active = false; + +/* + * Logging categories: this needs to match the list in bin/named/log.c. + */ +static isc_logcategory_t categories[] = { { "", 0 }, + { "client", 0 }, + { "network", 0 }, + { "update", 0 }, + { "queries", 0 }, + { "unmatched", 0 }, + { "update-security", 0 }, + { "query-errors", 0 }, + { NULL, 0 } }; + +static isc_result_t +loadzone(dns_db_t **db, const char *origin, const char *filename) { + isc_result_t result; + dns_fixedname_t fixed; + dns_name_t *name; + + name = dns_fixedname_initname(&fixed); + + result = dns_name_fromstring(name, origin, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_db_create(mctx, ZONEDB_DEFAULT, name, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, db); + if (result != ISC_R_SUCCESS) { + return result; + } + + result = dns_db_load(*db, filename, dns_masterformat_text, 0); + if (result == DNS_R_SEENINCLUDE) { + result = ISC_R_SUCCESS; + } + return result; +} + +int +main(int argc, char **argv) { + isc_result_t result; + char *origin, *file1, *file2, *journal; + dns_db_t *olddb = NULL, *newdb = NULL; + isc_logdestination_t destination; + isc_logconfig_t *logconfig = NULL; + + if (argc != 5) { + printf("usage: %s origin file1 file2 journal\n", argv[0]); + return 1; + } + + origin = argv[1]; + file1 = argv[2]; + file2 = argv[3]; + journal = argv[4]; + + isc_mem_debugging |= ISC_MEM_DEBUGRECORD; + isc_mem_create(&mctx); + + CHECK(dst_lib_init(mctx, NULL)); + dst_active = true; + + isc_log_create(mctx, &lctx, &logconfig); + isc_log_registercategories(lctx, categories); + isc_log_setcontext(lctx); + dns_log_init(lctx); + dns_log_setcontext(lctx); + + destination.file.stream = stderr; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_DYNAMIC, &destination, 0); + + CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL)); + + result = loadzone(&olddb, origin, file1); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "Couldn't load %s: ", file1); + goto cleanup; + } + + result = loadzone(&newdb, origin, file2); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "Couldn't load %s: ", file2); + goto cleanup; + } + + result = dns_db_diff(mctx, newdb, NULL, olddb, NULL, journal); + +cleanup: + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "%s\n", isc_result_totext(result)); + } + + if (newdb != NULL) { + dns_db_detach(&newdb); + } + if (olddb != NULL) { + dns_db_detach(&olddb); + } + + if (lctx != NULL) { + isc_log_destroy(&lctx); + } + if (dst_active) { + dst_lib_destroy(); + dst_active = false; + } + if (mctx != NULL) { + isc_mem_destroy(&mctx); + } + + return result != ISC_R_SUCCESS ? 1 : 0; +} diff --git a/bin/tests/system/masterfile/ns1/include.db b/bin/tests/system/masterfile/ns1/include.db new file mode 100644 index 0000000..149c819 --- /dev/null +++ b/bin/tests/system/masterfile/ns1/include.db @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; Test $INCLUDE current domain name and origin semantics + +$TTL 300 +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3600 + ) + NS ns + +ns A 127.0.0.1 + +a A 10.0.0.1 +$INCLUDE sub.db a +; use the current domain name + A 10.0.0.99 +b A 10.0.0.2 +$ORIGIN b +$INCLUDE sub.db +; use the current domain name +; A 10.0.0.99 +c A 10.0.0.3 diff --git a/bin/tests/system/masterfile/ns1/named.conf.j2 b/bin/tests/system/masterfile/ns1/named.conf.j2 new file mode 100644 index 0000000..788eaa6 --- /dev/null +++ b/bin/tests/system/masterfile/ns1/named.conf.j2 @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "include" { + type primary; + file "include.db"; +}; + +zone "ttl1" { + type primary; + file "ttl1.db"; +}; + +zone "ttl2" { + type primary; + file "ttl2.db"; +}; diff --git a/bin/tests/system/masterfile/ns1/sub.db b/bin/tests/system/masterfile/ns1/sub.db new file mode 100644 index 0000000..7e027b0 --- /dev/null +++ b/bin/tests/system/masterfile/ns1/sub.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +a A 10.0.1.1 +$ORIGIN foo +b A 10.0.2.2 + diff --git a/bin/tests/system/masterfile/ns1/ttl1.db b/bin/tests/system/masterfile/ns1/ttl1.db new file mode 100644 index 0000000..56afe9d --- /dev/null +++ b/bin/tests/system/masterfile/ns1/ttl1.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "soa minttl 3" +b 2 TXT "explicit ttl 2" +c TXT "soa minttl 3" +$TTL 1 +d TXT "default ttl 1" +e 4 TXT "explicit ttl 4" +f TXT "default ttl 1" diff --git a/bin/tests/system/masterfile/ns1/ttl2.db b/bin/tests/system/masterfile/ns1/ttl2.db new file mode 100644 index 0000000..778e8d3 --- /dev/null +++ b/bin/tests/system/masterfile/ns1/ttl2.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 IN SOA ns hostmaster ( + 1 ; serial + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +a TXT "inherited ttl 1" +b 2 TXT "explicit ttl 2" +c TXT "inherited ttl 2" +$TTL 3 +d TXT "default ttl 3" +e 2 TXT "explicit ttl 2" +f TXT "default ttl 3" + + + diff --git a/bin/tests/system/masterfile/ns2/example.db b/bin/tests/system/masterfile/ns2/example.db new file mode 100644 index 0000000..414403a --- /dev/null +++ b/bin/tests/system/masterfile/ns2/example.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2010042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/masterfile/ns2/named.conf.j2 b/bin/tests/system/masterfile/ns2/named.conf.j2 new file mode 100644 index 0000000..6333b05 --- /dev/null +++ b/bin/tests/system/masterfile/ns2/named.conf.j2 @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "missing" { + type primary; + file "missing.db"; +}; diff --git a/bin/tests/system/masterfile/tests_masterfile.py b/bin/tests/system/masterfile/tests_masterfile.py new file mode 100644 index 0000000..9aaaa76 --- /dev/null +++ b/bin/tests/system/masterfile/tests_masterfile.py @@ -0,0 +1,115 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +import dns.message +import dns.zone + +import isctest + + +def test_masterfile_include_semantics(): + """Test master file $INCLUDE semantics""" + msg_axfr = dns.message.make_query("include.", "AXFR") + res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") + axfr_include_semantics = """;ANSWER +include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600 +include. 300 IN NS ns.include. +a.include. 300 IN A 10.0.0.1 +a.include. 300 IN A 10.0.0.99 +a.a.include. 300 IN A 10.0.1.1 +b.foo.a.include. 300 IN A 10.0.2.2 +b.include. 300 IN A 10.0.0.2 +a.b.include. 300 IN A 10.0.1.1 +c.b.include. 300 IN A 10.0.0.3 +b.foo.b.include. 300 IN A 10.0.2.2 +ns.include. 300 IN A 127.0.0.1 +""" + expected = dns.message.from_text(axfr_include_semantics) + isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) + + +def test_masterfile_bind_8_compat_semantics(): + """Test master file BIND 8 TTL and $TTL semantics compatibility""" + msg_axfr = dns.message.make_query("ttl1.", "AXFR") + res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") + axfr_ttl_semantics = """;ANSWER +ttl1. 3 IN SOA ns.ttl1. hostmaster.ttl1. 1 3600 1800 1814400 3 +ttl1. 3 IN NS ns.ttl1. +a.ttl1. 3 IN TXT "soa minttl 3" +b.ttl1. 2 IN TXT "explicit ttl 2" +c.ttl1. 3 IN TXT "soa minttl 3" +d.ttl1. 1 IN TXT "default ttl 1" +e.ttl1. 4 IN TXT "explicit ttl 4" +f.ttl1. 1 IN TXT "default ttl 1" +ns.ttl1. 3 IN A 10.53.0.1 +""" + expected = dns.message.from_text(axfr_ttl_semantics) + isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) + + +def test_masterfile_rfc_1035_semantics(): + """Test master file RFC1035 TTL and $TTL semantics""" + msg_axfr = dns.message.make_query("ttl2.", "AXFR") + res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") + axfr_ttl_semantics = """;ANSWER +ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3 +ttl2. 1 IN NS ns.ttl2. +a.ttl2. 1 IN TXT "inherited ttl 1" +b.ttl2. 2 IN TXT "explicit ttl 2" +c.ttl2. 2 IN TXT "inherited ttl 2" +d.ttl2. 3 IN TXT "default ttl 3" +e.ttl2. 2 IN TXT "explicit ttl 2" +f.ttl2. 3 IN TXT "default ttl 3" +ns.ttl2. 1 IN A 10.53.0.1 +""" + expected = dns.message.from_text(axfr_ttl_semantics) + isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) + + +def test_masterfile_missing_master_file(): + """Test nameserver running with a missing master file""" + msg_soa = dns.message.make_query("example.", "SOA") + res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") + expected_soa_rr = """;ANSWER +example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600 +""" + expected = dns.message.from_text(expected_soa_rr) + isctest.check.rrsets_equal(res_soa.answer, expected.answer, compare_ttl=True) + + +def test_masterfile_missing_master_file_servfail(): + """Test nameserver returning SERVFAIL for a missing master file""" + msg_soa = dns.message.make_query("missing.", "SOA") + res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") + isctest.check.servfail(res_soa) + + +def test_masterfile_owner_inheritance(): + """Test owner inheritance after $INCLUDE""" + checker_output = isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + "example", + "zone/inheritownerafterinclude.db", + ] + ).stdout.decode("utf-8") + owner_inheritance_zone = """ +example. 0 IN SOA . . 0 0 0 0 0 +example. 0 IN TXT "this should be at the zone apex" +example. 0 IN NS . +""" + checker_zone = dns.zone.from_text(checker_output, origin="example.") + expected = dns.zone.from_text(owner_inheritance_zone, origin="example.") + isctest.check.zones_equal(checker_zone, expected, compare_ttl=True) diff --git a/bin/tests/system/masterfile/zone/inheritownerafterinclude.db b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db new file mode 100644 index 0000000..11b97ea --- /dev/null +++ b/bin/tests/system/masterfile/zone/inheritownerafterinclude.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +$INCLUDE zone/nameservers.db + IN TXT "this should be at the zone apex" diff --git a/bin/tests/system/masterfile/zone/nameservers.db b/bin/tests/system/masterfile/zone/nameservers.db new file mode 100644 index 0000000..f7b6525 --- /dev/null +++ b/bin/tests/system/masterfile/zone/nameservers.db @@ -0,0 +1,12 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ IN NS . diff --git a/bin/tests/system/masterformat/ns1/compile.sh b/bin/tests/system/masterformat/ns1/compile.sh new file mode 100755 index 0000000..52c3140 --- /dev/null +++ b/bin/tests/system/masterformat/ns1/compile.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +$CHECKZONE -D -F raw -o example.db.raw example \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o ../ns3/example.db.raw example \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o ../ns3/dynamic.db.raw dynamic \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw=1 -o example.db.raw1 example-explicit \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw=0 -o example.db.compat example-compat \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -L 3333 -o example.db.serial.raw example \ + example.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o under-limit.db.raw under-limit under-limit.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o under-limit-kasp.db.raw under-limit-kasp under-limit-kasp.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o below-limit.db.raw below-limit below-limit.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o below-limit-kasp.db.raw below-limit-kasp below-limit-kasp.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o above-limit.db.raw above-limit above-limit.db >/dev/null 2>&1 +$CHECKZONE -D -F raw -o 255types.db.raw 255types 255types.db >/dev/null 2>&1 + +$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed >/dev/null 2>&1 +$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed >/dev/null 2>&1 +$SIGNER -S -f signed.db.signed -o signed signed.db >/dev/null +$CHECKZONE -D -F raw -o signed.db.raw signed signed.db.signed >/dev/null 2>&1 diff --git a/bin/tests/system/masterformat/ns1/empty.db.in b/bin/tests/system/masterformat/ns1/empty.db.in new file mode 100644 index 0000000..5a81863 --- /dev/null +++ b/bin/tests/system/masterformat/ns1/empty.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1D + +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 diff --git a/bin/tests/system/masterformat/ns1/example.db b/bin/tests/system/masterformat/ns1/example.db new file mode 100644 index 0000000..2dee1a9 --- /dev/null +++ b/bin/tests/system/masterformat/ns1/example.db @@ -0,0 +1,59 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1D + +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +mx MX 10 mail +a A 10.53.0.1 + A 10.53.0.2 +aaaa AAAA 2001:db8::53 +cname CNAME cname-target +dname DNAME dname-target +txt TXT "this is text" + +;; +;; we are not testing DNSSEC behavior, so we don't care about the semantics +;; of the following records. +dnskey 300 DNSKEY 256 3 13 ( + TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR + wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O + 3uhPJsJ7ivpbh+w== + ) +private-dnskey 300 DNSKEY 256 3 253 ( AAo= ) +ds 300 NS . +ds 300 DS 30795 1 1 ( + 310D27F4D82C1FC2400704EA9939FE6E1CEA + A3B9 ) +cdnskey 300 CDNSKEY 256 3 13 ( + TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR + wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O + 3uhPJsJ7ivpbh+w== + ) +private-cdnskey 300 CDNSKEY 256 3 253 ( AAo= ) +cds 300 CDS 30795 1 1 ( + 310D27F4D82C1FC2400704EA9939FE6E1CEA + A3B9 ) +nsec 600 NSEC nsecnext NS DS RRSIG NSEC +rrsig 300 RRSIG SOA 1 0 300 20050714214747 ( + 20050614214747 30795 . + yi/RRPAQmn6rnjDQaCqVValBa+ICF00ZldKf + ZSDaoew5mMUh83DlrrPPNeAxrzMSNzDGlJ6P + fdyIFgzPn/CvthF4kjBUAiJTp4r2zhlaUJQ+ + QFo+drYXYgVJo6aA36fj ) diff --git a/bin/tests/system/masterformat/ns1/named.conf.in b/bin/tests/system/masterformat/ns1/named.conf.in new file mode 100644 index 0000000..24ecdc4 --- /dev/null +++ b/bin/tests/system/masterformat/ns1/named.conf.in @@ -0,0 +1,136 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.1; }; + port @PORT@; + listen-on-v6 { none; }; + recursion no; + notify no; + session-keyfile "session.key"; + servfail-ttl 0; + dnssec-validation no; + max-records-per-type 2050; + max-types-per-name 500; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "masterformat" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +zone "example" { + type primary; + masterfile-format raw; + file "example.db.raw"; +}; + +zone "compat-example" { + type primary; + masterfile-format raw; + file "example.db.compat"; +}; + +zone "transfer1" { + type primary; + file "example.db"; + allow-transfer { any; }; +}; + +zone "transfer2" { + type primary; + file "example.db"; + allow-transfer { any; }; +}; + +zone "transfer3" { + type primary; + file "example.db"; + allow-transfer { any; }; +}; + +zone "transfer4" { + type primary; + file "example.db"; + allow-transfer { any; }; +}; + + +zone "under-limit" { + type primary; + file "under-limit.db.raw"; + masterfile-format raw; + allow-transfer { any; }; +}; + +zone "under-limit-kasp" { + type primary; + file "under-limit-kasp.db.raw"; + masterfile-format raw; + dnssec-policy masterformat; + allow-transfer { any; }; +}; + +zone "below-limit" { + type primary; + file "below-limit.db.raw"; + masterfile-format raw; + allow-transfer { any; }; +}; + +zone "below-limit-kasp" { + type primary; + file "below-limit-kasp.db.raw"; + masterfile-format raw; + dnssec-policy masterformat; + inline-signing no; + allow-update { any; }; + allow-transfer { any; }; +}; + +zone "above-limit" { + type primary; + file "above-limit.db.raw"; + masterfile-format raw; + allow-transfer { any; }; +}; + +zone "255types" { + type primary; + file "255types.db.raw"; + masterfile-format raw; + allow-transfer { any; }; +}; + +zone "signed" { + type primary; + file "signed.db.raw"; + masterfile-format raw; + allow-transfer { any; }; + update-policy local; + dnssec-policy masterformat; +}; diff --git a/bin/tests/system/masterformat/ns1/signed.db b/bin/tests/system/masterformat/ns1/signed.db new file mode 100644 index 0000000..55d6fae --- /dev/null +++ b/bin/tests/system/masterformat/ns1/signed.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1D + +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +mx MX 10 mail +a A 10.53.0.1 + A 10.53.0.2 +aaaa AAAA 2001:db8::53 +cname CNAME cname-target +dname DNAME dname-target +txt TXT "this is text" diff --git a/bin/tests/system/masterformat/ns2/formerly-text.db.in b/bin/tests/system/masterformat/ns2/formerly-text.db.in new file mode 100644 index 0000000..02ce216 --- /dev/null +++ b/bin/tests/system/masterformat/ns2/formerly-text.db.in @@ -0,0 +1,48 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 86400 ; 1 day +transfer3 IN SOA ns.transfer3. hostmaster.transfer3. ( + 1 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 minutes) + 1814400 ; expire (3 weeks) + 3 ; minimum (3 seconds) + ) + NS ns.transfer3. +$ORIGIN transfer3. +a A 10.53.0.1 + A 10.53.0.2 +aaaa AAAA 2001:db8::53 +cname CNAME cname-target +dname DNAME dname-target +$TTL 300 ; 5 minutes +dnskey DNSKEY 256 3 13 ( + TEcpWeW1mJp+OujqyInMbjGRODJIYen/4kMR + wO6zW3RzrvmNIMgFag6G uXofiSwJ6YDeQ0O + 3uhPJsJ7ivpbh+w== + ) +ds DS 30795 1 1 ( + 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9 ) +$TTL 86400 ; 1 day +mx MX 10 mail +ns A 10.53.0.1 +$TTL 600 ; 10 minutes +nsec NSEC nsecnext.transfer3. NS DS RRSIG NSEC +$TTL 300 ; 5 minutes +rrsig RRSIG SOA 1 0 300 ( + 20050714214747 20050614214747 30795 . + yi/RRPAQmn6rnjDQaCqVValBa+ICF00ZldKfZSDaoew5 + mMUh83DlrrPPNeAxrzMSNzDGlJ6PfdyIFgzPn/CvthF4 + kjBUAiJTp4r2zhlaUJQ+QFo+drYXYgVJo6aA36fj ) +$TTL 86400 ; 1 day +txt TXT "this is text" diff --git a/bin/tests/system/masterformat/ns2/named.conf.in b/bin/tests/system/masterformat/ns2/named.conf.in new file mode 100644 index 0000000..862b71a --- /dev/null +++ b/bin/tests/system/masterformat/ns2/named.conf.in @@ -0,0 +1,94 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.2; }; + listen-on-v6 { none; }; + port @PORT@; + recursion no; + notify no; + servfail-ttl 0; + dnssec-validation no; + max-records-per-type 2000; + max-types-per-name 200; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "transfer1" { + type secondary; + primaries { 10.53.0.1; }; + file "transfer.db.raw"; +}; + +zone "transfer2" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format text; + file "transfer.db.txt"; +}; + +zone "transfer3" { + type secondary; + primaries { 10.53.0.1; }; + file "formerly-text.db"; +}; + +zone "transfer4" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format text; + masterfile-style full; + file "transfer.db.full"; +}; + +zone "under-limit" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format raw; + file "under-limit.bk"; +}; + +zone "under-limit-kasp" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format raw; + file "under-limit-kasp.bk"; +}; + +zone "below-limit" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format raw; + file "below-limit.bk"; +}; + +zone "below-limit-kasp" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format raw; + file "below-limit-kasp.bk"; +}; + +zone "255types" { + type secondary; + primaries { 10.53.0.1; }; + masterfile-format raw; + file "255types.bk"; +}; diff --git a/bin/tests/system/masterformat/ns3/named.conf.in b/bin/tests/system/masterformat/ns3/named.conf.in new file mode 100644 index 0000000..deaed8b --- /dev/null +++ b/bin/tests/system/masterformat/ns3/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.3; }; + port @PORT@; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "example" { + type primary; + masterfile-format raw; + file "example.db.raw"; +}; + +zone "dynamic" { + type primary; + masterfile-format raw; + file "dynamic.db.raw"; + allow-update { any; }; +}; diff --git a/bin/tests/system/masterformat/ns4/compile.sh b/bin/tests/system/masterformat/ns4/compile.sh new file mode 100755 index 0000000..9dabc50 --- /dev/null +++ b/bin/tests/system/masterformat/ns4/compile.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +for zone in kasp-max-records-per-type \ + kasp-max-records-per-type-dnskey \ + kasp-max-types-per-name; do + $CHECKZONE -D -F raw -o $zone.db.raw $zone template.db >/dev/null 2>&1 +done diff --git a/bin/tests/system/masterformat/ns4/kasp.db b/bin/tests/system/masterformat/ns4/kasp.db new file mode 100644 index 0000000..2da3007 --- /dev/null +++ b/bin/tests/system/masterformat/ns4/kasp.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1D + +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +mx MX 10 mail +a A 10.53.0.1 +aaaa AAAA 2001:db8::53 +cname CNAME cname-target +dname DNAME dname-target +txt TXT "this is text" diff --git a/bin/tests/system/masterformat/ns4/named1.conf.in b/bin/tests/system/masterformat/ns4/named1.conf.in new file mode 100644 index 0000000..0adc4e9 --- /dev/null +++ b/bin/tests/system/masterformat/ns4/named1.conf.in @@ -0,0 +1,89 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.4; }; + port @PORT@; + listen-on-v6 { none; }; + recursion no; + notify no; + session-keyfile "session.key"; + servfail-ttl 0; + dnssec-validation no; + + /* Ridicously low on purpose */ + max-records-per-type 1; + max-types-per-name 11; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +dnssec-policy "masterformat" { + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +/* + * This one should be okay, since the default policy only introduces one DNSKEY + * and each signature covering a different type is considered a separate RRset. + */ +zone "kasp-max-records-per-type" { + type primary; + file "kasp-max-records-per-type.db.raw"; + masterfile-format raw; + dnssec-policy "default"; + inline-signing no; + allow-update { any; }; + allow-transfer { any; }; +}; + +/* + * This one uses a ZSK / KSK, so that is two records in one RRset, + * thus it should fail to sign. + */ +zone "kasp-max-records-per-type-dnskey" { + type primary; + file "kasp-max-records-per-type-dnskey.db.raw"; + masterfile-format raw; + dnssec-policy "masterformat"; + inline-signing no; + allow-update { any; }; + allow-transfer { any; }; +}; + +/* + * The template zone is fine and should be possible to sign, but when + * adding an extra type to the apex the max-types-per-name will be exceeded, + * meaning the update should fail. + */ +zone "kasp-max-types-per-name" { + type primary; + file "kasp-max-types-per-name.db.raw"; + masterfile-format raw; + dnssec-policy "default"; + inline-signing no; + allow-update { any; }; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/masterformat/ns4/named2.conf.in b/bin/tests/system/masterformat/ns4/named2.conf.in new file mode 100644 index 0000000..fb810cc --- /dev/null +++ b/bin/tests/system/masterformat/ns4/named2.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + pid-file "named.pid"; + listen-on port @PORT@ { 10.53.0.4; }; + port @PORT@; + listen-on-v6 { none; }; + recursion no; + notify no; + session-keyfile "session.key"; + servfail-ttl 0; + dnssec-validation no; + + /* Ridicously low on purpose */ + max-records-per-type 1; + max-types-per-name 9; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* + * The template zone is fine, but when adding the DNSSEC records to the apex, + * the max-types-per-name will be exceeded, meaning signing should fail. + */ +zone "kasp-max-types-per-name" { + type primary; + file "kasp-max-types-per-name.db.raw"; + masterfile-format raw; + dnssec-policy "default"; + inline-signing no; + allow-update { any; }; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/masterformat/ns4/template.db b/bin/tests/system/masterformat/ns4/template.db new file mode 100644 index 0000000..2da3007 --- /dev/null +++ b/bin/tests/system/masterformat/ns4/template.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 1D + +@ IN SOA ns hostmaster ( + 1 + 3600 + 1800 + 1814400 + 3 + ) + NS ns +ns A 10.53.0.1 +mx MX 10 mail +a A 10.53.0.1 +aaaa AAAA 2001:db8::53 +cname CNAME cname-target +dname DNAME dname-target +txt TXT "this is text" diff --git a/bin/tests/system/masterformat/setup.sh b/bin/tests/system/masterformat/setup.sh new file mode 100755 index 0000000..a09ab63 --- /dev/null +++ b/bin/tests/system/masterformat/setup.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named1.conf.in ns4/named.conf + +cp ns1/example.db ns2/ +cp ns2/formerly-text.db.in ns2/formerly-text.db +cp ns1/empty.db.in ns1/under-limit.db + +# counts are set with respect to these limits in named.conf: +# max-records-per-type 2050; +# max-types-per-name 500; +awk 'END { + for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; } + for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; } + for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; } +}' >ns1/under-limit.db +cp ns1/under-limit.db ns1/under-limit-kasp.db + +cp ns1/empty.db.in ns1/below-limit.db +awk 'END { + for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; } + for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; } + for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; } + for (i = 0; i < 2050; i++ ) { print "2050-txt TXT", i; } +}' >ns1/below-limit.db +cp ns1/below-limit.db ns1/below-limit-kasp.db + +cp ns1/empty.db.in ns1/above-limit.db +awk 'END { + for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; } + for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; } + for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; } + for (i = 0; i < 2050; i++ ) { print "2050-txt TXT", i; } + for (i = 0; i < 2100; i++ ) { print "2100-txt TXT", i; } +}' >ns1/above-limit.db + +cp ns1/empty.db.in ns1/255types.db +for ntype in $(seq 65280 65534); do + echo "m TYPE${ntype} \# 0" +done >>ns1/255types.db +echo "m TXT bunny" >>ns1/255types.db +(cd ns1 && $SHELL compile.sh) +(cd ns4 && $SHELL compile.sh) diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh new file mode 100755 index 0000000..cbf5215 --- /dev/null +++ b/bin/tests/system/masterformat/tests.sh @@ -0,0 +1,550 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +status=0 +n=1 + +israw() { + # shellcheck disable=SC2016 + $PERL -e 'binmode STDIN; + read(STDIN, $input, 8); + ($style, $version) = unpack("NN", $input); + exit 1 if ($style != 2 || $version > 1);' <"$1" || return $? +} + +isfull() { + # there should be no whitespace at the beginning of a line + if grep '^[ ][ ]*' "$1" >/dev/null 2>&1; then + return 1 + else + return 0 + fi +} + +rawversion() { + # shellcheck disable=SC2016 + $PERL -e 'binmode STDIN; + read(STDIN, $input, 8); + if (length($input) < 8) { print "not raw\n"; exit 0; }; + ($style, $version) = unpack("NN", $input); + print ($style == 2 || $style == 3 ? "$version\n" : + "not raw\n");' <"$1" +} + +sourceserial() { + # shellcheck disable=SC2016 + $PERL -e 'binmode STDIN; + read(STDIN, $input, 20); + if (length($input) < 20) { print "UNSET\n"; exit; }; + ($format, $version, $dumptime, $flags, $sourceserial) = + unpack("NNNNN", $input); + if ($format != 2 || $version < 1) { print "UNSET\n"; exit; }; + if ($flags & 02) { + print $sourceserial . "\n"; + } else { + print "UNSET\n"; + }' <"$1" +} + +stomp() { + # shellcheck disable=SC2016 + $PERL -e 'open(my $file, "+<", $ARGV[0]); + binmode $file; + seek($file, $ARGV[1], 0); + for (my $i = 0; $i < $ARGV[2]; $i++) { + print $file pack("C", $ARGV[3]); + } + close($file);' "$@" +} + +restart() { + sleep 1 + start_server --noclean --restart --port "${PORT}" ns3 +} + +dig_with_opts() { + "$DIG" +tcp +noauth +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${PORT}" "$@" +} + +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "$@" +} + +status=0 + +echo_i "checking that files in raw format loaded ($n)" +ret=0 +set -- 1 2 3 +for zone in example example-explicit example-compat; do + for server in "$@"; do + for qname in ns mx a aaaa cname dname txt rrsig nsec \ + dnskey ds cdnskey cds; do + qtype="$qname" + dig_with_opts @10.53.0.${server} -q ${qname}.${zone}. -t ${qtype} + echo + done >dig.out.${zone}.${server}.test${n} + for qname in private-dnskey private-cdnskey; do + qtype=$(expr "$qname" : '.*-\(.*\)') + dig_with_opts @10.53.0.${server} -q ${qname}.${zone}. -t ${qtype} + done >>dig.out.${zone}.${server}.test${n} + done + digcomp dig.out.${zone}.1.test${n} dig.out.${zone}.2.test${n} || ret=1 + if [ "$zone" = "example" ]; then + set -- 1 2 + digcomp dig.out.${zone}.1.test${n} dig.out.${zone}.3.test${n} || ret=1 + fi +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking raw format versions ($n)" +ret=0 +israw ns1/example.db.raw || ret=1 +israw ns1/example.db.raw1 || ret=1 +israw ns1/example.db.compat || ret=1 +[ "$(rawversion ns1/example.db.raw)" -eq 1 ] || ret=1 +[ "$(rawversion ns1/example.db.raw1)" -eq 1 ] || ret=1 +[ "$(rawversion ns1/example.db.compat)" -eq 0 ] || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking source serial numbers ($n)" +ret=0 +[ "$(sourceserial ns1/example.db.raw)" = "UNSET" ] || ret=1 +[ "$(sourceserial ns1/example.db.serial.raw)" = "3333" ] || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "waiting for transfers to complete" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + test -f ns2/transfer.db.raw -a -f ns2/transfer.db.txt && break + sleep 1 +done + +echo_i "checking that secondary was saved in raw format by default ($n)" +ret=0 +israw ns2/transfer.db.raw || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that secondary was saved in text format when configured ($n)" +ret=0 +israw ns2/transfer.db.txt && ret=1 +isfull ns2/transfer.db.txt && ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that secondary was saved in 'full' style when configured ($n)" +ret=0 +isfull ns2/transfer.db.full >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that secondary formerly in text format is now raw ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + israw ns2/formerly-text.db >/dev/null 2>&1 || ret=1 + [ "$(rawversion ns2/formerly-text.db)" -eq 1 ] || ret=1 + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that under-limit rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt; do + $DIG +tcp txt "${rrcount}.under-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that under-limit rdatasets transfered ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt; do + $DIG +tcp txt "${rrcount}.under-limit" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that under-limit-kasp dnskeys loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + + $DIG +tcp +dnssec dnskey "under-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.dnskey.test$n" + grep "status: NOERROR" "dig.out.ns1.dnskey.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns1.dnskey.test$n" >/dev/null || ret=1 + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that under-limit-kasp rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt; do + $DIG +tcp +dnssec txt "${rrcount}.under-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that under-limit-kasp rdatasets transfered ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt; do + $DIG +tcp +dnssec txt "${rrcount}.under-limit-kasp" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that below-limit rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do + $DIG +tcp txt "${rrcount}.below-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that below-limit rdatasets not transfered ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do + $DIG +tcp txt "${rrcount}.below-limit" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n" + grep "status: SERVFAIL" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that below-limit-kasp rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do + $DIG +tcp +dnssec txt "${rrcount}.below-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that below-limit-kasp rdatasets not transfered ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do + $DIG +tcp +dnssec txt "${rrcount}.below-limit-kasp" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n" + grep "status: SERVFAIL" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that above-limit rdatasets not loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt 2100-txt; do + $DIG +tcp txt "${rrcount}.above-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: SERVFAIL" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# Check that the corresponding log message about exceeding the limit is present. +msg="error adding '2100-txt.above-limit/TXT' in 'above-limit/IN' (zone): too many records (must not exceed 2050)" +wait_for_log 10 "$msg" ns1/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +# Prepare for any further checking of the logs later on. +nextpart ns1/named.run >/dev/null + +echo_i "checking that kasp-max-records-per-type rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrtype in soa dnskey ns; do + $DIG +tcp +dnssec $rrtype "kasp-max-records-per-type" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n" + grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that kasp-max-records-per-type-dnskey rdatasets not signed ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrtype in soa dnskey ns; do + $DIG +tcp +dnssec $rrtype "kasp-max-records-per-type-dnskey" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n" + grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null && ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that kasp-max-types-per-name rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrtype in soa dnskey ns; do + $DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n" + grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# Update zone with nsupdate. +echo_i "add new type to zone and check that it fails ($n)" +ret=0 +( + echo zone kasp-max-types-per-name. + echo server 10.53.0.4 "$PORT" + echo update add kasp-max-types-per-name. 300 TXT KAPUTT + echo send +) | $NSUPDATE && ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that kasp-max-types-per-name rdatasets loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrtype in soa dnskey ns txt; do + $DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n" + grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + grep "KAPUTT" "dig.out.ns4.$rrtype.test$n" >/dev/null && ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +# Reconfigure ns4 +echo_i "reconfigure ns4" +stop_server ns4 +copy_setports ns4/named2.conf.in ns4/named.conf +# Recompile zone +$CHECKZONE -D -F raw -o ns4/kasp.db.raw kasp-max-types-per-name ns4/template.db >/dev/null 2>&1 +start_server --noclean --restart --port "${PORT}" ns4 + +echo_i "checking that kasp-max-types-per-name rdatasets not loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrtype in soa dnskey ns; do + $DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n" + grep "status: SERVFAIL" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that 255 types are loaded ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + $DIG +tcp TXT "m.255types" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.test$n" + grep "status: NOERROR" "dig.out.ns1.test$n" >/dev/null || ret=1 + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that 255 types types are not transfered ($n)" +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + $DIG +tcp TXT "m.255types" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.test$n" + grep "status: SERVFAIL" "dig.out.ns2.test$n" >/dev/null || ret=1 + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking format transitions: text->raw->text ($n)" +ret=0 +$CHECKZONE -D -f text -F text -o baseline.txt example.nil ns1/example.db >/dev/null +$CHECKZONE -D -f text -F raw -o raw.1 example.nil baseline.txt >/dev/null +$CHECKZONE -D -f raw -F text -o text.1 example.nil raw.1 >/dev/null +cmp -s baseline.txt text.1 || ret=0 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking raw format loading with journal file rollforward ($n)" +ret=0 +$NSUPDATE </dev/null || status=1 +server 10.53.0.3 ${PORT} +ttl 600 +update add newtext.dynamic IN TXT "added text" +update delete aaaa.dynamic +send +END +dig_with_opts @10.53.0.3 newtext.dynamic txt >"dig.out.dynamic1.ns3.test$n" +grep "added text" "dig.out.dynamic1.ns3.test$n" >/dev/null 2>&1 || ret=1 +dig_with_opts +comm @10.53.0.3 added.dynamic txt >"dig.out.dynamic2.ns3.test$n" +grep "NXDOMAIN" "dig.out.dynamic2.ns3.test$n" >/dev/null 2>&1 || ret=1 +# using "rndc halt" ensures that we don't dump the zone file +stop_server --use-rndc --halt --port ${CONTROLPORT} ns3 +restart +check_added_text() { + dig_with_opts @10.53.0.3 newtext.dynamic txt >"dig.out.dynamic3.ns3.test$n" || return 1 + grep "added text" "dig.out.dynamic3.ns3.test$n" >/dev/null || return 1 + return 0 +} +retry_quiet 10 check_added_text || ret=1 +dig_with_opts +comm @10.53.0.3 added.dynamic txt >"dig.out.dynamic4.ns3.test$n" +grep "NXDOMAIN" "dig.out.dynamic4.ns3.test$n" >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking raw format file dumps correctly ($n)" +ret=0 +$NSUPDATE </dev/null || status=1 +server 10.53.0.3 ${PORT} +ttl 600 +update add moretext.dynamic IN TXT "more text" +send +END +dig_with_opts @10.53.0.3 moretext.dynamic txt >"dig.out.dynamic1.ns3.test$n" +grep "more text" "dig.out.dynamic1.ns3.test$n" >/dev/null 2>&1 || ret=1 +# using "rndc stop" will cause the zone file to flush before shutdown +stop_server --use-rndc --port ${CONTROLPORT} ns3 +rm ns3/*.jnl +restart +#shellcheck disable=SC2034 +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + lret=0 + dig_with_opts +comm @10.53.0.3 moretext.dynamic txt >"dig.out.dynamic2.ns3.test$n" + grep "more text" "dig.out.dynamic2.ns3.test$n" >/dev/null 2>&1 || lret=1 + [ $lret -eq 0 ] && break +done +[ $lret -eq 1 ] && ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking raw format zone is scheduled for resigning (compilezone) ($n)" +ret=0 +rndccmd 10.53.0.1 zonestatus signed >rndc.out 2>&1 || ret=1 +grep 'next resign' rndc.out >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking raw format zone is scheduled for resigning (signzone) ($n)" +ret=0 +rndccmd 10.53.0.1 freeze signed >rndc.out 2>&1 || ret=1 +( + cd ns1 || exit 1 + $SIGNER -S -O raw -f signed.db.raw -o signed signed.db >/dev/null +) +rndc_reload ns1 10.53.0.1 signed +rndccmd 10.53.0.1 zonestatus signed >rndc.out 2>&1 || ret=1 +grep 'next resign' rndc.out >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "checking that below-limit-kasp rdatasets loaded after re-sign and re-start ($n)" +ret=0 +stop_server ns1 +start_server --noclean --restart --port "${PORT}" ns1 + +for _attempt in 0 1 2 3 4 5 6 7 8 9; do + ret=0 + for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do + $DIG +tcp +dnssec txt "${rrcount}.below-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n" + grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1 + done + [ $ret -eq 0 ] && break + sleep 1 +done +n=$((n + 1)) +[ $ret -eq 0 ] || echo_i "failed" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/masterformat/tests_sh_masterformat.py b/bin/tests/system/masterformat/tests_sh_masterformat.py new file mode 100644 index 0000000..d8f75df --- /dev/null +++ b/bin/tests/system/masterformat/tests_sh_masterformat.py @@ -0,0 +1,46 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "baseline.txt", + "dig.out.*", + "raw.*", + "rndc.out*", + "text.*", + "ns*/*.raw*", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/*.signed", + "ns*/dsset-*", + "ns*/K*", + "ns1/255types.db", + "ns1/example.db.compat", + "ns1/below-limit-kasp.db", + "ns1/below-limit.db", + "ns1/above-limit.db", + "ns1/under-limit-kasp.db", + "ns1/under-limit.db", + "ns2/db-*", + "ns2/example.db", + "ns2/formerly-text.db", + "ns2/transfer.db.full", + "ns2/transfer.db.txt", + "ns2/under-limit-kasp.bk", + "ns2/under-limit.bk", + ] +) + + +def test_masterformat(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/metadata/child.db b/bin/tests/system/metadata/child.db new file mode 100644 index 0000000..35fff9c --- /dev/null +++ b/bin/tests/system/metadata/child.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 20 +child.parent.nil IN SOA ns.child.parent.nil. hostmaster.parent.nil. ( + 1 ; serial + 2000 ; refresh (33 minutes 20 seconds) + 2000 ; retry (33 minutes 20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns.child.parent.nil. +$ORIGIN child.parent.nil. +$TTL 300 ; 5 minutes +ns A 10.53.0.3 diff --git a/bin/tests/system/metadata/parent.db b/bin/tests/system/metadata/parent.db new file mode 100644 index 0000000..a5484e3 --- /dev/null +++ b/bin/tests/system/metadata/parent.db @@ -0,0 +1,31 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +parent.nil IN SOA ns1.parent.nil. hostmaster.parent.nil. ( + 1 ; serial + 2000 ; refresh (33 minutes 20 seconds) + 2000 ; retry (33 minutes 20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns1.parent.nil. + NS ns2.parent.nil. +$ORIGIN parent.nil. +$TTL 3600 ; 1 hour +a A 1.1.1.1 +$TTL 300 ; 5 minutes +ns1 A 10.53.0.1 +ns2 A 10.53.0.2 + +child NS ns.child +ns.child A 10.53.0.3 diff --git a/bin/tests/system/metadata/setup.sh b/bin/tests/system/metadata/setup.sh new file mode 100644 index 0000000..3998a09 --- /dev/null +++ b/bin/tests/system/metadata/setup.sh @@ -0,0 +1,59 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +pzone=parent.nil +czone=child.parent.nil + +echo_i "generating keys" + +# active zsk +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $czone) +echo $zsk >zsk.key + +# not yet published or active +pending=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P none -A none $czone) +echo $pending >pending.key + +# published but not active +standby=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A none $czone) +echo $standby >standby.key + +# inactive +inact=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now-24h -A now-24h -I now $czone) +echo $inact >inact.key + +# active ksk +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone) +echo $ksk >ksk.key + +# published but not YET active; will be active in 15 seconds +rolling=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone) +$SETTIME -A now+15s $rolling >/dev/null +echo $rolling >rolling.key + +# revoked +revoke1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone) +echo $revoke1 >prerev.key +revoke2=$($REVOKE $revoke1) +echo $revoke2 | sed -e 's#\./##' -e "s/\.key.*$//" >postrev.key + +pzsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $pzone) +echo $pzsk >parent.zsk.key + +pksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $pzone) +echo $pksk >parent.ksk.key + +oldstyle=$($KEYGEN -Cq -a ${DEFAULT_ALGORITHM} $pzone) +echo $oldstyle >oldstyle.key diff --git a/bin/tests/system/metadata/tests.sh b/bin/tests/system/metadata/tests.sh new file mode 100644 index 0000000..e945f88 --- /dev/null +++ b/bin/tests/system/metadata/tests.sh @@ -0,0 +1,233 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +pzone=parent.nil pfile=parent.db +czone=child.parent.nil cfile=child.db +status=0 +n=1 + +echo_i "setting key timers" +$SETTIME -A now+15s $(cat rolling.key) >/dev/null + +inact=$(keyfile_to_key_id "$(cat inact.key)") +ksk=$(keyfile_to_key_id "$(cat ksk.key)") +pending=$(keyfile_to_key_id "$(cat pending.key)") +postrev=$(keyfile_to_key_id "$(cat postrev.key)") +prerev=$(keyfile_to_key_id "$(cat prerev.key)") +rolling=$(keyfile_to_key_id "$(cat rolling.key)") +standby=$(keyfile_to_key_id "$(cat standby.key)") +zsk=$(keyfile_to_key_id "$(cat zsk.key)") + +echo_i "signing zones" +$SIGNER -Sg -o $czone $cfile >/dev/null +$SIGNER -Sg -o $pzone $pfile >/dev/null + +awk '$2 ~ /RRSIG/ { + type = $3; + getline; + id = $3; + if ($4 ~ /'${czone}'/) { + print type, id + } +}' <${cfile}.signed >sigs + +awk '$2 ~ /DNSKEY/ { + flags = $3; + while ($0 !~ /key id =/) + getline; + id = $NF; + print flags, id; +}' <${cfile}.signed >keys + +echo_i "checking that KSK signed DNSKEY only ($n)" +ret=0 +grep "DNSKEY $ksk"'$' sigs >/dev/null || ret=1 +grep "SOA $ksk"'$' sigs >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that ZSK signed ($n)" +ret=0 +grep "SOA $zsk"'$' sigs >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that standby ZSK did not sign ($n)" +ret=0 +grep " $standby"'$' sigs >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that inactive key did not sign ($n)" +ret=0 +grep " $inact"'$' sigs >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that pending key was not published ($n)" +ret=0 +grep " $pending"'$' keys >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that standby KSK did not sign but is delegated ($n)" +ret=0 +grep " $rolling"'$' sigs >/dev/null && ret=1 +grep " $rolling"'$' keys >/dev/null || ret=1 +grep -E "DS[ ]*$rolling[ ]" ${pfile}.signed >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that key was revoked ($n)" +ret=0 +grep " $prerev"'$' keys >/dev/null && ret=1 +grep " $postrev"'$' keys >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that revoked key self-signed ($n)" +ret=0 +grep "DNSKEY $postrev"'$' sigs >/dev/null || ret=1 +grep "SOA $postrev"'$' sigs >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "waiting 20 seconds for key changes to occur" +sleep 20 + +echo_i "re-signing zone" +$SIGNER -Sg -o $czone -f ${cfile}.new ${cfile}.signed >/dev/null + +echo_i "checking that standby KSK is now active ($n)" +ret=0 +grep "DNSKEY $rolling"'$' sigs >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking update of an old-style key ($n)" +ret=0 +# printing metadata should not work with an old-style key +$SETTIME -pall $(cat oldstyle.key) >/dev/null 2>&1 && ret=1 +$SETTIME -f $(cat oldstyle.key) >/dev/null 2>&1 || ret=1 +# but now it should +$SETTIME -pall $(cat oldstyle.key) >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking warning about permissions change on key with dnssec-settime ($n)" +ret=0 +# settime should print a warning about changing the permissions +chmod 644 $(cat oldstyle.key).private +$SETTIME -P none $(cat oldstyle.key) >settime1.test$n 2>&1 || ret=1 +grep "warning: Permissions on the file.*have changed" settime1.test$n >/dev/null 2>&1 || ret=1 +$SETTIME -P none $(cat oldstyle.key) >settime2.test$n 2>&1 || ret=1 +grep "warning: Permissions on the file.*have changed" settime2.test$n >/dev/null 2>&1 && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking warning about delete date < inactive date with dnssec-settime ($n)" +ret=0 +# settime should print a warning about delete < inactive +$SETTIME -I now+15s -D now $(cat oldstyle.key) >tmp.out 2>&1 || ret=1 +grep "warning" tmp.out >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking no warning about delete date < inactive date with dnssec-settime when delete date is unset ($n)" +ret=0 +$SETTIME -D none $(cat oldstyle.key) >tmp.out 2>&1 || ret=1 +$SETTIME -p all $(cat oldstyle.key) >tmp.out 2>&1 || ret=1 +grep "warning" tmp.out >/dev/null 2>&1 && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking warning about delete date < inactive date with dnssec-keygen ($n)" +ret=0 +# keygen should print a warning about delete < inactive +$KEYGEN -q -a ${DEFAULT_ALGORITHM} -I now+15s -D now $czone >tmp.out 2>&1 || ret=1 +grep "warning" tmp.out >/dev/null 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking correct behavior setting activation without publication date ($n)" +ret=0 +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w $czone) +pub=$($SETTIME -upP $key | awk '{print $2}') +act=$($SETTIME -upA $key | awk '{print $2}') +[ $pub -eq $act ] || ret=1 +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w -i 1d $czone) +pub=$($SETTIME -upP $key | awk '{print $2}') +act=$($SETTIME -upA $key | awk '{print $2}') +[ $pub -lt $act ] || ret=1 +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A +1w -P never $czone) +pub=$($SETTIME -upP $key | awk '{print $2}') +[ $pub = "UNSET" ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking calculation of dates for a successor key ($n)" +ret=0 +oldkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $czone) +newkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $czone) +$SETTIME -A -2d -I +2d $oldkey >settime1.test$n 2>&1 || ret=1 +$SETTIME -i 1d -S $oldkey $newkey >settime2.test$n 2>&1 || ret=1 +$SETTIME -pA $newkey | grep "1970" >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $czone) + +echo_i "checking -p output time is accepted ($n)" +t=$($SETTIME -pA $key | sed 's/.*: //') +$SETTIME -Psync "$t" $key >settime2.test$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking -up output time is accepted ($n)" +t=$($SETTIME -upA $key | sed 's/.*: //') +$SETTIME -Dsync "$t" $key >settime2.test$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking -p unset time is accepted ($n)" +# The Delete timing metadata is unset. +t=$($SETTIME -pD $key | sed 's/.*: //') +$SETTIME -Psync "$t" $key >settime2.test$n 2>&1 || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/metadata/tests_sh_metadata.py b/bin/tests/system/metadata/tests_sh_metadata.py new file mode 100644 index 0000000..accfae2 --- /dev/null +++ b/bin/tests/system/metadata/tests_sh_metadata.py @@ -0,0 +1,40 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "*.new", + "*.signed", + "K*", + "dsset-*", + "inact.key", + "keys", + "ksk.key", + "oldstyle.key", + "parent.ksk.key", + "parent.zsk.key", + "pending.key", + "postrev.key", + "prerev.key", + "rolling.key", + "settime*.test*", + "sigs", + "standby.key", + "tmp.out", + "zsk.key", + ] +) + + +def test_metadata(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/mirror/README b/bin/tests/system/mirror/README new file mode 100644 index 0000000..f76b41b --- /dev/null +++ b/bin/tests/system/mirror/README @@ -0,0 +1,26 @@ + + +This test checks whether zones configured with "type mirror;" behave as +expected. + +ns1 is an authoritative-only server. It only serves the root zone, which is +mirrored by ns3. + +ns2 is an authoritative-only server. It serves a number of zones, some of which +are delegated to it by ns1 and used in recursive resolution tests aimed at ns3 +while others are only served so that ns3 has a primary server to mirror zones +from during various tests of the mirror zone implementation. + +ns3 is a recursive resolver. It has a number of mirror zones configured. This +is the only server whose behavior is being examined by this system test. diff --git a/bin/tests/system/mirror/ns1/named.conf.in b/bin/tests/system/mirror/ns1/named.conf.in new file mode 100644 index 0000000..32f6d2e --- /dev/null +++ b/bin/tests/system/mirror/ns1/named.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; diff --git a/bin/tests/system/mirror/ns1/root.db.in b/bin/tests/system/mirror/ns1/root.db.in new file mode 100644 index 0000000..98ecf1f --- /dev/null +++ b/bin/tests/system/mirror/ns1/root.db.in @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA a.root-servers.nil. hostmaster 1 3600 1200 604800 3600 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +example NS ns2.example. +ns2.example. A 10.53.0.2 +initially-unavailable. NS ns2.initially-unavailable. +ns2.initially-unavailable. A 10.53.0.2 diff --git a/bin/tests/system/mirror/ns1/sign.sh b/bin/tests/system/mirror/ns1/sign.sh new file mode 100644 index 0000000..4337500 --- /dev/null +++ b/bin/tests/system/mirror/ns1/sign.sh @@ -0,0 +1,37 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +(cd ../ns2 && $SHELL -e sign.sh) + +cp ../ns2/dsset-* . + +zone=. +infile=root.db.in +zonefile=root.db + +keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2>/dev/null) +keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2>/dev/null) + +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +# Add a trust anchor for a name whose non-existence can be securely proved +# without recursing when the root zone is mirrored. This will exercise code +# attempting to send TAT queries for such names (in ns3). Key data is +# irrelevant here, so just reuse the root zone key generated above. +sed "s/^\./nonexistent./;" $keyname1.key >$keyname1.modified.key + +keyfile_to_static_ds $keyname1 $keyname1.modified >trusted.conf diff --git a/bin/tests/system/mirror/ns2/example.db.in b/bin/tests/system/mirror/ns2/example.db.in new file mode 100644 index 0000000..5472399 --- /dev/null +++ b/bin/tests/system/mirror/ns2/example.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2 hostmaster 1 3600 1200 604800 3600 +@ NS ns2 +ns2 A 10.53.0.2 +foo A 127.0.0.1 +sub NS ns2 diff --git a/bin/tests/system/mirror/ns2/initially-unavailable.db.in b/bin/tests/system/mirror/ns2/initially-unavailable.db.in new file mode 100644 index 0000000..cf809e3 --- /dev/null +++ b/bin/tests/system/mirror/ns2/initially-unavailable.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA a.root-servers.nil. hostmaster 1 3600 1200 604800 3600 +@ NS ns2 +ns2 A 10.53.0.2 +foo CNAME foo.example. diff --git a/bin/tests/system/mirror/ns2/named.conf.in b/bin/tests/system/mirror/ns2/named.conf.in new file mode 100644 index 0000000..57261bf --- /dev/null +++ b/bin/tests/system/mirror/ns2/named.conf.in @@ -0,0 +1,87 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +zone "example" { + type primary; + file "example.db.signed"; +}; + +zone "sub.example" { + type primary; + file "sub.example.db.signed"; +}; + +zone "initially-unavailable" { + type primary; + file "initially-unavailable.db.signed"; + allow-transfer { 10.53.0.254; }; +}; + +zone "verify-addzone" { + type primary; + file "verify-addzone.db.original.signed"; +}; + +zone "verify-axfr" { + type primary; + file "verify-axfr.db.signed"; +}; + +zone "verify-csk" { + type primary; + file "verify-csk.db.signed"; +}; + +zone "verify-ixfr" { + type primary; + file "verify-ixfr.db.signed"; + ixfr-from-differences yes; + allow-transfer { 10.53.0.3; }; +}; + +zone "verify-reconfig" { + type primary; + file "verify-reconfig.db.signed"; +}; + +zone "verify-unsigned" { + type primary; + file "verify.db.in"; +}; + +zone "verify-untrusted" { + type primary; + file "verify-untrusted.db.signed"; +}; diff --git a/bin/tests/system/mirror/ns2/sign.sh b/bin/tests/system/mirror/ns2/sign.sh new file mode 100644 index 0000000..2cd449b --- /dev/null +++ b/bin/tests/system/mirror/ns2/sign.sh @@ -0,0 +1,79 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +keys_to_trust="" + +for zonename in sub.example example initially-unavailable; do + zone=$zonename + infile=$zonename.db.in + zonefile=$zonename.db + + keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2>/dev/null) + keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2>/dev/null) + + cat $infile $keyname1.key $keyname2.key >$zonefile + + $SIGNER -P -g -o $zone $zonefile >/dev/null +done + +# Only add the key for "initially-unavailable" to the list of keys trusted by +# ns3. "example" is expected to be validated using a chain of trust starting in +# the "root" zone on ns1. +keys_to_trust="$keys_to_trust $keyname1" + +# Prepare a zone signed using a Combined Signing Key (CSK) without the SEP bit +# set and add that key to the list of keys to trust. +zone=verify-csk +infile=verify.db.in +zonefile=verify-csk.db + +keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2>/dev/null) +cat $infile $keyname.key >$zonefile +$SIGNER -P -o $zone $zonefile >/dev/null +keys_to_trust="$keys_to_trust $keyname" + +# Prepare remaining zones used in the test. +ORIGINAL_SERIAL=$(awk '$2 == "SOA" {print $5}' verify.db.in) +UPDATED_SERIAL_BAD=$((ORIGINAL_SERIAL + 1)) +UPDATED_SERIAL_GOOD=$((ORIGINAL_SERIAL + 2)) + +for variant in addzone axfr ixfr load reconfig untrusted; do + zone=verify-$variant + infile=verify.db.in + zonefile=verify-$variant.db + + keyname1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -f KSK $zone 2>/dev/null) + keyname2=$($KEYGEN -a ${DEFAULT_ALGORITHM} $zone 2>/dev/null) + + cat $infile $keyname1.key $keyname2.key >$zonefile + + # Prepare a properly signed version of the zone ("*.original.signed"). + $SIGNER -P -o $zone $zonefile >/dev/null + cp $zonefile.signed $zonefile.original.signed + # Prepare a version of the zone with a bogus SOA RRSIG ("*.bad.signed"). + sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_BAD}/;" $zonefile.signed >$zonefile.bad.signed + # Prepare another properly signed version of the zone ("*.good.signed"). + sed "s/${ORIGINAL_SERIAL}/${UPDATED_SERIAL_GOOD}/;" $zonefile >$zonefile.good + $SIGNER -P -o $zone $zonefile.good >/dev/null + rm -f $zonefile.good + + # Except for the "verify-untrusted" zone, declare the KSK used for + # signing the zone to be a trust anchor for ns3. + if [ "$variant" != "untrusted" ]; then + keys_to_trust="$keys_to_trust $keyname1" + fi +done + +keyfile_to_static_ds $keys_to_trust >trusted-mirror.conf diff --git a/bin/tests/system/mirror/ns2/sub.example.db.in b/bin/tests/system/mirror/ns2/sub.example.db.in new file mode 100644 index 0000000..d2c15c7 --- /dev/null +++ b/bin/tests/system/mirror/ns2/sub.example.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2.example. hostmaster 1 3600 1200 604800 3600 +@ NS ns2.example. +foo A 127.0.0.1 diff --git a/bin/tests/system/mirror/ns2/verify.db.in b/bin/tests/system/mirror/ns2/verify.db.in new file mode 100644 index 0000000..b3ed22a --- /dev/null +++ b/bin/tests/system/mirror/ns2/verify.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns2 hostmaster 2000010100 3600 1200 604800 3600 +@ NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/mirror/ns3/named.args b/bin/tests/system/mirror/ns3/named.args new file mode 100644 index 0000000..e5ebb6c --- /dev/null +++ b/bin/tests/system/mirror/ns3/named.args @@ -0,0 +1 @@ +-D mirror-ns3 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -T tat=3 diff --git a/bin/tests/system/mirror/ns3/named.conf.in b/bin/tests/system/mirror/ns3/named.conf.in new file mode 100644 index 0000000..3d494df --- /dev/null +++ b/bin/tests/system/mirror/ns3/named.conf.in @@ -0,0 +1,101 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + allow-query-cache { 10.53.0.1; }; + trust-anchor-telemetry yes; + allow-new-zones yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "." { + type mirror; + primaries { 10.53.0.1; }; + file "root.db.mirror"; +}; + +zone "initially-unavailable" { + type mirror; + primaries { 10.53.0.2; }; + file "initially-unavailable.db.mirror"; +}; + +zone "verify-axfr" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-axfr.db.mirror"; +}; + +zone "verify-csk" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-csk.db.mirror"; +}; + +zone "verify-ixfr" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-ixfr.db.mirror"; + masterfile-format text; +}; + +zone "verify-load" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-load.db.mirror"; + masterfile-format text; +}; + +zone "verify-reconfig" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-reconfig.db.mirror"; + masterfile-format text; +}; + +zone "verify-unsigned" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-unsigned.db.mirror"; +}; + +zone "verify-untrusted" { + type mirror; + primaries { 10.53.0.2; }; + file "verify-untrusted.db.mirror"; +}; + +include "../ns1/trusted.conf"; +include "../ns2/trusted-mirror.conf"; diff --git a/bin/tests/system/mirror/setup.sh b/bin/tests/system/mirror/setup.sh new file mode 100644 index 0000000..134c4ad --- /dev/null +++ b/bin/tests/system/mirror/setup.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf + +(cd ns1 && $SHELL -e sign.sh) + +cat ns2/verify-axfr.db.bad.signed >ns2/verify-axfr.db.signed +cat ns2/verify-load.db.bad.signed >ns3/verify-load.db.mirror diff --git a/bin/tests/system/mirror/tests.sh b/bin/tests/system/mirror/tests.sh new file mode 100644 index 0000000..77a88f5 --- /dev/null +++ b/bin/tests/system/mirror/tests.sh @@ -0,0 +1,558 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT} -b 10.53.0.1 +dnssec +time=2 +tries=1 +multi" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +# Wait until the transfer of the given zone to ns3 either completes +# successfully or is aborted by a verification failure or a REFUSED response +# from the primary. Note that matching on any transfer status is deliberately +# avoided because some checks performed by this test cause transfer attempts to +# end with the "IXFR failed" status, which is followed by an AXFR retry and +# this test needs to check what the result of the latter transfer attempt is. +wait_for_transfer() { + zone=$1 + for i in 1 2 3 4 5 6 7 8 9 10; do + # Wait until a "freeing transfer context" message is logged + # after one of the transfer results we are looking for is + # logged. This is needed to prevent races when checking for + # "mirror zone is now in use" messages. + nextpartpeek ns3/named.run \ + | awk "matched; /'$zone\/IN'.*Transfer status: (success|verify failure|REFUSED)/ {matched=1}" \ + | grep "'$zone/IN'.*freeing transfer context" >/dev/null && return + sleep 1 + done + echo_i "exceeded time limit waiting for proof of '$zone' being transferred to appear in ns3/named.run" + ret=1 +} + +# Wait until loading the given zone on the given server either completes +# successfully for the specified serial number or fails. +wait_for_load() { + zone=$1 + serial=$2 + log=$3 + for i in 1 2 3 4 5 6 7 8 9 10; do + # Wait until a "zone_postload: (...): done" message is logged + # after one of the loading-related messages we are looking for + # is logged. This is needed to prevent races when checking for + # "mirror zone is now in use" messages. + nextpartpeek $log \ + | awk "matched; /$zone.*(loaded serial $serial|unable to load)/ {matched=1}" \ + | grep "zone_postload: zone $zone/IN: done" >/dev/null && return + sleep 1 + done + echo_i "exceeded time limit waiting for proof of '$zone' being loaded to appear in $log" + ret=1 +} + +# Trigger a reload of ns2 and wait until loading the given zone completes. +reload_zone() { + zone=$1 + serial=$2 + rndc_reload ns2 10.53.0.2 + wait_for_load $zone $serial ns2/named.run +} + +status=0 +n=0 + +ORIGINAL_SERIAL=$(awk '$2 == "SOA" {print $5}' ns2/verify.db.in) +UPDATED_SERIAL_BAD=$((ORIGINAL_SERIAL + 1)) +UPDATED_SERIAL_GOOD=$((ORIGINAL_SERIAL + 2)) + +n=$((n + 1)) +echo_i "checking that an unsigned mirror zone is rejected ($n)" +ret=0 +wait_for_transfer verify-unsigned +$DIG $DIGOPTS @10.53.0.3 +norec verify-unsigned SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "verify-unsigned.*Zone contains no DNSSEC keys" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-unsigned.*mirror zone is now in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a mirror zone signed using an untrusted key is rejected ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_transfer verify-untrusted +$DIG $DIGOPTS @10.53.0.3 +norec verify-untrusted SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "verify-untrusted.*No trusted DNSKEY found" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-untrusted.*mirror zone is now in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a mirror zone signed using a CSK without the SEP bit set is accepted ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_transfer verify-csk +$DIG $DIGOPTS @10.53.0.3 +norec verify-csk SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${ORIGINAL_SERIAL}.*; serial" dig.out.ns3.test$n >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-csk.*mirror zone is now in use" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that an AXFR of an incorrectly signed mirror zone is rejected ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_transfer verify-axfr +$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-axfr SOA" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that an AXFR of an updated, correctly signed mirror zone is accepted ($n)" +ret=0 +nextpart ns3/named.run >/dev/null +cat ns2/verify-axfr.db.good.signed >ns2/verify-axfr.db.signed +reload_zone verify-axfr ${UPDATED_SERIAL_GOOD} +$RNDCCMD 10.53.0.3 retransfer verify-axfr >/dev/null 2>&1 +wait_for_transfer verify-axfr +$DIG $DIGOPTS @10.53.0.3 +norec verify-axfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-axfr.*mirror zone is now in use" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that an IXFR of an incorrectly signed mirror zone is rejected ($n)" +nextpartreset ns3/named.run +ret=0 +wait_for_transfer verify-ixfr +# Sanity check: the initial, properly signed version of the zone should have +# been announced as coming into effect. +nextpart ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" >/dev/null || ret=1 +# Make a copy of the original zone file for reuse in journal tests below. +cp ns2/verify-ixfr.db.signed ns3/verify-journal.db.mirror +# Wait 1 second so that the zone file timestamp changes and the subsequent +# invocation of "rndc reload" triggers a zone reload. +sleep 1 +cat ns2/verify-ixfr.db.bad.signed >ns2/verify-ixfr.db.signed +reload_zone verify-ixfr ${UPDATED_SERIAL_BAD} +# Make a copy of the bad zone journal for reuse in journal tests below. +cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.bad.mirror.jnl +# Trigger IXFR. +$RNDCCMD 10.53.0.3 refresh verify-ixfr >/dev/null 2>&1 +wait_for_transfer verify-ixfr +# Ensure the transfer was incremental as expected. +if [ $(nextpartpeek ns3/named.run | grep "verify-ixfr.*got incremental response" | wc -l) -eq 0 ]; then + echo_i "failed: did not get an incremental response" + ret=1 +fi +# Ensure the new, bad version of the zone was not accepted. +$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +# A positive answer is expected as the original version of the "verify-ixfr" +# zone should have been successfully verified. +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-ixfr SOA" >/dev/null || ret=1 +# Despite the verification failure for this IXFR, this mirror zone should still +# be in use as its previous version should have been verified successfully. +nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is no longer in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that an IXFR of an updated, correctly signed mirror zone is accepted after AXFR failover ($n)" +ret=0 +nextpart ns3/named.run >/dev/null +# Wait 1 second so that the zone file timestamp changes and the subsequent +# invocation of "rndc reload" triggers a zone reload. +sleep 1 +cat ns2/verify-ixfr.db.good.signed >ns2/verify-ixfr.db.signed +reload_zone verify-ixfr ${UPDATED_SERIAL_GOOD} +# Make a copy of the good zone journal for reuse in journal tests below. +cp ns2/verify-ixfr.db.signed.jnl ns3/verify-journal.db.good.mirror.jnl +# Trigger IXFR. +$RNDCCMD 10.53.0.3 refresh verify-ixfr >/dev/null 2>&1 +wait_for_transfer verify-ixfr +# Ensure the new, good version of the zone was accepted. +$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n >/dev/null || ret=1 +# The log message announcing the mirror zone coming into effect should not have +# been logged this time since the mirror zone in question is expected to +# already be in use before this test case is checked. +nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that loading an incorrectly signed mirror zone from disk fails ($n)" +ret=0 +nextpartreset ns3/named.run +wait_for_load verify-load ${UPDATED_SERIAL_BAD} ns3/named.run +$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-load SOA" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "ensuring trust anchor telemetry queries are sent upstream for a mirror zone ($n)" +ret=0 +# ns3 is started with "-T tat=3", so TAT queries should have already been sent. +wait_for_log_re 3 "_ta-[-0-9a-f]*/NULL" ns1/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that loading a correctly signed mirror zone from disk succeeds ($n)" +ret=0 +stop_server --use-rndc --port ${CONTROLPORT} ns3 +cat ns2/verify-load.db.good.signed >ns3/verify-load.db.mirror +nextpart ns3/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns3 +wait_for_load verify-load ${UPDATED_SERIAL_GOOD} ns3/named.run +$DIG $DIGOPTS @10.53.0.3 +norec verify-load SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-load.*mirror zone is now in use" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that loading a journal for an incorrectly signed mirror zone fails ($n)" +ret=0 +stop_server --use-rndc --port ${CONTROLPORT} ns3 +cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror +cp ns3/verify-journal.db.bad.mirror.jnl ns3/verify-ixfr.db.mirror.jnl +# Temporarily disable transfers of the "verify-ixfr" zone on ns2. This is +# required to reliably test whether the message announcing the mirror zone +# coming into effect is not logged after a failed journal verification since +# otherwise a corrected version of the zone may be transferred after +# verification fails but before we look for the aforementioned log message. +# (NOTE: Keep the embedded newline in the sed function list below.) +sed '/^zone "verify-ixfr" {$/,/^};$/ { + s/10.53.0.3/10.53.0.254/ +}' ns2/named.conf >ns2/named.conf.modified +mv ns2/named.conf.modified ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +nextpart ns3/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns3 +wait_for_load verify-ixfr ${UPDATED_SERIAL_BAD} ns3/named.run +$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpartpeek ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-ixfr SOA" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" >/dev/null && ret=1 +# Restore transfers for the "verify-ixfr" zone on ns2. +# (NOTE: Keep the embedded newline in the sed function list below.) +sed '/^zone "verify-ixfr" {$/,/^};$/ { + s/10.53.0.254/10.53.0.3/ +}' ns2/named.conf >ns2/named.conf.modified +mv ns2/named.conf.modified ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that loading a journal for a correctly signed mirror zone succeeds ($n)" +ret=0 +stop_server --use-rndc --port ${CONTROLPORT} ns3 +cp ns3/verify-journal.db.mirror ns3/verify-ixfr.db.mirror +cp ns3/verify-journal.db.good.mirror.jnl ns3/verify-ixfr.db.mirror.jnl +nextpart ns3/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns3 +wait_for_load verify-ixfr ${UPDATED_SERIAL_GOOD} ns3/named.run +$DIG $DIGOPTS @10.53.0.3 +norec verify-ixfr SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "${UPDATED_SERIAL_GOOD}.*; serial" dig.out.ns3.test$n >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "verify-ixfr.*mirror zone is now in use" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking delegations sourced from a mirror zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 foo.example A +norec >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null && ret=1 +# Check that a delegation containing a DS RRset and glue is present. +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null || ret=1 +grep "example.*IN.*NS" dig.out.ns3.test$n >/dev/null || ret=1 +grep "example.*IN.*DS" dig.out.ns3.test$n >/dev/null || ret=1 +grep "ns2.example.*A.*10.53.0.2" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that resolution involving a mirror zone works as expected ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 foo.example A >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +# Ensure ns1 was not queried. +grep "query 'foo.example/A/IN'" ns1/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that non-recursive queries for names below mirror zone get responded from cache ($n)" +ret=0 +# Issue a non-recursive query for an RRset which is expected to be in cache. +$DIG $DIGOPTS @10.53.0.3 +norec foo.example. A >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +# Ensure the response is not a delegation. +grep "ANSWER: 0" dig.out.ns3.test$n >/dev/null && ret=1 +grep "foo.example.*IN.*A.*127.0.0.1" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that delegations from cache which improve mirror zone delegations are properly handled ($n)" +ret=0 +# First, issue a recursive query in order to cache an RRset which is not within +# the mirror zone's bailiwick. +$DIG $DIGOPTS @10.53.0.3 sub.example. NS >dig.out.ns3.test$n.1 2>&1 || ret=1 +# Ensure the child-side NS RRset is returned. +grep "NOERROR" dig.out.ns3.test$n.1 >/dev/null || ret=1 +grep "ANSWER: 2" dig.out.ns3.test$n.1 >/dev/null || ret=1 +grep "sub.example.*IN.*NS" dig.out.ns3.test$n.1 >/dev/null || ret=1 +# Issue a non-recursive query for something below the cached zone cut. +$DIG $DIGOPTS @10.53.0.3 +norec foo.sub.example. A >dig.out.ns3.test$n.2 2>&1 || ret=1 +# Ensure the cached NS RRset is returned in a delegation, along with the +# parent-side DS RRset. +grep "NOERROR" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "ANSWER: 0" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "sub.example.*IN.*NS" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "sub.example.*IN.*DS" dig.out.ns3.test$n.2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking flags set in a DNSKEY response sourced from a mirror zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 . DNSKEY >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking flags set in a SOA response sourced from a mirror zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 . SOA >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that resolution succeeds with unavailable mirror zone data ($n)" +ret=0 +wait_for_transfer initially-unavailable +# Query for a record in a zone that is set up to be mirrored, but +# untransferrable from the configured primary. Resolution should still succeed. +$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A >dig.out.ns3.test$n.1 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n.1 >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.1 >/dev/null || ret=1 +# Sanity check: the authoritative server should have been queried. +nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null || ret=1 +# Reconfigure ns2 so that the zone can be mirrored on ns3. +sed '/^zone "initially-unavailable" {$/,/^};$/ { + s/10.53.0.254/10.53.0.3/ +}' ns2/named.conf >ns2/named.conf.modified +mv ns2/named.conf.modified ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +# Flush the cache on ns3 and retransfer the mirror zone. +$RNDCCMD 10.53.0.3 flush >/dev/null 2>&1 +nextpart ns3/named.run >/dev/null +$RNDCCMD 10.53.0.3 retransfer initially-unavailable >/dev/null 2>&1 +wait_for_transfer initially-unavailable +# Query for the same record again. Resolution should still succeed. +$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A >dig.out.ns3.test$n.2 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.2 >/dev/null || ret=1 +# Ensure the authoritative server was not queried. +nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that resolution succeeds with expired mirror zone data ($n)" +ret=0 +# Reconfigure ns2 so that the zone from the previous test can no longer be +# mirrored on ns3. +sed '/^zone "initially-unavailable" {$/,/^};$/ { + s/10.53.0.3/10.53.0.254/ +}' ns2/named.conf >ns2/named.conf.modified +mv ns2/named.conf.modified ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +# Stop ns3, update the timestamp of the zone file to one far in the past, then +# restart ns3. +stop_server --use-rndc --port ${CONTROLPORT} ns3 +touch -t 200001010000 ns3/initially-unavailable.db.mirror +nextpart ns3/named.run >/dev/null +start_server --noclean --restart --port ${PORT} ns3 +# Ensure named attempts to retransfer the zone due to its expiry. +wait_for_transfer initially-unavailable +# Ensure the expected messages were logged. +nextpartpeek ns3/named.run | grep "initially-unavailable.*expired" >/dev/null || ret=1 +nextpartpeek ns3/named.run | grep "initially-unavailable.*mirror zone is no longer in use" >/dev/null || ret=1 +# Query for a record in the expired zone. Resolution should still succeed. +$DIG $DIGOPTS @10.53.0.3 foo.initially-unavailable. A >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +# Sanity check: the authoritative server should have been queried. +nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that clients without cache access cannot retrieve mirror zone data ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 -b 10.53.0.3 +norec . SOA >dig.out.ns3.test$n 2>&1 || ret=1 +# Check response code and flags in the answer. +grep "REFUSED" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that outgoing transfers of mirror zones are disabled by default ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.3 . AXFR >dig.out.ns3.test$n 2>&1 || ret=1 +grep "; Transfer failed" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that notifies are disabled by default for mirror zones ($n)" +ret=0 +grep "initially-unavailable.*sending notifies" ns3/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking output of \"rndc zonestatus\" for a mirror zone ($n)" +ret=0 +$RNDCCMD 10.53.0.3 zonestatus . >rndc.out.ns3.test$n 2>&1 +grep "type: mirror" rndc.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that \"rndc reconfig\" properly handles a mirror -> secondary zone type change ($n)" +ret=0 +# Sanity check before we start. +$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA >dig.out.ns3.test$n.1 2>&1 || ret=1 +grep "NOERROR" dig.out.ns3.test$n.1 >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.1 >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.1 >/dev/null || ret=1 +# Reconfigure the zone so that it is no longer a mirror zone. +# (NOTE: Keep the embedded newline in the sed function list below.) +sed '/^zone "verify-reconfig" {$/,/^};$/ { + s/type mirror;/type secondary;/ +}' ns3/named.conf >ns3/named.conf.modified +mv ns3/named.conf.modified ns3/named.conf +nextpart ns3/named.run >/dev/null +rndc_reconfig ns3 10.53.0.3 +# Zones whose type was changed should not be reusable, which means the tested +# zone should have been reloaded from disk. +wait_for_load verify-reconfig ${ORIGINAL_SERIAL} ns3/named.run +# Ensure responses sourced from the reconfigured zone have AA=1 and AD=0. +$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA >dig.out.ns3.test$n.2 2>&1 || ret=1 +grep "NOERROR" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.2 >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that \"rndc reconfig\" properly handles a secondary -> mirror zone type change ($n)" +ret=0 +# Put an incorrectly signed version of the zone in the zone file used by ns3. +nextpart ns3/named.run >/dev/null +cat ns2/verify-reconfig.db.bad.signed >ns3/verify-reconfig.db.mirror +# Reconfigure the zone so that it is a mirror zone again. +# (NOTE: Keep the embedded newline in the sed function list below.) +sed '/^zone "verify-reconfig" {$/,/^};$/ { + s/type secondary;/type mirror;/ +}' ns3/named.conf >ns3/named.conf.modified +mv ns3/named.conf.modified ns3/named.conf +rndc_reconfig ns3 10.53.0.3 +# The reconfigured zone should fail verification. +wait_for_load verify-reconfig ${UPDATED_SERIAL_BAD} ns3/named.run +$DIG $DIGOPTS @10.53.0.3 +norec verify-reconfig SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "${UPDATED_SERIAL_BAD}.*; serial" dig.out.ns3.test$n >/dev/null && ret=1 +nextpart ns3/named.run | grep "No correct ${DEFAULT_ALGORITHM} signature for verify-reconfig SOA" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a mirror zone can be added using rndc ($n)" +ret=0 +# Sanity check: the zone should not exist in the root zone. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA >dig.out.ns3.test$n.1 2>&1 || ret=1 +grep "NXDOMAIN" dig.out.ns3.test$n.1 >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.1 >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.1 >/dev/null || ret=1 +# Mirror a zone which does not exist in the root zone. +nextpart ns3/named.run >/dev/null +$RNDCCMD 10.53.0.3 addzone verify-addzone '{ type mirror; primaries { 10.53.0.2; }; };' >rndc.out.ns3.test$n 2>&1 || ret=1 +wait_for_transfer verify-addzone +# Check whether the mirror zone was added and whether it behaves as expected. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA >dig.out.ns3.test$n.2 2>&1 || ret=1 +grep "NOERROR" dig.out.ns3.test$n.2 >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n.2 >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n.2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that a mirror zone can be deleted using rndc ($n)" +ret=0 +# Remove the mirror zone added in the previous test. +nextpart ns3/named.run >/dev/null +$RNDCCMD 10.53.0.3 delzone verify-addzone >rndc.out.ns3.test$n 2>&1 || ret=1 +wait_for_log 20 "zone verify-addzone/IN: mirror zone is no longer in use; reverting to normal recursion" ns3/named.run || ret=1 +# Check whether the mirror zone was removed. +$DIG $DIGOPTS @10.53.0.3 +norec verify-addzone SOA >dig.out.ns3.test$n 2>&1 || ret=1 +grep "NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +grep "flags:.* aa" dig.out.ns3.test$n >/dev/null && ret=1 +grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/mirror/tests_sh_mirror.py b/bin/tests/system/mirror/tests_sh_mirror.py new file mode 100644 index 0000000..5aefe67 --- /dev/null +++ b/bin/tests/system/mirror/tests_sh_mirror.py @@ -0,0 +1,34 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "ns*/db-*", + "ns*/dsset-*", + "ns*/jn-*", + "ns*/K*", + "ns*/*.conf", + "ns*/*.db", + "ns*/*.jnl", + "ns*/*.mirror", + "ns*/*.nzf*", + "ns*/*.nzd*", + "ns*/*.signed", + ] +) + + +def test_mirror(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/mkeys/README b/bin/tests/system/mkeys/README new file mode 100644 index 0000000..25637bf --- /dev/null +++ b/bin/tests/system/mkeys/README @@ -0,0 +1,34 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +This is for testing RFC 5011 Automated Updates of DNSSEC Trust Anchors. + +ns1 is the root server that offers new KSKs and hosts one record for +testing. The TTL for the zone's records is 2 seconds. + +ns2 is a validator that uses managed keys. "-T mkeytimers=2/20/40" +is used so it will attempt do automated updates frequently. "-T tat=1" +is used so it will send TAT queries once per second. + +ns3 is a validator with a broken initializing key in trust-anchors. + +ns4 is a validator with a deliberately broken managed-keys.bind and +managed-keys.jnl, causing RFC 5011 initialization to fail. + +ns5 is a validator which is prevented from getting a response from the +root server, causing key refresh queries to fail. + +ns6 is a validator which has unsupported algorithms, one at start up, +one because of an algorithm rollover. + +ns7 is a validator with multiple views configured. It is used for +testing per-view rndc commands and checking interactions between options +related to and potentially affecting RFC 5011 processing. diff --git a/bin/tests/system/mkeys/ns1/named1.conf.in b/bin/tests/system/mkeys/ns1/named1.conf.in new file mode 100644 index 0000000..d45e98d --- /dev/null +++ b/bin/tests/system/mkeys/ns1/named1.conf.in @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +acl allowed { + ! 10.53.0.5; + any; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation yes; + allow-query { allowed; }; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +zone "tld" { + type primary; + file "tld.db.signed"; +}; + +zone "sub.tld" { + type primary; + file "sub.tld.db.signed"; +}; diff --git a/bin/tests/system/mkeys/ns1/named2.conf.in b/bin/tests/system/mkeys/ns1/named2.conf.in new file mode 100644 index 0000000..d45e98d --- /dev/null +++ b/bin/tests/system/mkeys/ns1/named2.conf.in @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +acl allowed { + ! 10.53.0.5; + any; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation yes; + allow-query { allowed; }; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +zone "tld" { + type primary; + file "tld.db.signed"; +}; + +zone "sub.tld" { + type primary; + file "sub.tld.db.signed"; +}; diff --git a/bin/tests/system/mkeys/ns1/named3.conf.in b/bin/tests/system/mkeys/ns1/named3.conf.in new file mode 100644 index 0000000..12b8c71 --- /dev/null +++ b/bin/tests/system/mkeys/ns1/named3.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +zone "tld" { + type primary; + file "tld.db.signed"; +}; + +zone "sub.tld" { + type primary; + file "sub.tld.db.signed"; +}; diff --git a/bin/tests/system/mkeys/ns1/root.db b/bin/tests/system/mkeys/ns1/root.db new file mode 100644 index 0000000..333ee45 --- /dev/null +++ b/bin/tests/system/mkeys/ns1/root.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 1 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +; no delegation + +example. TXT "This is a test." + +tld. NS ns.tld. +ns.tld. A 10.53.0.1 diff --git a/bin/tests/system/mkeys/ns1/sign.sh b/bin/tests/system/mkeys/ns1/sign.sh new file mode 100644 index 0000000..e41cca4 --- /dev/null +++ b/bin/tests/system/mkeys/ns1/sign.sh @@ -0,0 +1,93 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=sub.tld +zonefile=sub.tld.db + +keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone) +zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone) + +$SIGNER -Sg -o $zone $zonefile >/dev/null 2>/dev/null +keyfile_to_initial_ds $keyname >island.conf +cp island.conf ../ns5/island.conf + +zone=tld +zonefile=tld.db + +keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone) +zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone) + +$SIGNER -Sg -o $zone $zonefile >/dev/null 2>/dev/null + +zone=. +zonefile=root.db + +keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone) +zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone) + +$SIGNER -Sg -N unixtime -o $zone $zonefile >/dev/null 2>/dev/null + +# Configure the resolving server with an initializing key. +keyfile_to_initial_ds $keyname >managed.conf +cp managed.conf ../ns2/managed.conf +cp managed.conf ../ns4/managed.conf +cp managed.conf ../ns5/managed.conf + +# Configure broken trust anchor for ns3 +# Rotate each nibble in the digest by -1 +$DSFROMKEY $keyname.key \ + | awk '!/^; /{ + printf "trust-anchors {\n" + printf "\t\""$1"\" initial-ds " + printf $4 " " $5 " " $6 " \"" + for (i=7; i<=NF; i++) { + # rotate digest + digest=$i + gsub("0", ":", digest) + gsub("1", "0", digest) + gsub("2", "1", digest) + gsub("3", "2", digest) + gsub("4", "3", digest) + gsub("5", "4", digest) + gsub("6", "5", digest) + gsub("7", "6", digest) + gsub("8", "7", digest) + gsub("9", "8", digest) + gsub("A", "9", digest) + gsub("B", "A", digest) + gsub("C", "B", digest) + gsub("D", "C", digest) + gsub("E", "D", digest) + gsub("F", "E", digest) + gsub(":", "F", digest) + printf digest + } + printf "\";\n" + printf "};\n" + }' >../ns3/broken.conf + +# Configure a static key to be used by delv. +keyfile_to_static_ds $keyname >trusted.conf + +# Prepare an unsupported algorithm key. +unsupportedkey=Kunknown.+255+00000 +cp unsupported.key "${unsupportedkey}.key" + +# +# Save keyname and keyid for managed key id test. +# +echo "$keyname" >managed.key +echo "$zskkeyname" >zone.key +keyfile_to_key_id $keyname >managed.key.id diff --git a/bin/tests/system/mkeys/ns1/sub.tld.db b/bin/tests/system/mkeys/ns1/sub.tld.db new file mode 100644 index 0000000..35d4361 --- /dev/null +++ b/bin/tests/system/mkeys/ns1/sub.tld.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +sub.tld. IN SOA marka.isc.org. ns.sub.tld. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +sub.tld. NS ns.sub.tld. +ns.sub.tld. A 10.53.0.1 diff --git a/bin/tests/system/mkeys/ns1/tld.db b/bin/tests/system/mkeys/ns1/tld.db new file mode 100644 index 0000000..5c54e0e --- /dev/null +++ b/bin/tests/system/mkeys/ns1/tld.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +tld. IN SOA marka.isc.org. ns.tld. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +tld. NS ns.tld. +ns.tld. A 10.53.0.1 +sub.tld. NS ns.sub.tld. +ns.sub.tld. A 10.53.0.1 diff --git a/bin/tests/system/mkeys/ns1/unsupported.key b/bin/tests/system/mkeys/ns1/unsupported.key new file mode 100644 index 0000000..7435d03 --- /dev/null +++ b/bin/tests/system/mkeys/ns1/unsupported.key @@ -0,0 +1 @@ +. IN DNSKEY 257 3 255 BJiXuidPHuGIne8GlCBLG+Oq/FZruQd2s3uBo+SxY16NUP/Vwl8MctMK62KsblDU1gIJAdEMVep2tsOkuSm0bIbJ8NBex+N9rSvzH2YJlDCT9QnNfv4q5RRTcVA3lk9nkmWHo6zcAT33yuS+THOCSznOMCJRq8JGZ6xqMJLv9FucuK6CCe6QBAZ5e98dpyGTWQLu7AERKKFqda9YCk3KQfdzx/HZ4SpQpRLncIXvGm1PIMT8Ar95NB/BsFJGwr5ZTaQtRYOXf2DD7wD3pfMsTJCdZyC0J0EtGBG109I+Oou1cswUfqZLXip/aV3eaBAUqLcZpg8P8vAbrvEq4uMS4OMZeXL6nu0irrdS1Pqmax8RsC+x3fg9EBH3QmHroJZtiU5h+0x4qApp7HE4Z5zFRuxIp9iB diff --git a/bin/tests/system/mkeys/ns2/named.args b/bin/tests/system/mkeys/ns2/named.args new file mode 100644 index 0000000..175e02c --- /dev/null +++ b/bin/tests/system/mkeys/ns2/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D mkeys-ns2 -g -T maxcachesize=2097152 -T mkeytimers=5/10/20 -T tat=1 diff --git a/bin/tests/system/mkeys/ns2/named.conf.in b/bin/tests/system/mkeys/ns2/named.conf.in new file mode 100644 index 0000000..feed923 --- /dev/null +++ b/bin/tests/system/mkeys/ns2/named.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + bindkeys-file "managed.conf"; + servfail-ttl 0; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/mkeys/ns3/named.args b/bin/tests/system/mkeys/ns3/named.args new file mode 100644 index 0000000..342cbe3 --- /dev/null +++ b/bin/tests/system/mkeys/ns3/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -D mkeys-ns3 -g -T maxcachesize=2097152 -T mkeytimers=5/10/20 diff --git a/bin/tests/system/mkeys/ns3/named.conf.in b/bin/tests/system/mkeys/ns3/named.conf.in new file mode 100644 index 0000000..d590a31 --- /dev/null +++ b/bin/tests/system/mkeys/ns3/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + bindkeys-file "managed.conf"; + trust-anchor-telemetry no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "broken.conf"; diff --git a/bin/tests/system/mkeys/ns4/named.conf.in b/bin/tests/system/mkeys/ns4/named.conf.in new file mode 100644 index 0000000..1ad75aa --- /dev/null +++ b/bin/tests/system/mkeys/ns4/named.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + bindkeys-file "managed.conf"; + managed-keys-directory "nope"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "sub.foo" { + type primary; + file "sub.foo.db.signed"; +}; diff --git a/bin/tests/system/mkeys/ns4/sign.sh b/bin/tests/system/mkeys/ns4/sign.sh new file mode 100644 index 0000000..8fb8519 --- /dev/null +++ b/bin/tests/system/mkeys/ns4/sign.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=sub.foo +zonefile=sub.foo.db + +keyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk $zone) +zskkeyname=$($KEYGEN -a ${DEFAULT_ALGORITHM} -q $zone) + +$SIGNER -Sg -o $zone $zonefile >/dev/null 2>/dev/null +keyfile_to_initial_ds $keyname >private.conf +cp private.conf ../ns5/private.conf diff --git a/bin/tests/system/mkeys/ns4/sub.foo.db b/bin/tests/system/mkeys/ns4/sub.foo.db new file mode 100644 index 0000000..7bc3104 --- /dev/null +++ b/bin/tests/system/mkeys/ns4/sub.foo.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +sub.foo. IN SOA marka.isc.org. ns.foo. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +sub.foo. NS ns.sub.foo. +ns.sub.foo. A 10.53.0.4 diff --git a/bin/tests/system/mkeys/ns5/foo.db b/bin/tests/system/mkeys/ns5/foo.db new file mode 100644 index 0000000..092a1c3 --- /dev/null +++ b/bin/tests/system/mkeys/ns5/foo.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +foo. IN SOA marka.isc.org. ns.foo. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +foo. NS ns.foo. +ns.foo. A 10.53.0.5 +sub.foo. NS ns.sub.foo. +ns.sub.foo. A 10.53.0.4 diff --git a/bin/tests/system/mkeys/ns5/named.conf.in b/bin/tests/system/mkeys/ns5/named.conf.in new file mode 100644 index 0000000..8669971 --- /dev/null +++ b/bin/tests/system/mkeys/ns5/named.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + bindkeys-file "managed.conf"; + servfail-ttl 0; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "foo" { + type primary; + file "foo.db"; +}; + +include "island.conf"; +include "private.conf"; diff --git a/bin/tests/system/mkeys/ns5/named1.args b/bin/tests/system/mkeys/ns5/named1.args new file mode 100644 index 0000000..cd9a228 --- /dev/null +++ b/bin/tests/system/mkeys/ns5/named1.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/mkeys/ns5/named2.args b/bin/tests/system/mkeys/ns5/named2.args new file mode 100644 index 0000000..a251448 --- /dev/null +++ b/bin/tests/system/mkeys/ns5/named2.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -g -T maxcachesize=2097152 -T mkeytimers=2/20/40 diff --git a/bin/tests/system/mkeys/ns6/named.args b/bin/tests/system/mkeys/ns6/named.args new file mode 100644 index 0000000..bfab8cb --- /dev/null +++ b/bin/tests/system/mkeys/ns6/named.args @@ -0,0 +1 @@ +-m record -c named.conf -d 99 -g -T maxcachesize=2097152 -T mkeytimers=5/10/20 diff --git a/bin/tests/system/mkeys/ns6/named.conf.in b/bin/tests/system/mkeys/ns6/named.conf.in new file mode 100644 index 0000000..114e2b7 --- /dev/null +++ b/bin/tests/system/mkeys/ns6/named.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + trust-anchor-telemetry no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "managed.conf"; diff --git a/bin/tests/system/mkeys/ns6/setup.sh b/bin/tests/system/mkeys/ns6/setup.sh new file mode 100644 index 0000000..2ea7aa4 --- /dev/null +++ b/bin/tests/system/mkeys/ns6/setup.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +zonefile=root.db + +# a key for a trust island +islandkey=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk island.) + +# a key with unsupported algorithm +unsupportedkey=Kunknown.+255+00000 +cp unsupported-managed.key "${unsupportedkey}.key" + +# root key +rootkey=$(cat ../ns1/managed.key) +cp "../ns1/${rootkey}.key" . + +# Configure the resolving server with an initializing key. +# (We use key-format trust anchors here because otherwise the +# unsupported algorithm test won't work.) +keyfile_to_initial_keys $unsupportedkey $islandkey $rootkey >managed.conf diff --git a/bin/tests/system/mkeys/ns6/unsupported-managed.key b/bin/tests/system/mkeys/ns6/unsupported-managed.key new file mode 100644 index 0000000..be872a0 --- /dev/null +++ b/bin/tests/system/mkeys/ns6/unsupported-managed.key @@ -0,0 +1 @@ +unsupported. IN DNSKEY 257 3 255 BOOVAhiJDPqhfU7+yGXjhetrtC/rtjmwO1yo52BUHUd8R4hQ/ZPdYCVvQlvNkRxDblPkFM5YRXkesS30pJSoNYrg+djbMNumJrLG+lbhFIc/ahTjlYOxb1zm2z00ubHju/1uGBifiRvKWSK0Vr0u6NtS4PKZfsnXt+piSHiRAHSfkjGHwqPYYKh9EUW12kJmIzlMaM6WYl+gJOvL+f8VqNLtvsMPT6OPK/3h/Dnfnxyeudp/jzAnNDDiTgX2XfzIXB4UwxtzIOGaHLnprpNf3zoBm0kyaEdSQQ/qKkpCOqjBasYEHRjVz3RncPUkdLr7PQuPBfFDr3SUMMJqufJrO4IJjtD4cCBT7K1i39Jg471nEzU1vkPzxF+Rw1QHT4nZaXbltf3BEZGS4Knoe9XPwi5KjGW6 diff --git a/bin/tests/system/mkeys/ns7/named.conf.in b/bin/tests/system/mkeys/ns7/named.conf.in new file mode 100644 index 0000000..7ccf59e --- /dev/null +++ b/bin/tests/system/mkeys/ns7/named.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS7 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion yes; + notify no; + dnssec-validation auto; + bindkeys-file "managed.conf"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view view1 { + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; + +view view2 { + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; diff --git a/bin/tests/system/mkeys/setup.sh b/bin/tests/system/mkeys/setup.sh new file mode 100644 index 0000000..4b5e752 --- /dev/null +++ b/bin/tests/system/mkeys/setup.sh @@ -0,0 +1,40 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Explicitly setting ALGORITHM_SET is only needed is the script is executed +# standalone without the pytest runner (e.g. for debugging). +export ALGORITHM_SET="ecc_default" + +. ../conf.sh + +copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf + +cp ns5/named1.args ns5/named.args + +(cd ns1 && $SHELL sign.sh) +(cd ns4 && $SHELL sign.sh) +(cd ns6 && $SHELL setup.sh) + +cp ns2/managed.conf ns2/managed1.conf + +cd ns4 +mkdir nope +touch nope/managed-keys.bind +touch nope/managed.keys.bind.jnl +chmod 444 nope/* diff --git a/bin/tests/system/mkeys/tests.sh b/bin/tests/system/mkeys/tests.sh new file mode 100644 index 0000000..b460121 --- /dev/null +++ b/bin/tests/system/mkeys/tests.sh @@ -0,0 +1,919 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +#shellcheck source=conf.sh +. ../conf.sh + +dig_with_opts() ( + "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "${PORT}" "$@" +) + +delv_with_opts() ( + "$DELV" -a ns1/trusted.conf -p "${PORT}" "$@" +) + +rndccmd() ( + "$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "$@" +) + +mkeys_reconfig_on() ( + nsidx=$1 + rndccmd "10.53.0.${nsidx}" reconfig . | sed "s/^/ns${nsidx} /" | cat_i +) + +mkeys_reload_on() ( + nsidx=$1 + nextpart "ns${nsidx}"/named.run >/dev/null + rndc_reload "ns${nsidx}" "10.53.0.${nsidx}" + wait_for_log 20 "loaded serial" "ns${nsidx}"/named.run || return 1 +) + +mkeys_resign_rootzone() ( + n=$1 + ( + cd ns1 + sleep 1 # ensure modification time changes + $SIGNER -PSg -N unixtime -o . root.db >signer.out.test$1 2>&1 + ) + nextpart ns1/named.run >/dev/null + rndccmd "10.53.0.1" reload . | sed "s/^/ns1 /" | cat_i + wait_for_log 20 "loaded serial" ns1/named.run || return 1 +) + +mkeys_refresh_on() ( + nsidx=$1 + nextpart "ns${nsidx}"/named.run >/dev/null + rndccmd "10.53.0.${nsidx}" managed-keys refresh | sed "s/^/ns${nsidx} /" | cat_i + wait_for_log 20 "Returned from key fetch in keyfetch_done()" "ns${nsidx}"/named.run || return 1 +) + +mkeys_sync_on() ( + # No race with mkeys_refresh_on() is possible as even if the latter + # returns immediately after the expected log message is written, the + # managed-keys zone is already locked and the command below calls + # dns_zone_flush(), which also attempts to take that zone's lock + nsidx=$1 + nextpart "ns${nsidx}"/named.run >/dev/null + rndccmd "10.53.0.${nsidx}" managed-keys sync | sed "s/^/ns${nsidx} /" | cat_i + wait_for_log 20 "dump_done" "ns${nsidx}"/named.run || return 1 +) + +mkeys_status_on() ( + # No race with mkeys_refresh_on() is possible as even if the latter + # returns immediately after the expected log message is written, the + # managed-keys zone is already locked and the command below calls + # mkey_status(), which in turn calls dns_zone_getrefreshkeytime(), + # which also attempts to take that zone's lock + nsidx=$1 + rndccmd "10.53.0.${nsidx}" managed-keys status +) + +mkeys_flush_on() ( + nsidx=$1 + rndccmd "10.53.0.${nsidx}" flush | sed "s/^/ns${nsidx} /" | cat_i +) + +mkeys_secroots_on() ( + nsidx=$1 + rndccmd "10.53.0.${nsidx}" secroots | sed "s/^/ns${nsidx} /" | cat_i +) + +original=$(cat ns1/managed.key) +originalid=$(cat ns1/managed.key.id) + +status=0 +n=1 + +rm -f dig.out.* + +echo_i "check for signed record ($n)" +ret=0 +dig_with_opts +norec example. @10.53.0.1 TXT >dig.out.ns1.test$n || ret=1 +grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*TXT[[:space:]]*\"This is a test\.\"" dig.out.ns1.test$n >/dev/null || ret=1 +grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*RRSIG[[:space:]]*TXT[[:space:]]" dig.out.ns1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check positive validation with valid trust anchor ($n)" +ret=0 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if [ -x "$DELV" ]; then + n=$((n + 1)) + ret=0 + echo_i "check positive validation using delv ($n)" + delv_with_opts @10.53.0.1 txt example >delv.out$n || ret=1 + grep "; fully validated" delv.out$n >/dev/null || ret=1 # redundant + grep "example..*TXT.*This is a test" delv.out$n >/dev/null || ret=1 + grep "example..*.RRSIG..*TXT" delv.out$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "check for failed validation due to wrong key in managed-keys ($n)" +ret=0 +dig_with_opts +noauth example. @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns3.test$n >/dev/null && ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns3.test$n >/dev/null && ret=1 +grep "opcode: QUERY, status: SERVFAIL, id" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check new trust anchor can be added ($n)" +ret=0 +standby1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .) +mkeys_resign_rootzone $n || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# there should be two keys listed now +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# one indicates current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# one indicates pending trust +count=$(grep -c "trust pending" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check new trust anchor can't be added with bad initial key ($n)" +ret=0 +mkeys_refresh_on 3 || ret=1 +mkeys_status_on 3 >rndc.out.$n 2>&1 || ret=1 +# there should be one key listed now +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# one line indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# ... and the key is not trusted +count=$(grep -c "no trust" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove untrusted standby key, check timer restarts ($n)" +ret=0 +mkeys_sync_on 2 || ret=1 +t1=$(grep "trust pending" ns2/managed-keys.bind) || true +$SETTIME -D now -K ns1 "$standby1" >/dev/null +mkeys_resign_rootzone $n || ret=1 +# Less than a second may have passed since the last time ns2 received a +# ./DNSKEY response from ns1. Ensure keys are refreshed at a different +# timestamp to prevent false negatives caused by the acceptance timer getting +# reset to the same timestamp. +sleep 1 +mkeys_refresh_on 2 || ret=1 +mkeys_sync_on 2 || ret=1 +t2=$(grep "trust pending" ns2/managed-keys.bind) || true +# trust pending date must be different +[ -n "$t2" ] || ret=1 +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "restore untrusted standby key, revoke original key ($n)" +t1=$t2 +$SETTIME -D none -K ns1 "$standby1" >/dev/null +$SETTIME -R now -K ns1 "$original" >/dev/null +mkeys_resign_rootzone $n || ret=1 +# Less than a second may have passed since the last time ns2 received a +# ./DNSKEY response from ns1. Ensure keys are refreshed at a different +# timestamp to prevent false negatives caused by the acceptance timer getting +# reset to the same timestamp. +sleep 1 +mkeys_refresh_on 2 || ret=1 +mkeys_sync_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# trust is revoked +count=$(grep -c "trust revoked" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# removal scheduled +count=$(grep -c "remove at" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# trust is still pending on the standby key +count=$(grep -c "trust pending" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# pending date moved forward for the standby key +t2=$(grep "trust pending" ns2/managed-keys.bind) || true +[ -n "$t2" ] || ret=1 +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "refresh managed-keys, ensure same result ($n)" +t1=$t2 +# Less than a second may have passed since the last time ns2 received a +# ./DNSKEY response from ns1. Ensure keys are refreshed at a different +# timestamp to prevent false negatives caused by the acceptance timer getting +# reset to the same timestamp. +sleep 1 +mkeys_refresh_on 2 || ret=1 +mkeys_sync_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# trust is revoked +count=$(grep -c "trust revoked" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# removal scheduled +count=$(grep -c "remove at" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# trust is still pending on the standby key +count=$(grep -c "trust pending" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# pending date moved forward for the standby key +t2=$(grep "trust pending" ns2/managed-keys.bind) || true +[ -n "$t2" ] || ret=1 +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "restore revoked key, ensure same result ($n)" +t1=$t2 +$SETTIME -R none -D now -K ns1 "$original" >/dev/null +mkeys_resign_rootzone $n || ret=1 +$SETTIME -D none -K ns1 "$original" >/dev/null +mkeys_resign_rootzone $n || ret=1 +# Less than a second may have passed since the last time ns2 received a +# ./DNSKEY response from ns1. Ensure keys are refreshed at a different +# timestamp to prevent false negatives caused by the acceptance timer getting +# reset to the same timestamp. +sleep 1 +mkeys_refresh_on 2 || ret=1 +mkeys_sync_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# trust is revoked +count=$(grep -c "trust revoked" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# removal scheduled +count=$(grep -c "remove at" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# trust is still pending on the standby key +count=$(grep -c "trust pending" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# pending date moved forward for the standby key +t2=$(grep "trust pending" ns2/managed-keys.bind) || true +[ -n "$t2" ] || ret=1 +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "reinitialize trust anchors, add second key to bind.keys" +stop_server --use-rndc --port "${CONTROLPORT}" ns2 +rm -f ns2/managed-keys.bind* +keyfile_to_initial_ds ns1/"$original" ns1/"$standby1" >ns2/managed.conf +nextpart ns2/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns2 + +n=$((n + 1)) +echo_i "check that no key from bind.keys is marked as an initializing key ($n)" +ret=0 +wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1 +mkeys_secroots_on 2 || ret=1 +grep '; initializing' ns2/named.secroots >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "reinitialize trust anchors, revert to one key in bind.keys" +stop_server --use-rndc --port "${CONTROLPORT}" ns2 +rm -f ns2/managed-keys.bind* +mv ns2/managed1.conf ns2/managed.conf +nextpart ns2/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns2 + +n=$((n + 1)) +echo_i "check that standby key is now trusted ($n)" +ret=0 +wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# both indicate current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "revoke original key, add new standby ($n)" +ret=0 +standby2=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .) +$SETTIME -R now -K ns1 "$original" >/dev/null +mkeys_resign_rootzone $n || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# three keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# one is revoked +count=$(grep -c "REVOKE" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# three lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# one indicates current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# one indicates revoked trust +count=$(grep -c "trust revoked" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# one indicates trust pending +count=$(grep -c "trust pending" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +# removal scheduled +count=$(grep -c "remove at" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "revoke standby before it is trusted ($n)" +ret=0 +standby3=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .) +mkeys_resign_rootzone $n || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.1.$n 2>&1 || ret=1 +# four keys listed +count=$(grep -c "keyid: " rndc.out.1.$n) || true +[ "$count" -eq 4 ] || { + echo_i "keyid: count ($count) != 4" + ret=1 +} +# one revoked +count=$(grep -c "trust revoked" rndc.out.1.$n) || true +[ "$count" -eq 1 ] || { + echo_i "trust revoked count ($count) != 1" + ret=1 +} +# two pending +count=$(grep -c "trust pending" rndc.out.1.$n) || true +[ "$count" -eq 2 ] || { + echo_i "trust pending count ($count) != 2" + ret=1 +} +$SETTIME -R now -K ns1 "$standby3" >/dev/null +mkeys_resign_rootzone $n || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.2.$n 2>&1 || ret=1 +# now three keys listed +count=$(grep -c "keyid: " rndc.out.2.$n) || true +[ "$count" -eq 3 ] || { + echo_i "keyid: count ($count) != 3" + ret=1 +} +# one revoked +count=$(grep -c "trust revoked" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || { + echo_i "trust revoked count ($count) != 1" + ret=1 +} +# one pending +count=$(grep -c "trust pending" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || { + echo_i "trust pending count ($count) != 1" + ret=1 +} +$SETTIME -D now -K ns1 "$standby3" >/dev/null +mkeys_resign_rootzone $n || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait 20 seconds for key add/remove holddowns to expire ($n)" +ret=0 +sleep 20 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# none revoked +count=$(grep -c "REVOKE" rndc.out.$n) || true +[ "$count" -eq 0 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# both indicate current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "revoke all keys, confirm roll to insecure ($n)" +ret=0 +$SETTIME -D now -K ns1 "$original" >/dev/null +$SETTIME -R now -K ns1 "$standby1" >/dev/null +$SETTIME -R now -K ns1 "$standby2" >/dev/null +mkeys_resign_rootzone $n || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# two keys listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# both revoked +count=$(grep -c "REVOKE" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# both indicate trust revoked +count=$(grep -c "trust revoked" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# both have removal scheduled +count=$(grep -c "remove at" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check for insecure response ($n)" +ret=0 +mkeys_refresh_on 2 || ret=1 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reset the root server ($n)" +ret=0 +$SETTIME -D none -R none -K ns1 "$original" >/dev/null +$SETTIME -D now -K ns1 "$standby1" >/dev/null +$SETTIME -D now -K ns1 "$standby2" >/dev/null +sleep 1 # ensure modification time changes +$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db >/dev/null 2>/dev/null +copy_setports ns1/named2.conf.in ns1/named.conf +rm -f ns1/root.db.signed.jnl +mkeys_reconfig_on 1 || ret=1 +mkeys_reload_on 1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "reinitialize trust anchors" +stop_server --use-rndc --port "${CONTROLPORT}" ns2 +rm -f ns2/managed-keys.bind* +nextpart ns2/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns2 + +n=$((n + 1)) +echo_i "check positive validation ($n)" +ret=0 +wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "revoke key with bad signature, check revocation is ignored ($n)" +ret=0 +revoked=$($REVOKE -K ns1 "$original") +rkeyid=$(keyfile_to_key_id "$revoked") +rm -f ns1/root.db.signed.jnl +# We need to activate at least one valid DNSKEY to prevent dnssec-signzone from +# failing. Alternatively, we could use -P to disable post-sign verification, +# but we actually do want post-sign verification to happen to ensure the zone +# is correct before we break it on purpose. +$SETTIME -R none -D none -K ns1 "$standby1" >/dev/null +$SIGNER -Sg -K ns1 -N unixtime -O full -o . -f signer.out.$n ns1/root.db >/dev/null 2>/dev/null +cp -f ns1/root.db.signed ns1/root.db.tmp +BADSIG="SVn2tLDzpNX2rxR4xRceiCsiTqcWNKh7NQ0EQfCrVzp9WEmLw60sQ5kP xGk4FS/xSKfh89hO2O/H20Bzp0lMdtr2tKy8IMdU/mBZxQf2PXhUWRkg V2buVBKugTiOPTJSnaqYCN3rSfV1o7NtC1VNHKKK/D5g6bpDehdn5Gaq kpBhN+MSCCh9OZP2IT20luS1ARXxLlvuSVXJ3JYuuhTsQXUbX/SQpNoB Lo6ahCE55szJnmAxZEbb2KOVnSlZRA6ZBHDhdtO0S4OkvcmTutvcVV+7 w53CbKdaXhirvHIh0mZXmYk2PbPLDY7PU9wSH40UiWPOB9f00wwn6hUe uEQ1Qg==" +# Less than a second may have passed since ns1 was started. If we call +# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the +# subsequent "rndc reload ." call on platforms which do not set the +# "nanoseconds" field of isc_time_t, due to zone load time being seemingly +# equal to master file modification time. +sleep 1 +sed -e "/ $rkeyid \./s, \. .*$, . $BADSIG," signer.out.$n >ns1/root.db.signed +mkeys_reload_on 1 || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +# one key listed +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 1 ] || { + echo_i "'keyid:' count ($count) != 1" + ret=1 +} +# it's the original key id +count=$(grep -c "keyid: $originalid" rndc.out.$n) || true +[ "$count" -eq 1 ] || { + echo_i "'keyid: $originalid' count ($count) != 1" + ret=1 +} +# not revoked +count=$(grep -c "REVOKE" rndc.out.$n) || true +[ "$count" -eq 0 ] || { + echo_i "'REVOKE' count ($count) != 0" + ret=1 +} +# trust is still current +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 1 ] || { + echo_i "'trust' count != 1" + ret=1 +} +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 1 ] || { + echo_i "'trusted since' count != 1" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check validation fails with bad DNSKEY rrset ($n)" +ret=0 +mkeys_flush_on 2 || ret=1 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "status: SERVFAIL" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "restore DNSKEY rrset, check validation succeeds again ($n)" +ret=0 +rm -f "${revoked}".key "${revoked}".private +rm -f ns1/root.db.signed.jnl +$SETTIME -D none -R none -K ns1 "$original" >/dev/null +$SETTIME -D now -K ns1 "$standby1" >/dev/null +# Less than a second may have passed since ns1 was started. If we call +# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the +# subsequent "rndc reload ." call on platforms which do not set the +# "nanoseconds" field of isc_time_t, due to zone load time being seemingly +# equal to master file modification time. +sleep 1 +$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db >/dev/null 2>/dev/null +mkeys_reload_on 1 || ret=1 +mkeys_flush_on 2 || ret=1 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reset the root server with no keys, check for minimal update ($n)" +ret=0 +# Refresh keys first to prevent previous checks from influencing this one. +# Note that we might still get occasional false negatives on some really slow +# machines, when $t1 equals $t2 due to the time elapsed between "rndc +# managed-keys status" calls being equal to the normal active refresh period +# (as calculated per rules listed in RFC 5011 section 2.3) minus an "hour" (as +# set using -T mkeytimers). +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.1.$n 2>&1 || ret=1 +t1=$(grep 'next refresh:' rndc.out.1.$n) || true +stop_server --use-rndc --port "${CONTROLPORT}" ns1 +rm -f ns1/root.db.signed.jnl +cp ns1/root.db ns1/root.db.signed +nextpart ns1/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns1 +wait_for_log 20 "all zones loaded" ns1/named.run || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.2.$n 2>&1 || ret=1 +# one key listed +count=$(grep -c "keyid: " rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +# it's the original key id +count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +# not revoked +count=$(grep -c "REVOKE" rndc.out.2.$n) || true +[ "$count" -eq 0 ] || ret=1 +# trust is still current +count=$(grep -c "trust" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +count=$(grep -c "trusted since" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +t2=$(grep 'next refresh:' rndc.out.2.$n) || true +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reset the root server with no signatures, check for minimal update ($n)" +ret=0 +# Refresh keys first to prevent previous checks from influencing this one +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.1.$n 2>&1 || ret=1 +t1=$(grep 'next refresh:' rndc.out.1.$n) || true +stop_server --use-rndc --port "${CONTROLPORT}" ns1 +rm -f ns1/root.db.signed.jnl +cat ns1/K*.key >>ns1/root.db.signed +nextpart ns1/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns1 +wait_for_log 20 "all zones loaded" ns1/named.run || ret=1 +# Less than a second may have passed since the last time ns2 received a +# ./DNSKEY response from ns1. Ensure keys are refreshed at a different +# timestamp to prevent minimal update from resetting it to the same timestamp. +sleep 1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.2.$n 2>&1 || ret=1 +# one key listed +count=$(grep -c "keyid: " rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +# it's the original key id +count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +# not revoked +count=$(grep -c "REVOKE" rndc.out.2.$n) || true +[ "$count" -eq 0 ] || ret=1 +# trust is still current +count=$(grep -c "trust" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +count=$(grep -c "trusted since" rndc.out.2.$n) || true +[ "$count" -eq 1 ] || ret=1 +t2=$(grep 'next refresh:' rndc.out.2.$n) || true +[ "$t1" = "$t2" ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "restore root server, check validation succeeds again ($n)" +ret=0 +rm -f ns1/root.db.signed.jnl +$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db >/dev/null 2>/dev/null +mkeys_reload_on 1 || ret=1 +mkeys_refresh_on 2 || ret=1 +mkeys_status_on 2 >rndc.out.$n 2>&1 || ret=1 +dig_with_opts +noauth example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null || ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that trust-anchor-telemetry queries are logged ($n)" +ret=0 +grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns2/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that trust-anchor-telemetry queries are received ($n)" +ret=0 +grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc-managed-keys destroy' ($n)" +ret=0 +rndccmd 10.53.0.2 managed-keys destroy | sed 's/^/ns2 /' | cat_i +mkeys_status_on 2 >rndc.out.1.$n 2>&1 || ret=1 +grep "no views with managed keys" rndc.out.1.$n >/dev/null || ret=1 +mkeys_reconfig_on 2 || ret=1 +check_root_trust_anchor_is_present_in_status() { + mkeys_status_on 2 >rndc.out.2.$n 2>&1 || return 1 + grep "name: \." rndc.out.2.$n >/dev/null || return 1 + return 0 +} +retry_quiet 5 check_root_trust_anchor_is_present_in_status || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that trust-anchor-telemetry queries contain the correct key ($n)" +ret=0 +# convert the hexadecimal key from the TAT query into decimal and +# compare against the known key. +tathex=$(grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/') || true +tatkey=$($PERL -e 'printf("%d\n", hex(@ARGV[0]));' "$tathex") +realkey=$(rndccmd 10.53.0.2 secroots - | sed -n "s#.*${DEFAULT_ALGORITHM}/\([0-9][0-9]*\) ; .*managed.*#\1#p") +[ "$tatkey" -eq "$realkey" ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check initialization fails if managed-keys can't be created ($n)" +ret=0 +mkeys_secroots_on 4 || ret=1 +grep '; initializing managed' ns4/named.secroots >/dev/null 2>&1 || ret=1 +grep '; managed' ns4/named.secroots >/dev/null 2>&1 && ret=1 +grep '; trusted' ns4/named.secroots >/dev/null 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check failure to contact root servers does not prevent key refreshes after restart ($n)" +ret=0 +# By the time we get here, ns5 should have attempted refreshing its managed +# keys. These attempts should fail as ns1 is configured to REFUSE all queries +# from ns5. Note that named1.args does not contain "-T mkeytimers"; this is to +# ensure key refresh retry will be scheduled to one actual hour after the first +# key refresh failure instead of just a few seconds, in order to prevent races +# between the next scheduled key refresh time and startup time of restarted ns5. +stop_server --use-rndc --port "${CONTROLPORT}" ns5 +nextpart ns5/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns5 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.':" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld':" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo':" ns5/named.run || ret=1 +# ns5/named.run will contain logs from both the old instance and the new +# instance. In order for the test to pass, both must attempt a fetch. +count=$(grep -c "Creating key fetch" ns5/named.run) || true +[ "$count" -lt 2 ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc managed-keys' and islands of trust root unreachable ($n)" +ret=0 +mkeys_sync_on 5 +mkeys_status_on 5 >rndc.out.$n 2>&1 || ret=1 +# there should be three keys listed now +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# three lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# one indicates current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 1 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check key refreshes are resumed after root servers become available ($n)" +ret=0 +stop_server --use-rndc --port "${CONTROLPORT}" ns5 +# Prevent previous check from affecting this one +rm -f ns5/managed-keys.bind* +# named2.args adds "-T mkeytimers=2/20/40" to named1.args as we need to wait for +# an "hour" until keys are refreshed again after initial failure +cp ns5/named2.args ns5/named.args +nextpart ns5/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns5 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': failure" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': failure" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1 +mkeys_secroots_on 5 || ret=1 +grep '; initializing managed' ns5/named.secroots >/dev/null 2>&1 || ret=1 +# ns1 should still REFUSE queries from ns5, so resolving should be impossible +dig_with_opts +noauth example. @10.53.0.5 txt >dig.out.ns5.a.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns5.a.test$n >/dev/null && ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns5.a.test$n >/dev/null && ret=1 +grep "status: SERVFAIL" dig.out.ns5.a.test$n >/dev/null || ret=1 +# Allow queries from ns5 to ns1 +copy_setports ns1/named3.conf.in ns1/named.conf +rm -f ns1/root.db.signed.jnl +nextpart ns5/named.run >/dev/null +mkeys_reconfig_on 1 || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': success" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': success" ns5/named.run || ret=1 +wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1 +mkeys_secroots_on 5 || ret=1 +grep '; managed' ns5/named.secroots >/dev/null || ret=1 +# ns1 should not longer REFUSE queries from ns5, so managed keys should be +# correctly refreshed and resolving should succeed +dig_with_opts +noauth example. @10.53.0.5 txt >dig.out.ns5.b.test$n || ret=1 +grep "flags:.*ad.*QUERY" dig.out.ns5.b.test$n >/dev/null || ret=1 +grep "example..*.RRSIG..*TXT" dig.out.ns5.b.test$n >/dev/null || ret=1 +grep "status: NOERROR" dig.out.ns5.b.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "reinitialize trust anchors, add unsupported algorithm ($n)" +ret=0 +stop_server --use-rndc --port "${CONTROLPORT}" ns6 +rm -f ns6/managed-keys.bind* +nextpart ns6/named.run >/dev/null +start_server --noclean --restart --port "${PORT}" ns6 +# log when an unsupported algorithm is encountered during startup +wait_for_log 20 "ignoring initial-key for 'unsupported.': algorithm is unsupported" ns6/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "ignoring unsupported algorithm in managed-keys ($n)" +ret=0 +mkeys_status_on 6 >rndc.out.$n 2>&1 || ret=1 +# there should still be only two keys listed (for . and island.) +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 + +n=$((n + 1)) +echo_i "introduce unsupported algorithm rollover in authoritative zone ($n)" +ret=0 +cp ns1/root.db ns1/root.db.orig +ksk=$(cat ns1/managed.key) +zsk=$(cat ns1/zone.key) +cat "ns1/${ksk}.key" "ns1/${zsk}.key" ns1/unsupported.key >>ns1/root.db +grep "\.[[:space:]]*IN[[:space:]]*DNSKEY[[:space:]]*257 3 255" ns1/root.db >/dev/null || ret=1 +$SIGNER -K ns1 -N unixtime -o . ns1/root.db "$ksk" "$zsk" >/dev/null 2>/dev/null || ret=1 +grep "DNSKEY.*257 3 255" ns1/root.db.signed >/dev/null || ret=1 +cp ns1/root.db.orig ns1/root.db +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "ignoring unsupported algorithm in rollover ($n)" +ret=0 +mkeys_reload_on 1 || ret=1 +mkeys_refresh_on 6 || ret=1 +mkeys_status_on 6 >rndc.out.$n 2>&1 || ret=1 +# there should still be only two keys listed (for . and island.) +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# two lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 2 ] || ret=1 +# log when an unsupported algorithm is encountered during rollover +wait_for_log 20 "Cannot compute tag for key in zone .: algorithm is unsupported" ns6/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc managed-keys' and views ($n)" +ret=0 +rndccmd 10.53.0.7 managed-keys refresh in view1 >rndc.out.ns7.view1.test$n || ret=1 +grep "refreshing managed keys for 'view1'" rndc.out.ns7.view1.test$n >/dev/null || ret=1 +lines=$(wc -l rndc.out.ns7.view2.test$n || ret=1 +lines=$(wc -l /dev/null || ret=1 +grep "refreshing managed keys for 'view2'" rndc.out.ns7.view2.test$n >/dev/null || ret=1 +[ "$lines" -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc managed-keys' and islands of trust now that root is reachable ($n)" +ret=0 +mkeys_sync_on 5 +mkeys_status_on 5 >rndc.out.$n 2>&1 || ret=1 +# there should be three keys listed now +count=$(grep -c "keyid: " rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# theee lines indicating trust status +count=$(grep -c "trust" rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +# three indicates current trust +count=$(grep -c "trusted since" rndc.out.$n) || true +[ "$count" -eq 3 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/mkeys/tests_sh_mkeys.py b/bin/tests/system/mkeys/tests_sh_mkeys.py new file mode 100644 index 0000000..a98c98f --- /dev/null +++ b/bin/tests/system/mkeys/tests_sh_mkeys.py @@ -0,0 +1,57 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = [ + pytest.mark.algorithm_set("ecc_default"), + pytest.mark.extra_artifacts( + [ + "delv.*", + "dig.out.*", + "dsset-*", + "rndc.out.*", + "signer.out.*", + "ns*/dsset-*", + "ns*/*.bk", + "ns*/*.jnl", + "ns*/K*", + "ns*/island.conf", + "ns*/managed.conf", + "ns*/named.secroots", + "ns*/private.conf", + "ns*/signer.out.*", + "ns*/trusted.conf", + "ns*/*.signed", + "ns1/managed.key", + "ns1/managed.key.id", + "ns1/root.db.orig", + "ns1/root.db.tmp", + "ns1/zone.key", + "ns2/managed-keys.bind", + "ns2/managed1.conf", + "ns3/broken.conf", + "ns3/managed-keys.bind", + "ns4/nope", + "ns5/managed-keys.bind", + "ns5/named.args", + "ns7/view1.mkeys", + "ns7/view2.mkeys", + ] + ), +] + + +@isctest.mark.flaky(max_runs=2) # GL#3098 +def test_mkeys(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/multisigner/kasp.conf b/bin/tests/system/multisigner/kasp.conf new file mode 100644 index 0000000..5fe6de8 --- /dev/null +++ b/bin/tests/system/multisigner/kasp.conf @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "model2" { + keys { + ksk lifetime unlimited algorithm ecdsap256sha256; + zsk lifetime unlimited algorithm ecdsap256sha256; + }; +}; diff --git a/bin/tests/system/multisigner/ns3/model2.multisigner.db b/bin/tests/system/multisigner/ns3/model2.multisigner.db new file mode 100644 index 0000000..010b05b --- /dev/null +++ b/bin/tests/system/multisigner/ns3/model2.multisigner.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/multisigner/ns3/named.conf.in b/bin/tests/system/multisigner/ns3/named.conf.in new file mode 100644 index 0000000..7cf25bb --- /dev/null +++ b/bin/tests/system/multisigner/ns3/named.conf.in @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "../kasp.conf"; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + key-directory "."; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "model2.multisigner." { + type primary; + allow-update { any; }; + file "model2.multisigner.db"; + dnssec-policy model2; + inline-signing no; +}; + +zone "model2.secondary." { + type secondary; + primaries { 10.53.0.5; }; + file "model2.secondary.db"; + dnssec-policy model2; + inline-signing yes; +}; diff --git a/bin/tests/system/multisigner/ns3/setup.sh b/bin/tests/system/multisigner/ns3/setup.sh new file mode 100644 index 0000000..123528f --- /dev/null +++ b/bin/tests/system/multisigner/ns3/setup.sh @@ -0,0 +1,44 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns3/setup.sh" + +O="OMNIPRESENT" +ksktimes="-P now -A now -P sync now" +zsktimes="-P now -A now" + +zone="model2.multisigner" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" + +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1 +# ZSK will be added to the other provider with nsupdate. +cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk" + +zone="model2.secondary" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +cp "../ns5/${zonefile}.in" "$zonefile" + +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1 +# ZSK will be added to the other provider with nsupdate. +cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk" diff --git a/bin/tests/system/multisigner/ns4/model2.multisigner.db b/bin/tests/system/multisigner/ns4/model2.multisigner.db new file mode 100644 index 0000000..86a1708 --- /dev/null +++ b/bin/tests/system/multisigner/ns4/model2.multisigner.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns4 +ns4 A 10.53.0.4 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 diff --git a/bin/tests/system/multisigner/ns4/named.conf.in b/bin/tests/system/multisigner/ns4/named.conf.in new file mode 100644 index 0000000..3f36f76 --- /dev/null +++ b/bin/tests/system/multisigner/ns4/named.conf.in @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +include "../kasp.conf"; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + key-directory "."; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "model2.multisigner." { + type primary; + allow-update { any; }; + file "model2.multisigner.db"; + dnssec-policy model2; + inline-signing yes; +}; + +zone "model2.secondary." { + type secondary; + primaries { 10.53.0.5; }; + file "model2.secondary.db"; + dnssec-policy model2; + inline-signing yes; +}; diff --git a/bin/tests/system/multisigner/ns4/setup.sh b/bin/tests/system/multisigner/ns4/setup.sh new file mode 100644 index 0000000..dc3fc7c --- /dev/null +++ b/bin/tests/system/multisigner/ns4/setup.sh @@ -0,0 +1,44 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns4/setup.sh" + +O="OMNIPRESENT" +ksktimes="-P now -A now -P sync now" +zsktimes="-P now -A now" + +zone="model2.multisigner" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" + +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1 +# ZSK will be added to the other provider with nsupdate. +cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk" + +zone="model2.secondary" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +cp "../ns5/${zonefile}.in" "$zonefile" + +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1 +# ZSK will be added to the other provider with nsupdate. +cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk" diff --git a/bin/tests/system/multisigner/ns5/model2.secondary.db.in b/bin/tests/system/multisigner/ns5/model2.secondary.db.in new file mode 100644 index 0000000..ea0f3cc --- /dev/null +++ b/bin/tests/system/multisigner/ns5/model2.secondary.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 + NS ns4 +ns3 A 10.53.0.3 +ns4 A 10.53.0.4 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/multisigner/ns5/named.conf.in b/bin/tests/system/multisigner/ns5/named.conf.in new file mode 100644 index 0000000..0a8e4f5 --- /dev/null +++ b/bin/tests/system/multisigner/ns5/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +include "../kasp.conf"; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + key-directory "."; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "model2.secondary." { + type primary; + allow-update { any; }; + file "model2.secondary.db"; +}; diff --git a/bin/tests/system/multisigner/ns5/setup.sh b/bin/tests/system/multisigner/ns5/setup.sh new file mode 100644 index 0000000..6bf3e6f --- /dev/null +++ b/bin/tests/system/multisigner/ns5/setup.sh @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns5/setup.sh" + +zone="model2.secondary" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +cp "${zonefile}.in" "$zonefile" diff --git a/bin/tests/system/multisigner/setup.sh b/bin/tests/system/multisigner/setup.sh new file mode 100644 index 0000000..06066bc --- /dev/null +++ b/bin/tests/system/multisigner/setup.sh @@ -0,0 +1,34 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +( + cd ns3 + $SHELL setup.sh +) +( + cd ns4 + $SHELL setup.sh +) +( + cd ns5 + $SHELL setup.sh +) diff --git a/bin/tests/system/multisigner/tests.sh b/bin/tests/system/multisigner/tests.sh new file mode 100644 index 0000000..abe19ff --- /dev/null +++ b/bin/tests/system/multisigner/tests.sh @@ -0,0 +1,771 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh +# shellcheck source=kasp.sh +. ../kasp.sh + +dig_with_opts() { + $DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p $PORT "$@" +} + +start_time="$(TZ=UTC date +%s)" +status=0 +n=0 + +set_zone "model2.multisigner" +set_policy "model2" "2" "3600" + +# Key properties and states. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "0" +set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "0" +set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" + +key_clear "KEY3" +key_clear "KEY4" + +set_keytimes_model2() { + # The first KSK is immediately published and activated. + created=$(key_get KEY1 CREATED) + set_keytime "KEY1" "PUBLISHED" "${created}" + set_keytime "KEY1" "ACTIVE" "${created}" + set_keytime "KEY1" "SYNCPUBLISH" "${created}" + + # The first ZSKs are immediately published and activated. + created=$(key_get KEY2 CREATED) + set_keytime "KEY2" "PUBLISHED" "${created}" + set_keytime "KEY2" "ACTIVE" "${created}" +} + +set_server "ns3" "10.53.0.3" +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +set_keytimes_model2 +check_keytimes +check_apex +dnssec_verify + +set_server "ns4" "10.53.0.4" +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +set_keytimes_model2 +check_keytimes +check_apex +dnssec_verify + +# +# Update DNSKEY RRset. +# + +# Check that the ZSKs from the other provider are published. +zsks_are_published() { + dig_with_opts "$ZONE" "@${SERVER}" DNSKEY >"dig.out.$DIR.test$n" || return 1 + cat dig.out.$DIR.test$n | tr [:blank:] ' ' >dig.out.$DIR.test$n.tr || return 1 + # We should have two ZSKs. + lines=$(grep "256 3 13" dig.out.$DIR.test$n.tr | wc -l) + test "$lines" -eq 2 || return 1 + # Both ZSKs are published. + grep "$(cat ns3/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr >/dev/null || return 1 + grep "$(cat ns4/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr >/dev/null || return 1 + # And one KSK. + lines=$(grep "257 3 13" dig.out.$DIR.test$n.tr | wc -l) + test "$lines" -eq 1 || return 1 +} + +# Test to make sure no DNSSEC records end up in the raw journal. +no_dnssec_in_journal() { + n=$((n + 1)) + ret=0 + echo_i "check zone ${ZONE} raw journal has no DNSSEC ($n)" + $JOURNALPRINT "${DIR}/${ZONE}.db.jnl" >"${DIR}/${ZONE}.journal.out.test$n" + rrset_exists NSEC "${DIR}/${ZONE}.journal.out.test$n" && ret=1 + rrset_exists NSEC3 "${DIR}/${ZONE}.journal.out.test$n" && ret=1 + rrset_exists NSEC3PARAM "${DIR}/${ZONE}.journal.out.test$n" && ret=1 + rrset_exists RRSIG "${DIR}/${ZONE}.journal.out.test$n" && ret= 1 + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Check if a certain RRtype is present in the journal file. +rrset_exists() ( + rrtype=$1 + file=$2 + lines=$(awk -v rt="${rrtype}" '$5 == rt {print}' ${file} | wc -l) + test "$lines" -gt 0 +) + +n=$((n + 1)) +echo_i "add dnskey record: update zone ${ZONE} at ns3 with ZSK from provider ns4 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "ns4/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Check the new DNSKEY RRset. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Check the logs for find zone keys errors. +n=$((n + 1)) +echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)" +ret=0 +grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Verify again. +dnssec_verify + +n=$((n + 1)) +echo_i "add dnskey record: - update zone ${ZONE} at ns4 with ZSK from provider ns3 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "ns3/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Check the new DNSKEY RRset. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Check the logs for find zone keys errors. +n=$((n + 1)) +echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)" +ret=0 +grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Verify again. +dnssec_verify +no_dnssec_in_journal + +n=$((n + 1)) +echo_i "remove dnskey record: - try to remove ns3 ZSK from provider ns3 (should fail) ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "ns3/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Both ZSKs should still be published. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after failed update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove dnskey record: remove ns4 ZSK from provider ns3 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "ns4/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# We should have only the KSK and ZSK from provider ns3. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +check_keys +check_apex +dnssec_verify + +n=$((n + 1)) +echo_i "remove dnskey record: try to remove ns4 ZSK from provider ns4 (should fail) ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "ns4/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Both ZSKs should still be published. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after failed update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove dnskey record: remove ns3 ZSK from provider ns4 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "ns3/${ZONE}.zsk") + echo send +) | $NSUPDATE +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# We should have only the KSK and ZSK from provider ns4. +n=$((n + 1)) +echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +check_keys +check_apex +dnssec_verify +no_dnssec_in_journal + +# +# Update CDNSKEY RRset. +# + +# Check that the CDNSKEY from both providers are published. +records_published() { + _rrtype=$1 + _expect=$2 + + dig_with_opts "$ZONE" "@${SERVER}" "${_rrtype}" >"dig.out.$DIR.test$n" || return 1 + lines=$(awk -v rt="${_rrtype}" '$4 == rt {print}' dig.out.$DIR.test$n | wc -l) + test "$lines" -eq "$_expect" || return 1 +} + +# Retrieve CDNSKEY records from the other provider. +dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY >dig.out.ns3.cdnskey +awk '$4 == "CDNSKEY" {print}' dig.out.ns3.cdnskey >cdnskey.ns3 +dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY >dig.out.ns4.cdnskey +awk '$4 == "CDNSKEY" {print}' dig.out.ns4.cdnskey >cdnskey.ns4 + +n=$((n + 1)) +echo_i "add cdnskey record: update zone ${ZONE} at ns3 with CDNSKEY from provider ns4 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +# Initially there should be one CDNSKEY. +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "cdnskey.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDNSKEY records (we test that BIND does not +# skip it during DNSSEC maintenance). +n=$((n + 1)) +echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "add cdnskey record: update zone ${ZONE} at ns4 with CDNSKEY from provider ns3 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +# Initially there should be one CDNSKEY. +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "cdnskey.ns3") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDNSKEY records (we test that BIND does not +# skip it during DNSSEC maintenance). +n=$((n + 1)) +echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# No DNSSEC in raw journal. +no_dnssec_in_journal + +n=$((n + 1)) +echo_i "remove cdnskey record: remove ns4 CDNSKEY from provider ns3 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "cdnskey.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDNSKEY record again. +n=$((n + 1)) +echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove cdnskey record: remove ns3 CDNSKEY from provider ns4 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "cdnskey.ns3") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDNSKEY record again. +n=$((n + 1)) +echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"ret=0 +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# No DNSSEC in raw journal. +no_dnssec_in_journal + +# +# Update CDS RRset. +# + +# Retrieve CDS records from the other provider. +dig_with_opts ${ZONE} @10.53.0.3 CDS >dig.out.ns3.cds +awk '$4 == "CDS" {print}' dig.out.ns3.cds >cds.ns3 +dig_with_opts ${ZONE} @10.53.0.4 CDS >dig.out.ns4.cds +awk '$4 == "CDS" {print}' dig.out.ns4.cds >cds.ns4 + +n=$((n + 1)) +echo_i "add cds record: update zone ${ZONE} at ns3 with CDS from provider ns4 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +# Initially there should be one CDS. +retry_quiet 10 records_published CDS 1 || ret=1 +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "cds.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDS records (we test that BIND does not +# skip it during DNSSEC maintenance). +n=$((n + 1)) +echo_i "check zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "add cds record: update zone ${ZONE} at ns4 with CDS from provider ns3 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +# Initially there should be one CDS. +retry_quiet 10 records_published CDS 1 || ret=1 +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "cds.ns3") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDS records (we test that BIND does not +# skip it during DNSSEC maintenance). +n=$((n + 1)) +echo_i "check zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# No DNSSEC in raw journal. +no_dnssec_in_journal + +n=$((n + 1)) +echo_i "remove cds record: remove ns4 CDS from provider ns3 ($n)" +ret=0 +set_server "ns3" "10.53.0.3" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "cds.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDS record again. +n=$((n + 1)) +echo_i "check zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove cds record: remove ns3 CDS from provider ns4 ($n)" +ret=0 +set_server "ns4" "10.53.0.4" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "cds.ns3") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDS record again. +n=$((n + 1)) +echo_i "check zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# No DNSSEC in raw journal. +no_dnssec_in_journal + +# +# Check secondary server behaviour. +# +set_zone "model2.secondary" +set_policy "model2" "2" "3600" + +set_server "ns3" "10.53.0.3" +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +set_keytimes_model2 +check_keytimes +check_apex +dnssec_verify + +set_server "ns4" "10.53.0.4" +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +set_keytimes_model2 +check_keytimes +check_apex +dnssec_verify + +# +# Update DNSKEY RRset. +# +n=$((n + 1)) +echo_i "add dnskey record: update zone ${ZONE} at ns5 with ZSKs from providers ns3 and ns4 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "ns3/${ZONE}.zsk") + echo update add $(cat "ns4/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 zsks_are_published || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "remove dnskey record: remove ns3 and ns4 DNSKEY records from primary ns5 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "ns3/${ZONE}.zsk") + echo update del $(cat "ns4/${ZONE}.zsk") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one DNSKEY record again. +# While we did remove both DNSKEY records, the bump in the wire signer, i.e +# the secondary inline-signing zone, should add back the DNSKEY belonging to +# its own KSK when re-signing the zone. +# +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +check_keys +check_apex +dnssec_verify +no_dnssec_in_journal +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)" +ret=0 +check_keys +check_apex +dnssec_verify +no_dnssec_in_journal + +# +# Update CDNSKEY RRset. +# + +# Retrieve CDNSKEY records from the providers. +n=$((n + 1)) +echo_i "check initial CDSNKEY response for zone ${ZONE} at ns3 and ns4 ($n)" +ret=0 +dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY >dig.out.ns3.secondary.cdnskey +awk '$4 == "CDNSKEY" {print}' dig.out.ns3.secondary.cdnskey >secondary.cdnskey.ns3 +dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY >dig.out.ns4.secondary.cdnskey +awk '$4 == "CDNSKEY" {print}' dig.out.ns4.secondary.cdnskey >secondary.cdnskey.ns4 +# Initially there should be one CDNSKEY. +set_server "ns3" "10.53.0.3" +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +set_server "ns4" "10.53.0.4" +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "add cdnskey record: update zone ${ZONE} at ns5 with CDNSKEY records from providers ns3 and ns4 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "secondary.cdnskey.ns3") + echo update add $(cat "secondary.cdnskey.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDNSKEY records (we test that BIND does not +# skip it during DNSSEC maintenance). +# +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal + +n=$((n + 1)) +echo_i "remove cdnskey record: remove ns3 and ns4 CDNSKEY records from primary ns5 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "secondary.cdnskey.ns3") + echo update del $(cat "secondary.cdnskey.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDNSKEY record again. +# While we did remove both CDNSKEY records, the bump in the wire signer, i.e +# the secondary inline-signing zone, should add back the CDNSKEY belonging to +# its own KSK when re-signing the zone. +# +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDNSKEY 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal + +# +# Update CDS RRset. +# + +# Retrieve CDS records from the other provider. +n=$((n + 1)) +echo_i "check initial CDS response for zone ${ZONE} at ns3 and ns4 ($n)" +ret=0 +dig_with_opts ${ZONE} @10.53.0.3 CDS >dig.out.ns3.secondary.cds +awk '$4 == "CDS" {print}' dig.out.ns3.secondary.cds >secondary.cds.ns3 +dig_with_opts ${ZONE} @10.53.0.4 CDS >dig.out.ns4.secondary.cds +awk '$4 == "CDS" {print}' dig.out.ns4.secondary.cds >secondary.cds.ns4 +# Initially there should be one CDS. +set_server "ns3" "10.53.0.3" +retry_quiet 10 records_published CDS 1 || ret=1 +set_server "ns4" "10.53.0.4" +retry_quiet 10 records_published CDS 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +n=$((n + 1)) +echo_i "add cds record: update zone ${ZONE} at ns5 with CDS from provider ns4 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update add $(cat "secondary.cds.ns3") + echo update add $(cat "secondary.cds.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be two CDS records (we test that BIND does not +# skip it during DNSSEC maintenance). +# +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 2 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal + +n=$((n + 1)) +echo_i "remove cds record: remove ns3 and ns4 CDS records from primary ns5 ($n)" +ret=0 +set_server "ns5" "10.53.0.5" +( + echo zone "${ZONE}" + echo server "${SERVER}" "${PORT}" + echo update del $(cat "secondary.cds.ns3") + echo update del $(cat "secondary.cds.ns4") + echo send +) | $NSUPDATE || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +# Now there should be one CDS record again. +# While we did remove both CDS records, the bump in the wire signer, i.e +# the secondary inline-signing zone, should add back the CDS belonging to +# its own KSK when re-signing the zone. +# +# NS3 +n=$((n + 1)) +set_server "ns3" "10.53.0.3" +echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal +# NS4 +n=$((n + 1)) +set_server "ns4" "10.53.0.4" +echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)" +ret=0 +retry_quiet 10 records_published CDS 1 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) +dnssec_verify +no_dnssec_in_journal + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/multisigner/tests_sh_multisigner.py b/bin/tests/system/multisigner/tests_sh_multisigner.py new file mode 100644 index 0000000..61d6c5d --- /dev/null +++ b/bin/tests/system/multisigner/tests_sh_multisigner.py @@ -0,0 +1,39 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "*.created", + "cdnskey.ns*", + "cds.ns*", + "dig.out.*", + "rndc.dnssec.status.out.*", + "secondary.cdnskey.ns*", + "secondary.cds.ns*", + "verify.out.*", + "ns*/K*", + "ns*/db-*", + "ns*/keygen.out.*", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/*.zsk", + "ns*/*.signed", + "ns*/*.journal.out.*", + "ns*/settime.out.*", + "ns*/model2.secondary.db", + ] +) + + +def test_multisigner(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/names/ns1/example.db b/bin/tests/system/names/ns1/example.db new file mode 100644 index 0000000..a3e9f90 --- /dev/null +++ b/bin/tests/system/names/ns1/example.db @@ -0,0 +1,50 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns1 +ns1 A 10.53.0.1 +@ MX 0 m1.mail-servers.example. +@ MX 0 m2.mail-servers.example. +@ MX 0 m3.mail-servers.example. +@ MX 0 m4.mail-servers.example. +@ MX 0 m5.mail-servers.example. +@ MX 0 m6.mail-servers.example. +@ MX 0 m7.mail-servers.example. +@ MX 0 m8.mail-servers.example. +@ MX 0 m9.mail-servers.example. +@ MX 0 m10.mail-servers.example. +@ MX 0 m11.mail-servers.example. +@ MX 0 m12.mail-servers.example. +@ MX 0 m13.mail-servers.example. +@ MX 0 m14.mail-servers.example. +@ MX 0 m15.mail-servers.example. +@ MX 0 m16.mail-servers.example. +@ MX 0 m17.mail-servers.example. +@ MX 0 m18.mail-servers.example. +@ MX 0 m19.mail-servers.example. +@ MX 0 m20.mail-servers.example. +@ MX 0 m21.mail-servers.example. +@ MX 0 m22.mail-servers.example. +@ MX 0 m23.mail-servers.example. +@ MX 0 m24.mail-servers.example. +@ MX 0 m25.mail-servers.example. +@ MX 0 m26.mail-servers.example. +@ MX 0 m27.mail-servers.example. +@ MX 0 m28.mail-servers.example. +@ MX 0 m29.mail-servers.example. diff --git a/bin/tests/system/names/ns1/named.conf.j2 b/bin/tests/system/names/ns1/named.conf.j2 new file mode 100644 index 0000000..c065e38 --- /dev/null +++ b/bin/tests/system/names/ns1/named.conf.j2 @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + ixfr-from-differences yes; + check-integrity no; + dnssec-validation no; +}; + + +view compress { + match-clients { 10.53.0.1/32; }; + zone "example" { + type primary; + file "example.db"; + }; +}; + +view nocompress { + match-clients { 10.53.0.2/32; }; + message-compression no; + zone "example" { + type primary; + file "example.db"; + }; +}; diff --git a/bin/tests/system/names/tests_names.py b/bin/tests/system/names/tests_names.py new file mode 100644 index 0000000..e4fc296 --- /dev/null +++ b/bin/tests/system/names/tests_names.py @@ -0,0 +1,33 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytest.importorskip("dns", minversion="2.7.0") + + +import dns.message +import isctest + + +# The query answer sent with compression disabled should have a size that is +# about twice as large as the answer with compression enabled, while +# maintaining identical content. +def test_names(): + msg = dns.message.make_query("example.", "MX") + # Getting message size with compression enabled + res_enabled = isctest.query.tcp(msg, ip="10.53.0.1", source="10.53.0.1") + # Getting message size with compression disabled + res_disabled = isctest.query.tcp(msg, ip="10.53.0.1", source="10.53.0.2") + # Checking if responses are identical content-wise + isctest.check.rrsets_equal(res_enabled.answer, res_disabled.answer) + # Checking if message with compression disabled is significantly (say 70%) larger + assert len(res_disabled.wire) > len(res_enabled.wire) * 1.7 diff --git a/bin/tests/system/notify/CA/CA.cfg b/bin/tests/system/notify/CA/CA.cfg new file mode 100644 index 0000000..1a3ed65 --- /dev/null +++ b/bin/tests/system/notify/CA/CA.cfg @@ -0,0 +1,77 @@ +# See ../../doth/CA/ca.cfg for more information + +# certificate authority configuration +[ca] +default_ca = CA_default # The default ca section + +[CA_default] +dir = . +new_certs_dir = $dir/newcerts # new certs dir (must be created) +certificate = $dir/CA.pem # The CA cert +private_key = $dir/private/CA.key # CA private key + +serial = $dir/serial # serial number file for the next certificate + # Update before issuing it: + # xxd -l 8 -u -ps /dev/urandom > ./serial +database = $dir/index.txt # (must be created manually: touch ./index.txt) + +default_days = 1 # how long to certify for + +#default_crl_days = 30 # the number of days before the +default_crl_days = 10950 # next CRL is due. That is the + # days from now to place in the + # CRL nextUpdate field. If CRL + # is expired, certificate + # verifications will fail even + # for otherwise valid + # certificates. Clients might + # cache the CRL, so the expiry + # period should normally be + # relatively short (default: + # 30) for production CAs. + +default_md = sha256 # digest to use + +policy = policy_default # default policy +email_in_dn = no # Don't add the email into cert DN + +name_opt = ca_default # Subject name display option +cert_opt = ca_default # Certificate display option + +# We need the following in order to copy Subject Alt Name(s) from a +# request to the certificate. +copy_extensions = copy # copy extensions from request + +[policy_default] +countryName = optional +stateOrProvinceName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# default certificate requests settings +[req] +# Options for the `req` tool (`man req`). +default_bits = 3072 # for RSA only +distinguished_name = req_default +string_mask = utf8only +# SHA-1 is deprecated, so use SHA-256 instead. +default_md = sha256 +# do not encrypt the private key file +encrypt_key = no + +[req_default] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (e.g., city) +0.organizationName = Organization Name (e.g., company) +organizationalUnitName = Organizational Unit Name (e.g. department) +commonName = Common Name (e.g. server FQDN or YOUR name) +emailAddress = Email Address +# defaults +countryName_default = UA +stateOrProvinceName_default = Kharkiv Oblast +localityName_default = Kharkiv +0.organizationName_default = ISC +organizationalUnitName_default = Software Engeneering (BIND 9) diff --git a/bin/tests/system/notify/CA/CA.pem b/bin/tests/system/notify/CA/CA.pem new file mode 100644 index 0000000..1f725db --- /dev/null +++ b/bin/tests/system/notify/CA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE3TCCA0WgAwIBAgIUeZPKrvbGEBZaRc2jNczlIsJXyPYwDQYJKoZIhvcNAQEL +BQAwfTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G +A1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0 +aXVtMRwwGgYDVQQDDBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDEyNDEyNDA1 +NFoYDzIwNTIwMTE3MTI0MDU0WjB9MQswCQYDVQQGEwJVQTEYMBYGA1UECAwPS2hh +cmtpdiBPYmxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5l +dCBTeXN0ZW1zIENvbnNvcnRpdW0xHDAaBgNVBAMME2NhLnRlc3QuZXhhbXBsZS5j +b20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCi6hEegBzpUKbE1NTo +Z7uz7EMUY7TBckkiw/7ydTLKNa8YI4JpBguFvWQsDY0dGFJIoVwyHyNx3seW/LoI +B5zWPZ2xbOvLLceA+t2NZpbc98E7jUOVS123yED+nqlfZjCq9Zt0r/ezwnQtjnFF +ko1mcU4H9Jvg8aIgnU2AxE78zciU9CY8799pFFNThIjbooI8oVbfjbzbpmLzxjA5 +3rDmZBTh+ySTlMa2U2oT4WPjRltZWnJVegRRLpG95GnTbQ1fkJAbj1Iu10XTkCee +wBOqaA1UJem0a6pby5odE414Y7c0ETKcmaJtYENQyO0IJwZWDKtVe5OTIAklakia +eyFTCAw1h5tHCYLaJW/Yu2wlLl5RNQcRZ9+cWXnldTY+TI1iBjfmADjLdKJYUlhX +z7kWJtTi63Sdv6WYcEXxaWpxT+R3e2kaR/R7GOo4gdkWpX1siGlRteHHH2/36CSQ +ZD2etcTUpGW+KDHFR4grnEfL1rt9UgvCjpa4KcssmZtWSSUCAwEAAaNTMFEwHQYD +VR0OBBYEFHyJ6Fzr5R9ySATFj/uSCJz1YCY5MB8GA1UdIwQYMBaAFHyJ6Fzr5R9y +SATFj/uSCJz1YCY5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGB +AF3y0hvzyZWtmuG1JwIcOcc1aPl1KdRy8bao/5iHYGYYrsdDgcO5/e+y9S/izalc +TdW7SKB5iBOCiE8fBNtToCvGP+fxNxHijpAmTr37G5sWuSo1T1VYFizHWL+df/Ig +TcSvDrEjSnAwaEdNJUWtjoIC4VzNKTLtZf16QIATTzTZa3bfgSetpWS7LhLQbHod +CSGI2QB1LRbqGC+a1Y85QxHv81jWzPWPzXYvnOLrDdQyBMOBcxDzrN4b6zg+5Itz +qGYt+IS71jAH0IhxAyD/U5n1jGJv02BnSq0ynLEOD6gsnZjqAwPbt/PM9pGbtbXO +70Q9rxr+vQc1IISKAEiH3txaEPi10wU98d6LbInJvQrmgHo/ntet8skWNYuxlEzS +wvynuE9KvvQtOTodWt5AePtKrhHdxu527a4CHVp59nYUjKSdMKjvmhMRXM1cNjFE +rA/pyyhozR47w3RzHMJVHw2GJ2B/HeqmxpXr1CmJjoRP38QCR7N+mqiZy85Fq2j2 +8Q== +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/README b/bin/tests/system/notify/CA/README new file mode 100644 index 0000000..13069ca --- /dev/null +++ b/bin/tests/system/notify/CA/README @@ -0,0 +1,2 @@ +Please take a look at the contents of the CA.cfg file for further +instructions and configurations options. diff --git a/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.key b/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.key new file mode 100644 index 0000000..68fa7b6 --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDBbu3hxycrhJ+msVeQ0 +mNB/WkW7rxNr8Zi8iXLETgBJ40cJu0d/IA4jrJ4gvfwT82uhZANiAAT+AGZM20R/ +AnlbmJOoZ4qHWgcPhEDIZ3+5rzIYpyL67adW2henRZ2s/ULMi/v/OpLYfuT8f1Ro +RHxhJUK0kpu1yx1R0mEI94kimw2Ocpnf2VHIksml+D8tEek0h0lczC0= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.pem b/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.pem new file mode 100644 index 0000000..1ccfd32 --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv02.crt01-expired.example.com.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:a2 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 17 16:18:18 2024 GMT + Not After : Sep 18 16:18:18 2024 GMT + Subject: CN=srv02.crt01-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:fe:00:66:4c:db:44:7f:02:79:5b:98:93:a8:67: + 8a:87:5a:07:0f:84:40:c8:67:7f:b9:af:32:18:a7: + 22:fa:ed:a7:56:da:17:a7:45:9d:ac:fd:42:cc:8b: + fb:ff:3a:92:d8:7e:e4:fc:7f:54:68:44:7c:61:25: + 42:b4:92:9b:b5:cb:1d:51:d2:61:08:f7:89:22:9b: + 0d:8e:72:99:df:d9:51:c8:92:c9:a5:f8:3f:2d:11: + e9:34:87:49:5c:cc:2d + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01-expired.example.com, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 03:4C:AC:DE:C0:A3:EB:04:56:1C:10:47:EB:C9:4D:1A:5F:FD:8E:A1 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 25:33:d0:30:6e:60:5e:f3:29:e7:1d:36:83:4d:cd:06:d2:35: + df:80:76:25:e5:56:c6:e7:5f:cb:70:c8:30:da:a1:15:50:1b: + 5d:e0:7b:01:60:47:32:ee:ea:98:cd:27:c2:2e:b8:d5:4a:2f: + 76:7b:f1:0d:ff:c3:b3:74:f9:98:37:c1:07:85:04:55:8f:42: + 25:b7:21:03:50:83:50:01:6a:88:84:bc:83:2c:48:3f:e5:96: + 04:d7:b5:56:68:7c:fe:d9:06:e2:bc:f0:fd:47:fd:4b:4c:9b: + 15:ca:ab:10:e4:8d:8f:b5:f7:dd:69:8c:9d:06:00:8f:80:5b: + 30:a6:6c:31:d2:b8:4b:cf:10:2a:bf:64:fb:be:da:3f:e2:ee: + f1:6c:74:02:a7:c5:0c:e2:13:f1:54:63:a9:45:43:7b:b7:85: + a3:48:00:62:34:db:ac:a1:b6:b8:76:b9:d9:aa:17:a2:f9:0b: + 96:87:ad:da:5e:95:50:2b:73:17:d7:2c:d0:43:40:e3:e9:80: + e2:87:be:1d:65:68:17:0d:90:98:0a:9b:6d:4f:2d:91:3e:f0: + 16:4e:c0:c3:e7:a9:a6:e8:bf:8e:b6:d0:3b:72:e6:d9:9a:b3: + 70:82:23:c1:02:c2:cc:91:d7:75:19:3c:79:33:ea:86:8d:80: + 9a:6b:f2:93:b4:dc:22:19:11:82:3d:62:1d:e5:58:58:7f:50: + 84:b0:d4:5a:67:be:d0:28:b0:be:a1:7f:9d:1b:a2:98:9b:70: + 5a:c0:a8:c5:03:ec:de:8a:e2:ea:03:2d:4e:9f:6c:7d:d8:0e: + 41:3c:58:df:3f:1e:4f:69:04:68:54:59:58:ef:dd:e3:32:b3: + 2c:b4:cc:40:28:eb:3e:3b:37:fd:42:f7:d9:60:bf:fa:6d:87: + ca:ed:43:24:93:47:a8:bc:54:cc:c9:4d:ac:d0:b8:09:cb:85: + c3:02:55:73:bf:f0:ff:a3:fc:d2:d1:ae:ea:5a:96:6a:76:51: + fb:da:d9:ad:e4:cd +-----BEGIN CERTIFICATE----- +MIIDcDCCAdigAwIBAgIJAMWGaDl7HMSiMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAeFw0yNDA5MTcxNjE4MThaFw0yNDA5MTgx +NjE4MThaMCoxKDAmBgNVBAMMH3NydjAyLmNydDAxLWV4cGlyZWQuZXhhbXBsZS5j +b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT+AGZM20R/AnlbmJOoZ4qHWgcPhEDI +Z3+5rzIYpyL67adW2henRZ2s/ULMi/v/OpLYfuT8f1RoRHxhJUK0kpu1yx1R0mEI +94kimw2Ocpnf2VHIksml+D8tEek0h0lczC2jdDByMDAGA1UdEQQpMCeCH3NydjAy +LmNydDAxLWV4cGlyZWQuZXhhbXBsZS5jb22HBAo1AAIwHQYDVR0OBBYEFANMrN7A +o+sEVhwQR+vJTRpf/Y6hMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQAlM9AwbmBe8ynnHTaDTc0G0jXfgHYl5VbG51/L +cMgw2qEVUBtd4HsBYEcy7uqYzSfCLrjVSi92e/EN/8OzdPmYN8EHhQRVj0IltyED +UINQAWqIhLyDLEg/5ZYE17VWaHz+2QbivPD9R/1LTJsVyqsQ5I2PtffdaYydBgCP +gFswpmwx0rhLzxAqv2T7vto/4u7xbHQCp8UM4hPxVGOpRUN7t4WjSABiNNusoba4 +drnZqhei+QuWh63aXpVQK3MX1yzQQ0Dj6YDih74dZWgXDZCYCpttTy2RPvAWTsDD +56mm6L+OttA7cubZmrNwgiPBAsLMkdd1GTx5M+qGjYCaa/KTtNwiGRGCPWId5VhY +f1CEsNRaZ77QKLC+oX+dG6KYm3BawKjFA+zeiuLqAy1On2x92A5BPFjfPx5PaQRo +VFlY793jMrMstMxAKOs+Ozf9QvfZYL/6bYfK7UMkk0eovFTMyU2s0LgJy4XDAlVz +v/D/o/zS0a7qWpZqdlH72tmt5M0= +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.key b/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.key new file mode 100644 index 0000000..c3bade8 --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAxARyCz9Aq5XQpE4SV +IKYvvz2K9IjosWKkcbxjh0rW62RGyi4c3pSo6so8tpvHXzmhZANiAAQ2bCdh34Lt +hA8MzF7BeZhYfvUODFH3fSSAJuRDMSaO02f294+E2Icy91W9AhFetSceZa0Dhldc +aVVaPVm3bhhjvLUGFImFmccFtNtQj/llRCbY9VFtbfXaY/Vq5243EAg= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.pem b/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.pem new file mode 100644 index 0000000..52baf96 --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv02.crt01.example.com.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:9f + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 3 15:33:14 2024 GMT + Not After : Aug 27 15:33:14 2054 GMT + Subject: CN=srv02.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:36:6c:27:61:df:82:ed:84:0f:0c:cc:5e:c1:79: + 98:58:7e:f5:0e:0c:51:f7:7d:24:80:26:e4:43:31: + 26:8e:d3:67:f6:f7:8f:84:d8:87:32:f7:55:bd:02: + 11:5e:b5:27:1e:65:ad:03:86:57:5c:69:55:5a:3d: + 59:b7:6e:18:63:bc:b5:06:14:89:85:99:c7:05:b4: + db:50:8f:f9:65:44:26:d8:f5:51:6d:6d:f5:da:63: + f5:6a:e7:6e:37:10:08 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.com, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 4C:A6:2B:5F:55:DF:2E:1E:FA:E8:C6:3F:05:25:20:69:BA:60:3B:E2 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 1d:22:c4:60:42:9a:d8:ac:54:cf:77:be:17:d0:eb:b4:7d:44: + b1:ad:bf:53:0e:be:61:37:bf:7b:a6:78:7e:a0:3f:aa:21:cd: + 09:3a:d4:41:b5:9f:31:a2:c9:db:df:94:a4:05:02:dd:98:04: + 38:55:af:20:3a:4d:82:cd:37:0f:a5:b8:9c:dc:0d:f8:07:c9: + 9d:8e:0a:4f:df:f1:8d:0c:53:9b:56:a2:35:7e:0a:3d:47:89: + ad:76:8f:6c:f5:15:0e:3f:05:af:fb:f8:97:97:a3:91:a6:cf: + 22:04:c0:35:24:84:b4:e5:4d:c0:bf:e0:8d:8b:59:bf:71:2e: + c3:d8:8e:c9:9d:ba:0a:32:cb:0f:b8:b8:e3:91:f9:77:78:55: + 17:9f:6e:09:d6:29:86:25:b6:0d:9b:52:b7:0a:75:f7:cd:09: + 5d:04:83:9f:08:8f:eb:8c:23:73:e0:14:2b:be:ba:22:96:8f: + 68:f8:c7:39:a7:44:9b:1d:ce:cb:eb:04:33:c0:da:b8:03:c0: + 5b:7a:3c:a1:f5:28:92:93:06:f2:32:c3:38:fe:68:5d:64:21: + 6e:3f:8b:80:f8:01:8f:19:5c:fa:13:6c:5e:27:55:19:70:87: + 70:02:80:79:d2:37:d3:d9:05:b1:8e:50:37:24:f0:32:33:bb: + e9:f2:26:f8:19:92:d5:ad:2a:09:c1:b0:48:52:f4:e3:62:cd: + e1:b4:51:d9:0a:88:e3:fb:1e:c9:5c:a5:83:fe:30:9d:cf:83: + 22:ba:1a:cd:c9:a9:e0:3d:cc:8d:f7:68:9e:17:a2:36:78:ab: + 6f:01:de:20:a1:0d:a2:30:12:ee:45:14:b6:f7:c4:e4:d3:4e: + c7:0b:d7:14:b2:49:5c:f8:3a:fc:29:43:fa:97:d1:70:46:54: + c0:a9:c6:eb:f0:91:59:0e:24:8f:e5:38:79:38:fb:86:ab:3c: + b1:ea:d2:a3:4c:2c:e4:29:1a:03:da:54:a0:a6:73:ac:b4:c8: + 02:5a:4c:38:e0:23 +-----BEGIN CERTIFICATE----- +MIIDYjCCAcqgAwIBAgIJAMWGaDl7HMSfMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yNDA5MDMxNTMzMTRaGA8yMDU0MDgy +NzE1MzMxNFowIjEgMB4GA1UEAwwXc3J2MDIuY3J0MDEuZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQ2bCdh34LthA8MzF7BeZhYfvUODFH3fSSAJuRD +MSaO02f294+E2Icy91W9AhFetSceZa0DhldcaVVaPVm3bhhjvLUGFImFmccFtNtQ +j/llRCbY9VFtbfXaY/Vq5243EAijbDBqMCgGA1UdEQQhMB+CF3NydjAyLmNydDAx +LmV4YW1wbGUuY29thwQKNQACMB0GA1UdDgQWBBRMpitfVd8uHvroxj8FJSBpumA7 +4jAfBgNVHSMEGDAWgBR8iehc6+UfckgExY/7kgic9WAmOTANBgkqhkiG9w0BAQsF +AAOCAYEAHSLEYEKa2KxUz3e+F9DrtH1Esa2/Uw6+YTe/e6Z4fqA/qiHNCTrUQbWf +MaLJ29+UpAUC3ZgEOFWvIDpNgs03D6W4nNwN+AfJnY4KT9/xjQxTm1aiNX4KPUeJ +rXaPbPUVDj8Fr/v4l5ejkabPIgTANSSEtOVNwL/gjYtZv3Euw9iOyZ26CjLLD7i4 +45H5d3hVF59uCdYphiW2DZtStwp1980JXQSDnwiP64wjc+AUK766IpaPaPjHOadE +mx3Oy+sEM8DauAPAW3o8ofUokpMG8jLDOP5oXWQhbj+LgPgBjxlc+hNsXidVGXCH +cAKAedI309kFsY5QNyTwMjO76fIm+BmS1a0qCcGwSFL042LN4bRR2QqI4/seyVyl +g/4wnc+DIroazcmp4D3MjfdonheiNnirbwHeIKENojAS7kUUtvfE5NNOxwvXFLJJ +XPg6/ClD+pfRcEZUwKnG6/CRWQ4kj+U4eTj7hqs8serSo0ws5CkaA9pUoKZzrLTI +AlpMOOAj +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.key b/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.key new file mode 100644 index 0000000..cde19c3 --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAEmVA9V00diOvZfEJV +N7piEbfN7fULRHWg2k4g7V2Ivpn9LfBsaYh5+Acf271G0mKhZANiAAQSbFty27Ro +RO7BPZFI9yM5V64xIUGMe4o4LYBA6cKhFFCVO0fX6h6bO0wgh2fCgYbWOq2X6Q1X +/x36gVJCzgXSBXPNktdMIxki9cttREvXo1cmELKl/n+PXDgxcbg/RbM= +-----END PRIVATE KEY----- diff --git a/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.pem b/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.pem new file mode 100644 index 0000000..0d45e7a --- /dev/null +++ b/bin/tests/system/notify/CA/certs/srv03.crt01.example.com.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:a0 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 3 15:33:18 2024 GMT + Not After : Aug 27 15:33:18 2054 GMT + Subject: CN=srv03.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:12:6c:5b:72:db:b4:68:44:ee:c1:3d:91:48:f7: + 23:39:57:ae:31:21:41:8c:7b:8a:38:2d:80:40:e9: + c2:a1:14:50:95:3b:47:d7:ea:1e:9b:3b:4c:20:87: + 67:c2:81:86:d6:3a:ad:97:e9:0d:57:ff:1d:fa:81: + 52:42:ce:05:d2:05:73:cd:92:d7:4c:23:19:22:f5: + cb:6d:44:4b:d7:a3:57:26:10:b2:a5:fe:7f:8f:5c: + 38:31:71:b8:3f:45:b3 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv03.crt01.example.com, IP Address:10.53.0.3 + X509v3 Subject Key Identifier: + 6A:4F:85:19:52:0E:08:29:28:1B:96:53:84:97:0E:AA:35:C3:96:27 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 62:05:bb:62:4e:2a:6a:46:00:49:3e:83:b3:a7:ff:40:68:02: + 36:06:1f:e7:c9:47:db:72:09:be:78:bc:e6:c5:b4:8c:51:7c: + d5:93:06:ec:24:ad:11:a7:32:16:3a:55:79:a3:ab:4c:68:10: + 78:f2:e8:24:b3:c0:9c:3a:cd:11:45:7a:22:37:3e:a3:9d:5d: + 3e:ed:91:bd:58:04:2d:f6:6d:2e:0f:61:1d:4f:ab:d7:47:11: + 1b:c7:06:9d:1d:2d:df:85:93:fa:08:dc:27:32:3a:70:37:61: + 7a:58:95:0a:ca:62:ea:28:64:a1:2d:37:0e:7d:f9:0a:6c:71: + 23:20:6a:5d:2d:6b:f2:fe:23:f8:7b:89:51:21:e3:dd:2d:52: + e7:a3:bc:b9:62:86:65:21:de:90:6a:66:f8:ef:25:aa:da:e5: + b7:5f:f1:8e:ab:2d:5a:50:5f:b8:98:8a:00:d0:7b:e3:51:ec: + d8:a5:67:ee:2a:93:b5:62:84:9b:f5:c7:cd:72:de:53:99:a8: + 45:b3:f6:4c:31:58:f2:5c:cd:a3:ec:f1:1c:3a:29:cf:8e:b8: + 60:ba:c3:cd:d9:7d:bd:9a:b0:41:b3:dd:fb:37:0f:56:54:5b: + 5e:99:d1:a7:58:57:ac:9e:52:c5:74:3e:c2:df:72:82:07:bf: + b2:48:87:9e:16:d8:03:3b:3b:a2:0a:03:55:83:69:44:f2:14: + c8:6b:50:20:89:85:16:b4:be:c6:6c:42:91:00:09:d7:55:9f: + c3:0c:9b:5f:58:bf:43:9d:42:ca:f3:25:1f:d8:f4:b2:87:86: + a8:59:60:e9:53:23:2e:27:e8:97:02:d6:a6:91:9a:81:fb:28: + e4:47:86:c3:3a:55:ca:f0:24:1f:be:dd:00:d3:db:6a:20:5c: + a3:b0:7a:5f:d9:a7:9b:35:f7:23:c7:2b:9d:98:f9:5c:89:5a: + 6d:d4:ed:1c:d7:ec:40:0c:b0:c2:92:24:4b:78:a1:ab:7e:27: + cf:19:2c:ec:3a:77 +-----BEGIN CERTIFICATE----- +MIIDYjCCAcqgAwIBAgIJAMWGaDl7HMSgMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yNDA5MDMxNTMzMThaGA8yMDU0MDgy +NzE1MzMxOFowIjEgMB4GA1UEAwwXc3J2MDMuY3J0MDEuZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQSbFty27RoRO7BPZFI9yM5V64xIUGMe4o4LYBA +6cKhFFCVO0fX6h6bO0wgh2fCgYbWOq2X6Q1X/x36gVJCzgXSBXPNktdMIxki9ctt +REvXo1cmELKl/n+PXDgxcbg/RbOjbDBqMCgGA1UdEQQhMB+CF3NydjAzLmNydDAx +LmV4YW1wbGUuY29thwQKNQADMB0GA1UdDgQWBBRqT4UZUg4IKSgbllOElw6qNcOW +JzAfBgNVHSMEGDAWgBR8iehc6+UfckgExY/7kgic9WAmOTANBgkqhkiG9w0BAQsF +AAOCAYEAYgW7Yk4qakYAST6Ds6f/QGgCNgYf58lH23IJvni85sW0jFF81ZMG7CSt +EacyFjpVeaOrTGgQePLoJLPAnDrNEUV6Ijc+o51dPu2RvVgELfZtLg9hHU+r10cR +G8cGnR0t34WT+gjcJzI6cDdheliVCspi6ihkoS03Dn35CmxxIyBqXS1r8v4j+HuJ +USHj3S1S56O8uWKGZSHekGpm+O8lqtrlt1/xjqstWlBfuJiKANB741Hs2KVn7iqT +tWKEm/XHzXLeU5moRbP2TDFY8lzNo+zxHDopz464YLrDzdl9vZqwQbPd+zcPVlRb +XpnRp1hXrJ5SxXQ+wt9ygge/skiHnhbYAzs7ogoDVYNpRPIUyGtQIImFFrS+xmxC +kQAJ11WfwwybX1i/Q51CyvMlH9j0soeGqFlg6VMjLifolwLWppGagfso5EeGwzpV +yvAkH77dANPbaiBco7B6X9mnmzX3I8crnZj5XIlabdTtHNfsQAywwpIkS3ihq34n +zxks7Dp3 +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/index.txt b/bin/tests/system/notify/CA/index.txt new file mode 100644 index 0000000..73de299 --- /dev/null +++ b/bin/tests/system/notify/CA/index.txt @@ -0,0 +1,3 @@ +V 20540827153314Z C58668397B1CC49F unknown /CN=srv02.crt01.example.com +V 20540827153318Z C58668397B1CC4A0 unknown /CN=srv03.crt01.example.com +V 240918161818Z C58668397B1CC4A2 unknown /CN=srv02.crt01-expired.example.com diff --git a/bin/tests/system/notify/CA/index.txt.attr b/bin/tests/system/notify/CA/index.txt.attr new file mode 100644 index 0000000..8f7e63a --- /dev/null +++ b/bin/tests/system/notify/CA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/bin/tests/system/notify/CA/newcerts/C58668397B1CC49F.pem b/bin/tests/system/notify/CA/newcerts/C58668397B1CC49F.pem new file mode 100644 index 0000000..52baf96 --- /dev/null +++ b/bin/tests/system/notify/CA/newcerts/C58668397B1CC49F.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:9f + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 3 15:33:14 2024 GMT + Not After : Aug 27 15:33:14 2054 GMT + Subject: CN=srv02.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:36:6c:27:61:df:82:ed:84:0f:0c:cc:5e:c1:79: + 98:58:7e:f5:0e:0c:51:f7:7d:24:80:26:e4:43:31: + 26:8e:d3:67:f6:f7:8f:84:d8:87:32:f7:55:bd:02: + 11:5e:b5:27:1e:65:ad:03:86:57:5c:69:55:5a:3d: + 59:b7:6e:18:63:bc:b5:06:14:89:85:99:c7:05:b4: + db:50:8f:f9:65:44:26:d8:f5:51:6d:6d:f5:da:63: + f5:6a:e7:6e:37:10:08 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01.example.com, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 4C:A6:2B:5F:55:DF:2E:1E:FA:E8:C6:3F:05:25:20:69:BA:60:3B:E2 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 1d:22:c4:60:42:9a:d8:ac:54:cf:77:be:17:d0:eb:b4:7d:44: + b1:ad:bf:53:0e:be:61:37:bf:7b:a6:78:7e:a0:3f:aa:21:cd: + 09:3a:d4:41:b5:9f:31:a2:c9:db:df:94:a4:05:02:dd:98:04: + 38:55:af:20:3a:4d:82:cd:37:0f:a5:b8:9c:dc:0d:f8:07:c9: + 9d:8e:0a:4f:df:f1:8d:0c:53:9b:56:a2:35:7e:0a:3d:47:89: + ad:76:8f:6c:f5:15:0e:3f:05:af:fb:f8:97:97:a3:91:a6:cf: + 22:04:c0:35:24:84:b4:e5:4d:c0:bf:e0:8d:8b:59:bf:71:2e: + c3:d8:8e:c9:9d:ba:0a:32:cb:0f:b8:b8:e3:91:f9:77:78:55: + 17:9f:6e:09:d6:29:86:25:b6:0d:9b:52:b7:0a:75:f7:cd:09: + 5d:04:83:9f:08:8f:eb:8c:23:73:e0:14:2b:be:ba:22:96:8f: + 68:f8:c7:39:a7:44:9b:1d:ce:cb:eb:04:33:c0:da:b8:03:c0: + 5b:7a:3c:a1:f5:28:92:93:06:f2:32:c3:38:fe:68:5d:64:21: + 6e:3f:8b:80:f8:01:8f:19:5c:fa:13:6c:5e:27:55:19:70:87: + 70:02:80:79:d2:37:d3:d9:05:b1:8e:50:37:24:f0:32:33:bb: + e9:f2:26:f8:19:92:d5:ad:2a:09:c1:b0:48:52:f4:e3:62:cd: + e1:b4:51:d9:0a:88:e3:fb:1e:c9:5c:a5:83:fe:30:9d:cf:83: + 22:ba:1a:cd:c9:a9:e0:3d:cc:8d:f7:68:9e:17:a2:36:78:ab: + 6f:01:de:20:a1:0d:a2:30:12:ee:45:14:b6:f7:c4:e4:d3:4e: + c7:0b:d7:14:b2:49:5c:f8:3a:fc:29:43:fa:97:d1:70:46:54: + c0:a9:c6:eb:f0:91:59:0e:24:8f:e5:38:79:38:fb:86:ab:3c: + b1:ea:d2:a3:4c:2c:e4:29:1a:03:da:54:a0:a6:73:ac:b4:c8: + 02:5a:4c:38:e0:23 +-----BEGIN CERTIFICATE----- +MIIDYjCCAcqgAwIBAgIJAMWGaDl7HMSfMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yNDA5MDMxNTMzMTRaGA8yMDU0MDgy +NzE1MzMxNFowIjEgMB4GA1UEAwwXc3J2MDIuY3J0MDEuZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQ2bCdh34LthA8MzF7BeZhYfvUODFH3fSSAJuRD +MSaO02f294+E2Icy91W9AhFetSceZa0DhldcaVVaPVm3bhhjvLUGFImFmccFtNtQ +j/llRCbY9VFtbfXaY/Vq5243EAijbDBqMCgGA1UdEQQhMB+CF3NydjAyLmNydDAx +LmV4YW1wbGUuY29thwQKNQACMB0GA1UdDgQWBBRMpitfVd8uHvroxj8FJSBpumA7 +4jAfBgNVHSMEGDAWgBR8iehc6+UfckgExY/7kgic9WAmOTANBgkqhkiG9w0BAQsF +AAOCAYEAHSLEYEKa2KxUz3e+F9DrtH1Esa2/Uw6+YTe/e6Z4fqA/qiHNCTrUQbWf +MaLJ29+UpAUC3ZgEOFWvIDpNgs03D6W4nNwN+AfJnY4KT9/xjQxTm1aiNX4KPUeJ +rXaPbPUVDj8Fr/v4l5ejkabPIgTANSSEtOVNwL/gjYtZv3Euw9iOyZ26CjLLD7i4 +45H5d3hVF59uCdYphiW2DZtStwp1980JXQSDnwiP64wjc+AUK766IpaPaPjHOadE +mx3Oy+sEM8DauAPAW3o8ofUokpMG8jLDOP5oXWQhbj+LgPgBjxlc+hNsXidVGXCH +cAKAedI309kFsY5QNyTwMjO76fIm+BmS1a0qCcGwSFL042LN4bRR2QqI4/seyVyl +g/4wnc+DIroazcmp4D3MjfdonheiNnirbwHeIKENojAS7kUUtvfE5NNOxwvXFLJJ +XPg6/ClD+pfRcEZUwKnG6/CRWQ4kj+U4eTj7hqs8serSo0ws5CkaA9pUoKZzrLTI +AlpMOOAj +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A0.pem b/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A0.pem new file mode 100644 index 0000000..0d45e7a --- /dev/null +++ b/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A0.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:a0 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 3 15:33:18 2024 GMT + Not After : Aug 27 15:33:18 2054 GMT + Subject: CN=srv03.crt01.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:12:6c:5b:72:db:b4:68:44:ee:c1:3d:91:48:f7: + 23:39:57:ae:31:21:41:8c:7b:8a:38:2d:80:40:e9: + c2:a1:14:50:95:3b:47:d7:ea:1e:9b:3b:4c:20:87: + 67:c2:81:86:d6:3a:ad:97:e9:0d:57:ff:1d:fa:81: + 52:42:ce:05:d2:05:73:cd:92:d7:4c:23:19:22:f5: + cb:6d:44:4b:d7:a3:57:26:10:b2:a5:fe:7f:8f:5c: + 38:31:71:b8:3f:45:b3 + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv03.crt01.example.com, IP Address:10.53.0.3 + X509v3 Subject Key Identifier: + 6A:4F:85:19:52:0E:08:29:28:1B:96:53:84:97:0E:AA:35:C3:96:27 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 62:05:bb:62:4e:2a:6a:46:00:49:3e:83:b3:a7:ff:40:68:02: + 36:06:1f:e7:c9:47:db:72:09:be:78:bc:e6:c5:b4:8c:51:7c: + d5:93:06:ec:24:ad:11:a7:32:16:3a:55:79:a3:ab:4c:68:10: + 78:f2:e8:24:b3:c0:9c:3a:cd:11:45:7a:22:37:3e:a3:9d:5d: + 3e:ed:91:bd:58:04:2d:f6:6d:2e:0f:61:1d:4f:ab:d7:47:11: + 1b:c7:06:9d:1d:2d:df:85:93:fa:08:dc:27:32:3a:70:37:61: + 7a:58:95:0a:ca:62:ea:28:64:a1:2d:37:0e:7d:f9:0a:6c:71: + 23:20:6a:5d:2d:6b:f2:fe:23:f8:7b:89:51:21:e3:dd:2d:52: + e7:a3:bc:b9:62:86:65:21:de:90:6a:66:f8:ef:25:aa:da:e5: + b7:5f:f1:8e:ab:2d:5a:50:5f:b8:98:8a:00:d0:7b:e3:51:ec: + d8:a5:67:ee:2a:93:b5:62:84:9b:f5:c7:cd:72:de:53:99:a8: + 45:b3:f6:4c:31:58:f2:5c:cd:a3:ec:f1:1c:3a:29:cf:8e:b8: + 60:ba:c3:cd:d9:7d:bd:9a:b0:41:b3:dd:fb:37:0f:56:54:5b: + 5e:99:d1:a7:58:57:ac:9e:52:c5:74:3e:c2:df:72:82:07:bf: + b2:48:87:9e:16:d8:03:3b:3b:a2:0a:03:55:83:69:44:f2:14: + c8:6b:50:20:89:85:16:b4:be:c6:6c:42:91:00:09:d7:55:9f: + c3:0c:9b:5f:58:bf:43:9d:42:ca:f3:25:1f:d8:f4:b2:87:86: + a8:59:60:e9:53:23:2e:27:e8:97:02:d6:a6:91:9a:81:fb:28: + e4:47:86:c3:3a:55:ca:f0:24:1f:be:dd:00:d3:db:6a:20:5c: + a3:b0:7a:5f:d9:a7:9b:35:f7:23:c7:2b:9d:98:f9:5c:89:5a: + 6d:d4:ed:1c:d7:ec:40:0c:b0:c2:92:24:4b:78:a1:ab:7e:27: + cf:19:2c:ec:3a:77 +-----BEGIN CERTIFICATE----- +MIIDYjCCAcqgAwIBAgIJAMWGaDl7HMSgMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAgFw0yNDA5MDMxNTMzMThaGA8yMDU0MDgy +NzE1MzMxOFowIjEgMB4GA1UEAwwXc3J2MDMuY3J0MDEuZXhhbXBsZS5jb20wdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQSbFty27RoRO7BPZFI9yM5V64xIUGMe4o4LYBA +6cKhFFCVO0fX6h6bO0wgh2fCgYbWOq2X6Q1X/x36gVJCzgXSBXPNktdMIxki9ctt +REvXo1cmELKl/n+PXDgxcbg/RbOjbDBqMCgGA1UdEQQhMB+CF3NydjAzLmNydDAx +LmV4YW1wbGUuY29thwQKNQADMB0GA1UdDgQWBBRqT4UZUg4IKSgbllOElw6qNcOW +JzAfBgNVHSMEGDAWgBR8iehc6+UfckgExY/7kgic9WAmOTANBgkqhkiG9w0BAQsF +AAOCAYEAYgW7Yk4qakYAST6Ds6f/QGgCNgYf58lH23IJvni85sW0jFF81ZMG7CSt +EacyFjpVeaOrTGgQePLoJLPAnDrNEUV6Ijc+o51dPu2RvVgELfZtLg9hHU+r10cR +G8cGnR0t34WT+gjcJzI6cDdheliVCspi6ihkoS03Dn35CmxxIyBqXS1r8v4j+HuJ +USHj3S1S56O8uWKGZSHekGpm+O8lqtrlt1/xjqstWlBfuJiKANB741Hs2KVn7iqT +tWKEm/XHzXLeU5moRbP2TDFY8lzNo+zxHDopz464YLrDzdl9vZqwQbPd+zcPVlRb +XpnRp1hXrJ5SxXQ+wt9ygge/skiHnhbYAzs7ogoDVYNpRPIUyGtQIImFFrS+xmxC +kQAJ11WfwwybX1i/Q51CyvMlH9j0soeGqFlg6VMjLifolwLWppGagfso5EeGwzpV +yvAkH77dANPbaiBco7B6X9mnmzX3I8crnZj5XIlabdTtHNfsQAywwpIkS3ihq34n +zxks7Dp3 +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A2.pem b/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A2.pem new file mode 100644 index 0000000..1ccfd32 --- /dev/null +++ b/bin/tests/system/notify/CA/newcerts/C58668397B1CC4A2.pem @@ -0,0 +1,76 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + c5:86:68:39:7b:1c:c4:a2 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 17 16:18:18 2024 GMT + Not After : Sep 18 16:18:18 2024 GMT + Subject: CN=srv02.crt01-expired.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (384 bit) + pub: + 04:fe:00:66:4c:db:44:7f:02:79:5b:98:93:a8:67: + 8a:87:5a:07:0f:84:40:c8:67:7f:b9:af:32:18:a7: + 22:fa:ed:a7:56:da:17:a7:45:9d:ac:fd:42:cc:8b: + fb:ff:3a:92:d8:7e:e4:fc:7f:54:68:44:7c:61:25: + 42:b4:92:9b:b5:cb:1d:51:d2:61:08:f7:89:22:9b: + 0d:8e:72:99:df:d9:51:c8:92:c9:a5:f8:3f:2d:11: + e9:34:87:49:5c:cc:2d + ASN1 OID: secp384r1 + NIST CURVE: P-384 + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv02.crt01-expired.example.com, IP Address:10.53.0.2 + X509v3 Subject Key Identifier: + 03:4C:AC:DE:C0:A3:EB:04:56:1C:10:47:EB:C9:4D:1A:5F:FD:8E:A1 + X509v3 Authority Key Identifier: + 7C:89:E8:5C:EB:E5:1F:72:48:04:C5:8F:FB:92:08:9C:F5:60:26:39 + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 25:33:d0:30:6e:60:5e:f3:29:e7:1d:36:83:4d:cd:06:d2:35: + df:80:76:25:e5:56:c6:e7:5f:cb:70:c8:30:da:a1:15:50:1b: + 5d:e0:7b:01:60:47:32:ee:ea:98:cd:27:c2:2e:b8:d5:4a:2f: + 76:7b:f1:0d:ff:c3:b3:74:f9:98:37:c1:07:85:04:55:8f:42: + 25:b7:21:03:50:83:50:01:6a:88:84:bc:83:2c:48:3f:e5:96: + 04:d7:b5:56:68:7c:fe:d9:06:e2:bc:f0:fd:47:fd:4b:4c:9b: + 15:ca:ab:10:e4:8d:8f:b5:f7:dd:69:8c:9d:06:00:8f:80:5b: + 30:a6:6c:31:d2:b8:4b:cf:10:2a:bf:64:fb:be:da:3f:e2:ee: + f1:6c:74:02:a7:c5:0c:e2:13:f1:54:63:a9:45:43:7b:b7:85: + a3:48:00:62:34:db:ac:a1:b6:b8:76:b9:d9:aa:17:a2:f9:0b: + 96:87:ad:da:5e:95:50:2b:73:17:d7:2c:d0:43:40:e3:e9:80: + e2:87:be:1d:65:68:17:0d:90:98:0a:9b:6d:4f:2d:91:3e:f0: + 16:4e:c0:c3:e7:a9:a6:e8:bf:8e:b6:d0:3b:72:e6:d9:9a:b3: + 70:82:23:c1:02:c2:cc:91:d7:75:19:3c:79:33:ea:86:8d:80: + 9a:6b:f2:93:b4:dc:22:19:11:82:3d:62:1d:e5:58:58:7f:50: + 84:b0:d4:5a:67:be:d0:28:b0:be:a1:7f:9d:1b:a2:98:9b:70: + 5a:c0:a8:c5:03:ec:de:8a:e2:ea:03:2d:4e:9f:6c:7d:d8:0e: + 41:3c:58:df:3f:1e:4f:69:04:68:54:59:58:ef:dd:e3:32:b3: + 2c:b4:cc:40:28:eb:3e:3b:37:fd:42:f7:d9:60:bf:fa:6d:87: + ca:ed:43:24:93:47:a8:bc:54:cc:c9:4d:ac:d0:b8:09:cb:85: + c3:02:55:73:bf:f0:ff:a3:fc:d2:d1:ae:ea:5a:96:6a:76:51: + fb:da:d9:ad:e4:cd +-----BEGIN CERTIFICATE----- +MIIDcDCCAdigAwIBAgIJAMWGaDl7HMSiMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNVBAcMB0toYXJr +aXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1bTEcMBoGA1UE +AwwTY2EudGVzdC5leGFtcGxlLmNvbTAeFw0yNDA5MTcxNjE4MThaFw0yNDA5MTgx +NjE4MThaMCoxKDAmBgNVBAMMH3NydjAyLmNydDAxLWV4cGlyZWQuZXhhbXBsZS5j +b20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT+AGZM20R/AnlbmJOoZ4qHWgcPhEDI +Z3+5rzIYpyL67adW2henRZ2s/ULMi/v/OpLYfuT8f1RoRHxhJUK0kpu1yx1R0mEI +94kimw2Ocpnf2VHIksml+D8tEek0h0lczC2jdDByMDAGA1UdEQQpMCeCH3NydjAy +LmNydDAxLWV4cGlyZWQuZXhhbXBsZS5jb22HBAo1AAIwHQYDVR0OBBYEFANMrN7A +o+sEVhwQR+vJTRpf/Y6hMB8GA1UdIwQYMBaAFHyJ6Fzr5R9ySATFj/uSCJz1YCY5 +MA0GCSqGSIb3DQEBCwUAA4IBgQAlM9AwbmBe8ynnHTaDTc0G0jXfgHYl5VbG51/L +cMgw2qEVUBtd4HsBYEcy7uqYzSfCLrjVSi92e/EN/8OzdPmYN8EHhQRVj0IltyED +UINQAWqIhLyDLEg/5ZYE17VWaHz+2QbivPD9R/1LTJsVyqsQ5I2PtffdaYydBgCP +gFswpmwx0rhLzxAqv2T7vto/4u7xbHQCp8UM4hPxVGOpRUN7t4WjSABiNNusoba4 +drnZqhei+QuWh63aXpVQK3MX1yzQQ0Dj6YDih74dZWgXDZCYCpttTy2RPvAWTsDD +56mm6L+OttA7cubZmrNwgiPBAsLMkdd1GTx5M+qGjYCaa/KTtNwiGRGCPWId5VhY +f1CEsNRaZ77QKLC+oX+dG6KYm3BawKjFA+zeiuLqAy1On2x92A5BPFjfPx5PaQRo +VFlY793jMrMstMxAKOs+Ozf9QvfZYL/6bYfK7UMkk0eovFTMyU2s0LgJy4XDAlVz +v/D/o/zS0a7qWpZqdlH72tmt5M0= +-----END CERTIFICATE----- diff --git a/bin/tests/system/notify/CA/private/CA.key b/bin/tests/system/notify/CA/private/CA.key new file mode 100644 index 0000000..2d5419d --- /dev/null +++ b/bin/tests/system/notify/CA/private/CA.key @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEAouoRHoAc6VCmxNTU6Ge7s+xDFGO0wXJJIsP+8nUyyjWvGCOC +aQYLhb1kLA2NHRhSSKFcMh8jcd7Hlvy6CAec1j2dsWzryy3HgPrdjWaW3PfBO41D +lUtdt8hA/p6pX2YwqvWbdK/3s8J0LY5xRZKNZnFOB/Sb4PGiIJ1NgMRO/M3IlPQm +PO/faRRTU4SI26KCPKFW342826Zi88YwOd6w5mQU4fskk5TGtlNqE+Fj40ZbWVpy +VXoEUS6RveRp020NX5CQG49SLtdF05AnnsATqmgNVCXptGuqW8uaHRONeGO3NBEy +nJmibWBDUMjtCCcGVgyrVXuTkyAJJWpImnshUwgMNYebRwmC2iVv2LtsJS5eUTUH +EWffnFl55XU2PkyNYgY35gA4y3SiWFJYV8+5FibU4ut0nb+lmHBF8WlqcU/kd3tp +Gkf0exjqOIHZFqV9bIhpUbXhxx9v9+gkkGQ9nrXE1KRlvigxxUeIK5xHy9a7fVIL +wo6WuCnLLJmbVkklAgMBAAECggGBAI5ZV3v/FUQIZK+4CBDKEwizeClotZgR9DWc +bDgOj8KABe5hmKGL1qWVRuH3NUYm6j7sP1LMQnxM3LjhOuupOzE3xYIyWhW+eoQI +r23OJiQNl5ohZNweblUXdTMGD5h8AipfUOY0m4tGbZ0gyXixBTxt5HCvG0UB3VgC +GqZY4Wujo5ADhSXZsqxuRiDDvZGr/YBcuTu87Tg/ulam5ZyrKIcnC9gpSVxqsva9 +DAMy/cSoxUjd7ukhJISK3G3AF3fV4GSslQcJTlyJ2D3+LnqPuHJKYTI4hc46lN3x +E2g24GdSCPYf6SoEPwACXtbavV8TXwQPJrHN+f+0/ePCI4jkYe5NoA3gwVgMb/WB +wFchxzVh3V4e8tPGiG+ofKl81DSAW8VZCJLUIbTEce9oxafPT78WJxdC0wWbh5S8 +V/qN6sW/yWnK3oY9SilWhJGRwKOZ+8xtStaDeCzyCaOqEcWi8ZR0QfC33UozlhdC +SrMKnOXmn/rUuXGrVR56IzIl0M7YAQKBwQDM3GJDdlFuHn6L0syKYdHDS8gXD9ke +s+ochIP6jvkEPcayaEoZGl8s7RT3iztqXod7wLaZdotktxfDAZnJfeuOcVrCu+Bx +HLytnBvV6czMfp3REGgQAJQeusSgtlBCTHHVOsDzIjdnkY3WBa7IiFYWO5wnYrGx +r3ucnwnHaUVDMj1r4YI7mYIpCuYQl6eGyW7mhWewyhVwoQXKbifdrXxjvOigL0Cp +tgsoU9pql3hpphOaYMX6hLOincTfaMxfnCECgcEAy5UXp3dA0OwK+4iDGKr+cUpk +AtGTheiE+8zEVh2KYFLt921mW/QZiB1+xtnkknp3c7u07Ugk8jAEXzCkwMnN5ZCx +LrJ72fC+cLIAbRm6/vMMP8iz83wyttao4qNMeoOBBfE9rEiP+lrugpv282V3ZHYa +IUZWTeugJbckUHTbD3RZQExmQcRVG3m/TzonBfoZ8HoRj/n3d7V2T911cHUhi8Xn +RQIi2m63VofOIep86LgartlKneMWnL0oOPq4RKyFAoHAZUzpDkD4nUJZAx025Yrf +ZfoYNEcy7vq6XmWsuX5vZoiBs4DcezNOMvH9NzdTJxMdXbV61cIHxcK/7j7hZABv +NZ2Z6sdqgaRbLGIQZaPaEJjfwxygyKDwnY1vY6UjZNVWSMFn3hJiYUVZZKakuiao +ow/Q9KzZ/2ot7tG5zTCh/ktekfUOKBiNg2wPPc8wGPeMblMzZflXxrzpFyOHdRev +dcZZJbSX/hO1yrhEPgculNd5xBHsdCegiF4JlwvEW9bhAoHAZQQiy5bx03j8bhkr +q6bVQFPAUmG5iL16lxLg7TYVPnyH1bk0DDaQIKk6CeN+dmxML2IZgY/FvWK0GKOj +bIH2J43nTRuFNvwtEvBQI9KbpfvlvRSSriOXaoATJvoObdAoylEM4BrVTk2mgapw +HA/h8Thk+NPU6S8ctPouC7ogJIf/7Va7erC35j0//0kEqgOSsW9wnXdUItMo1LI3 +nsiQD7Hwcp5/utErKcWTM+MNfdA0dUQesT9ILhfyCGvn2TOdAoHBAKldZkDyRcu9 +r9uDF1bhUEnpV2k4hgvTuCvQ3rzyx3WrVT8ChEmePC8Ke5A54ffu/YdbpDLbdf2c +j4n5CQhHbMIZs3P2hB3WqDCImApCfMbXaltfBbaT0j7uLJPMp+2+f/wWYpc3R+bn +HVnaRI2PoXXmG9OjQSQdVZ5gNpkEuemAo3dJOSS6BMqQaSxUynGy7o/a/d4izBjd +B58Fwq3sZI/Xv90Se9+b6ICST3YJ3p0vn8RKzmlCQjLg/xynpCByiw== +-----END RSA PRIVATE KEY----- diff --git a/bin/tests/system/notify/CA/serial b/bin/tests/system/notify/CA/serial new file mode 100644 index 0000000..82f4fbe --- /dev/null +++ b/bin/tests/system/notify/CA/serial @@ -0,0 +1 @@ +C58668397B1CC4A3 diff --git a/bin/tests/system/notify/dhparam3072.pem b/bin/tests/system/notify/dhparam3072.pem new file mode 100644 index 0000000..fb31ccd --- /dev/null +++ b/bin/tests/system/notify/dhparam3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 +7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 +nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu +N///////////AgEC +-----END DH PARAMETERS----- diff --git a/bin/tests/system/notify/ns1/named.conf.in b/bin/tests/system/notify/ns1/named.conf.in new file mode 100644 index 0000000..3f20cf1 --- /dev/null +++ b/bin/tests/system/notify/ns1/named.conf.in @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + # invalid notify-source-v6 address + notify-source-v6 fd92:7065:b8e:fffe::a35:5; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/notify/ns1/root.db b/bin/tests/system/notify/ns1/root.db new file mode 100644 index 0000000..77b876b --- /dev/null +++ b/bin/tests/system/notify/ns1/root.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +; sends NOTIFY using invalid notify-source-v6 address +. NS other.root-servers.nil. +other.root-servers.nil. AAAA fd92:7065:b8e:fffe::a35:4 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/notify/ns2/example1.db b/bin/tests/system/notify/ns2/example1.db new file mode 100644 index 0000000..3b8d33b --- /dev/null +++ b/bin/tests/system/notify/ns2/example1.db @@ -0,0 +1,144 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 1 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example. NS ns3.example. +ns3.example. A 10.53.0.3 + +$ORIGIN example. +a A 10.0.0.1 +$TTL 3600 ; 1 hour +a01 A 0.0.0.0 +a02 A 255.255.255.255 +a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01 AFSDB 0 hostname +afsdb02 AFSDB 65535 . +$TTL 300 ; 5 minutes +b CNAME foo.net. +c A 73.80.65.49 +$TTL 3600 ; 1 hour +cert01 CERT 65534 65535 PRIVATEOID ( + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +cname01 CNAME cname-target. +cname02 CNAME cname-target +cname03 CNAME . +$TTL 300 ; 5 minutes +d A 73.80.65.49 +$TTL 3600 ; 1 hour +dname01 DNAME dname-target. +dname02 DNAME dname-target +dname03 DNAME . +$TTL 300 ; 5 minutes +e MX 10 mail + TXT "one" + TXT "three" + TXT "two" + A 73.80.65.49 + A 73.80.65.50 + A 73.80.65.52 + A 73.80.65.51 +f A 73.80.65.52 +$TTL 3600 ; 1 hour +gpos01 GPOS "-22.6882" "116.8652" "250.0" +gpos02 GPOS "" "" "" +hinfo01 HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 HINFO "PC" "NetBSD" +isdn01 ISDN "isdn-address" +isdn02 ISDN "isdn-address" "subaddress" +isdn03 ISDN "isdn-address" +isdn04 ISDN "isdn-address" "subaddress" +key01 KEY 512 255 1 ( + AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR + yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 + GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o + jqf0BaqHT+8= ) +kx01 KX 10 kdc +kx02 KX 10 . +loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01 MG madname +mb02 MG . +mg01 MG mgmname +mg02 MG . +minfo01 MINFO rmailbx emailbx +minfo02 MINFO . . +mr01 MR mrname +mr02 MR . +mx01 MX 10 mail +mx02 MX 10 . +naptr01 NAPTR 0 0 "" "" "" . +naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nsap-ptr01 NSAP-PTR foo. + NSAP-PTR . +nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT ) +nxt02 NXT . ( NSAP-PTR NXT ) +nxt03 NXT . ( A ) +nxt04 NXT . ( 127 ) +ptr01 PTR example. +px01 PX 65535 foo. bar. +px02 PX 65535 . . +rp01 RP mbox-dname txt-dname +rp02 RP . . +rt01 RT 0 intermediate-host +rt02 RT 65535 . +$TTL 300 ; 5 minutes +s NS ns.s +$ORIGIN s.example. +ns A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +sig01 SIG NXT 1 3 3600 20000102030405 ( + 19961211100908 2143 foo + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +srv01 SRV 0 0 0 . +srv02 SRV 65535 65535 65535 old-slow-box.example.com. +$TTL 301 ; 5 minutes 1 second +t A 73.80.65.49 +$TTL 3600 ; 1 hour +txt01 TXT "foo" +txt02 TXT "foo" "bar" +txt03 TXT "foo" +txt04 TXT "foo" "bar" +txt05 TXT "foo bar" +txt06 TXT "foo bar" +txt07 TXT "foo bar" +txt08 TXT "foo\010bar" +txt09 TXT "foo\010bar" +txt10 TXT "foo bar" +txt11 TXT "\"foo\"" +txt12 TXT "\"foo\"" +$TTL 300 ; 5 minutes +u TXT "txt-not-in-nxt" +$ORIGIN u.example. +a A 73.80.65.49 +b A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 ) +wks02 WKS 10.0.0.1 17 ( 0 1 2 53 ) +wks03 WKS 10.0.0.2 6 ( 65535 ) +x2501 X25 "123456789" diff --git a/bin/tests/system/notify/ns2/example2.db b/bin/tests/system/notify/ns2/example2.db new file mode 100644 index 0000000..bc88426 --- /dev/null +++ b/bin/tests/system/notify/ns2/example2.db @@ -0,0 +1,145 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 2 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example. NS ns3.example. +ns3.example. A 10.53.0.3 +ns3.example. AAAA fd92:7065:b8e:ffff::3 + +$ORIGIN example. +a A 10.0.0.2 +$TTL 3600 ; 1 hour +a01 A 0.0.0.0 +a02 A 255.255.255.255 +a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01 AFSDB 0 hostname +afsdb02 AFSDB 65535 . +$TTL 300 ; 5 minutes +b CNAME foo.net. +c A 73.80.65.49 +$TTL 3600 ; 1 hour +cert01 CERT 65534 65535 PRIVATEOID ( + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +cname01 CNAME cname-target. +cname02 CNAME cname-target +cname03 CNAME . +$TTL 300 ; 5 minutes +d A 73.80.65.49 +$TTL 3600 ; 1 hour +dname01 DNAME dname-target. +dname02 DNAME dname-target +dname03 DNAME . +$TTL 300 ; 5 minutes +e MX 10 mail + TXT "one" + TXT "three" + TXT "two" + A 73.80.65.49 + A 73.80.65.50 + A 73.80.65.52 + A 73.80.65.51 +f A 73.80.65.52 +$TTL 3600 ; 1 hour +gpos01 GPOS "-22.6882" "116.8652" "250.0" +gpos02 GPOS "" "" "" +hinfo01 HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 HINFO "PC" "NetBSD" +isdn01 ISDN "isdn-address" +isdn02 ISDN "isdn-address" "subaddress" +isdn03 ISDN "isdn-address" +isdn04 ISDN "isdn-address" "subaddress" +key01 KEY 512 255 1 ( + AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR + yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 + GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o + jqf0BaqHT+8= ) +kx01 KX 10 kdc +kx02 KX 10 . +loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01 MG madname +mb02 MG . +mg01 MG mgmname +mg02 MG . +minfo01 MINFO rmailbx emailbx +minfo02 MINFO . . +mr01 MR mrname +mr02 MR . +mx01 MX 10 mail +mx02 MX 10 . +naptr01 NAPTR 0 0 "" "" "" . +naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nsap-ptr01 NSAP-PTR foo. + NSAP-PTR . +nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT ) +nxt02 NXT . ( NSAP-PTR NXT ) +nxt03 NXT . ( A ) +nxt04 NXT . ( 127 ) +ptr01 PTR example. +px01 PX 65535 foo. bar. +px02 PX 65535 . . +rp01 RP mbox-dname txt-dname +rp02 RP . . +rt01 RT 0 intermediate-host +rt02 RT 65535 . +$TTL 300 ; 5 minutes +s NS ns.s +$ORIGIN s.example. +ns A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +sig01 SIG NXT 1 3 3600 20000102030405 ( + 19961211100908 2143 foo + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +srv01 SRV 0 0 0 . +srv02 SRV 65535 65535 65535 old-slow-box.example.com. +$TTL 301 ; 5 minutes 1 second +t A 73.80.65.49 +$TTL 3600 ; 1 hour +txt01 TXT "foo" +txt02 TXT "foo" "bar" +txt03 TXT "foo" +txt04 TXT "foo" "bar" +txt05 TXT "foo bar" +txt06 TXT "foo bar" +txt07 TXT "foo bar" +txt08 TXT "foo\010bar" +txt09 TXT "foo\010bar" +txt10 TXT "foo bar" +txt11 TXT "\"foo\"" +txt12 TXT "\"foo\"" +$TTL 300 ; 5 minutes +u TXT "txt-not-in-nxt" +$ORIGIN u.example. +a A 73.80.65.49 +b A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 ) +wks02 WKS 10.0.0.1 17 ( 0 1 2 53 ) +wks03 WKS 10.0.0.2 6 ( 65535 ) +x2501 X25 "123456789" diff --git a/bin/tests/system/notify/ns2/example3.db b/bin/tests/system/notify/ns2/example3.db new file mode 100644 index 0000000..dd3371b --- /dev/null +++ b/bin/tests/system/notify/ns2/example3.db @@ -0,0 +1,144 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 3 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example. NS ns3.example. +ns3.example. A 10.53.0.3 + +$ORIGIN example. +a A 10.0.0.3 +$TTL 3600 ; 1 hour +a01 A 0.0.0.0 +a02 A 255.255.255.255 +a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01 AFSDB 0 hostname +afsdb02 AFSDB 65535 . +$TTL 300 ; 5 minutes +b CNAME foo.net. +c A 73.80.65.49 +$TTL 3600 ; 1 hour +cert01 CERT 65534 65535 PRIVATEOID ( + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +cname01 CNAME cname-target. +cname02 CNAME cname-target +cname03 CNAME . +$TTL 300 ; 5 minutes +d A 73.80.65.49 +$TTL 3600 ; 1 hour +dname01 DNAME dname-target. +dname02 DNAME dname-target +dname03 DNAME . +$TTL 300 ; 5 minutes +e MX 10 mail + TXT "one" + TXT "three" + TXT "two" + A 73.80.65.49 + A 73.80.65.50 + A 73.80.65.52 + A 73.80.65.51 +f A 73.80.65.52 +$TTL 3600 ; 1 hour +gpos01 GPOS "-22.6882" "116.8652" "250.0" +gpos02 GPOS "" "" "" +hinfo01 HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 HINFO "PC" "NetBSD" +isdn01 ISDN "isdn-address" +isdn02 ISDN "isdn-address" "subaddress" +isdn03 ISDN "isdn-address" +isdn04 ISDN "isdn-address" "subaddress" +key01 KEY 512 255 1 ( + AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR + yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 + GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o + jqf0BaqHT+8= ) +kx01 KX 10 kdc +kx02 KX 10 . +loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01 MG madname +mb02 MG . +mg01 MG mgmname +mg02 MG . +minfo01 MINFO rmailbx emailbx +minfo02 MINFO . . +mr01 MR mrname +mr02 MR . +mx01 MX 10 mail +mx02 MX 10 . +naptr01 NAPTR 0 0 "" "" "" . +naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nsap-ptr01 NSAP-PTR foo. + NSAP-PTR . +nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT ) +nxt02 NXT . ( NSAP-PTR NXT ) +nxt03 NXT . ( A ) +nxt04 NXT . ( 127 ) +ptr01 PTR example. +px01 PX 65535 foo. bar. +px02 PX 65535 . . +rp01 RP mbox-dname txt-dname +rp02 RP . . +rt01 RT 0 intermediate-host +rt02 RT 65535 . +$TTL 300 ; 5 minutes +s NS ns.s +$ORIGIN s.example. +ns A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +sig01 SIG NXT 1 3 3600 20000102030405 ( + 19961211100908 2143 foo + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +srv01 SRV 0 0 0 . +srv02 SRV 65535 65535 65535 old-slow-box.example.com. +$TTL 301 ; 5 minutes 1 second +t A 73.80.65.49 +$TTL 3600 ; 1 hour +txt01 TXT "foo" +txt02 TXT "foo" "bar" +txt03 TXT "foo" +txt04 TXT "foo" "bar" +txt05 TXT "foo bar" +txt06 TXT "foo bar" +txt07 TXT "foo bar" +txt08 TXT "foo\010bar" +txt09 TXT "foo\010bar" +txt10 TXT "foo bar" +txt11 TXT "\"foo\"" +txt12 TXT "\"foo\"" +$TTL 300 ; 5 minutes +u TXT "txt-not-in-nxt" +$ORIGIN u.example. +a A 73.80.65.49 +b A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 ) +wks02 WKS 10.0.0.1 17 ( 0 1 2 53 ) +wks03 WKS 10.0.0.2 6 ( 65535 ) +x2501 X25 "123456789" diff --git a/bin/tests/system/notify/ns2/example4.db b/bin/tests/system/notify/ns2/example4.db new file mode 100644 index 0000000..86d9bf2 --- /dev/null +++ b/bin/tests/system/notify/ns2/example4.db @@ -0,0 +1,144 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +example IN SOA mname1. . ( + 4 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example. NS ns3.example. +ns3.example. A 10.53.0.3 + +$ORIGIN example. +a A 10.0.0.4 +$TTL 3600 ; 1 hour +a01 A 0.0.0.0 +a02 A 255.255.255.255 +a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01 AFSDB 0 hostname +afsdb02 AFSDB 65535 . +$TTL 300 ; 5 minutes +b CNAME foo.net. +c A 73.80.65.49 +$TTL 3600 ; 1 hour +cert01 CERT 65534 65535 PRIVATEOID ( + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +cname01 CNAME cname-target. +cname02 CNAME cname-target +cname03 CNAME . +$TTL 300 ; 5 minutes +d A 73.80.65.49 +$TTL 3600 ; 1 hour +dname01 DNAME dname-target. +dname02 DNAME dname-target +dname03 DNAME . +$TTL 300 ; 5 minutes +e MX 10 mail + TXT "one" + TXT "three" + TXT "two" + A 73.80.65.49 + A 73.80.65.50 + A 73.80.65.52 + A 73.80.65.51 +f A 73.80.65.52 +$TTL 3600 ; 1 hour +gpos01 GPOS "-22.6882" "116.8652" "250.0" +gpos02 GPOS "" "" "" +hinfo01 HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02 HINFO "PC" "NetBSD" +isdn01 ISDN "isdn-address" +isdn02 ISDN "isdn-address" "subaddress" +isdn03 ISDN "isdn-address" +isdn04 ISDN "isdn-address" "subaddress" +key01 KEY 512 255 1 ( + AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR + yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3 + GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o + jqf0BaqHT+8= ) +kx01 KX 10 kdc +kx02 KX 10 . +loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01 MG madname +mb02 MG . +mg01 MG mgmname +mg02 MG . +minfo01 MINFO rmailbx emailbx +minfo02 MINFO . . +mr01 MR mrname +mr02 MR . +mx01 MX 10 mail +mx02 MX 10 . +naptr01 NAPTR 0 0 "" "" "" . +naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +nsap-ptr01 NSAP-PTR foo. + NSAP-PTR . +nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT ) +nxt02 NXT . ( NSAP-PTR NXT ) +nxt03 NXT . ( A ) +nxt04 NXT . ( 127 ) +ptr01 PTR example. +px01 PX 65535 foo. bar. +px02 PX 65535 . . +rp01 RP mbox-dname txt-dname +rp02 RP . . +rt01 RT 0 intermediate-host +rt02 RT 65535 . +$TTL 300 ; 5 minutes +s NS ns.s +$ORIGIN s.example. +ns A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +sig01 SIG NXT 1 3 3600 20000102030405 ( + 19961211100908 2143 foo + MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi + WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl + d80jEeC8aTrO+KKmCaY= ) +srv01 SRV 0 0 0 . +srv02 SRV 65535 65535 65535 old-slow-box.example.com. +$TTL 301 ; 5 minutes 1 second +t A 73.80.65.49 +$TTL 3600 ; 1 hour +txt01 TXT "foo" +txt02 TXT "foo" "bar" +txt03 TXT "foo" +txt04 TXT "foo" "bar" +txt05 TXT "foo bar" +txt06 TXT "foo bar" +txt07 TXT "foo bar" +txt08 TXT "foo\010bar" +txt09 TXT "foo\010bar" +txt10 TXT "foo bar" +txt11 TXT "\"foo\"" +txt12 TXT "\"foo\"" +$TTL 300 ; 5 minutes +u TXT "txt-not-in-nxt" +$ORIGIN u.example. +a A 73.80.65.49 +b A 73.80.65.49 +$ORIGIN example. +$TTL 3600 ; 1 hour +wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 ) +wks02 WKS 10.0.0.1 17 ( 0 1 2 53 ) +wks03 WKS 10.0.0.2 6 ( 65535 ) +x2501 X25 "123456789" diff --git a/bin/tests/system/notify/ns2/generic.db b/bin/tests/system/notify/ns2/generic.db new file mode 100644 index 0000000..108b552 --- /dev/null +++ b/bin/tests/system/notify/ns2/generic.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 diff --git a/bin/tests/system/notify/ns2/named-tls.conf.in b/bin/tests/system/notify/ns2/named-tls.conf.in new file mode 100644 index 0000000..e069662 --- /dev/null +++ b/bin/tests/system/notify/ns2/named-tls.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls tls-forward-secrecy { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt01.example.com.key"; + cert-file "../CA/certs/srv02.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; + +tls tls-forward-secrecy-mutual-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt01.example.com.key"; + cert-file "../CA/certs/srv02.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-expired { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + key-file "../CA/certs/srv02.crt01-expired.example.com.key"; + cert-file "../CA/certs/srv02.crt01-expired.example.com.pem"; + dhparam-file "../dhparam3072.pem"; +}; diff --git a/bin/tests/system/notify/ns2/named.conf.in b/bin/tests/system/notify/ns2/named.conf.in new file mode 100644 index 0000000..224d5aa --- /dev/null +++ b/bin/tests/system/notify/ns2/named.conf.in @@ -0,0 +1,89 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "named-tls.conf"; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + notify-source-v6 fd92:7065:b8e:ffff::2; + transfer-source 10.53.0.2; + port @PORT@; + include "options-tls.conf"; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + startup-notify-rate 5; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; + // Check that named can handle a empty also-notify. + also-notify { /* empty */ }; +}; + +remote-servers noport { 10.53.0.4; }; +remote-servers x21 port @EXTRAPORT1@ { noport; }; + +zone x1 { + type primary; + file "generic.db"; + also-notify { 10.53.0.3; }; + notify-source 10.53.0.2 port @EXTRAPORT2@; + notify primary-only; +}; +zone x2 { + type primary; + file "generic.db"; + also-notify { 10.53.0.3; }; + notify master-only; # test old syntax +}; + +zone x3 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x4 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x5 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x6 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x7 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x8 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x9 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x10 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x11 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x12 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x13 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x14 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x15 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x16 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x17 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x18 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x19 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x20 { type primary; file "generic.db"; also-notify { 10.53.0.3; }; }; +zone x21 { type primary; file "x21.db"; allow-update { any; }; also-notify { x21; }; }; diff --git a/bin/tests/system/notify/ns2/options-tls.conf.in b/bin/tests/system/notify/ns2/options-tls.conf.in new file mode 100644 index 0000000..29f4df5 --- /dev/null +++ b/bin/tests/system/notify/ns2/options-tls.conf.in @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + tls-port @TLSPORT@; + listen-on tls ephemeral { 10.53.0.2; }; + listen-on port @EXTRAPORT1@ tls tls-forward-secrecy { 10.53.0.2; }; + listen-on port @EXTRAPORT3@ tls tls-forward-secrecy-mutual-tls { 10.53.0.2; }; + listen-on port @EXTRAPORT4@ tls tls-expired { 10.53.0.2; }; diff --git a/bin/tests/system/notify/ns3/generic.db b/bin/tests/system/notify/ns3/generic.db new file mode 100644 index 0000000..42a669e --- /dev/null +++ b/bin/tests/system/notify/ns3/generic.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 diff --git a/bin/tests/system/notify/ns3/named-tls.conf.in b/bin/tests/system/notify/ns3/named-tls.conf.in new file mode 100644 index 0000000..1e1b291 --- /dev/null +++ b/bin/tests/system/notify/ns3/named-tls.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +tls tls-forward-secrecy { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-forward-secrecy-remote-hostname { + protocols { TLSv1.2; }; + ca-file "../CA/CA.pem"; + remote-hostname "srv02.crt01.example.com"; +}; + +tls tls-forward-secrecy-bad-remote-hostname { + protocols { TLSv1.2; }; + ca-file "../CA/CA.pem"; + remote-hostname "srv02-bad.crt01.example.com"; +}; + +tls tls-forward-secrecy-mutual-tls { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + key-file "../CA/certs/srv03.crt01.example.com.key"; + cert-file "../CA/certs/srv03.crt01.example.com.pem"; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +tls tls-expired { + protocols { TLSv1.2; }; + ciphers "HIGH:!kRSA:!aNULL:!eNULL:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!SHA1:!SHA256:!SHA384"; + prefer-server-ciphers yes; + dhparam-file "../dhparam3072.pem"; + ca-file "../CA/CA.pem"; +}; + +zone tls-x1 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 tls ephemeral; }; +}; + +zone tls-x2 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 port @EXTRAPORT1@ tls tls-forward-secrecy; }; +}; + +zone tls-x3 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 port @EXTRAPORT1@ tls tls-forward-secrecy-remote-hostname; }; +}; + +zone tls-x4 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 port @EXTRAPORT1@ tls tls-forward-secrecy-bad-remote-hostname; }; +}; + +zone tls-x5 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 port @EXTRAPORT3@ tls tls-forward-secrecy-mutual-tls; }; +}; + +zone tls-x6 { + type primary; + file "generic.db"; + notify explicit; + also-notify { 10.53.0.2 port @EXTRAPORT4@ tls tls-expired; }; +}; diff --git a/bin/tests/system/notify/ns3/named.conf.in b/bin/tests/system/notify/ns3/named.conf.in new file mode 100644 index 0000000..47a2df8 --- /dev/null +++ b/bin/tests/system/notify/ns3/named.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "named-tls.conf"; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + include "options-tls.conf"; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.2; }; + file "example.bk"; + # non-responsive notify recipient (no reply, no ICMP errors) + also-notify { 10.53.10.53; }; +}; + +zone "notify-source-port-test" { + type primary; + file "notify-source-port-test.db"; + notify-source 10.53.0.3 port @EXTRAPORT2@; +}; diff --git a/bin/tests/system/notify/ns3/notify-source-port-test.db b/bin/tests/system/notify/ns3/notify-source-port-test.db new file mode 100644 index 0000000..221fca1 --- /dev/null +++ b/bin/tests/system/notify/ns3/notify-source-port-test.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +notify-source-port-test. SOA mname1. . ( + 1 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +notify-source-port-test. NS ns2.notify-source-port-test. +ns2.notify-source-port-test. A 10.53.0.2 +notify-source-port-test. NS ns3.notify-source-port-test. +ns3.notify-source-port-test. A 10.53.0.3 diff --git a/bin/tests/system/notify/ns3/options-tls.conf.in b/bin/tests/system/notify/ns3/options-tls.conf.in new file mode 100644 index 0000000..fe3491e --- /dev/null +++ b/bin/tests/system/notify/ns3/options-tls.conf.in @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + tls-port @TLSPORT@; diff --git a/bin/tests/system/notify/ns4/named.conf.in b/bin/tests/system/notify/ns4/named.conf.in new file mode 100644 index 0000000..ce6373d --- /dev/null +++ b/bin/tests/system/notify/ns4/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @EXTRAPORT1@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "x21" { + type secondary; + primaries { 10.53.0.2 port @PORT@; }; + file "x21.bk"; +}; diff --git a/bin/tests/system/notify/ns4/named.port.in b/bin/tests/system/notify/ns4/named.port.in new file mode 100644 index 0000000..8e94a3c --- /dev/null +++ b/bin/tests/system/notify/ns4/named.port.in @@ -0,0 +1 @@ +@EXTRAPORT1@ diff --git a/bin/tests/system/notify/ns5/named.conf.in b/bin/tests/system/notify/ns5/named.conf.in new file mode 100644 index 0000000..5bdaa57 --- /dev/null +++ b/bin/tests/system/notify/ns5/named.conf.in @@ -0,0 +1,71 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key "a" { + algorithm @DEFAULT_HMAC@; + secret "aaaaaaaaaaaaaaaaaaaa"; +}; + +key "b" { + algorithm @DEFAULT_HMAC@; + secret "bbbbbbbbbbbbbbbbbbbb"; +}; + +key "c" { + algorithm @DEFAULT_HMAC@; + secret "cccccccccccccccccccc"; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +view "a" { + match-clients { key "a"; }; + zone "x21" { + type primary; + also-notify { 10.53.0.5 key "b"; 10.53.0.5 key "c"; }; + file "x21.db"; + allow-update { any; }; + }; +}; + +view "b" { + match-clients { key "b"; }; + zone "x21" { + type secondary; + primaries { 10.53.0.5 key "a"; }; + file "x21.bk-b"; + notify no; + }; +}; + +view "c" { + match-clients { key "c"; }; + zone "x21" { + type secondary; + primaries { 10.53.0.5 key "a"; }; + file "x21.bk-c"; + notify no; + }; +}; diff --git a/bin/tests/system/notify/ns5/x21.db b/bin/tests/system/notify/ns5/x21.db new file mode 100644 index 0000000..8f2ac7d --- /dev/null +++ b/bin/tests/system/notify/ns5/x21.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 300 ; refresh (300 seconds) + 300 ; retry (300 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns5 +ns5 A 10.53.0.5 +a A 10.0.0.1 diff --git a/bin/tests/system/notify/setup.sh b/bin/tests/system/notify/setup.sh new file mode 100644 index 0000000..6793a33 --- /dev/null +++ b/bin/tests/system/notify/setup.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +if $FEATURETEST --have-fips-dh; then + copy_setports ns2/named-tls.conf.in ns2/named-tls.conf + copy_setports ns2/options-tls.conf.in ns2/options-tls.conf + copy_setports ns2/named.conf.in ns2/named.conf +else + cp /dev/null ns2/named-tls.conf + cp /dev/null ns2/options-tls.conf + copy_setports ns2/named.conf.in ns2/named.conf +fi +if $FEATURETEST --have-fips-dh; then + copy_setports ns3/named-tls.conf.in ns3/named-tls.conf + copy_setports ns3/options-tls.conf.in ns3/options-tls.conf + copy_setports ns3/named.conf.in ns3/named.conf +else + cp /dev/null ns3/named-tls.conf + cp /dev/null ns3/options-tls.conf + copy_setports ns3/named.conf.in ns3/named.conf +fi +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +copy_setports ns4/named.port.in ns4/named.port + +cp -f ns2/example1.db ns2/example.db +cp -f ns2/generic.db ns2/x21.db diff --git a/bin/tests/system/notify/tests.sh b/bin/tests/system/notify/tests.sh new file mode 100644 index 0000000..223840a --- /dev/null +++ b/bin/tests/system/notify/tests.sh @@ -0,0 +1,244 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck disable=SC2034 +. ../conf.sh + +dig_plus_opts() { + $DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p "${PORT}" "$@" +} + +status=0 +n=0 + +test_start() { + n=$((n + 1)) + echo_i "$* ($n)" + ret=0 +} + +test_end() { + [ $ret = 0 ] || echo_i "failed" + status=$((status + ret)) +} + +# +# Wait up to 10 seconds for the servers to finish starting before testing. +# +for i in 1 2 3 4 5 6 7 8 9 10; do + ret=0 + $DIG +tcp -p "${PORT}" example @10.53.0.2 soa >dig.out.ns2.test$n || ret=1 + grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 + grep "flags:.* aa[ ;]" dig.out.ns2.test$n >/dev/null || ret=1 + $DIG +tcp -p "${PORT}" example @10.53.0.3 soa >dig.out.ns3.test$n || ret=1 + grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 + grep "flags:.* aa[ ;]" dig.out.ns3.test$n >/dev/null || ret=1 + nr=$(grep -c 'x[0-9].*sending notify to' ns2/named.run) + [ "$nr" -ge 23 ] || ret=1 + [ $ret = 0 ] && break + sleep 1 +done + +test_start "checking initial status" + +dig_plus_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "10.0.0.1" dig.out.ns2.test$n >/dev/null || ret=1 + +dig_plus_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +grep "10.0.0.1" dig.out.ns3.test$n >/dev/null || ret=1 + +digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1 + +test_end + +test_start "checking startup notify rate limit" +awk '/x[0-9].*sending notify to/ { + split($2, a, ":"); + this = a[1] * 3600 + a[2] * 60 + a[3]; + if (lasta1 && lasta1 > a[1]) { + fix = 3600 * 24; + } + this += fix; + if (last) { + delta = this - last; + print delta; + + total += delta; + if (!maxdelta || delta > maxdelta) { + maxdelta = delta; + } + if (!mindelta || delta < mindelta) { + mindelta = delta; + } + } + lasta1 = a[1]; + last = this; + count++; +} +END { + average = total / count; + print "mindelta:", mindelta; + print "maxdelta:" maxdelta; + print "count:", count; + print "average:", average; + if (average < 0.180) exit(1); + if (count < 23) exit(1); +}' ns2/named.run >awk.out.ns2.test$n || ret=1 +test_end + +# See [GL#4689] +test_start "checking server behaviour with invalid notify-source-v6 address" +grep "zone ./IN: sending notify to fd92:7065:b8e:fffe::a35:4#" ns1/named.run >/dev/null || ret=1 +grep "dns_request_create: failed address not available" ns1/named.run >/dev/null || ret=1 +test_end + +nextpart ns3/named.run >/dev/null + +sleep 1 # make sure filesystem time stamp is newer for reload. +rm -f ns2/example.db +cp -f ns2/example2.db ns2/example.db +echo_i "reloading with example2 using HUP and waiting up to 45 seconds" +kill -HUP "$(cat ns2/named.pid)" +wait_for_log_re 45 "transfer of 'example/IN' from 10.53.0.2#.*success" ns3/named.run + +test_start "checking notify message was logged" +grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 2$' ns3/named.run >/dev/null || ret=1 +grep 'refused notify from non-primary: fd92:7065:b8e:ffff::2#[0-9][0-9]*$' ns3/named.run >/dev/null || ret=1 +test_end + +if $FEATURETEST --have-fips-dh; then + test_start "checking notify over TLS successful" + grep "zone tls-x1/IN: notify to 10.53.0.2#${TLSPORT} successful" ns3/named.run >/dev/null || ret=1 + grep "zone tls-x2/IN: notify to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1 + grep "zone tls-x3/IN: notify to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1 + grep "zone tls-x5/IN: notify to 10.53.0.2#${EXTRAPORT3} successful" ns3/named.run >/dev/null || ret=1 + test_end + + test_start "checking notify over TLS failed" + grep "zone tls-x4/IN: notify to 10.53.0.2#${EXTRAPORT1} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1 + grep "zone tls-x6/IN: notify to 10.53.0.2#${EXTRAPORT4} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1 + test_end +fi + +test_start "checking example2 loaded" +dig_plus_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "10.0.0.2" dig.out.ns2.test$n >/dev/null || ret=1 +test_end + +test_start "checking example2 contents have been transferred after HUP reload" + +dig_plus_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "10.0.0.2" dig.out.ns2.test$n >/dev/null || ret=1 + +dig_plus_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +grep "10.0.0.2" dig.out.ns3.test$n >/dev/null || ret=1 + +digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1 + +test_end + +echo_i "stopping primary and restarting with example4 then waiting up to 45 seconds" +stop_server ns2 + +rm -f ns2/example.db +cp -f ns2/example4.db ns2/example.db + +start_server --noclean --restart --port "${PORT}" ns2 +wait_for_log_re 45 "transfer of 'example/IN' from 10.53.0.2#.*success" ns3/named.run + +test_start "checking notify message was logged" +grep 'notify from 10.53.0.2#[0-9][0-9]*: serial 4$' ns3/named.run >/dev/null || ret=1 +test_end + +test_start "checking example4 loaded" +dig_plus_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "10.0.0.4" dig.out.ns2.test$n >/dev/null || ret=1 +test_end + +test_start "checking example4 contents have been transferred after restart" + +dig_plus_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "10.0.0.4" dig.out.ns2.test$n >/dev/null || ret=1 + +dig_plus_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 +grep "10.0.0.4" dig.out.ns3.test$n >/dev/null || ret=1 + +digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1 + +test_end + +test_start "checking notify to alternate port with primary server inheritance" +$NSUPDATE <"$fn" || ret=1 + grep "test string" "$fn" >/dev/null && break + sleep 1 +done +grep "test string" "$fn" >/dev/null || ret=1 +test_end + +test_start "checking notify to multiple views using tsig" +$NSUPDATE <"$fnb" || ret=1 + dig_plus_opts added.x21. -y "${DEFAULT_HMAC}:c:cccccccccccccccccccc" @10.53.0.5 \ + txt >"$fnc" || ret=1 + grep "test string" "$fnb" >/dev/null \ + && grep "test string" "$fnc" >/dev/null \ + && break + sleep 1 +done +grep "test string" "$fnb" >/dev/null || ret=1 +grep "test string" "$fnc" >/dev/null || ret=1 +grep "sending notify to 10.53.0.5#[0-9]* : TSIG (b)" ns5/named.run >/dev/null || ret=1 +grep "sending notify to 10.53.0.5#[0-9]* : TSIG (c)" ns5/named.run >/dev/null || ret=1 +test_end + +test_start "checking notify-source uses port option correctly" +grep "10.53.0.3#${EXTRAPORT2}: received notify for zone 'notify-source-port-test'" ns2/named.run >/dev/null || ret=1 +test_end + +# notify messages were sent to unresponsive 10.53.10.53 during the tests +# above, which should time out at some point; we need to wait for them to +# appear in the logs in case the tests run faster than the notify timeouts + +test_start "checking notify to retry over TCP within 45 seconds" +nextpartreset ns3/named.run +wait_for_log 45 'retrying over TCP' ns3/named.run || ret=1 +test_end + +# the TCP timeout is set to 15 seconds, double that for some leeway +test_start "checking notify retries expire within 30 seconds" +nextpartreset ns3/named.run +wait_for_log 30 'retries exceeded' ns3/named.run || ret=1 +test_end + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/notify/tests_sh_notify.py b/bin/tests/system/notify/tests_sh_notify.py new file mode 100644 index 0000000..ff8e9df --- /dev/null +++ b/bin/tests/system/notify/tests_sh_notify.py @@ -0,0 +1,38 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "awk.out.*", + "dig.out.*", + "ns2/example.db", + "ns2/named-tls.conf", + "ns2/options-tls.conf", + "ns2/x21.db*", + "ns3/example.bk", + "ns3/named-tls.conf", + "ns3/options-tls.conf", + "ns4/named.port", + "ns4/x21.bk", + "ns4/x21.bk.jnl", + "ns5/x21.bk-b", + "ns5/x21.bk-b.jnl", + "ns5/x21.bk-c", + "ns5/x21.bk-c.jnl", + "ns5/x21.db.jnl", + ] +) + + +def test_notify(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/nsec3/ns2/named.conf.in b/bin/tests/system/nsec3/ns2/named.conf.in new file mode 100644 index 0000000..924e9d2 --- /dev/null +++ b/bin/tests/system/nsec3/ns2/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +dnssec-policy "nsec3" { + nsec3param; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "nsec3-xfr-inline.kasp" { + type primary; + file "nsec3-xfr-inline.kasp.db"; + dnssec-policy "nsec3"; +}; diff --git a/bin/tests/system/nsec3/ns2/setup.sh b/bin/tests/system/nsec3/ns2/setup.sh new file mode 100644 index 0000000..1cbe02f --- /dev/null +++ b/bin/tests/system/nsec3/ns2/setup.sh @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns2/setup.sh" + +zone="nsec3-xfr-inline.kasp" +echo_i "setting up zone: $zone" +zonefile="${zone}.db" +cp template.db.in "$zonefile" diff --git a/bin/tests/system/nsec3/ns2/template.db.in b/bin/tests/system/nsec3/ns2/template.db.in new file mode 100644 index 0000000..8379c37 --- /dev/null +++ b/bin/tests/system/nsec3/ns2/template.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/nsec3/ns3/named-fips.conf.in b/bin/tests/system/nsec3/ns3/named-fips.conf.in new file mode 100644 index 0000000..4ed7cc0 --- /dev/null +++ b/bin/tests/system/nsec3/ns3/named-fips.conf.in @@ -0,0 +1,155 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +dnssec-policy "nsec" { + // no need to change configuration: if no 'nsec3param' is set, + // NSEC will be used; +}; + +dnssec-policy "nsec3" { + nsec3param; +}; + +dnssec-policy "optout" { + nsec3param optout yes; +}; + +dnssec-policy "nsec3-other" { + nsec3param iterations 0 optout yes salt-length 8; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* This zone starts with NSEC, but will be reconfigured to use NSEC3. */ +zone "nsec-to-nsec3.kasp" { + type primary; + file "nsec-to-nsec3.kasp.db"; + dnssec-policy "nsec"; +}; + +/* These zones use the default NSEC3 settings. */ +zone "nsec3.kasp" { + type primary; + file "nsec3.kasp.db"; + dnssec-policy "nsec3"; +}; + +zone "nsec3-dynamic.kasp" { + type primary; + file "nsec3-dynamic.kasp.db"; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* This zone uses non-default NSEC3 settings. */ +zone "nsec3-other.kasp" { + type primary; + file "nsec3-other.kasp.db"; + dnssec-policy "nsec3-other"; +}; + +/* These zones will be reconfigured to use other NSEC3 settings. */ +zone "nsec3-change.kasp" { + type primary; + file "nsec3-change.kasp.db"; + dnssec-policy "nsec3"; +}; + +zone "nsec3-dynamic-change.kasp" { + type primary; + file "nsec3-dynamic-change.kasp.db"; + inline-signing no; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* The zone will be reconfigured to use opt-out. */ +zone "nsec3-to-optout.kasp" { + type primary; + file "nsec3-to-optout.kasp.db"; + dnssec-policy "nsec3"; +}; + +/* The zone will be reconfigured to disable opt-out. */ +zone "nsec3-from-optout.kasp" { + type primary; + file "nsec3-from-optout.kasp.db"; + dnssec-policy "optout"; +}; + +/* The zone starts with NSEC3, but will be reconfigured to use NSEC. */ +zone "nsec3-to-nsec.kasp" { + type primary; + file "nsec3-to-nsec.kasp.db"; + dnssec-policy "nsec3"; +}; + +/* The zone fails to load, this should not prevent shutdown. */ +zone "nsec3-fails-to-load.kasp" { + type primary; + file "nsec3-fails-to-load.kasp.db"; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* These zones switch from dynamic to inline-signing or vice versa. */ +zone "nsec3-dynamic-to-inline.kasp" { + type primary; + file "nsec3-dynamic-to-inline.kasp.db"; + inline-signing no; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +zone "nsec3-inline-to-dynamic.kasp" { + type primary; + file "nsec3-inline-to-dynamic.kasp.db"; + dnssec-policy "nsec3"; +}; + +/* Test adding a NSEC3 record to an inline-signing dnssec-policy zone. */ +zone "nsec3-dynamic-update-inline.kasp" { + type primary; + file "nsec3-dynamic-update-inline.kasp.db"; + allow-update { any; }; + dnssec-policy "nsec"; +}; + +zone "nsec3-xfr-inline.kasp" { + type secondary; + file "nsec3-xfr-inline.kasp.db"; + dnssec-policy "nsec"; + primaries { 10.53.0.2; }; +}; diff --git a/bin/tests/system/nsec3/ns3/named1.conf.in b/bin/tests/system/nsec3/ns3/named1.conf.in new file mode 100644 index 0000000..9b1235e --- /dev/null +++ b/bin/tests/system/nsec3/ns3/named1.conf.in @@ -0,0 +1,67 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "named-fips.conf"; + +dnssec-policy "rsasha1" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should work despite the incompatible RSAHSHA1 algorithm, + * because the DS is still in hidden state. + */ +zone "rsasha1-to-nsec3.kasp" { + type primary; + file "rsasha1-to-nsec3.kasp.db"; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should block because RSASHA1 is not compatible with NSEC3, + * and the DS is published. + */ +zone "rsasha1-to-nsec3-wait.kasp" { + type primary; + file "rsasha1-to-nsec3-wait.kasp.db"; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should work despite the incompatible RSAHSHA1 + * algorithm, because the DS is still in hidden state. + */ +zone "nsec3-to-rsasha1.kasp" { + type primary; + file "nsec3-to-rsasha1.kasp.db"; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should also be fine because we are allowed + * to change to NSEC with any algorithm, then we can also publish the new + * DNSKEY and signatures of the RSASHA1 algorithm. + */ +zone "nsec3-to-rsasha1-ds.kasp" { + type primary; + file "nsec3-to-rsasha1-ds.kasp.db"; + dnssec-policy "nsec3"; +}; diff --git a/bin/tests/system/nsec3/ns3/named2-fips.conf.in b/bin/tests/system/nsec3/ns3/named2-fips.conf.in new file mode 100644 index 0000000..2c9a2b7 --- /dev/null +++ b/bin/tests/system/nsec3/ns3/named2-fips.conf.in @@ -0,0 +1,157 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +dnssec-policy "nsec" { + // no need to change configuration: if no 'nsec3param' is set, + // NSEC will be used; +}; + +dnssec-policy "nsec3" { + nsec3param; +}; + +dnssec-policy "optout" { + nsec3param optout yes; +}; + +dnssec-policy "nsec3-other" { + nsec3param iterations 0 optout yes salt-length 8; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* This zone starts with NSEC, but will be reconfigured to use NSEC3. */ +zone "nsec-to-nsec3.kasp" { + type primary; + file "nsec-to-nsec3.kasp.db"; + //dnssec-policy "nsec"; + dnssec-policy "nsec3"; +}; + +/* These zones use the default NSEC3 settings. */ +zone "nsec3.kasp" { + type primary; + file "nsec3.kasp.db"; + dnssec-policy "nsec3"; +}; + +zone "nsec3-dynamic.kasp" { + type primary; + file "nsec3-dynamic.kasp.db"; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* This zone uses non-default NSEC3 settings. */ +zone "nsec3-other.kasp" { + type primary; + file "nsec3-other.kasp.db"; + dnssec-policy "nsec3-other"; +}; + +/* These zone will be reconfigured to use other NSEC3 settings. */ +zone "nsec3-change.kasp" { + type primary; + file "nsec3-change.kasp.db"; + //dnssec-policy "nsec3"; + dnssec-policy "nsec3-other"; +}; + +zone "nsec3-dynamic-change.kasp" { + type primary; + file "nsec3-dynamic-change.kasp.db"; + //dnssec-policy "nsec3"; + inline-signing no; + dnssec-policy "nsec3-other"; + allow-update { any; }; +}; + +/* The zone will be reconfigured to use opt-out. */ +zone "nsec3-to-optout.kasp" { + type primary; + file "nsec3-to-optout.kasp.db"; + //dnssec-policy "nsec3"; + dnssec-policy "optout"; +}; + +/* The zone will be reconfigured to disable opt-out. */ +zone "nsec3-from-optout.kasp" { + type primary; + file "nsec3-from-optout.kasp.db"; + //dnssec-policy "optout"; + dnssec-policy "nsec3"; +}; + +/* The zone starts with NSEC3, but will be reconfigured to use NSEC. */ +zone "nsec3-to-nsec.kasp" { + type primary; + file "nsec3-to-nsec.kasp.db"; + //dnssec-policy "nsec3"; + dnssec-policy "nsec"; +}; + +/* The zone fails to load, but is fixed after a reload. */ +zone "nsec3-fails-to-load.kasp" { + type primary; + file "nsec3-fails-to-load.kasp.db"; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* These zones switch from dynamic to inline-signing or vice versa. */ +zone "nsec3-dynamic-to-inline.kasp" { + type primary; + file "nsec3-dynamic-to-inline.kasp.db"; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +zone "nsec3-inline-to-dynamic.kasp" { + type primary; + file "nsec3-inline-to-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "nsec3"; + allow-update { any; }; +}; + +/* + * This zone will have an empty nonterminal node added and a node deleted. + */ +zone "nsec3-ent.kasp" { + type primary; + file "nsec3-ent.kasp.db"; + dnssec-policy "nsec3"; + inline-signing yes; +}; diff --git a/bin/tests/system/nsec3/ns3/named2.conf.in b/bin/tests/system/nsec3/ns3/named2.conf.in new file mode 100644 index 0000000..a883940 --- /dev/null +++ b/bin/tests/system/nsec3/ns3/named2.conf.in @@ -0,0 +1,71 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +include "named-fips.conf"; + +dnssec-policy "rsasha1" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should work despite the incompatible RSAHSHA1 algorithm, + * because the DS is still in hidden state. + */ +zone "rsasha1-to-nsec3.kasp" { + type primary; + file "rsasha1-to-nsec3.kasp.db"; + //dnssec-policy "rsasha1"; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should block because RSASHA1 is not compatible with NSEC3, + * and the DS is published. + */ +zone "rsasha1-to-nsec3-wait.kasp" { + type primary; + file "rsasha1-to-nsec3-wait.kasp.db"; + //dnssec-policy "rsasha1"; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should work despite the incompatible RSAHSHA1 + * algorithm, because the DS is still in hidden state. + */ +zone "nsec3-to-rsasha1.kasp" { + type primary; + file "nsec3-to-rsasha1.kasp.db"; + //dnssec-policy "nsec3"; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should also be fine because we are allowed + * to change to NSEC with any algorithm, then we can also publish the new + * DNSKEY and signatures of the RSASHA1 algorithm. + */ +zone "nsec3-to-rsasha1-ds.kasp" { + type primary; + file "nsec3-to-rsasha1-ds.kasp.db"; + //dnssec-policy "nsec3"; + dnssec-policy "rsasha1"; +}; diff --git a/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in b/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in new file mode 100644 index 0000000..77b0d10 --- /dev/null +++ b/bin/tests/system/nsec3/ns3/nsec3-fails-to-load.kasp.db.in @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ IN SOA kasp. nsec3-fails-to-load.kasp. ( + 1 ; serial + 30 ; refresh (30 seconds) + 10 ; retry (10 seconds) + 3600000 ; expire (5 weeks 6 days 16 hours) + 300 ; minimum (5 minutes) + ) + NS nsec3-fails-to-load.kasp. diff --git a/bin/tests/system/nsec3/ns3/setup.sh b/bin/tests/system/nsec3/ns3/setup.sh new file mode 100644 index 0000000..32ddf5e --- /dev/null +++ b/bin/tests/system/nsec3/ns3/setup.sh @@ -0,0 +1,57 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +echo_i "ns3/setup.sh" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + cp template.db.in "$zonefile" +} + +for zn in nsec-to-nsec3 nsec3 nsec3-other nsec3-change nsec3-to-nsec \ + nsec3-to-optout nsec3-from-optout nsec3-dynamic \ + nsec3-dynamic-change nsec3-dynamic-to-inline \ + nsec3-inline-to-dynamic nsec3-dynamic-update-inline \ + nsec3-ent; do + setup "${zn}.kasp" +done + +if [ $RSASHA1_SUPPORTED = 1 ]; then + for zn in rsasha1-to-nsec3 rsasha1-to-nsec3-wait nsec3-to-rsasha1 \ + nsec3-to-rsasha1-ds; do + setup "${zn}.kasp" + done + + longago="now-1y" + keytimes="-P ${longago} -A ${longago}" + O="omnipresent" + + zone="rsasha1-to-nsec3-wait.kasp" + CSK=$($KEYGEN -k "rsasha1" -l named.conf $keytimes $zone 2>keygen.out.$zone) + echo_i "Created key file $CSK" + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 + + zone="nsec3-to-rsasha1-ds.kasp" + CSK=$($KEYGEN -k "default" -l named.conf $keytimes $zone 2>keygen.out.$zone) + echo_i "Created key file $CSK" + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 +else + echo_i "skip: skip rsasha1 zones - signing with RSASHA1 not supported" +fi + +cp nsec3-fails-to-load.kasp.db.in nsec3-fails-to-load.kasp.db diff --git a/bin/tests/system/nsec3/ns3/template.db.in b/bin/tests/system/nsec3/ns3/template.db.in new file mode 100644 index 0000000..010b05b --- /dev/null +++ b/bin/tests/system/nsec3/ns3/template.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/nsec3/ns3/template2.db.in b/bin/tests/system/nsec3/ns3/template2.db.in new file mode 100644 index 0000000..963606b --- /dev/null +++ b/bin/tests/system/nsec3/ns3/template2.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA mname1. . ( + 2 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 900 ; minimum (15 minutes) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/nsec3/setup.sh b/bin/tests/system/nsec3/setup.sh new file mode 100644 index 0000000..56c3ac2 --- /dev/null +++ b/bin/tests/system/nsec3/setup.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns2/named.conf.in ns2/named.conf +( + cd ns2 + $SHELL setup.sh +) + +if [ $RSASHA1_SUPPORTED = 0 ]; then + copy_setports ns3/named-fips.conf.in ns3/named.conf +else + copy_setports ns3/named-fips.conf.in ns3/named-fips.conf + # includes named-fips.conf + cp ns3/named1.conf.in ns3/named.conf +fi +( + cd ns3 + $SHELL setup.sh +) diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh new file mode 100644 index 0000000..757d181 --- /dev/null +++ b/bin/tests/system/nsec3/tests.sh @@ -0,0 +1,622 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh +# shellcheck source=kasp.sh +. ../kasp.sh + +# Log errors and increment $ret. +log_error() { + echo_i "error: $1" + ret=$((ret + 1)) +} + +# Call dig with default options. +dig_with_opts() { + $DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@" +} + +# Call rndc. +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +# Set zone name ($1) and policy ($2) for testing nsec3. +# Also set the expected number of keys ($3) and DNSKEY TTL ($4). +set_zone_policy() { + ZONE=$1 + POLICY=$2 + NUM_KEYS=$3 + DNSKEY_TTL=$4 + KEYFILE_TTL=$4 + # The CDS digest type in these tests are all the default, + # which is SHA-256 (2). + CDS_SHA256="yes" + CDS_SHA384="no" +} +# Set expected NSEC3 parameters: flags ($1) and salt length ($2). +set_nsec3param() { + FLAGS=$1 + SALTLEN=$2 + # Reset salt. + SALT="" +} + +# Set expected default dnssec-policy keys values. +set_key_default_values() { + key_clear $1 + + set_keyrole $1 "csk" + set_keylifetime $1 "0" + set_keyalgorithm $1 "13" "ECDSAP256SHA256" "256" + set_keysigning $1 "yes" + set_zonesigning $1 "yes" + + set_keystate $1 "GOAL" "omnipresent" + set_keystate $1 "STATE_DNSKEY" "rumoured" + set_keystate $1 "STATE_KRRSIG" "rumoured" + set_keystate $1 "STATE_ZRRSIG" "rumoured" + set_keystate $1 "STATE_DS" "hidden" +} + +# Set expected rsasha1 dnssec-policy keys values. +set_key_rsasha1_values() { + key_clear $1 + + set_keyrole $1 "csk" + set_keylifetime $1 "0" + set_keyalgorithm $1 "5" "RSASHA1" "2048" + set_keysigning $1 "yes" + set_zonesigning $1 "yes" + + set_keystate $1 "GOAL" "omnipresent" + set_keystate $1 "STATE_DNSKEY" "rumoured" + set_keystate $1 "STATE_KRRSIG" "rumoured" + set_keystate $1 "STATE_ZRRSIG" "rumoured" + set_keystate $1 "STATE_DS" "hidden" +} + +# Update the key states. +set_key_states() { + set_keystate $1 "GOAL" "$2" + set_keystate $1 "STATE_DNSKEY" "$3" + set_keystate $1 "STATE_KRRSIG" "$4" + set_keystate $1 "STATE_ZRRSIG" "$5" + set_keystate $1 "STATE_DS" "$6" +} + +# The apex NSEC3PARAM record indicates that it is signed. +_wait_for_nsec3param() { + dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC3PARAM >"dig.out.test$n.wait" || return 1 + grep "${ZONE}\..*IN.*NSEC3PARAM 1 0 0.*${SALT}" "dig.out.test$n.wait" >/dev/null || return 1 + grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" >/dev/null || return 1 + return 0 +} +# The apex NSEC record indicates that it is signed. +_wait_for_nsec() { + dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC >"dig.out.test$n.wait" || return 1 + grep "NS SOA" "dig.out.test$n.wait" >/dev/null || return 1 + grep "${ZONE}\..*IN.*RRSIG" "dig.out.test$n.wait" >/dev/null || return 1 + grep "${ZONE}\..*IN.*NSEC3PARAM" "dig.out.test$n.wait" >/dev/null && return 1 + return 0 +} + +# Wait for the zone to be signed. +wait_for_zone_is_signed() { + n=$((n + 1)) + ret=0 + echo_i "wait for ${ZONE} to be signed with $1 ($n)" + + if [ "$1" = "nsec3" ]; then + retry_quiet 10 _wait_for_nsec3param || log_error "wait for ${ZONE} to be signed failed" + else + retry_quiet 10 _wait_for_nsec || log_error "wait for ${ZONE} to be signed failed" + fi + + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Test: check DNSSEC verify +_check_dnssec_verify() { + dig_with_opts @$SERVER "${ZONE}" AXFR >"dig.out.test$n.axfr.$ZONE" || return 1 + $VERIFY -z -o "$ZONE" "dig.out.test$n.axfr.$ZONE" >"verify.out.test$n.$ZONE" 2>&1 || return 1 + return 0 +} + +# Test: check NSEC in answers +_check_nsec_nsec3param() { + dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM >"dig.out.test$n.nsec3param.$ZONE" || return 1 + grep "NSEC3PARAM" "dig.out.test$n.nsec3param.$ZONE" >/dev/null && return 1 + return 0 +} + +_check_nsec_nxdomain() { + dig_with_opts @$SERVER "nosuchname.${ZONE}" >"dig.out.test$n.nxdomain.$ZONE" || return 1 + grep "${ZONE}.*IN.*NSEC.*NS.*SOA.*RRSIG.*NSEC.*DNSKEY" "dig.out.test$n.nxdomain.$ZONE" >/dev/null || return 1 + grep "NSEC3" "dig.out.test$n.nxdomain.$ZONE" >/dev/null && return 1 + return 0 +} + +check_nsec() { + wait_for_zone_is_signed "nsec" + + n=$((n + 1)) + echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)" + ret=0 + check_keys + retry_quiet 10 _check_apex_dnskey || log_error "bad DNSKEY RRset for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + n=$((n + 1)) + echo_i "verify DNSSEC for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check NSEC3PARAM response for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_nsec_nsec3param || log_error "unexpected NSEC3PARAM in response for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check NXDOMAIN response for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_nsec_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +# Test: check NSEC3 parameters in answers +_check_nsec3_nsec3param() { + dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM >"dig.out.test$n.nsec3param.$ZONE" || return 1 + grep "${ZONE}.*0.*IN.*NSEC3PARAM.*1.*0.*0.*${SALT}" "dig.out.test$n.nsec3param.$ZONE" >/dev/null || return 1 + + if [ -z "$SALT" ]; then + SALT=$(awk '$4 == "NSEC3PARAM" { print $8 }' dig.out.test$n.nsec3param.$ZONE) + fi + return 0 +} + +_check_nsec3_nxdomain() { + dig_with_opts @$SERVER "nosuchname.${ZONE}" >"dig.out.test$n.nxdomain.$ZONE" || return 1 + grep ".*\.${ZONE}.*IN.*NSEC3.*1.${FLAGS}.*0.*${SALT}" "dig.out.test$n.nxdomain.$ZONE" >/dev/null || return 1 + return 0 +} + +check_nsec3() { + wait_for_zone_is_signed "nsec3" + + n=$((n + 1)) + echo_i "check that NSEC3PARAM 1 0 0 ${SALT} is published zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_nsec3_nsec3param || log_error "bad NSEC3PARAM response for ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + n=$((n + 1)) + echo_i "check NXDOMAIN response has correct NSEC3 1 ${FLAGS} 0 ${SALT} for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_nsec3_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) + + n=$((n + 1)) + echo_i "verify DNSSEC for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +} + +start_time="$(TZ=UTC date +%s)" +status=0 +n=0 + +key_clear "KEY1" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + +# Zone: nsec-to-nsec3.kasp. +set_zone_policy "nsec-to-nsec3.kasp" "nsec" 1 3600 +set_server "ns3" "10.53.0.3" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec + +if [ $RSASHA1_SUPPORTED = 1 ]; then + # Zone: rsasha1-to-nsec3.kasp. + set_zone_policy "rsasha1-to-nsec3.kasp" "rsasha1" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + echo_i "initial check zone ${ZONE}" + check_nsec + + # Zone: rsasha1-to-nsec3-wait.kasp. + set_zone_policy "rsasha1-to-nsec3-wait.kasp" "rsasha1" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + echo_i "initial check zone ${ZONE}" + check_nsec + + # Zone: nsec3-to-rsasha1.kasp. + set_zone_policy "nsec3-to-rsasha1.kasp" "nsec3" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + echo_i "initial check zone ${ZONE}" + check_nsec3 + + # Zone: nsec3-to-rsasha1-ds.kasp. + set_zone_policy "nsec3-to-rsasha1-ds.kasp" "nsec3" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + echo_i "initial check zone ${ZONE}" + check_nsec3 +fi + +# Zone: nsec3.kasp. +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-dynamic.kasp. +set_zone_policy "nsec3-dynamic.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-change.kasp. +set_zone_policy "nsec3-change.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Test that NSEC3PARAM TTL is equal to SOA MINIMUM. +n=$((n + 1)) +echo_i "check TTL of NSEC3PARAM in zone $ZONE is equal to SOA MINIMUM ($n)" +ret=0 +dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC3PARAM >"dig.out.test$n" || ret=1 +grep "${ZONE}\..*3600.*IN.*NSEC3PARAM" "dig.out.test$n" >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Update SOA MINIMUM. +cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db" +rndccmd $SERVER reload $ZONE >rndc.reload.test$n.$ZONE || log_error "failed to call rndc reload $ZONE" +_wait_for_new_soa() { + dig_with_opts +noquestion "@${SERVER}" "$ZONE" SOA >"dig.out.soa.test$n" || return 1 + grep "${ZONE}\..*IN.*SOA.*mname1..*..*20.*20.*.1814400.*900" "dig.out.soa.test$n" >/dev/null || return 1 +} +retry_quiet 10 _wait_for_new_soa || log_error "failed to update SOA record in zone $ZONE" + +# Zone: nsec3-dynamic-change.kasp. +set_zone_policy "nsec3-dynamic-change.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-dynamic-to-inline.kasp. +set_zone_policy "nsec3-dynamic-to-inline.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-inline-to-dynamic.kasp. +set_zone_policy "nsec3-inline-to-dynamic.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-to-nsec.kasp. +set_zone_policy "nsec3-to-nsec.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-to-optout.kasp. +set_zone_policy "nsec3-to-optout.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-from-optout.kasp. +set_zone_policy "nsec3-from-optout.kasp" "optout" 1 3600 +set_nsec3param "1" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-other.kasp. +set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600 +set_nsec3param "1" "8" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-xfr-inline.kasp. +# This is a secondary zone, where the primary is signed with NSEC3 but +# the dnssec-policy dictates NSEC. +set_zone_policy "nsec3-xfr-inline.kasp" "nsec" 1 3600 +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec + +# Zone: nsec3-dynamic-update-inline.kasp. +set_zone_policy "nsec3-dynamic-update-inline.kasp" "nsec" 1 3600 +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec + +n=$((n + 1)) +echo_i "dynamic update dnssec-policy zone ${ZONE} with NSEC3 ($n)" +ret=0 +$NSUPDATE >update.out.$ZONE.test$n 2>&1 <"dig.out.nsec3param.test$n" || ret=1 +grep "${ZONE}\..*900.*IN.*NSEC3PARAM" "dig.out.nsec3param.test$n" >/dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +# Using rndc signing -nsec3param (should fail) +echo_i "use rndc signing -nsec3param ${ZONE} to change NSEC3 settings" +rndccmd $SERVER signing -nsec3param 1 1 12 ffff $ZONE >rndc.signing.test$n.$ZONE || log_error "failed to call rndc signing -nsec3param $ZONE" +grep "zone uses dnssec-policy, use rndc dnssec command instead" rndc.signing.test$n.$ZONE >/dev/null || log_error "rndc signing -nsec3param should fail" +check_nsec3 + +# Zone: nsec3-dynamic-change.kasp. (reconfigured) +set_zone_policy "nsec3-dynamic-change.kasp" "nsec3-other" 1 3600 +set_nsec3param "1" "8" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} after reconfig" +check_nsec3 + +# Zone: nsec3-dynamic-to-inline.kasp. (same) +set_zone_policy "nsec3-dynamic-to-inline.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} after reconfig" +check_nsec3 + +# Zone: nsec3-inline-to-dynamic.kasp. (same) +set_zone_policy "nsec3-inline-to-dynamic.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "initial check zone ${ZONE}" +check_nsec3 + +# Zone: nsec3-to-nsec.kasp. (reconfigured) +set_zone_policy "nsec3-to-nsec.kasp" "nsec" 1 3600 +set_nsec3param "1" "8" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} after reconfig" +check_nsec + +# Zone: nsec3-to-optout.kasp. (reconfigured) +# DISABLED: +# There is a bug in the nsec3param building code that thinks when the +# optout bit is changed, the chain already exists. [GL #2216] +#set_zone_policy "nsec3-to-optout.kasp" "optout" 1 3600 +#set_nsec3param "1" "0" +#set_key_default_values "KEY1" +#echo_i "check zone ${ZONE} after reconfig" +#check_nsec3 + +# Zone: nsec3-from-optout.kasp. (reconfigured) +# DISABLED: +# There is a bug in the nsec3param building code that thinks when the +# optout bit is changed, the chain already exists. [GL #2216] +#set_zone_policy "nsec3-from-optout.kasp" "nsec3" 1 3600 +#set_nsec3param "0" "0" +#set_key_default_values "KEY1" +#echo_i "check zone ${ZONE} after reconfig" +#check_nsec3 + +# Zone: nsec3-other.kasp. (same) +set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600 +set_nsec3param "1" "8" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} after reconfig" +check_nsec3 + +# Test NSEC3 and NSEC3PARAM is the same after restart +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} before restart" +check_nsec3 + +# Restart named, NSEC3 should stay the same. +ret=0 +echo "stop ns3" +stop_server --use-rndc --port ${CONTROLPORT} ${DIR} || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +ret=0 +echo "start ns3" +start_server --noclean --restart --port ${PORT} ${DIR} +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +prevsalt="${SALT}" +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +SALT="${prevsalt}" +echo_i "check zone ${ZONE} after restart has salt ${SALT}" +check_nsec3 + +# Zone: nsec3-fails-to-load.kasp. (should be fixed after reload) +cp ns3/template.db.in ns3/nsec3-fails-to-load.kasp.db +rndc_reload ns3 10.53.0.3 + +set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" 1 3600 +set_nsec3param "0" "0" +set_key_default_values "KEY1" +echo_i "check zone ${ZONE} after reload" +check_nsec3 + +# Zone: nsec3-ent.kasp (regression test for #5108) +n=$((n + 1)) +echo_i "check query for newly empty name does not crash ($n)" +set_zone_policy "nsec3-ent.kasp" +set_server "ns3" "10.53.0.3" +# confirm the pre-existing name still exists +dig_with_opts +noquestion "@${SERVER}" c.$ZONE >"dig.out.$ZONE.test$n.1" || ret=1 +grep "c\.nsec3-ent\.kasp\..*IN.*A.*10\.0\.0\.3" "dig.out.$ZONE.test$n.1" >/dev/null || ret=1 +# remove a name, bump the SOA, and reload +sed -e 's/1 *; serial/2/' -e '/^c/d' ns3/template.db.in >ns3/nsec3-ent.kasp.db +rndc_reload ns3 10.53.0.3 +# try the query again +dig_with_opts +noquestion "@${SERVER}" c.$ZONE >"dig.out.$ZONE.test$n.2" || ret=1 +grep "status: NXDOMAIN" "dig.out.$ZONE.test$n.2" >/dev/null || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check queries for new names below ENT do not crash ($n)" +set_zone_policy "nsec3-ent.kasp" +set_server "ns3" "10.53.0.3" +# confirm the ENT name does not exist yet +dig_with_opts +noquestion "@${SERVER}" x.y.z.$ZONE >"dig.out.$ZONE.test$n.1" || ret=1 +grep "status: NXDOMAIN" "dig.out.$ZONE.test$n.1" >/dev/null || ret=1 +# add a name with an ENT, bump the SOA, and reload +sed -e 's/1 *; serial/3/' ns3/template.db.in >ns3/nsec3-ent.kasp.db +echo "x.y.z A 10.0.0.4" >>ns3/nsec3-ent.kasp.db +rndc_reload ns3 10.53.0.3 +# try the query again +dig_with_opts +noquestion "@${SERVER}" x.y.z.$ZONE >"dig.out.$ZONE.test$n.2" || ret=1 +grep "x\.y\.z\.nsec3-ent\.kasp\..*IN.*A.*10\.0\.0\.4" "dig.out.$ZONE.test$n.2" >/dev/null || ret=1 +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/nsec3/tests_sh_nsec3.py b/bin/tests/system/nsec3/tests_sh_nsec3.py new file mode 100644 index 0000000..90476f2 --- /dev/null +++ b/bin/tests/system/nsec3/tests_sh_nsec3.py @@ -0,0 +1,36 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "*.created", + "dig.out.*", + "rndc.reload.*", + "rndc.signing.*", + "update.out.*", + "verify.out.*", + "ns*/dsset-**", + "ns*/K*", + "ns*/settime.out.*", + "ns*/*.db", + "ns*/*.jbk", + "ns*/*.jnl", + "ns*/*.signed", + "ns*/keygen.out.*", + "ns3/named-fips.conf", + ] +) + + +def test_nsec3(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/nslookup/ns1/example.net.db b/bin/tests/system/nslookup/ns1/example.net.db new file mode 100644 index 0000000..73aeeb1 --- /dev/null +++ b/bin/tests/system/nslookup/ns1/example.net.db @@ -0,0 +1,31 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 + +@ 86400 IN SOA ns1 hostmaster ( + 1397051952 ; "SER0" + 5 + 5 + 1814400 + 3600 ) +@ NS ns1 +ns1 A 10.53.0.1 + +a-only A 1.2.3.4 +aaaa-only AAAA 2001::ffff + +dual A 1.2.3.4 + AAAA 2001::ffff + +cname-a-only CNAME a-only +cname-aaaa-only CNAME aaaa-only +cname-dual CNAME dual diff --git a/bin/tests/system/nslookup/ns1/named.conf.in b/bin/tests/system/nslookup/ns1/named.conf.in new file mode 100644 index 0000000..8338a9c --- /dev/null +++ b/bin/tests/system/nslookup/ns1/named.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "example.net" { + type primary; + file "example.net.db"; +}; diff --git a/bin/tests/system/nslookup/setup.sh b/bin/tests/system/nslookup/setup.sh new file mode 100644 index 0000000..5989f88 --- /dev/null +++ b/bin/tests/system/nslookup/setup.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 1 >ns1/example.db + +copy_setports ns1/named.conf.in ns1/named.conf diff --git a/bin/tests/system/nslookup/tests.sh b/bin/tests/system/nslookup/tests.sh new file mode 100644 index 0000000..85dc1d7 --- /dev/null +++ b/bin/tests/system/nslookup/tests.sh @@ -0,0 +1,143 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck disable=SC2086 +. ../conf.sh + +status=0 +n=0 + +n=$((n + 1)) +echo_i "Check that domain names that are too big when applying a search list entry are handled cleanly ($n)" +ret=0 +l=012345678901234567890123456789012345678901234567890123456789012 +t=0123456789012345678901234567890123456789012345678901234567890 +d=$l.$l.$l.$t +$NSLOOKUP -port=${PORT} -domain=$d -type=soa example 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check A only lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} a-only.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check AAAA only lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} aaaa-only.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check dual A + AAAA lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} dual.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +grep "2001::ffff" nslookup.out${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to A only lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} cname-a-only.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to AAAA only lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} cname-aaaa-only.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check CNAME to dual A + AAAA lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} cname-dual.example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(wc -l /dev/null || ret=1 +grep "2001::ffff" nslookup.out${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "Check ANY lookup ($n)" +ret=0 +$NSLOOKUP -port=${PORT} -type=ANY example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1 +lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" nslookup.out${n}) +test $lines -eq 1 || ret=1 +lines=$(grep -c 'origin = ns1\.example\.net' nslookup.out${n}) +test $lines -eq 1 || ret=1 +lines=$(grep -c 'mail addr = hostmaster\.example\.net' nslookup.out${n}) +test $lines -eq 1 || ret=1 +lines=$(grep -c 'nameserver = ns1\.example\.net.' nslookup.out${n}) +test $lines -eq 1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/nslookup/tests_sh_nslookup.py b/bin/tests/system/nslookup/tests_sh_nslookup.py new file mode 100644 index 0000000..0b75844 --- /dev/null +++ b/bin/tests/system/nslookup/tests_sh_nslookup.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "nslookup.err*", + "nslookup.out*", + "ns1/example.db", + ] +) + + +def test_nslookup(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/nsupdate/CA/CA-other.pem b/bin/tests/system/nsupdate/CA/CA-other.pem new file mode 100644 index 0000000..6bdbeda --- /dev/null +++ b/bin/tests/system/nsupdate/CA/CA-other.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEZTCCAs0CFDYlin3oeYDu16bFItl9tGZz1Ra4MA0GCSqGSIb3DQEBCwUAMG4x +CzAJBgNVBAYTAlVBMRcwFQYDVQQIDA5LaGFya2l2IE9ibGFzdDEQMA4GA1UEBwwH +S2hhcmtpdjEMMAoGA1UECgwDSVNDMSYwJAYDVQQLDB1Tb2Z0d2FyZSBFbmdlbmVl +cmluZyAoQklORCA5KTAgFw0yMjA5MDcyMTIzNTBaGA8yMDUyMDgzMDIxMjM1MFow +bjELMAkGA1UEBhMCVUExFzAVBgNVBAgMDktoYXJraXYgT2JsYXN0MRAwDgYDVQQH +DAdLaGFya2l2MQwwCgYDVQQKDANJU0MxJjAkBgNVBAsMHVNvZnR3YXJlIEVuZ2Vu +ZWVyaW5nIChCSU5EIDkpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA +10Xj8dH8/XCfUvhdL/S3E10TnrYY8IIDBmU0lkUR5IHwgP9IYVyR/0Mibg79FAs+ +rvuEDifUK+6wvkpj+BXNVZCspo9/u3cl7dqrLH+1SeUs50OeQnbbTrBl0PuNwvzE +kbk7xwLlVDOyRmmvY/EEu7WkitQZgXSAYgttrk62CuJUQUmwUTX5Jxndsjydk/zW +/DiulTsX+zv8kG5NiwpXCfL6QxBoMZNI4fUmDL3bX1XfHaFA+45GT2lHu07xc+cV +eZIRCo0Nk+fIO53lDol8mmR8/5vna27gRnqEUSU7MZAMG6QBXkotnq3rHnrI/ku6 +dCJW4tbWV/ANQ+TG17g2tygzC/smqTuLqavyP9V5cRrdU9awEqwvy8uVbGkTmUZd +tjkGWCcmBSWJvkH3MRJmijS7rDcb8m/g9+xKe79V1c8durGWvcfMRZZhWaoHyhnH +g9+JLUCC3EUCp/1206w5vTXEQNpqi9Z3AZfgboPzJyji4OeYfcQ5eaIZ3OuIpyQz +AgMBAAEwDQYJKoZIhvcNAQELBQADggGBAKdQkmmyUqcE1by7AeHoxkqFgqUeSAlh +flXi5DD+j5+Op2GAUrx84LGy4+heKEwAkV5Cw2c9IMHmDDMnGe/g4FjBS+dTZsTs +JRXXDR7t20eWiBpvO/3IMqVpPq9CAQY1L9PYAVuVM5cwdzsJXdH82z2BZ3Ttg3GX +NPnybxzD/auC051vqEp28Jzbswd4c3VvTmRnYY7rYNNKnLD7812BIp7lnE6s5X2D +y0PPSYdhscTqfJV0+GDF5hUduOFX1xTcPlXaXfyKLLelqtrw40p3ynww9v/J4mwt +FBV+a8gguM7tCZMoV/VJZghObglV/wpokAQchL/pnxL7+U8JklRqaU4DlxyGZ+K4 +QlR5mJe19ZlkgHePk1MbwNZaTXjaOFirYmZzs4YynOp3iBHrW3CYY3kVlrUpKP08 +o101hce32VxkyST6i5W24MU02O/wuPdyQpN+rJjYv32Axsrh/ePkI5qKew9eZ63i +WzNb7BW1LrHrQ/lXoJ3ekRQd10UX3xhk/w== +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/CA.cfg b/bin/tests/system/nsupdate/CA/CA.cfg new file mode 100644 index 0000000..369e43a --- /dev/null +++ b/bin/tests/system/nsupdate/CA/CA.cfg @@ -0,0 +1,77 @@ +# See ../../doth/CA/ca.cfg for more information + +# certificate authority configuration +[ca] +default_ca = CA_default # The default ca section + +[CA_default] +dir = . +new_certs_dir = $dir/newcerts # new certs dir (must be created) +certificate = $dir/CA.pem # The CA cert +private_key = $dir/private/CA.key # CA private key + +serial = $dir/serial # serial number file for the next certificate + # Update before issuing it: + # xxd -l 8 -u -ps /dev/urandom > ./serial +database = $dir/index.txt # (must be created manually: touch ./index.txt) + +default_days = 10950 # how long to certify for + +#default_crl_days = 30 # the number of days before the +default_crl_days = 10950 # next CRL is due. That is the + # days from now to place in the + # CRL nextUpdate field. If CRL + # is expired, certificate + # verifications will fail even + # for otherwise valid + # certificates. Clients might + # cache the CRL, so the expiry + # period should normally be + # relatively short (default: + # 30) for production CAs. + +default_md = sha256 # digest to use + +policy = policy_default # default policy +email_in_dn = no # Don't add the email into cert DN + +name_opt = ca_default # Subject name display option +cert_opt = ca_default # Certificate display option + +# We need the following in order to copy Subject Alt Name(s) from a +# request to the certificate. +copy_extensions = copy # copy extensions from request + +[policy_default] +countryName = optional +stateOrProvinceName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# default certificate requests settings +[req] +# Options for the `req` tool (`man req`). +default_bits = 3072 # for RSA only +distinguished_name = req_default +string_mask = utf8only +# SHA-1 is deprecated, so use SHA-256 instead. +default_md = sha256 +# do not encrypt the private key file +encrypt_key = no + +[req_default] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name (full name) +localityName = Locality Name (e.g., city) +0.organizationName = Organization Name (e.g., company) +organizationalUnitName = Organizational Unit Name (e.g. department) +commonName = Common Name (e.g. server FQDN or YOUR name) +emailAddress = Email Address +# defaults +countryName_default = UA +stateOrProvinceName_default = Kharkiv Oblast +localityName_default = Kharkiv +0.organizationName_default = ISC +organizationalUnitName_default = Software Engeneering (BIND 9) diff --git a/bin/tests/system/nsupdate/CA/CA.pem b/bin/tests/system/nsupdate/CA/CA.pem new file mode 100644 index 0000000..1f725db --- /dev/null +++ b/bin/tests/system/nsupdate/CA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE3TCCA0WgAwIBAgIUeZPKrvbGEBZaRc2jNczlIsJXyPYwDQYJKoZIhvcNAQEL +BQAwfTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4G +A1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0 +aXVtMRwwGgYDVQQDDBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDEyNDEyNDA1 +NFoYDzIwNTIwMTE3MTI0MDU0WjB9MQswCQYDVQQGEwJVQTEYMBYGA1UECAwPS2hh +cmtpdiBPYmxhc3QnMRAwDgYDVQQHDAdLaGFya2l2MSQwIgYDVQQKDBtJbnRlcm5l +dCBTeXN0ZW1zIENvbnNvcnRpdW0xHDAaBgNVBAMME2NhLnRlc3QuZXhhbXBsZS5j +b20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCi6hEegBzpUKbE1NTo +Z7uz7EMUY7TBckkiw/7ydTLKNa8YI4JpBguFvWQsDY0dGFJIoVwyHyNx3seW/LoI +B5zWPZ2xbOvLLceA+t2NZpbc98E7jUOVS123yED+nqlfZjCq9Zt0r/ezwnQtjnFF +ko1mcU4H9Jvg8aIgnU2AxE78zciU9CY8799pFFNThIjbooI8oVbfjbzbpmLzxjA5 +3rDmZBTh+ySTlMa2U2oT4WPjRltZWnJVegRRLpG95GnTbQ1fkJAbj1Iu10XTkCee +wBOqaA1UJem0a6pby5odE414Y7c0ETKcmaJtYENQyO0IJwZWDKtVe5OTIAklakia +eyFTCAw1h5tHCYLaJW/Yu2wlLl5RNQcRZ9+cWXnldTY+TI1iBjfmADjLdKJYUlhX +z7kWJtTi63Sdv6WYcEXxaWpxT+R3e2kaR/R7GOo4gdkWpX1siGlRteHHH2/36CSQ +ZD2etcTUpGW+KDHFR4grnEfL1rt9UgvCjpa4KcssmZtWSSUCAwEAAaNTMFEwHQYD +VR0OBBYEFHyJ6Fzr5R9ySATFj/uSCJz1YCY5MB8GA1UdIwQYMBaAFHyJ6Fzr5R9y +SATFj/uSCJz1YCY5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGB +AF3y0hvzyZWtmuG1JwIcOcc1aPl1KdRy8bao/5iHYGYYrsdDgcO5/e+y9S/izalc +TdW7SKB5iBOCiE8fBNtToCvGP+fxNxHijpAmTr37G5sWuSo1T1VYFizHWL+df/Ig +TcSvDrEjSnAwaEdNJUWtjoIC4VzNKTLtZf16QIATTzTZa3bfgSetpWS7LhLQbHod +CSGI2QB1LRbqGC+a1Y85QxHv81jWzPWPzXYvnOLrDdQyBMOBcxDzrN4b6zg+5Itz +qGYt+IS71jAH0IhxAyD/U5n1jGJv02BnSq0ynLEOD6gsnZjqAwPbt/PM9pGbtbXO +70Q9rxr+vQc1IISKAEiH3txaEPi10wU98d6LbInJvQrmgHo/ntet8skWNYuxlEzS +wvynuE9KvvQtOTodWt5AePtKrhHdxu527a4CHVp59nYUjKSdMKjvmhMRXM1cNjFE +rA/pyyhozR47w3RzHMJVHw2GJ2B/HeqmxpXr1CmJjoRP38QCR7N+mqiZy85Fq2j2 +8Q== +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/README b/bin/tests/system/nsupdate/CA/README new file mode 100644 index 0000000..13069ca --- /dev/null +++ b/bin/tests/system/nsupdate/CA/README @@ -0,0 +1,2 @@ +Please take a look at the contents of the CA.cfg file for further +instructions and configurations options. diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.key b/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.key new file mode 100644 index 0000000..5e3420e --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCrYC6cYeOJxlIr +vOnhBf0YZUIg9lYWQDPSy5/37yJUp8lVcMpS8OKiWDh/EK0rBeARtmkhfy04Vt3V +5PPepzI19zMqUoCut9Z8NXTDDIrDOhhhaHNiWFb/eCVXHHu+mIgh3RyKE6WaUkiY +2T3EKKZ+mxFWfs4Ju1GJiqgbALVzK0GTsWJAMCnq9qPnvPDpngcrrqmgHU3Z+BhN +g0dOaO5XyFUVhjxtHvUx8d7Pwn5rjiJaxXav0AHeq3oDspYzzKAmrt7EvXaFlseI +5Ea8P8ZUyZWDh5xJDTHdxBdSmeRlSZud863OZghX9IO+XofaQloBKm1o0Y042Riu +Xi5UcosBRZav9aPQKV0ii7TUMK8CNsUt6SnrLOpqfiezcPyHHyvEsTqmwum3wm9G +Y7eWLlPYt83D9LVtsvxXSayfmMn+tPV8k0guk9zpGFRjXxij5xKq/jjwc+UXHv5A +ZYGoj2BGwhbyqJ2xG7zOBd43sqiGR72Nkt7g5UKJuOP4sSQIfpkCAwEAAQKCAYEA +i3PT2fsp3cXcvayXID3wSvayzgHF4YtS4FhEDsuvwvVZtsX2TXGo6fQh3Pvj/dtl +DuTBPbmwQWUmVNRewbKKADHsl6bVAdekmCQjpEhDbkOK7VDCe6do+693qyAJbfnO +5Md5Xr5IBoCohIBaa5Gskd97R0gePvsHiYWj730vKc1sKlOwoIzQv1r92yf7Xg7y +xM/3RcwyuojQtdp6nspyEEp7Oe2mpCEJ4x9vcN5SYxEg0X5Xaw83RkuBGRsscHA0 +GN+4eJ59Ld1R9uktLYvUA06ZdoAVZyblE4xxjk2vueE3K2/kT2ooKHVWulGI+PnF +2xYedZsZkgwLbXcEhPXBo3vMTjzRlePh668ULi9B6ntMjWpCSCvGnz142Uwatfq0 +PeasBVgRngu9Wg+smkA4kHnDi7ih3zpLh6sTcOKL7F1cBgvtjgIyzZDp9eJUEfVH +G/89mTCswhqV1WtQ3n9zbYVbSK9vaAxCrfK50pG+IfHXG9EqnrQPzKsRxNsDpN91 +AoHBANeNLQb3gSk6sBg53smh9oFUEwwgAjHY31ZOOInO4X7udXrtRcON6SCkZjaD +6y1N3Orjama6mr+/eHxJeDEbWBB7INOsaqHewoQF8qaOa7HHmCbXcUIlAQFvaE6e +Qd5e+YHLmbYZbkPfntqWmXuSmk7hUxjnPPOv1P9sgv/3b4TJQJ4FEJasKpWgIOAy +3g8UrjtbI3ITSo3SKCei3wvOCzIdnzwgcHY420jU1yU/oDzN07D4K0iODAbasUl1 +ZH5UvwKBwQDLiNual2aCUtjKAoRLnGDtP6LOYV3eXchBrywIj2tNAMlD7TXbjG04 +Le+I9O+azRorvXQ2WBBIYzka1JozK8WTsxkQYRd9AEy2AsQgPlK5hfy3xcGxSscC +vdxSdQQQ/ASKHHbCTKhDhnA2b2fvLhWxZqsbSO4hSmvjXrSUpGrAABFipK9VqS6Y +Sg6uEo1AlTrwsGW66LHpFeG6YQ0uj4sF0x5mzH7R50And30lVg8DjJASdClzOIWJ +WV+3opbgSqcCgcEAvGGJhJkyrJG57LJG3vlJsmWD8AjZYi8joQ3jo6zGrmRBEBnl +6q5PnFORcPuBwapW9IGkL/vN2t6/sf+Tp3c6U80IN3ZsCuPgI/n+w0mdHVZOx0Nq +nGAyrMps4qi08F8YuDL0N42qLG93KZqMsM7DRUTvlsghIOf+wuxW4NWjBO3OJ0xN +3yDAZtv3X3mVUKDGVOGl7MCnW6LbrShOvsZoSnhQ/f9ryiaOnuxEyyz8IafQ5s09 +Jr/eCu9+GbEbDr2JAoHAXUZg7Z3IupzhAOLaYhROTyvEnrP8YrWz2nY+xcWENQvR +MLH65pyaSQ60IZ2uWND512XBZk5BWAsw1lzsNdsvdpqzN9BnBUAn55mo6+Xj32XK +BSY5t9g/D8CWwasiq+3y3qBgxHaA/kEUF75CcVg7VMtqStzHVLZYbyCtvRkEWu0t +CnnSaH1Z/yyhQaD63sgE9NzCIkAVmG4QvmtPsTDTU14HJrE8xVEnE28tCPlBdCzs +sahOfqE+gU1WEkAOyMctAoHAASVc1KFfBI48tM+cr8vDt1QklVgnKn44DL6HF5tp +iA8/xhB2fHKq6a+xuGxubXo7jo0KbKyYXPFyE5MDrzIDKp0GLUr7WtaunNVMKbKs +B/2YSw+PELoIc5GpiH4lqP5iFYyHKmJighou4oxLcjMlHpRWUERPdxA+L6zggPyJ +56PX2tcezcCZMVm65VpHsX3CqEQyWnFDCt0zclRNFWPKCENsl10emenBZVnxb8fc +smxv7aRpgoWBRa5vinKvOv2T +-----END PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.pem b/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.pem new file mode 100644 index 0000000..f32b4c4 --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.client01.example.nil.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010842 (0x70b9f4eb2fa1959a) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 8 08:20:17 2022 GMT + Not After : Aug 31 08:20:17 2052 GMT + Subject: CN=srv01.client01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:ab:60:2e:9c:61:e3:89:c6:52:2b:bc:e9:e1:05: + fd:18:65:42:20:f6:56:16:40:33:d2:cb:9f:f7:ef: + 22:54:a7:c9:55:70:ca:52:f0:e2:a2:58:38:7f:10: + ad:2b:05:e0:11:b6:69:21:7f:2d:38:56:dd:d5:e4: + f3:de:a7:32:35:f7:33:2a:52:80:ae:b7:d6:7c:35: + 74:c3:0c:8a:c3:3a:18:61:68:73:62:58:56:ff:78: + 25:57:1c:7b:be:98:88:21:dd:1c:8a:13:a5:9a:52: + 48:98:d9:3d:c4:28:a6:7e:9b:11:56:7e:ce:09:bb: + 51:89:8a:a8:1b:00:b5:73:2b:41:93:b1:62:40:30: + 29:ea:f6:a3:e7:bc:f0:e9:9e:07:2b:ae:a9:a0:1d: + 4d:d9:f8:18:4d:83:47:4e:68:ee:57:c8:55:15:86: + 3c:6d:1e:f5:31:f1:de:cf:c2:7e:6b:8e:22:5a:c5: + 76:af:d0:01:de:ab:7a:03:b2:96:33:cc:a0:26:ae: + de:c4:bd:76:85:96:c7:88:e4:46:bc:3f:c6:54:c9: + 95:83:87:9c:49:0d:31:dd:c4:17:52:99:e4:65:49: + 9b:9d:f3:ad:ce:66:08:57:f4:83:be:5e:87:da:42: + 5a:01:2a:6d:68:d1:8d:38:d9:18:ae:5e:2e:54:72: + 8b:01:45:96:af:f5:a3:d0:29:5d:22:8b:b4:d4:30: + af:02:36:c5:2d:e9:29:eb:2c:ea:6a:7e:27:b3:70: + fc:87:1f:2b:c4:b1:3a:a6:c2:e9:b7:c2:6f:46:63: + b7:96:2e:53:d8:b7:cd:c3:f4:b5:6d:b2:fc:57:49: + ac:9f:98:c9:fe:b4:f5:7c:93:48:2e:93:dc:e9:18: + 54:63:5f:18:a3:e7:12:aa:fe:38:f0:73:e5:17:1e: + fe:40:65:81:a8:8f:60:46:c2:16:f2:a8:9d:b1:1b: + bc:ce:05:de:37:b2:a8:86:47:bd:8d:92:de:e0:e5: + 42:89:b8:e3:f8:b1:24:08:7e:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client01.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 07:97:69:51:12:50:6a:e1:02:a0:b0:dc:93:75:16:c4:38:0f: + 5c:b3:47:da:bf:fa:9c:b6:de:c0:ef:38:f7:cc:d9:8d:71:ba: + 51:89:e5:48:36:dd:e1:f8:73:9d:92:80:1c:42:30:69:4f:8c: + 19:5d:f7:1d:03:e4:f2:76:e0:58:7b:c2:76:c4:0a:7e:20:69: + 26:6c:3e:cb:31:45:93:1d:07:5f:45:44:8e:5a:fb:87:17:7b: + 4d:5c:bf:37:bd:5e:ba:5c:22:84:bf:26:21:4a:c4:e9:f9:cb: + 73:de:fc:62:04:96:ad:aa:fd:89:09:5c:74:d6:bd:5f:07:17: + ef:9c:3d:ee:b7:dc:08:11:7f:12:66:ab:c4:ff:43:6d:7f:1e: + 01:b6:d1:19:73:53:18:e4:02:b0:7c:9e:99:63:d8:57:dd:07: + 79:fb:83:39:09:de:76:6e:68:b7:87:81:13:b8:26:e5:1c:c9: + a0:23:e5:97:39:ff:93:c7:8d:08:d8:ce:97:34:fc:ad:22:14: + 89:c0:ae:83:7d:0a:3f:cf:a0:9b:b4:6a:5c:b3:6d:5d:3b:88: + ca:1e:9b:99:54:64:57:58:3c:4c:bd:26:ee:11:c3:13:0b:1d: + f5:fd:d9:37:b0:31:72:6f:1d:e8:ba:43:37:46:f7:71:fe:6d: + 4a:30:33:29:c5:7b:37:8b:7e:06:22:89:a4:46:36:f0:fe:c6: + f5:f0:53:04:c0:35:52:78:6e:10:24:3a:d8:bf:7b:13:2f:98: + bc:69:31:41:68:02:5a:c4:f9:11:a2:6b:3f:c8:e0:d4:b3:80: + af:d2:be:fe:28:70:61:18:ed:8a:de:c4:cb:da:c9:60:94:91: + 76:63:69:8c:6e:96:f5:ba:e7:be:1e:1c:c3:84:b1:8d:e8:31: + f7:66:8c:0d:da:a8:78:57:19:fd:a0:8d:fa:9a:7e:51:1c:d1: + d0:84:07:a2:45:40:2d:c4:6b:e9:9f:86:4a:08:20:8f:9c:79: + 97:e3:7f:2a:14:73 +-----BEGIN CERTIFICATE----- +MIIEVTCCAr2gAwIBAgIIcLn06y+hlZowDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDkwODA4MjAxN1oYDzIwNTIwODMx +MDgyMDE3WjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLm5pbDCC +AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKtgLpxh44nGUiu86eEF/Rhl +QiD2VhZAM9LLn/fvIlSnyVVwylLw4qJYOH8QrSsF4BG2aSF/LThW3dXk896nMjX3 +MypSgK631nw1dMMMisM6GGFoc2JYVv94JVcce76YiCHdHIoTpZpSSJjZPcQopn6b +EVZ+zgm7UYmKqBsAtXMrQZOxYkAwKer2o+e88OmeByuuqaAdTdn4GE2DR05o7lfI +VRWGPG0e9THx3s/CfmuOIlrFdq/QAd6regOyljPMoCau3sS9doWWx4jkRrw/xlTJ +lYOHnEkNMd3EF1KZ5GVJm53zrc5mCFf0g75eh9pCWgEqbWjRjTjZGK5eLlRyiwFF +lq/1o9ApXSKLtNQwrwI2xS3pKess6mp+J7Nw/IcfK8SxOqbC6bfCb0Zjt5YuU9i3 +zcP0tW2y/FdJrJ+Yyf609XyTSC6T3OkYVGNfGKPnEqr+OPBz5Rce/kBlgaiPYEbC +FvKonbEbvM4F3jeyqIZHvY2S3uDlQom44/ixJAh+mQIDAQABoy8wLTArBgNVHREE +JDAighpzcnYwMS5jbGllbnQwMS5leGFtcGxlLm5pbIcECjUAATANBgkqhkiG9w0B +AQsFAAOCAYEAB5dpURJQauECoLDck3UWxDgPXLNH2r/6nLbewO8498zZjXG6UYnl +SDbd4fhznZKAHEIwaU+MGV33HQPk8nbgWHvCdsQKfiBpJmw+yzFFkx0HX0VEjlr7 +hxd7TVy/N71eulwihL8mIUrE6fnLc978YgSWrar9iQlcdNa9XwcX75w97rfcCBF/ +EmarxP9DbX8eAbbRGXNTGOQCsHyemWPYV90HefuDOQnedm5ot4eBE7gm5RzJoCPl +lzn/k8eNCNjOlzT8rSIUicCug30KP8+gm7RqXLNtXTuIyh6bmVRkV1g8TL0m7hHD +Ewsd9f3ZN7Axcm8d6LpDN0b3cf5tSjAzKcV7N4t+BiKJpEY28P7G9fBTBMA1Unhu +ECQ62L97Ey+YvGkxQWgCWsT5EaJrP8jg1LOAr9K+/ihwYRjtit7Ey9rJYJSRdmNp +jG6W9brnvh4cw4Sxjegx92aMDdqoeFcZ/aCN+pp+URzR0IQHokVALcRr6Z+GSggg +j5x5l+N/KhRz +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.key b/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.key new file mode 100644 index 0000000..d8f68ac --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/wIBADANBgkqhkiG9w0BAQEFAASCBukwggblAgEAAoIBgQDAEScXJTqthaA7 +WQsiZGN9uwUyNU9o1RkrzUa94rZCjAjPCQ2ozVjZG3fbF4r88FXy4VD0/ZCqSRVd +6ptaR8QvggdGh/YF7xUCpDyh2vxbdTYS9xJQVfi+DH0hkeKS2EE/cf6yF8BoHQm+ +/MQk7O/SXFKpT9ZdMLiraC456YtbxvBkQve4vbKQMiJovDhwLxSuyHxjBNURsgrx +jhMQsjtp9P464vFYViiTwSiqpxnJkRJD+PUdNFg9Mp8RZ9EfU9Tg1Qx4LG84P+GJ +abUJPBL0qe7lL8VHZaaC+up4SDGJEbYjiiftfB1t6KugKd5A9PKbYSLanCIy9z34 +TOE4p+LDr6Rnf5Sk/VIliU30mtY1upgg8UvJpc+sclgqzTtKPukEMeKadDLVUmA0 +rQyFAmVYQXQqV5E0VTapFFtFzCgn1226VaPdnwAEpEPCr1yvhlOm1adJqjHWXpJ9 +Jt2N9IeKm0joJfTHNMrP4/eEGTtDx2q42m5vha+NDPt86sdznJsCAwEAAQKCAYBv +D3wTHiv3+rTUnICbuoDtSx+OENWCQPb1JRYq5tWNVXwie5GycktV/1QnFE4CRNbu +QuuVPqpQTUJVtDtw0N7Yuc+LMUNJ2x3DEUUeMoqKOBS0krm8SnozKvWQW9MwJmxU +S46DXMida20fSvoAgCGM+mWyEcBa0rl2JB/WzP0QbNDEqRSldsuyJctP1Mat2AuV +pciHWVv7h4BcfVL47Jb+hfQcCO6Vrfx4s9DYHRgEPibZtzPFV2dOu97PKcD65HXL +o30hP9xhhy8nT4oFijEQ9rPi0JvOpvB5bJQ42OAznWByR0uL9ZoXopkYDDemzt7t +D5F9X/2iH9dv3GA0AiPCF6DjyVMwbh/NOt8oxS+NMY2RPlzA+r9SZpCcyPFk1hMi +LHzrPU8dwC2GmaMKB3Uw/bA5ufw3IpcbJIZEBJQ5Ttf7zEFcfDo/jidTz3ZOptOT +kSKoCN73AUlmcx8UoKF9JwcpJq63ww8eef+1HLL5Dk0uM4YSKd15gI6477RgfgEC +gcEA48ZpMdz4mz7rO0CMyPfOLdHOcxHuZI4oJg6gJ1IBxCnIB1mhy6xn+NdkS5Mm +/1S6eFuo+DgabXO/A2xSDrJ4Lnlf4H4OjQKCeJdO9JglHjdTzv7TB8Vm/IdGC0Jk +eDRY1lmkSXcdSmGqPVgd2AHpkcTgLyUb+iIWkIspelsaNNQBHJzd4S/x9Pp/ftrg +CpfwGKsmNia3n3m21lkeTLtKVsPuK8CAJnCDaEI22mhV83x6grPxA0GVFZ0VHfCL +qZVhAoHBANfd/oVKWGTiJzlc+aHJAb4XRROQzCL4yi6uspT3h9QN5QiFD7PhgIOg +mES35mpGocN78oc19zhfD4XLNkLbQuMQhpk0D4MjLfUS/IskFoOJWuQbIBPqrMzY +Z93DDkiBno2As1IN7fZ9amw7Thcf8Qt6yVNFjIMcfk63VmC+AnPUj4KCes7IuGDH +SA/LjjiKgMa3g3I5/HVB6q1dyZQggBF3dCJ/V8ecgtdibUfzvvViZ52Hd7XDs1SX +yCas+IE3ewKBwQC/YSFYBRtZjacmFNl1rkitVQCKzMEp+guf1mAYSZ40TQrFqjj4 +obaGbavWmCCHHpDCufkh/jmuRzdyT9wufyPdoJu/Sws8zaQEYNW1S/S8C66+WHvF +psYeXiarJTC3kvwlthIErDGPIrpgap5AtXKjyPC4jAySwXuGHXdPWCaPxqXcfa0s +HRXGSYdAdfUS0ZCpmXw0uZlFRIYsWZrMy/ztJBkE5+yE37p5qlDeeBXnzGo/UaOq +obr6+w4YJtmiNmECgcEAsSAPqzEgrM7AnpoCn1S+4EpZvL8wMXXw+DMSh5dAVah9 +COudwdzDxb2tk51OLF/+dderXnTSgOfHZeIjiOI+1PAHcYg9Pj5MhG5q2ITpEE9R +TCBRxuXlmkPrnhRiEO6CudsjyK1zV7D69QoIfoMQF3pN3c0QibiEj3RyJPlkK8T7 +aHxF5ozedVKvd35wGUbUebm02rJny5Mly9FMCQZN74cTvQa+cSSkW7UAtGx1gQWY +vbKdcIC/Eidk7Q867VQnAoHBAKqiugBoItfhuN1GUI5bqIx0ya4DSVECpSFiF8h3 +eK+bO7uG4OBH+qoAmC8EqQNVPtivxpsA2aBvdoUMTYPu/S5cVFXcMkEJ1jX8L8IZ +ImE5LXC+SiZO3G9SyHfj+rgwr66G7NWDVJhZ2t/56s4qEdewwR4Vjm99gVvHHAFP +rrkT9jfHVmozRroL/XAMNITZpJw+vwPMwWOaRncjzyyPp0JWt0h+Wv0+A3SjBIh2 +c+Ctg5Ig6vwr2weVc7s/4jz9Kg== +-----END PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.pem b/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.pem new file mode 100644 index 0000000..bbdb6de --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.client02-expired.example.nil.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010843 (0x70b9f4eb2fa1959b) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 7 08:14:18 2022 GMT + Not After : Sep 8 08:14:18 2022 GMT + Subject: CN=srv01.client02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:c0:11:27:17:25:3a:ad:85:a0:3b:59:0b:22:64: + 63:7d:bb:05:32:35:4f:68:d5:19:2b:cd:46:bd:e2: + b6:42:8c:08:cf:09:0d:a8:cd:58:d9:1b:77:db:17: + 8a:fc:f0:55:f2:e1:50:f4:fd:90:aa:49:15:5d:ea: + 9b:5a:47:c4:2f:82:07:46:87:f6:05:ef:15:02:a4: + 3c:a1:da:fc:5b:75:36:12:f7:12:50:55:f8:be:0c: + 7d:21:91:e2:92:d8:41:3f:71:fe:b2:17:c0:68:1d: + 09:be:fc:c4:24:ec:ef:d2:5c:52:a9:4f:d6:5d:30: + b8:ab:68:2e:39:e9:8b:5b:c6:f0:64:42:f7:b8:bd: + b2:90:32:22:68:bc:38:70:2f:14:ae:c8:7c:63:04: + d5:11:b2:0a:f1:8e:13:10:b2:3b:69:f4:fe:3a:e2: + f1:58:56:28:93:c1:28:aa:a7:19:c9:91:12:43:f8: + f5:1d:34:58:3d:32:9f:11:67:d1:1f:53:d4:e0:d5: + 0c:78:2c:6f:38:3f:e1:89:69:b5:09:3c:12:f4:a9: + ee:e5:2f:c5:47:65:a6:82:fa:ea:78:48:31:89:11: + b6:23:8a:27:ed:7c:1d:6d:e8:ab:a0:29:de:40:f4: + f2:9b:61:22:da:9c:22:32:f7:3d:f8:4c:e1:38:a7: + e2:c3:af:a4:67:7f:94:a4:fd:52:25:89:4d:f4:9a: + d6:35:ba:98:20:f1:4b:c9:a5:cf:ac:72:58:2a:cd: + 3b:4a:3e:e9:04:31:e2:9a:74:32:d5:52:60:34:ad: + 0c:85:02:65:58:41:74:2a:57:91:34:55:36:a9:14: + 5b:45:cc:28:27:d7:6d:ba:55:a3:dd:9f:00:04:a4: + 43:c2:af:5c:af:86:53:a6:d5:a7:49:aa:31:d6:5e: + 92:7d:26:dd:8d:f4:87:8a:9b:48:e8:25:f4:c7:34: + ca:cf:e3:f7:84:19:3b:43:c7:6a:b8:da:6e:6f:85: + af:8d:0c:fb:7c:ea:c7:73:9c:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client02-expired.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 18:f1:7c:24:5b:d2:03:b0:60:0e:60:e6:32:f9:a7:47:d1:e4: + bd:3f:a3:21:53:90:84:9a:c6:2c:87:b2:16:28:95:07:a3:2a: + c3:33:8f:60:70:3f:26:58:be:ec:a2:6c:44:89:d3:4e:ef:bb: + ce:af:9b:5f:15:06:03:21:74:e3:6f:2a:dc:5c:19:4e:d3:cb: + ba:c3:5f:d8:76:89:59:50:82:69:5f:a1:ac:9f:be:79:e1:22: + 12:37:f9:d3:2e:00:35:03:03:9d:08:24:45:65:7a:e9:72:31: + e1:67:44:32:17:25:dd:b9:72:eb:c6:40:d7:5d:8d:5f:00:48: + 07:09:0d:3c:4c:a1:f1:05:4b:05:9b:2b:5a:21:09:46:f4:17: + 7a:cf:34:87:ad:bf:ef:bd:56:74:d7:1a:8f:07:ce:70:b1:aa: + 4d:82:4f:08:dc:56:27:f9:21:20:b8:06:c7:29:b4:8e:36:82: + b8:43:85:1c:2d:9f:be:2d:b9:9d:40:de:52:55:6a:2e:0b:28: + 33:fc:f8:1b:70:e9:c5:46:50:f3:05:be:8d:ed:99:ec:f1:8c: + 51:8a:1c:4b:95:f4:c4:dd:cd:42:74:bc:6f:66:64:54:b8:c1: + 6e:c8:3d:e9:fe:10:02:61:50:77:38:b9:b0:b8:13:37:8f:0e: + 5b:49:92:3a:9d:9a:60:51:68:99:8a:d5:7e:92:71:7e:fa:db: + 52:37:4d:f9:0d:6c:3b:79:a3:b9:16:b7:95:00:ea:eb:17:54: + e2:50:d7:a5:08:54:58:2c:79:66:01:4b:95:65:ed:b8:81:f7: + 4c:fa:f8:89:37:ad:d9:dc:c9:75:9d:02:3e:e5:92:b3:03:ab: + 70:69:83:f5:6c:a6:27:7e:2e:fc:9d:b2:59:0a:43:ad:3f:55: + 2f:5d:ec:ef:52:f0:3e:be:b5:d6:e2:c3:91:9d:dd:5d:e1:9e: + e6:18:90:0b:6a:85:f8:e3:83:2a:7c:91:c3:52:1c:6d:aa:2b: + 44:b8:6f:2b:af:6e +-----BEGIN CERTIFICATE----- +MIIEYzCCAsugAwIBAgIIcLn06y+hlZswDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTIyMDkwNzA4MTQxOFoXDTIyMDkwODA4 +MTQxOFowLTErMCkGA1UEAwwic3J2MDEuY2xpZW50MDItZXhwaXJlZC5leGFtcGxl +Lm5pbDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMARJxclOq2FoDtZ +CyJkY327BTI1T2jVGSvNRr3itkKMCM8JDajNWNkbd9sXivzwVfLhUPT9kKpJFV3q +m1pHxC+CB0aH9gXvFQKkPKHa/Ft1NhL3ElBV+L4MfSGR4pLYQT9x/rIXwGgdCb78 +xCTs79JcUqlP1l0wuKtoLjnpi1vG8GRC97i9spAyImi8OHAvFK7IfGME1RGyCvGO +ExCyO2n0/jri8VhWKJPBKKqnGcmREkP49R00WD0ynxFn0R9T1ODVDHgsbzg/4Ylp +tQk8EvSp7uUvxUdlpoL66nhIMYkRtiOKJ+18HW3oq6Ap3kD08pthItqcIjL3PfhM +4Tin4sOvpGd/lKT9UiWJTfSa1jW6mCDxS8mlz6xyWCrNO0o+6QQx4pp0MtVSYDSt +DIUCZVhBdCpXkTRVNqkUW0XMKCfXbbpVo92fAASkQ8KvXK+GU6bVp0mqMdZekn0m +3Y30h4qbSOgl9Mc0ys/j94QZO0PHarjabm+Fr40M+3zqx3OcmwIDAQABozcwNTAz +BgNVHREELDAqgiJzcnYwMS5jbGllbnQwMi1leHBpcmVkLmV4YW1wbGUubmlshwQK +NQABMA0GCSqGSIb3DQEBCwUAA4IBgQAY8XwkW9IDsGAOYOYy+adH0eS9P6MhU5CE +msYsh7IWKJUHoyrDM49gcD8mWL7somxEidNO77vOr5tfFQYDIXTjbyrcXBlO08u6 +w1/YdolZUIJpX6Gsn7554SISN/nTLgA1AwOdCCRFZXrpcjHhZ0QyFyXduXLrxkDX +XY1fAEgHCQ08TKHxBUsFmytaIQlG9Bd6zzSHrb/vvVZ01xqPB85wsapNgk8I3FYn ++SEguAbHKbSONoK4Q4UcLZ++LbmdQN5SVWouCygz/PgbcOnFRlDzBb6N7Zns8YxR +ihxLlfTE3c1CdLxvZmRUuMFuyD3p/hACYVB3OLmwuBM3jw5bSZI6nZpgUWiZitV+ +knF++ttSN035DWw7eaO5FreVAOrrF1TiUNelCFRYLHlmAUuVZe24gfdM+viJN63Z +3Ml1nQI+5ZKzA6twaYP1bKYnfi78nbJZCkOtP1UvXezvUvA+vrXW4sORnd1d4Z7m +GJALaoX444MqfJHDUhxtqitEuG8rr24= +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.key b/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.key new file mode 100644 index 0000000..8a1f5dc --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/AIBADANBgkqhkiG9w0BAQEFAASCBuYwggbiAgEAAoIBgQC0mmOYBK29qym/ +InBUMN/Ha3dduF4LzQ6gbHQ350t40Zbaypl9krHkGgoetBy+7syVjFIDk4XhQENo +hoa8amJt1grK7k+TLe5r33r23PpEpjmALDh8ic3Zo5ns6CtIbYRBPQ4aH2heF4iP +pdpNHDYmrrR+0v6iWdVnOlbCIWUN3Zdv8OW0HoeulzUN9Juu3Io+KKq4oqvunbLF +kfZxmaWGyzGcBdablBNGqZrJpVVfbMzQhCfisbVzOQh/gC8EJpYMjSmbvl7MOa+i +24KCVwfmskrZPch5bmdh80g3qE+fs8+EtlAIPemF6al2UIDnLG9llcviI0FYOXDn +eCk9wtYgfCuHML2Yh2PtSq257XpLE6E9Yl62dGTvJaPdk0eq0yV+KtcJG1xZUPHU +xpzyZIp8y8xSN1CIS4Q1QFEOoQaiYLaw44/52I5Fd30OfRGSIhUPozeExCXcFLQg +ercWlnLUv01d0qtxQ0S+h0TSuHT3hj/SXd1e5nSr+8yjXaaEgAsCAwEAAQKCAYAG +wzkzeglfbsdTZuC55lKazwVbNwoeewEvNKBtb3W+AmsZqjhxIUsT9X2nhKsG4z45 +41U22RFMS/G6Oj9VUs54umkRDDdilXe2Blo+YCvm4iqJCB7dWvOgUKX03wSv45nu +L3EVvVNVIqB0cItqE8JbVHNhxFjQj3iUMvUIs+Nqz39aK7UON45xFSxhZ2Vk+NEc +Xr11yHGTr8f/6eVGf7BZCcbDxtwwWy0Vmkg3gL9foV1R+YDc1jarJ9mPnKcmCqPH +lW5aT5putR0kO1vO6Rh7YfbHsqw334B9v1yjB4TgaJBKVHz5Z8KTvDFHodMtLqCC +WV61O2h7gh4mQ6lEX5tjArqYdKMuWLAhZ+9AK9sSs4k+/nlvEbqAOCbkx7UmrZoF +QkYfDt2Gjrk7WLwb9CCFIH0a2EEB2Fms1iHBK++S3iA4w0kfbePP0mo4GTsTwA45 +DKDbYByzJzVUvGmowMaaypE548sopQ9K4kQJ9okLV+Gc1V7fjklYIIBmwDgqfIEC +gcEA5Xt0qFjYn4H2gu2xyD0etx83CjKUx0mjwPvdwLg79HMb9P+OTTU+NzsHTa2I +CTEJ1gA4VkqOtKxEBJQarQmJnVL/fiIp88h9fmLBQ48HLefH33S+bF3VWvKOgJeY +uVyyWnhTwHNQv3RsO+DEcjqG3aJ2vdzCnDLBr9ATFV8uzpk1Op0h7QljUbhHv1mS +ip2yQVeuJwtWFixjqEp7BuTluqk/UlGP39PBjgG04Tpw3MkiZNJgk/kSnN+YYOiu +i91rAoHBAMl4/WAaIL5lHiyakHAmE0fwUm+LUKPG1rF22qvqdBFV6OE14/VgTKNP +LfcS7Ulzmt7hM7fbcJ0FYxeyPbbQRjBRsGXFzLU96VgoUxoI/IyFXFY83UJ0s63L +RhZmg4GNvpO0qfOjL4wQtB3N6LPhxpF+pLkkHXSdFkUyocaXGUGOBC+ZEBaCd8Lm +2GlGoi/f+zSl4xSY4crspS7GNG2+jcXh5K/OMdjEb1/tyRYnHf0D89WNmr10EeYG +Pe9alaDv4QKBwDROcYa1yZqB6who2W8Ez216BfejE9pg5JxmTGNTGwda/XJYlbzv +d+Dq6X1BIpLFxLIslqrEj8aKxW4tu+7ZD672bhn3+4v/lOsr41Vc0owaGqrKV2Un +9iumweh5pWwKvvR0HNLu9ebNyKXVU7GduYPnNh2MpicoQpGqYc8rROX+ce2MR2Fa +FHNaB7CL4CUMUMcoDyADK3oeYBDJ+UTXA64KSc6fnKWuBJ4zsWDtCzCn/9jvQug3 +i5CKPpdIMhDbRQKBwEekz61B/UzXVnCUEjLfR1H4osfpqaZjyerXkhE6UUXs3+Be +Mo8KTJZyTK0kvN62zmbdfG+wCA6+YKuHhayhyaPbGLhIK3Bz8KuZw1tpwK0Tq287 +O48rQs3VkDndAHysdA3AXAM4j2rmcbZ7h3mYGu2YNGll71eNmOLIi4C8MI4AO3rV +mkP25zGWt3RQWtJdes4RA3xKlVh86IyGjRRNg8rPdmwSDeXAjL53J1/KTz6vDiFt +to4SXV8H7zRTaQwO4QKBwBwMU2zjMYXLJq0LAmn3h4h6CVZjPrqzR8PeSd/YM831 +qdH7OvnkadqIdqMOo6BUA9PvUIY/B5c5zSSOJg9gh1PJ3vDLIZY23zkXigh7poBe +YW6/PLvGQJ0Rzyz5pf6uPX8AWkAqTyI1Ox3NdxzirarxWDPznvA2KsVxVF/jxnvr +TD/R5kCQUcxZuInguahGYd1JF3dArYh6NKRPyVO0r73LfVeZ+udlo/+ZMNVGlNNF +v3Tmy/b2gUdEwuKFCxx97g== +-----END PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.pem b/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.pem new file mode 100644 index 0000000..e08666b --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.crt01.example.nil.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010840 (0x70b9f4eb2fa19598) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 7 20:28:03 2022 GMT + Not After : Aug 30 20:28:03 2052 GMT + Subject: CN=srv01.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:b4:9a:63:98:04:ad:bd:ab:29:bf:22:70:54:30: + df:c7:6b:77:5d:b8:5e:0b:cd:0e:a0:6c:74:37:e7: + 4b:78:d1:96:da:ca:99:7d:92:b1:e4:1a:0a:1e:b4: + 1c:be:ee:cc:95:8c:52:03:93:85:e1:40:43:68:86: + 86:bc:6a:62:6d:d6:0a:ca:ee:4f:93:2d:ee:6b:df: + 7a:f6:dc:fa:44:a6:39:80:2c:38:7c:89:cd:d9:a3: + 99:ec:e8:2b:48:6d:84:41:3d:0e:1a:1f:68:5e:17: + 88:8f:a5:da:4d:1c:36:26:ae:b4:7e:d2:fe:a2:59: + d5:67:3a:56:c2:21:65:0d:dd:97:6f:f0:e5:b4:1e: + 87:ae:97:35:0d:f4:9b:ae:dc:8a:3e:28:aa:b8:a2: + ab:ee:9d:b2:c5:91:f6:71:99:a5:86:cb:31:9c:05: + d6:9b:94:13:46:a9:9a:c9:a5:55:5f:6c:cc:d0:84: + 27:e2:b1:b5:73:39:08:7f:80:2f:04:26:96:0c:8d: + 29:9b:be:5e:cc:39:af:a2:db:82:82:57:07:e6:b2: + 4a:d9:3d:c8:79:6e:67:61:f3:48:37:a8:4f:9f:b3: + cf:84:b6:50:08:3d:e9:85:e9:a9:76:50:80:e7:2c: + 6f:65:95:cb:e2:23:41:58:39:70:e7:78:29:3d:c2: + d6:20:7c:2b:87:30:bd:98:87:63:ed:4a:ad:b9:ed: + 7a:4b:13:a1:3d:62:5e:b6:74:64:ef:25:a3:dd:93: + 47:aa:d3:25:7e:2a:d7:09:1b:5c:59:50:f1:d4:c6: + 9c:f2:64:8a:7c:cb:cc:52:37:50:88:4b:84:35:40: + 51:0e:a1:06:a2:60:b6:b0:e3:8f:f9:d8:8e:45:77: + 7d:0e:7d:11:92:22:15:0f:a3:37:84:c4:25:dc:14: + b4:20:7a:b7:16:96:72:d4:bf:4d:5d:d2:ab:71:43: + 44:be:87:44:d2:b8:74:f7:86:3f:d2:5d:dd:5e:e6: + 74:ab:fb:cc:a3:5d:a6:84:80:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt01.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 94:15:c0:4a:f1:aa:15:30:f7:cb:fe:f9:fa:ba:5f:f0:18:1f: + 7e:44:9a:b1:d4:9c:f9:78:d3:a7:c7:65:f2:d1:48:62:f4:cb: + 2f:20:ea:7c:af:08:cf:db:e2:0f:ab:c0:22:38:16:c5:0c:e5: + c7:6e:34:b1:ed:f6:02:1a:69:c0:09:d1:43:b3:30:77:fc:00: + 07:1b:da:88:97:5b:28:4e:e6:92:ca:00:cc:86:66:a9:a9:0a: + 75:be:74:88:7d:09:52:e7:a9:82:8f:a9:62:5e:b3:19:64:14: + e5:54:9e:6d:9c:98:39:8b:1f:92:92:59:f9:a2:46:75:96:11: + 71:8a:c8:71:05:10:2a:b8:f3:a4:19:db:eb:05:17:0a:dd:98: + 2c:58:54:3a:7f:8c:c2:26:9e:62:ca:04:dd:3c:99:1f:a0:64: + 69:fb:d6:04:c1:0b:8c:62:f6:2d:ea:bc:6c:a9:39:7b:f1:20: + b8:b7:04:3c:a7:65:fa:1f:db:22:e2:5b:8b:91:75:60:be:e1: + 1e:50:13:23:d5:4b:93:87:20:ec:46:6f:5f:94:dc:b1:60:d1: + 79:4b:5e:76:c9:6d:0d:be:a6:9a:6b:67:8b:a7:48:7e:51:b5: + 9b:9d:ec:a6:0c:c1:b3:d9:0b:26:8b:f2:7c:cf:61:d0:a2:a0: + 90:90:18:6b:b4:ca:56:b8:5e:5a:8b:78:71:c4:d1:fc:15:30: + 0a:03:26:74:85:3d:6c:ed:d3:e1:c9:c1:b0:d4:0c:b9:f3:04: + 93:0d:e3:a6:2c:a7:ee:e0:24:0d:dd:37:fc:6b:09:d5:b5:55: + 33:12:82:cf:f2:ba:0f:b0:e2:ce:f7:c0:ac:2c:7f:ab:f9:dd: + 87:b1:9b:95:f2:d7:32:98:dd:4c:b3:28:b7:0d:2b:2f:62:65: + ce:59:fb:95:d4:5f:9d:fd:83:5a:01:3b:5f:48:5f:3c:fa:4b: + 52:91:66:e1:49:8e:cd:09:78:f5:ce:f8:cd:5c:85:3e:ad:bd: + 1c:4e:e0:3f:0a:8b +-----BEGIN CERTIFICATE----- +MIIETzCCAregAwIBAgIIcLn06y+hlZgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDkwNzIwMjgwM1oYDzIwNTIwODMw +MjAyODAzWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLm5pbDCCAaIw +DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALSaY5gErb2rKb8icFQw38drd124 +XgvNDqBsdDfnS3jRltrKmX2SseQaCh60HL7uzJWMUgOTheFAQ2iGhrxqYm3WCsru +T5Mt7mvfevbc+kSmOYAsOHyJzdmjmezoK0hthEE9DhofaF4XiI+l2k0cNiautH7S +/qJZ1Wc6VsIhZQ3dl2/w5bQeh66XNQ30m67cij4oqriiq+6dssWR9nGZpYbLMZwF +1puUE0apmsmlVV9szNCEJ+KxtXM5CH+ALwQmlgyNKZu+Xsw5r6LbgoJXB+ayStk9 +yHluZ2HzSDeoT5+zz4S2UAg96YXpqXZQgOcsb2WVy+IjQVg5cOd4KT3C1iB8K4cw +vZiHY+1KrbnteksToT1iXrZ0ZO8lo92TR6rTJX4q1wkbXFlQ8dTGnPJkinzLzFI3 +UIhLhDVAUQ6hBqJgtrDjj/nYjkV3fQ59EZIiFQ+jN4TEJdwUtCB6txaWctS/TV3S +q3FDRL6HRNK4dPeGP9Jd3V7mdKv7zKNdpoSACwIDAQABoywwKjAoBgNVHREEITAf +ghdzcnYwMS5jcnQwMS5leGFtcGxlLm5pbIcECjUAATANBgkqhkiG9w0BAQsFAAOC +AYEAlBXASvGqFTD3y/75+rpf8BgffkSasdSc+XjTp8dl8tFIYvTLLyDqfK8Iz9vi +D6vAIjgWxQzlx240se32AhppwAnRQ7Mwd/wABxvaiJdbKE7mksoAzIZmqakKdb50 +iH0JUuepgo+pYl6zGWQU5VSebZyYOYsfkpJZ+aJGdZYRcYrIcQUQKrjzpBnb6wUX +Ct2YLFhUOn+MwiaeYsoE3TyZH6BkafvWBMELjGL2Leq8bKk5e/EguLcEPKdl+h/b +IuJbi5F1YL7hHlATI9VLk4cg7EZvX5TcsWDReUtedsltDb6mmmtni6dIflG1m53s +pgzBs9kLJovyfM9h0KKgkJAYa7TKVrheWot4ccTR/BUwCgMmdIU9bO3T4cnBsNQM +ufMEkw3jpiyn7uAkDd03/GsJ1bVVMxKCz/K6D7DizvfArCx/q/ndh7GblfLXMpjd +TLMotw0rL2Jlzln7ldRfnf2DWgE7X0hfPPpLUpFm4UmOzQl49c74zVyFPq29HE7g +PwqL +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.key b/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.key new file mode 100644 index 0000000..307d26d --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.key @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDsLIgBtYs6dFYN +V7N1/QVYBe2Kq+gpDvFSNC4iYm5BdP94M7T/FXP6zpAQpP7SZhR7C3l71iCI+UEx +FJpJNow4dEvz4lHn5W+9ZTjmnDCAPyRW9mieCXaBW1mBRFafHD9I8JW/YEAp36xC +PcNvhS3DDgi29xIqUQC/z/5srtd93sFy+DIDX8k/St7l+iSQRvBKXwnYk0y/HGFM +0tzbbPivc1u3O3robRy7JiNHh/1QBg/xtYiKqCVpV+NGO9JrUvtaAfaW6SrPE+cW +TP1a9h8Ljfclo2jXFfxcSEkF4oUkcFex2AUkriY6AJtyqEcFxfN8LfJYcjf7wYtP +Qo/dmqxbrm8hYq0pgbmLS2z/YZkPfAnTbQAgLbEMAGyZTJLcDhEt57p7x8ixoxph ++Mwsrxe228w2Av77ZhV3hHDNQiW3FmQorp2MgYWg4FCCqujprFH8K2NEsQi4kNeM +HCOyGwhZhdXdOUT3R15ICDTrLN91Rwi2tuYy7XZ0d849Tf4CsTMCAwEAAQKCAYA+ +B7AtKr6HutiDJp63BZ6qsNvkCSSv7AHMAnJ/i3TD8nPK4WHPgZX1sN070eov3qnQ +a4Ib2XCwKS9LMcsYIaCQj1MHmlDC5IsFpplcUHeYp3zm7k8p+vhKH3ERt548qhGh +GbdrDV+s39eBinFTUBpl2cDGNXxq6t2Ug4+iggWNRL1wcenI4xabbhG/O4Tw9ADW +t8GBRabppw2TPOrPIv7qLhVPueqdM1NRgEHR3tDUfNMhO/nB2UoCMhg6cSniEGf8 +32NDQHI7ajIcETnn9z0tAP67+w5VUYMlP3+VGr8v4UZCL6Qal9Swv4XWPqHjHoIi +q5by4H6HEYeoUPT5hCJjMdXlHrWWUgsX/YdgY4tJJBowMR6rovA7Ypy71FxRnXkP +2iD36jZmDI1mBQ41Yx7P5iM+veRQmBOH/x70Bd9ZbSLlmeTX5dhjAxNShjZxxeUy +QbQGe3JLzdCGzRY9TKFMmLa/qs+Ggqxopdh4AZuHtQpKUej6g9GI9Eo0IIWTKEkC +gcEA+EC1ms0MEIIq/JJrsN4ByEyZXbuNKny/04h8dfkT0lTXk8QihQLke6ZLLOl9 +mwgO9NOHkghtU9wdNXg/dNR2VDevUZCjIlYZT6stjEX7X0oNACJwSeBwEXxn6I94 +umuvJ9hq9WchTnQA4lrIXCETIUxThjm7jfJe9RKzghQkCfGnxzclXg0viqxvm21j +eg0iide23y9xpFd8Qn1oq+hhzcKqHWdkHuDjRJD5gfAEPD7MJ7oT5jR4szQoIUcP +4C+NAoHBAPOLUwAwcY5zUBAZ7oZ8wRgnAFZjHdYYWDr04ahA1DpwPeX67MczdGud +L7hUq3APa3qcj4hrDL2jkF6FkbURhtdguMccb4hBENyYr+qjoTAfYJIZwJ9akQ/j +x8u+5kGsN+ozaKikHFsI2xXHJhbShICL3sIfNeqGFB2onp/dv8WdywTnSf2aXGjf +NFvVJYnaEOGiTM7uIf/F0n8Iae8HSdPZXtDTXNjnLFzzHjvFe1mfyYO55BDkxmr2 +PDnhVkbTvwKBwQCNPwQU16WNnwImQojTUP1ioXKBSjy/d8sM6BMobFdCzNL7WBTr +6QFm+O681vyIQMWBtvjjtbe+hvZ3fbtdFaVdtXEiz1CCMMql8ZcwwICNbuyGrxGE +dxZMXKQiRb9DEhHOcewpRExG/umh4FUvVgI0Z+D99csosEYm2kUYNa1rmvsC9fVk +1cu+8u1tWYfH4cFM/FcoFS5revtQOVpctRMwpxlzMWhdyUaFtJbBv3YpcPFniQ/Z +YvFpxLswc+Ysf+ECgcEAhEeMUXH+e6zOM7CiCZIBHykv2bwEHKEkawFO/6AWpZcJ +R7y+loOwHDNIFAqJA1icvAAFRcc/KFGKvIw30+0tHBaAxkT/nzYX/nlAM2Wkywp/ +3Vr3cJY0bDj/7/5D+i+cPyylD9PzQs7QkEeWvJajOV6/Ixjoo/UnP+SyI4rB+of2 +GTe2zHPm9V8mhSqENReoS6Vnqo1VEiNUbYMYZqfCxbou8aWbrIQDaIj0RurAULGl +NlLlOPfJfZc4pwdpYRbpAoHAJ7Vxdfn1ec+8xIpjn6dQzWDQWrOw+4pyi54sPlVb +RUWC9nYDbTwEKkWdQ0FdyJkU7tiYIIFlVNfPAa1lkujIiC5zxe41VJ1598pXPEXn +a6UB1yn2Ay7kmCq7/qOD6IRkAS8TKyzM6Z7nFgglMEPPdzYBkeKP/aWl75el1B4e +mpGz7o6u6kSHXt0UWZ7VT9AspEw0oyHIoaXmYHvpXjGtWghn6MKPMngKIb87Xjvt +bKvcUjDKJOb0BURXpKzS8Rf9 +-----END PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.pem b/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.pem new file mode 100644 index 0000000..9a407f6 --- /dev/null +++ b/bin/tests/system/nsupdate/CA/certs/srv01.crt02-expired.example.nil.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010841 (0x70b9f4eb2fa19599) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 6 20:34:09 2022 GMT + Not After : Sep 7 20:34:09 2022 GMT + Subject: CN=srv01.crt02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:ec:2c:88:01:b5:8b:3a:74:56:0d:57:b3:75:fd: + 05:58:05:ed:8a:ab:e8:29:0e:f1:52:34:2e:22:62: + 6e:41:74:ff:78:33:b4:ff:15:73:fa:ce:90:10:a4: + fe:d2:66:14:7b:0b:79:7b:d6:20:88:f9:41:31:14: + 9a:49:36:8c:38:74:4b:f3:e2:51:e7:e5:6f:bd:65: + 38:e6:9c:30:80:3f:24:56:f6:68:9e:09:76:81:5b: + 59:81:44:56:9f:1c:3f:48:f0:95:bf:60:40:29:df: + ac:42:3d:c3:6f:85:2d:c3:0e:08:b6:f7:12:2a:51: + 00:bf:cf:fe:6c:ae:d7:7d:de:c1:72:f8:32:03:5f: + c9:3f:4a:de:e5:fa:24:90:46:f0:4a:5f:09:d8:93: + 4c:bf:1c:61:4c:d2:dc:db:6c:f8:af:73:5b:b7:3b: + 7a:e8:6d:1c:bb:26:23:47:87:fd:50:06:0f:f1:b5: + 88:8a:a8:25:69:57:e3:46:3b:d2:6b:52:fb:5a:01: + f6:96:e9:2a:cf:13:e7:16:4c:fd:5a:f6:1f:0b:8d: + f7:25:a3:68:d7:15:fc:5c:48:49:05:e2:85:24:70: + 57:b1:d8:05:24:ae:26:3a:00:9b:72:a8:47:05:c5: + f3:7c:2d:f2:58:72:37:fb:c1:8b:4f:42:8f:dd:9a: + ac:5b:ae:6f:21:62:ad:29:81:b9:8b:4b:6c:ff:61: + 99:0f:7c:09:d3:6d:00:20:2d:b1:0c:00:6c:99:4c: + 92:dc:0e:11:2d:e7:ba:7b:c7:c8:b1:a3:1a:61:f8: + cc:2c:af:17:b6:db:cc:36:02:fe:fb:66:15:77:84: + 70:cd:42:25:b7:16:64:28:ae:9d:8c:81:85:a0:e0: + 50:82:aa:e8:e9:ac:51:fc:2b:63:44:b1:08:b8:90: + d7:8c:1c:23:b2:1b:08:59:85:d5:dd:39:44:f7:47: + 5e:48:08:34:eb:2c:df:75:47:08:b6:b6:e6:32:ed: + 76:74:77:ce:3d:4d:fe:02:b1:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt02-expired.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 2a:52:c4:cb:a9:2f:f7:2b:ed:04:b5:03:d5:06:59:ed:5c:7c: + b7:00:9e:c4:33:90:fe:d0:b0:18:f3:f2:06:30:54:18:fe:34: + cb:ea:61:4f:9c:23:67:3c:ae:ed:20:df:82:52:ec:59:88:45: + ad:3c:6c:a7:34:24:1c:4d:66:ab:71:3d:59:8c:ef:cd:a0:e2: + 7b:59:2d:43:94:cd:f5:0a:3c:4e:81:24:e8:fd:c6:d0:fd:ad: + 6f:cc:29:5b:67:0b:b7:ee:43:38:a4:91:c2:d9:3b:f8:d6:97: + bc:92:dd:ec:a1:ab:85:35:44:f4:0a:df:ad:8d:8c:52:c3:49: + 7e:39:10:a1:13:43:78:71:e2:92:aa:31:3d:d9:94:15:7f:86: + c8:aa:b4:a1:6d:bf:eb:55:b1:d7:41:6f:c3:7d:88:5e:9c:b7: + b1:4b:0d:a7:17:4f:3e:4a:46:3f:6f:48:27:8c:d0:e5:51:fc: + 42:ba:c5:b9:4f:63:6f:2e:f2:fd:0c:c0:6e:23:b4:59:93:68: + a4:2d:16:ce:f4:7b:3a:45:1d:a0:6e:98:0b:f7:6a:e6:75:0c: + db:56:19:6b:88:f0:7f:6b:08:f8:fc:bb:d1:3f:25:25:1a:6c: + 8e:34:cb:91:18:54:d5:2d:ce:9c:d0:b7:c3:bc:b5:0a:e0:b9: + 73:6f:4d:ad:6b:3c:b6:49:ef:c0:10:13:c7:0a:78:4d:98:7d: + cb:84:a1:29:40:8c:dd:31:7d:ae:c4:f5:25:5d:b9:74:b2:f5: + e2:2b:e0:43:c8:50:61:a3:a8:26:1a:03:ab:1a:24:3b:13:56: + da:0d:ee:ff:2f:bd:d5:77:82:72:63:b8:aa:e1:18:f7:3b:c1: + a1:f8:51:b1:70:b9:25:39:df:a3:41:79:d7:2b:ec:32:f6:cb: + 30:28:d2:1e:f1:b4:e1:80:03:9f:c2:0f:36:85:82:5e:39:ba: + 9e:eb:67:76:42:93:bf:e0:df:64:b2:b5:5f:98:a1:45:3f:4a: + 1f:5c:c5:04:10:f6 +-----BEGIN CERTIFICATE----- +MIIEXTCCAsWgAwIBAgIIcLn06y+hlZkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTIyMDkwNjIwMzQwOVoXDTIyMDkwNzIw +MzQwOVowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDItZXhwaXJlZC5leGFtcGxlLm5p +bDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAOwsiAG1izp0Vg1Xs3X9 +BVgF7Yqr6CkO8VI0LiJibkF0/3gztP8Vc/rOkBCk/tJmFHsLeXvWIIj5QTEUmkk2 +jDh0S/PiUeflb71lOOacMIA/JFb2aJ4JdoFbWYFEVp8cP0jwlb9gQCnfrEI9w2+F +LcMOCLb3EipRAL/P/myu133ewXL4MgNfyT9K3uX6JJBG8EpfCdiTTL8cYUzS3Nts ++K9zW7c7euhtHLsmI0eH/VAGD/G1iIqoJWlX40Y70mtS+1oB9pbpKs8T5xZM/Vr2 +HwuN9yWjaNcV/FxISQXihSRwV7HYBSSuJjoAm3KoRwXF83wt8lhyN/vBi09Cj92a +rFuubyFirSmBuYtLbP9hmQ98CdNtACAtsQwAbJlMktwOES3nunvHyLGjGmH4zCyv +F7bbzDYC/vtmFXeEcM1CJbcWZCiunYyBhaDgUIKq6OmsUfwrY0SxCLiQ14wcI7Ib +CFmF1d05RPdHXkgINOss33VHCLa25jLtdnR3zj1N/gKxMwIDAQABozQwMjAwBgNV +HREEKTAngh9zcnYwMS5jcnQwMi1leHBpcmVkLmV4YW1wbGUubmlshwQKNQABMA0G +CSqGSIb3DQEBCwUAA4IBgQAqUsTLqS/3K+0EtQPVBlntXHy3AJ7EM5D+0LAY8/IG +MFQY/jTL6mFPnCNnPK7tIN+CUuxZiEWtPGynNCQcTWarcT1ZjO/NoOJ7WS1DlM31 +CjxOgSTo/cbQ/a1vzClbZwu37kM4pJHC2Tv41pe8kt3soauFNUT0Ct+tjYxSw0l+ +ORChE0N4ceKSqjE92ZQVf4bIqrShbb/rVbHXQW/DfYhenLexSw2nF08+SkY/b0gn +jNDlUfxCusW5T2NvLvL9DMBuI7RZk2ikLRbO9Hs6RR2gbpgL92rmdQzbVhlriPB/ +awj4/LvRPyUlGmyONMuRGFTVLc6c0LfDvLUK4Llzb02tazy2Se/AEBPHCnhNmH3L +hKEpQIzdMX2uxPUlXbl0svXiK+BDyFBho6gmGgOrGiQ7E1baDe7/L73Vd4JyY7iq +4Rj3O8Gh+FGxcLklOd+jQXnXK+wy9sswKNIe8bThgAOfwg82hYJeObqe62d2QpO/ +4N9ksrVfmKFFP0ofXMUEEPY= +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/index.txt b/bin/tests/system/nsupdate/CA/index.txt new file mode 100644 index 0000000..020155f --- /dev/null +++ b/bin/tests/system/nsupdate/CA/index.txt @@ -0,0 +1,4 @@ +V 20520830202803Z 70B9F4EB2FA19598 unknown /CN=srv01.crt01.example.nil +V 220907203409Z 70B9F4EB2FA19599 unknown /CN=srv01.crt02-expired.example.nil +V 20520831082017Z 70B9F4EB2FA1959A unknown /CN=srv01.client01.example.nil +V 220908081418Z 70B9F4EB2FA1959B unknown /CN=srv01.client02-expired.example.nil diff --git a/bin/tests/system/nsupdate/CA/index.txt.attr b/bin/tests/system/nsupdate/CA/index.txt.attr new file mode 100644 index 0000000..8f7e63a --- /dev/null +++ b/bin/tests/system/nsupdate/CA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19598.pem b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19598.pem new file mode 100644 index 0000000..e08666b --- /dev/null +++ b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19598.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010840 (0x70b9f4eb2fa19598) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 7 20:28:03 2022 GMT + Not After : Aug 30 20:28:03 2052 GMT + Subject: CN=srv01.crt01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:b4:9a:63:98:04:ad:bd:ab:29:bf:22:70:54:30: + df:c7:6b:77:5d:b8:5e:0b:cd:0e:a0:6c:74:37:e7: + 4b:78:d1:96:da:ca:99:7d:92:b1:e4:1a:0a:1e:b4: + 1c:be:ee:cc:95:8c:52:03:93:85:e1:40:43:68:86: + 86:bc:6a:62:6d:d6:0a:ca:ee:4f:93:2d:ee:6b:df: + 7a:f6:dc:fa:44:a6:39:80:2c:38:7c:89:cd:d9:a3: + 99:ec:e8:2b:48:6d:84:41:3d:0e:1a:1f:68:5e:17: + 88:8f:a5:da:4d:1c:36:26:ae:b4:7e:d2:fe:a2:59: + d5:67:3a:56:c2:21:65:0d:dd:97:6f:f0:e5:b4:1e: + 87:ae:97:35:0d:f4:9b:ae:dc:8a:3e:28:aa:b8:a2: + ab:ee:9d:b2:c5:91:f6:71:99:a5:86:cb:31:9c:05: + d6:9b:94:13:46:a9:9a:c9:a5:55:5f:6c:cc:d0:84: + 27:e2:b1:b5:73:39:08:7f:80:2f:04:26:96:0c:8d: + 29:9b:be:5e:cc:39:af:a2:db:82:82:57:07:e6:b2: + 4a:d9:3d:c8:79:6e:67:61:f3:48:37:a8:4f:9f:b3: + cf:84:b6:50:08:3d:e9:85:e9:a9:76:50:80:e7:2c: + 6f:65:95:cb:e2:23:41:58:39:70:e7:78:29:3d:c2: + d6:20:7c:2b:87:30:bd:98:87:63:ed:4a:ad:b9:ed: + 7a:4b:13:a1:3d:62:5e:b6:74:64:ef:25:a3:dd:93: + 47:aa:d3:25:7e:2a:d7:09:1b:5c:59:50:f1:d4:c6: + 9c:f2:64:8a:7c:cb:cc:52:37:50:88:4b:84:35:40: + 51:0e:a1:06:a2:60:b6:b0:e3:8f:f9:d8:8e:45:77: + 7d:0e:7d:11:92:22:15:0f:a3:37:84:c4:25:dc:14: + b4:20:7a:b7:16:96:72:d4:bf:4d:5d:d2:ab:71:43: + 44:be:87:44:d2:b8:74:f7:86:3f:d2:5d:dd:5e:e6: + 74:ab:fb:cc:a3:5d:a6:84:80:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt01.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 94:15:c0:4a:f1:aa:15:30:f7:cb:fe:f9:fa:ba:5f:f0:18:1f: + 7e:44:9a:b1:d4:9c:f9:78:d3:a7:c7:65:f2:d1:48:62:f4:cb: + 2f:20:ea:7c:af:08:cf:db:e2:0f:ab:c0:22:38:16:c5:0c:e5: + c7:6e:34:b1:ed:f6:02:1a:69:c0:09:d1:43:b3:30:77:fc:00: + 07:1b:da:88:97:5b:28:4e:e6:92:ca:00:cc:86:66:a9:a9:0a: + 75:be:74:88:7d:09:52:e7:a9:82:8f:a9:62:5e:b3:19:64:14: + e5:54:9e:6d:9c:98:39:8b:1f:92:92:59:f9:a2:46:75:96:11: + 71:8a:c8:71:05:10:2a:b8:f3:a4:19:db:eb:05:17:0a:dd:98: + 2c:58:54:3a:7f:8c:c2:26:9e:62:ca:04:dd:3c:99:1f:a0:64: + 69:fb:d6:04:c1:0b:8c:62:f6:2d:ea:bc:6c:a9:39:7b:f1:20: + b8:b7:04:3c:a7:65:fa:1f:db:22:e2:5b:8b:91:75:60:be:e1: + 1e:50:13:23:d5:4b:93:87:20:ec:46:6f:5f:94:dc:b1:60:d1: + 79:4b:5e:76:c9:6d:0d:be:a6:9a:6b:67:8b:a7:48:7e:51:b5: + 9b:9d:ec:a6:0c:c1:b3:d9:0b:26:8b:f2:7c:cf:61:d0:a2:a0: + 90:90:18:6b:b4:ca:56:b8:5e:5a:8b:78:71:c4:d1:fc:15:30: + 0a:03:26:74:85:3d:6c:ed:d3:e1:c9:c1:b0:d4:0c:b9:f3:04: + 93:0d:e3:a6:2c:a7:ee:e0:24:0d:dd:37:fc:6b:09:d5:b5:55: + 33:12:82:cf:f2:ba:0f:b0:e2:ce:f7:c0:ac:2c:7f:ab:f9:dd: + 87:b1:9b:95:f2:d7:32:98:dd:4c:b3:28:b7:0d:2b:2f:62:65: + ce:59:fb:95:d4:5f:9d:fd:83:5a:01:3b:5f:48:5f:3c:fa:4b: + 52:91:66:e1:49:8e:cd:09:78:f5:ce:f8:cd:5c:85:3e:ad:bd: + 1c:4e:e0:3f:0a:8b +-----BEGIN CERTIFICATE----- +MIIETzCCAregAwIBAgIIcLn06y+hlZgwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDkwNzIwMjgwM1oYDzIwNTIwODMw +MjAyODAzWjAiMSAwHgYDVQQDDBdzcnYwMS5jcnQwMS5leGFtcGxlLm5pbDCCAaIw +DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALSaY5gErb2rKb8icFQw38drd124 +XgvNDqBsdDfnS3jRltrKmX2SseQaCh60HL7uzJWMUgOTheFAQ2iGhrxqYm3WCsru +T5Mt7mvfevbc+kSmOYAsOHyJzdmjmezoK0hthEE9DhofaF4XiI+l2k0cNiautH7S +/qJZ1Wc6VsIhZQ3dl2/w5bQeh66XNQ30m67cij4oqriiq+6dssWR9nGZpYbLMZwF +1puUE0apmsmlVV9szNCEJ+KxtXM5CH+ALwQmlgyNKZu+Xsw5r6LbgoJXB+ayStk9 +yHluZ2HzSDeoT5+zz4S2UAg96YXpqXZQgOcsb2WVy+IjQVg5cOd4KT3C1iB8K4cw +vZiHY+1KrbnteksToT1iXrZ0ZO8lo92TR6rTJX4q1wkbXFlQ8dTGnPJkinzLzFI3 +UIhLhDVAUQ6hBqJgtrDjj/nYjkV3fQ59EZIiFQ+jN4TEJdwUtCB6txaWctS/TV3S +q3FDRL6HRNK4dPeGP9Jd3V7mdKv7zKNdpoSACwIDAQABoywwKjAoBgNVHREEITAf +ghdzcnYwMS5jcnQwMS5leGFtcGxlLm5pbIcECjUAATANBgkqhkiG9w0BAQsFAAOC +AYEAlBXASvGqFTD3y/75+rpf8BgffkSasdSc+XjTp8dl8tFIYvTLLyDqfK8Iz9vi +D6vAIjgWxQzlx240se32AhppwAnRQ7Mwd/wABxvaiJdbKE7mksoAzIZmqakKdb50 +iH0JUuepgo+pYl6zGWQU5VSebZyYOYsfkpJZ+aJGdZYRcYrIcQUQKrjzpBnb6wUX +Ct2YLFhUOn+MwiaeYsoE3TyZH6BkafvWBMELjGL2Leq8bKk5e/EguLcEPKdl+h/b +IuJbi5F1YL7hHlATI9VLk4cg7EZvX5TcsWDReUtedsltDb6mmmtni6dIflG1m53s +pgzBs9kLJovyfM9h0KKgkJAYa7TKVrheWot4ccTR/BUwCgMmdIU9bO3T4cnBsNQM +ufMEkw3jpiyn7uAkDd03/GsJ1bVVMxKCz/K6D7DizvfArCx/q/ndh7GblfLXMpjd +TLMotw0rL2Jlzln7ldRfnf2DWgE7X0hfPPpLUpFm4UmOzQl49c74zVyFPq29HE7g +PwqL +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19599.pem b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19599.pem new file mode 100644 index 0000000..9a407f6 --- /dev/null +++ b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA19599.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010841 (0x70b9f4eb2fa19599) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 6 20:34:09 2022 GMT + Not After : Sep 7 20:34:09 2022 GMT + Subject: CN=srv01.crt02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:ec:2c:88:01:b5:8b:3a:74:56:0d:57:b3:75:fd: + 05:58:05:ed:8a:ab:e8:29:0e:f1:52:34:2e:22:62: + 6e:41:74:ff:78:33:b4:ff:15:73:fa:ce:90:10:a4: + fe:d2:66:14:7b:0b:79:7b:d6:20:88:f9:41:31:14: + 9a:49:36:8c:38:74:4b:f3:e2:51:e7:e5:6f:bd:65: + 38:e6:9c:30:80:3f:24:56:f6:68:9e:09:76:81:5b: + 59:81:44:56:9f:1c:3f:48:f0:95:bf:60:40:29:df: + ac:42:3d:c3:6f:85:2d:c3:0e:08:b6:f7:12:2a:51: + 00:bf:cf:fe:6c:ae:d7:7d:de:c1:72:f8:32:03:5f: + c9:3f:4a:de:e5:fa:24:90:46:f0:4a:5f:09:d8:93: + 4c:bf:1c:61:4c:d2:dc:db:6c:f8:af:73:5b:b7:3b: + 7a:e8:6d:1c:bb:26:23:47:87:fd:50:06:0f:f1:b5: + 88:8a:a8:25:69:57:e3:46:3b:d2:6b:52:fb:5a:01: + f6:96:e9:2a:cf:13:e7:16:4c:fd:5a:f6:1f:0b:8d: + f7:25:a3:68:d7:15:fc:5c:48:49:05:e2:85:24:70: + 57:b1:d8:05:24:ae:26:3a:00:9b:72:a8:47:05:c5: + f3:7c:2d:f2:58:72:37:fb:c1:8b:4f:42:8f:dd:9a: + ac:5b:ae:6f:21:62:ad:29:81:b9:8b:4b:6c:ff:61: + 99:0f:7c:09:d3:6d:00:20:2d:b1:0c:00:6c:99:4c: + 92:dc:0e:11:2d:e7:ba:7b:c7:c8:b1:a3:1a:61:f8: + cc:2c:af:17:b6:db:cc:36:02:fe:fb:66:15:77:84: + 70:cd:42:25:b7:16:64:28:ae:9d:8c:81:85:a0:e0: + 50:82:aa:e8:e9:ac:51:fc:2b:63:44:b1:08:b8:90: + d7:8c:1c:23:b2:1b:08:59:85:d5:dd:39:44:f7:47: + 5e:48:08:34:eb:2c:df:75:47:08:b6:b6:e6:32:ed: + 76:74:77:ce:3d:4d:fe:02:b1:33 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.crt02-expired.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 2a:52:c4:cb:a9:2f:f7:2b:ed:04:b5:03:d5:06:59:ed:5c:7c: + b7:00:9e:c4:33:90:fe:d0:b0:18:f3:f2:06:30:54:18:fe:34: + cb:ea:61:4f:9c:23:67:3c:ae:ed:20:df:82:52:ec:59:88:45: + ad:3c:6c:a7:34:24:1c:4d:66:ab:71:3d:59:8c:ef:cd:a0:e2: + 7b:59:2d:43:94:cd:f5:0a:3c:4e:81:24:e8:fd:c6:d0:fd:ad: + 6f:cc:29:5b:67:0b:b7:ee:43:38:a4:91:c2:d9:3b:f8:d6:97: + bc:92:dd:ec:a1:ab:85:35:44:f4:0a:df:ad:8d:8c:52:c3:49: + 7e:39:10:a1:13:43:78:71:e2:92:aa:31:3d:d9:94:15:7f:86: + c8:aa:b4:a1:6d:bf:eb:55:b1:d7:41:6f:c3:7d:88:5e:9c:b7: + b1:4b:0d:a7:17:4f:3e:4a:46:3f:6f:48:27:8c:d0:e5:51:fc: + 42:ba:c5:b9:4f:63:6f:2e:f2:fd:0c:c0:6e:23:b4:59:93:68: + a4:2d:16:ce:f4:7b:3a:45:1d:a0:6e:98:0b:f7:6a:e6:75:0c: + db:56:19:6b:88:f0:7f:6b:08:f8:fc:bb:d1:3f:25:25:1a:6c: + 8e:34:cb:91:18:54:d5:2d:ce:9c:d0:b7:c3:bc:b5:0a:e0:b9: + 73:6f:4d:ad:6b:3c:b6:49:ef:c0:10:13:c7:0a:78:4d:98:7d: + cb:84:a1:29:40:8c:dd:31:7d:ae:c4:f5:25:5d:b9:74:b2:f5: + e2:2b:e0:43:c8:50:61:a3:a8:26:1a:03:ab:1a:24:3b:13:56: + da:0d:ee:ff:2f:bd:d5:77:82:72:63:b8:aa:e1:18:f7:3b:c1: + a1:f8:51:b1:70:b9:25:39:df:a3:41:79:d7:2b:ec:32:f6:cb: + 30:28:d2:1e:f1:b4:e1:80:03:9f:c2:0f:36:85:82:5e:39:ba: + 9e:eb:67:76:42:93:bf:e0:df:64:b2:b5:5f:98:a1:45:3f:4a: + 1f:5c:c5:04:10:f6 +-----BEGIN CERTIFICATE----- +MIIEXTCCAsWgAwIBAgIIcLn06y+hlZkwDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTIyMDkwNjIwMzQwOVoXDTIyMDkwNzIw +MzQwOVowKjEoMCYGA1UEAwwfc3J2MDEuY3J0MDItZXhwaXJlZC5leGFtcGxlLm5p +bDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAOwsiAG1izp0Vg1Xs3X9 +BVgF7Yqr6CkO8VI0LiJibkF0/3gztP8Vc/rOkBCk/tJmFHsLeXvWIIj5QTEUmkk2 +jDh0S/PiUeflb71lOOacMIA/JFb2aJ4JdoFbWYFEVp8cP0jwlb9gQCnfrEI9w2+F +LcMOCLb3EipRAL/P/myu133ewXL4MgNfyT9K3uX6JJBG8EpfCdiTTL8cYUzS3Nts ++K9zW7c7euhtHLsmI0eH/VAGD/G1iIqoJWlX40Y70mtS+1oB9pbpKs8T5xZM/Vr2 +HwuN9yWjaNcV/FxISQXihSRwV7HYBSSuJjoAm3KoRwXF83wt8lhyN/vBi09Cj92a +rFuubyFirSmBuYtLbP9hmQ98CdNtACAtsQwAbJlMktwOES3nunvHyLGjGmH4zCyv +F7bbzDYC/vtmFXeEcM1CJbcWZCiunYyBhaDgUIKq6OmsUfwrY0SxCLiQ14wcI7Ib +CFmF1d05RPdHXkgINOss33VHCLa25jLtdnR3zj1N/gKxMwIDAQABozQwMjAwBgNV +HREEKTAngh9zcnYwMS5jcnQwMi1leHBpcmVkLmV4YW1wbGUubmlshwQKNQABMA0G +CSqGSIb3DQEBCwUAA4IBgQAqUsTLqS/3K+0EtQPVBlntXHy3AJ7EM5D+0LAY8/IG +MFQY/jTL6mFPnCNnPK7tIN+CUuxZiEWtPGynNCQcTWarcT1ZjO/NoOJ7WS1DlM31 +CjxOgSTo/cbQ/a1vzClbZwu37kM4pJHC2Tv41pe8kt3soauFNUT0Ct+tjYxSw0l+ +ORChE0N4ceKSqjE92ZQVf4bIqrShbb/rVbHXQW/DfYhenLexSw2nF08+SkY/b0gn +jNDlUfxCusW5T2NvLvL9DMBuI7RZk2ikLRbO9Hs6RR2gbpgL92rmdQzbVhlriPB/ +awj4/LvRPyUlGmyONMuRGFTVLc6c0LfDvLUK4Llzb02tazy2Se/AEBPHCnhNmH3L +hKEpQIzdMX2uxPUlXbl0svXiK+BDyFBho6gmGgOrGiQ7E1baDe7/L73Vd4JyY7iq +4Rj3O8Gh+FGxcLklOd+jQXnXK+wy9sswKNIe8bThgAOfwg82hYJeObqe62d2QpO/ +4N9ksrVfmKFFP0ofXMUEEPY= +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959A.pem b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959A.pem new file mode 100644 index 0000000..f32b4c4 --- /dev/null +++ b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959A.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010842 (0x70b9f4eb2fa1959a) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 8 08:20:17 2022 GMT + Not After : Aug 31 08:20:17 2052 GMT + Subject: CN=srv01.client01.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:ab:60:2e:9c:61:e3:89:c6:52:2b:bc:e9:e1:05: + fd:18:65:42:20:f6:56:16:40:33:d2:cb:9f:f7:ef: + 22:54:a7:c9:55:70:ca:52:f0:e2:a2:58:38:7f:10: + ad:2b:05:e0:11:b6:69:21:7f:2d:38:56:dd:d5:e4: + f3:de:a7:32:35:f7:33:2a:52:80:ae:b7:d6:7c:35: + 74:c3:0c:8a:c3:3a:18:61:68:73:62:58:56:ff:78: + 25:57:1c:7b:be:98:88:21:dd:1c:8a:13:a5:9a:52: + 48:98:d9:3d:c4:28:a6:7e:9b:11:56:7e:ce:09:bb: + 51:89:8a:a8:1b:00:b5:73:2b:41:93:b1:62:40:30: + 29:ea:f6:a3:e7:bc:f0:e9:9e:07:2b:ae:a9:a0:1d: + 4d:d9:f8:18:4d:83:47:4e:68:ee:57:c8:55:15:86: + 3c:6d:1e:f5:31:f1:de:cf:c2:7e:6b:8e:22:5a:c5: + 76:af:d0:01:de:ab:7a:03:b2:96:33:cc:a0:26:ae: + de:c4:bd:76:85:96:c7:88:e4:46:bc:3f:c6:54:c9: + 95:83:87:9c:49:0d:31:dd:c4:17:52:99:e4:65:49: + 9b:9d:f3:ad:ce:66:08:57:f4:83:be:5e:87:da:42: + 5a:01:2a:6d:68:d1:8d:38:d9:18:ae:5e:2e:54:72: + 8b:01:45:96:af:f5:a3:d0:29:5d:22:8b:b4:d4:30: + af:02:36:c5:2d:e9:29:eb:2c:ea:6a:7e:27:b3:70: + fc:87:1f:2b:c4:b1:3a:a6:c2:e9:b7:c2:6f:46:63: + b7:96:2e:53:d8:b7:cd:c3:f4:b5:6d:b2:fc:57:49: + ac:9f:98:c9:fe:b4:f5:7c:93:48:2e:93:dc:e9:18: + 54:63:5f:18:a3:e7:12:aa:fe:38:f0:73:e5:17:1e: + fe:40:65:81:a8:8f:60:46:c2:16:f2:a8:9d:b1:1b: + bc:ce:05:de:37:b2:a8:86:47:bd:8d:92:de:e0:e5: + 42:89:b8:e3:f8:b1:24:08:7e:99 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client01.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 07:97:69:51:12:50:6a:e1:02:a0:b0:dc:93:75:16:c4:38:0f: + 5c:b3:47:da:bf:fa:9c:b6:de:c0:ef:38:f7:cc:d9:8d:71:ba: + 51:89:e5:48:36:dd:e1:f8:73:9d:92:80:1c:42:30:69:4f:8c: + 19:5d:f7:1d:03:e4:f2:76:e0:58:7b:c2:76:c4:0a:7e:20:69: + 26:6c:3e:cb:31:45:93:1d:07:5f:45:44:8e:5a:fb:87:17:7b: + 4d:5c:bf:37:bd:5e:ba:5c:22:84:bf:26:21:4a:c4:e9:f9:cb: + 73:de:fc:62:04:96:ad:aa:fd:89:09:5c:74:d6:bd:5f:07:17: + ef:9c:3d:ee:b7:dc:08:11:7f:12:66:ab:c4:ff:43:6d:7f:1e: + 01:b6:d1:19:73:53:18:e4:02:b0:7c:9e:99:63:d8:57:dd:07: + 79:fb:83:39:09:de:76:6e:68:b7:87:81:13:b8:26:e5:1c:c9: + a0:23:e5:97:39:ff:93:c7:8d:08:d8:ce:97:34:fc:ad:22:14: + 89:c0:ae:83:7d:0a:3f:cf:a0:9b:b4:6a:5c:b3:6d:5d:3b:88: + ca:1e:9b:99:54:64:57:58:3c:4c:bd:26:ee:11:c3:13:0b:1d: + f5:fd:d9:37:b0:31:72:6f:1d:e8:ba:43:37:46:f7:71:fe:6d: + 4a:30:33:29:c5:7b:37:8b:7e:06:22:89:a4:46:36:f0:fe:c6: + f5:f0:53:04:c0:35:52:78:6e:10:24:3a:d8:bf:7b:13:2f:98: + bc:69:31:41:68:02:5a:c4:f9:11:a2:6b:3f:c8:e0:d4:b3:80: + af:d2:be:fe:28:70:61:18:ed:8a:de:c4:cb:da:c9:60:94:91: + 76:63:69:8c:6e:96:f5:ba:e7:be:1e:1c:c3:84:b1:8d:e8:31: + f7:66:8c:0d:da:a8:78:57:19:fd:a0:8d:fa:9a:7e:51:1c:d1: + d0:84:07:a2:45:40:2d:c4:6b:e9:9f:86:4a:08:20:8f:9c:79: + 97:e3:7f:2a:14:73 +-----BEGIN CERTIFICATE----- +MIIEVTCCAr2gAwIBAgIIcLn06y+hlZowDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMCAXDTIyMDkwODA4MjAxN1oYDzIwNTIwODMx +MDgyMDE3WjAlMSMwIQYDVQQDDBpzcnYwMS5jbGllbnQwMS5leGFtcGxlLm5pbDCC +AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKtgLpxh44nGUiu86eEF/Rhl +QiD2VhZAM9LLn/fvIlSnyVVwylLw4qJYOH8QrSsF4BG2aSF/LThW3dXk896nMjX3 +MypSgK631nw1dMMMisM6GGFoc2JYVv94JVcce76YiCHdHIoTpZpSSJjZPcQopn6b +EVZ+zgm7UYmKqBsAtXMrQZOxYkAwKer2o+e88OmeByuuqaAdTdn4GE2DR05o7lfI +VRWGPG0e9THx3s/CfmuOIlrFdq/QAd6regOyljPMoCau3sS9doWWx4jkRrw/xlTJ +lYOHnEkNMd3EF1KZ5GVJm53zrc5mCFf0g75eh9pCWgEqbWjRjTjZGK5eLlRyiwFF +lq/1o9ApXSKLtNQwrwI2xS3pKess6mp+J7Nw/IcfK8SxOqbC6bfCb0Zjt5YuU9i3 +zcP0tW2y/FdJrJ+Yyf609XyTSC6T3OkYVGNfGKPnEqr+OPBz5Rce/kBlgaiPYEbC +FvKonbEbvM4F3jeyqIZHvY2S3uDlQom44/ixJAh+mQIDAQABoy8wLTArBgNVHREE +JDAighpzcnYwMS5jbGllbnQwMS5leGFtcGxlLm5pbIcECjUAATANBgkqhkiG9w0B +AQsFAAOCAYEAB5dpURJQauECoLDck3UWxDgPXLNH2r/6nLbewO8498zZjXG6UYnl +SDbd4fhznZKAHEIwaU+MGV33HQPk8nbgWHvCdsQKfiBpJmw+yzFFkx0HX0VEjlr7 +hxd7TVy/N71eulwihL8mIUrE6fnLc978YgSWrar9iQlcdNa9XwcX75w97rfcCBF/ +EmarxP9DbX8eAbbRGXNTGOQCsHyemWPYV90HefuDOQnedm5ot4eBE7gm5RzJoCPl +lzn/k8eNCNjOlzT8rSIUicCug30KP8+gm7RqXLNtXTuIyh6bmVRkV1g8TL0m7hHD +Ewsd9f3ZN7Axcm8d6LpDN0b3cf5tSjAzKcV7N4t+BiKJpEY28P7G9fBTBMA1Unhu +ECQ62L97Ey+YvGkxQWgCWsT5EaJrP8jg1LOAr9K+/ihwYRjtit7Ey9rJYJSRdmNp +jG6W9brnvh4cw4Sxjegx92aMDdqoeFcZ/aCN+pp+URzR0IQHokVALcRr6Z+GSggg +j5x5l+N/KhRz +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959B.pem b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959B.pem new file mode 100644 index 0000000..bbdb6de --- /dev/null +++ b/bin/tests/system/nsupdate/CA/newcerts/70B9F4EB2FA1959B.pem @@ -0,0 +1,93 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 8122792693893010843 (0x70b9f4eb2fa1959b) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=UA, ST=Kharkiv Oblast', L=Kharkiv, O=Internet Systems Consortium, CN=ca.test.example.com + Validity + Not Before: Sep 7 08:14:18 2022 GMT + Not After : Sep 8 08:14:18 2022 GMT + Subject: CN=srv01.client02-expired.example.nil + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (3072 bit) + Modulus: + 00:c0:11:27:17:25:3a:ad:85:a0:3b:59:0b:22:64: + 63:7d:bb:05:32:35:4f:68:d5:19:2b:cd:46:bd:e2: + b6:42:8c:08:cf:09:0d:a8:cd:58:d9:1b:77:db:17: + 8a:fc:f0:55:f2:e1:50:f4:fd:90:aa:49:15:5d:ea: + 9b:5a:47:c4:2f:82:07:46:87:f6:05:ef:15:02:a4: + 3c:a1:da:fc:5b:75:36:12:f7:12:50:55:f8:be:0c: + 7d:21:91:e2:92:d8:41:3f:71:fe:b2:17:c0:68:1d: + 09:be:fc:c4:24:ec:ef:d2:5c:52:a9:4f:d6:5d:30: + b8:ab:68:2e:39:e9:8b:5b:c6:f0:64:42:f7:b8:bd: + b2:90:32:22:68:bc:38:70:2f:14:ae:c8:7c:63:04: + d5:11:b2:0a:f1:8e:13:10:b2:3b:69:f4:fe:3a:e2: + f1:58:56:28:93:c1:28:aa:a7:19:c9:91:12:43:f8: + f5:1d:34:58:3d:32:9f:11:67:d1:1f:53:d4:e0:d5: + 0c:78:2c:6f:38:3f:e1:89:69:b5:09:3c:12:f4:a9: + ee:e5:2f:c5:47:65:a6:82:fa:ea:78:48:31:89:11: + b6:23:8a:27:ed:7c:1d:6d:e8:ab:a0:29:de:40:f4: + f2:9b:61:22:da:9c:22:32:f7:3d:f8:4c:e1:38:a7: + e2:c3:af:a4:67:7f:94:a4:fd:52:25:89:4d:f4:9a: + d6:35:ba:98:20:f1:4b:c9:a5:cf:ac:72:58:2a:cd: + 3b:4a:3e:e9:04:31:e2:9a:74:32:d5:52:60:34:ad: + 0c:85:02:65:58:41:74:2a:57:91:34:55:36:a9:14: + 5b:45:cc:28:27:d7:6d:ba:55:a3:dd:9f:00:04:a4: + 43:c2:af:5c:af:86:53:a6:d5:a7:49:aa:31:d6:5e: + 92:7d:26:dd:8d:f4:87:8a:9b:48:e8:25:f4:c7:34: + ca:cf:e3:f7:84:19:3b:43:c7:6a:b8:da:6e:6f:85: + af:8d:0c:fb:7c:ea:c7:73:9c:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:srv01.client02-expired.example.nil, IP Address:10.53.0.1 + Signature Algorithm: sha256WithRSAEncryption + 18:f1:7c:24:5b:d2:03:b0:60:0e:60:e6:32:f9:a7:47:d1:e4: + bd:3f:a3:21:53:90:84:9a:c6:2c:87:b2:16:28:95:07:a3:2a: + c3:33:8f:60:70:3f:26:58:be:ec:a2:6c:44:89:d3:4e:ef:bb: + ce:af:9b:5f:15:06:03:21:74:e3:6f:2a:dc:5c:19:4e:d3:cb: + ba:c3:5f:d8:76:89:59:50:82:69:5f:a1:ac:9f:be:79:e1:22: + 12:37:f9:d3:2e:00:35:03:03:9d:08:24:45:65:7a:e9:72:31: + e1:67:44:32:17:25:dd:b9:72:eb:c6:40:d7:5d:8d:5f:00:48: + 07:09:0d:3c:4c:a1:f1:05:4b:05:9b:2b:5a:21:09:46:f4:17: + 7a:cf:34:87:ad:bf:ef:bd:56:74:d7:1a:8f:07:ce:70:b1:aa: + 4d:82:4f:08:dc:56:27:f9:21:20:b8:06:c7:29:b4:8e:36:82: + b8:43:85:1c:2d:9f:be:2d:b9:9d:40:de:52:55:6a:2e:0b:28: + 33:fc:f8:1b:70:e9:c5:46:50:f3:05:be:8d:ed:99:ec:f1:8c: + 51:8a:1c:4b:95:f4:c4:dd:cd:42:74:bc:6f:66:64:54:b8:c1: + 6e:c8:3d:e9:fe:10:02:61:50:77:38:b9:b0:b8:13:37:8f:0e: + 5b:49:92:3a:9d:9a:60:51:68:99:8a:d5:7e:92:71:7e:fa:db: + 52:37:4d:f9:0d:6c:3b:79:a3:b9:16:b7:95:00:ea:eb:17:54: + e2:50:d7:a5:08:54:58:2c:79:66:01:4b:95:65:ed:b8:81:f7: + 4c:fa:f8:89:37:ad:d9:dc:c9:75:9d:02:3e:e5:92:b3:03:ab: + 70:69:83:f5:6c:a6:27:7e:2e:fc:9d:b2:59:0a:43:ad:3f:55: + 2f:5d:ec:ef:52:f0:3e:be:b5:d6:e2:c3:91:9d:dd:5d:e1:9e: + e6:18:90:0b:6a:85:f8:e3:83:2a:7c:91:c3:52:1c:6d:aa:2b: + 44:b8:6f:2b:af:6e +-----BEGIN CERTIFICATE----- +MIIEYzCCAsugAwIBAgIIcLn06y+hlZswDQYJKoZIhvcNAQELBQAwfTELMAkGA1UE +BhMCVUExGDAWBgNVBAgMD0toYXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtp +djEkMCIGA1UECgwbSW50ZXJuZXQgU3lzdGVtcyBDb25zb3J0aXVtMRwwGgYDVQQD +DBNjYS50ZXN0LmV4YW1wbGUuY29tMB4XDTIyMDkwNzA4MTQxOFoXDTIyMDkwODA4 +MTQxOFowLTErMCkGA1UEAwwic3J2MDEuY2xpZW50MDItZXhwaXJlZC5leGFtcGxl +Lm5pbDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMARJxclOq2FoDtZ +CyJkY327BTI1T2jVGSvNRr3itkKMCM8JDajNWNkbd9sXivzwVfLhUPT9kKpJFV3q +m1pHxC+CB0aH9gXvFQKkPKHa/Ft1NhL3ElBV+L4MfSGR4pLYQT9x/rIXwGgdCb78 +xCTs79JcUqlP1l0wuKtoLjnpi1vG8GRC97i9spAyImi8OHAvFK7IfGME1RGyCvGO +ExCyO2n0/jri8VhWKJPBKKqnGcmREkP49R00WD0ynxFn0R9T1ODVDHgsbzg/4Ylp +tQk8EvSp7uUvxUdlpoL66nhIMYkRtiOKJ+18HW3oq6Ap3kD08pthItqcIjL3PfhM +4Tin4sOvpGd/lKT9UiWJTfSa1jW6mCDxS8mlz6xyWCrNO0o+6QQx4pp0MtVSYDSt +DIUCZVhBdCpXkTRVNqkUW0XMKCfXbbpVo92fAASkQ8KvXK+GU6bVp0mqMdZekn0m +3Y30h4qbSOgl9Mc0ys/j94QZO0PHarjabm+Fr40M+3zqx3OcmwIDAQABozcwNTAz +BgNVHREELDAqgiJzcnYwMS5jbGllbnQwMi1leHBpcmVkLmV4YW1wbGUubmlshwQK +NQABMA0GCSqGSIb3DQEBCwUAA4IBgQAY8XwkW9IDsGAOYOYy+adH0eS9P6MhU5CE +msYsh7IWKJUHoyrDM49gcD8mWL7somxEidNO77vOr5tfFQYDIXTjbyrcXBlO08u6 +w1/YdolZUIJpX6Gsn7554SISN/nTLgA1AwOdCCRFZXrpcjHhZ0QyFyXduXLrxkDX +XY1fAEgHCQ08TKHxBUsFmytaIQlG9Bd6zzSHrb/vvVZ01xqPB85wsapNgk8I3FYn ++SEguAbHKbSONoK4Q4UcLZ++LbmdQN5SVWouCygz/PgbcOnFRlDzBb6N7Zns8YxR +ihxLlfTE3c1CdLxvZmRUuMFuyD3p/hACYVB3OLmwuBM3jw5bSZI6nZpgUWiZitV+ +knF++ttSN035DWw7eaO5FreVAOrrF1TiUNelCFRYLHlmAUuVZe24gfdM+viJN63Z +3Ml1nQI+5ZKzA6twaYP1bKYnfi78nbJZCkOtP1UvXezvUvA+vrXW4sORnd1d4Z7m +GJALaoX444MqfJHDUhxtqitEuG8rr24= +-----END CERTIFICATE----- diff --git a/bin/tests/system/nsupdate/CA/private/CA-other.key b/bin/tests/system/nsupdate/CA/private/CA-other.key new file mode 100644 index 0000000..41818aa --- /dev/null +++ b/bin/tests/system/nsupdate/CA/private/CA-other.key @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEA10Xj8dH8/XCfUvhdL/S3E10TnrYY8IIDBmU0lkUR5IHwgP9I +YVyR/0Mibg79FAs+rvuEDifUK+6wvkpj+BXNVZCspo9/u3cl7dqrLH+1SeUs50Oe +QnbbTrBl0PuNwvzEkbk7xwLlVDOyRmmvY/EEu7WkitQZgXSAYgttrk62CuJUQUmw +UTX5Jxndsjydk/zW/DiulTsX+zv8kG5NiwpXCfL6QxBoMZNI4fUmDL3bX1XfHaFA ++45GT2lHu07xc+cVeZIRCo0Nk+fIO53lDol8mmR8/5vna27gRnqEUSU7MZAMG6QB +Xkotnq3rHnrI/ku6dCJW4tbWV/ANQ+TG17g2tygzC/smqTuLqavyP9V5cRrdU9aw +Eqwvy8uVbGkTmUZdtjkGWCcmBSWJvkH3MRJmijS7rDcb8m/g9+xKe79V1c8durGW +vcfMRZZhWaoHyhnHg9+JLUCC3EUCp/1206w5vTXEQNpqi9Z3AZfgboPzJyji4OeY +fcQ5eaIZ3OuIpyQzAgMBAAECggGAD+vUWvsr2datgeZqhfR0YdM9czyGhasn7B4q +EH8VPrA5iGDZCpJdHeLqNfeX0hau0SQ69Q0PDRy/J6O61wtNv2lOy5bLXKMIRBor +FMRxNQDlHEmM999wgtZbAWTJbEVjiF+Jw0M8kMiuA7UnSp31uqhJfhcHt+JU6Gtt +9jlOD2oDzzxS9P6n6bNpCRigkuRdRhQvHUxcjrE2EbyGsaTXIR4+Uh1xh1EcT9Hg +uYqFIfzo3nkhpDk2jAL+UiUZiHfrpO6OfqpNQj27jju/35DT+2hgGuS2JApzpi91 +gJSDXwsDQYdP2a2B0y3K0+HwC7/YovAzlXkfes06ebtsiG4Nzl15vnKaTbON0vZO +7jMkedmstKaLGM5PlLW0afls5ahr0dtrhWFs+1QKcv1JahcfeEvggeH9/gtjpunM +MT31VuYbwleWAsRxjGG3OWKLgst4cJXqGTdM21JzBDOP43/ZIaaedl43jJzIgIM5 +b4ae9DrhsTNIboYO20XYdwtn9Q2pAoHBAPLO1xTWfqpCwZU6udtX73jMfpwhGlWW +0jqg9gvxs9Neg4nfYMtiliBS5VT+6oID8YSKOSWXHWFGFkBN5hqfGbu5Nd94rY0J +g6UYgGOAcNfoGOTpI2xljpEWJJfquTFgbajwFg+q3p6mL1zShkzvf6hzqENxbLxy +OvEPkszN6cy16jgEUv5qK9qNf7ISB8Ki3yFSKAfuRlapny3TcRTYkJNZ0y398/sG +E5vqrrYyjUWv5Uwz0mHmZpmZuZuaUJxtlwKBwQDi+BKnIiYYwdJPmCNCykRJB02Z +QZlxtnrrajxZsXHysTopX5HkOQH80VSbH6fj287qX7vV0ux2maFLoszjM0wtfQhE +8fsuKRPfzxR0cFtPFtncCHI5FVT2MOsdz5dZ8BsinCgsVlZ3SrUC9gxPKpVdRd21 +OUC3r+tOPvM0gdfyT560GDLhaH12iOA5KtWnE3FIEpk6y95D1a4E7zu4ZaoI98UU +F8ezSREzF9UzAcdVn8MA3v82nlGQS8iFI9mHicUCgcACWkS1O/rQNYNgqcgBOxHj +7r9PTfbOW36/+K1JolbmtmS54kMy1Uq1F3iHYUzuY5Fkgl5ZYeRz+9TdXKPdICuE +qR+/gZDU7AGtiNY9oJH3VZVgKm4gb7944mkKW8jdlJybZXAhSLuNd/i/gn6woiVv +gWdg9+lgzg6KJWd7uocIZ77UOh5/vpGcNYDGPex7U06sKPqgUQu3bT9Ql1riI9MK +ynUEXhCOHxnzicuVklnSEgk7usjQEAZweI/W1SDw0xMCgcEAm9BQBdsEqlRNDAVW +l6CB9lyEIiUNsSnkAr9AxRZzMngGhKauYi3ctnICkifOOzgIOZAVRDpzyQu41lLi +M0thDY1bYvF4TX03vprL4Q/NL2NxloNZ3uRNGmIE1sdPkRermTv4vE9dNrHbyDef +xa1nMswm4yV1z2R+to2yqqZE2H1eZyaBr4rrLrfSroxAdl17lE3oUZvpb0o/F/Yg +Wnu4mkV2T0/v8Z3Ep/3BiC29aYOu/Gcab6WKOvQ7qWMuD8U9AoHBAJslXJMsMZVc +UIaxRbknRMEBRBJW6X6EPbV3zGa+R9e9XRSG7jYSOWB9Yb2AbwjsvF4Qq+8VQq+V +Ksxs7XOuwR202oZFzQDMoVj1LL4Cn60rRWlI+p6Q5SB2DQVo2kulTv1NtvdVR+U0 +ABa0xp5TKi7+jTY/e3CJGiT69sZc7v2VXptoiGytlUl9GVr0SImD1ZJdaJSJCPZX +S+cEzfF6LVnnhlaq4puuv/vKjumNWDymv3zwZOy9D8nn/tMHqLKWSg== +-----END RSA PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/private/CA.key b/bin/tests/system/nsupdate/CA/private/CA.key new file mode 100644 index 0000000..2d5419d --- /dev/null +++ b/bin/tests/system/nsupdate/CA/private/CA.key @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEAouoRHoAc6VCmxNTU6Ge7s+xDFGO0wXJJIsP+8nUyyjWvGCOC +aQYLhb1kLA2NHRhSSKFcMh8jcd7Hlvy6CAec1j2dsWzryy3HgPrdjWaW3PfBO41D +lUtdt8hA/p6pX2YwqvWbdK/3s8J0LY5xRZKNZnFOB/Sb4PGiIJ1NgMRO/M3IlPQm +PO/faRRTU4SI26KCPKFW342826Zi88YwOd6w5mQU4fskk5TGtlNqE+Fj40ZbWVpy +VXoEUS6RveRp020NX5CQG49SLtdF05AnnsATqmgNVCXptGuqW8uaHRONeGO3NBEy +nJmibWBDUMjtCCcGVgyrVXuTkyAJJWpImnshUwgMNYebRwmC2iVv2LtsJS5eUTUH +EWffnFl55XU2PkyNYgY35gA4y3SiWFJYV8+5FibU4ut0nb+lmHBF8WlqcU/kd3tp +Gkf0exjqOIHZFqV9bIhpUbXhxx9v9+gkkGQ9nrXE1KRlvigxxUeIK5xHy9a7fVIL +wo6WuCnLLJmbVkklAgMBAAECggGBAI5ZV3v/FUQIZK+4CBDKEwizeClotZgR9DWc +bDgOj8KABe5hmKGL1qWVRuH3NUYm6j7sP1LMQnxM3LjhOuupOzE3xYIyWhW+eoQI +r23OJiQNl5ohZNweblUXdTMGD5h8AipfUOY0m4tGbZ0gyXixBTxt5HCvG0UB3VgC +GqZY4Wujo5ADhSXZsqxuRiDDvZGr/YBcuTu87Tg/ulam5ZyrKIcnC9gpSVxqsva9 +DAMy/cSoxUjd7ukhJISK3G3AF3fV4GSslQcJTlyJ2D3+LnqPuHJKYTI4hc46lN3x +E2g24GdSCPYf6SoEPwACXtbavV8TXwQPJrHN+f+0/ePCI4jkYe5NoA3gwVgMb/WB +wFchxzVh3V4e8tPGiG+ofKl81DSAW8VZCJLUIbTEce9oxafPT78WJxdC0wWbh5S8 +V/qN6sW/yWnK3oY9SilWhJGRwKOZ+8xtStaDeCzyCaOqEcWi8ZR0QfC33UozlhdC +SrMKnOXmn/rUuXGrVR56IzIl0M7YAQKBwQDM3GJDdlFuHn6L0syKYdHDS8gXD9ke +s+ochIP6jvkEPcayaEoZGl8s7RT3iztqXod7wLaZdotktxfDAZnJfeuOcVrCu+Bx +HLytnBvV6czMfp3REGgQAJQeusSgtlBCTHHVOsDzIjdnkY3WBa7IiFYWO5wnYrGx +r3ucnwnHaUVDMj1r4YI7mYIpCuYQl6eGyW7mhWewyhVwoQXKbifdrXxjvOigL0Cp +tgsoU9pql3hpphOaYMX6hLOincTfaMxfnCECgcEAy5UXp3dA0OwK+4iDGKr+cUpk +AtGTheiE+8zEVh2KYFLt921mW/QZiB1+xtnkknp3c7u07Ugk8jAEXzCkwMnN5ZCx +LrJ72fC+cLIAbRm6/vMMP8iz83wyttao4qNMeoOBBfE9rEiP+lrugpv282V3ZHYa +IUZWTeugJbckUHTbD3RZQExmQcRVG3m/TzonBfoZ8HoRj/n3d7V2T911cHUhi8Xn +RQIi2m63VofOIep86LgartlKneMWnL0oOPq4RKyFAoHAZUzpDkD4nUJZAx025Yrf +ZfoYNEcy7vq6XmWsuX5vZoiBs4DcezNOMvH9NzdTJxMdXbV61cIHxcK/7j7hZABv +NZ2Z6sdqgaRbLGIQZaPaEJjfwxygyKDwnY1vY6UjZNVWSMFn3hJiYUVZZKakuiao +ow/Q9KzZ/2ot7tG5zTCh/ktekfUOKBiNg2wPPc8wGPeMblMzZflXxrzpFyOHdRev +dcZZJbSX/hO1yrhEPgculNd5xBHsdCegiF4JlwvEW9bhAoHAZQQiy5bx03j8bhkr +q6bVQFPAUmG5iL16lxLg7TYVPnyH1bk0DDaQIKk6CeN+dmxML2IZgY/FvWK0GKOj +bIH2J43nTRuFNvwtEvBQI9KbpfvlvRSSriOXaoATJvoObdAoylEM4BrVTk2mgapw +HA/h8Thk+NPU6S8ctPouC7ogJIf/7Va7erC35j0//0kEqgOSsW9wnXdUItMo1LI3 +nsiQD7Hwcp5/utErKcWTM+MNfdA0dUQesT9ILhfyCGvn2TOdAoHBAKldZkDyRcu9 +r9uDF1bhUEnpV2k4hgvTuCvQ3rzyx3WrVT8ChEmePC8Ke5A54ffu/YdbpDLbdf2c +j4n5CQhHbMIZs3P2hB3WqDCImApCfMbXaltfBbaT0j7uLJPMp+2+f/wWYpc3R+bn +HVnaRI2PoXXmG9OjQSQdVZ5gNpkEuemAo3dJOSS6BMqQaSxUynGy7o/a/d4izBjd +B58Fwq3sZI/Xv90Se9+b6ICST3YJ3p0vn8RKzmlCQjLg/xynpCByiw== +-----END RSA PRIVATE KEY----- diff --git a/bin/tests/system/nsupdate/CA/serial b/bin/tests/system/nsupdate/CA/serial new file mode 100644 index 0000000..0a263a5 --- /dev/null +++ b/bin/tests/system/nsupdate/CA/serial @@ -0,0 +1 @@ +70B9F4EB2FA1959C diff --git a/bin/tests/system/nsupdate/ans4/ans.pl b/bin/tests/system/nsupdate/ans4/ans.pl new file mode 100644 index 0000000..30c792f --- /dev/null +++ b/bin/tests/system/nsupdate/ans4/ans.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use IO::Socket; +use IO::File; +use strict; + +# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early +local $SIG{PIPE} = 'IGNORE'; + +# Flush logged output after every line +local $| = 1; + +my $server_addr = "10.53.0.4"; +if (@ARGV > 0) { + $server_addr = @ARGV[0]; +} + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; +my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +print "listening on $server_addr:$localport.\n"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!";; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +# Main +for (;;) { + my $rin; + my $rout; + + $rin = ''; + vec($rin, fileno($udpsock), 1) = 1; + vec($rin, fileno($tcpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($udpsock), 1)) { + printf "UDP request\n"; + my $buf; + $udpsock->recv($buf, 512); + } elsif (vec($rout, fileno($tcpsock), 1)) { + printf "TCP request\n"; + } +} diff --git a/bin/tests/system/nsupdate/commandlist b/bin/tests/system/nsupdate/commandlist new file mode 100644 index 0000000..41c8049 --- /dev/null +++ b/bin/tests/system/nsupdate/commandlist @@ -0,0 +1,15 @@ +server 127.0.0.1 +server 127.0.0.1 port +update +update delete +update delete dummy +update delete dummy in +update delete dummy in a +update delete dummy in a 127.0.0.1 +update add +update add domain +update add domain 0 +update add domain 0 in +update add domain 0 in a +update add domain 0 a +update add domain 0 a in diff --git a/bin/tests/system/nsupdate/dhparam3072.pem b/bin/tests/system/nsupdate/dhparam3072.pem new file mode 100644 index 0000000..fb31ccd --- /dev/null +++ b/bin/tests/system/nsupdate/dhparam3072.pem @@ -0,0 +1,11 @@ +-----BEGIN DH PARAMETERS----- +MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3 +7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32 +nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu +N///////////AgEC +-----END DH PARAMETERS----- diff --git a/bin/tests/system/nsupdate/knowngood.ns1.after b/bin/tests/system/nsupdate/knowngood.ns1.after new file mode 100644 index 0000000..4114159 --- /dev/null +++ b/bin/tests/system/nsupdate/knowngood.ns1.after @@ -0,0 +1,99 @@ +example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600 +example.nil. 300 IN NS ns1.example.nil. +example.nil. 300 IN NS ns2.example.nil. +*.example.nil. 300 IN MX 10 mail.example.nil. +a.example.nil. 300 IN TXT "foo foo foo" +a.example.nil. 300 IN PTR foo.net. +a01.example.nil. 3600 IN A 0.0.0.0 +a02.example.nil. 3600 IN A 255.255.255.255 +a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil. +afsdb02.example.nil. 3600 IN AFSDB 65535 . +b.example.nil. 300 IN CNAME foo.net. +c.example.nil. 300 IN A 73.80.65.49 +cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +cname01.example.nil. 3600 IN CNAME cname-target. +cname02.example.nil. 3600 IN CNAME cname-target.example.nil. +cname03.example.nil. 3600 IN CNAME . +d.example.nil. 300 IN A 73.80.65.49 +dname01.example.nil. 3600 IN DNAME dname-target. +dname02.example.nil. 3600 IN DNAME dname-target.example.nil. +dname03.example.nil. 3600 IN DNAME . +e.example.nil. 300 IN MX 10 mail.example.nil. +e.example.nil. 300 IN TXT "one" +e.example.nil. 300 IN TXT "two" +e.example.nil. 300 IN TXT "three" +e.example.nil. 300 IN A 73.80.65.49 +e.example.nil. 300 IN A 73.80.65.50 +e.example.nil. 300 IN A 73.80.65.51 +e.example.nil. 300 IN A 73.80.65.52 +f.example.nil. 300 IN A 73.80.65.52 +gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0" +gpos02.example.nil. 3600 IN GPOS "" "" "" +hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD" +isdn01.example.nil. 3600 IN ISDN "isdn-address" +isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress" +isdn03.example.nil. 3600 IN ISDN "isdn-address" +isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress" +key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +kx01.example.nil. 3600 IN KX 10 kdc.example.nil. +kx02.example.nil. 3600 IN KX 10 . +loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01.example.nil. 3600 IN MG madname.example.nil. +mb02.example.nil. 3600 IN MG . +mg01.example.nil. 3600 IN MG mgmname.example.nil. +mg02.example.nil. 3600 IN MG . +minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil. +minfo02.example.nil. 3600 IN MINFO . . +mr01.example.nil. 3600 IN MR mrname.example.nil. +mr02.example.nil. 3600 IN MR . +mx01.example.nil. 3600 IN MX 10 mail.example.nil. +mx02.example.nil. 3600 IN MX 10 . +naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" . +naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +ns1.example.nil. 300 IN A 10.53.0.1 +ns2.example.nil. 300 IN A 10.53.0.2 +nsap-ptr01.example.nil. 3600 IN NSAP-PTR . +nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo. +nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT +nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT +nxt03.example.nil. 3600 IN NXT . A +nxt04.example.nil. 3600 IN NXT . 127 +ptr01.example.nil. 3600 IN PTR example.nil. +px01.example.nil. 3600 IN PX 65535 foo. bar. +px02.example.nil. 3600 IN PX 65535 . . +rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil. +rp02.example.nil. 3600 IN RP . . +rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil. +rt02.example.nil. 3600 IN RT 65535 . +s.example.nil. 300 IN NS ns.s.example.nil. +ns.s.example.nil. 300 IN A 73.80.65.49 +sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +srv01.example.nil. 3600 IN SRV 0 0 0 . +srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. +txt01.example.nil. 3600 IN TXT "foo" +txt02.example.nil. 3600 IN TXT "foo" "bar" +txt03.example.nil. 3600 IN TXT "foo" +txt04.example.nil. 3600 IN TXT "foo" "bar" +txt05.example.nil. 3600 IN TXT "foo bar" +txt06.example.nil. 3600 IN TXT "foo bar" +txt07.example.nil. 3600 IN TXT "foo bar" +txt08.example.nil. 3600 IN TXT "foo\010bar" +txt09.example.nil. 3600 IN TXT "foo\010bar" +txt10.example.nil. 3600 IN TXT "foo bar" +txt11.example.nil. 3600 IN TXT "\"foo\"" +txt12.example.nil. 3600 IN TXT "\"foo\"" +u.example.nil. 300 IN TXT "txt-not-in-nxt" +a.u.example.nil. 300 IN A 73.80.65.49 +b.u.example.nil. 300 IN A 73.80.65.49 +updated.example.nil. 600 IN TXT "Foo" +updated.example.nil. 600 IN A 10.10.10.1 +wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535 +x2501.example.nil. 3600 IN X25 "123456789" +example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600 diff --git a/bin/tests/system/nsupdate/knowngood.ns1.afterstop b/bin/tests/system/nsupdate/knowngood.ns1.afterstop new file mode 100644 index 0000000..e871d4c --- /dev/null +++ b/bin/tests/system/nsupdate/knowngood.ns1.afterstop @@ -0,0 +1,3 @@ +updated4.example.nil. 600 IN A 10.10.10.3 +example.nil. 300 IN NS ns1.example.nil. +example.nil. 300 IN NS ns2.example.nil. diff --git a/bin/tests/system/nsupdate/knowngood.ns1.before b/bin/tests/system/nsupdate/knowngood.ns1.before new file mode 100644 index 0000000..4a5e630 --- /dev/null +++ b/bin/tests/system/nsupdate/knowngood.ns1.before @@ -0,0 +1,98 @@ +example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600 +example.nil. 300 IN NS ns1.example.nil. +example.nil. 300 IN NS ns2.example.nil. +*.example.nil. 300 IN MX 10 mail.example.nil. +a.example.nil. 300 IN TXT "foo foo foo" +a.example.nil. 300 IN PTR foo.net. +a01.example.nil. 3600 IN A 0.0.0.0 +a02.example.nil. 3600 IN A 255.255.255.255 +a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff +afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil. +afsdb02.example.nil. 3600 IN AFSDB 65535 . +b.example.nil. 300 IN CNAME foo.net. +c.example.nil. 300 IN A 73.80.65.49 +cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +cname01.example.nil. 3600 IN CNAME cname-target. +cname02.example.nil. 3600 IN CNAME cname-target.example.nil. +cname03.example.nil. 3600 IN CNAME . +d.example.nil. 300 IN A 73.80.65.49 +dname01.example.nil. 3600 IN DNAME dname-target. +dname02.example.nil. 3600 IN DNAME dname-target.example.nil. +dname03.example.nil. 3600 IN DNAME . +e.example.nil. 300 IN MX 10 mail.example.nil. +e.example.nil. 300 IN TXT "one" +e.example.nil. 300 IN TXT "two" +e.example.nil. 300 IN TXT "three" +e.example.nil. 300 IN A 73.80.65.49 +e.example.nil. 300 IN A 73.80.65.50 +e.example.nil. 300 IN A 73.80.65.51 +e.example.nil. 300 IN A 73.80.65.52 +f.example.nil. 300 IN A 73.80.65.52 +gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0" +gpos02.example.nil. 3600 IN GPOS "" "" "" +hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" +hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD" +isdn01.example.nil. 3600 IN ISDN "isdn-address" +isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress" +isdn03.example.nil. 3600 IN ISDN "isdn-address" +isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress" +key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= +kx01.example.nil. 3600 IN KX 10 kdc.example.nil. +kx02.example.nil. 3600 IN KX 10 . +loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m +mb01.example.nil. 3600 IN MG madname.example.nil. +mb02.example.nil. 3600 IN MG . +mg01.example.nil. 3600 IN MG mgmname.example.nil. +mg02.example.nil. 3600 IN MG . +minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil. +minfo02.example.nil. 3600 IN MINFO . . +mr01.example.nil. 3600 IN MR mrname.example.nil. +mr02.example.nil. 3600 IN MR . +mx01.example.nil. 3600 IN MX 10 mail.example.nil. +mx02.example.nil. 3600 IN MX 10 . +naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" . +naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blllbb" foo. +ns1.example.nil. 300 IN A 10.53.0.1 +ns2.example.nil. 300 IN A 10.53.0.2 +nsap-ptr01.example.nil. 3600 IN NSAP-PTR . +nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo. +nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 +nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT +nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT +nxt03.example.nil. 3600 IN NXT . A +nxt04.example.nil. 3600 IN NXT . 127 +ptr01.example.nil. 3600 IN PTR example.nil. +px01.example.nil. 3600 IN PX 65535 foo. bar. +px02.example.nil. 3600 IN PX 65535 . . +rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil. +rp02.example.nil. 3600 IN RP . . +rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil. +rt02.example.nil. 3600 IN RT 65535 . +s.example.nil. 300 IN NS ns.s.example.nil. +ns.s.example.nil. 300 IN A 73.80.65.49 +sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= +srv01.example.nil. 3600 IN SRV 0 0 0 . +srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. +t.example.nil. 301 IN A 73.80.65.49 +txt01.example.nil. 3600 IN TXT "foo" +txt02.example.nil. 3600 IN TXT "foo" "bar" +txt03.example.nil. 3600 IN TXT "foo" +txt04.example.nil. 3600 IN TXT "foo" "bar" +txt05.example.nil. 3600 IN TXT "foo bar" +txt06.example.nil. 3600 IN TXT "foo bar" +txt07.example.nil. 3600 IN TXT "foo bar" +txt08.example.nil. 3600 IN TXT "foo\010bar" +txt09.example.nil. 3600 IN TXT "foo\010bar" +txt10.example.nil. 3600 IN TXT "foo bar" +txt11.example.nil. 3600 IN TXT "\"foo\"" +txt12.example.nil. 3600 IN TXT "\"foo\"" +u.example.nil. 300 IN TXT "txt-not-in-nxt" +a.u.example.nil. 300 IN A 73.80.65.49 +b.u.example.nil. 300 IN A 73.80.65.49 +wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 +wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53 +wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535 +x2501.example.nil. 3600 IN X25 "123456789" +example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600 diff --git a/bin/tests/system/nsupdate/krb/setup.sh b/bin/tests/system/nsupdate/krb/setup.sh new file mode 100644 index 0000000..8b252df --- /dev/null +++ b/bin/tests/system/nsupdate/krb/setup.sh @@ -0,0 +1,116 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -x + +PWD=$(pwd) + +KRB5_CONFIG="${PWD}/krb5.conf" +export KRB5_CONFIG + +KRB5_KDC_PROFILE=${PWD}/krb5kdc +export KRB5_KDC_PROFILE + +now=$(date +%s) +lifetime=$((2147483647 - now)) +lifetime=$((lifetime / 3600 / 24 - 30)) + +cat <"${KRB5_CONFIG}" +[libdefaults] + default_realm = EXAMPLE.COM + dns_lookup_kdc = false + # Depending on what you are testing, you may want something like: + # default_keytab_name = FILE:/usr/local/var/keytab +[realms] + EXAMPLE.COM = { + admin_server = 127.0.0.1:50001 + kdc = 127.0.0.1:50000 + database_module = DB2 + kdc_ports = 50000 + kadmind_port = 50001 + } +[dbmodules] + DB2 = { + db_library = db2 + } +[logging] + # Use any pathnames you want here. + kdc = FILE:${PWD}/kdc.log + admin_server = FILE:${PWD}/kadmin.log +# Depending on what you are testing, you may want: +# [domain_realm] +# your.domain = EXAMPLE.COM +EOF + +rm -rf ${KRB5_KDC_PROFILE} +mkdir -p ${KRB5_KDC_PROFILE} +chmod 700 ${KRB5_KDC_PROFILE} + +cat <"${KRB5_KDC_PROFILE}"/kdc.conf +[kdcdefaults] + kdc_ports = 50000 + kdc_tcp_ports = 50000 + +[realms] + EXAMPLE.COM = { + key_stash_file = ${KRB5_KDC_PROFILE}/.k5.EXAMPLE.COM + database_module = EXAMPLE.COM + max_life = ${lifetime}d +} + +[dbmodules] + EXAMPLE.COM = { + db_library = db2 + database_name = ${KRB5_KDC_PROFILE}/principal + } +EOF + +kdb5_util create -s <$zonefile + +$SIGNER -P -3 - -H 1 -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null + +zone=dnskey.test. +infile=dnskey.test.db.in +zonefile=dnskey.test.db + +keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone -f KSK $zone) +keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) + +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -P -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null + +zone=delegation.test. +infile=delegation.test.db.in +zonefile=delegation.test.db + +keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -f KSK $zone) +keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone) + +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -A -3 - -P -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null + +# Just copy multisigner.db.in because it is signed with dnssec-policy. +cp multisigner.test.db.in multisigner.test.db diff --git a/bin/tests/system/nsupdate/ns3/too-big.test.db.in b/bin/tests/system/nsupdate/ns3/too-big.test.db.in new file mode 100644 index 0000000..45ee9ad --- /dev/null +++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 10 +too-big.test. IN SOA too-big.test. hostmaster.too-big.test. 1 3600 900 2419200 3600 +too-big.test. IN NS too-big.test. +too-big.test. IN A 10.53.0.3 diff --git a/bin/tests/system/nsupdate/ns5/local.db.in b/bin/tests/system/nsupdate/ns5/local.db.in new file mode 100644 index 0000000..12a5d8b --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/local.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +local.nil IN SOA ns5.local.nil. hostmaster.local.nil. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +local.nil. NS ns5.local.nil. +ns5.local.nil. A 10.53.0.5 + +$ORIGIN local.nil. +a A 10.10.10.10 diff --git a/bin/tests/system/nsupdate/ns5/named.args b/bin/tests/system/nsupdate/ns5/named.args new file mode 100644 index 0000000..64da462 --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/named.args @@ -0,0 +1 @@ +-D nsupdate-ns5 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -T fixedlocal diff --git a/bin/tests/system/nsupdate/ns5/named.conf.in b/bin/tests/system/nsupdate/ns5/named.conf.in new file mode 100644 index 0000000..223abd9 --- /dev/null +++ b/bin/tests/system/nsupdate/ns5/named.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "local.nil" { + type primary; + file "local.db"; + update-policy local; +}; diff --git a/bin/tests/system/nsupdate/ns6/2.0.0.2.ip6.addr.db.in b/bin/tests/system/nsupdate/ns6/2.0.0.2.ip6.addr.db.in new file mode 100644 index 0000000..71609c3 --- /dev/null +++ b/bin/tests/system/nsupdate/ns6/2.0.0.2.ip6.addr.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns5.local.nil. hostmaster.local.nil. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns6 +ns6 A 10.53.0.6 diff --git a/bin/tests/system/nsupdate/ns6/in-addr.db.in b/bin/tests/system/nsupdate/ns6/in-addr.db.in new file mode 100644 index 0000000..9ac2b61 --- /dev/null +++ b/bin/tests/system/nsupdate/ns6/in-addr.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns5.local.nil. hostmaster.local.nil. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns5 +ns5 A 10.53.0.5 diff --git a/bin/tests/system/nsupdate/ns6/named.args b/bin/tests/system/nsupdate/ns6/named.args new file mode 100644 index 0000000..e0a2225 --- /dev/null +++ b/bin/tests/system/nsupdate/ns6/named.args @@ -0,0 +1 @@ +-D nsupdate-ns6 -m record -c named.conf -d 99 -g -T maxcachesize=2097152 -T fixedlocal diff --git a/bin/tests/system/nsupdate/ns6/named.conf.in b/bin/tests/system/nsupdate/ns6/named.conf.in new file mode 100644 index 0000000..e2950aa --- /dev/null +++ b/bin/tests/system/nsupdate/ns6/named.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + query-source-v6 address fd92:7065:b8e:ffff::6; + notify-source-v6 fd92:7065:b8e:ffff::6; + transfer-source-v6 fd92:7065:b8e:ffff::6; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.6; }; + listen-on-v6 { fd92:7065:b8e:ffff::6; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.db"; + update-policy { grant * tcp-self . PTR(1) ANY(2) A; }; +}; + +zone "2.0.0.2.ip6.arpa" { + type primary; + file "2.0.0.2.ip6.addr.db"; + update-policy { grant * 6to4-self . NS(10) DS(4); }; +}; diff --git a/bin/tests/system/nsupdate/ns7/dns.keytab b/bin/tests/system/nsupdate/ns7/dns.keytab new file mode 100644 index 0000000..08d5ef4 Binary files /dev/null and b/bin/tests/system/nsupdate/ns7/dns.keytab differ diff --git a/bin/tests/system/nsupdate/ns7/example.com.db.in b/bin/tests/system/nsupdate/ns7/example.com.db.in new file mode 100644 index 0000000..6e4b17a --- /dev/null +++ b/bin/tests/system/nsupdate/ns7/example.com.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns7.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns7 +ns7 A 10.53.0.7 +single.any.self-srv SRV 0 0 0 machine.example.com. +many.any.self-srv SRV 0 0 0 machine.example.com. +many.any.self-srv SRV 0 0 0 notmachine.example.com. +single.srv.self-srv SRV 0 0 0 machine.example.com. +many.srv.self-srv SRV 0 0 0 machine.example.com. +many.srv.self-srv SRV 0 0 0 notmachine.example.com. diff --git a/bin/tests/system/nsupdate/ns7/in-addr.db.in b/bin/tests/system/nsupdate/ns7/in-addr.db.in new file mode 100644 index 0000000..973c77f --- /dev/null +++ b/bin/tests/system/nsupdate/ns7/in-addr.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns7.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns7 +ns7 A 10.53.0.7 +single.any.self-ptr PTR machine.example.com. +many.any.self-ptr PTR machine.example.com. +many.any.self-ptr PTR notmachine.example.com. +single.ptr.self-ptr PTR machine.example.com. +many.ptr.self-ptr PTR machine.example.com. +many.ptr.self-ptr PTR notmachine.example.com. diff --git a/bin/tests/system/nsupdate/ns7/machine.ccache b/bin/tests/system/nsupdate/ns7/machine.ccache new file mode 100644 index 0000000..7dcd959 Binary files /dev/null and b/bin/tests/system/nsupdate/ns7/machine.ccache differ diff --git a/bin/tests/system/nsupdate/ns7/named1.conf.in b/bin/tests/system/nsupdate/ns7/named1.conf.in new file mode 100644 index 0000000..0fcdcab --- /dev/null +++ b/bin/tests/system/nsupdate/ns7/named1.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.db"; + update-policy { grant EXAMPLE.COM krb5-subdomain-self-rhs . PTR; }; +}; + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant EXAMPLE.COM krb5-self . ANY; + grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV; + grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv.example.com SRV; + grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv-no-type.example.com; + }; +}; diff --git a/bin/tests/system/nsupdate/ns7/named2.conf.in b/bin/tests/system/nsupdate/ns7/named2.conf.in new file mode 100644 index 0000000..8ef779b --- /dev/null +++ b/bin/tests/system/nsupdate/ns7/named2.conf.in @@ -0,0 +1,54 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; + tkey-gssapi-keytab "dns.keytab"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.db"; + update-policy { grant EXAMPLE.COM krb5-subdomain-self-rhs . PTR; }; +}; + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant EXAMPLE.COM krb5-self . ANY; + grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV; + grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv.example.com SRV; + grant EXAMPLE.COM krb5-subdomain-self-rhs self-srv-no-type.example.com; + }; +}; diff --git a/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab b/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab new file mode 100644 index 0000000..3340049 Binary files /dev/null and b/bin/tests/system/nsupdate/ns8/dns-other-than-KRB5_KTNAME.keytab differ diff --git a/bin/tests/system/nsupdate/ns8/example.com.db.in b/bin/tests/system/nsupdate/ns8/example.com.db.in new file mode 100644 index 0000000..f83a3eb --- /dev/null +++ b/bin/tests/system/nsupdate/ns8/example.com.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns8.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns8 +ns8 A 10.53.0.8 diff --git a/bin/tests/system/nsupdate/ns8/in-addr.db.in b/bin/tests/system/nsupdate/ns8/in-addr.db.in new file mode 100644 index 0000000..f83a3eb --- /dev/null +++ b/bin/tests/system/nsupdate/ns8/in-addr.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns8.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns8 +ns8 A 10.53.0.8 diff --git a/bin/tests/system/nsupdate/ns8/machine.ccache b/bin/tests/system/nsupdate/ns8/machine.ccache new file mode 100644 index 0000000..6e75aff Binary files /dev/null and b/bin/tests/system/nsupdate/ns8/machine.ccache differ diff --git a/bin/tests/system/nsupdate/ns8/named.conf.in b/bin/tests/system/nsupdate/ns8/named.conf.in new file mode 100644 index 0000000..3d9913f --- /dev/null +++ b/bin/tests/system/nsupdate/ns8/named.conf.in @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; + tkey-gssapi-keytab "dns-other-than-KRB5_KTNAME.keytab"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.db"; + update-policy { grant EXAMPLE.COM krb5-subdomain . PTR; }; +}; + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant EXAMPLE.COM krb5-selfsub . ANY; + grant EXAMPLE.COM krb5-subdomain _tcp.example.com SRV; + }; +}; diff --git a/bin/tests/system/nsupdate/ns9/dns.keytab b/bin/tests/system/nsupdate/ns9/dns.keytab new file mode 100644 index 0000000..470317f Binary files /dev/null and b/bin/tests/system/nsupdate/ns9/dns.keytab differ diff --git a/bin/tests/system/nsupdate/ns9/example.com.db.in b/bin/tests/system/nsupdate/ns9/example.com.db.in new file mode 100644 index 0000000..cb3fae5 --- /dev/null +++ b/bin/tests/system/nsupdate/ns9/example.com.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns9.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns9 +ns9 A 10.53.0.9 diff --git a/bin/tests/system/nsupdate/ns9/in-addr.db.in b/bin/tests/system/nsupdate/ns9/in-addr.db.in new file mode 100644 index 0000000..cb3fae5 --- /dev/null +++ b/bin/tests/system/nsupdate/ns9/in-addr.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns9.example.com. hostmaster.example.com. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns9 +ns9 A 10.53.0.9 diff --git a/bin/tests/system/nsupdate/ns9/machine.ccache b/bin/tests/system/nsupdate/ns9/machine.ccache new file mode 100644 index 0000000..2b59cec Binary files /dev/null and b/bin/tests/system/nsupdate/ns9/machine.ccache differ diff --git a/bin/tests/system/nsupdate/ns9/named.conf.in b/bin/tests/system/nsupdate/ns9/named.conf.in new file mode 100644 index 0000000..07e38d2 --- /dev/null +++ b/bin/tests/system/nsupdate/ns9/named.conf.in @@ -0,0 +1,66 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + minimal-responses no; + dnssec-validation no; + @TKEY_CONFIGURATION@ +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key subkey { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.db"; + update-policy { grant EXAMPLE.COM ms-subdomain . PTR; }; +}; + +zone "example.com" { + type primary; + file "example.com.db"; + update-policy { + grant EXAMPLE.COM ms-self . ANY; + grant EXAMPLE.COM ms-subdomain _tcp.example.com SRV; + }; +}; + +zone "denyname.example" { + type primary; + file "denyname.example.db"; + update-policy { + deny subkey name denyname.example; + grant subkey subdomain denyname.example; + }; +}; diff --git a/bin/tests/system/nsupdate/prereq.sh b/bin/tests/system/nsupdate/prereq.sh new file mode 100644 index 0000000..c52be9c --- /dev/null +++ b/bin/tests/system/nsupdate/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/nsupdate/resolv.conf b/bin/tests/system/nsupdate/resolv.conf new file mode 100644 index 0000000..e713bae --- /dev/null +++ b/bin/tests/system/nsupdate/resolv.conf @@ -0,0 +1,15 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +nameserver 10.53.0.1 +nameserver 10.53.0.3 diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh new file mode 100644 index 0000000..38942ba --- /dev/null +++ b/bin/tests/system/nsupdate/setup.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if $FEATURETEST --have-fips-dh; then + copy_setports ns1/tls.conf.in ns1/tls.conf + copy_setports ns1/tls.options.in ns1/tls.options +else + : >ns1/tls.conf + : >ns1/tls.options +fi +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named1.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf + +# If "tkey-gssapi-credential" is set in the configuration and GSSAPI support is +# not available, named will refuse to start. As the test system framework does +# not support starting named instances conditionally, ensure that +# "tkey-gssapi-credential" is only present in named.conf if GSSAPI support is +# available. +copy_setports ns9/named.conf.in ns9/named.conf.in.tkey +copy_setports ns10/named.conf.in ns10/named.conf.in.tkey +if $FEATURETEST --gssapi; then + sed 's|@TKEY_CONFIGURATION@|tkey-gssapi-credential "DNS/ns9.example.com@EXAMPLE.COM";|' ns9/named.conf.in.tkey >ns9/named.conf + sed 's|@TKEY_CONFIGURATION@|tkey-gssapi-credential "DNS/ns10.example.com@EXAMPLE.COM";|' ns10/named.conf.in.tkey >ns10/named.conf +else + sed 's|@TKEY_CONFIGURATION@||' ns9/named.conf.in.tkey >ns9/named.conf + sed 's|@TKEY_CONFIGURATION@||' ns10/named.conf.in.tkey >ns10/named.conf +fi +rm -f ns9/named.conf.in.tkey +rm -f ns10/named.conf.in.tkey + +copy_setports verylarge.in verylarge + +cp -f ns1/example1.db ns1/example.db +sed 's/example.nil/other.nil/g' ns1/example1.db >ns1/other.db +sed 's/example.nil/unixtime.nil/g' ns1/example1.db >ns1/unixtime.db +sed 's/example.nil/yyyymmddvv.nil/g' ns1/example1.db >ns1/yyyymmddvv.db +sed 's/example.nil/keytests.nil/g' ns1/example1.db >ns1/keytests.db +cp -f ns3/example.db.in ns3/example.db +cp -f ns3/relaxed.db.in ns3/relaxed.db +cp -f ns3/too-big.test.db.in ns3/too-big.test.db + +# update_test.pl has its own zone file because it +# requires a specific NS record set. +cat <<\EOF >ns1/update.db +$ORIGIN . +$TTL 300 ; 5 minutes +update.nil IN SOA ns1.example.nil. hostmaster.example.nil. ( + 1 ; serial + 2000 ; refresh (2000 seconds) + 2000 ; retry (2000 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +update.nil. NS ns1.update.nil. +ns1.update.nil. A 10.53.0.2 +ns2.update.nil. AAAA ::1 +EOF + +$TSIGKEYGEN ddns-key.example.nil >ns1/ddns.key + +if $FEATURETEST --md5; then + $TSIGKEYGEN -a hmac-md5 md5-key >ns1/md5.key +else + echo "/* MD5 NOT SUPPORTED */" >ns1/md5.key +fi +$TSIGKEYGEN -a hmac-sha1 sha1-key >ns1/sha1.key +$TSIGKEYGEN -a hmac-sha224 sha224-key >ns1/sha224.key +$TSIGKEYGEN -a hmac-sha256 sha256-key >ns1/sha256.key +$TSIGKEYGEN -a hmac-sha384 sha384-key >ns1/sha384.key +$TSIGKEYGEN -a hmac-sha512 sha512-key >ns1/sha512.key + +if $FEATURETEST --md5; then + echo 'key "legacy-157" { algorithm "hmac-md5"; secret "mGcDSCx/fF121GOVJlITLg=="; };' >ns1/legacy157.key +else + echo "/* MD5 NOT SUPPORTED */" >ns1/legacy157.key +fi +echo 'key "legacy-161" { algorithm "hmac-sha1"; secret "N80fGvcr8JifzRUJ62R4rQ=="; };' >ns1/legacy161.key +echo 'key "legacy-162" { algorithm "hmac-sha224"; secret "nSIKzFAGS7/tvBs8JteI+Q=="; };' >ns1/legacy162.key +echo 'key "legacy-163" { algorithm "hmac-sha256"; secret "CvaupxnDeES3HnlYhTq53w=="; };' >ns1/legacy163.key +echo 'key "legacy-164" { algorithm "hmac-sha384"; secret "wDldBJwJrYfPoL1Pj4ucOQ=="; };' >ns1/legacy164.key +echo 'key "legacy-165" { algorithm "hmac-sha512"; secret "OgZrTcEa8P76hVY+xyN7Wg=="; };' >ns1/legacy165.key + +( + cd ns3 + $SHELL -e sign.sh +) + +cp -f ns1/many.test.db.in ns1/many.test.db + +cp ns1/sample.db.in ns1/sample.db +cp ns2/sample.db.in ns2/sample.db + +cp -f ns1/maxjournal.db.in ns1/maxjournal.db + +cp -f ns5/local.db.in ns5/local.db +cp -f ns6/2.0.0.2.ip6.addr.db.in ns6/2.0.0.2.ip6.addr.db +cp -f ns6/in-addr.db.in ns6/in-addr.db +cp -f ns7/in-addr.db.in ns7/in-addr.db +cp -f ns7/example.com.db.in ns7/example.com.db +cp -f ns8/in-addr.db.in ns8/in-addr.db +cp -f ns8/example.com.db.in ns8/example.com.db +cp -f ns9/in-addr.db.in ns9/in-addr.db +cp -f ns9/example.com.db.in ns9/example.com.db +cp -f ns9/example.com.db.in ns9/denyname.example.db +cp -f ns10/in-addr.db.in ns10/in-addr.db +cp -f ns10/example.com.db.in ns10/example.com.db diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh new file mode 100755 index 0000000..2e6f8c8 --- /dev/null +++ b/bin/tests/system/nsupdate/tests.sh @@ -0,0 +1,3032 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +# +# Uncomment when creating credential cache files. +# +# KRB5_CONFIG="$(pwd)/krb/krb5.conf" +# +# Cd krb and run krb/setup.sh to create new keys. +# Run nsupdate system test. +# Kill the krb5kdc server started by krb/setup.sh. +# Check the expiry date on the cached machine.ccache with klist is in 2038. +# Comment out KRB5_CONFIG. +# Re-run nsupdate system test to confirm everything still works. +# git add and commit the resulting ns*/machine.ccache and ns*/dns.keytab files. +# Clean up krb. +# + +status=0 +n=0 + +nextpartreset ns3/named.run + +# wait for zone transfer to complete +tries=0 +while true; do + if [ $tries -eq 10 ]; then + exit 1 + fi + + if grep "example.nil/IN.*Transfer status" ns2/named.run >/dev/null; then + break + else + echo_i "zones are not fully loaded, waiting..." + tries=$((tries + 1)) + sleep 1 + fi +done + +has_positive_response() { + zone=$1 + type=$2 + ns=$3 + $DIG $DIGOPTS +tcp +norec $zone $type @$ns >dig.out.post.test$n || return 1 + grep "status: NOERROR" dig.out.post.test$n >/dev/null || return 1 + grep "ANSWER: 0," dig.out.post.test$n >/dev/null && return 1 + return 0 +} + +ret=0 +echo_i "fetching first copy of zone before update" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.1 axfr >dig.out.ns1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "fetching second copy of zone before update" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.2 axfr >dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "comparing pre-update copies to known good data" +digcomp knowngood.ns1.before dig.out.ns1 || ret=1 +digcomp knowngood.ns1.before dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "ensure an unrelated zone is mentioned in its NOTAUTH log" +$NSUPDATE -k ns1/ddns.key >nsupdate.out 2>&1 </dev/null 2>&1 || ret=1 +grep ' unconfigured.test: not authoritative' ns1/named.run \ + >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "ensure a subdomain is mentioned in its NOTAUTH log" +$NSUPDATE -k ns1/ddns.key >nsupdate.out 2>&1 </dev/null 2>&1 || ret=1 +grep ' sub.sub.example.nil: not authoritative' ns1/named.run \ + >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "updating zone" +# nsupdate will print a ">" prompt to stdout as it gets each input line. +$NSUPDATE -k ns1/ddns.key </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add updated.example.nil. 600 A 10.10.10.1 +add updated.example.nil. 600 TXT Foo +delete t.example.nil. + +END +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +echo_i "sleeping 5 seconds for server to incorporate changes" +sleep 5 + +ret=0 +echo_i "fetching first copy of zone after update" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.1 axfr >dig.out.ns1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "fetching second copy of zone after update" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.2 axfr >dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "comparing post-update copies to known good data" +digcomp knowngood.ns1.after dig.out.ns1 || ret=1 +digcomp knowngood.ns1.after dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "testing local update policy" +pre=$($DIG $DIGOPTS +short new.other.nil. @10.53.0.1 a) || ret=1 +[ -z "$pre" ] || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "updating zone" +# nsupdate will print a ">" prompt to stdout as it gets each input line. +$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >/dev/null <nsupdate.out 2>&1 </dev/null 2>&1 || ret=1 +# ...but should work if an A record is inserted first: +$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >nsupdate.out 2>&1 </dev/null 2>&1 && ret=1 +# ...or if an AAAA record does: +$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >nsupdate.out 2>&1 </dev/null 2>&1 && ret=1 +# ...or if the NS and A/AAAA are inserted together: +$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >nsupdate.out 2>&1 </dev/null 2>&1 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +echo_i "sleeping 5 seconds for server to incorporate changes" +sleep 5 + +ret=0 +echo_i "checking result of update" +$DIG $DIGOPTS +short @10.53.0.1 ns other.nil >dig.out.ns1 || ret=1 +grep ns3.other.nil dig.out.ns1 >/dev/null 2>&1 && ret=1 +grep ns4.other.nil dig.out.ns1 >/dev/null 2>&1 || ret=1 +grep ns5.other.nil dig.out.ns1 >/dev/null 2>&1 || ret=1 +grep ns6.other.nil dig.out.ns1 >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "ensure 'check-mx ignore' allows adding MX records containing an address without a warning" +$NSUPDATE -k ns1/ddns.key >nsupdate.out 2>&1 </dev/null 2>&1 && ret=1 +grep "mx03.example.nil/MX:.*MX is an address" ns1/named.run >/dev/null 2>&1 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "ensure 'check-mx warn' allows adding MX records containing an address with a warning" +$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >nsupdate.out 2>&1 </dev/null 2>&1 && ret=1 +grep "mx03.other.nil/MX:.*MX is an address" ns1/named.run >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "ensure 'check-mx fail' prevents adding MX records containing an address with a warning" +$NSUPDATE >nsupdate.out 2>&1 </dev/null 2>&1 || ret=1 +grep "mx03.update.nil/MX:.*MX is an address" ns1/named.run >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "check SIG(0) key is accepted" +key=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -T KEY -n ENTITY xxx) +echo "" | $NSUPDATE -k ${key}.private >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check TYPE=0 update is rejected by nsupdate ($n)" +$NSUPDATE <nsupdate.out 2>&1 && ret=1 + server 10.53.0.1 ${PORT} + ttl 300 + update add example.nil. in type0 "" + send +END +grep "unknown class/type" nsupdate.out >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check TYPE=0 prerequisite is handled ($n)" +$NSUPDATE -k ns1/ddns.key <nsupdate.out 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + prereq nxrrset example.nil. type0 + send +END +$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that TYPE=0 update is handled ($n)" +echo "a0e4280000010000000100000000060001c00c000000fe000000000000" \ + | $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1 +$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that TYPE=0 additional data is handled ($n)" +echo "a0e4280000010000000000010000060001c00c000000fe000000000000" \ + | $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1 +$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that update to undefined class is handled ($n)" +echo "a0e4280000010001000000000000060101c00c000000fe000000000000" \ + | $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp >/dev/null || ret=1 +$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 >dig.out.ns1.$n || ret=1 +grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that address family mismatch is handled ($n)" +$NSUPDATE </dev/null 2>&1 && ret=1 +server ::1 +local 127.0.0.1 +update add 600 txt.example.nil in txt "test" +send +END +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that unixtime serial number is correctly generated ($n)" +$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 >dig.out.old.test$n || ret=1 +oldserial=$(awk '{print $3}' dig.out.old.test$n) || ret=1 +start=$($PERL -e 'print time()."\n";') +$NSUPDATE </dev/null 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + ttl 600 + update add new.unixtime.nil in a 1.2.3.4 + send +END +now=$($PERL -e 'print time()."\n";') +sleep 1 +$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 >dig.out.new.test$n || ret=1 +serial=$(awk '{print $3}' dig.out.new.test$n) || ret=1 +[ "$oldserial" = "$serial" ] && { + echo_i "oldserial == serial" + ret=1 +} +if [ "$serial" -lt "$start" ]; then + echo_i "out-of-range serial=$serial < start=$start" + ret=1 +elif [ "$serial" -gt "$now" ]; then + echo_i "out-of-range serial=$serial > now=$now" + ret=1 +fi +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +if $PERL -e 'use Net::DNS;' 2>/dev/null; then + n=$((n + 1)) + ret=0 + echo_i "running update.pl test ($n)" + $PERL update_test.pl -s 10.53.0.1 -p ${PORT} update.nil. >perl.update_test.out || ret=1 + [ $ret -eq 1 ] && { + echo_i "failed" + status=1 + } + + if $PERL -e 'use Net::DNS; die "Net::DNS too old ($Net::DNS::VERSION < 1.01)" if ($Net::DNS::VERSION < 1.01)' >/dev/null; then + n=$((n + 1)) + ret=0 + echo_i "check for too many NSEC3 iterations log ($n)" + grep "updating zone 'update.nil/IN': too many NSEC3 iterations (51)" ns1/named.run >/dev/null || ret=1 + [ $ret -eq 1 ] && { + echo_i "failed" + status=1 + } + fi +else + echo_i "The second part of this test requires the Net::DNS library." >&2 +fi + +n=$((n + 1)) +ret=0 +echo_i "fetching first copy of test zone ($n)" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.1 axfr >dig.out.ns1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "fetching second copy of test zone ($n)" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.2 axfr >dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "comparing zones ($n)" +digcomp dig.out.ns1 dig.out.ns2 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +echo_i "SIGKILL and restart server ns1" +cd ns1 +kill -KILL $(cat named.pid) +rm named.pid +cd .. +sleep 10 +if + start_server --noclean --restart --port ${PORT} ns1 +then + echo_i "restarted server ns1" +else + echo_i "could not restart server ns1" + exit 1 +fi +sleep 10 + +n=$((n + 1)) +ret=0 +echo_i "fetching ns1 after hard restart ($n)" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil. @10.53.0.1 axfr >dig.out.ns1.after || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "comparing zones ($n)" +digcomp dig.out.ns1 dig.out.ns1.after || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +echo_i "begin RT #482 regression test" + +n=$((n + 1)) +ret=0 +echo_i "update primary ($n)" +$NSUPDATE -k ns1/ddns.key </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add updated2.example.nil. 600 A 10.10.10.2 +update add updated2.example.nil. 600 TXT Bar +update delete c.example.nil. +send +END +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +sleep 5 + +echo_i "SIGHUP secondary" +kill -HUP $(cat ns2/named.pid) + +sleep 5 + +n=$((n + 1)) +ret=0 +echo_i "update primary again ($n)" +$NSUPDATE -k ns1/ddns.key </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add updated3.example.nil. 600 A 10.10.10.3 +update add updated3.example.nil. 600 TXT Zap +del d.example.nil. +send +END +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +sleep 5 + +echo_i "SIGHUP secondary again" +kill -HUP $(cat ns2/named.pid) + +sleep 5 + +n=$((n + 1)) +echo_i "check to 'out of sync' message ($n)" +if grep "out of sync" ns2/named.run >/dev/null; then + echo_i "failed (found 'out of sync')" + status=1 +fi + +echo_i "end RT #482 regression test" + +n=$((n + 1)) +ret=0 +echo_i "remove nonexistent PTR record ($n)" +$NSUPDATE -k ns1/ddns.key -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.1 ${PORT} +zone example.nil. +update delete nonexistent.example.nil. 0 IN PTR foo. +send +EOF +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "remove nonexistent SRV record ($n)" +$NSUPDATE -k ns1/ddns.key -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.1 ${PORT} +zone example.nil. +update delete nonexistent.example.nil. 0 IN SRV 0 0 0 foo. +send +EOF +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +i=0 +echo_i "check that nsupdate does not hang when processing a large number of updates interactively ($n)" +{ + echo "server 10.53.0.3 ${PORT}" + echo "zone many-updates.test." + while [ $i -le 2000 ]; do + echo "update add host$i.many-updates.test. 3600 IN TXT \"host $i\"" + i=$((i + 1)) + done + echo "send" +} | $NSUPDATE +echo_i "query for host2000.many-updates.test ($n)" +retry_quiet 5 has_positive_response host2000.many-updates.test TXT 10.53.0.3 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "start NSEC3PARAM changes via UPDATE on a unsigned zone test ($n)" +$NSUPDATE <dig.out.ns3.$n || ret=1 +grep "ANSWER: 0," dig.out.ns3.$n >/dev/null || ret=1 +grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "change the NSEC3PARAM ttl via update ($n)" +$NSUPDATE <dig.out.ns3.$n || ret=1 +grep "ANSWER: 1," dig.out.ns3.$n >/dev/null || ret=1 +grep "3600.*NSEC3PARAM" dig.out.ns3.$n >/dev/null || ret=1 +grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "testing that rndc stop updates the file" +$NSUPDATE -k ns1/ddns.key </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add updated4.example.nil. 600 A 10.10.10.3 +send +END +sleep 3 +stop_server --use-rndc --port ${CONTROLPORT} ns1 +sleep 3 +# Removing the journal file and restarting the server means +# that the data served by the new server process are exactly +# those dumped to the file by "rndc stop". +rm -f ns1/*jnl +start_server --noclean --restart --port ${PORT} ns1 +for try in 0 1 2 3 4 5 6 7 8 9; do + iret=0 + $DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + updated4.example.nil. @10.53.0.1 a >dig.out.ns1 || iret=1 + digcomp knowngood.ns1.afterstop dig.out.ns1 || iret=1 + [ "$iret" -eq 0 ] && break + sleep 1 +done +[ "$iret" -ne 0 ] && ret=1 +[ "$ret" -eq 0 ] || { + echo_i "failed" + status=1 +} + +ret=0 +echo_i "check that 'nsupdate -l' with a missing keyfile reports the missing file" +$NSUPDATE -4 -p ${PORT} -l -k ns1/nonexistent.key 2>nsupdate.out /dev/null || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy local' works from localhost address ($n)" +$NSUPDATE -k ns5/session.key >nsupdate.out.$n 2>&1 </dev/null 2>&1 && ret=1 +$DIG $DIGOPTS @10.53.0.5 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + fromlocal.local.nil. >dig.out.ns5.$n || ret=1 +grep fromlocal dig.out.ns5.$n >/dev/null 2>&1 || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy local' fails from non-localhost address ($n)" +grep 'match on session key not from localhost' ns5/named.run >/dev/null && ret=1 +$NSUPDATE -k ns5/session.key >nsupdate.out.$n 2>&1 </dev/null 2>&1 || ret=1 +grep 'match on session key not from localhost' ns5/named.run >/dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.5 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + nonlocal.local.nil. >dig.out.ns5.$n || ret=1 +grep nonlocal dig.out.ns5.$n >/dev/null 2>&1 && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy tcp-self' refuses update of records via UDP ($n)" +$NSUPDATE >nsupdate.out.$n 2>&1 </dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + -x 127.0.0.1 >dig.out.ns6.$n +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy tcp-self' permits update of records for the client's own address via TCP ($n)" +$NSUPDATE -v >nsupdate.out.$n 2>&1 </dev/null 2>&1 && ret=1 +$DIG $DIGOPTS @10.53.0.6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + -x 127.0.0.1 >dig.out.ns6.$n || ret=1 +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy tcp-self' refuses update of records for a different address from the client's own address via TCP ($n)" +$NSUPDATE -v >nsupdate.out.$n 2>&1 </dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + -x 192.168.0.1 >dig.out.ns6.$n +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy 6to4-self' refuses update of records via UDP over IPv4 ($n)" +REVERSE_NAME=6.0.0.0.5.3.a.0.2.0.0.2.ip6.arpa +$NSUPDATE >nsupdate.out.$n 2>&1 </dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + $REVERSE_NAME NS >dig.out.ns6.$n +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "check that 'update-policy 6to4-self' permits update of records for the client's own address via TCP over IPv4 ($n)" +ret=0 +REVERSE_NAME=6.0.0.0.5.3.a.0.2.0.0.2.ip6.arpa +$NSUPDATE -v >nsupdate.out.$n 2>&1 </dev/null 2>&1 && ret=1 +$DIG $DIGOPTS @10.53.0.6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + $REVERSE_NAME NS >dig.out.ns6.$n || ret=1 +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy 6to4-self' refuses update of records via UDP over IPv6 ($n)" +REVERSE_NAME=7.0.0.0.5.3.a.0.2.0.0.2.ip6.arpa +$NSUPDATE >nsupdate.out.$n 2>&1 </dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @fd92:7065:b8e:ffff::6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + $REVERSE_NAME NS >dig.out.ns6.$n +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "check that 'update-policy 6to4-self' permits update of records for the client's own address via TCP over IPv6 ($n)" +ret=0 +REVERSE_NAME=7.0.0.0.5.3.a.0.2.0.0.2.ip6.arpa +$NSUPDATE -v >nsupdate.out.$n 2>&1 </dev/null 2>&1 && ret=1 +$DIG $DIGOPTS @fd92:7065:b8e:ffff::6 \ + +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \ + $REVERSE_NAME NS >dig.out.ns6.$n || ret=1 +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy subdomain' is properly enforced ($n)" +# "restricted.example.nil" matches "grant ... subdomain restricted.example.nil" +# and thus this UPDATE should succeed. +$NSUPDATE -d <nsupdate.out1-$n 2>&1 || ret=1 +server 10.53.0.1 ${PORT} +key $DEFAULT_HMAC:restricted.example.nil 1234abcd8765 +update add restricted.example.nil 0 IN TXT everywhere. +send +END +$DIG $DIGOPTS +tcp @10.53.0.1 restricted.example.nil TXT >dig.out.1.test$n || ret=1 +grep "TXT.*everywhere" dig.out.1.test$n >/dev/null || ret=1 +# "example.nil" does not match "grant ... subdomain restricted.example.nil" and +# thus this UPDATE should fail. +$NSUPDATE -d <nsupdate.out2-$n 2>&1 && ret=1 +server 10.53.0.1 ${PORT} +key $DEFAULT_HMAC:restricted.example.nil 1234abcd8765 +update add example.nil 0 IN TXT everywhere. +send +END +$DIG $DIGOPTS +tcp @10.53.0.1 example.nil TXT >dig.out.2.test$n || ret=1 +grep "TXT.*everywhere" dig.out.2.test$n >/dev/null && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that 'update-policy zonesub' is properly enforced ($n)" +# grant zonesub-key.example.nil zonesub TXT; +# the A record update should be rejected as it is not in the type list +$NSUPDATE -d <nsupdate.out1-$n 2>&1 && ret=1 +server 10.53.0.1 ${PORT} +key $DEFAULT_HMAC:zonesub-key.example.nil 1234subk8765 +update add zonesub.example.nil 0 IN A 1.2.3.4 +send +END +$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil A >dig.out.1.test$n || ret=1 +grep "status: REFUSED" nsupdate.out1-$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.1.test$n >/dev/null || ret=1 +# the TXT record update should be accepted as it is in the type list +$NSUPDATE -d <nsupdate.out2-$n 2>&1 || ret=1 +server 10.53.0.1 ${PORT} +key $DEFAULT_HMAC:zonesub-key.example.nil 1234subk8765 +update add zonesub.example.nil 0 IN TXT everywhere. +send +END +$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil TXT >dig.out.2.test$n || ret=1 +grep "status: REFUSED" nsupdate.out2-$n >/dev/null && ret=1 +grep "ANSWER: 1," dig.out.2.test$n >/dev/null || ret=1 +grep "TXT.*everywhere" dig.out.2.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check 'grant' in deny name + grant subdomain ($n)" +$NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 +key $DEFAULT_HMAC:subkey 1234abcd8765 +server 10.53.0.9 ${PORT} +zone denyname.example +update add foo.denyname.example 3600 IN TXT added +send +EOF +$DIG $DIGOPTS +tcp @10.53.0.9 foo.denyname.example TXT >dig.out.ns9.test$n || ret=1 +grep "added" dig.out.ns9.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check 'deny' in deny name + grant subdomain ($n)" +$NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 +key $DEFAULT_HMAC:subkey 1234abcd8765 +server 10.53.0.9 ${PORT} +zone denyname.example +update add denyname.example 3600 IN TXT added +send +EOF +$DIG $DIGOPTS +tcp @10.53.0.9 denyname.example TXT >dig.out.ns9.test$n || ret=1 +grep "added" dig.out.ns9.test$n >/dev/null && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that changes to the DNSKEY RRset TTL do not have side effects ($n)" +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \ + @10.53.0.3 dnskey \ + | awk -v port="${PORT}" 'BEGIN { print "server 10.53.0.3", port; } + $2 == 10 && $3 == "IN" && $4 == "DNSKEY" { $2 = 600; print "update add", $0 } + END { print "send" }' >update.in.$n || ret=1 +$NSUPDATE update.in.$n + +$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \ + @10.53.0.3 any >dig.out.ns3.$n || ret=1 + +grep "600.*DNSKEY" dig.out.ns3.$n >/dev/null || ret=1 +grep TYPE65534 dig.out.ns3.$n >/dev/null && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check notify with TSIG worked ($n)" +# if the alternate view received a notify--meaning, the notify was +# validly signed by "altkey"--then the zonefile update.alt.bk will +# will have been created. +[ -f ns2/update.alt.bk ] || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check type list options ($n)" +$NSUPDATE -T >typelist.out.T.${n} || { + ret=1 + echo_i "nsupdate -T failed" +} +$NSUPDATE -P >typelist.out.P.${n} || { + ret=1 + echo_i "nsupdate -P failed" +} +$NSUPDATE -TP >typelist.out.TP.${n} || { + ret=1 + echo_i "nsupdate -TP failed" +} +grep ANY typelist.out.T.${n} >/dev/null && { + ret=1 + echo_i "failed: ANY found (-T)" +} +grep ANY typelist.out.P.${n} >/dev/null && { + ret=1 + echo_i "failed: ANY found (-P)" +} +grep ANY typelist.out.TP.${n} >/dev/null && { + ret=1 + echo_i "failed: ANY found (-TP)" +} +grep KEYDATA typelist.out.T.${n} >/dev/null && { + ret=1 + echo_i "failed: KEYDATA found (-T)" +} +grep KEYDATA typelist.out.P.${n} >/dev/null && { + ret=1 + echo_i "failed: KEYDATA found (-P)" +} +grep KEYDATA typelist.out.TP.${n} >/dev/null && { + ret=1 + echo_i "failed: KEYDATA found (-TP)" +} +grep AAAA typelist.out.T.${n} >/dev/null || { + ret=1 + echo_i "failed: AAAA not found (-T)" +} +grep AAAA typelist.out.P.${n} >/dev/null && { + ret=1 + echo_i "failed: AAAA found (-P)" +} +grep AAAA typelist.out.TP.${n} >/dev/null || { + ret=1 + echo_i "failed: AAAA not found (-TP)" +} +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check command list ($n)" +( + while read cmd; do + { + echo "$cmd" | $NSUPDATE >/dev/null 2>&1 + rc=$? + } || true + if test $rc -gt 1; then + echo_i "failed ($cmd)" + ret=1 + fi + { + echo "$cmd " | $NSUPDATE >/dev/null 2>&1 + rc=$? + } || true + if test $rc -gt 1; then + echo_i "failed ($cmd)" + ret=1 + fi + done + exit $ret +) nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${TLSPORT} + update add dot-non-auth-client-o.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-non-auth-client-o.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 || ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (strict-tls) with an implicit hostname (by IP address) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${EXTRAPORT1} + update add dot-non-auth-client.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-non-auth-client.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 || ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (strict-tls) with an implicit hostname (by IP address) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${EXTRAPORT1} + update add dot-fs.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fs.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 || ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (strict-tls) with a correct hostname ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -H srv01.crt01.example.nil -k ns1/ddns.key <nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${EXTRAPORT1} + update add dot-fs-h.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fs-h.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 || ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (strict-tls) with an incorrect hostname (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -H srv01.crt01.example.bad -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT1} + update add dot-fs-h-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fs-h-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (strict-tls) with a wrong authority (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA-other.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT1} + update add dot-fs-auth-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fs-auth-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (mutual-tls) with a valid client certificate ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -K CA/certs/srv01.client01.example.nil.key -E CA/certs/srv01.client01.example.nil.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 || ret=1 + server 10.53.0.1 ${EXTRAPORT2} + update add dot-fsmt.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fsmt.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 || ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (mutual-tls) with a valid client certificate but with an incorrect hostname (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -K CA/certs/srv01.client01.example.nil.key -E CA/certs/srv01.client01.example.nil.pem -H srv01.crt01.example.bad -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT2} + update add dot-fsmt-h-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fsmt-h-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (mutual-tls) with a valid client certificate but with a wrong authority (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA-other.pem -K CA/certs/srv01.client01.example.nil.key -E CA/certs/client01.crt01.example.nil.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT2} + update add dot-fsmt-auth-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fsmt-auth-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (mutual-tls) with an expired client certificate (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -K CA/certs/srv01.client02-expired.example.nil.key -E CA/certs/srv01.client02-expired.example.nil.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT2} + update add dot-fsmt-exp-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fsmt-exp-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check DoT (mutual-tls) with a valid client certificate and an expired server certificate (failure expected) ($n)" +if $FEATURETEST --have-fips-dh; then + $NSUPDATE -D -S -A CA/CA.pem -K CA/certs/srv01.client01.example.nil.key -E CA/certs/srv01.client01.example.nil.pem -k ns1/ddns.key <nsupdate.out.test$n 2>&1 && ret=1 + server 10.53.0.1 ${EXTRAPORT3} + update add dot-fsmt-exp-bad.example.nil. 600 A 10.10.10.3 + send +END + sleep 2 + $DIG $DIGOPTS +short @10.53.0.1 dot-fsmt-exp-bad.example.nil >dig.out.test$n 2>&1 || ret=1 + grep -F "10.10.10.3" dig.out.test$n >/dev/null 2>&1 && ret=1 + if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 + fi +else + echo_i "skipped: DH not supported in FIPS mode" +fi + +n=$((n + 1)) +ret=0 +echo_i "check TSIG key algorithms using legacy K file pairs (nsupdate -k) ($n)" +if $FEATURETEST --md5; then + ALGS="157 161 162 163 164 165" +else + ALGS="161 162 163 164 165" + echo_i "skipping disabled md5 (157) algorithm" +fi +for alg in $ALGS; do + $NSUPDATE -k ns1/legacy/Klegacy-${alg}.+${alg}+*.key <nsupdate.alg-$alg.out 2>&1 || ret=1 +server 10.53.0.1 ${PORT} +update add ${alg}.keytests.nil. 600 A 10.10.10.3 +send +END +done +sleep 2 +for alg in $ALGS; do + $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 >/dev/null 2>&1 || ret=1 + grep "Use of K\* file pairs for HMAC is deprecated" nsupdate.alg-$alg.out >/dev/null || ret=1 +done +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check TSIG key algorithms (nsupdate -k) ($n)" +if $FEATURETEST --md5; then + ALGS="md5 sha1 sha224 sha256 sha384 sha512" +else + ALGS="sha1 sha224 sha256 sha384 sha512" + echo_i "skipping disabled md5 algorithm" +fi +for alg in $ALGS; do + $NSUPDATE -k ns1/${alg}.key </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add ${alg}.keytests.nil. 600 A 10.10.10.3 +send +END +done +sleep 2 +for alg in $ALGS; do + $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 >/dev/null 2>&1 || ret=1 +done +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check TSIG key algorithms (nsupdate -y) ($n)" +for alg in $ALGS; do + secret=$(sed -n 's/.*secret "\(.*\)";.*/\1/p' ns1/${alg}.key) + $NSUPDATE -y "hmac-${alg}:${alg}-key:$secret" </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add ${alg}.keytests.nil. 600 A 10.10.10.50 +send +END +done +sleep 2 +for alg in $ALGS; do + $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.50 >/dev/null 2>&1 || ret=1 +done +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that ttl is capped by max-ttl ($n)" +$NSUPDATE </dev/null || ret=1 +server 10.53.0.1 ${PORT} +update add cap.max-ttl.nil. 600 A 10.10.10.3 +update add nocap.max-ttl.nil. 150 A 10.10.10.3 +send +END +sleep 2 +$DIG $DIGOPTS @10.53.0.1 cap.max-ttl.nil | grep "^cap.max-ttl.nil. 300" >/dev/null 2>&1 || ret=1 +$DIG $DIGOPTS @10.53.0.1 nocap.max-ttl.nil | grep "^nocap.max-ttl.nil. 150" >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "check adding more records than max-records-per-type fails ($n)" +ret=0 +$NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.1 ${PORT} +zone max-ttl.nil. +update add a.max-ttl.nil. 60 IN A 192.0.2.1 +update add a.max-ttl.nil. 60 IN A 192.0.2.2 +update add a.max-ttl.nil. 60 IN A 192.0.2.3 +update add a.max-ttl.nil. 60 IN A 192.0.2.4 +send +END +grep "update failed: SERVFAIL" nsupdate.out.test$n >/dev/null || ret=1 +msg="error updating 'a.max-ttl.nil/A' in 'max-ttl.nil/IN' (zone): too many records (must not exceed 3)" +wait_for_log 10 "$msg" ns1/named.run || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} +nextpart ns1/named.run >/dev/null + +n=$((n + 1)) +ret=0 +echo_i "add a record which is truncated when logged. ($n)" +$NSUPDATE verylarge || ret=1 +$DIG $DIGOPTS +tcp @10.53.0.1 txt txt.update.nil >dig.out.ns1.test$n || ret=1 +grep "ANSWER: 1," dig.out.ns1.test$n >/dev/null || ret=1 +grep "adding an RR at 'txt.update.nil' TXT .* \[TRUNCATED\]" ns1/named.run >/dev/null || ret=1 +if [ $ret -ne 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that yyyymmddvv serial number is correctly generated ($n)" +oldserial=$($DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}') || ret=1 +$NSUPDATE </dev/null 2>&1 || ret=1 + server 10.53.0.1 ${PORT} + ttl 600 + update add new.yyyymmddvv.nil in a 1.2.3.4 + send +END +now=$($PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];') +sleep 1 +serial=$($DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}') || ret=1 +[ "$oldserial" -ne "$serial" ] || ret=1 +[ "$serial" -eq "$now" ] || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +# +# Refactor to use perl to launch the parallel updates. +# +if false; then + n=$((n + 1)) + echo_i "send many simultaneous updates via a update forwarder ($n)" + ret=0 + for i in 0 1 2 3 4 5 6 7; do + ( + for j in 0 1 2 3 4 5 6 7; do + ( + $NSUPDATE <dig.out.test$n + lines=$(awk '$4 == "A" { l++ } END { print l }' dig.out.test$n) + test ${lines:-0} -eq 64 || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } +fi + +n=$((n + 1)) +echo_i "check max-journal-size limits ($n)" +ret=0 +rm -f nsupdate.out1-$n +# add one record +$NSUPDATE <>nsupdate.out1-$n 2>&1 +server 10.53.0.1 ${PORT} +zone maxjournal.test +update add z.maxjournal.test 300 IN A 10.20.30.40 +send +EOF +for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + # repeatedly add and remove the same set of records to fill up + # the journal file without changing the zone content + $NSUPDATE <>nsupdate.out1-$n 2>&1 +server 10.53.0.1 ${PORT} +zone maxjournal.test +update add a.maxjournal.test 300 IN A 1.2.3.4 +update add b.maxjournal.test 300 IN A 1.2.3.4 +update add c.maxjournal.test 300 IN A 1.2.3.4 +update add d.maxjournal.test 300 IN A 1.2.3.4 +send +update del a.maxjournal.test +update del b.maxjournal.test +update del c.maxjournal.test +update del d.maxjournal.test +send +EOF +done +# check that the journal is big enough to require truncation. +size=$($PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl) +[ "$size" -gt 6000 ] || ret=1 +sleep 1 +$RNDCCMD 10.53.0.1 sync maxjournal.test +check_size_lt_5000() ( + size=$($PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl) + [ "$size" -lt 5000 ] +) +retry_quiet 20 check_size_lt_5000 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +echo_i "check check-names processing ($n)" +ret=0 +$NSUPDATE <nsupdate.out1-$n 2>&1 && ret=1 +update add # 0 in a 1.2.3.4 +EOF +grep "bad owner" nsupdate.out1-$n >/dev/null || ret=1 + +$NSUPDATE <nsupdate.out2-$n 2>&1 || ret=1 +check-names off +update add # 0 in a 1.2.3.4 +EOF +grep "bad owner" nsupdate.out2-$n >/dev/null && ret=1 + +$NSUPDATE <nsupdate.out3-$n 2>&1 && ret=1 +update add . 0 in mx 0 # +EOF +grep "bad name" nsupdate.out3-$n >/dev/null || ret=1 + +$NSUPDATE <nsupdate.out4-$n 2>&1 || ret=1 +check-names off +update add . 0 in mx 0 # +EOF +grep "bad name" nsupdate.out4-$n >/dev/null && ret=1 + +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +echo_i "check check-svcb processing ($n)" +ret=0 +$NSUPDATE <nsupdate.out1-$n 2>&1 && ret=1 +update add _dns.ns.example 0 in svcb 1 ns.example dohpath=/{?dns} +EOF +grep "check-svcb failed: no ALPN" nsupdate.out1-$n >/dev/null || ret=1 + +$NSUPDATE <nsupdate.out2-$n 2>&1 || ret=1 +check-svcb off +update add _dns.ns.example 0 in svcb 1 ns.example dohpath=/{?dns} +EOF +grep "check-svcb failed: no ALPN" nsupdate.out2-$n >/dev/null && ret=1 + +$NSUPDATE <nsupdate.out3-$n 2>&1 && ret=1 +update add _dns.ns.example 0 in svcb 1 ns.example alpn=h2 +EOF +grep "check-svcb failed: no DOHPATH" nsupdate.out3-$n >/dev/null || ret=1 + +$NSUPDATE <nsupdate.out4-$n 2>&1 || ret=1 +check-svcb off +update add _dns.ns.example 0 in svcb 1 ns.example alpn=h2 +EOF +grep "check-svcb failed: no DOHPATH" nsupdate.out4-$n >/dev/null && ret=1 + +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +echo_i "check adding of delegating NS records processing ($n)" +ret=0 +$NSUPDATE -v <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone delegation.test. +update add child.delegation.test. 3600 NS foo.example.net. +update add child.delegation.test. 3600 NS bar.example.net. +send +EOF +$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +grep "AUTHORITY: 2" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +echo_i "check deleting of delegating NS records processing ($n)" +ret=0 +$NSUPDATE -v <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone delegation.test. +update del child.delegation.test. 3600 NS foo.example.net. +update del child.delegation.test. 3600 NS bar.example.net. +send +EOF +$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +echo_i "check that adding too many records is blocked ($n)" +ret=0 +$NSUPDATE -v <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone too-big.test. +update add r1.too-big.test 3600 IN TXT r1.too-big.test +send +EOF +grep "update failed: SERVFAIL" nsupdate.out.test$n >/dev/null || ret=1 +$DIG $DIGOPTS +tcp @10.53.0.3 r1.too-big.test TXT >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +grep "records in zone (4) exceeds max-records (3)" ns3/named.run >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check whether valid addresses are used for primary failover (UDP with defaults) ($n)" +t1=$($PERL -e 'print time()') +$NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.4 ${PORT} +zone unreachable. +update add unreachable. 600 A 192.0.2.1 +send +END +t2=$($PERL -e 'print time()') +grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "not implemented" nsupdate.out.test$n >/dev/null 2>&1 && ret=1 +elapsed=$((t2 - t1)) +# Check that default timeout value is respected, there should be 4 tries with 3 seconds each. +test $elapsed -lt 12 && ret=1 +test $elapsed -gt 15 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check whether valid addresses are used for primary failover (UDP with -u udptimeout) ($n)" +t1=$($PERL -e 'print time()') +$NSUPDATE -u 4 -r 1 <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.4 ${PORT} +zone unreachable. +update add unreachable. 600 A 192.0.2.1 +send +END +t2=$($PERL -e 'print time()') +grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "not implemented" nsupdate.out.test$n >/dev/null 2>&1 && ret=1 +elapsed=$((t2 - t1)) +# Check that given timeout value is respected, there should be 2 tries with 4 seconds each. +test $elapsed -lt 8 && ret=1 +test $elapsed -gt 12 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check whether valid addresses are used for primary failover (UDP with -t timeout) ($n)" +t1=$($PERL -e 'print time()') +$NSUPDATE -u 0 -t 8 -r 1 <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.4 ${PORT} +zone unreachable. +update add unreachable. 600 A 192.0.2.1 +send +END +t2=$($PERL -e 'print time()') +grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "not implemented" nsupdate.out.test$n >/dev/null 2>&1 && ret=1 +elapsed=$((t2 - t1)) +# Check that given timeout value is respected, there should be 2 tries with 4 seconds each. +test $elapsed -lt 8 && ret=1 +test $elapsed -gt 12 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check whether valid addresses are used for primary failover (UDP with -u udptimeout -t timeout) ($n)" +t1=$($PERL -e 'print time()') +$NSUPDATE -u 4 -t 30 -r 1 <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.4 ${PORT} +zone unreachable. +update add unreachable. 600 A 192.0.2.1 +send +END +t2=$($PERL -e 'print time()') +grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "not implemented" nsupdate.out.test$n >/dev/null 2>&1 && ret=1 +elapsed=$((t2 - t1)) +# Check that given timeout value is respected, there should be 2 tries with 4 seconds each, as -u takes precedence over -t. +test $elapsed -lt 8 && ret=1 +test $elapsed -gt 12 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check whether valid addresses are used for primary failover (TCP with -t timeout) ($n)" +t1=$($PERL -e 'print time()') +$NSUPDATE -t 8 -v <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.4 ${PORT} +zone unreachable. +update add unreachable. 600 A 192.0.2.1 +send +END +t2=$($PERL -e 'print time()') +grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "not implemented" nsupdate.out.test$n >/dev/null 2>&1 && ret=1 +elapsed=$((t2 - t1)) +# Check that given timeout value is respected, there should be 1 try with 8 seconds. +test $elapsed -lt 8 && ret=1 +test $elapsed -gt 12 && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure bad owner name is fatal in non-interactive mode ($n)" +$NSUPDATE <nsupdate.out 2>&1 && ret=1 + update add emptylabel..nil. 600 A 10.10.10.1 +END +grep "invalid owner name: empty label" nsupdate.out >/dev/null || ret=1 +grep "syntax error" nsupdate.out >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure bad owner name is not fatal in interactive mode ($n)" +$NSUPDATE -i <nsupdate.out 2>&1 || ret=1 + update add emptylabel..nil. 600 A 10.10.10.1 +END +grep "invalid owner name: empty label" nsupdate.out >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure invalid key type is fatal in non-interactive mode ($n)" +$NSUPDATE <nsupdate.out 2>&1 && ret=1 + key badkeytype:example abcd12345678 +END +grep "unknown key type 'badkeytype'" nsupdate.out >/dev/null || ret=1 +grep "syntax error" nsupdate.out >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure invalid key type is not fatal in interactive mode ($n)" +$NSUPDATE -i <nsupdate.out 2>&1 || ret=1 + key badkeytype:example abcd12345678 +END +grep "unknown key type 'badkeytype'" nsupdate.out >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure unresolvable server name is fatal in non-interactive mode ($n)" +$NSUPDATE <nsupdate.out 2>&1 && ret=1 + server unresolvable.. +END +grep "couldn't get address for 'unresolvable..':" nsupdate.out >/dev/null || ret=1 +grep "syntax error" nsupdate.out >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "ensure unresolvable server name is not fatal in interactive mode ($n)" +$NSUPDATE -i <nsupdate.out 2>&1 || ret=1 + server unresolvable.. +END +grep "couldn't get address for 'unresolvable..':" nsupdate.out >/dev/null || ret=1 +grep "syntax error" nsupdate.out >/dev/null && ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check nsupdate -4 -6 ($n)" +$NSUPDATE -4 -6 <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone delegation.test. +update del child.delegation.test. 3600 NS foo.example.net. +update del child.delegation.test. 3600 NS bar.example.net. +send +END +grep "only one of -4 and -6 allowed" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check nsupdate -4 with an IPv6 server address ($n)" +$NSUPDATE -4 <nsupdate.out.test$n 2>&1 && ret=1 +server fd92:7065:b8e:ffff::2 ${PORT} +zone delegation.test. +update del child.delegation.test. 3600 NS foo.example.net. +update del child.delegation.test. 3600 NS bar.example.net. +send +END +grep "address family not supported" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that TKEY in a update is rejected ($n)" +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +update add tkey.example 0 in tkey invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw== +send +END +grep "UPDATE, status: NOERROR" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +grep "UPDATE, status: FORMERR" nsupdate.out.test$n >/dev/null 2>&1 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that max records is enforced ($n)" +nextpart ns6/named.run >/dev/null +$NSUPDATE -v >nsupdate.out.$n 2>&1 <dig.out.ns6.$n || ret=1 +# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so only the +# first PTR record should be added. +grep localhost. dig.out.ns6.$n >/dev/null 2>&1 || ret=1 +grep other. dig.out.ns6.$n >/dev/null 2>&1 && ret=1 +nextpart ns6/named.run >nextpart.out.$n +grep "attempt to add more records than permitted by policy" nextpart.out.$n >/dev/null || ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that max records for ANY is enforced ($n)" +nextpart ns6/named.run >/dev/null +$NSUPDATE -v >nsupdate.out.$n 2>&1 <dig.out.ns6.test$n || ret=1 +nextpart ns6/named.run >nextpart.out.test$n +grep "attempt to add more records than permitted by policy" nextpart.out.test$n >/dev/null || ret=1 +# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so all the A +# records should have been added as there is no limit and the first 2 +# of the AAAA records added as they match ANY(2). +c1=$(awk '$4 == "A" { print }' dig.out.ns6.test$n | wc -l) +c2=$(awk '$4 == "AAAA" { print }' dig.out.ns6.test$n | wc -l) +test "$c1" -eq 3 -a "$c2" -eq 2 || ret=1 +grep "::ffff:1.2.3.2" dig.out.ns6.test$n >/dev/null && ret=1 +if test $ret -ne 0; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +ret=0 +echo_i "check that DS to the zone apex is ignored ($n)" +$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.pre.test$n >/dev/null || ret=1 +nextpart ns3/named.run >/dev/null +# specify zone to override the default of adding to parent zone +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone example +update add example 0 in DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C +send +END +msg=": attempt to add a DS record at zone apex ignored" +nextpart ns3/named.run | grep "$msg" >/dev/null || ret=1 +$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 >dig.out.post.test$n || ret=1 +grep "status: NOERROR" dig.out.post.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.post.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that CDS with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)" +$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.pre.test$n >/dev/null || ret=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone multisigner.test +update add multisigner.test 3600 IN CDS 14364 14 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C +send +END +msg=": bad CDS RRset" +nextpart ns3/named.run | grep "$msg" >/dev/null || ret=1 +$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 >dig.out.post.test$n || ret=1 +grep "status: NOERROR" dig.out.post.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.post.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that CDNSKEY with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)" +$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.pre.test$n >/dev/null || ret=1 +nextpart ns3/named.run >/dev/null +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone multisigner.test +update add multisigner.test 3600 IN CDNSKEY 257 3 14 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ== +send +END +msg=": bad CDNSKEY RRset" +nextpart ns3/named.run | grep "$msg" >/dev/null || ret=1 +$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 >dig.out.post.test$n || ret=1 +grep "status: NOERROR" dig.out.post.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.post.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that CDS to DNSSEC multisigner zone is allowed ($n)" +$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.pre.test$n >/dev/null || ret=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone multisigner.test +update add multisigner.test 3600 IN CDS 14364 13 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C +send +END +retry_quiet 5 has_positive_response multisigner.test CDS 10.53.0.3 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that CDNSKEY to DNSSEC multisigner zone is allowed ($n)" +$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.pre.test$n >/dev/null || ret=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone multisigner.test +update add multisigner.test 3600 IN CDNSKEY 257 3 13 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ== +send +END +retry_quiet 5 has_positive_response multisigner.test CDNSKEY 10.53.0.3 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)" +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone example +update add example 0 in NSEC3PARAM 1 0 51 - +END +grep "NSEC3PARAM has excessive iterations (> 50)" nsupdate.out.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check nsupdate retries with another server on REFUSED response ($n)" +# resolv.conf uses 10.53.0.1 followed by 10.53.0.3; example is only +# served by 10.53.0.3, so we should fail over to the second server; +# that's what we're testing for. (failure is still expected, however, +# because the address lookup for the primary doesn't use the overridden +# resolv.conf file). +$NSUPDATE -D -C resolv.conf -p ${PORT} <nsupdate.out.test$n 2>&1 && ret=1 +zone example +update add a 3600 IN A 1.2.3.4 +send +EOF +grep '10.53.0.1.*REFUSED' nsupdate.out.test$n >/dev/null || ret=1 +grep 'Reply from SOA query' nsupdate.out.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that named rejects '_dns' SVCB with missing ALPN ($n)" +nextpart ns3/named.run >/dev/null +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone example +check-svcb no +update add _dns.ns.example 0 in SVCB 1 ns.example dohpath=/{?dns} +send +END +grep 'status: REFUSED' nsupdate.out.test$n >/dev/null || ret=1 +msg="update failed: _dns.ns.example/SVCB: no ALPN (REFUSED)" +nextpart ns3/named.run | grep "$msg" >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that named accepts '_dns' SVCB with missing ALPN (check-svcb no) ($n)" +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone relaxed +check-svcb no +update add _dns.ns.relaxed 0 in SVCB 1 ns.relaxed dohpath=/{?dns} +send +END +$DIG $DIGOPTS +tcp @10.53.0.3 _dns.ns.relaxed SVCB >dig.out.ns3.test$n || ret=1 +grep '1 ns.relaxed. key7="/{?dns}"' dig.out.ns3.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that named rejects '_dns' SVCB with missing DOHPATH ($n)" +nextpart ns3/named.run >/dev/null +$NSUPDATE -d <nsupdate.out.test$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone example +check-svcb no +update add _dns.ns.example 0 in SVCB 1 ns.example alpn=h2 +send +END +grep 'status: REFUSED' nsupdate.out.test$n >/dev/null || ret=1 +msg="update failed: _dns.ns.example/SVCB: no DOHPATH (REFUSED)" +nextpart ns3/named.run | grep "$msg" >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that named accepts '_dns' SVCB with missing DOHPATH (check-svcb no) ($n)" +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone relaxed +check-svcb no +update add _dns.ns.relaxed 0 in SVCB 1 ns.relaxed alpn=h2 +send +END +$DIG $DIGOPTS +tcp @10.53.0.3 _dns.ns.relaxed SVCB >dig.out.ns3.test$n || ret=1 +grep '1 ns.relaxed. alpn="h2"' dig.out.ns3.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that update is rejected if query is not allowed ($n)" +{ + $NSUPDATE -d <nsupdate.out.test$n 2>&1 +grep 'failed: REFUSED' nsupdate.out.test$n >/dev/null || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + +n=$((n + 1)) +ret=0 +echo_i "check that update is rejected if quota is exceeded ($n)" +for loop in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + { + $NSUPDATE -4 -l -p ${PORT} -k ns1/session.key >/dev/null 2>&1 <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + send +EOF + grep "response to GSS-TSIG query was unsuccessful (REFUSED)" nsupdate.out.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + copy_setports ns7/named2.conf.in ns7/named.conf + rndc_reload ns7 10.53.0.7 + + n=$((n + 1)) + ret=0 + echo_i "check krb5-self match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add machine.example.com 3600 IN A 10.53.0.7 + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 machine.example.com A >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "machine.example.com..*A.*10.53.0.7" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-self no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add foo.example.com 3600 IN A 10.53.0.7 + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 foo.example.com A >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._tcp.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._udp.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs match PTR ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update add 4.3.2.1.in-addr.arpa 3600 IN PTR machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 4.3.2.1.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "4.3.2.1.in-addr.arpa.*PTR.*machine.example.com" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs no-match PTR ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update add 5.3.2.1.in-addr.arpa 3600 IN PTR notme.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 5.3.2.1.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs match SRV ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _xxx.self-srv.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv.example.com ANY >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "_xxx.self-srv.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs no listed types match (SRV & TXT) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _xxx.self-srv-no-type.example.com 3600 IN SRV 0 0 0 machine.example.com + update add _xxx.self-srv-no-type.example.com 3600 IN TXT a txt record + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv-no-type.example.com ANY >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep '_xxx.self-srv-no-type.example.com.*SRV.*0 0 0 machine.example.com' dig.out.ns7.test$n >/dev/null || ret=1 + grep '_xxx.self-srv-no-type.example.com.*TXT.*"a" "txt" "record"' dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs no-match RDATA (SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _yyy.self-srv.example.com 3600 IN SRV 0 0 0 notme.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 _yyy.self-srv.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs no-match TYPE (TXT) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update add _yyy.self-srv.example.com 3600 IN TXT a-txt-record + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 _yyy.self-srv.example.com TXT >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete PTR (matching PTR) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.7 single.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns7.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns7.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update delete single.ptr.self-ptr.in-addr.arpa PTR + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 single.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete PTR (matching PTR with non-matching PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update delete many.ptr.self-ptr.in-addr.arpa PTR + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 many.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete ANY (matching PTR) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-ptr.in-addr.arpa PTR >dig.out.ns7.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns7.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update delete single.any.self-ptr.in-addr.arpa + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-ptr.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete ANY (matching PTR with non-matching PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone in-addr.arpa + update delete many.any.self-ptr.in-addr.arpa + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 many.any.self-ptr.in-addr.arpa PTR >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete SRV (matching SRV) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.7 single.srv.self-srv.example.com SRV >dig.out.ns7.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns7.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update delete single.srv.self-srv.example.com SRV + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 single.srv.self-srv.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete SRV (matching SRV with non-matching SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update delete many.srv.self-srv.example.com SRV + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 many.srv.self-srv.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete ANY (matching SRV) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-srv.example.com SRV >dig.out.ns7.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns7.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update delete single.any.self-srv.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.7 single.any.self-srv.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-subdomain-self-rhs delete ANY (matching SRV with non-matching SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns7/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.7 ${PORT} + zone example.com + update delete many.any.self-srv.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.7 many.any.self-srv.example.com SRV >dig.out.ns7.test$n || ret=1 + grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns7.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-selfsub match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns8/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.8 ${PORT} + zone example.com + update add xxx.machine.example.com 3600 IN A 10.53.0.8 + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.8 xxx.machine.example.com A >dig.out.ns8.test$n || ret=1 + grep "status: NOERROR" dig.out.ns8.test$n >/dev/null || ret=1 + grep "xxx.machine.example.com..*A.*10.53.0.8" dig.out.ns8.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check krb5-selfsub no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns8/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.8 ${PORT} + zone example.com + update add foo.example.com 3600 IN A 10.53.0.8 + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.8 foo.example.com A >dig.out.ns8.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns8.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-self match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.9 ${PORT} + zone example.com + update add machine.example.com 3600 IN A 10.53.0.9 + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.9 machine.example.com A >dig.out.ns9.test$n || ret=1 + grep "status: NOERROR" dig.out.ns9.test$n >/dev/null || ret=1 + grep "machine.example.com..*A.*10.53.0.9" dig.out.ns9.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-self no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.9 ${PORT} + zone example.com + update add foo.example.com 3600 IN A 10.53.0.9 + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.9 foo.example.com A >dig.out.ns9.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns9.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.9 ${PORT} + zone example.com + update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._tcp.example.com SRV >dig.out.ns9.test$n || ret=1 + grep "status: NOERROR" dig.out.ns9.test$n >/dev/null || ret=1 + grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns9.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns9/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.9 ${PORT} + zone example.com + update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._udp.example.com SRV >dig.out.ns9.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns9.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs match (PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update add 4.3.2.1.in-addr.arpa 3600 IN PTR machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 4.3.2.1.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "4.3.2.1.in-addr.arpa.*PTR.*machine.example.com" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs no-match (PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update add 5.3.2.1.in-addr.arpa 3600 IN PTR notme.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 5.3.2.1.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs match (SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update add _xxx.self-srv.example.com 3600 IN SRV 0 0 0 machine.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 _xxx.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "_xxx.self-srv.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs no-match (SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update add _yyy.self-srv.example.com 3600 IN SRV 0 0 0 notme.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 _yyy.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete SRV (matching SRV) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.10 single.srv.self-srv.example.com SRV >dig.out.ns10.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns10.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update delete single.srv.self-srv.example.com SRV + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 single.srv.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete SRV (matching SRV with non-matching SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update delete many.srv.self-srv.example.com SRV + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 many.srv.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete PTR (matching PTR) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.10 single.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns10.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns10.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update delete single.ptr.self-ptr.in-addr.arpa PTR + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 single.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete PTR (matching PTR with non-matching PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update delete many.ptr.self-ptr.in-addr.arpa PTR + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 many.ptr.self-ptr.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete ANY (matching PTR) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-ptr.in-addr.arpa PTR >dig.out.ns10.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns10.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update delete single.any.self-ptr.in-addr.arpa + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-ptr.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete ANY (matching PTR with non-matching PTR) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone in-addr.arpa + update delete many.any.self-ptr.in-addr.arpa + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 many.any.self-ptr.in-addr.arpa PTR >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete ANY (matching SRV) ($n)" + $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-srv.example.com SRV >dig.out.ns10.pre.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.pre.test$n >/dev/null || ret=1 + grep "ANSWER: 1," dig.out.ns10.pre.test$n >/dev/null || ret=1 + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update delete single.any.self-srv.example.com + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 single.any.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-subdomain-self-rhs delete ANY (matching SRV with non-matching SRV) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update delete many.any.self-srv.example.com + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 many.any.self-srv.example.com SRV >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "ANSWER: 2," dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-selfsub match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update add xxx.machine.example.com 3600 IN A 10.53.0.10 + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 xxx.machine.example.com A >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "xxx.machine.example.com..*A.*10.53.0.10" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-selfsub no-match ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE <nsupdate.out.test$n 2>&1 && ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${PORT} + zone example.com + update add foo.example.com 3600 IN A 10.53.0.10 + send +EOF + grep "update failed: REFUSED" nsupdate.out.test$n >/dev/null || ret=1 + $DIG $DIGOPTS +tcp @10.53.0.10 foo.example.com A >dig.out.ns10.test$n || ret=1 + grep "status: NXDOMAIN" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } + + n=$((n + 1)) + ret=0 + echo_i "check ms-selfsub match using DoT (opportunistic-tls) ($n)" + KRB5CCNAME="FILE:$(pwd)/ns10/machine.ccache" + export KRB5CCNAME + $NSUPDATE -d -S -O <nsupdate.out.test$n 2>&1 || ret=1 + gsstsig + realm EXAMPLE.COM + server 10.53.0.10 ${TLSPORT} + zone example.com + update add dot.machine.example.com 3600 IN A 10.53.0.10 + send +EOF + $DIG $DIGOPTS +tcp @10.53.0.10 dot.machine.example.com A >dig.out.ns10.test$n || ret=1 + grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 + grep "dot.machine.example.com..*A.*10.53.0.10" dig.out.ns10.test$n >/dev/null || ret=1 + [ $ret = 0 ] || { + echo_i "failed" + status=1 + } +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/nsupdate/tests_sh_nsupdate.py b/bin/tests/system/nsupdate/tests_sh_nsupdate.py new file mode 100644 index 0000000..20d8fc9 --- /dev/null +++ b/bin/tests/system/nsupdate/tests_sh_nsupdate.py @@ -0,0 +1,85 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import platform + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "Kxxx*", + "dig.out.*", + "nextpart.out.*", + "nsupdate.*out*", + "perl.update_test.out", + "typelist.out.*", + "update.in.*", + "verylarge", + "ans*/ans.run", + "ns*/*.jnl", + "ns*/*.jnl", + "ns1/ddns.key", + "ns1/example.db", + "ns1/keytests.db", + "ns1/legacy*.key", + "ns1/many.test.db", + "ns1/maxjournal.db", + "ns1/md5.key", + "ns1/other.db", + "ns1/sample.db", + "ns1/sha*.key", + "ns1/tls.conf", + "ns1/tls.options", + "ns1/unixtime.db", + "ns1/update.db", + "ns1/yyyymmddvv.db", + "ns2/example.bk", + "ns2/sample.db", + "ns2/update.alt.bk", + "ns2/update.bk", + "ns3/dsset-*", + "ns3/K*", + "ns3/*.signed", + "ns3/delegation.test.db", + "ns3/dnskey.test.db", + "ns3/example.db", + "ns3/multisigner.test.db", + "ns3/nsec3param.test.db", + "ns3/relaxed.db", + "ns3/too-big.test.db", + "ns5/local.db", + "ns6/2.0.0.2.ip6.addr.db", + "ns6/in-addr.db", + "ns7/_default.tsigkeys", + "ns7/example.com.db", + "ns7/in-addr.db", + "ns8/_default.tsigkeys", + "ns8/example.com.db", + "ns8/in-addr.db", + "ns9/_default.tsigkeys", + "ns9/denyname.example.db", + "ns9/example.com.db", + "ns9/in-addr.db", + "ns10/_default.tsigkeys", + "ns10/example.com.db", + "ns10/in-addr.db", + ] +) + + +MAX_RUNS = 2 if platform.system() == "FreeBSD" else 1 # GL#3846 + + +@isctest.mark.flaky(max_runs=MAX_RUNS) +def test_nsupdate(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/nsupdate/update_test.pl b/bin/tests/system/nsupdate/update_test.pl new file mode 100644 index 0000000..066fa2c --- /dev/null +++ b/bin/tests/system/nsupdate/update_test.pl @@ -0,0 +1,429 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Dynamic update test suite. +# +# Usage: +# +# perl update_test.pl [-s server] [-p port] zone +# +# The server defaults to 127.0.0.1. +# The port defaults to 53. +# +# The "Special NS rules" tests will only work correctly if the +# zone has no NS records to begin with, or alternatively has a +# single NS record pointing at the name "ns1" (relative to +# the zone name). +# +# Installation notes: +# +# This program uses the Net::DNS::Resolver module. +# You can install it by saying +# +# perl -MCPAN -e "install Net::DNS" +# + +use Getopt::Std; +use Net::DNS; +use Net::DNS::Update; +use Net::DNS::Resolver; + +$opt_s = "127.0.0.1"; +$opt_p = 53; + +getopt('s:p:'); + +$res = new Net::DNS::Resolver; +$res->nameservers($opt_s); +$res->port($opt_p); +$res->defnames(0); # Do not append default domain. + +@ARGV == 1 or die + "usage: perl update_test.pl [-s server] [-p port] zone\n"; + +$zone = shift @ARGV; + +my $failures = 0; + +sub assert { + my ($cond, $explanation) = @_; + if (!$cond) { + print "Test Failed: $explanation ***\n"; + $failures++; + } +} + +sub test { + my ($expected, @records) = @_; + + my $update = new Net::DNS::Update("$zone"); + + foreach $rec (@records) { + $update->push(@$rec); + } + + $reply = $res->send($update); + + # Did it work? + if (defined $reply) { + my $rcode = $reply->header->rcode; + assert($rcode eq $expected, "expected $expected, got $rcode"); + } else { + print "Update failed: ", $res->errorstring, "\n"; + $failures++; + } +} + +sub section { + my ($msg) = @_; + print "$msg\n"; +} + +section("Delete any leftovers from previous tests"); +test("NOERROR", ["update", rr_del("a.$zone")]); +test("NOERROR", ["update", rr_del("b.$zone")]); +test("NOERROR", ["update", rr_del("c.$zone")]); +test("NOERROR", ["update", rr_del("d.$zone")]); +test("NOERROR", ["update", rr_del("e.$zone")]); +test("NOERROR", ["update", rr_del("f.$zone")]); +test("NOERROR", ["update", rr_del("ns.s.$zone")]); +test("NOERROR", ["update", rr_del("s.$zone")]); +test("NOERROR", ["update", rr_del("t.$zone")]); +test("NOERROR", ["update", rr_del("*.$zone")]); +test("NOERROR", ["update", rr_del("u.$zone")]); +test("NOERROR", ["update", rr_del("a.u.$zone")]); +test("NOERROR", ["update", rr_del("b.u.$zone")]); + +section("Simple prerequisites in the absence of data"); +# Name is in Use +test("NXDOMAIN", ["pre", yxdomain("a.$zone")]); +# RRset exists (value independent) +test("NXRRSET", ["pre", yxrrset("a.$zone A")]); +# Name is not in use +test("NOERROR", ["pre", nxdomain("a.$zone")]); +# RRset does not exist +test("NOERROR", ["pre", nxrrset("a.$zone A")]); +# RRset exists (value dependent) +test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]); + + +section ("Simple creation of data"); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); + +section ("Simple prerequisites in the presence of data"); +# Name is in use +test("NOERROR", ["pre", yxdomain("a.$zone")]); +# RRset exists (value independent) +test("NOERROR", ["pre", yxrrset("a.$zone A")]); +# Name is not in use +test("YXDOMAIN", ["pre", nxdomain("a.$zone")]); +# RRset does not exist +test("YXRRSET", ["pre", nxrrset("a.$zone A")]); +# RRset exists (value dependent) +test("NOERROR", ["pre", yxrrset("a.$zone A 73.80.65.49")]); + +# +# Merging of RRsets +# +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); + +section("Detailed tests of \"RRset exists (value dependent)\" prerequisites"); +test("NOERROR", ["pre", + yxrrset("a.$zone A 73.80.65.49"), + yxrrset("a.$zone A 73.80.65.50")]); +test("NOERROR", ["pre", + yxrrset("a.$zone A 73.80.65.50"), + yxrrset("a.$zone A 73.80.65.49")]); +test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.49")]); +test("NXRRSET", ["pre", yxrrset("a.$zone A 73.80.65.50")]); +test("NXRRSET", ["pre", + yxrrset("a.$zone A 73.80.65.49"), + yxrrset("a.$zone A 73.80.65.50"), + yxrrset("a.$zone A 73.80.65.51")]); + + +section("Torture test of \"RRset exists (value dependent)\" prerequisites."); + +test("NOERROR", ["update", + rr_add("e.$zone 300 A 73.80.65.49"), + rr_add("e.$zone 300 TXT 'one'"), + rr_add("e.$zone 300 A 73.80.65.50")]); +test("NOERROR", ["update", + rr_add("e.$zone 300 A 73.80.65.52"), + rr_add("f.$zone 300 A 73.80.65.52"), + rr_add("e.$zone 300 A 73.80.65.51")]); +test("NOERROR", ["update", + rr_add("e.$zone 300 TXT 'three'"), + rr_add("e.$zone 300 TXT 'two'")]); +test("NOERROR", ["update", + rr_add("e.$zone 300 MX 10 mail.$zone")]); + +test("NOERROR", ["pre", + yxrrset("e.$zone A 73.80.65.52"), + yxrrset("e.$zone TXT 'two'"), + yxrrset("e.$zone A 73.80.65.51"), + yxrrset("e.$zone TXT 'three'"), + yxrrset("e.$zone A 73.80.65.50"), + yxrrset("f.$zone A 73.80.65.52"), + yxrrset("e.$zone A 73.80.65.49"), + yxrrset("e.$zone TXT 'one'")]); + + +section("Subtraction of RRsets"); +test("NOERROR", ["update", rr_del("a.$zone A 73.80.65.49")]); +test("NOERROR", ["pre", + yxrrset("a.$zone A 73.80.65.50")]); + +test("NOERROR", ["update", rr_del("a.$zone A 73.80.65.50")]); +test("NOERROR", ["pre", nxrrset("a.$zone A")]); +test("NOERROR", ["pre", nxdomain("a.$zone")]); + +section("Other forms of deletion"); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); +test("NOERROR", ["update", rr_add("a.$zone 300 MX 10 mail.$zone")]); +test("NOERROR", ["update", rr_del("a.$zone A")]); +test("NOERROR", ["pre", nxrrset("a.$zone A")]); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]); +test("NOERROR", ["update", rr_del("a.$zone")]); +test("NOERROR", ["pre", nxdomain("a.$zone")]); + +section("Case insensitivity"); +test("NOERROR", ["update", rr_add("a.$zone 300 PTR foo.net.")]); +test("NOERROR", ["pre", yxrrset("A.$zone PTR fOo.NeT.")]); + +section("Special CNAME rules"); +test("NOERROR", ["update", rr_add("b.$zone 300 CNAME foo.net.")]); +test("NOERROR", ["update", rr_add("b.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["pre", yxrrset("b.$zone CNAME foo.net.")]); +test("NOERROR", ["pre", nxrrset("b.$zone A")]); + +test("NOERROR", ["update", rr_add("c.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["update", rr_add("c.$zone 300 CNAME foo.net.")]); +test("NOERROR", ["pre", yxrrset("c.$zone A")]); +test("NOERROR", ["pre", nxrrset("c.$zone CNAME")]); + +# XXX should test with SIG, KEY, NXT, too. + +# +# Currently commented out because Net::DNS does not properly +# support WKS records. +# +#section("Special WKS rules"); +#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP telnet ftp")]); +#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp")]); +#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]); +#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP smtp")]); +#test("NOERROR", ["pre", +# yxrrset("c.$zone WKS 73.80.65.49 TCP smtp"), +# yxrrset("c.$zone WKS 73.80.65.49 UDP telnet ftp"), +# yxrrset("c.$zone WKS 73.80.65.50 TCP telnet ftp")]); + + +section("Special NS rules"); + +# Deleting the last NS record using "Delete an RR from an RRset" +# should fail at the zone apex and work elsewhere. The pseudocode +# in RFC2136 says it should fail everywhere, but this is in conflict +# with the actual text. + +# Apex +test("NOERROR", ["update", + rr_add("$zone 300 NS ns1.$zone"), + rr_add("$zone 300 NS ns2.$zone")]); +test("NOERROR", ["update", rr_del("$zone NS ns1.$zone")]); +test("NOERROR", ["update", rr_del("$zone NS ns2.$zone")]); +test("NOERROR", ["pre", + yxrrset("$zone NS ns2.$zone")]); + +# Non-apex +test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); +test("NOERROR", ["update", rr_del("n.$zone NS ns1.$zone")]); +test("NOERROR", ["pre", nxrrset("n.$zone NS")]); + +# Other ways of deleting NS records should also fail at the apex +# and work elsewhere. + +# Non-apex +test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); +test("NOERROR", ["update", rr_del("n.$zone NS")]); +test("NOERROR", ["pre", nxrrset("n.$zone NS")]); + +test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]); +test("NOERROR", ["pre", yxrrset("n.$zone NS")]); +test("NOERROR", ["update", rr_del("n.$zone")]); +test("NOERROR", ["pre", nxrrset("n.$zone NS")]); + +# Apex +test("NOERROR", ["update", rr_del("$zone NS")]); +test("NOERROR", ["pre", + yxrrset("$zone NS ns2.$zone")]); + +test("NOERROR", ["update", rr_del("$zone")]); +test("NOERROR", ["pre", + yxrrset("$zone NS ns2.$zone")]); + +# They should not touch the SOA, either. + +test("NOERROR", ["update", rr_del("$zone SOA")]); +test("NOERROR", ["pre", yxrrset("$zone SOA")]); + + +section("Idempotency"); + +test("NOERROR", ["update", rr_add("d.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["pre", yxrrset("d.$zone A 73.80.65.49")]); +test("NOERROR", ["update", + rr_add("d.$zone 300 A 73.80.65.49"), + rr_del("d.$zone A")]); +test("NOERROR", ["pre", nxrrset("d.$zone A")]); + +test("NOERROR", ["update", rr_del("d.$zone A 73.80.65.49")]); +test("NOERROR", ["pre", nxrrset("d.$zone A")]); +test("NOERROR", ["update", + rr_del("d.$zone A"), + rr_add("d.$zone 300 A 73.80.65.49")]); + +test("NOERROR", ["pre", yxrrset("d.$zone A")]); + +section("Out-of-zone prerequisites and updates"); +test("NOTZONE", ["pre", yxrrset("a.somewhere.else. A 73.80.65.49")]); +test("NOTZONE", ["update", rr_add("a.somewhere.else. 300 A 73.80.65.49")]); + + +section("Glue"); +test("NOERROR", ["update", rr_add("s.$zone 300 NS ns.s.$zone")]); +test("NOERROR", ["update", rr_add("ns.s.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["pre", yxrrset("ns.s.$zone A 73.80.65.49")]); + +section("Wildcards"); +test("NOERROR", ["update", rr_add("*.$zone 300 MX 10 mail.$zone")]); +test("NOERROR", ["pre", yxrrset("*.$zone MX 10 mail.$zone")]); +test("NXRRSET", ["pre", yxrrset("w.$zone MX 10 mail.$zone")]); +test("NOERROR", ["pre", nxrrset("w.$zone MX")]); +test("NOERROR", ["pre", nxdomain("w.$zone")]); + + +section("SOA serial handling"); + +my $soatimers = "20 20 1814400 3600"; + +# Get the current SOA serial number. +my $query = $res->query($zone, "SOA"); +my ($old_soa) = $query->answer; + +my $old_serial = $old_soa->serial; + +# Increment it by 10. +my $new_serial = $old_serial + 10; +if ($new_serial > 0xFFFFFFFF) { + $new_serial -= 0x80000000; + $new_serial -= 0x80000000; +} + +# Replace the SOA with a new one. +test("NOERROR", ["update", rr_add("$zone 300 SOA mname1. . $new_serial $soatimers")]); + +# Check that the SOA really got replaced. +($db_soa) = $res->query($zone, "SOA")->answer; +assert($db_soa->mname eq "mname1"); + +# Check that attempts to decrement the serial number are ignored. +$new_serial = $old_serial - 10; +if ($new_serial < 0) { + $new_serial += 0x80000000; + $new_serial += 0x80000000; +} +test("NOERROR", ["update", rr_add("$zone 300 SOA mname2. . $new_serial $soatimers")]); +assert($db_soa->mname eq "mname1"); + +# Check that attempts to leave the serial number unchanged are ignored. +($old_soa) = $res->query($zone, "SOA")->answer; +$old_serial = $old_soa->serial; +test("NOERROR", ["update", rr_add("$zone 300 SOA mname3. . $old_serial " . + $soatimers)]); +($db_soa) = $res->query($zone, "SOA")->answer; +assert($db_soa->mname eq "mname1"); + +# +# Currently commented out because Net::DNS does not properly +# support multiple strings in TXT records. +# +#section("Big data"); +#test("NOERROR", ["update", rr_add("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]); +#test("NOERROR", ["update", rr_del("a.$zone TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]); +test("NOERROR", ["update", rr_add("a.$zone 300 TXT " . ("foo " x 3))]); + +section("Updating TTLs only"); + +test("NOERROR", ["update", rr_add("t.$zone 300 A 73.80.65.49")]); +($a) = $res->query("t.$zone", "A")->answer; +$ttl = $a->ttl; +assert($ttl == 300, "incorrect TTL value $ttl != 300"); +test("NOERROR", ["update", + rr_del("t.$zone A 73.80.65.49"), + rr_add("t.$zone 301 A 73.80.65.49")]); +($a) = $res->query("t.$zone", "A")->answer; +$ttl = $a->ttl; +assert($ttl == 301, "incorrect TTL value $ttl != 301"); + +# Add an RR that is identical to an existing one except for the TTL. +# RFC2136 is not clear about what this should do; it says "duplicate RRs +# will be silently ignored" but is an RR differing only in TTL +# to be considered a duplicate or not? The test assumes that it +# should not be considered a duplicate. +test("NOERROR", ["update", rr_add("t.$zone 302 A 73.80.65.50")]); +($a) = $res->query("t.$zone", "A")->answer; +$ttl = $a->ttl; +assert($ttl == 302, "incorrect TTL value $ttl != 302"); + +section("TTL normalization"); + +# The desired behaviour is that the old RRs get their TTL +# changed to match the new one. RFC2136 does not explicitly +# specify this, but I think it makes more sense than the +# alternatives. + +test("NOERROR", ["update", rr_add("t.$zone 303 A 73.80.65.51")]); +(@answers) = $res->query("t.$zone", "A")->answer; +$nanswers = scalar @answers; +assert($nanswers == 3, "wrong number of answers $nanswers != 3"); +foreach $a (@answers) { + $ttl = $a->ttl; + assert($ttl == 303, "incorrect TTL value $ttl != 303"); +} + +section("Obscuring existing data by zone cut"); +test("NOERROR", ["update", rr_add("a.u.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["update", rr_add("b.u.$zone 300 A 73.80.65.49")]); +test("NOERROR", ["update", rr_add("u.$zone 300 TXT txt-not-in-nxt")]); +test("NOERROR", ["update", rr_add("u.$zone 300 NS ns.u.$zone")]); + +test("NOERROR", ["update", rr_del("u.$zone NS ns.u.$zone")]); + +if ($Net::DNS::VERSION < 1.01) { + print "skipped Excessive NSEC3PARAM iterations; Net::DNS too old.\n"; +} else { + section("Excessive NSEC3PARAM iterations"); + test("REFUSED", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 51 -")]); + test("NOERROR", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 50 -")]); +} + +if ($failures) { + print "$failures tests failed.\n"; +} else { + print "All tests successful.\n"; +} +exit $failures; diff --git a/bin/tests/system/nsupdate/verylarge.in b/bin/tests/system/nsupdate/verylarge.in new file mode 100644 index 0000000..2e66221 --- /dev/null +++ b/bin/tests/system/nsupdate/verylarge.in @@ -0,0 +1,3 @@ +server 10.53.0.1 @PORT@ +update add txt.update.nil. 600 TXT 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 +send diff --git a/bin/tests/system/nzd2nzf/ns1/added.db b/bin/tests/system/nzd2nzf/ns1/added.db new file mode 100644 index 0000000..286e717 --- /dev/null +++ b/bin/tests/system/nzd2nzf/ns1/added.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +;$ORIGIN added.example. +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + MX 10 mail + +a A 10.0.0.1 +mail A 10.0.0.2 diff --git a/bin/tests/system/nzd2nzf/ns1/named.conf.j2 b/bin/tests/system/nzd2nzf/ns1/named.conf.j2 new file mode 100644 index 0000000..91ebc66 --- /dev/null +++ b/bin/tests/system/nzd2nzf/ns1/named.conf.j2 @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-query { any; }; + recursion no; + allow-new-zones yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/nzd2nzf/tests_nzd2nzf.py b/bin/tests/system/nzd2nzf/tests_nzd2nzf.py new file mode 100644 index 0000000..cd22bef --- /dev/null +++ b/bin/tests/system/nzd2nzf/tests_nzd2nzf.py @@ -0,0 +1,66 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + + +import os +import pytest + +import isctest +import isctest.mark +import isctest.run + +import dns.message + +pytestmark = [ + isctest.mark.with_lmdb, + pytest.mark.extra_artifacts( + ["ns1/_default.nzd", "ns1/_default.nzf~"], + ), +] + + +def test_nzd2nzf(servers): + zone_data = '"added.example" { type primary; file "added.db"; };' + msg = dns.message.make_query("a.added.example.", "A") + + # query for non-existing zone data + res = isctest.query.tcp(msg, servers["ns1"].ip) + isctest.check.refused(res) + + # add new zone into the default NZD using "rndc addzone" + servers["ns1"].rndc(f"addzone {zone_data}", log=False) + + # query for existing zone data + res = isctest.query.tcp(msg, servers["ns1"].ip) + isctest.check.noerror(res) + + servers["ns1"].stop() + + # dump "_default.nzd" to "_default.nzf" and check that it contains the expected content + cfg_dir = "ns1" + stdout = isctest.run.cmd( + [os.environ["NZD2NZF"], "_default.nzd"], cwd=cfg_dir + ).stdout.decode("utf-8") + assert f"zone {zone_data}" in stdout + nzf_filename = os.path.join(cfg_dir, "_default.nzf") + with open(nzf_filename, "w", encoding="utf-8") as nzf_file: + nzf_file.write(stdout) + + # delete "_default.nzd" database + nzd_filename = os.path.join(cfg_dir, "_default.nzd") + os.remove(nzd_filename) + + # start ns1 again, it should migrate "_default.nzf" to "_default.nzd" + servers["ns1"].start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + + # query for zone data from the migrated zone config + res = isctest.query.tcp(msg, servers["ns1"].ip) + isctest.check.noerror(res) diff --git a/bin/tests/system/org.isc.bind.system b/bin/tests/system/org.isc.bind.system new file mode 100644 index 0000000..48a5756 --- /dev/null +++ b/bin/tests/system/org.isc.bind.system @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# see also ifconfig.sh.in and testsock.pl + +ifup() { + /sbin/ifconfig lo0 10.53.$1.$3 alias + /sbin/ifconfig lo0 inet6 fd92:7065:b8e:${2}ff::${3} alias +} + +for ns in 1 2 3 4 5 6 7 8 9 10 11 +do + ifup 0 ff $ns +done +for ns in 1 2 +do + ifup 1 99 $ns + ifup 2 00 $ns +done +/sbin/ifconfig lo0 inet6 fd92:7065:b8e:fffe::10.53.0.4 alias +/sbin/ifconfig lo0 inet6 2002:a35:7::1 alias diff --git a/bin/tests/system/org.isc.bind.system.plist b/bin/tests/system/org.isc.bind.system.plist new file mode 100644 index 0000000..18d3c5d --- /dev/null +++ b/bin/tests/system/org.isc.bind.system.plist @@ -0,0 +1,17 @@ + + + + + Label + org.isc.bind.system + ProgramArguments + + /bin/bash + /Library/LaunchDaemons/org.isc.bind.system + + RunAtLoad + + + + diff --git a/bin/tests/system/packet.pl b/bin/tests/system/packet.pl new file mode 100644 index 0000000..900a0c0 --- /dev/null +++ b/bin/tests/system/packet.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# This is a tool for sending an arbitrary packet via UDP or TCP to an +# arbitrary address and port. The packet is specified in a file or on +# the standard input, in the form of a series of bytes in hexadecimal. +# Whitespace is ignored, as is anything following a '#' symbol. +# +# For example, the following input would generate normal query for +# isc.org/NS/IN": +# +# # QID: +# 0c d8 +# # header: +# 01 00 00 01 00 00 00 00 00 00 +# # qname isc.org: +# 03 69 73 63 03 6f 72 67 00 +# # qtype NS: +# 00 02 +# # qclass IN: +# 00 01 +# +# Note that we do not wait for a response for the server. This is simply +# a way of injecting arbitrary packets to test server resposnes. +# +# Usage: packet.pl [-a
] [-d] [-p ] [-t (udp|tcp)] [-r ] [filename] +# +# Options: +# -a
: specify address (XXX: no IPv6 support yet) +# -p : specify port +# -t : specify UDP or TCP +# -r : send packet times +# -d: dump response packets +# +# If not specified, address defaults to 127.0.0.1, port to 53, protocol +# to udp, and file to stdin. + +require 5.006.001; + +use strict; +use Getopt::Std; +use IO::File; +use IO::Socket; + +sub usage { + print ("Usage: packet.pl [-a address] [-d] [-p port] [-t (tcp|udp)] [-r ] [file]\n"); + exit 1; +} + +my $sock; +my $proto; + +sub dumppacket { + use Net::DNS; + use Net::DNS::Packet; + + my $rin; + my $rout; + $rin = ''; + vec($rin, fileno($sock), 1) = 1; + select($rout = $rin, undef, undef, 1); + if (vec($rout, fileno($sock), 1)) { + my $buf; + + if ($proto eq "udp") { + $sock->recv($buf, 512); + } else { + my $n = $sock->sysread($buf, 2); + return unless $n == 2; + my $len = unpack("n", $buf); + $n = $sock->sysread($buf, $len); + return unless $n == $len; + } + + my $response; + if ($Net::DNS::VERSION > 0.68) { + $response = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($response, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + $response->print; + } +} + +my %options={}; +getopts("a:dp:t:r:", \%options); + +my $addr = "127.0.0.1"; +$addr = $options{a} if defined $options{a}; + +my $port = 53; +$port = $options{p} if defined $options{p}; + +$proto = "udp"; +$proto = lc $options{t} if defined $options{t}; +usage if ($proto !~ /^(udp|tcp)$/); + +my $repeats = 1; +$repeats = $options{r} if defined $options{r}; + +my $file = "STDIN"; +if (@ARGV >= 1) { + my $filename = shift @ARGV; + open FH, "<$filename" or die "$filename: $!"; + $file = "FH"; +} + +my $input = ""; +while (defined(my $line = <$file>) ) { + chomp $line; + $line =~ s/#.*$//; + $input .= $line; +} + +$input =~ s/\s+//g; +my $data = pack("H*", $input); +my $len = length $data; + +my $output = unpack("H*", $data); +print ("sending $repeats time(s): $output\n"); + +$sock = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port, + Blocking => 0, + Proto => $proto,) or die "$!"; + +STDOUT->autoflush(1); + +my $bytes = 0; +while ($repeats > 0) { + if ($proto eq "udp") { + $bytes += $sock->send($data); + } else { + $bytes += $sock->syswrite(pack("n", $len), 2); + $bytes += $sock->syswrite($data, $len); + } + + $repeats = $repeats - 1; + + if ($repeats % 1000 == 0) { + print "."; + } +} + +$sock->shutdown(SHUT_WR); +if (defined $options{d}) { + dumppacket; +} + +$sock->close; +close $file; +print ("\nsent $bytes bytes to $addr:$port\n"); diff --git a/bin/tests/system/padding/ns1/named.conf.in b/bin/tests/system/padding/ns1/named.conf.in new file mode 100644 index 0000000..32dbf90 --- /dev/null +++ b/bin/tests/system/padding/ns1/named.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/padding/ns1/root.db b/bin/tests/system/padding/ns1/root.db new file mode 100644 index 0000000..17780d1 --- /dev/null +++ b/bin/tests/system/padding/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/padding/ns2/example.db b/bin/tests/system/padding/ns2/example.db new file mode 100644 index 0000000..f6a4b03 --- /dev/null +++ b/bin/tests/system/padding/ns2/example.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA ns2 hostmaster.isc.org. 1 600 600 1200 600 +@ NS ns2 +ns2 A 10.53.0.2 +foo A 10.53.1.1 diff --git a/bin/tests/system/padding/ns2/named.conf.in b/bin/tests/system/padding/ns2/named.conf.in new file mode 100644 index 0000000..6f2a34c --- /dev/null +++ b/bin/tests/system/padding/ns2/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + send-cookie yes; + response-padding { !10.53.0.8; any; } block-size 64; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/padding/ns3/named.conf.in b/bin/tests/system/padding/ns3/named.conf.in new file mode 100644 index 0000000..1b44e47 --- /dev/null +++ b/bin/tests/system/padding/ns3/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +server 10.53.0.2 { + tcp-only yes; + padding 64; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/padding/ns4/named.conf.in b/bin/tests/system/padding/ns4/named.conf.in new file mode 100644 index 0000000..957175c --- /dev/null +++ b/bin/tests/system/padding/ns4/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation no; +}; + +server 10.53.0.2 { + tcp-only no; + padding 64; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/padding/setup.sh b/bin/tests/system/padding/setup.sh new file mode 100644 index 0000000..eb37490 --- /dev/null +++ b/bin/tests/system/padding/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +touch ns2/named.stats diff --git a/bin/tests/system/padding/tests.sh b/bin/tests/system/padding/tests.sh new file mode 100644 index 0000000..ef6b2cf --- /dev/null +++ b/bin/tests/system/padding/tests.sh @@ -0,0 +1,141 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +n=0 +status=0 + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +getcookie() { + awk '$2 == "COOKIE:" { + print $3; + }' <$1 +} + +echo_i "checking that dig handles padding ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +qr +padding=128 foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null || ret=1 +grep "; QUERY SIZE: 128" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that dig added padding ($n)" +ret=0 +n=$((n + 1)) +nextpart ns2/named.stats >/dev/null +$RNDCCMD 10.53.0.2 stats +wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1 +nextpart ns2/named.stats | grep "EDNS padding option received" >/dev/null || ret=1 + +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that padding is added for TCP responses ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +vc +padding=128 foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null || ret=1 +grep "rcvd: 128" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that padding is added to valid cookie responses ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +cookie foo.example @10.53.0.2 >dig.out.testc || ret=1 +cookie=$(getcookie dig.out.testc) +$DIG $DIGOPTS +cookie=$cookie +padding=128 foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null || ret=1 +grep "rcvd: 128" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that padding must be requested (TCP) ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +vc foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that padding must be requested (valid cookie) ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +cookie=$cookie foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that padding can be filtered out ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +vc +padding=128 -b 10.53.0.8 foo.example @10.53.0.2 >dig.out.test$n || ret=1 +grep "; PAD" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that a TCP and padding server config enables padding ($n)" +ret=0 +n=$((n + 1)) +nextpart ns2/named.stats >/dev/null +$RNDCCMD 10.53.0.2 stats +wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1 +opad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}') +$DIG $DIGOPTS foo.example @10.53.0.3 >dig.out.test$n || ret=1 +$RNDCCMD 10.53.0.2 stats +wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1 +npad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}') +if [ "$opad" -eq "$npad" ]; then + echo_i "error: opad ($opad) == npad ($npad)" + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that a padding server config should enforce TCP ($n)" +ret=0 +n=$((n + 1)) +nextpart ns2/named.stats >/dev/null +$RNDCCMD 10.53.0.2 stats +wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1 +opad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}') +$DIG $DIGOPTS foo.example @10.53.0.4 >dig.out.test$n || ret=1 +$RNDCCMD 10.53.0.2 stats +wait_for_log_peek 5 "--- Statistics Dump ---" ns2/named.stats || ret=1 +npad=$(nextpart ns2/named.stats | awk '/EDNS padding option received/ { print $1}') +if [ "$opad" -ne "$npad" ]; then + echo_i "error: opad ($opad) != npad ($npad)" + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that zero-length padding option has no effect ($n)" +ret=0 +n=$((n + 1)) +$DIG $DIGOPTS +qr +ednsopt=12 foo.example @10.53.0.2 >dig.out.test$n.1 || ret=1 +grep "; PAD" dig.out.test$n.1 >/dev/null || ret=1 +$DIG $DIGOPTS +qr +ednsopt=12:00 foo.example @10.53.0.2 >dig.out.test$n.2 || ret=1 +grep "; PAD" dig.out.test$n.2 >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/padding/tests_sh_padding.py b/bin/tests/system/padding/tests_sh_padding.py new file mode 100644 index 0000000..1d23191 --- /dev/null +++ b/bin/tests/system/padding/tests_sh_padding.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns2/named.stats*", + ] +) + + +def test_padding(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/pending/ns1/named.conf.in b/bin/tests/system/pending/ns1/named.conf.in new file mode 100644 index 0000000..af5d628 --- /dev/null +++ b/bin/tests/system/pending/ns1/named.conf.in @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "trusted.conf"; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; diff --git a/bin/tests/system/pending/ns1/root.db.in b/bin/tests/system/pending/ns1/root.db.in new file mode 100644 index 0000000..fe7fe92 --- /dev/null +++ b/bin/tests/system/pending/ns1/root.db.in @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example.com. NS ns2.example.com. +ns2.example.com. A 10.53.0.2 +hostile. NS ns3.hostile. +ns3.hostile. A 10.53.0.3 +nice.good. A 10.10.10.10 diff --git a/bin/tests/system/pending/ns1/sign.sh b/bin/tests/system/pending/ns1/sign.sh new file mode 100644 index 0000000..c7b99c3 --- /dev/null +++ b/bin/tests/system/pending/ns1/sign.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +(cd ../ns2 && $SHELL -e sign.sh) + +cp ../ns2/dsset-example. . +cp ../ns2/dsset-example.com. . + +keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone) +cat $infile $keyname1.key $keyname2.key >$zonefile + +$SIGNER -g -o $zone $zonefile >/dev/null + +# Configure the resolving server with a static key. +keyfile_to_static_ds $keyname2 >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns4/trusted.conf diff --git a/bin/tests/system/pending/ns2/example.com.db.in b/bin/tests/system/pending/ns2/example.com.db.in new file mode 100644 index 0000000..ee3a1b8 --- /dev/null +++ b/bin/tests/system/pending/ns2/example.com.db.in @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +@ IN SOA mname1. . ( + 2009110300 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail +ns2 A 10.53.0.2 +mail A 192.0.2.2 + AAAA 2001:db8::2 +pending-ok A 192.0.2.2 +pending-ng A 192.0.2.102 +removed A 10.9.8.7 diff --git a/bin/tests/system/pending/ns2/example.db.in b/bin/tests/system/pending/ns2/example.db.in new file mode 100644 index 0000000..5b42e2a --- /dev/null +++ b/bin/tests/system/pending/ns2/example.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +$ORIGIN example. +@ IN SOA mname1. . ( + 2009110300 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + MX 10 mail +ns2 A 10.53.0.2 +mail A 10.0.0.2 +bad CNAME nice.good. +worse A 6.6.6.6 diff --git a/bin/tests/system/pending/ns2/forgery.db b/bin/tests/system/pending/ns2/forgery.db new file mode 100644 index 0000000..fbf42bc --- /dev/null +++ b/bin/tests/system/pending/ns2/forgery.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +$ORIGIN good. +@ IN SOA mname1. . ( + 2009110300 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 + +nice.good. CNAME worse.example. diff --git a/bin/tests/system/pending/ns2/named.conf.in b/bin/tests/system/pending/ns2/named.conf.in new file mode 100644 index 0000000..a403f13 --- /dev/null +++ b/bin/tests/system/pending/ns2/named.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +include "trusted.conf"; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db.signed"; +}; + +zone "example.com" { + type primary; + file "example.com.db.signed"; + allow-update { 10.53.0.0/16; }; +}; + +zone "good" { + type primary; + file "forgery.db"; + allow-query { any; }; +}; diff --git a/bin/tests/system/pending/ns2/sign.sh b/bin/tests/system/pending/ns2/sign.sh new file mode 100644 index 0000000..062e989 --- /dev/null +++ b/bin/tests/system/pending/ns2/sign.sh @@ -0,0 +1,33 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +for domain in example example.com; do + zone=${domain}. + infile=${domain}.db.in + zonefile=${domain}.db + + keyname1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) + keyname2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -f KSK -n zone $zone) + + cat $infile $keyname1.key $keyname2.key >$zonefile + + $SIGNER -3 bebe -o $zone $zonefile >/dev/null +done + +# remove "removed" record from example.com, causing the server to +# send an apparently-invalid NXDOMAIN +sed '/^removed/d' example.com.db.signed >example.com.db.new +rm -f example.com.db.signed +mv example.com.db.new example.com.db.signed diff --git a/bin/tests/system/pending/ns3/hostile.db b/bin/tests/system/pending/ns3/hostile.db new file mode 100644 index 0000000..a199922 --- /dev/null +++ b/bin/tests/system/pending/ns3/hostile.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +@ IN SOA mname1. . ( + 2009110500 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns3 + MX 10 mail.example. +ns3 A 10.53.0.3 diff --git a/bin/tests/system/pending/ns3/mail.example.db b/bin/tests/system/pending/ns3/mail.example.db new file mode 100644 index 0000000..77eb731 --- /dev/null +++ b/bin/tests/system/pending/ns3/mail.example.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 +@ IN SOA mname1. . ( + 2009110300 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +@ NS ns3 +ns3 A 10.53.0.3 +;mail A 10.0.0.2 // the correct record +@ A 10.0.0.3 diff --git a/bin/tests/system/pending/ns3/named.conf.in b/bin/tests/system/pending/ns3/named.conf.in new file mode 100644 index 0000000..6d69d67 --- /dev/null +++ b/bin/tests/system/pending/ns3/named.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +include "trusted.conf"; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion no; + notify no; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "mail.example" { + type primary; + file "mail.example.db"; +}; + +zone "hostile" { + type primary; + file "hostile.db"; +}; diff --git a/bin/tests/system/pending/ns4/named.conf.in b/bin/tests/system/pending/ns4/named.conf.in new file mode 100644 index 0000000..0c2e8a8 --- /dev/null +++ b/bin/tests/system/pending/ns4/named.conf.in @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "trusted.conf"; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/pending/setup.sh b/bin/tests/system/pending/setup.sh new file mode 100644 index 0000000..f16857c --- /dev/null +++ b/bin/tests/system/pending/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +cd ns1 && $SHELL -e sign.sh diff --git a/bin/tests/system/pending/tests.sh b/bin/tests/system/pending/tests.sh new file mode 100644 index 0000000..29ab3e9 --- /dev/null +++ b/bin/tests/system/pending/tests.sh @@ -0,0 +1,199 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +# replace_data dname RR old_data new_data +replace_data() { + if [ $# -ne 4 ]; then + echo_i "unexpected input for replace_data" + return 1 + fi + + _dname=$1 + _rr=$2 + _olddata=$3 + _newdata=$4 + + _ret=0 + $NSUPDATE -d <>nsupdate.out.test 2>&1 || _ret=1 +server 10.53.0.2 ${PORT} +update delete ${_dname} 30 ${_rr} ${_olddata} +update add ${_dname} 30 ${_rr} ${_newdata} +send +END + + if [ $_ret != 0 ]; then + echo_i "failed to update the test data" + return 1 + fi + + return 0 +} + +status=0 +n=0 + +DIGOPTS="+short +tcp -p ${PORT}" +DIGOPTS_CD="$DIGOPTS +cd" + +echo_i "Priming cache." +ret=0 +expect="10 mail.example." +ans=$($DIG $DIGOPTS_CD @10.53.0.4 hostile MX) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Checking that bogus additional is not returned with +CD." +ret=0 +expect="10.0.0.2" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 mail.example A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +# +# Prime cache with pending additional records. These should not be promoted +# to answer. +# +echo_i "Priming cache (pending additional A and AAAA)" +ret=0 +expect="10 mail.example.com." +ans=$($DIG $DIGOPTS @10.53.0.4 example.com MX) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Replacing pending A" +ret=0 +replace_data mail.example.com. A 192.0.2.2 192.0.2.3 || ret=1 +status=$((status + ret)) + +echo_i "Replacing pending AAAA" +ret=0 +replace_data mail.example.com. AAAA 2001:db8::2 2001:db8::3 || ret=1 +status=$((status + ret)) + +echo_i "Checking updated data to be returned (without CD)" +ret=0 +expect="192.0.2.3" +ans=$($DIG $DIGOPTS @10.53.0.4 mail.example.com A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Checking updated data to be returned (with CD)" +ret=0 +expect="2001:db8::3" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 mail.example.com AAAA) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +# +# Prime cache with a pending answer record. It can be returned (without +# validation) with +CD. +# +echo_i "Priming cache (pending answer)" +ret=0 +expect="192.0.2.2" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ok.example.com A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Replacing pending data" +ret=0 +replace_data pending-ok.example.com. A 192.0.2.2 192.0.2.3 || ret=1 +status=$((status + ret)) + +echo_i "Confirming cached pending data to be returned with CD" +ret=0 +expect="192.0.2.2" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ok.example.com A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +# +# Prime cache with a pending answer record. It should not be returned +# to no-DNSSEC clients. +# +echo_i "Priming cache (pending answer)" +ret=0 +expect="192.0.2.102" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 pending-ng.example.com A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Replacing pending data" +ret=0 +replace_data pending-ng.example.com. A 192.0.2.102 192.0.2.103 || ret=1 +status=$((status + ret)) + +echo_i "Confirming updated data returned, not the cached one, without CD" +ret=0 +expect="192.0.2.103" +ans=$($DIG $DIGOPTS @10.53.0.4 pending-ng.example.com A) || ret=1 +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +# +# Try to fool the resolver with an out-of-bailiwick CNAME +# +echo_i "Trying to Prime out-of-bailiwick pending answer with CD" +ret=0 +expect="10.10.10.10" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 bad.example. A) || ret=1 +ans=$(echo $ans | awk '{print $NF}') +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Confirming the out-of-bailiwick answer is not cached or reused with CD" +ret=0 +expect="10.10.10.10" +ans=$($DIG $DIGOPTS_CD @10.53.0.4 nice.good. A) || ret=1 +ans=$(echo $ans | awk '{print $NF}') +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +# +# Make sure the resolver doesn't cache bogus NXDOMAIN +# +echo_i "Trying to Prime bogus NXDOMAIN" +ret=0 +expect="SERVFAIL" +ans=$($DIG +tcp -p ${PORT} @10.53.0.4 removed.example.com. A) || ret=1 +ans=$(echo $ans | sed 's/^.*status: \([A-Z][A-Z]*\).*$/\1/') +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "Confirming the bogus NXDOMAIN was not cached" +ret=0 +expect="SERVFAIL" +ans=$($DIG +tcp -p ${PORT} @10.53.0.4 removed.example.com. A) || ret=1 +ans=$(echo $ans | sed 's/^.*status: \([A-Z][A-Z]*\).*$/\1/') +test "$ans" = "$expect" || ret=1 +test $ret = 0 || echo_i "failed, got '$ans', expected '$expect'" +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/pending/tests_sh_pending.py b/bin/tests/system/pending/tests_sh_pending.py new file mode 100644 index 0000000..9f90194 --- /dev/null +++ b/bin/tests/system/pending/tests_sh_pending.py @@ -0,0 +1,31 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "nsupdate.out.*", + "ns*/dsset-*", + "ns*/K*", + "ns*/*.jnl", + "ns*/*.signed", + "ns*/trusted.conf", + "ns*/K*", + "ns1/root.db", + "ns2/example.com.db", + "ns2/example.db", + ] +) + + +def test_pending(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/pipelined/ans5/ans.py b/bin/tests/system/pipelined/ans5/ans.py new file mode 100644 index 0000000..bac5ed3 --- /dev/null +++ b/bin/tests/system/pipelined/ans5/ans.py @@ -0,0 +1,212 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +############################################################################ +# +# This tool acts as a TCP/UDP proxy and delays all incoming packets by 500 +# milliseconds. +# +# We use it to check pipelining - a client sents 8 questions over a +# pipelined connection - that require asking a normal (examplea) and a +# slow-responding (exampleb) servers: +# a.examplea +# a.exampleb +# b.examplea +# b.exampleb +# c.examplea +# c.exampleb +# d.examplea +# d.exampleb +# +# If pipelining works properly the answers will be returned out of order +# with all answers from examplea returned first, and then all answers +# from exampleb. +# +############################################################################ + +from __future__ import print_function + +import datetime +import os +import select +import signal +import socket +import sys +import time +import threading +import struct + +DELAY = 0.5 +THREADS = [] + + +def log(msg): + print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg) + + +def sigterm(*_): + log("SIGTERM received, shutting down") + for thread in THREADS: + thread.close() + thread.join() + os.remove("ans.pid") + sys.exit(0) + + +class TCPDelayer(threading.Thread): + """For a given TCP connection conn we open a connection to (ip, port), + and then we delay each incoming packet by DELAY by putting it in a + queue. + In the pipelined test TCP should not be used, but it's here for + completnes. + """ + + def __init__(self, conn, ip, port): + threading.Thread.__init__(self) + self.conn = conn + self.cconn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.cconn.connect((ip, port)) + self.queue = [] + self.running = True + + def close(self): + self.running = False + + def run(self): + while self.running: + curr_timeout = 0.5 + try: + curr_timeout = self.queue[0][0] - time.time() + except StopIteration: + pass + if curr_timeout > 0: + if curr_timeout == 0: + curr_timeout = 0.5 + rfds, _, _ = select.select( + [self.conn, self.cconn], [], [], curr_timeout + ) + if self.conn in rfds: + data = self.conn.recv(65535) + if not data: + return + self.queue.append((time.time() + DELAY, data)) + if self.cconn in rfds: + data = self.cconn.recv(65535) + if not data == 0: + return + self.conn.send(data) + try: + while self.queue[0][0] - time.time() < 0: + _, data = self.queue.pop(0) + self.cconn.send(data) + except StopIteration: + pass + + +class UDPDelayer(threading.Thread): + """Every incoming UDP packet is put in a queue for DELAY time, then + it's sent to (ip, port). We remember the query id to send the + response we get to a proper source, responses are not delayed. + """ + + def __init__(self, usock, ip, port): + threading.Thread.__init__(self) + self.sock = usock + self.csock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.dst = (ip, port) + self.queue = [] + self.qid_mapping = {} + self.running = True + + def close(self): + self.running = False + + def run(self): + while self.running: + curr_timeout = 0.5 + if self.queue: + curr_timeout = self.queue[0][0] - time.time() + if curr_timeout >= 0: + if curr_timeout == 0: + curr_timeout = 0.5 + rfds, _, _ = select.select( + [self.sock, self.csock], [], [], curr_timeout + ) + if self.sock in rfds: + data, addr = self.sock.recvfrom(65535) + if not data: + return + self.queue.append((time.time() + DELAY, data)) + qid = struct.unpack(">H", data[:2])[0] + log("Received a query from %s, queryid %d" % (str(addr), qid)) + self.qid_mapping[qid] = addr + if self.csock in rfds: + data, addr = self.csock.recvfrom(65535) + if not data: + return + qid = struct.unpack(">H", data[:2])[0] + dst = self.qid_mapping.get(qid) + if dst is not None: + self.sock.sendto(data, dst) + log( + "Received a response from %s, queryid %d, sending to %s" + % (str(addr), qid, str(dst)) + ) + while self.queue and self.queue[0][0] - time.time() < 0: + _, data = self.queue.pop(0) + qid = struct.unpack(">H", data[:2])[0] + log("Sending a query to %s, queryid %d" % (str(self.dst), qid)) + self.csock.sendto(data, self.dst) + + +def main(): + signal.signal(signal.SIGTERM, sigterm) + signal.signal(signal.SIGINT, sigterm) + + with open("ans.pid", "w") as pidfile: + print(os.getpid(), file=pidfile) + + listenip = "10.53.0.5" + serverip = "10.53.0.2" + + try: + port = int(os.environ["PORT"]) + except KeyError: + port = 5300 + + log("Listening on %s:%d" % (listenip, port)) + + usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + usock.bind((listenip, port)) + thread = UDPDelayer(usock, serverip, port) + thread.start() + THREADS.append(thread) + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((listenip, port)) + sock.listen(1) + sock.settimeout(1) + + while True: + try: + (clientsock, _) = sock.accept() + log("Accepted connection from %s" % clientsock) + thread = TCPDelayer(clientsock, serverip, port) + thread.start() + THREADS.append(thread) + except socket.timeout: + pass + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/pipelined/input b/bin/tests/system/pipelined/input new file mode 100644 index 0000000..485cf81 --- /dev/null +++ b/bin/tests/system/pipelined/input @@ -0,0 +1,8 @@ +a.examplea +a.exampleb +b.examplea +b.exampleb +c.examplea +c.exampleb +d.examplea +d.exampleb diff --git a/bin/tests/system/pipelined/inputb b/bin/tests/system/pipelined/inputb new file mode 100644 index 0000000..6ea367e --- /dev/null +++ b/bin/tests/system/pipelined/inputb @@ -0,0 +1,8 @@ +e.examplea +e.exampleb +f.examplea +f.exampleb +g.examplea +g.exampleb +h.examplea +h.exampleb diff --git a/bin/tests/system/pipelined/ns1/named.conf.j2 b/bin/tests/system/pipelined/ns1/named.conf.j2 new file mode 100644 index 0000000..6cfac77 --- /dev/null +++ b/bin/tests/system/pipelined/ns1/named.conf.j2 @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/pipelined/ns1/root.db b/bin/tests/system/pipelined/ns1/root.db new file mode 100644 index 0000000..f2819a1 --- /dev/null +++ b/bin/tests/system/pipelined/ns1/root.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +examplea. NS ns2.examplea. +ns2.examplea. A 10.53.0.5 + +exampleb. NS ns3.exampleb. +ns3.exampleb. A 10.53.0.3 diff --git a/bin/tests/system/pipelined/ns2/examplea.db b/bin/tests/system/pipelined/ns2/examplea.db new file mode 100644 index 0000000..1be2d11 --- /dev/null +++ b/bin/tests/system/pipelined/ns2/examplea.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +examplea IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +examplea. NS ns2.examplea. +ns2.examplea. A 10.53.0.5 + +$ORIGIN examplea. +a A 10.0.1.1 +b A 10.0.1.2 +c A 10.0.1.3 +d A 10.0.1.4 +e A 10.0.1.5 +f A 10.0.1.6 +g A 10.0.1.7 +h A 10.0.1.8 diff --git a/bin/tests/system/pipelined/ns2/named.conf.j2 b/bin/tests/system/pipelined/ns2/named.conf.j2 new file mode 100644 index 0000000..8cb605c --- /dev/null +++ b/bin/tests/system/pipelined/ns2/named.conf.j2 @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "examplea" { + type primary; + file "examplea.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/pipelined/ns3/exampleb.db b/bin/tests/system/pipelined/ns3/exampleb.db new file mode 100644 index 0000000..91b94c3 --- /dev/null +++ b/bin/tests/system/pipelined/ns3/exampleb.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +exampleb IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +exampleb. NS ns3.exampleb. +ns3.exampleb. A 10.53.0.3 + +$ORIGIN exampleb. +a A 10.0.2.1 +b A 10.0.2.2 +c A 10.0.2.3 +d A 10.0.2.4 +e A 10.0.2.5 +f A 10.0.2.6 +g A 10.0.2.7 +h A 10.0.2.8 diff --git a/bin/tests/system/pipelined/ns3/named.conf.j2 b/bin/tests/system/pipelined/ns3/named.conf.j2 new file mode 100644 index 0000000..96a9a92 --- /dev/null +++ b/bin/tests/system/pipelined/ns3/named.conf.j2 @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "exampleb" { + type primary; + file "exampleb.db"; + allow-update { any; }; +}; diff --git a/bin/tests/system/pipelined/ns4/named.conf.j2 b/bin/tests/system/pipelined/ns4/named.conf.j2 new file mode 100644 index 0000000..3a187bf --- /dev/null +++ b/bin/tests/system/pipelined/ns4/named.conf.j2 @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + directory "."; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c new file mode 100644 index 0000000..c7943be --- /dev/null +++ b/bin/tests/system/pipelined/pipequeries.c @@ -0,0 +1,304 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHECK(str, x) \ + { \ + if ((x) != ISC_R_SUCCESS) { \ + fprintf(stderr, "I:%s: %s\n", (str), \ + isc_result_totext(x)); \ + exit(EXIT_FAILURE); \ + } \ + } + +#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) + +#define PORT 5300 +#define TIMEOUT 30 + +static isc_mem_t *mctx = NULL; +static dns_requestmgr_t *requestmgr = NULL; +static isc_loopmgr_t *loopmgr = NULL; +static bool have_src = false; +static isc_sockaddr_t srcaddr; +static isc_sockaddr_t dstaddr; +static int onfly; + +static void +recvresponse(void *arg) { + isc_result_t result; + dns_request_t *request = (dns_request_t *)arg; + dns_message_t *query = dns_request_getarg(request); + dns_message_t *response = NULL; + isc_buffer_t outbuf; + char output[1024]; + + result = dns_request_getresult(request); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "I:request event result: %s\n", + isc_result_totext(result)); + exit(EXIT_FAILURE); + } + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, + &response); + + result = dns_request_getresponse(request, response, + DNS_MESSAGEPARSE_PRESERVEORDER); + CHECK("dns_request_getresponse", result); + + if (response->rcode != dns_rcode_noerror) { + result = dns_result_fromrcode(response->rcode); + fprintf(stderr, "I:response rcode: %s\n", + isc_result_totext(result)); + exit(EXIT_FAILURE); + } + if (response->counts[DNS_SECTION_ANSWER] != 1U) { + fprintf(stderr, "I:response answer count (%u!=1)\n", + response->counts[DNS_SECTION_ANSWER]); + } + + isc_buffer_init(&outbuf, output, sizeof(output)); + result = dns_message_sectiontotext( + response, DNS_SECTION_ANSWER, &dns_master_style_simple, + DNS_MESSAGETEXTFLAG_NOCOMMENTS, &outbuf); + CHECK("dns_message_sectiontotext", result); + printf("%.*s", (int)isc_buffer_usedlength(&outbuf), + (char *)isc_buffer_base(&outbuf)); + fflush(stdout); + + dns_message_detach(&query); + dns_message_detach(&response); + dns_request_destroy(&request); + + if (--onfly == 0) { + isc_loopmgr_shutdown(loopmgr); + } + return; +} + +static isc_result_t +sendquery(void) { + dns_request_t *request = NULL; + dns_message_t *message = NULL; + dns_name_t *qname = NULL; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + dns_fixedname_t queryname; + isc_buffer_t buf; + static char host[256]; + int c; + + c = scanf("%255s", host); + if (c == EOF) { + return ISC_R_NOMORE; + } + + onfly++; + + dns_fixedname_init(&queryname); + isc_buffer_init(&buf, host, strlen(host)); + isc_buffer_add(&buf, strlen(host)); + result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf, + dns_rootname, 0, NULL); + CHECK("dns_name_fromtext", result); + + dns_message_create(mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &message); + + message->opcode = dns_opcode_query; + message->flags |= DNS_MESSAGEFLAG_RD; + message->rdclass = dns_rdataclass_in; + message->id = (unsigned short)(random() & 0xFFFF); + + dns_message_gettempname(message, &qname); + + dns_message_gettemprdataset(message, &qrdataset); + + dns_name_clone(dns_fixedname_name(&queryname), qname); + dns_rdataset_makequestion(qrdataset, dns_rdataclass_in, + dns_rdatatype_a); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + result = dns_request_create( + requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, NULL, + NULL, DNS_REQUESTOPT_TCP, NULL, TIMEOUT, 0, 0, + isc_loop_main(loopmgr), recvresponse, message, &request); + CHECK("dns_request_create", result); + + return ISC_R_SUCCESS; +} + +static void +sendqueries(void *arg) { + isc_result_t result; + + UNUSED(arg); + + do { + result = sendquery(); + } while (result == ISC_R_SUCCESS); + + if (onfly == 0) { + isc_loopmgr_shutdown(loopmgr); + } + return; +} + +static void +teardown_view(void *arg) { + dns_view_t *view = arg; + dns_view_detach(&view); +} + +static void +teardown_requestmgr(void *arg) { + dns_requestmgr_t *mgr = arg; + + dns_requestmgr_shutdown(mgr); + dns_requestmgr_detach(&mgr); +} + +static void +teardown_dispatchv4(void *arg) { + dns_dispatch_t *dispatchv4 = arg; + dns_dispatch_detach(&dispatchv4); +} + +static void +teardown_dispatchmgr(void *arg) { + dns_dispatchmgr_t *dispatchmgr = arg; + dns_dispatchmgr_detach(&dispatchmgr); +} + +int +main(int argc, char *argv[]) { + isc_sockaddr_t bind_any; + struct in_addr inaddr; + isc_result_t result; + isc_log_t *lctx = NULL; + isc_logconfig_t *lcfg = NULL; + isc_nm_t *netmgr = NULL; + dns_dispatchmgr_t *dispatchmgr = NULL; + dns_dispatch_t *dispatchv4 = NULL; + dns_view_t *view = NULL; + uint16_t port = PORT; + int c; + + isc_commandline_errprint = false; + while ((c = isc_commandline_parse(argc, argv, "p:r:")) != -1) { + switch (c) { + case 'p': + result = isc_parse_uint16(&port, + isc_commandline_argument, 10); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "bad port '%s'\n", + isc_commandline_argument); + exit(EXIT_FAILURE); + } + break; + case 'r': + fprintf(stderr, "The -r option has been deprecated.\n"); + break; + case '?': + fprintf(stderr, "%s: invalid argument '%c'", argv[0], + c); + break; + default: + break; + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + POST(argv); + + if (argc > 0) { + have_src = true; + } + + isc_sockaddr_any(&bind_any); + + result = ISC_R_FAILURE; + if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) { + CHECK("inet_pton", result); + } + isc_sockaddr_fromin(&srcaddr, &inaddr, 0); + + result = ISC_R_FAILURE; + if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) { + CHECK("inet_pton", result); + } + isc_sockaddr_fromin(&dstaddr, &inaddr, port); + + isc_managers_create(&mctx, 1, &loopmgr, &netmgr); + + isc_log_create(mctx, &lctx, &lcfg); + + RUNCHECK(dst_lib_init(mctx, NULL)); + + RUNCHECK(dns_dispatchmgr_create(mctx, loopmgr, netmgr, &dispatchmgr)); + + RUNCHECK(dns_dispatch_createudp( + dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchv4)); + RUNCHECK(dns_requestmgr_create(mctx, loopmgr, dispatchmgr, dispatchv4, + NULL, &requestmgr)); + + RUNCHECK(dns_view_create(mctx, loopmgr, NULL, 0, "_test", &view)); + + isc_loopmgr_setup(loopmgr, sendqueries, NULL); + isc_loopmgr_teardown(loopmgr, teardown_view, view); + isc_loopmgr_teardown(loopmgr, teardown_requestmgr, requestmgr); + isc_loopmgr_teardown(loopmgr, teardown_dispatchv4, dispatchv4); + isc_loopmgr_teardown(loopmgr, teardown_dispatchmgr, dispatchmgr); + + isc_loopmgr_run(loopmgr); + + dst_lib_destroy(); + + isc_log_destroy(&lctx); + + isc_managers_destroy(&mctx, &loopmgr, &netmgr); + + return 0; +} diff --git a/bin/tests/system/pipelined/ref b/bin/tests/system/pipelined/ref new file mode 100644 index 0000000..fe123f6 --- /dev/null +++ b/bin/tests/system/pipelined/ref @@ -0,0 +1,8 @@ +a.examplea. 10.0.1.1 +a.exampleb. 10.0.2.1 +b.examplea. 10.0.1.2 +b.exampleb. 10.0.2.2 +c.examplea. 10.0.1.3 +c.exampleb. 10.0.2.3 +d.examplea. 10.0.1.4 +d.exampleb. 10.0.2.4 diff --git a/bin/tests/system/pipelined/refb b/bin/tests/system/pipelined/refb new file mode 100644 index 0000000..a24c6bc --- /dev/null +++ b/bin/tests/system/pipelined/refb @@ -0,0 +1,8 @@ +e.examplea. 10.0.1.5 +e.exampleb. 10.0.2.5 +f.examplea. 10.0.1.6 +f.exampleb. 10.0.2.6 +g.examplea. 10.0.1.7 +g.exampleb. 10.0.2.7 +h.examplea. 10.0.1.8 +h.exampleb. 10.0.2.8 diff --git a/bin/tests/system/pipelined/tests.sh b/bin/tests/system/pipelined/tests.sh new file mode 100644 index 0000000..59dfda9 --- /dev/null +++ b/bin/tests/system/pipelined/tests.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +mdig_with_opts() { + "$MDIG" -p "${PORT}" "${@}" +} + +rndccmd() { + "$RNDC" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${@}" +} + +pipequeries() { + "$PIPEQUERIES" -p "${PORT}" +} + +status=0 +n=1 +ret=0 + +echo_i "check pipelined TCP queries ($n)" +pipequeries raw.$n || ret=1 +awk '{ print $1 " " $5 }' output.$n +sort output-sorted.$n +diff ref output-sorted.$n || { + ret=1 + echo_i "diff sorted failed" +} +diff ref output.$n >/dev/null && { + ret=1 + echo_i "diff out of order failed" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) +ret=0 + +echo_i "check pipelined TCP queries using mdig ($n)" +rndccmd 10.53.0.4 flush +wait_for_log 10 "flushing caches in all views succeeded" ns4/named.run +mdig_with_opts +noall +answer +vc -f input -b 10.53.0.4 @10.53.0.4 >raw.mdig.$n +awk '{ print $1 " " $5 }' output.mdig.$n +sort output-sorted.mdig.$n +diff ref output-sorted.mdig.$n || { + ret=1 + echo_i "diff sorted failed" +} +diff ref output.mdig.$n >/dev/null && { + ret=1 + echo_i "diff out of order failed" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) +ret=0 + +echo_i "check mdig -4 -6 ($n)" +mdig_with_opts -4 -6 -f input @10.53.0.4 >output.mdig.$n 2>&1 && ret=1 +grep "only one of -4 and -6 allowed" output.mdig.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) +ret=0 + +echo_i "check mdig -4 with an IPv6 server address ($n)" +mdig_with_opts -4 -f input @fd92:7065:b8e:ffff::2 >output.mdig.$n 2>&1 && ret=1 +grep "address family not supported" output.mdig.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +n=$((n + 1)) +ret=0 + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/pipelined/tests_sh_pipelined.py b/bin/tests/system/pipelined/tests_sh_pipelined.py new file mode 100644 index 0000000..7efe483 --- /dev/null +++ b/bin/tests/system/pipelined/tests_sh_pipelined.py @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "output*", + "raw*", + "ans*/ans.run", + ] +) + + +def test_pipelined(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/proxy/ns1/named.conf.in b/bin/tests/system/proxy/ns1/named.conf.in new file mode 100644 index 0000000..4e2c620 --- /dev/null +++ b/bin/tests/system/proxy/ns1/named.conf.in @@ -0,0 +1,119 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls self-signed { + cert-file "../self-signed-cert.pem"; + key-file "../self-signed-key.pem"; +}; + +options { + pid-file "named.pid"; + ## + # generic test + listen-on port @PORT@ { 10.53.0.1; }; + + listen-on port @EXTRAPORT1@ proxy plain { 10.53.0.1; }; + listen-on port @EXTRAPORT1@ proxy plain { 10.53.0.2; }; + listen-on port @TLSPORT@ proxy encrypted tls self-signed { 10.53.0.1; }; + listen-on port @EXTRAPORT2@ proxy plain tls self-signed { 10.53.0.1; }; + listen-on port @HTTPSPORT@ proxy encrypted tls self-signed http default { 10.53.0.1; }; + listen-on port @EXTRAPORT3@ proxy plain tls self-signed http default { 10.53.0.1; }; + listen-on port @HTTPPORT@ proxy plain tls none http default { 10.53.0.1; }; + + listen-on-v6 port @EXTRAPORT1@ proxy plain { fd92:7065:b8e:ffff::1; }; + listen-on-v6 port @EXTRAPORT1@ proxy plain { fd92:7065:b8e:ffff::2; }; + listen-on-v6 port @TLSPORT@ proxy encrypted tls self-signed { fd92:7065:b8e:ffff::1; }; + listen-on-v6 port @EXTRAPORT2@ proxy plain tls self-signed { fd92:7065:b8e:ffff::1; }; + listen-on-v6 port @HTTPSPORT@ proxy encrypted tls self-signed http default { fd92:7065:b8e:ffff::1; }; + listen-on-v6 port @EXTRAPORT3@ proxy plain tls self-signed http default { fd92:7065:b8e:ffff::1; }; + listen-on-v6 port @HTTPPORT@ proxy plain tls none http default { fd92:7065:b8e:ffff::1; }; + + allow-proxy { 10.53.0.10; fd92:7065:b8e:ffff::10; }; + allow-proxy-on { 10.53.0.1; fd92:7065:b8e:ffff::1; }; + + recursion no; + notify explicit; + statistics-file "named.stats"; + dnssec-validation yes; + tcp-initial-timeout 1200; +}; + +trust-anchors { }; + +zone "example0" { + type primary; + file "example.db"; + allow-query { any; }; +}; + +zone "example1" { + type primary; + file "example.db"; + allow-query { 1.2.3.4; fd0f:99d3:98a7::1234; }; + allow-query-on { 4.3.2.1; fd0f:99d3:98a7::4321; }; # note, we are *not* listening on the interface +}; + +zone "example2" { + type primary; + file "example.db"; + # allow the real addresses only so that we can test LOCAL requests + allow-query { 10.53.0.10; fd92:7065:b8e:ffff::10; }; + allow-query-on { 10.53.0.1; fd92:7065:b8e:ffff::1; }; +}; + +# Let's define some zones that will help us verify that ports +# information from PROXY headers is used. Please note that we are NOT +# listening on the ports used. +zone "example-proxy-do53" { + type primary; + file "example.db"; + allow-transfer port 53 transport tcp { 1.2.3.4; fd0f:99d3:98a7::1234; }; +}; + +zone "example-proxy-encrypted-dot" { + type primary; + file "example.db"; + allow-transfer port 853 transport tls { 1.2.3.4; fd0f:99d3:98a7::1234; }; +}; + +zone "example-proxy-plain-dot" { + type primary; + file "example.db"; + allow-transfer port 853 transport tls { 1.2.3.4; fd0f:99d3:98a7::1234; }; +}; + +# Now let's make something similar, but for LOCAL PROXY requests (when +# real ports and addresses are used) +zone "example-proxy-local-do53" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT1@ transport tcp { 10.53.0.10; fd92:7065:b8e:ffff::10; }; +}; + +zone "example-proxy-local-encrypted-dot" { + type primary; + file "example.db"; + allow-transfer port @TLSPORT@ transport tls { 10.53.0.10; fd92:7065:b8e:ffff::10; }; +}; + +zone "example-proxy-local-plain-dot" { + type primary; + file "example.db"; + allow-transfer port @EXTRAPORT2@ transport tls { 10.53.0.10; fd92:7065:b8e:ffff::10; }; +}; diff --git a/bin/tests/system/proxy/ns3/named.conf.in b/bin/tests/system/proxy/ns3/named.conf.in new file mode 100644 index 0000000..db1c346 --- /dev/null +++ b/bin/tests/system/proxy/ns3/named.conf.in @@ -0,0 +1,58 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +tls self-signed { + cert-file "../self-signed-cert.pem"; + key-file "../self-signed-key.pem"; +}; + +options { + pid-file "named.pid"; + ## + # generic test + listen-on port @PORT@ { 10.53.0.3; }; + + listen-on port @EXTRAPORT1@ proxy plain { 10.53.0.3; }; + listen-on port @TLSPORT@ proxy encrypted tls self-signed { 10.53.0.3; }; + listen-on port @EXTRAPORT2@ proxy plain tls self-signed { 10.53.0.3; }; + listen-on port @HTTPSPORT@ proxy encrypted tls self-signed http default { 10.53.0.3; }; + listen-on port @EXTRAPORT3@ proxy plain tls self-signed http default { 10.53.0.3; }; + listen-on port @HTTPPORT@ proxy plain tls none http default { 10.53.0.3; }; + + listen-on-v6 port @EXTRAPORT1@ proxy plain { fd92:7065:b8e:ffff::3; }; + listen-on-v6 port @TLSPORT@ proxy encrypted tls self-signed { fd92:7065:b8e:ffff::3; }; + listen-on-v6 port @EXTRAPORT2@ proxy plain tls self-signed { fd92:7065:b8e:ffff::3; }; + listen-on-v6 port @HTTPSPORT@ proxy encrypted tls self-signed http default { fd92:7065:b8e:ffff::3; }; + listen-on-v6 port @EXTRAPORT3@ proxy plain tls self-signed http default { fd92:7065:b8e:ffff::3; }; + listen-on-v6 port @HTTPPORT@ proxy plain tls none http default { fd92:7065:b8e:ffff::3; }; + + recursion no; + notify explicit; + statistics-file "named.stats"; + dnssec-validation yes; + tcp-initial-timeout 1200; +}; + +trust-anchors { }; + +zone "example" { + type primary; + file "example.db"; + allow-query { any; }; +}; diff --git a/bin/tests/system/proxy/prereq.sh b/bin/tests/system/proxy/prereq.sh new file mode 100644 index 0000000..225c1e2 --- /dev/null +++ b/bin/tests/system/proxy/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$FEATURETEST --with-libnghttp2 || { + echo_i "This test requires libnghttp2 support." >&2 + exit 255 +} + +exit 0 diff --git a/bin/tests/system/proxy/self-signed-cert.pem b/bin/tests/system/proxy/self-signed-cert.pem new file mode 100644 index 0000000..0aeb46a --- /dev/null +++ b/bin/tests/system/proxy/self-signed-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWDCCAf+gAwIBAgIUXudNo4NQ7lRM1xFFJ4ugVtyCzKgwCgYIKoZIzj0EAwIw +gYExCzAJBgNVBAYTAlVBMRgwFgYDVQQIDA9LaGFya2l2IE9ibGFzdCcxEDAOBgNV +BAcMB0toYXJraXYxJDAiBgNVBAoMG0ludGVybmV0IFN5c3RlbXMgQ29uc29ydGl1 +bTEgMB4GA1UEAwwXc2VsZi5zaWduZWQuZXhhbXBsZS5jb20wHhcNMjMxMTE3MTU1 +NjI3WhcNNDQwNTMwMTU1NjI3WjCBgTELMAkGA1UEBhMCVUExGDAWBgNVBAgMD0to +YXJraXYgT2JsYXN0JzEQMA4GA1UEBwwHS2hhcmtpdjEkMCIGA1UECgwbSW50ZXJu +ZXQgU3lzdGVtcyBDb25zb3J0aXVtMSAwHgYDVQQDDBdzZWxmLnNpZ25lZC5leGFt +cGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNWscxXohNTBjcW4rhKD +ZbLi7IqI7WYe5lOS1CrukfYJuMM1+qjYnzO6Wg5qTwin/Cvr4/GTm95I64nZLPQz +CxajUzBRMB0GA1UdDgQWBBSnOr8xGlELdrcmyDIw9scsqn4UYjAfBgNVHSMEGDAW +gBSnOr8xGlELdrcmyDIw9scsqn4UYjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMCA0cAMEQCIG0OgexHV7bl/ZHd3Rn0VAudCHC7b1W2Sr6q+7kspLfhAiBemkVD +POeoih/7KT3yn8j90+WWVlzV+mpom3eaVkjjog== +-----END CERTIFICATE----- diff --git a/bin/tests/system/proxy/self-signed-key.pem b/bin/tests/system/proxy/self-signed-key.pem new file mode 100644 index 0000000..535f472 --- /dev/null +++ b/bin/tests/system/proxy/self-signed-key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHwX7CofJJGLEG6evl6h9WSmZ1q1HAOO+SKgvMiqCFcXoAoGCCqGSM49 +AwEHoUQDQgAE1axzFeiE1MGNxbiuEoNlsuLsiojtZh7mU5LUKu6R9gm4wzX6qNif +M7paDmpPCKf8K+vj8ZOb3kjridks9DMLFg== +-----END EC PRIVATE KEY----- diff --git a/bin/tests/system/proxy/setup.sh b/bin/tests/system/proxy/setup.sh new file mode 100644 index 0000000..7857c71 --- /dev/null +++ b/bin/tests/system/proxy/setup.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck disable=SC1091 +. ../conf.sh + +$SHELL "${TOP_SRCDIR}"/bin/tests/system/genzone.sh 2 >ns1/example.db +$SHELL "${TOP_SRCDIR}"/bin/tests/system/genzone.sh 2 >ns3/example.db + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns3/named.conf.in ns3/named.conf diff --git a/bin/tests/system/proxy/tests.sh b/bin/tests/system/proxy/tests.sh new file mode 100644 index 0000000..a62044c --- /dev/null +++ b/bin/tests/system/proxy/tests.sh @@ -0,0 +1,253 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck disable=SC1091 +. ../conf.sh + +dig_out_basename="dig.out.test" +testing="PROXY test" +fail_regex='(^(; EDE: 18 \(Prohibited\))|(; Transfer failed\.$))' + +dig_with_opts() { + # shellcheck disable=SC2086 + "$DIG" +noadd +nosea +nostat +noquest +nocmd +tries=1 "$@" +} + +status=0 +n=0 + +run_dig_test() { + test_message="$1" + shift + n=$((n + 1)) + echo_i "$test_message ($n)" + ret=0 + dig_failed=0 + dig_with_opts "$@" >"$dig_out_basename$n" || dig_failed=1 +} + +run_dig_test_expect_success() { + run_dig_test "$@" + if [ $dig_failed != 0 ]; then + ret=1 + elif ! [ -s "$dig_out_basename$n" ]; then + ret=1 + else + grep -E "$fail_regex" "$dig_out_basename$n" >/dev/null && ret=1 + fi + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +} + +run_dig_test_expect_failure() { + run_dig_test "$@" + if [ $dig_failed -eq 0 ] && [ -s "$dig_out_basename$n" ]; then + grep -E "$fail_regex" "$dig_out_basename$n" >/dev/null || ret=1 + fi + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +} + +run_dig_multitest_expect_success() { + message="$1" + shift + proxy_addrs="$1" + shift + run_dig_test_expect_success "$message (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +notcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.10 @10.53.0.1 +https "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.10 @10.53.0.1 +https "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTP)" -p "${HTTPPORT}" -b 10.53.0.10 @10.53.0.1 +http-plain "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +notcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_success "$message (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +http-plain "+proxy=$proxy_addrs" "$@" +} + +run_dig_multitest_expect_failure() { + message="$1" + shift + proxy_addrs="$1" + shift + run_dig_test_expect_failure "$message (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +notcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.10 @10.53.0.1 +https "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.10 @10.53.0.1 +https "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTP)" -p "${HTTPPORT}" -b 10.53.0.10 @10.53.0.1 +http-plain "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +notcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https "+proxy=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https "+proxy-plain=$proxy_addrs" "$@" + run_dig_test_expect_failure "$message (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +http-plain "+proxy=$proxy_addrs" "$@" +} + +# generic tests + +# Bind to the IP address that is allowed to send PROXYv2 +run_dig_test_expect_success "$testing: allow-proxy expect success (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +notcp +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.10 @10.53.0.1 +https +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.10 @10.53.0.1 +https +proxy-plain NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTP)" -p "${HTTPPORT}" -b 10.53.0.10 @10.53.0.1 +http-plain +proxy NS example0 + +run_dig_test_expect_success "$testing: allow-proxy expect success (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +notcp +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https +proxy NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +https +proxy-plain NS example0 +run_dig_test_expect_success "$testing: allow-proxy expect success (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +http-plain +proxy NS example0 + +# Bind to the IP address that is not allowed to send PROXYv2 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.11 @10.53.0.1 +notcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.11 @10.53.0.1 +tcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.11 @10.53.0.1 +tls +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.11 @10.53.0.1 +tls +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.11 @10.53.0.1 +https +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.11 @10.53.0.1 +https +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTP)" -p "${HTTPPORT}" -b 10.53.0.11 @10.53.0.1 +http-plain +proxy NS example0 + +run_dig_test_expect_failure "$testing: allow-proxy expect failure (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +notcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +tcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +tls +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +tls +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +https +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +https +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy expect failure (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::11 @fd92:7065:b8e:ffff::1 +http-plain +proxy NS example0 + +# Send a query to the interface that is not allowed to accept PROXYv2 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.2 +notcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.2 +tcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.2 +tls +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.2 +tls +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.10 @10.53.0.2 +https +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.10 @10.53.0.2 +https +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTP)" -p "${HTTPPORT}" -b 10.53.0.10 @10.53.0.2 +http-plain +proxy NS example0 + +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +notcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +tcp +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +tls +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +tls +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +https +proxy NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +https +proxy-plain NS example0 +run_dig_test_expect_failure "$testing: allow-proxy-on expect failure (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::2 +http-plain +proxy NS example0 + +## Now let's check if the addresses passed via PROXYv2 are getting used by BIND9. +run_dig_multitest_expect_success "check if IPv4 addresses are getting passed and accepted" "1.2.3.4-4.3.2.1" NS example1 +run_dig_multitest_expect_success "check if IPv6 addresses are getting passed and accepted" "fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321" NS example1 + +run_dig_multitest_expect_failure "check if IPv4 addresses are getting passed and rejected" "4.4.4.4-5.5.5.5" NS example1 +run_dig_multitest_expect_failure "check if IPv6 addresses are getting passed and rejected" "fd0f:99d3:98a7::4444-fd0f:99d3:98a7::5555" NS example1 + +run_dig_multitest_expect_failure "check if IPv4 addresses are getting passed and an unexpected source address is getting rejected" "4.4.4.4-4.3.2.1" NS example1 +run_dig_multitest_expect_failure "check if IPv6 addresses are getting passed and an unexpected source address is getting rejected" "fd0f:99d3:98a7::4444-fd0f:99d3:98a7::4321" NS example1 + +run_dig_multitest_expect_failure "check if IPv4 addresses are getting passed and an unexpected destination address is getting rejected" "1.2.3.4-5.5.5.5" NS example1 +run_dig_multitest_expect_failure "check if IPv6 addresses are getting passed and an unexpected destination address is getting rejected" "fd0f:99d3:98a7::1234-fd0f:99d3:98a7::5.5.5.5" NS example1 + +## Let's check if the real addresses are used by BIND9 for LOCAL requests +run_dig_multitest_expect_success "check if LOCAL PROXYv2 headers are accepted and real connection addresses are used" "" NS example2 + +## Let's check if BIND9 does not like suspicious PROXY headers with zeroed addresses or destination ports +run_dig_multitest_expect_failure "check if port 0 is not accepted when used in the destination IPv4 address" "1.2.3.4-4.3.2.1#0" NS example1 +run_dig_multitest_expect_failure "check if port 0 is not accepted when used in the destination IPv6 address" "fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#0" NS example1 + +run_dig_multitest_expect_failure "check if \"0.0.0.0\" is not accepted as a source address" "0.0.0.0-4.3.2.1" NS example1 +run_dig_multitest_expect_failure "check if \"::\" is not accepted as a source address" "::-fd0f:99d3:98a7::4321" NS example1 + +run_dig_multitest_expect_failure "check if \"0.0.0.0\" is not accepted as a destination address" "1.2.3.4-0.0.0.0" NS example1 +run_dig_multitest_expect_failure "check if \"::\" is not accepted as a destination address" "fd0f:99d3:98a7::1234-::" NS example1 + +# Let's verify that ports information from PROXY headers is being used by BIND +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy="1.2.3.4-4.3.2.1#53" AXFR example-proxy-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy="1.2.3.4-4.3.2.1#853" AXFR example-proxy-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain="1.2.3.4-4.3.2.1#853" AXFR example-proxy-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy="1.2.3.4-4.3.2.1#53" AXFR example-proxy-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy="1.2.3.4-4.3.2.1#853" AXFR example-proxy-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain="1.2.3.4-4.3.2.1#853" AXFR example-proxy-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#53" AXFR example-proxy-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#853" AXFR example-proxy-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#853" AXFR example-proxy-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#53" AXFR example-proxy-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#853" AXFR example-proxy-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#853" AXFR example-proxy-plain-dot + +# Let's use a wrong ports to see if BIND will reject the queries (as it should) +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-do53 +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-encrypted-dot +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-plain-dot + +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-do53 +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-encrypted-dot +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND for rejection (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain="1.2.3.4-4.3.2.1#1234" AXFR example-proxy-plain-dot + +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-do53 +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-encrypted-dot +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-plain-dot + +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-do53 +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-encrypted-dot +run_dig_test_expect_failure "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND for rejection (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain="fd0f:99d3:98a7::1234-fd0f:99d3:98a7::4321#1234" AXFR example-proxy-plain-dot + +# Now let's make something similar, but for LOCAL PROXY requests +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy AXFR example-proxy-local-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy AXFR example-proxy-local-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain AXFR example-proxy-local-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy AXFR example-proxy-local-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy AXFR example-proxy-local-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv4 addresses is being used by BIND (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain AXFR example-proxy-local-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.1 +tcp +proxy AXFR example-proxy-local-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.1 +tls +proxy AXFR example-proxy-local-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.1 +tls +proxy-plain AXFR example-proxy-local-plain-dot + +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tcp +proxy AXFR example-proxy-local-do53 +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy AXFR example-proxy-local-encrypted-dot +run_dig_test_expect_success "$testing: check if ports information from a PROXYv2 header with IPv6 addresses is being used by BIND (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::1 +tls +proxy-plain AXFR example-proxy-local-plain-dot + +# verify that by default PROXYv2 is not accepted +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (UDP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.3 +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TCP)" -p "${EXTRAPORT1}" -b 10.53.0.10 @10.53.0.3 +tcp +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TLS/PROXY encrypted)" -p "${TLSPORT}" -b 10.53.0.10 @10.53.0.3 +tls +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TLS/PROXY plain)" -p "${EXTRAPORT2}" -b 10.53.0.10 @10.53.0.3 +tls +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTPS/PROXY encrypted)" -p "${HTTPSPORT}" -b 10.53.0.10 @10.53.0.3 +https +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTPS/PROXY plain)" -p "${EXTRAPORT3}" -b 10.53.0.10 @10.53.0.3 +https +proxy-plain NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTP)" -p "${HTTPPORT}" -b 10.53.0.10 @10.53.0.3 +https +proxy NS example + +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (UDP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TCP, IPv6)" -p "${EXTRAPORT1}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +tcp +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TLS/PROXY encrypted, IPv6)" -p "${TLSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +tls +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (TLS/PROXY plain, IPv6)" -p "${EXTRAPORT2}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +tls +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTPS/PROXY encrypted, IPv6)" -p "${HTTPSPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +https +proxy NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTPS/PROXY plain, IPv6)" -p "${EXTRAPORT3}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +https +proxy-plain NS example +run_dig_test_expect_failure "$testing: check if BIND does not accept PROXYv2 by default (HTTP, IPv6)" -p "${HTTPPORT}" -b fd92:7065:b8e:ffff::10 @fd92:7065:b8e:ffff::3 +https +proxy NS example + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/proxy/tests_sh_proxy.py b/bin/tests/system/proxy/tests_sh_proxy.py new file mode 100644 index 0000000..98239f2 --- /dev/null +++ b/bin/tests/system/proxy/tests_sh_proxy.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns*/example.db", + ] +) + + +def test_proxy(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/pytest.ini b/bin/tests/system/pytest.ini new file mode 100644 index 0000000..5574b3e --- /dev/null +++ b/bin/tests/system/pytest.ini @@ -0,0 +1,24 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +[pytest] +addopts = --tb=short -rA -vv +log_format = %(asctime)s %(levelname)s:%(name)s %(message)s +log_date_format = %Y-%m-%d %H:%M:%S +log_cli = 1 +log_level = INFO +python_files = tests_*.py +junit_logging = log +junit_log_passing_tests = 0 +markers = + requires_zones_loaded: ensures the test does not start until the specified named instances load all configured zones + algorithm_set: use to select desired algorithms from isctest/vars/algorithms.py + extra_artifacts: list of files (globs) that are expected to appear in the test directory after the test is run diff --git a/bin/tests/system/qmin/ans2/1.0.0.2.ip6.arpa.db b/bin/tests/system/qmin/ans2/1.0.0.2.ip6.arpa.db new file mode 100644 index 0000000..7042434 --- /dev/null +++ b/bin/tests/system/qmin/ans2/1.0.0.2.ip6.arpa.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 30 SOA ns2.good. hostmaster.arpa. 2018050100 1 1 1 1 +@ 30 NS ns2.good. + +8.2.6.0 60 NS ns3.good. + +1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0 1 PTR nee.com. diff --git a/bin/tests/system/qmin/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py new file mode 100644 index 0000000..18f0777 --- /dev/null +++ b/bin/tests/system/qmin/ans2/ans.py @@ -0,0 +1,115 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from typing import AsyncGenerator + +import dns.message +import dns.name +import dns.rcode +import dns.rdataclass +import dns.rdatatype + +from isctest.asyncserver import ( + AsyncDnsServer, + DnsResponseSend, + DomainHandler, + QueryContext, + ResponseAction, +) + +from qmin_ans import ( + DelayedResponseHandler, + EntRcodeChanger, + QueryLogHandler, + log_query, +) + + +class QueryLogger(QueryLogHandler): + domains = ["1.0.0.2.ip6.arpa.", "fwd.", "good."] + + +class BadHandler(EntRcodeChanger): + domains = ["bad."] + rcode = dns.rcode.NXDOMAIN + + +class UglyHandler(EntRcodeChanger): + domains = ["ugly."] + rcode = dns.rcode.FORMERR + + +class SlowHandler(DelayedResponseHandler): + domains = ["slow."] + delay = 0.2 + + +def send_delegation( + qctx: QueryContext, zone_cut: dns.name.Name, target_addr: str +) -> ResponseAction: + """ + Delegate `zone_cut` to a single in-bailiwick name server, `ns.`, + with a single IPv4 glue record (provided in `target_addr`) included in the + ADDITIONAL section. + """ + ns_name = "ns." + zone_cut.to_text() + ns_rrset = dns.rrset.from_text( + zone_cut, 2, dns.rdataclass.IN, dns.rdatatype.NS, ns_name + ) + a_rrset = dns.rrset.from_text( + ns_name, 2, dns.rdataclass.IN, dns.rdatatype.A, target_addr + ) + + response = dns.message.make_response(qctx.query) + response.set_rcode(dns.rcode.NOERROR) + response.authority.append(ns_rrset) + response.additional.append(a_rrset) + + return DnsResponseSend(response, authoritative=False) + + +class StaleHandler(DomainHandler): + """ + `a.b.stale` is a subdomain of `b.stale` and these two subdomains need to be + delegated to different name servers. Therefore, their delegations cannot + be placed in the zone file because the zone cut at `b.stale` would occlude + the one at `a.b.stale`. Generate these delegations dynamically depending + on the QNAME. + """ + + domains = ["stale."] + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + log_query(qctx) + a_b_stale = dns.name.from_text("a.b.stale.") + b_stale = dns.name.from_text("b.stale.") + if qctx.qname.is_subdomain(a_b_stale): + yield send_delegation(qctx, a_b_stale, "10.53.0.3") + elif qctx.qname.is_subdomain(b_stale): + yield send_delegation(qctx, b_stale, "10.53.0.4") + + +def main() -> None: + server = AsyncDnsServer() + server.install_response_handler(QueryLogger()) + server.install_response_handler(BadHandler()) + server.install_response_handler(UglyHandler()) + server.install_response_handler(SlowHandler()) + server.install_response_handler(StaleHandler()) + server.run() + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/qmin/ans2/bad.db b/bin/tests/system/qmin/ans2/bad.db new file mode 100644 index 0000000..54a20e6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/bad.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1 + +@ 30 NS ns2 +ns2 30 A 10.53.0.2 + 30 AAAA fd92:7065:b8e:ffff::2 + +zoop.boing 30 NS ns3 +ns3 30 A 10.53.0.3 + 30 AAAA fd92:7065:b8e:ffff::3 + +ns4 30 A 10.53.0.4 + 30 AAAA fd92:7065:b8e:ffff::4 + +a.bit.longer.ns.name 1 A 10.53.0.4 + 1 AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/qmin/ans2/fwd.db b/bin/tests/system/qmin/ans2/fwd.db new file mode 100644 index 0000000..54a20e6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/fwd.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1 + +@ 30 NS ns2 +ns2 30 A 10.53.0.2 + 30 AAAA fd92:7065:b8e:ffff::2 + +zoop.boing 30 NS ns3 +ns3 30 A 10.53.0.3 + 30 AAAA fd92:7065:b8e:ffff::3 + +ns4 30 A 10.53.0.4 + 30 AAAA fd92:7065:b8e:ffff::4 + +a.bit.longer.ns.name 1 A 10.53.0.4 + 1 AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/qmin/ans2/good.db b/bin/tests/system/qmin/ans2/good.db new file mode 100644 index 0000000..54a20e6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/good.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1 + +@ 30 NS ns2 +ns2 30 A 10.53.0.2 + 30 AAAA fd92:7065:b8e:ffff::2 + +zoop.boing 30 NS ns3 +ns3 30 A 10.53.0.3 + 30 AAAA fd92:7065:b8e:ffff::3 + +ns4 30 A 10.53.0.4 + 30 AAAA fd92:7065:b8e:ffff::4 + +a.bit.longer.ns.name 1 A 10.53.0.4 + 1 AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/qmin/ans2/slow.db b/bin/tests/system/qmin/ans2/slow.db new file mode 100644 index 0000000..54a20e6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/slow.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1 + +@ 30 NS ns2 +ns2 30 A 10.53.0.2 + 30 AAAA fd92:7065:b8e:ffff::2 + +zoop.boing 30 NS ns3 +ns3 30 A 10.53.0.3 + 30 AAAA fd92:7065:b8e:ffff::3 + +ns4 30 A 10.53.0.4 + 30 AAAA fd92:7065:b8e:ffff::4 + +a.bit.longer.ns.name 1 A 10.53.0.4 + 1 AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/qmin/ans2/stale.db b/bin/tests/system/qmin/ans2/stale.db new file mode 100644 index 0000000..b1b1ac6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/stale.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 2 SOA ns2 hostmaster.stale. 1 2 3 4 5 +@ 2 NS ns2 +ns2 2 A 10.53.0.2 + 2 AAAA fd92:7065:b8e:ffff::2 diff --git a/bin/tests/system/qmin/ans2/ugly.db b/bin/tests/system/qmin/ans2/ugly.db new file mode 100644 index 0000000..54a20e6 --- /dev/null +++ b/bin/tests/system/qmin/ans2/ugly.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1 + +@ 30 NS ns2 +ns2 30 A 10.53.0.2 + 30 AAAA fd92:7065:b8e:ffff::2 + +zoop.boing 30 NS ns3 +ns3 30 A 10.53.0.3 + 30 AAAA fd92:7065:b8e:ffff::3 + +ns4 30 A 10.53.0.4 + 30 AAAA fd92:7065:b8e:ffff::4 + +a.bit.longer.ns.name 1 A 10.53.0.4 + 1 AAAA fd92:7065:b8e:ffff::4 diff --git a/bin/tests/system/qmin/ans3/8.2.6.0.1.0.0.2.ip6.arpa.db b/bin/tests/system/qmin/ans3/8.2.6.0.1.0.0.2.ip6.arpa.db new file mode 100644 index 0000000..e50c75c --- /dev/null +++ b/bin/tests/system/qmin/ans3/8.2.6.0.1.0.0.2.ip6.arpa.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 30 SOA ns3.good. hostmaster.arpa. 2018050100 1 1 1 1 +@ 30 NS ns3.good. + +1.1.1.1 60 NS ns4.good. diff --git a/bin/tests/system/qmin/ans3/a.b.stale.db b/bin/tests/system/qmin/ans3/a.b.stale.db new file mode 100644 index 0000000..e595890 --- /dev/null +++ b/bin/tests/system/qmin/ans3/a.b.stale.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns hostmaster.a.b.stale. 1 2 3 4 5 +@ 1 NS ns +@ 1 TXT "peekaboo" +ns 1 A 10.53.0.3 diff --git a/bin/tests/system/qmin/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py new file mode 100644 index 0000000..6547dd2 --- /dev/null +++ b/bin/tests/system/qmin/ans3/ans.py @@ -0,0 +1,50 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +import dns.rcode + +from isctest.asyncserver import AsyncDnsServer + +from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler + + +class QueryLogger(QueryLogHandler): + domains = ["8.2.6.0.1.0.0.2.ip6.arpa.", "a.b.stale.", "zoop.boing.good."] + + +class ZoopBoingBadHandler(EntRcodeChanger): + domains = ["zoop.boing.bad."] + rcode = dns.rcode.NXDOMAIN + + +class ZoopBoingUglyHandler(EntRcodeChanger): + domains = ["zoop.boing.ugly."] + rcode = dns.rcode.FORMERR + + +class ZoopBoingSlowHandler(DelayedResponseHandler): + domains = ["zoop.boing.slow."] + delay = 0.4 + + +def main() -> None: + server = AsyncDnsServer() + server.install_response_handler(QueryLogger()) + server.install_response_handler(ZoopBoingBadHandler()) + server.install_response_handler(ZoopBoingUglyHandler()) + server.install_response_handler(ZoopBoingSlowHandler()) + server.run() + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/qmin/ans3/zoop.boing.bad.db b/bin/tests/system/qmin/ans3/zoop.boing.bad.db new file mode 100644 index 0000000..c3a5b52 --- /dev/null +++ b/bin/tests/system/qmin/ans3/zoop.boing.bad.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns3.bad. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS ns3.bad. +icky.ptang 1 NS a.bit.longer.ns.name.bad. diff --git a/bin/tests/system/qmin/ans3/zoop.boing.good.db b/bin/tests/system/qmin/ans3/zoop.boing.good.db new file mode 100644 index 0000000..cc4a3eb --- /dev/null +++ b/bin/tests/system/qmin/ans3/zoop.boing.good.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns3.good. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS ns3.good. +icky.ptang 1 NS a.bit.longer.ns.name.good. diff --git a/bin/tests/system/qmin/ans3/zoop.boing.slow.db b/bin/tests/system/qmin/ans3/zoop.boing.slow.db new file mode 100644 index 0000000..67635bb --- /dev/null +++ b/bin/tests/system/qmin/ans3/zoop.boing.slow.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns3.slow. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS ns3.slow. +icky.ptang 1 NS a.bit.longer.ns.name.slow. diff --git a/bin/tests/system/qmin/ans3/zoop.boing.ugly.db b/bin/tests/system/qmin/ans3/zoop.boing.ugly.db new file mode 100644 index 0000000..27c5ee0 --- /dev/null +++ b/bin/tests/system/qmin/ans3/zoop.boing.ugly.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns3.ugly. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS ns3.ugly. +icky.ptang 1 NS a.bit.longer.ns.name.ugly. diff --git a/bin/tests/system/qmin/ans4/1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.db b/bin/tests/system/qmin/ans4/1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.db new file mode 100644 index 0000000..f4058b3 --- /dev/null +++ b/bin/tests/system/qmin/ans4/1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 30 SOA ns4.good. hostmaster.arpa. 2018050100 1 1 1 1 +@ 30 NS ns4.good. + +test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4 1 TXT "long_ip6_name" diff --git a/bin/tests/system/qmin/ans4/a.b.stale.db b/bin/tests/system/qmin/ans4/a.b.stale.db new file mode 100644 index 0000000..68e63ce --- /dev/null +++ b/bin/tests/system/qmin/ans4/a.b.stale.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns hostmaster.a.b.stale. 1 2 3 4 5 +@ 1 NS ns +ns 1 A 10.53.0.4 +@ 1 TXT "hooray" diff --git a/bin/tests/system/qmin/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py new file mode 100644 index 0000000..ebe500b --- /dev/null +++ b/bin/tests/system/qmin/ans4/ans.py @@ -0,0 +1,97 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from typing import AsyncGenerator + +import dns.rcode + +from isctest.asyncserver import ( + AsyncDnsServer, + DnsResponseSend, + DomainHandler, + QueryContext, + ResponseAction, +) + +from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler, log_query + + +class QueryLogger(QueryLogHandler): + domains = [ + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + "icky.ptang.zoop.boing.good.", + ] + + +class StaleHandler(DomainHandler): + """ + The test code relies on this server returning non-minimal (i.e. including + address records in the ADDITIONAL section) responses to NS queries for + `b.stale` and `a.b.stale`. While this logic (returning non-minimal + responses to NS queries) could be implemented in AsyncDnsServer itself, + doing so breaks a lot of other checks in this system test. Therefore, only + these two zones behave in this particular way, thanks to a custom response + handler implemented below. + """ + + domains = ["b.stale", "a.b.stale"] + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + log_query(qctx) + + if qctx.qtype == dns.rdatatype.NS: + assert qctx.zone + assert qctx.response.answer[0] + + for nameserver in qctx.response.answer[0]: + if not nameserver.target.is_subdomain(qctx.response.answer[0].name): + continue + glue_a = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.A) + if glue_a: + qctx.response.additional.append(glue_a) + glue_aaaa = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.AAAA) + if glue_aaaa: + qctx.response.additional.append(glue_aaaa) + + yield DnsResponseSend(qctx.response) + + +class IckyPtangZoopBoingBadHandler(EntRcodeChanger): + domains = ["icky.ptang.zoop.boing.bad."] + rcode = dns.rcode.NXDOMAIN + + +class IckyPtangZoopBoingUglyHandler(EntRcodeChanger): + domains = ["icky.ptang.zoop.boing.ugly."] + rcode = dns.rcode.FORMERR + + +class IckyPtangZoopBoingSlowHandler(DelayedResponseHandler): + domains = ["icky.ptang.zoop.boing.slow."] + delay = 0.4 + + +def main() -> None: + server = AsyncDnsServer() + server.install_response_handler(QueryLogger()) + server.install_response_handler(StaleHandler()) + server.install_response_handler(IckyPtangZoopBoingBadHandler()) + server.install_response_handler(IckyPtangZoopBoingUglyHandler()) + server.install_response_handler(IckyPtangZoopBoingSlowHandler()) + server.run() + + +if __name__ == "__main__": + main() diff --git a/bin/tests/system/qmin/ans4/b.stale.db b/bin/tests/system/qmin/ans4/b.stale.db new file mode 100644 index 0000000..4dda578 --- /dev/null +++ b/bin/tests/system/qmin/ans4/b.stale.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns hostmaster.b.stale. 1 2 3 4 5 +@ 1 NS ns +ns 1 A 10.53.0.4 +a 1 NS ns.a +ns.a 1 A 10.53.0.4 diff --git a/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.bad.db b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.bad.db new file mode 100644 index 0000000..a5d4d08 --- /dev/null +++ b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.bad.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns4.bad. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS a.bit.longer.ns.name.bad. +icky.icky 1 A 192.0.2.1 +more.icky.icky 1 A 192.0.2.2 diff --git a/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.good.db b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.good.db new file mode 100644 index 0000000..152451a --- /dev/null +++ b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.good.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns4.good. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS a.bit.longer.ns.name.good. +icky.icky 1 A 192.0.2.1 +more.icky.icky 1 A 192.0.2.2 diff --git a/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.slow.db b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.slow.db new file mode 100644 index 0000000..091cca4 --- /dev/null +++ b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.slow.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns4.slow. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS a.bit.longer.ns.name.slow. +icky.icky 1 A 192.0.2.1 +more.icky.icky 1 A 192.0.2.2 diff --git a/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.ugly.db b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.ugly.db new file mode 100644 index 0000000..fbc71d1 --- /dev/null +++ b/bin/tests/system/qmin/ans4/icky.ptang.zoop.boing.ugly.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 1 SOA ns4.ugly. hostmaster.arpa. 2018050100 1 1 1 1 +@ 1 NS a.bit.longer.ns.name.ugly. +icky.icky 1 A 192.0.2.1 +more.icky.icky 1 A 192.0.2.2 diff --git a/bin/tests/system/qmin/ns1/named.conf.j2 b/bin/tests/system/qmin/ns1/named.conf.j2 new file mode 100644 index 0000000..e366cca --- /dev/null +++ b/bin/tests/system/qmin/ns1/named.conf.j2 @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/qmin/ns1/root.db b/bin/tests/system/qmin/ns1/root.db new file mode 100644 index 0000000..3854fc8 --- /dev/null +++ b/bin/tests/system/qmin/ns1/root.db @@ -0,0 +1,44 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +. IN SOA wpk.isc.org. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +ip6.arpa. NS ns2.good. + +good. NS ns2.good. +ns2.good. A 10.53.0.2 + +bad. NS ns2.bad. +ns2.bad. A 10.53.0.2 + +slow NS ns2.slow. +ns2.slow. A 10.53.0.2 + +ugly. NS ns2.ugly. +ns2.ugly. A 10.53.0.2 + +fwd. NS ns2.fwd. +ns2.fwd. A 10.53.0.2 + +$TTL 2 +stale. NS ns2.stale. +ns2.stale. A 10.53.0.2 + +in-addr.arpa. NS ns5.in-addr.arpa. +ns5.in-addr.arpa. A 10.53.0.5 diff --git a/bin/tests/system/qmin/ns5/in-addr.arpa.db b/bin/tests/system/qmin/ns5/in-addr.arpa.db new file mode 100644 index 0000000..1866d06 --- /dev/null +++ b/bin/tests/system/qmin/ns5/in-addr.arpa.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 20 +@ IN SOA wpk.isc.org. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 2 ; minimum + ) +@ NS ns5 +ns5 A 10.53.0.5 diff --git a/bin/tests/system/qmin/ns5/named.conf.j2 b/bin/tests/system/qmin/ns5/named.conf.j2 new file mode 100644 index 0000000..f2382e5 --- /dev/null +++ b/bin/tests/system/qmin/ns5/named.conf.j2 @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization disabled; + querylog yes; + resolver-query-timeout 30000; # 30 seconds + dnssec-validation no; + disable-empty-zone 10.in-addr.arpa; + fetches-per-zone 40; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "in-addr.arpa" { + type primary; + file "in-addr.arpa.db"; +}; diff --git a/bin/tests/system/qmin/ns6/named.conf.j2 b/bin/tests/system/qmin/ns6/named.conf.j2 new file mode 100644 index 0000000..6301fb2 --- /dev/null +++ b/bin/tests/system/qmin/ns6/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization strict; + querylog yes; + resolver-query-timeout 30000; # 30 seconds + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/qmin/ns7/named.conf.j2 b/bin/tests/system/qmin/ns7/named.conf.j2 new file mode 100644 index 0000000..b6bf4c6 --- /dev/null +++ b/bin/tests/system/qmin/ns7/named.conf.j2 @@ -0,0 +1,52 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS7 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + recursion yes; + qname-minimization relaxed; + querylog yes; + resolver-query-timeout 30000; # 30 seconds + dnssec-validation no; + disable-empty-zone 10.in-addr.arpa; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "fwd." IN { + type forward; + forwarders { + 10.53.0.2; + }; + forward only; +}; diff --git a/bin/tests/system/qmin/prereq.sh b/bin/tests/system/qmin/prereq.sh new file mode 100644 index 0000000..b6b005f --- /dev/null +++ b/bin/tests/system/qmin/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PYTHON} -c 'import dns'; then + echo_i "python dns module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/qmin/qmin_ans.py b/bin/tests/system/qmin/qmin_ans.py new file mode 100644 index 0000000..c610eb5 --- /dev/null +++ b/bin/tests/system/qmin/qmin_ans.py @@ -0,0 +1,107 @@ +""" +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. +""" + +from typing import AsyncGenerator + +import abc + +import dns.rcode +import dns.rdataclass +import dns.rdatatype + +from isctest.asyncserver import ( + DnsResponseSend, + DomainHandler, + QueryContext, + ResponseAction, +) + +from isctest.compat import dns_rcode + + +def log_query(qctx: QueryContext) -> None: + """ + Log a received DNS query to a text file inspected by `tests.sh`. AAAA and + A queries are logged identically because the relative order in which they + are received does not matter. + """ + qname = qctx.qname.to_text() + qtype = dns.rdatatype.to_text(qctx.qtype) + if qtype in ("A", "AAAA"): + qtype = "ADDR" + + with open("query.log", "a", encoding="utf-8") as query_log: + print(f"{qtype} {qname}", file=query_log) + + +class QueryLogHandler(DomainHandler): + """ + Log all received DNS queries to a text file. Use the zone file for + preparing responses. + """ + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + log_query(qctx) + yield DnsResponseSend(qctx.response) + + +class EntRcodeChanger(DomainHandler): + """ + Log all received DNS queries to a text file. Use the zone file for + preparing responses, but override the RCODE returned for empty + non-terminals (ENTs) to the value specified by the child class. This + emulates broken authoritative servers. + """ + + @property + @abc.abstractmethod + def rcode(self) -> dns_rcode: + raise NotImplementedError + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + assert qctx.zone + + log_query(qctx) + + if ( + qctx.response.rcode() == dns.rcode.NOERROR + and not qctx.response.answer + and qctx.response.authority + and qctx.response.authority[0].rdtype == dns.rdatatype.SOA + and not qctx.zone.get_node(qctx.qname) + ): + qctx.response.set_rcode(self.rcode) + yield DnsResponseSend(qctx.response) + + +class DelayedResponseHandler(DomainHandler): + """ + Log all received DNS queries to a text file. Use the zone file for + preparing responses, but delay sending every answer by the amount of time + specified (in seconds) by the child class. This emulates network delays. + """ + + @property + @abc.abstractmethod + def delay(self) -> float: + raise NotImplementedError + + async def get_responses( + self, qctx: QueryContext + ) -> AsyncGenerator[ResponseAction, None]: + log_query(qctx) + yield DnsResponseSend(qctx.response, delay=self.delay) diff --git a/bin/tests/system/qmin/tests.sh b/bin/tests/system/qmin/tests.sh new file mode 100755 index 0000000..6cf8d2b --- /dev/null +++ b/bin/tests/system/qmin/tests.sh @@ -0,0 +1,575 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="-p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" +CLEANQL="rm -f ans*/query.log" +status=0 +n=0 + +n=$((n + 1)) +echo_i "query for .good is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.5 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +cat <<__EOF | diff ans2/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.good. +ADDR ns3.good. +ADDR ns3.good. +ADDR a.bit.longer.ns.name.good. +ADDR a.bit.longer.ns.name.good. +__EOF +echo "ADDR icky.icky.icky.ptang.zoop.boing.good." | diff ans3/query.log - >/dev/null || ret=1 +echo "ADDR icky.icky.icky.ptang.zoop.boing.good." | diff ans4/query.log - >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .bad is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.5 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +cat <<__EOF | diff ans2/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.bad. +ADDR ns3.bad. +ADDR ns3.bad. +ADDR a.bit.longer.ns.name.bad. +ADDR a.bit.longer.ns.name.bad. +__EOF +echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | diff ans3/query.log - >/dev/null || ret=1 +echo "ADDR icky.icky.icky.ptang.zoop.boing.bad." | diff ans4/query.log - >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .slow is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.5 >dig.out.test$n || ret=1 +sleep 5 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.slow. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +cat <<__EOF | diff ans2/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.slow. +ADDR ns3.slow. +ADDR ns3.slow. +ADDR a.bit.longer.ns.name.slow. +ADDR a.bit.longer.ns.name.slow. +__EOF +echo "ADDR icky.icky.icky.ptang.zoop.boing.slow." | diff ans3/query.log - >/dev/null || ret=1 +echo "ADDR icky.icky.icky.ptang.zoop.boing.slow." | diff ans4/query.log - >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .ugly is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.5 >dig.out.test$n || ret=1 +sleep 5 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +cat <<__EOF | diff ans2/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.ugly. +ADDR ns3.ugly. +ADDR ns3.ugly. +ADDR a.bit.longer.ns.name.ugly. +ADDR a.bit.longer.ns.name.ugly. +__EOF +echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - >/dev/null || ret=1 +echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .good is properly minimized when qname-minimization is in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.good. +ADDR a.bit.longer.ns.name.good. +ADDR ns2.good. +ADDR ns3.good. +ADDR ns3.good. +NS bit.longer.ns.name.good. +NS boing.good. +NS good. +NS longer.ns.name.good. +NS name.good. +NS ns.name.good. +NS zoop.boing.good. +__EOF +cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1 +NS zoop.boing.good. +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. +__EOF +cat <<__EOF | diff ans4/query.log - >/dev/null || ret=1 +NS icky.ptang.zoop.boing.good. +NS icky.icky.ptang.zoop.boing.good. +ADDR icky.icky.icky.ptang.zoop.boing.good. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .good is properly minimized when qname-minimization is in relaxed mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.7 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.good. +ADDR a.bit.longer.ns.name.good. +ADDR ns2.good. +ADDR ns3.good. +ADDR ns3.good. +NS bit.longer.ns.name.good. +NS boing.good. +NS longer.ns.name.good. +NS name.good. +NS ns.name.good. +NS zoop.boing.good. +__EOF +cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1 +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. +__EOF +cat <<__EOF | diff ans4/query.log - >/dev/null || ret=1 +NS icky.icky.ptang.zoop.boing.good. +ADDR icky.icky.icky.ptang.zoop.boing.good. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .bad fails when qname-minimization is in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns2.bad. +NS bad. +NS boing.bad. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .bad succeeds when qname-minimization is in relaxed mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.7 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.bad. +ADDR a.bit.longer.ns.name.bad. +ADDR icky.icky.icky.ptang.zoop.boing.bad. +ADDR ns2.bad. +ADDR ns3.bad. +ADDR ns3.bad. +NS boing.bad. +NS name.bad. +__EOF +cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.bad. +__EOF +cat <<__EOF | diff ans4/query.log - >/dev/null || ret=1 +ADDR icky.icky.icky.ptang.zoop.boing.bad. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .ugly fails when qname-minimization is in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.6 >dig.out.test$n || ret=1 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns2.ugly. +NS boing.ugly. +NS ugly. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +$RNDCCMD 10.53.0.6 flush + +n=$((n + 1)) +echo_i "query for .ugly succeeds when qname-minimization is in relaxed mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.7 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.ugly. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.ugly. +ADDR a.bit.longer.ns.name.ugly. +ADDR icky.icky.icky.ptang.zoop.boing.ugly. +ADDR ns2.ugly. +ADDR ns3.ugly. +ADDR ns3.ugly. +NS boing.ugly. +NS name.ugly. +NS name.ugly. +__EOF +echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - >/dev/null || ret=1 +echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +$RNDCCMD 10.53.0.7 flush + +n=$((n + 1)) +echo_i "information that minimization was unsuccessful for .ugly is logged in relaxed mode ($n)" +ret=0 +wait_for_log 5 "success resolving 'icky.icky.icky.ptang.zoop.boing.ugly/A' after disabling qname minimization" ns7/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .slow is properly minimized when qname-minimization is on ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.slow. @10.53.0.6 >dig.out.test$n || ret=1 +sleep 5 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "icky.icky.icky.ptang.zoop.boing.slow. 1 IN A 192.0.2.1" dig.out.test$n >/dev/null || ret=1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.slow. +ADDR a.bit.longer.ns.name.slow. +ADDR ns2.slow. +ADDR ns3.slow. +ADDR ns3.slow. +NS bit.longer.ns.name.slow. +NS boing.slow. +NS longer.ns.name.slow. +NS name.slow. +NS ns.name.slow. +NS slow. +NS zoop.boing.slow. +__EOF +cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1 +NS zoop.boing.slow. +NS ptang.zoop.boing.slow. +NS icky.ptang.zoop.boing.slow. +__EOF +cat <<__EOF | diff ans4/query.log - >/dev/null || ret=1 +NS icky.ptang.zoop.boing.slow. +NS icky.icky.ptang.zoop.boing.slow. +ADDR icky.icky.icky.ptang.zoop.boing.slow. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .ip6.arpa succeeds and skips on proper boundaries when qname-minimization is on ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.6 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. 1 IN PTR nee.com." dig.out.test$n >/dev/null || ret=1 +sleep 1 +grep -F "ip6.arpa." ans2/query.log >ans2/query.log.trimmed +cat <<__EOF | diff ans2/query.log.trimmed - >/dev/null || ret=1 +NS 1.0.0.2.ip6.arpa. +NS 8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +NS 0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +PTR 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for multiple label name skips after 7th label ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS more.icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "more.icky.icky.icky.ptang.zoop.boing.good. 1 IN A 192.0.2.2" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.good. +ADDR a.bit.longer.ns.name.good. +ADDR ns2.good. +ADDR ns3.good. +ADDR ns3.good. +NS bit.longer.ns.name.good. +NS boing.good. +NS good. +NS longer.ns.name.good. +NS name.good. +NS ns.name.good. +NS zoop.boing.good. +__EOF +cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1 +NS zoop.boing.good. +NS ptang.zoop.boing.good. +NS icky.ptang.zoop.boing.good. +__EOF +# There's no NS icky.icky.icky.ptang.zoop.boing.good. query - we skipped it. +cat <<__EOF | diff ans4/query.log - >/dev/null || ret=1 +NS icky.ptang.zoop.boing.good. +NS icky.icky.ptang.zoop.boing.good. +ADDR more.icky.icky.icky.ptang.zoop.boing.good. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "qname minimization is disabled when forwarding ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS a.bit.longer.ns.name.fwd. @10.53.0.7 >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a.bit.longer.ns.name.fwd. 1 IN A 10.53.0.4" dig.out.test$n >/dev/null || ret=1 +sleep 1 +cat <<__EOF | diff ans2/query.log - >/dev/null || ret=1 +ADDR a.bit.longer.ns.name.fwd. +__EOF +for ans in ans2; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "qname minimization resolves unusual ip6.arpa. names ($n)" +ret=0 +$CLEANQL +$DIG $DIGOPTS test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa. txt @10.53.0.7 >dig.out.test$n 2>&1 || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +# Expected output in dig.out.test$n: +# ;; ANSWER SECTION: +# test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa. 1 IN TXT "long_ip6_name" +grep 'ip6\.arpa.*TXT.*long_ip6_name' dig.out.test$n >/dev/null || ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Below are test cases for GL #2665: The QNAME minimization (if enabled) should +# also occur on the second query, after the RRsets have expired from cache. +# BIND will still have the entries in cache, but marked stale. These stale +# entries should not prevent the resolver from minimizing the QNAME. +# We query for the test domain a.b.stale. in all cases (QNAME minimization off, +# strict mode, and relaxed mode) and expect it to behave the same the second +# time when we have a stale delegation structure in cache. +n=$((n + 1)) +echo_i "query for .stale is not minimized when qname-minimization is off ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.5 flush +$DIG $DIGOPTS @10.53.0.5 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*peekaboo" dig.out.test$n >/dev/null || ret=1 +sleep 1 +echo "TXT a.b.stale." | diff ans2/query.log - >/dev/null || ret=1 +echo "TXT a.b.stale." | diff ans3/query.log - >/dev/null || ret=1 +test -f ans4/query.log && ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .stale is properly minimized when qname-minimization is in strict mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS @10.53.0.6 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +ADDR ns2.stale. +NS b.stale. +NS stale. +__EOF +test -f ans3/query.log && ret=1 +sort ans4/query.log >ans4/query.log.sorted +cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +NS b.stale. +TXT a.b.stale. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .stale is properly minimized when qname-minimization is in relaxed mode ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS @10.53.0.7 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +ADDR ns2.stale. +NS b.stale. +__EOF +test -f ans3/query.log && ret=1 +sort ans4/query.log >ans4/query.log.sorted +cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +TXT a.b.stale. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sleep 2, allow entries in cache to go stale" +sleep 2 + +n=$((n + 1)) +echo_i "query for .stale is not minimized when qname-minimization is off (stale cache) ($n)" +ret=0 +$CLEANQL +$DIG $DIGOPTS @10.53.0.5 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*peekaboo" dig.out.test$n >/dev/null || ret=1 +sleep 1 +echo "TXT a.b.stale." | diff ans2/query.log - >/dev/null || ret=1 +echo "TXT a.b.stale." | diff ans3/query.log - >/dev/null || ret=1 +test -f ans4/query.log && ret=1 +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .stale is properly minimized when qname-minimization is in strict mode (stale cache) ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.6 flush +$DIG $DIGOPTS @10.53.0.6 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +ADDR ns2.stale. +NS b.stale. +NS stale. +__EOF +test -f ans3/query.log && ret=1 +sort ans4/query.log >ans4/query.log.sorted +cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +NS b.stale. +TXT a.b.stale. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "query for .stale is properly minimized when qname-minimization is in relaxed mode (stale cache) ($n)" +ret=0 +$CLEANQL +$RNDCCMD 10.53.0.7 flush +$DIG $DIGOPTS @10.53.0.7 txt a.b.stale. >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1 +sleep 1 +sort ans2/query.log >ans2/query.log.sorted +cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +ADDR ns2.stale. +NS b.stale. +__EOF +test -f ans3/query.log && ret=1 +sort ans4/query.log >ans4/query.log.sorted +cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1 +ADDR ns.b.stale. +TXT a.b.stale. +__EOF +for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test that \"success resolving\" is not logged for NXDOMAIN final answer when qname-minimization is in relaxed mode ($n)" +ret=0 +nextpart ns7/named.run >/dev/null +$DIG $DIGOPTS 1.0.53.10.in-addr.arpa ptr @10.53.0.7 >dig.out.test$n || ret=1 +nextpart ns7/named.run >named.run.test$n +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "success resolving" named.run.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/qmin/tests_sh_qmin.py b/bin/tests/system/qmin/tests_sh_qmin.py new file mode 100644 index 0000000..2d9f90b --- /dev/null +++ b/bin/tests/system/qmin/tests_sh_qmin.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "named.run.*", + "query*.log", + "ans*/ans.run", + "ans*/query.log*", + ] +) + + +# The qmin test is inherently unstable, see GL #904 for details. +@isctest.mark.flaky(max_runs=3) +def test_qmin(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/query-source/ns1/named.conf.j2 b/bin/tests/system/query-source/ns1/named.conf.j2 new file mode 100644 index 0000000..58ca683 --- /dev/null +++ b/bin/tests/system/query-source/ns1/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + listen-on { 10.53.0.1; }; + recursion no; + dnssec-validation no; + query-source 10.53.0.1; + query-source-v6 fd92:7065:b8e:ffff::1; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/query-source/ns1/root.db b/bin/tests/system/query-source/ns1/root.db new file mode 100644 index 0000000..e635a62 --- /dev/null +++ b/bin/tests/system/query-source/ns1/root.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 SOA . . 0 0 0 0 0 +. 300 NS a.root-servers.nil. +a.root-servers.nil. 300 A 10.53.0.1 +example. 300 A 10.53.0.10 +exampletwo. 300 A 10.53.0.11 \ No newline at end of file diff --git a/bin/tests/system/query-source/ns2/named.conf.j2 b/bin/tests/system/query-source/ns2/named.conf.j2 new file mode 100644 index 0000000..de69fe3 --- /dev/null +++ b/bin/tests/system/query-source/ns2/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion yes; + dnssec-validation no; + query-source none; + query-source-v6 fd92:7065:b8e:ffff::2; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns2/root.hint b/bin/tests/system/query-source/ns2/root.hint new file mode 100644 index 0000000..315a233 --- /dev/null +++ b/bin/tests/system/query-source/ns2/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/query-source/ns3/named.conf.j2 b/bin/tests/system/query-source/ns3/named.conf.j2 new file mode 100644 index 0000000..408edb3 --- /dev/null +++ b/bin/tests/system/query-source/ns3/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { fd92:7065:b8e:ffff::3; }; + recursion yes; + dnssec-validation no; + query-source-v6 none; + query-source 10.53.0.3; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns3/root.hint b/bin/tests/system/query-source/ns3/root.hint new file mode 100644 index 0000000..e0f186c --- /dev/null +++ b/bin/tests/system/query-source/ns3/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/query-source/ns4/named.conf.j2 b/bin/tests/system/query-source/ns4/named.conf.j2 new file mode 100644 index 0000000..7fc4dab --- /dev/null +++ b/bin/tests/system/query-source/ns4/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { fd92:7065:b8e:ffff::4; }; + recursion yes; + dnssec-validation no; + query-source none; + query-source-v6 fd92:7065:b8e:ffff::4; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns4/root.hint b/bin/tests/system/query-source/ns4/root.hint new file mode 100644 index 0000000..49dcae0 --- /dev/null +++ b/bin/tests/system/query-source/ns4/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.1 diff --git a/bin/tests/system/query-source/ns5/named.conf.j2 b/bin/tests/system/query-source/ns5/named.conf.j2 new file mode 100644 index 0000000..df8975f --- /dev/null +++ b/bin/tests/system/query-source/ns5/named.conf.j2 @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { fd92:7065:b8e:ffff::5; }; + recursion yes; + dnssec-validation no; + query-source 10.53.0.5; + query-source-v6 none; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/query-source/ns5/root.hint b/bin/tests/system/query-source/ns5/root.hint new file mode 100644 index 0000000..315a233 --- /dev/null +++ b/bin/tests/system/query-source/ns5/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::1 diff --git a/bin/tests/system/query-source/tests_querysource_none.py b/bin/tests/system/query-source/tests_querysource_none.py new file mode 100644 index 0000000..0f19d05 --- /dev/null +++ b/bin/tests/system/query-source/tests_querysource_none.py @@ -0,0 +1,58 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest +import isctest + +pytest.importorskip("dns") +import dns.message + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns*/named.pid", + "ns*/managed-keys.bind*", + ] +) + + +def test_querysource_none(): + msg = dns.message.make_query("example.", "A", want_dnssec=False) + + res = isctest.query.udp(msg, "10.53.0.2") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "10.53.0.3") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "10.53.0.4") + isctest.check.servfail(res) + + res = isctest.query.udp(msg, "10.53.0.5") + isctest.check.servfail(res) + + # using a different name below to make sure we don't use the + # resolver cache + + msg = dns.message.make_query("exampletwo.", "A", want_dnssec=False) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::2") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::3") + isctest.check.noerror(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::4") + isctest.check.servfail(res) + + res = isctest.query.udp(msg, "fd92:7065:b8e:ffff::5") + isctest.check.servfail(res) diff --git a/bin/tests/system/reclimit/README b/bin/tests/system/reclimit/README new file mode 100644 index 0000000..e474907 --- /dev/null +++ b/bin/tests/system/reclimit/README @@ -0,0 +1,19 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +system test for recursion limits + +ns1 -- root server +ans2 -- for example.org: delegate to ns1.(n+1).example.org for all n, up to the + value specified in ans.limit (or forever if limit is 0) +ns3 -- resolver under test +ans4 -- for ns*.example.com: return address records. +ans7 -- "victim" server diff --git a/bin/tests/system/reclimit/ans2/ans.pl b/bin/tests/system/reclimit/ans2/ans.pl new file mode 100644 index 0000000..4576951 --- /dev/null +++ b/bin/tests/system/reclimit/ans2/ans.pl @@ -0,0 +1,235 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +use IO::File; +use IO::Socket; +use Net::DNS; + +my $localaddr = "10.53.0.2"; +my $limit = getlimit(); +my $no_more_waiting = 0; +my @delayed_response; +my $timeout; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my $count = 0; +my $send_response = 0; + +sub getlimit { + if ( -e "ans.limit") { + open(FH, "<", "ans.limit"); + my $line = ; + chomp $line; + close FH; + if ($line =~ /^\d+$/) { + return $line; + } + } + + return 0; +} + +# If $wait == 0 is returned, returned reply will be sent immediately. +# If $wait == 1 is returned, sending the returned reply might be delayed; see +# comments inside handle_UDP() for details. +sub reply_handler { + my ($qname, $qclass, $qtype) = @_; + my ($rcode, @ans, @auth, @add, $wait); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + $wait = 0; + $count += 1; + + if ($qname eq "count" ) { + if ($qtype eq "TXT") { + my ($ttl, $rdata) = (0, "$count"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\tcount: $count\n"); + } + $rcode = "NOERROR"; + } elsif ($qname eq "reset" ) { + $count = 0; + $send_response = 0; + $limit = getlimit(); + $rcode = "NOERROR"; + print ("\tlimit: $limit\n"); + } elsif ($qname eq "direct.example.org" ) { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "indirect1.example.org" || + $qname eq "indirect2.example.org" || + $qname eq "indirect3.example.org" || + $qname eq "indirect4.example.org" || + $qname eq "indirect5.example.org" || + $qname eq "indirect6.example.org" || + $qname eq "indirect7.example.org" || + $qname eq "indirect8.example.org") { + if (! $send_response) { + my $rr = new Net::DNS::RR("$qname 86400 $qclass NS ns1.1.example.org"); + push @auth, $rr; + } elsif ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) { + my $next = $1 + 1; + $wait = 1; + if ($limit == 0 || (! $send_response && $next <= $limit)) { + my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org"); + push @auth, $rr; + } else { + $send_response = 1; + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, "10.53.0.4"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + print("\tresponse: $qname $ttl $qclass $qtype $rdata\n"); + push @ans, $rr; + } + } + $rcode = "NOERROR"; + } elsif ($qname eq "direct.example.net" ) { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif( $qname =~ /^ns1\.(\d+)\.example\.net$/ ) { + my $next = ($1 + 1) * 16; + for (my $i = 1; $i < 16; $i++) { + my $s = $next + $i; + my $rr = new Net::DNS::RR("$1.example.net 86400 $qclass NS ns1.$s.example.net"); + push @auth, $rr; + $rr = new Net::DNS::RR("ns1.$s.example.net 86400 $qclass A 10.53.0.7"); + push @add, $rr; + } + $rcode = "NOERROR"; + } else { + $rcode = "NXDOMAIN"; + } + + return ($rcode, \@ans, \@auth, \@add, $wait); +} + +sub handleUDP { + my ($buf, $peer) = @_; + my ($request, $rcode, $ans, $auth, $add, $wait); + + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + + my ($question) = $request->question; + my $qname = $question->qname; + my $qclass = $question->qclass; + my $qtype = $question->qtype; + + ($rcode, $ans, $auth, $add, $wait) = reply_handler($qname, $qclass, $qtype); + + my $reply = $request->reply(); + + $reply->header->rcode($rcode); + $reply->header->aa(@$ans ? 1 : 0); + $reply->header->id($request->header->id); + $reply->{answer} = $ans if $ans; + $reply->{authority} = $auth if $auth; + $reply->{additional} = $add if $add; + + if ($wait) { + # reply_handler() asked us to delay sending this reply until + # another reply with $wait == 1 is generated or a timeout + # occurs. + if (@delayed_response) { + # A delayed reply is already queued, so we can now send + # both the delayed reply and the current reply. + send_delayed_response(); + return $reply; + } elsif ($no_more_waiting) { + # It was determined before that there is no point in + # waiting for "accompanying" queries. Thus, send the + # current reply immediately. + return $reply; + } else { + # No delayed reply is queued and the client is expected + # to send an "accompanying" query shortly. Do not send + # the current reply right now, just save it for later + # and wait for an "accompanying" query to be received. + @delayed_response = ($reply, $peer); + $timeout = 0.5; + return; + } + } else { + # Send reply immediately. + return $reply; + } +} + +sub send_delayed_response { + my ($reply, $peer) = @delayed_response; + # Truncation to 512 bytes is required for triggering "NS explosion" on + # builds without IPv6 support + $udpsock->send($reply->data(512), 0, $peer); + undef @delayed_response; + undef $timeout; +} + +# Main +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, $timeout); + + if (vec($rout, fileno($udpsock), 1)) { + my ($buf, $peer, $reply); + $udpsock->recv($buf, 512); + $peer = $udpsock->peername(); + $reply = handleUDP($buf, $peer); + # Truncation to 512 bytes is required for triggering "NS + # explosion" on builds without IPv6 support + $udpsock->send($reply->data(512), 0, $peer) if $reply; + } else { + # An "accompanying" query was expected to come in, but did not. + # Assume the client never sends "accompanying" queries to + # prevent pointlessly waiting for them ever again. + $no_more_waiting = 1; + # Send the delayed reply to the query which caused us to wait. + send_delayed_response(); + } +} diff --git a/bin/tests/system/reclimit/ans4/ans.pl b/bin/tests/system/reclimit/ans4/ans.pl new file mode 100644 index 0000000..d5002aa --- /dev/null +++ b/bin/tests/system/reclimit/ans4/ans.pl @@ -0,0 +1,240 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +use IO::File; +use IO::Socket; +use Net::DNS; + +my $localaddr = "10.53.0.4"; +my $limit = getlimit(); +my $no_more_waiting = 0; +my @delayed_response; +my $timeout; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my $count = 0; +my $send_response = 1; + +sub getlimit { + if ( -e "ans.limit") { + open(FH, "<", "ans.limit"); + my $line = ; + chomp $line; + close FH; + if ($line =~ /^\d+$/) { + return $line; + } + } + + return 0; +} + +# If $wait == 0 is returned, returned reply will be sent immediately. +# If $wait == 1 is returned, sending the returned reply might be delayed; see +# comments inside handle_UDP() for details. +sub reply_handler { + my ($qname, $qclass, $qtype) = @_; + my ($rcode, @ans, @auth, @add, $wait); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + $wait = 0; + $count += 1; + + if ($qname eq "count" ) { + if ($qtype eq "TXT") { + my ($ttl, $rdata) = (0, "$count"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\tcount: $count\n"); + } + $rcode = "NOERROR"; + } elsif ($qname eq "reset" ) { + $count = 0; + $send_response = 1; + $limit = getlimit(); + $rcode = "NOERROR"; + print ("\tlimit: $limit\n"); + } elsif ($qname eq "direct.example.org" ) { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n"); + } + $rcode = "NOERROR"; + } elsif ($qname eq "indirect1.example.org" || + $qname eq "indirect2.example.org" || + $qname eq "indirect3.example.org" || + $qname eq "indirect4.example.org" || + $qname eq "indirect5.example.org" || + $qname eq "indirect6.example.org" || + $qname eq "indirect7.example.org" || + $qname eq "indirect8.example.org") { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n"); + } + $rcode = "NOERROR"; + } elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) { + my $next = $1 + 1; + $wait = 1; + if ($limit == 0) { + my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org"); + push @auth, $rr; + print ("\twait=$wait auth: $1.example.org 86400 $qclass NS ns1.$next.example.org\n"); + } else { + $send_response = 1; + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + print("\tresponse: $qname $ttl $qclass $qtype $rdata\n"); + push @ans, $rr; + } + } + $rcode = "NOERROR"; + } elsif ($qname eq "direct.example.net" ) { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\twait=$wait ans: $qname $ttl $qclass $qtype $rdata\n"); + } + $rcode = "NOERROR"; + } elsif( $qname =~ /^ns1\.(\d+)\.example\.net$/ ) { + my $next = ($1 + 1) * 16; + for (my $i = 1; $i < 16; $i++) { + my $s = $next + $i; + my $rr = new Net::DNS::RR("$1.example.net 86400 $qclass NS ns1.$s.example.net"); + push @auth, $rr; + print ("\twait=$wait auth: $1.example.net 86400 $qclass NS ns1.$s.example.net\n"); + $rr = new Net::DNS::RR("ns1.$s.example.net 86400 $qclass A 10.53.0.7"); + print ("\twait=$wait add: ns1.$s.example.net 86400 $qclass A 10.53.0.7\n"); + push @add, $rr; + } + $rcode = "NOERROR"; + } else { + $rcode = "NXDOMAIN"; + print ("\twait=$wait NXDOMAIN\n"); + } + + return ($rcode, \@ans, \@auth, \@add, $wait); +} + +sub handleUDP { + my ($buf, $peer) = @_; + my ($request, $rcode, $ans, $auth, $add, $wait); + + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + + my ($question) = $request->question; + my $qname = $question->qname; + my $qclass = $question->qclass; + my $qtype = $question->qtype; + + ($rcode, $ans, $auth, $add, $wait) = reply_handler($qname, $qclass, $qtype); + + my $reply = $request->reply(); + + $reply->header->rcode($rcode); + $reply->header->aa(@$ans ? 1 : 0); + $reply->header->id($request->header->id); + $reply->{answer} = $ans if $ans; + $reply->{authority} = $auth if $auth; + $reply->{additional} = $add if $add; + + if ($wait) { + # reply_handler() asked us to delay sending this reply until + # another reply with $wait == 1 is generated or a timeout + # occurs. + if (@delayed_response) { + # A delayed reply is already queued, so we can now send + # both the delayed reply and the current reply. + send_delayed_response(); + return $reply; + } elsif ($no_more_waiting) { + # It was determined before that there is no point in + # waiting for "accompanying" queries. Thus, send the + # current reply immediately. + return $reply; + } else { + # No delayed reply is queued and the client is expected + # to send an "accompanying" query shortly. Do not send + # the current reply right now, just save it for later + # and wait for an "accompanying" query to be received. + @delayed_response = ($reply, $peer); + $timeout = 0.5; + return; + } + } else { + # Send reply immediately. + return $reply; + } +} + +sub send_delayed_response { + my ($reply, $peer) = @delayed_response; + # Truncation to 512 bytes is required for triggering "NS explosion" on + # builds without IPv6 support + $udpsock->send($reply->data(512), 0, $peer); + undef @delayed_response; + undef $timeout; + print ("send_delayed_response\n"); +} + +# Main +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, $timeout); + + if (vec($rout, fileno($udpsock), 1)) { + my ($buf, $peer, $reply); + $udpsock->recv($buf, 512); + $peer = $udpsock->peername(); + $reply = handleUDP($buf, $peer); + # Truncation to 512 bytes is required for triggering "NS + # explosion" on builds without IPv6 support + $udpsock->send($reply->data(512), 0, $peer) if $reply; + } else { + # An "accompanying" query was expected to come in, but did not. + # Assume the client never sends "accompanying" queries to + # prevent pointlessly waiting for them ever again. + $no_more_waiting = 1; + # Send the delayed reply to the query which caused us to wait. + send_delayed_response(); + } +} diff --git a/bin/tests/system/reclimit/ans7/ans.pl b/bin/tests/system/reclimit/ans7/ans.pl new file mode 100644 index 0000000..52110f1 --- /dev/null +++ b/bin/tests/system/reclimit/ans7/ans.pl @@ -0,0 +1,88 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +use IO::File; +use Getopt::Long; +use Net::DNS::Nameserver; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; +sub term { }; + +$SIG{INT} = \&rmpid; +if ($Net::DNS::VERSION >= 1.42) { + $SIG{TERM} = \&term; +} else { + $SIG{TERM} = \&rmpid; +} + +my $count = 0; + +my $localaddr = "10.53.0.7"; +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } +my $verbose = 0; + +sub reply_handler { + my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_; + my ($rcode, @ans, @auth, @add); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + $count += 1; + + if ($qname eq "count" ) { + if ($qtype eq "TXT") { + my ($ttl, $rdata) = (0, "$count"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\tcount: $count\n"); + } + $rcode = "NOERROR"; + } elsif ($qname eq "reset") { + $count = 0; + $rcode = "NOERROR"; + } else { + $rcode = "REFUSED"; + } + + # mark the answer as authoritative (by setting the 'aa' flag + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); +} + +GetOptions( + 'port=i' => \$localport, + 'verbose!' => \$verbose, +); + +my $ns = Net::DNS::Nameserver->new( + LocalAddr => $localaddr, + LocalPort => $localport, + ReplyHandler => \&reply_handler, + Verbose => $verbose, +); + +if ($Net::DNS::VERSION >= 1.42) { + $ns->start_server(); + select(undef, undef, undef, undef); + $ns->stop_server(); + unlink "ans.pid"; +} else { + $ns->main_loop; +} diff --git a/bin/tests/system/reclimit/ns1/big.db b/bin/tests/system/reclimit/ns1/big.db new file mode 100644 index 0000000..6659aae --- /dev/null +++ b/bin/tests/system/reclimit/ns1/big.db @@ -0,0 +1,2774 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 + +big. IN SOA ns.big. hostmaster.ns.big. 1 0 0 0 120 +big. IN NS ns.big. +ns.big. IN A 10.53.0.1 + +biganswer.big. IN A 10.10.1.1 +biganswer.big. IN A 10.10.1.2 +biganswer.big. IN A 10.10.1.3 +biganswer.big. IN A 10.10.1.4 +biganswer.big. IN A 10.10.1.5 +biganswer.big. IN A 10.10.1.6 +biganswer.big. IN A 10.10.1.7 +biganswer.big. IN A 10.10.1.8 +biganswer.big. IN A 10.10.1.9 +biganswer.big. IN A 10.10.1.10 +biganswer.big. IN A 10.10.1.11 +biganswer.big. IN A 10.10.1.12 +biganswer.big. IN A 10.10.1.13 +biganswer.big. IN A 10.10.1.14 +biganswer.big. IN A 10.10.1.15 +biganswer.big. IN A 10.10.1.16 +biganswer.big. IN A 10.10.1.17 +biganswer.big. IN A 10.10.1.18 +biganswer.big. IN A 10.10.1.19 +biganswer.big. IN A 10.10.1.20 +biganswer.big. IN A 10.10.1.21 +biganswer.big. IN A 10.10.1.22 +biganswer.big. IN A 10.10.1.23 +biganswer.big. IN A 10.10.1.24 +biganswer.big. IN A 10.10.1.25 +biganswer.big. IN A 10.10.1.26 +biganswer.big. IN A 10.10.1.27 +biganswer.big. IN A 10.10.1.28 +biganswer.big. IN A 10.10.1.29 +biganswer.big. IN A 10.10.1.30 +biganswer.big. IN A 10.10.1.31 +biganswer.big. IN A 10.10.1.32 +biganswer.big. IN A 10.10.1.33 +biganswer.big. IN A 10.10.1.34 +biganswer.big. IN A 10.10.1.35 +biganswer.big. IN A 10.10.1.36 +biganswer.big. IN A 10.10.1.37 +biganswer.big. IN A 10.10.1.38 +biganswer.big. IN A 10.10.1.39 +biganswer.big. IN A 10.10.1.40 +biganswer.big. IN A 10.10.1.41 +biganswer.big. IN A 10.10.1.42 +biganswer.big. IN A 10.10.1.43 +biganswer.big. IN A 10.10.1.44 +biganswer.big. IN A 10.10.1.45 +biganswer.big. IN A 10.10.1.46 +biganswer.big. IN A 10.10.1.47 +biganswer.big. IN A 10.10.1.48 +biganswer.big. IN A 10.10.1.49 +biganswer.big. IN A 10.10.1.50 +biganswer.big. IN A 10.10.2.1 +biganswer.big. IN A 10.10.2.2 +biganswer.big. IN A 10.10.2.3 +biganswer.big. IN A 10.10.2.4 +biganswer.big. IN A 10.10.2.5 +biganswer.big. IN A 10.10.2.6 +biganswer.big. IN A 10.10.2.7 +biganswer.big. IN A 10.10.2.8 +biganswer.big. IN A 10.10.2.9 +biganswer.big. IN A 10.10.2.10 +biganswer.big. IN A 10.10.2.11 +biganswer.big. IN A 10.10.2.12 +biganswer.big. IN A 10.10.2.13 +biganswer.big. IN A 10.10.2.14 +biganswer.big. IN A 10.10.2.15 +biganswer.big. IN A 10.10.2.16 +biganswer.big. IN A 10.10.2.17 +biganswer.big. IN A 10.10.2.18 +biganswer.big. IN A 10.10.2.19 +biganswer.big. IN A 10.10.2.20 +biganswer.big. IN A 10.10.2.21 +biganswer.big. IN A 10.10.2.22 +biganswer.big. IN A 10.10.2.23 +biganswer.big. IN A 10.10.2.24 +biganswer.big. IN A 10.10.2.25 +biganswer.big. IN A 10.10.2.26 +biganswer.big. IN A 10.10.2.27 +biganswer.big. IN A 10.10.2.28 +biganswer.big. IN A 10.10.2.29 +biganswer.big. IN A 10.10.2.30 +biganswer.big. IN A 10.10.2.31 +biganswer.big. IN A 10.10.2.32 +biganswer.big. IN A 10.10.2.33 +biganswer.big. IN A 10.10.2.34 +biganswer.big. IN A 10.10.2.35 +biganswer.big. IN A 10.10.2.36 +biganswer.big. IN A 10.10.2.37 +biganswer.big. IN A 10.10.2.38 +biganswer.big. IN A 10.10.2.39 +biganswer.big. IN A 10.10.2.40 +biganswer.big. IN A 10.10.2.41 +biganswer.big. IN A 10.10.2.42 +biganswer.big. IN A 10.10.2.43 +biganswer.big. IN A 10.10.2.44 +biganswer.big. IN A 10.10.2.45 +biganswer.big. IN A 10.10.2.46 +biganswer.big. IN A 10.10.2.47 +biganswer.big. IN A 10.10.2.48 +biganswer.big. IN A 10.10.2.49 +biganswer.big. IN A 10.10.2.50 +biganswer.big. IN A 10.10.3.1 +biganswer.big. IN A 10.10.3.2 +biganswer.big. IN A 10.10.3.3 +biganswer.big. IN A 10.10.3.4 +biganswer.big. IN A 10.10.3.5 +biganswer.big. IN A 10.10.3.6 +biganswer.big. IN A 10.10.3.7 +biganswer.big. IN A 10.10.3.8 +biganswer.big. IN A 10.10.3.9 +biganswer.big. IN A 10.10.3.10 +biganswer.big. IN A 10.10.3.11 +biganswer.big. IN A 10.10.3.12 +biganswer.big. IN A 10.10.3.13 +biganswer.big. IN A 10.10.3.14 +biganswer.big. IN A 10.10.3.15 +biganswer.big. IN A 10.10.3.16 +biganswer.big. IN A 10.10.3.17 +biganswer.big. IN A 10.10.3.18 +biganswer.big. IN A 10.10.3.19 +biganswer.big. IN A 10.10.3.20 +biganswer.big. IN A 10.10.3.21 +biganswer.big. IN A 10.10.3.22 +biganswer.big. IN A 10.10.3.23 +biganswer.big. IN A 10.10.3.24 +biganswer.big. IN A 10.10.3.25 +biganswer.big. IN A 10.10.3.26 +biganswer.big. IN A 10.10.3.27 +biganswer.big. IN A 10.10.3.28 +biganswer.big. IN A 10.10.3.29 +biganswer.big. IN A 10.10.3.30 +biganswer.big. IN A 10.10.3.31 +biganswer.big. IN A 10.10.3.32 +biganswer.big. IN A 10.10.3.33 +biganswer.big. IN A 10.10.3.34 +biganswer.big. IN A 10.10.3.35 +biganswer.big. IN A 10.10.3.36 +biganswer.big. IN A 10.10.3.37 +biganswer.big. IN A 10.10.3.38 +biganswer.big. IN A 10.10.3.39 +biganswer.big. IN A 10.10.3.40 +biganswer.big. IN A 10.10.3.41 +biganswer.big. IN A 10.10.3.42 +biganswer.big. IN A 10.10.3.43 +biganswer.big. IN A 10.10.3.44 +biganswer.big. IN A 10.10.3.45 +biganswer.big. IN A 10.10.3.46 +biganswer.big. IN A 10.10.3.47 +biganswer.big. IN A 10.10.3.48 +biganswer.big. IN A 10.10.3.49 +biganswer.big. IN A 10.10.3.50 +biganswer.big. IN A 10.10.4.1 +biganswer.big. IN A 10.10.4.2 +biganswer.big. IN A 10.10.4.3 +biganswer.big. IN A 10.10.4.4 +biganswer.big. IN A 10.10.4.5 +biganswer.big. IN A 10.10.4.6 +biganswer.big. IN A 10.10.4.7 +biganswer.big. IN A 10.10.4.8 +biganswer.big. IN A 10.10.4.9 +biganswer.big. IN A 10.10.4.10 +biganswer.big. IN A 10.10.4.11 +biganswer.big. IN A 10.10.4.12 +biganswer.big. IN A 10.10.4.13 +biganswer.big. IN A 10.10.4.14 +biganswer.big. IN A 10.10.4.15 +biganswer.big. IN A 10.10.4.16 +biganswer.big. IN A 10.10.4.17 +biganswer.big. IN A 10.10.4.18 +biganswer.big. IN A 10.10.4.19 +biganswer.big. IN A 10.10.4.20 +biganswer.big. IN A 10.10.4.21 +biganswer.big. IN A 10.10.4.22 +biganswer.big. IN A 10.10.4.23 +biganswer.big. IN A 10.10.4.24 +biganswer.big. IN A 10.10.4.25 +biganswer.big. IN A 10.10.4.26 +biganswer.big. IN A 10.10.4.27 +biganswer.big. IN A 10.10.4.28 +biganswer.big. IN A 10.10.4.29 +biganswer.big. IN A 10.10.4.30 +biganswer.big. IN A 10.10.4.31 +biganswer.big. IN A 10.10.4.32 +biganswer.big. IN A 10.10.4.33 +biganswer.big. IN A 10.10.4.34 +biganswer.big. IN A 10.10.4.35 +biganswer.big. IN A 10.10.4.36 +biganswer.big. IN A 10.10.4.37 +biganswer.big. IN A 10.10.4.38 +biganswer.big. IN A 10.10.4.39 +biganswer.big. IN A 10.10.4.40 +biganswer.big. IN A 10.10.4.41 +biganswer.big. IN A 10.10.4.42 +biganswer.big. IN A 10.10.4.43 +biganswer.big. IN A 10.10.4.44 +biganswer.big. IN A 10.10.4.45 +biganswer.big. IN A 10.10.4.46 +biganswer.big. IN A 10.10.4.47 +biganswer.big. IN A 10.10.4.48 +biganswer.big. IN A 10.10.4.49 +biganswer.big. IN A 10.10.4.50 +biganswer.big. IN A 10.10.5.1 +biganswer.big. IN A 10.10.5.2 +biganswer.big. IN A 10.10.5.3 +biganswer.big. IN A 10.10.5.4 +biganswer.big. IN A 10.10.5.5 +biganswer.big. IN A 10.10.5.6 +biganswer.big. IN A 10.10.5.7 +biganswer.big. IN A 10.10.5.8 +biganswer.big. IN A 10.10.5.9 +biganswer.big. IN A 10.10.5.10 +biganswer.big. IN A 10.10.5.11 +biganswer.big. IN A 10.10.5.12 +biganswer.big. IN A 10.10.5.13 +biganswer.big. IN A 10.10.5.14 +biganswer.big. IN A 10.10.5.15 +biganswer.big. IN A 10.10.5.16 +biganswer.big. IN A 10.10.5.17 +biganswer.big. IN A 10.10.5.18 +biganswer.big. IN A 10.10.5.19 +biganswer.big. IN A 10.10.5.20 +biganswer.big. IN A 10.10.5.21 +biganswer.big. IN A 10.10.5.22 +biganswer.big. IN A 10.10.5.23 +biganswer.big. IN A 10.10.5.24 +biganswer.big. IN A 10.10.5.25 +biganswer.big. IN A 10.10.5.26 +biganswer.big. IN A 10.10.5.27 +biganswer.big. IN A 10.10.5.28 +biganswer.big. IN A 10.10.5.29 +biganswer.big. IN A 10.10.5.30 +biganswer.big. IN A 10.10.5.31 +biganswer.big. IN A 10.10.5.32 +biganswer.big. IN A 10.10.5.33 +biganswer.big. IN A 10.10.5.34 +biganswer.big. IN A 10.10.5.35 +biganswer.big. IN A 10.10.5.36 +biganswer.big. IN A 10.10.5.37 +biganswer.big. IN A 10.10.5.38 +biganswer.big. IN A 10.10.5.39 +biganswer.big. IN A 10.10.5.40 +biganswer.big. IN A 10.10.5.41 +biganswer.big. IN A 10.10.5.42 +biganswer.big. IN A 10.10.5.43 +biganswer.big. IN A 10.10.5.44 +biganswer.big. IN A 10.10.5.45 +biganswer.big. IN A 10.10.5.46 +biganswer.big. IN A 10.10.5.47 +biganswer.big. IN A 10.10.5.48 +biganswer.big. IN A 10.10.5.49 +biganswer.big. IN A 10.10.5.50 +biganswer.big. IN A 10.10.6.1 +biganswer.big. IN A 10.10.6.2 +biganswer.big. IN A 10.10.6.3 +biganswer.big. IN A 10.10.6.4 +biganswer.big. IN A 10.10.6.5 +biganswer.big. IN A 10.10.6.6 +biganswer.big. IN A 10.10.6.7 +biganswer.big. IN A 10.10.6.8 +biganswer.big. IN A 10.10.6.9 +biganswer.big. IN A 10.10.6.10 +biganswer.big. IN A 10.10.6.11 +biganswer.big. IN A 10.10.6.12 +biganswer.big. IN A 10.10.6.13 +biganswer.big. IN A 10.10.6.14 +biganswer.big. IN A 10.10.6.15 +biganswer.big. IN A 10.10.6.16 +biganswer.big. IN A 10.10.6.17 +biganswer.big. IN A 10.10.6.18 +biganswer.big. IN A 10.10.6.19 +biganswer.big. IN A 10.10.6.20 +biganswer.big. IN A 10.10.6.21 +biganswer.big. IN A 10.10.6.22 +biganswer.big. IN A 10.10.6.23 +biganswer.big. IN A 10.10.6.24 +biganswer.big. IN A 10.10.6.25 +biganswer.big. IN A 10.10.6.26 +biganswer.big. IN A 10.10.6.27 +biganswer.big. IN A 10.10.6.28 +biganswer.big. IN A 10.10.6.29 +biganswer.big. IN A 10.10.6.30 +biganswer.big. IN A 10.10.6.31 +biganswer.big. IN A 10.10.6.32 +biganswer.big. IN A 10.10.6.33 +biganswer.big. IN A 10.10.6.34 +biganswer.big. IN A 10.10.6.35 +biganswer.big. IN A 10.10.6.36 +biganswer.big. IN A 10.10.6.37 +biganswer.big. IN A 10.10.6.38 +biganswer.big. IN A 10.10.6.39 +biganswer.big. IN A 10.10.6.40 +biganswer.big. IN A 10.10.6.41 +biganswer.big. IN A 10.10.6.42 +biganswer.big. IN A 10.10.6.43 +biganswer.big. IN A 10.10.6.44 +biganswer.big. IN A 10.10.6.45 +biganswer.big. IN A 10.10.6.46 +biganswer.big. IN A 10.10.6.47 +biganswer.big. IN A 10.10.6.48 +biganswer.big. IN A 10.10.6.49 +biganswer.big. IN A 10.10.6.50 +biganswer.big. IN A 10.10.7.1 +biganswer.big. IN A 10.10.7.2 +biganswer.big. IN A 10.10.7.3 +biganswer.big. IN A 10.10.7.4 +biganswer.big. IN A 10.10.7.5 +biganswer.big. IN A 10.10.7.6 +biganswer.big. IN A 10.10.7.7 +biganswer.big. IN A 10.10.7.8 +biganswer.big. IN A 10.10.7.9 +biganswer.big. IN A 10.10.7.10 +biganswer.big. IN A 10.10.7.11 +biganswer.big. IN A 10.10.7.12 +biganswer.big. IN A 10.10.7.13 +biganswer.big. IN A 10.10.7.14 +biganswer.big. IN A 10.10.7.15 +biganswer.big. IN A 10.10.7.16 +biganswer.big. IN A 10.10.7.17 +biganswer.big. IN A 10.10.7.18 +biganswer.big. IN A 10.10.7.19 +biganswer.big. IN A 10.10.7.20 +biganswer.big. IN A 10.10.7.21 +biganswer.big. IN A 10.10.7.22 +biganswer.big. IN A 10.10.7.23 +biganswer.big. IN A 10.10.7.24 +biganswer.big. IN A 10.10.7.25 +biganswer.big. IN A 10.10.7.26 +biganswer.big. IN A 10.10.7.27 +biganswer.big. IN A 10.10.7.28 +biganswer.big. IN A 10.10.7.29 +biganswer.big. IN A 10.10.7.30 +biganswer.big. IN A 10.10.7.31 +biganswer.big. IN A 10.10.7.32 +biganswer.big. IN A 10.10.7.33 +biganswer.big. IN A 10.10.7.34 +biganswer.big. IN A 10.10.7.35 +biganswer.big. IN A 10.10.7.36 +biganswer.big. IN A 10.10.7.37 +biganswer.big. IN A 10.10.7.38 +biganswer.big. IN A 10.10.7.39 +biganswer.big. IN A 10.10.7.40 +biganswer.big. IN A 10.10.7.41 +biganswer.big. IN A 10.10.7.42 +biganswer.big. IN A 10.10.7.43 +biganswer.big. IN A 10.10.7.44 +biganswer.big. IN A 10.10.7.45 +biganswer.big. IN A 10.10.7.46 +biganswer.big. IN A 10.10.7.47 +biganswer.big. IN A 10.10.7.48 +biganswer.big. IN A 10.10.7.49 +biganswer.big. IN A 10.10.7.50 +biganswer.big. IN A 10.10.8.1 +biganswer.big. IN A 10.10.8.2 +biganswer.big. IN A 10.10.8.3 +biganswer.big. IN A 10.10.8.4 +biganswer.big. IN A 10.10.8.5 +biganswer.big. IN A 10.10.8.6 +biganswer.big. IN A 10.10.8.7 +biganswer.big. IN A 10.10.8.8 +biganswer.big. IN A 10.10.8.9 +biganswer.big. IN A 10.10.8.10 +biganswer.big. IN A 10.10.8.11 +biganswer.big. IN A 10.10.8.12 +biganswer.big. IN A 10.10.8.13 +biganswer.big. IN A 10.10.8.14 +biganswer.big. IN A 10.10.8.15 +biganswer.big. IN A 10.10.8.16 +biganswer.big. IN A 10.10.8.17 +biganswer.big. IN A 10.10.8.18 +biganswer.big. IN A 10.10.8.19 +biganswer.big. IN A 10.10.8.20 +biganswer.big. IN A 10.10.8.21 +biganswer.big. IN A 10.10.8.22 +biganswer.big. IN A 10.10.8.23 +biganswer.big. IN A 10.10.8.24 +biganswer.big. IN A 10.10.8.25 +biganswer.big. IN A 10.10.8.26 +biganswer.big. IN A 10.10.8.27 +biganswer.big. IN A 10.10.8.28 +biganswer.big. IN A 10.10.8.29 +biganswer.big. IN A 10.10.8.30 +biganswer.big. IN A 10.10.8.31 +biganswer.big. IN A 10.10.8.32 +biganswer.big. IN A 10.10.8.33 +biganswer.big. IN A 10.10.8.34 +biganswer.big. IN A 10.10.8.35 +biganswer.big. IN A 10.10.8.36 +biganswer.big. IN A 10.10.8.37 +biganswer.big. IN A 10.10.8.38 +biganswer.big. IN A 10.10.8.39 +biganswer.big. IN A 10.10.8.40 +biganswer.big. IN A 10.10.8.41 +biganswer.big. IN A 10.10.8.42 +biganswer.big. IN A 10.10.8.43 +biganswer.big. IN A 10.10.8.44 +biganswer.big. IN A 10.10.8.45 +biganswer.big. IN A 10.10.8.46 +biganswer.big. IN A 10.10.8.47 +biganswer.big. IN A 10.10.8.48 +biganswer.big. IN A 10.10.8.49 +biganswer.big. IN A 10.10.8.50 +biganswer.big. IN A 10.10.9.1 +biganswer.big. IN A 10.10.9.2 +biganswer.big. IN A 10.10.9.3 +biganswer.big. IN A 10.10.9.4 +biganswer.big. IN A 10.10.9.5 +biganswer.big. IN A 10.10.9.6 +biganswer.big. IN A 10.10.9.7 +biganswer.big. IN A 10.10.9.8 +biganswer.big. IN A 10.10.9.9 +biganswer.big. IN A 10.10.9.10 +biganswer.big. IN A 10.10.9.11 +biganswer.big. IN A 10.10.9.12 +biganswer.big. IN A 10.10.9.13 +biganswer.big. IN A 10.10.9.14 +biganswer.big. IN A 10.10.9.15 +biganswer.big. IN A 10.10.9.16 +biganswer.big. IN A 10.10.9.17 +biganswer.big. IN A 10.10.9.18 +biganswer.big. IN A 10.10.9.19 +biganswer.big. IN A 10.10.9.20 +biganswer.big. IN A 10.10.9.21 +biganswer.big. IN A 10.10.9.22 +biganswer.big. IN A 10.10.9.23 +biganswer.big. IN A 10.10.9.24 +biganswer.big. IN A 10.10.9.25 +biganswer.big. IN A 10.10.9.26 +biganswer.big. IN A 10.10.9.27 +biganswer.big. IN A 10.10.9.28 +biganswer.big. IN A 10.10.9.29 +biganswer.big. IN A 10.10.9.30 +biganswer.big. IN A 10.10.9.31 +biganswer.big. IN A 10.10.9.32 +biganswer.big. IN A 10.10.9.33 +biganswer.big. IN A 10.10.9.34 +biganswer.big. IN A 10.10.9.35 +biganswer.big. IN A 10.10.9.36 +biganswer.big. IN A 10.10.9.37 +biganswer.big. IN A 10.10.9.38 +biganswer.big. IN A 10.10.9.39 +biganswer.big. IN A 10.10.9.40 +biganswer.big. IN A 10.10.9.41 +biganswer.big. IN A 10.10.9.42 +biganswer.big. IN A 10.10.9.43 +biganswer.big. IN A 10.10.9.44 +biganswer.big. IN A 10.10.9.45 +biganswer.big. IN A 10.10.9.46 +biganswer.big. IN A 10.10.9.47 +biganswer.big. IN A 10.10.9.48 +biganswer.big. IN A 10.10.9.49 +biganswer.big. IN A 10.10.9.50 +biganswer.big. IN A 10.10.10.1 +biganswer.big. IN A 10.10.10.2 +biganswer.big. IN A 10.10.10.3 +biganswer.big. IN A 10.10.10.4 +biganswer.big. IN A 10.10.10.5 +biganswer.big. IN A 10.10.10.6 +biganswer.big. IN A 10.10.10.7 +biganswer.big. IN A 10.10.10.8 +biganswer.big. IN A 10.10.10.9 +biganswer.big. IN A 10.10.10.10 +biganswer.big. IN A 10.10.10.11 +biganswer.big. IN A 10.10.10.12 +biganswer.big. IN A 10.10.10.13 +biganswer.big. IN A 10.10.10.14 +biganswer.big. IN A 10.10.10.15 +biganswer.big. IN A 10.10.10.16 +biganswer.big. IN A 10.10.10.17 +biganswer.big. IN A 10.10.10.18 +biganswer.big. IN A 10.10.10.19 +biganswer.big. IN A 10.10.10.20 +biganswer.big. IN A 10.10.10.21 +biganswer.big. IN A 10.10.10.22 +biganswer.big. IN A 10.10.10.23 +biganswer.big. IN A 10.10.10.24 +biganswer.big. IN A 10.10.10.25 +biganswer.big. IN A 10.10.10.26 +biganswer.big. IN A 10.10.10.27 +biganswer.big. IN A 10.10.10.28 +biganswer.big. IN A 10.10.10.29 +biganswer.big. IN A 10.10.10.30 +biganswer.big. IN A 10.10.10.31 +biganswer.big. IN A 10.10.10.32 +biganswer.big. IN A 10.10.10.33 +biganswer.big. IN A 10.10.10.34 +biganswer.big. IN A 10.10.10.35 +biganswer.big. IN A 10.10.10.36 +biganswer.big. IN A 10.10.10.37 +biganswer.big. IN A 10.10.10.38 +biganswer.big. IN A 10.10.10.39 +biganswer.big. IN A 10.10.10.40 +biganswer.big. IN A 10.10.10.41 +biganswer.big. IN A 10.10.10.42 +biganswer.big. IN A 10.10.10.43 +biganswer.big. IN A 10.10.10.44 +biganswer.big. IN A 10.10.10.45 +biganswer.big. IN A 10.10.10.46 +biganswer.big. IN A 10.10.10.47 +biganswer.big. IN A 10.10.10.48 +biganswer.big. IN A 10.10.10.49 +biganswer.big. IN A 10.10.10.50 +biganswer.big. IN A 10.10.11.1 +biganswer.big. IN A 10.10.11.2 +biganswer.big. IN A 10.10.11.3 +biganswer.big. IN A 10.10.11.4 +biganswer.big. IN A 10.10.11.5 +biganswer.big. IN A 10.10.11.6 +biganswer.big. IN A 10.10.11.7 +biganswer.big. IN A 10.10.11.8 +biganswer.big. IN A 10.10.11.9 +biganswer.big. IN A 10.10.11.10 +biganswer.big. IN A 10.10.11.11 +biganswer.big. IN A 10.10.11.12 +biganswer.big. IN A 10.10.11.13 +biganswer.big. IN A 10.10.11.14 +biganswer.big. IN A 10.10.11.15 +biganswer.big. IN A 10.10.11.16 +biganswer.big. IN A 10.10.11.17 +biganswer.big. IN A 10.10.11.18 +biganswer.big. IN A 10.10.11.19 +biganswer.big. IN A 10.10.11.20 +biganswer.big. IN A 10.10.11.21 +biganswer.big. IN A 10.10.11.22 +biganswer.big. IN A 10.10.11.23 +biganswer.big. IN A 10.10.11.24 +biganswer.big. IN A 10.10.11.25 +biganswer.big. IN A 10.10.11.26 +biganswer.big. IN A 10.10.11.27 +biganswer.big. IN A 10.10.11.28 +biganswer.big. IN A 10.10.11.29 +biganswer.big. IN A 10.10.11.30 +biganswer.big. IN A 10.10.11.31 +biganswer.big. IN A 10.10.11.32 +biganswer.big. IN A 10.10.11.33 +biganswer.big. IN A 10.10.11.34 +biganswer.big. IN A 10.10.11.35 +biganswer.big. IN A 10.10.11.36 +biganswer.big. IN A 10.10.11.37 +biganswer.big. IN A 10.10.11.38 +biganswer.big. IN A 10.10.11.39 +biganswer.big. IN A 10.10.11.40 +biganswer.big. IN A 10.10.11.41 +biganswer.big. IN A 10.10.11.42 +biganswer.big. IN A 10.10.11.43 +biganswer.big. IN A 10.10.11.44 +biganswer.big. IN A 10.10.11.45 +biganswer.big. IN A 10.10.11.46 +biganswer.big. IN A 10.10.11.47 +biganswer.big. IN A 10.10.11.48 +biganswer.big. IN A 10.10.11.49 +biganswer.big. IN A 10.10.11.50 +biganswer.big. IN A 10.10.12.1 +biganswer.big. IN A 10.10.12.2 +biganswer.big. IN A 10.10.12.3 +biganswer.big. IN A 10.10.12.4 +biganswer.big. IN A 10.10.12.5 +biganswer.big. IN A 10.10.12.6 +biganswer.big. IN A 10.10.12.7 +biganswer.big. IN A 10.10.12.8 +biganswer.big. IN A 10.10.12.9 +biganswer.big. IN A 10.10.12.10 +biganswer.big. IN A 10.10.12.11 +biganswer.big. IN A 10.10.12.12 +biganswer.big. IN A 10.10.12.13 +biganswer.big. IN A 10.10.12.14 +biganswer.big. IN A 10.10.12.15 +biganswer.big. IN A 10.10.12.16 +biganswer.big. IN A 10.10.12.17 +biganswer.big. IN A 10.10.12.18 +biganswer.big. IN A 10.10.12.19 +biganswer.big. IN A 10.10.12.20 +biganswer.big. IN A 10.10.12.21 +biganswer.big. IN A 10.10.12.22 +biganswer.big. IN A 10.10.12.23 +biganswer.big. IN A 10.10.12.24 +biganswer.big. IN A 10.10.12.25 +biganswer.big. IN A 10.10.12.26 +biganswer.big. IN A 10.10.12.27 +biganswer.big. IN A 10.10.12.28 +biganswer.big. IN A 10.10.12.29 +biganswer.big. IN A 10.10.12.30 +biganswer.big. IN A 10.10.12.31 +biganswer.big. IN A 10.10.12.32 +biganswer.big. IN A 10.10.12.33 +biganswer.big. IN A 10.10.12.34 +biganswer.big. IN A 10.10.12.35 +biganswer.big. IN A 10.10.12.36 +biganswer.big. IN A 10.10.12.37 +biganswer.big. IN A 10.10.12.38 +biganswer.big. IN A 10.10.12.39 +biganswer.big. IN A 10.10.12.40 +biganswer.big. IN A 10.10.12.41 +biganswer.big. IN A 10.10.12.42 +biganswer.big. IN A 10.10.12.43 +biganswer.big. IN A 10.10.12.44 +biganswer.big. IN A 10.10.12.45 +biganswer.big. IN A 10.10.12.46 +biganswer.big. IN A 10.10.12.47 +biganswer.big. IN A 10.10.12.48 +biganswer.big. IN A 10.10.12.49 +biganswer.big. IN A 10.10.12.50 +biganswer.big. IN A 10.10.13.1 +biganswer.big. IN A 10.10.13.2 +biganswer.big. IN A 10.10.13.3 +biganswer.big. IN A 10.10.13.4 +biganswer.big. IN A 10.10.13.5 +biganswer.big. IN A 10.10.13.6 +biganswer.big. IN A 10.10.13.7 +biganswer.big. IN A 10.10.13.8 +biganswer.big. IN A 10.10.13.9 +biganswer.big. IN A 10.10.13.10 +biganswer.big. IN A 10.10.13.11 +biganswer.big. IN A 10.10.13.12 +biganswer.big. IN A 10.10.13.13 +biganswer.big. IN A 10.10.13.14 +biganswer.big. IN A 10.10.13.15 +biganswer.big. IN A 10.10.13.16 +biganswer.big. IN A 10.10.13.17 +biganswer.big. IN A 10.10.13.18 +biganswer.big. IN A 10.10.13.19 +biganswer.big. IN A 10.10.13.20 +biganswer.big. IN A 10.10.13.21 +biganswer.big. IN A 10.10.13.22 +biganswer.big. IN A 10.10.13.23 +biganswer.big. IN A 10.10.13.24 +biganswer.big. IN A 10.10.13.25 +biganswer.big. IN A 10.10.13.26 +biganswer.big. IN A 10.10.13.27 +biganswer.big. IN A 10.10.13.28 +biganswer.big. IN A 10.10.13.29 +biganswer.big. IN A 10.10.13.30 +biganswer.big. IN A 10.10.13.31 +biganswer.big. IN A 10.10.13.32 +biganswer.big. IN A 10.10.13.33 +biganswer.big. IN A 10.10.13.34 +biganswer.big. IN A 10.10.13.35 +biganswer.big. IN A 10.10.13.36 +biganswer.big. IN A 10.10.13.37 +biganswer.big. IN A 10.10.13.38 +biganswer.big. IN A 10.10.13.39 +biganswer.big. IN A 10.10.13.40 +biganswer.big. IN A 10.10.13.41 +biganswer.big. IN A 10.10.13.42 +biganswer.big. IN A 10.10.13.43 +biganswer.big. IN A 10.10.13.44 +biganswer.big. IN A 10.10.13.45 +biganswer.big. IN A 10.10.13.46 +biganswer.big. IN A 10.10.13.47 +biganswer.big. IN A 10.10.13.48 +biganswer.big. IN A 10.10.13.49 +biganswer.big. IN A 10.10.13.50 +biganswer.big. IN A 10.10.14.1 +biganswer.big. IN A 10.10.14.2 +biganswer.big. IN A 10.10.14.3 +biganswer.big. IN A 10.10.14.4 +biganswer.big. IN A 10.10.14.5 +biganswer.big. IN A 10.10.14.6 +biganswer.big. IN A 10.10.14.7 +biganswer.big. IN A 10.10.14.8 +biganswer.big. IN A 10.10.14.9 +biganswer.big. IN A 10.10.14.10 +biganswer.big. IN A 10.10.14.11 +biganswer.big. IN A 10.10.14.12 +biganswer.big. IN A 10.10.14.13 +biganswer.big. IN A 10.10.14.14 +biganswer.big. IN A 10.10.14.15 +biganswer.big. IN A 10.10.14.16 +biganswer.big. IN A 10.10.14.17 +biganswer.big. IN A 10.10.14.18 +biganswer.big. IN A 10.10.14.19 +biganswer.big. IN A 10.10.14.20 +biganswer.big. IN A 10.10.14.21 +biganswer.big. IN A 10.10.14.22 +biganswer.big. IN A 10.10.14.23 +biganswer.big. IN A 10.10.14.24 +biganswer.big. IN A 10.10.14.25 +biganswer.big. IN A 10.10.14.26 +biganswer.big. IN A 10.10.14.27 +biganswer.big. IN A 10.10.14.28 +biganswer.big. IN A 10.10.14.29 +biganswer.big. IN A 10.10.14.30 +biganswer.big. IN A 10.10.14.31 +biganswer.big. IN A 10.10.14.32 +biganswer.big. IN A 10.10.14.33 +biganswer.big. IN A 10.10.14.34 +biganswer.big. IN A 10.10.14.35 +biganswer.big. IN A 10.10.14.36 +biganswer.big. IN A 10.10.14.37 +biganswer.big. IN A 10.10.14.38 +biganswer.big. IN A 10.10.14.39 +biganswer.big. IN A 10.10.14.40 +biganswer.big. IN A 10.10.14.41 +biganswer.big. IN A 10.10.14.42 +biganswer.big. IN A 10.10.14.43 +biganswer.big. IN A 10.10.14.44 +biganswer.big. IN A 10.10.14.45 +biganswer.big. IN A 10.10.14.46 +biganswer.big. IN A 10.10.14.47 +biganswer.big. IN A 10.10.14.48 +biganswer.big. IN A 10.10.14.49 +biganswer.big. IN A 10.10.14.50 +biganswer.big. IN A 10.10.15.1 +biganswer.big. IN A 10.10.15.2 +biganswer.big. IN A 10.10.15.3 +biganswer.big. IN A 10.10.15.4 +biganswer.big. IN A 10.10.15.5 +biganswer.big. IN A 10.10.15.6 +biganswer.big. IN A 10.10.15.7 +biganswer.big. IN A 10.10.15.8 +biganswer.big. IN A 10.10.15.9 +biganswer.big. IN A 10.10.15.10 +biganswer.big. IN A 10.10.15.11 +biganswer.big. IN A 10.10.15.12 +biganswer.big. IN A 10.10.15.13 +biganswer.big. IN A 10.10.15.14 +biganswer.big. IN A 10.10.15.15 +biganswer.big. IN A 10.10.15.16 +biganswer.big. IN A 10.10.15.17 +biganswer.big. IN A 10.10.15.18 +biganswer.big. IN A 10.10.15.19 +biganswer.big. IN A 10.10.15.20 +biganswer.big. IN A 10.10.15.21 +biganswer.big. IN A 10.10.15.22 +biganswer.big. IN A 10.10.15.23 +biganswer.big. IN A 10.10.15.24 +biganswer.big. IN A 10.10.15.25 +biganswer.big. IN A 10.10.15.26 +biganswer.big. IN A 10.10.15.27 +biganswer.big. IN A 10.10.15.28 +biganswer.big. IN A 10.10.15.29 +biganswer.big. IN A 10.10.15.30 +biganswer.big. IN A 10.10.15.31 +biganswer.big. IN A 10.10.15.32 +biganswer.big. IN A 10.10.15.33 +biganswer.big. IN A 10.10.15.34 +biganswer.big. IN A 10.10.15.35 +biganswer.big. IN A 10.10.15.36 +biganswer.big. IN A 10.10.15.37 +biganswer.big. IN A 10.10.15.38 +biganswer.big. IN A 10.10.15.39 +biganswer.big. IN A 10.10.15.40 +biganswer.big. IN A 10.10.15.41 +biganswer.big. IN A 10.10.15.42 +biganswer.big. IN A 10.10.15.43 +biganswer.big. IN A 10.10.15.44 +biganswer.big. IN A 10.10.15.45 +biganswer.big. IN A 10.10.15.46 +biganswer.big. IN A 10.10.15.47 +biganswer.big. IN A 10.10.15.48 +biganswer.big. IN A 10.10.15.49 +biganswer.big. IN A 10.10.15.50 +biganswer.big. IN A 10.10.16.1 +biganswer.big. IN A 10.10.16.2 +biganswer.big. IN A 10.10.16.3 +biganswer.big. IN A 10.10.16.4 +biganswer.big. IN A 10.10.16.5 +biganswer.big. IN A 10.10.16.6 +biganswer.big. IN A 10.10.16.7 +biganswer.big. IN A 10.10.16.8 +biganswer.big. IN A 10.10.16.9 +biganswer.big. IN A 10.10.16.10 +biganswer.big. IN A 10.10.16.11 +biganswer.big. IN A 10.10.16.12 +biganswer.big. IN A 10.10.16.13 +biganswer.big. IN A 10.10.16.14 +biganswer.big. IN A 10.10.16.15 +biganswer.big. IN A 10.10.16.16 +biganswer.big. IN A 10.10.16.17 +biganswer.big. IN A 10.10.16.18 +biganswer.big. IN A 10.10.16.19 +biganswer.big. IN A 10.10.16.20 +biganswer.big. IN A 10.10.16.21 +biganswer.big. IN A 10.10.16.22 +biganswer.big. IN A 10.10.16.23 +biganswer.big. IN A 10.10.16.24 +biganswer.big. IN A 10.10.16.25 +biganswer.big. IN A 10.10.16.26 +biganswer.big. IN A 10.10.16.27 +biganswer.big. IN A 10.10.16.28 +biganswer.big. IN A 10.10.16.29 +biganswer.big. IN A 10.10.16.30 +biganswer.big. IN A 10.10.16.31 +biganswer.big. IN A 10.10.16.32 +biganswer.big. IN A 10.10.16.33 +biganswer.big. IN A 10.10.16.34 +biganswer.big. IN A 10.10.16.35 +biganswer.big. IN A 10.10.16.36 +biganswer.big. IN A 10.10.16.37 +biganswer.big. IN A 10.10.16.38 +biganswer.big. IN A 10.10.16.39 +biganswer.big. IN A 10.10.16.40 +biganswer.big. IN A 10.10.16.41 +biganswer.big. IN A 10.10.16.42 +biganswer.big. IN A 10.10.16.43 +biganswer.big. IN A 10.10.16.44 +biganswer.big. IN A 10.10.16.45 +biganswer.big. IN A 10.10.16.46 +biganswer.big. IN A 10.10.16.47 +biganswer.big. IN A 10.10.16.48 +biganswer.big. IN A 10.10.16.49 +biganswer.big. IN A 10.10.16.50 +biganswer.big. IN A 10.10.17.1 +biganswer.big. IN A 10.10.17.2 +biganswer.big. IN A 10.10.17.3 +biganswer.big. IN A 10.10.17.4 +biganswer.big. IN A 10.10.17.5 +biganswer.big. IN A 10.10.17.6 +biganswer.big. IN A 10.10.17.7 +biganswer.big. IN A 10.10.17.8 +biganswer.big. IN A 10.10.17.9 +biganswer.big. IN A 10.10.17.10 +biganswer.big. IN A 10.10.17.11 +biganswer.big. IN A 10.10.17.12 +biganswer.big. IN A 10.10.17.13 +biganswer.big. IN A 10.10.17.14 +biganswer.big. IN A 10.10.17.15 +biganswer.big. IN A 10.10.17.16 +biganswer.big. IN A 10.10.17.17 +biganswer.big. IN A 10.10.17.18 +biganswer.big. IN A 10.10.17.19 +biganswer.big. IN A 10.10.17.20 +biganswer.big. IN A 10.10.17.21 +biganswer.big. IN A 10.10.17.22 +biganswer.big. IN A 10.10.17.23 +biganswer.big. IN A 10.10.17.24 +biganswer.big. IN A 10.10.17.25 +biganswer.big. IN A 10.10.17.26 +biganswer.big. IN A 10.10.17.27 +biganswer.big. IN A 10.10.17.28 +biganswer.big. IN A 10.10.17.29 +biganswer.big. IN A 10.10.17.30 +biganswer.big. IN A 10.10.17.31 +biganswer.big. IN A 10.10.17.32 +biganswer.big. IN A 10.10.17.33 +biganswer.big. IN A 10.10.17.34 +biganswer.big. IN A 10.10.17.35 +biganswer.big. IN A 10.10.17.36 +biganswer.big. IN A 10.10.17.37 +biganswer.big. IN A 10.10.17.38 +biganswer.big. IN A 10.10.17.39 +biganswer.big. IN A 10.10.17.40 +biganswer.big. IN A 10.10.17.41 +biganswer.big. IN A 10.10.17.42 +biganswer.big. IN A 10.10.17.43 +biganswer.big. IN A 10.10.17.44 +biganswer.big. IN A 10.10.17.45 +biganswer.big. IN A 10.10.17.46 +biganswer.big. IN A 10.10.17.47 +biganswer.big. IN A 10.10.17.48 +biganswer.big. IN A 10.10.17.49 +biganswer.big. IN A 10.10.17.50 +biganswer.big. IN A 10.10.18.1 +biganswer.big. IN A 10.10.18.2 +biganswer.big. IN A 10.10.18.3 +biganswer.big. IN A 10.10.18.4 +biganswer.big. IN A 10.10.18.5 +biganswer.big. IN A 10.10.18.6 +biganswer.big. IN A 10.10.18.7 +biganswer.big. IN A 10.10.18.8 +biganswer.big. IN A 10.10.18.9 +biganswer.big. IN A 10.10.18.10 +biganswer.big. IN A 10.10.18.11 +biganswer.big. IN A 10.10.18.12 +biganswer.big. IN A 10.10.18.13 +biganswer.big. IN A 10.10.18.14 +biganswer.big. IN A 10.10.18.15 +biganswer.big. IN A 10.10.18.16 +biganswer.big. IN A 10.10.18.17 +biganswer.big. IN A 10.10.18.18 +biganswer.big. IN A 10.10.18.19 +biganswer.big. IN A 10.10.18.20 +biganswer.big. IN A 10.10.18.21 +biganswer.big. IN A 10.10.18.22 +biganswer.big. IN A 10.10.18.23 +biganswer.big. IN A 10.10.18.24 +biganswer.big. IN A 10.10.18.25 +biganswer.big. IN A 10.10.18.26 +biganswer.big. IN A 10.10.18.27 +biganswer.big. IN A 10.10.18.28 +biganswer.big. IN A 10.10.18.29 +biganswer.big. IN A 10.10.18.30 +biganswer.big. IN A 10.10.18.31 +biganswer.big. IN A 10.10.18.32 +biganswer.big. IN A 10.10.18.33 +biganswer.big. IN A 10.10.18.34 +biganswer.big. IN A 10.10.18.35 +biganswer.big. IN A 10.10.18.36 +biganswer.big. IN A 10.10.18.37 +biganswer.big. IN A 10.10.18.38 +biganswer.big. IN A 10.10.18.39 +biganswer.big. IN A 10.10.18.40 +biganswer.big. IN A 10.10.18.41 +biganswer.big. IN A 10.10.18.42 +biganswer.big. IN A 10.10.18.43 +biganswer.big. IN A 10.10.18.44 +biganswer.big. IN A 10.10.18.45 +biganswer.big. IN A 10.10.18.46 +biganswer.big. IN A 10.10.18.47 +biganswer.big. IN A 10.10.18.48 +biganswer.big. IN A 10.10.18.49 +biganswer.big. IN A 10.10.18.50 +biganswer.big. IN A 10.10.19.1 +biganswer.big. IN A 10.10.19.2 +biganswer.big. IN A 10.10.19.3 +biganswer.big. IN A 10.10.19.4 +biganswer.big. IN A 10.10.19.5 +biganswer.big. IN A 10.10.19.6 +biganswer.big. IN A 10.10.19.7 +biganswer.big. IN A 10.10.19.8 +biganswer.big. IN A 10.10.19.9 +biganswer.big. IN A 10.10.19.10 +biganswer.big. IN A 10.10.19.11 +biganswer.big. IN A 10.10.19.12 +biganswer.big. IN A 10.10.19.13 +biganswer.big. IN A 10.10.19.14 +biganswer.big. IN A 10.10.19.15 +biganswer.big. IN A 10.10.19.16 +biganswer.big. IN A 10.10.19.17 +biganswer.big. IN A 10.10.19.18 +biganswer.big. IN A 10.10.19.19 +biganswer.big. IN A 10.10.19.20 +biganswer.big. IN A 10.10.19.21 +biganswer.big. IN A 10.10.19.22 +biganswer.big. IN A 10.10.19.23 +biganswer.big. IN A 10.10.19.24 +biganswer.big. IN A 10.10.19.25 +biganswer.big. IN A 10.10.19.26 +biganswer.big. IN A 10.10.19.27 +biganswer.big. IN A 10.10.19.28 +biganswer.big. IN A 10.10.19.29 +biganswer.big. IN A 10.10.19.30 +biganswer.big. IN A 10.10.19.31 +biganswer.big. IN A 10.10.19.32 +biganswer.big. IN A 10.10.19.33 +biganswer.big. IN A 10.10.19.34 +biganswer.big. IN A 10.10.19.35 +biganswer.big. IN A 10.10.19.36 +biganswer.big. IN A 10.10.19.37 +biganswer.big. IN A 10.10.19.38 +biganswer.big. IN A 10.10.19.39 +biganswer.big. IN A 10.10.19.40 +biganswer.big. IN A 10.10.19.41 +biganswer.big. IN A 10.10.19.42 +biganswer.big. IN A 10.10.19.43 +biganswer.big. IN A 10.10.19.44 +biganswer.big. IN A 10.10.19.45 +biganswer.big. IN A 10.10.19.46 +biganswer.big. IN A 10.10.19.47 +biganswer.big. IN A 10.10.19.48 +biganswer.big. IN A 10.10.19.49 +biganswer.big. IN A 10.10.19.50 +biganswer.big. IN A 10.10.20.1 +biganswer.big. IN A 10.10.20.2 +biganswer.big. IN A 10.10.20.3 +biganswer.big. IN A 10.10.20.4 +biganswer.big. IN A 10.10.20.5 +biganswer.big. IN A 10.10.20.6 +biganswer.big. IN A 10.10.20.7 +biganswer.big. IN A 10.10.20.8 +biganswer.big. IN A 10.10.20.9 +biganswer.big. IN A 10.10.20.10 +biganswer.big. IN A 10.10.20.11 +biganswer.big. IN A 10.10.20.12 +biganswer.big. IN A 10.10.20.13 +biganswer.big. IN A 10.10.20.14 +biganswer.big. IN A 10.10.20.15 +biganswer.big. IN A 10.10.20.16 +biganswer.big. IN A 10.10.20.17 +biganswer.big. IN A 10.10.20.18 +biganswer.big. IN A 10.10.20.19 +biganswer.big. IN A 10.10.20.20 +biganswer.big. IN A 10.10.20.21 +biganswer.big. IN A 10.10.20.22 +biganswer.big. IN A 10.10.20.23 +biganswer.big. IN A 10.10.20.24 +biganswer.big. IN A 10.10.20.25 +biganswer.big. IN A 10.10.20.26 +biganswer.big. IN A 10.10.20.27 +biganswer.big. IN A 10.10.20.28 +biganswer.big. IN A 10.10.20.29 +biganswer.big. IN A 10.10.20.30 +biganswer.big. IN A 10.10.20.31 +biganswer.big. IN A 10.10.20.32 +biganswer.big. IN A 10.10.20.33 +biganswer.big. IN A 10.10.20.34 +biganswer.big. IN A 10.10.20.35 +biganswer.big. IN A 10.10.20.36 +biganswer.big. IN A 10.10.20.37 +biganswer.big. IN A 10.10.20.38 +biganswer.big. IN A 10.10.20.39 +biganswer.big. IN A 10.10.20.40 +biganswer.big. IN A 10.10.20.41 +biganswer.big. IN A 10.10.20.42 +biganswer.big. IN A 10.10.20.43 +biganswer.big. IN A 10.10.20.44 +biganswer.big. IN A 10.10.20.45 +biganswer.big. IN A 10.10.20.46 +biganswer.big. IN A 10.10.20.47 +biganswer.big. IN A 10.10.20.48 +biganswer.big. IN A 10.10.20.49 +biganswer.big. IN A 10.10.20.50 +biganswer.big. IN A 10.10.21.1 +biganswer.big. IN A 10.10.21.2 +biganswer.big. IN A 10.10.21.3 +biganswer.big. IN A 10.10.21.4 +biganswer.big. IN A 10.10.21.5 +biganswer.big. IN A 10.10.21.6 +biganswer.big. IN A 10.10.21.7 +biganswer.big. IN A 10.10.21.8 +biganswer.big. IN A 10.10.21.9 +biganswer.big. IN A 10.10.21.10 +biganswer.big. IN A 10.10.21.11 +biganswer.big. IN A 10.10.21.12 +biganswer.big. IN A 10.10.21.13 +biganswer.big. IN A 10.10.21.14 +biganswer.big. IN A 10.10.21.15 +biganswer.big. IN A 10.10.21.16 +biganswer.big. IN A 10.10.21.17 +biganswer.big. IN A 10.10.21.18 +biganswer.big. IN A 10.10.21.19 +biganswer.big. IN A 10.10.21.20 +biganswer.big. IN A 10.10.21.21 +biganswer.big. IN A 10.10.21.22 +biganswer.big. IN A 10.10.21.23 +biganswer.big. IN A 10.10.21.24 +biganswer.big. IN A 10.10.21.25 +biganswer.big. IN A 10.10.21.26 +biganswer.big. IN A 10.10.21.27 +biganswer.big. IN A 10.10.21.28 +biganswer.big. IN A 10.10.21.29 +biganswer.big. IN A 10.10.21.30 +biganswer.big. IN A 10.10.21.31 +biganswer.big. IN A 10.10.21.32 +biganswer.big. IN A 10.10.21.33 +biganswer.big. IN A 10.10.21.34 +biganswer.big. IN A 10.10.21.35 +biganswer.big. IN A 10.10.21.36 +biganswer.big. IN A 10.10.21.37 +biganswer.big. IN A 10.10.21.38 +biganswer.big. IN A 10.10.21.39 +biganswer.big. IN A 10.10.21.40 +biganswer.big. IN A 10.10.21.41 +biganswer.big. IN A 10.10.21.42 +biganswer.big. IN A 10.10.21.43 +biganswer.big. IN A 10.10.21.44 +biganswer.big. IN A 10.10.21.45 +biganswer.big. IN A 10.10.21.46 +biganswer.big. IN A 10.10.21.47 +biganswer.big. IN A 10.10.21.48 +biganswer.big. IN A 10.10.21.49 +biganswer.big. IN A 10.10.21.50 +biganswer.big. IN A 10.10.22.1 +biganswer.big. IN A 10.10.22.2 +biganswer.big. IN A 10.10.22.3 +biganswer.big. IN A 10.10.22.4 +biganswer.big. IN A 10.10.22.5 +biganswer.big. IN A 10.10.22.6 +biganswer.big. IN A 10.10.22.7 +biganswer.big. IN A 10.10.22.8 +biganswer.big. IN A 10.10.22.9 +biganswer.big. IN A 10.10.22.10 +biganswer.big. IN A 10.10.22.11 +biganswer.big. IN A 10.10.22.12 +biganswer.big. IN A 10.10.22.13 +biganswer.big. IN A 10.10.22.14 +biganswer.big. IN A 10.10.22.15 +biganswer.big. IN A 10.10.22.16 +biganswer.big. IN A 10.10.22.17 +biganswer.big. IN A 10.10.22.18 +biganswer.big. IN A 10.10.22.19 +biganswer.big. IN A 10.10.22.20 +biganswer.big. IN A 10.10.22.21 +biganswer.big. IN A 10.10.22.22 +biganswer.big. IN A 10.10.22.23 +biganswer.big. IN A 10.10.22.24 +biganswer.big. IN A 10.10.22.25 +biganswer.big. IN A 10.10.22.26 +biganswer.big. IN A 10.10.22.27 +biganswer.big. IN A 10.10.22.28 +biganswer.big. IN A 10.10.22.29 +biganswer.big. IN A 10.10.22.30 +biganswer.big. IN A 10.10.22.31 +biganswer.big. IN A 10.10.22.32 +biganswer.big. IN A 10.10.22.33 +biganswer.big. IN A 10.10.22.34 +biganswer.big. IN A 10.10.22.35 +biganswer.big. IN A 10.10.22.36 +biganswer.big. IN A 10.10.22.37 +biganswer.big. IN A 10.10.22.38 +biganswer.big. IN A 10.10.22.39 +biganswer.big. IN A 10.10.22.40 +biganswer.big. IN A 10.10.22.41 +biganswer.big. IN A 10.10.22.42 +biganswer.big. IN A 10.10.22.43 +biganswer.big. IN A 10.10.22.44 +biganswer.big. IN A 10.10.22.45 +biganswer.big. IN A 10.10.22.46 +biganswer.big. IN A 10.10.22.47 +biganswer.big. IN A 10.10.22.48 +biganswer.big. IN A 10.10.22.49 +biganswer.big. IN A 10.10.22.50 +biganswer.big. IN A 10.10.23.1 +biganswer.big. IN A 10.10.23.2 +biganswer.big. IN A 10.10.23.3 +biganswer.big. IN A 10.10.23.4 +biganswer.big. IN A 10.10.23.5 +biganswer.big. IN A 10.10.23.6 +biganswer.big. IN A 10.10.23.7 +biganswer.big. IN A 10.10.23.8 +biganswer.big. IN A 10.10.23.9 +biganswer.big. IN A 10.10.23.10 +biganswer.big. IN A 10.10.23.11 +biganswer.big. IN A 10.10.23.12 +biganswer.big. IN A 10.10.23.13 +biganswer.big. IN A 10.10.23.14 +biganswer.big. IN A 10.10.23.15 +biganswer.big. IN A 10.10.23.16 +biganswer.big. IN A 10.10.23.17 +biganswer.big. IN A 10.10.23.18 +biganswer.big. IN A 10.10.23.19 +biganswer.big. IN A 10.10.23.20 +biganswer.big. IN A 10.10.23.21 +biganswer.big. IN A 10.10.23.22 +biganswer.big. IN A 10.10.23.23 +biganswer.big. IN A 10.10.23.24 +biganswer.big. IN A 10.10.23.25 +biganswer.big. IN A 10.10.23.26 +biganswer.big. IN A 10.10.23.27 +biganswer.big. IN A 10.10.23.28 +biganswer.big. IN A 10.10.23.29 +biganswer.big. IN A 10.10.23.30 +biganswer.big. IN A 10.10.23.31 +biganswer.big. IN A 10.10.23.32 +biganswer.big. IN A 10.10.23.33 +biganswer.big. IN A 10.10.23.34 +biganswer.big. IN A 10.10.23.35 +biganswer.big. IN A 10.10.23.36 +biganswer.big. IN A 10.10.23.37 +biganswer.big. IN A 10.10.23.38 +biganswer.big. IN A 10.10.23.39 +biganswer.big. IN A 10.10.23.40 +biganswer.big. IN A 10.10.23.41 +biganswer.big. IN A 10.10.23.42 +biganswer.big. IN A 10.10.23.43 +biganswer.big. IN A 10.10.23.44 +biganswer.big. IN A 10.10.23.45 +biganswer.big. IN A 10.10.23.46 +biganswer.big. IN A 10.10.23.47 +biganswer.big. IN A 10.10.23.48 +biganswer.big. IN A 10.10.23.49 +biganswer.big. IN A 10.10.23.50 +biganswer.big. IN A 10.10.24.1 +biganswer.big. IN A 10.10.24.2 +biganswer.big. IN A 10.10.24.3 +biganswer.big. IN A 10.10.24.4 +biganswer.big. IN A 10.10.24.5 +biganswer.big. IN A 10.10.24.6 +biganswer.big. IN A 10.10.24.7 +biganswer.big. IN A 10.10.24.8 +biganswer.big. IN A 10.10.24.9 +biganswer.big. IN A 10.10.24.10 +biganswer.big. IN A 10.10.24.11 +biganswer.big. IN A 10.10.24.12 +biganswer.big. IN A 10.10.24.13 +biganswer.big. IN A 10.10.24.14 +biganswer.big. IN A 10.10.24.15 +biganswer.big. IN A 10.10.24.16 +biganswer.big. IN A 10.10.24.17 +biganswer.big. IN A 10.10.24.18 +biganswer.big. IN A 10.10.24.19 +biganswer.big. IN A 10.10.24.20 +biganswer.big. IN A 10.10.24.21 +biganswer.big. IN A 10.10.24.22 +biganswer.big. IN A 10.10.24.23 +biganswer.big. IN A 10.10.24.24 +biganswer.big. IN A 10.10.24.25 +biganswer.big. IN A 10.10.24.26 +biganswer.big. IN A 10.10.24.27 +biganswer.big. IN A 10.10.24.28 +biganswer.big. IN A 10.10.24.29 +biganswer.big. IN A 10.10.24.30 +biganswer.big. IN A 10.10.24.31 +biganswer.big. IN A 10.10.24.32 +biganswer.big. IN A 10.10.24.33 +biganswer.big. IN A 10.10.24.34 +biganswer.big. IN A 10.10.24.35 +biganswer.big. IN A 10.10.24.36 +biganswer.big. IN A 10.10.24.37 +biganswer.big. IN A 10.10.24.38 +biganswer.big. IN A 10.10.24.39 +biganswer.big. IN A 10.10.24.40 +biganswer.big. IN A 10.10.24.41 +biganswer.big. IN A 10.10.24.42 +biganswer.big. IN A 10.10.24.43 +biganswer.big. IN A 10.10.24.44 +biganswer.big. IN A 10.10.24.45 +biganswer.big. IN A 10.10.24.46 +biganswer.big. IN A 10.10.24.47 +biganswer.big. IN A 10.10.24.48 +biganswer.big. IN A 10.10.24.49 +biganswer.big. IN A 10.10.24.50 +biganswer.big. IN A 10.10.25.1 +biganswer.big. IN A 10.10.25.2 +biganswer.big. IN A 10.10.25.3 +biganswer.big. IN A 10.10.25.4 +biganswer.big. IN A 10.10.25.5 +biganswer.big. IN A 10.10.25.6 +biganswer.big. IN A 10.10.25.7 +biganswer.big. IN A 10.10.25.8 +biganswer.big. IN A 10.10.25.9 +biganswer.big. IN A 10.10.25.10 +biganswer.big. IN A 10.10.25.11 +biganswer.big. IN A 10.10.25.12 +biganswer.big. IN A 10.10.25.13 +biganswer.big. IN A 10.10.25.14 +biganswer.big. IN A 10.10.25.15 +biganswer.big. IN A 10.10.25.16 +biganswer.big. IN A 10.10.25.17 +biganswer.big. IN A 10.10.25.18 +biganswer.big. IN A 10.10.25.19 +biganswer.big. IN A 10.10.25.20 +biganswer.big. IN A 10.10.25.21 +biganswer.big. IN A 10.10.25.22 +biganswer.big. IN A 10.10.25.23 +biganswer.big. IN A 10.10.25.24 +biganswer.big. IN A 10.10.25.25 +biganswer.big. IN A 10.10.25.26 +biganswer.big. IN A 10.10.25.27 +biganswer.big. IN A 10.10.25.28 +biganswer.big. IN A 10.10.25.29 +biganswer.big. IN A 10.10.25.30 +biganswer.big. IN A 10.10.25.31 +biganswer.big. IN A 10.10.25.32 +biganswer.big. IN A 10.10.25.33 +biganswer.big. IN A 10.10.25.34 +biganswer.big. IN A 10.10.25.35 +biganswer.big. IN A 10.10.25.36 +biganswer.big. IN A 10.10.25.37 +biganswer.big. IN A 10.10.25.38 +biganswer.big. IN A 10.10.25.39 +biganswer.big. IN A 10.10.25.40 +biganswer.big. IN A 10.10.25.41 +biganswer.big. IN A 10.10.25.42 +biganswer.big. IN A 10.10.25.43 +biganswer.big. IN A 10.10.25.44 +biganswer.big. IN A 10.10.25.45 +biganswer.big. IN A 10.10.25.46 +biganswer.big. IN A 10.10.25.47 +biganswer.big. IN A 10.10.25.48 +biganswer.big. IN A 10.10.25.49 +biganswer.big. IN A 10.10.25.50 +biganswer.big. IN A 10.10.26.1 +biganswer.big. IN A 10.10.26.2 +biganswer.big. IN A 10.10.26.3 +biganswer.big. IN A 10.10.26.4 +biganswer.big. IN A 10.10.26.5 +biganswer.big. IN A 10.10.26.6 +biganswer.big. IN A 10.10.26.7 +biganswer.big. IN A 10.10.26.8 +biganswer.big. IN A 10.10.26.9 +biganswer.big. IN A 10.10.26.10 +biganswer.big. IN A 10.10.26.11 +biganswer.big. IN A 10.10.26.12 +biganswer.big. IN A 10.10.26.13 +biganswer.big. IN A 10.10.26.14 +biganswer.big. IN A 10.10.26.15 +biganswer.big. IN A 10.10.26.16 +biganswer.big. IN A 10.10.26.17 +biganswer.big. IN A 10.10.26.18 +biganswer.big. IN A 10.10.26.19 +biganswer.big. IN A 10.10.26.20 +biganswer.big. IN A 10.10.26.21 +biganswer.big. IN A 10.10.26.22 +biganswer.big. IN A 10.10.26.23 +biganswer.big. IN A 10.10.26.24 +biganswer.big. IN A 10.10.26.25 +biganswer.big. IN A 10.10.26.26 +biganswer.big. IN A 10.10.26.27 +biganswer.big. IN A 10.10.26.28 +biganswer.big. IN A 10.10.26.29 +biganswer.big. IN A 10.10.26.30 +biganswer.big. IN A 10.10.26.31 +biganswer.big. IN A 10.10.26.32 +biganswer.big. IN A 10.10.26.33 +biganswer.big. IN A 10.10.26.34 +biganswer.big. IN A 10.10.26.35 +biganswer.big. IN A 10.10.26.36 +biganswer.big. IN A 10.10.26.37 +biganswer.big. IN A 10.10.26.38 +biganswer.big. IN A 10.10.26.39 +biganswer.big. IN A 10.10.26.40 +biganswer.big. IN A 10.10.26.41 +biganswer.big. IN A 10.10.26.42 +biganswer.big. IN A 10.10.26.43 +biganswer.big. IN A 10.10.26.44 +biganswer.big. IN A 10.10.26.45 +biganswer.big. IN A 10.10.26.46 +biganswer.big. IN A 10.10.26.47 +biganswer.big. IN A 10.10.26.48 +biganswer.big. IN A 10.10.26.49 +biganswer.big. IN A 10.10.26.50 +biganswer.big. IN A 10.10.27.1 +biganswer.big. IN A 10.10.27.2 +biganswer.big. IN A 10.10.27.3 +biganswer.big. IN A 10.10.27.4 +biganswer.big. IN A 10.10.27.5 +biganswer.big. IN A 10.10.27.6 +biganswer.big. IN A 10.10.27.7 +biganswer.big. IN A 10.10.27.8 +biganswer.big. IN A 10.10.27.9 +biganswer.big. IN A 10.10.27.10 +biganswer.big. IN A 10.10.27.11 +biganswer.big. IN A 10.10.27.12 +biganswer.big. IN A 10.10.27.13 +biganswer.big. IN A 10.10.27.14 +biganswer.big. IN A 10.10.27.15 +biganswer.big. IN A 10.10.27.16 +biganswer.big. IN A 10.10.27.17 +biganswer.big. IN A 10.10.27.18 +biganswer.big. IN A 10.10.27.19 +biganswer.big. IN A 10.10.27.20 +biganswer.big. IN A 10.10.27.21 +biganswer.big. IN A 10.10.27.22 +biganswer.big. IN A 10.10.27.23 +biganswer.big. IN A 10.10.27.24 +biganswer.big. IN A 10.10.27.25 +biganswer.big. IN A 10.10.27.26 +biganswer.big. IN A 10.10.27.27 +biganswer.big. IN A 10.10.27.28 +biganswer.big. IN A 10.10.27.29 +biganswer.big. IN A 10.10.27.30 +biganswer.big. IN A 10.10.27.31 +biganswer.big. IN A 10.10.27.32 +biganswer.big. IN A 10.10.27.33 +biganswer.big. IN A 10.10.27.34 +biganswer.big. IN A 10.10.27.35 +biganswer.big. IN A 10.10.27.36 +biganswer.big. IN A 10.10.27.37 +biganswer.big. IN A 10.10.27.38 +biganswer.big. IN A 10.10.27.39 +biganswer.big. IN A 10.10.27.40 +biganswer.big. IN A 10.10.27.41 +biganswer.big. IN A 10.10.27.42 +biganswer.big. IN A 10.10.27.43 +biganswer.big. IN A 10.10.27.44 +biganswer.big. IN A 10.10.27.45 +biganswer.big. IN A 10.10.27.46 +biganswer.big. IN A 10.10.27.47 +biganswer.big. IN A 10.10.27.48 +biganswer.big. IN A 10.10.27.49 +biganswer.big. IN A 10.10.27.50 +biganswer.big. IN A 10.10.28.1 +biganswer.big. IN A 10.10.28.2 +biganswer.big. IN A 10.10.28.3 +biganswer.big. IN A 10.10.28.4 +biganswer.big. IN A 10.10.28.5 +biganswer.big. IN A 10.10.28.6 +biganswer.big. IN A 10.10.28.7 +biganswer.big. IN A 10.10.28.8 +biganswer.big. IN A 10.10.28.9 +biganswer.big. IN A 10.10.28.10 +biganswer.big. IN A 10.10.28.11 +biganswer.big. IN A 10.10.28.12 +biganswer.big. IN A 10.10.28.13 +biganswer.big. IN A 10.10.28.14 +biganswer.big. IN A 10.10.28.15 +biganswer.big. IN A 10.10.28.16 +biganswer.big. IN A 10.10.28.17 +biganswer.big. IN A 10.10.28.18 +biganswer.big. IN A 10.10.28.19 +biganswer.big. IN A 10.10.28.20 +biganswer.big. IN A 10.10.28.21 +biganswer.big. IN A 10.10.28.22 +biganswer.big. IN A 10.10.28.23 +biganswer.big. IN A 10.10.28.24 +biganswer.big. IN A 10.10.28.25 +biganswer.big. IN A 10.10.28.26 +biganswer.big. IN A 10.10.28.27 +biganswer.big. IN A 10.10.28.28 +biganswer.big. IN A 10.10.28.29 +biganswer.big. IN A 10.10.28.30 +biganswer.big. IN A 10.10.28.31 +biganswer.big. IN A 10.10.28.32 +biganswer.big. IN A 10.10.28.33 +biganswer.big. IN A 10.10.28.34 +biganswer.big. IN A 10.10.28.35 +biganswer.big. IN A 10.10.28.36 +biganswer.big. IN A 10.10.28.37 +biganswer.big. IN A 10.10.28.38 +biganswer.big. IN A 10.10.28.39 +biganswer.big. IN A 10.10.28.40 +biganswer.big. IN A 10.10.28.41 +biganswer.big. IN A 10.10.28.42 +biganswer.big. IN A 10.10.28.43 +biganswer.big. IN A 10.10.28.44 +biganswer.big. IN A 10.10.28.45 +biganswer.big. IN A 10.10.28.46 +biganswer.big. IN A 10.10.28.47 +biganswer.big. IN A 10.10.28.48 +biganswer.big. IN A 10.10.28.49 +biganswer.big. IN A 10.10.28.50 +biganswer.big. IN A 10.10.29.1 +biganswer.big. IN A 10.10.29.2 +biganswer.big. IN A 10.10.29.3 +biganswer.big. IN A 10.10.29.4 +biganswer.big. IN A 10.10.29.5 +biganswer.big. IN A 10.10.29.6 +biganswer.big. IN A 10.10.29.7 +biganswer.big. IN A 10.10.29.8 +biganswer.big. IN A 10.10.29.9 +biganswer.big. IN A 10.10.29.10 +biganswer.big. IN A 10.10.29.11 +biganswer.big. IN A 10.10.29.12 +biganswer.big. IN A 10.10.29.13 +biganswer.big. IN A 10.10.29.14 +biganswer.big. IN A 10.10.29.15 +biganswer.big. IN A 10.10.29.16 +biganswer.big. IN A 10.10.29.17 +biganswer.big. IN A 10.10.29.18 +biganswer.big. IN A 10.10.29.19 +biganswer.big. IN A 10.10.29.20 +biganswer.big. IN A 10.10.29.21 +biganswer.big. IN A 10.10.29.22 +biganswer.big. IN A 10.10.29.23 +biganswer.big. IN A 10.10.29.24 +biganswer.big. IN A 10.10.29.25 +biganswer.big. IN A 10.10.29.26 +biganswer.big. IN A 10.10.29.27 +biganswer.big. IN A 10.10.29.28 +biganswer.big. IN A 10.10.29.29 +biganswer.big. IN A 10.10.29.30 +biganswer.big. IN A 10.10.29.31 +biganswer.big. IN A 10.10.29.32 +biganswer.big. IN A 10.10.29.33 +biganswer.big. IN A 10.10.29.34 +biganswer.big. IN A 10.10.29.35 +biganswer.big. IN A 10.10.29.36 +biganswer.big. IN A 10.10.29.37 +biganswer.big. IN A 10.10.29.38 +biganswer.big. IN A 10.10.29.39 +biganswer.big. IN A 10.10.29.40 +biganswer.big. IN A 10.10.29.41 +biganswer.big. IN A 10.10.29.42 +biganswer.big. IN A 10.10.29.43 +biganswer.big. IN A 10.10.29.44 +biganswer.big. IN A 10.10.29.45 +biganswer.big. IN A 10.10.29.46 +biganswer.big. IN A 10.10.29.47 +biganswer.big. IN A 10.10.29.48 +biganswer.big. IN A 10.10.29.49 +biganswer.big. IN A 10.10.29.50 +biganswer.big. IN A 10.10.30.1 +biganswer.big. IN A 10.10.30.2 +biganswer.big. IN A 10.10.30.3 +biganswer.big. IN A 10.10.30.4 +biganswer.big. IN A 10.10.30.5 +biganswer.big. IN A 10.10.30.6 +biganswer.big. IN A 10.10.30.7 +biganswer.big. IN A 10.10.30.8 +biganswer.big. IN A 10.10.30.9 +biganswer.big. IN A 10.10.30.10 +biganswer.big. IN A 10.10.30.11 +biganswer.big. IN A 10.10.30.12 +biganswer.big. IN A 10.10.30.13 +biganswer.big. IN A 10.10.30.14 +biganswer.big. IN A 10.10.30.15 +biganswer.big. IN A 10.10.30.16 +biganswer.big. IN A 10.10.30.17 +biganswer.big. IN A 10.10.30.18 +biganswer.big. IN A 10.10.30.19 +biganswer.big. IN A 10.10.30.20 +biganswer.big. IN A 10.10.30.21 +biganswer.big. IN A 10.10.30.22 +biganswer.big. IN A 10.10.30.23 +biganswer.big. IN A 10.10.30.24 +biganswer.big. IN A 10.10.30.25 +biganswer.big. IN A 10.10.30.26 +biganswer.big. IN A 10.10.30.27 +biganswer.big. IN A 10.10.30.28 +biganswer.big. IN A 10.10.30.29 +biganswer.big. IN A 10.10.30.30 +biganswer.big. IN A 10.10.30.31 +biganswer.big. IN A 10.10.30.32 +biganswer.big. IN A 10.10.30.33 +biganswer.big. IN A 10.10.30.34 +biganswer.big. IN A 10.10.30.35 +biganswer.big. IN A 10.10.30.36 +biganswer.big. IN A 10.10.30.37 +biganswer.big. IN A 10.10.30.38 +biganswer.big. IN A 10.10.30.39 +biganswer.big. IN A 10.10.30.40 +biganswer.big. IN A 10.10.30.41 +biganswer.big. IN A 10.10.30.42 +biganswer.big. IN A 10.10.30.43 +biganswer.big. IN A 10.10.30.44 +biganswer.big. IN A 10.10.30.45 +biganswer.big. IN A 10.10.30.46 +biganswer.big. IN A 10.10.30.47 +biganswer.big. IN A 10.10.30.48 +biganswer.big. IN A 10.10.30.49 +biganswer.big. IN A 10.10.30.50 +biganswer.big. IN A 10.10.31.1 +biganswer.big. IN A 10.10.31.2 +biganswer.big. IN A 10.10.31.3 +biganswer.big. IN A 10.10.31.4 +biganswer.big. IN A 10.10.31.5 +biganswer.big. IN A 10.10.31.6 +biganswer.big. IN A 10.10.31.7 +biganswer.big. IN A 10.10.31.8 +biganswer.big. IN A 10.10.31.9 +biganswer.big. IN A 10.10.31.10 +biganswer.big. IN A 10.10.31.11 +biganswer.big. IN A 10.10.31.12 +biganswer.big. IN A 10.10.31.13 +biganswer.big. IN A 10.10.31.14 +biganswer.big. IN A 10.10.31.15 +biganswer.big. IN A 10.10.31.16 +biganswer.big. IN A 10.10.31.17 +biganswer.big. IN A 10.10.31.18 +biganswer.big. IN A 10.10.31.19 +biganswer.big. IN A 10.10.31.20 +biganswer.big. IN A 10.10.31.21 +biganswer.big. IN A 10.10.31.22 +biganswer.big. IN A 10.10.31.23 +biganswer.big. IN A 10.10.31.24 +biganswer.big. IN A 10.10.31.25 +biganswer.big. IN A 10.10.31.26 +biganswer.big. IN A 10.10.31.27 +biganswer.big. IN A 10.10.31.28 +biganswer.big. IN A 10.10.31.29 +biganswer.big. IN A 10.10.31.30 +biganswer.big. IN A 10.10.31.31 +biganswer.big. IN A 10.10.31.32 +biganswer.big. IN A 10.10.31.33 +biganswer.big. IN A 10.10.31.34 +biganswer.big. IN A 10.10.31.35 +biganswer.big. IN A 10.10.31.36 +biganswer.big. IN A 10.10.31.37 +biganswer.big. IN A 10.10.31.38 +biganswer.big. IN A 10.10.31.39 +biganswer.big. IN A 10.10.31.40 +biganswer.big. IN A 10.10.31.41 +biganswer.big. IN A 10.10.31.42 +biganswer.big. IN A 10.10.31.43 +biganswer.big. IN A 10.10.31.44 +biganswer.big. IN A 10.10.31.45 +biganswer.big. IN A 10.10.31.46 +biganswer.big. IN A 10.10.31.47 +biganswer.big. IN A 10.10.31.48 +biganswer.big. IN A 10.10.31.49 +biganswer.big. IN A 10.10.31.50 +biganswer.big. IN A 10.10.32.1 +biganswer.big. IN A 10.10.32.2 +biganswer.big. IN A 10.10.32.3 +biganswer.big. IN A 10.10.32.4 +biganswer.big. IN A 10.10.32.5 +biganswer.big. IN A 10.10.32.6 +biganswer.big. IN A 10.10.32.7 +biganswer.big. IN A 10.10.32.8 +biganswer.big. IN A 10.10.32.9 +biganswer.big. IN A 10.10.32.10 +biganswer.big. IN A 10.10.32.11 +biganswer.big. IN A 10.10.32.12 +biganswer.big. IN A 10.10.32.13 +biganswer.big. IN A 10.10.32.14 +biganswer.big. IN A 10.10.32.15 +biganswer.big. IN A 10.10.32.16 +biganswer.big. IN A 10.10.32.17 +biganswer.big. IN A 10.10.32.18 +biganswer.big. IN A 10.10.32.19 +biganswer.big. IN A 10.10.32.20 +biganswer.big. IN A 10.10.32.21 +biganswer.big. IN A 10.10.32.22 +biganswer.big. IN A 10.10.32.23 +biganswer.big. IN A 10.10.32.24 +biganswer.big. IN A 10.10.32.25 +biganswer.big. IN A 10.10.32.26 +biganswer.big. IN A 10.10.32.27 +biganswer.big. IN A 10.10.32.28 +biganswer.big. IN A 10.10.32.29 +biganswer.big. IN A 10.10.32.30 +biganswer.big. IN A 10.10.32.31 +biganswer.big. IN A 10.10.32.32 +biganswer.big. IN A 10.10.32.33 +biganswer.big. IN A 10.10.32.34 +biganswer.big. IN A 10.10.32.35 +biganswer.big. IN A 10.10.32.36 +biganswer.big. IN A 10.10.32.37 +biganswer.big. IN A 10.10.32.38 +biganswer.big. IN A 10.10.32.39 +biganswer.big. IN A 10.10.32.40 +biganswer.big. IN A 10.10.32.41 +biganswer.big. IN A 10.10.32.42 +biganswer.big. IN A 10.10.32.43 +biganswer.big. IN A 10.10.32.44 +biganswer.big. IN A 10.10.32.45 +biganswer.big. IN A 10.10.32.46 +biganswer.big. IN A 10.10.32.47 +biganswer.big. IN A 10.10.32.48 +biganswer.big. IN A 10.10.32.49 +biganswer.big. IN A 10.10.32.50 +biganswer.big. IN A 10.10.33.1 +biganswer.big. IN A 10.10.33.2 +biganswer.big. IN A 10.10.33.3 +biganswer.big. IN A 10.10.33.4 +biganswer.big. IN A 10.10.33.5 +biganswer.big. IN A 10.10.33.6 +biganswer.big. IN A 10.10.33.7 +biganswer.big. IN A 10.10.33.8 +biganswer.big. IN A 10.10.33.9 +biganswer.big. IN A 10.10.33.10 +biganswer.big. IN A 10.10.33.11 +biganswer.big. IN A 10.10.33.12 +biganswer.big. IN A 10.10.33.13 +biganswer.big. IN A 10.10.33.14 +biganswer.big. IN A 10.10.33.15 +biganswer.big. IN A 10.10.33.16 +biganswer.big. IN A 10.10.33.17 +biganswer.big. IN A 10.10.33.18 +biganswer.big. IN A 10.10.33.19 +biganswer.big. IN A 10.10.33.20 +biganswer.big. IN A 10.10.33.21 +biganswer.big. IN A 10.10.33.22 +biganswer.big. IN A 10.10.33.23 +biganswer.big. IN A 10.10.33.24 +biganswer.big. IN A 10.10.33.25 +biganswer.big. IN A 10.10.33.26 +biganswer.big. IN A 10.10.33.27 +biganswer.big. IN A 10.10.33.28 +biganswer.big. IN A 10.10.33.29 +biganswer.big. IN A 10.10.33.30 +biganswer.big. IN A 10.10.33.31 +biganswer.big. IN A 10.10.33.32 +biganswer.big. IN A 10.10.33.33 +biganswer.big. IN A 10.10.33.34 +biganswer.big. IN A 10.10.33.35 +biganswer.big. IN A 10.10.33.36 +biganswer.big. IN A 10.10.33.37 +biganswer.big. IN A 10.10.33.38 +biganswer.big. IN A 10.10.33.39 +biganswer.big. IN A 10.10.33.40 +biganswer.big. IN A 10.10.33.41 +biganswer.big. IN A 10.10.33.42 +biganswer.big. IN A 10.10.33.43 +biganswer.big. IN A 10.10.33.44 +biganswer.big. IN A 10.10.33.45 +biganswer.big. IN A 10.10.33.46 +biganswer.big. IN A 10.10.33.47 +biganswer.big. IN A 10.10.33.48 +biganswer.big. IN A 10.10.33.49 +biganswer.big. IN A 10.10.33.50 +biganswer.big. IN A 10.10.34.1 +biganswer.big. IN A 10.10.34.2 +biganswer.big. IN A 10.10.34.3 +biganswer.big. IN A 10.10.34.4 +biganswer.big. IN A 10.10.34.5 +biganswer.big. IN A 10.10.34.6 +biganswer.big. IN A 10.10.34.7 +biganswer.big. IN A 10.10.34.8 +biganswer.big. IN A 10.10.34.9 +biganswer.big. IN A 10.10.34.10 +biganswer.big. IN A 10.10.34.11 +biganswer.big. IN A 10.10.34.12 +biganswer.big. IN A 10.10.34.13 +biganswer.big. IN A 10.10.34.14 +biganswer.big. IN A 10.10.34.15 +biganswer.big. IN A 10.10.34.16 +biganswer.big. IN A 10.10.34.17 +biganswer.big. IN A 10.10.34.18 +biganswer.big. IN A 10.10.34.19 +biganswer.big. IN A 10.10.34.20 +biganswer.big. IN A 10.10.34.21 +biganswer.big. IN A 10.10.34.22 +biganswer.big. IN A 10.10.34.23 +biganswer.big. IN A 10.10.34.24 +biganswer.big. IN A 10.10.34.25 +biganswer.big. IN A 10.10.34.26 +biganswer.big. IN A 10.10.34.27 +biganswer.big. IN A 10.10.34.28 +biganswer.big. IN A 10.10.34.29 +biganswer.big. IN A 10.10.34.30 +biganswer.big. IN A 10.10.34.31 +biganswer.big. IN A 10.10.34.32 +biganswer.big. IN A 10.10.34.33 +biganswer.big. IN A 10.10.34.34 +biganswer.big. IN A 10.10.34.35 +biganswer.big. IN A 10.10.34.36 +biganswer.big. IN A 10.10.34.37 +biganswer.big. IN A 10.10.34.38 +biganswer.big. IN A 10.10.34.39 +biganswer.big. IN A 10.10.34.40 +biganswer.big. IN A 10.10.34.41 +biganswer.big. IN A 10.10.34.42 +biganswer.big. IN A 10.10.34.43 +biganswer.big. IN A 10.10.34.44 +biganswer.big. IN A 10.10.34.45 +biganswer.big. IN A 10.10.34.46 +biganswer.big. IN A 10.10.34.47 +biganswer.big. IN A 10.10.34.48 +biganswer.big. IN A 10.10.34.49 +biganswer.big. IN A 10.10.34.50 +biganswer.big. IN A 10.10.35.1 +biganswer.big. IN A 10.10.35.2 +biganswer.big. IN A 10.10.35.3 +biganswer.big. IN A 10.10.35.4 +biganswer.big. IN A 10.10.35.5 +biganswer.big. IN A 10.10.35.6 +biganswer.big. IN A 10.10.35.7 +biganswer.big. IN A 10.10.35.8 +biganswer.big. IN A 10.10.35.9 +biganswer.big. IN A 10.10.35.10 +biganswer.big. IN A 10.10.35.11 +biganswer.big. IN A 10.10.35.12 +biganswer.big. IN A 10.10.35.13 +biganswer.big. IN A 10.10.35.14 +biganswer.big. IN A 10.10.35.15 +biganswer.big. IN A 10.10.35.16 +biganswer.big. IN A 10.10.35.17 +biganswer.big. IN A 10.10.35.18 +biganswer.big. IN A 10.10.35.19 +biganswer.big. IN A 10.10.35.20 +biganswer.big. IN A 10.10.35.21 +biganswer.big. IN A 10.10.35.22 +biganswer.big. IN A 10.10.35.23 +biganswer.big. IN A 10.10.35.24 +biganswer.big. IN A 10.10.35.25 +biganswer.big. IN A 10.10.35.26 +biganswer.big. IN A 10.10.35.27 +biganswer.big. IN A 10.10.35.28 +biganswer.big. IN A 10.10.35.29 +biganswer.big. IN A 10.10.35.30 +biganswer.big. IN A 10.10.35.31 +biganswer.big. IN A 10.10.35.32 +biganswer.big. IN A 10.10.35.33 +biganswer.big. IN A 10.10.35.34 +biganswer.big. IN A 10.10.35.35 +biganswer.big. IN A 10.10.35.36 +biganswer.big. IN A 10.10.35.37 +biganswer.big. IN A 10.10.35.38 +biganswer.big. IN A 10.10.35.39 +biganswer.big. IN A 10.10.35.40 +biganswer.big. IN A 10.10.35.41 +biganswer.big. IN A 10.10.35.42 +biganswer.big. IN A 10.10.35.43 +biganswer.big. IN A 10.10.35.44 +biganswer.big. IN A 10.10.35.45 +biganswer.big. IN A 10.10.35.46 +biganswer.big. IN A 10.10.35.47 +biganswer.big. IN A 10.10.35.48 +biganswer.big. IN A 10.10.35.49 +biganswer.big. IN A 10.10.35.50 +biganswer.big. IN A 10.10.36.1 +biganswer.big. IN A 10.10.36.2 +biganswer.big. IN A 10.10.36.3 +biganswer.big. IN A 10.10.36.4 +biganswer.big. IN A 10.10.36.5 +biganswer.big. IN A 10.10.36.6 +biganswer.big. IN A 10.10.36.7 +biganswer.big. IN A 10.10.36.8 +biganswer.big. IN A 10.10.36.9 +biganswer.big. IN A 10.10.36.10 +biganswer.big. IN A 10.10.36.11 +biganswer.big. IN A 10.10.36.12 +biganswer.big. IN A 10.10.36.13 +biganswer.big. IN A 10.10.36.14 +biganswer.big. IN A 10.10.36.15 +biganswer.big. IN A 10.10.36.16 +biganswer.big. IN A 10.10.36.17 +biganswer.big. IN A 10.10.36.18 +biganswer.big. IN A 10.10.36.19 +biganswer.big. IN A 10.10.36.20 +biganswer.big. IN A 10.10.36.21 +biganswer.big. IN A 10.10.36.22 +biganswer.big. IN A 10.10.36.23 +biganswer.big. IN A 10.10.36.24 +biganswer.big. IN A 10.10.36.25 +biganswer.big. IN A 10.10.36.26 +biganswer.big. IN A 10.10.36.27 +biganswer.big. IN A 10.10.36.28 +biganswer.big. IN A 10.10.36.29 +biganswer.big. IN A 10.10.36.30 +biganswer.big. IN A 10.10.36.31 +biganswer.big. IN A 10.10.36.32 +biganswer.big. IN A 10.10.36.33 +biganswer.big. IN A 10.10.36.34 +biganswer.big. IN A 10.10.36.35 +biganswer.big. IN A 10.10.36.36 +biganswer.big. IN A 10.10.36.37 +biganswer.big. IN A 10.10.36.38 +biganswer.big. IN A 10.10.36.39 +biganswer.big. IN A 10.10.36.40 +biganswer.big. IN A 10.10.36.41 +biganswer.big. IN A 10.10.36.42 +biganswer.big. IN A 10.10.36.43 +biganswer.big. IN A 10.10.36.44 +biganswer.big. IN A 10.10.36.45 +biganswer.big. IN A 10.10.36.46 +biganswer.big. IN A 10.10.36.47 +biganswer.big. IN A 10.10.36.48 +biganswer.big. IN A 10.10.36.49 +biganswer.big. IN A 10.10.36.50 +biganswer.big. IN A 10.10.37.1 +biganswer.big. IN A 10.10.37.2 +biganswer.big. IN A 10.10.37.3 +biganswer.big. IN A 10.10.37.4 +biganswer.big. IN A 10.10.37.5 +biganswer.big. IN A 10.10.37.6 +biganswer.big. IN A 10.10.37.7 +biganswer.big. IN A 10.10.37.8 +biganswer.big. IN A 10.10.37.9 +biganswer.big. IN A 10.10.37.10 +biganswer.big. IN A 10.10.37.11 +biganswer.big. IN A 10.10.37.12 +biganswer.big. IN A 10.10.37.13 +biganswer.big. IN A 10.10.37.14 +biganswer.big. IN A 10.10.37.15 +biganswer.big. IN A 10.10.37.16 +biganswer.big. IN A 10.10.37.17 +biganswer.big. IN A 10.10.37.18 +biganswer.big. IN A 10.10.37.19 +biganswer.big. IN A 10.10.37.20 +biganswer.big. IN A 10.10.37.21 +biganswer.big. IN A 10.10.37.22 +biganswer.big. IN A 10.10.37.23 +biganswer.big. IN A 10.10.37.24 +biganswer.big. IN A 10.10.37.25 +biganswer.big. IN A 10.10.37.26 +biganswer.big. IN A 10.10.37.27 +biganswer.big. IN A 10.10.37.28 +biganswer.big. IN A 10.10.37.29 +biganswer.big. IN A 10.10.37.30 +biganswer.big. IN A 10.10.37.31 +biganswer.big. IN A 10.10.37.32 +biganswer.big. IN A 10.10.37.33 +biganswer.big. IN A 10.10.37.34 +biganswer.big. IN A 10.10.37.35 +biganswer.big. IN A 10.10.37.36 +biganswer.big. IN A 10.10.37.37 +biganswer.big. IN A 10.10.37.38 +biganswer.big. IN A 10.10.37.39 +biganswer.big. IN A 10.10.37.40 +biganswer.big. IN A 10.10.37.41 +biganswer.big. IN A 10.10.37.42 +biganswer.big. IN A 10.10.37.43 +biganswer.big. IN A 10.10.37.44 +biganswer.big. IN A 10.10.37.45 +biganswer.big. IN A 10.10.37.46 +biganswer.big. IN A 10.10.37.47 +biganswer.big. IN A 10.10.37.48 +biganswer.big. IN A 10.10.37.49 +biganswer.big. IN A 10.10.37.50 +biganswer.big. IN A 10.10.38.1 +biganswer.big. IN A 10.10.38.2 +biganswer.big. IN A 10.10.38.3 +biganswer.big. IN A 10.10.38.4 +biganswer.big. IN A 10.10.38.5 +biganswer.big. IN A 10.10.38.6 +biganswer.big. IN A 10.10.38.7 +biganswer.big. IN A 10.10.38.8 +biganswer.big. IN A 10.10.38.9 +biganswer.big. IN A 10.10.38.10 +biganswer.big. IN A 10.10.38.11 +biganswer.big. IN A 10.10.38.12 +biganswer.big. IN A 10.10.38.13 +biganswer.big. IN A 10.10.38.14 +biganswer.big. IN A 10.10.38.15 +biganswer.big. IN A 10.10.38.16 +biganswer.big. IN A 10.10.38.17 +biganswer.big. IN A 10.10.38.18 +biganswer.big. IN A 10.10.38.19 +biganswer.big. IN A 10.10.38.20 +biganswer.big. IN A 10.10.38.21 +biganswer.big. IN A 10.10.38.22 +biganswer.big. IN A 10.10.38.23 +biganswer.big. IN A 10.10.38.24 +biganswer.big. IN A 10.10.38.25 +biganswer.big. IN A 10.10.38.26 +biganswer.big. IN A 10.10.38.27 +biganswer.big. IN A 10.10.38.28 +biganswer.big. IN A 10.10.38.29 +biganswer.big. IN A 10.10.38.30 +biganswer.big. IN A 10.10.38.31 +biganswer.big. IN A 10.10.38.32 +biganswer.big. IN A 10.10.38.33 +biganswer.big. IN A 10.10.38.34 +biganswer.big. IN A 10.10.38.35 +biganswer.big. IN A 10.10.38.36 +biganswer.big. IN A 10.10.38.37 +biganswer.big. IN A 10.10.38.38 +biganswer.big. IN A 10.10.38.39 +biganswer.big. IN A 10.10.38.40 +biganswer.big. IN A 10.10.38.41 +biganswer.big. IN A 10.10.38.42 +biganswer.big. IN A 10.10.38.43 +biganswer.big. IN A 10.10.38.44 +biganswer.big. IN A 10.10.38.45 +biganswer.big. IN A 10.10.38.46 +biganswer.big. IN A 10.10.38.47 +biganswer.big. IN A 10.10.38.48 +biganswer.big. IN A 10.10.38.49 +biganswer.big. IN A 10.10.38.50 +biganswer.big. IN A 10.10.39.1 +biganswer.big. IN A 10.10.39.2 +biganswer.big. IN A 10.10.39.3 +biganswer.big. IN A 10.10.39.4 +biganswer.big. IN A 10.10.39.5 +biganswer.big. IN A 10.10.39.6 +biganswer.big. IN A 10.10.39.7 +biganswer.big. IN A 10.10.39.8 +biganswer.big. IN A 10.10.39.9 +biganswer.big. IN A 10.10.39.10 +biganswer.big. IN A 10.10.39.11 +biganswer.big. IN A 10.10.39.12 +biganswer.big. IN A 10.10.39.13 +biganswer.big. IN A 10.10.39.14 +biganswer.big. IN A 10.10.39.15 +biganswer.big. IN A 10.10.39.16 +biganswer.big. IN A 10.10.39.17 +biganswer.big. IN A 10.10.39.18 +biganswer.big. IN A 10.10.39.19 +biganswer.big. IN A 10.10.39.20 +biganswer.big. IN A 10.10.39.21 +biganswer.big. IN A 10.10.39.22 +biganswer.big. IN A 10.10.39.23 +biganswer.big. IN A 10.10.39.24 +biganswer.big. IN A 10.10.39.25 +biganswer.big. IN A 10.10.39.26 +biganswer.big. IN A 10.10.39.27 +biganswer.big. IN A 10.10.39.28 +biganswer.big. IN A 10.10.39.29 +biganswer.big. IN A 10.10.39.30 +biganswer.big. IN A 10.10.39.31 +biganswer.big. IN A 10.10.39.32 +biganswer.big. IN A 10.10.39.33 +biganswer.big. IN A 10.10.39.34 +biganswer.big. IN A 10.10.39.35 +biganswer.big. IN A 10.10.39.36 +biganswer.big. IN A 10.10.39.37 +biganswer.big. IN A 10.10.39.38 +biganswer.big. IN A 10.10.39.39 +biganswer.big. IN A 10.10.39.40 +biganswer.big. IN A 10.10.39.41 +biganswer.big. IN A 10.10.39.42 +biganswer.big. IN A 10.10.39.43 +biganswer.big. IN A 10.10.39.44 +biganswer.big. IN A 10.10.39.45 +biganswer.big. IN A 10.10.39.46 +biganswer.big. IN A 10.10.39.47 +biganswer.big. IN A 10.10.39.48 +biganswer.big. IN A 10.10.39.49 +biganswer.big. IN A 10.10.39.50 +biganswer.big. IN A 10.10.40.1 +biganswer.big. IN A 10.10.40.2 +biganswer.big. IN A 10.10.40.3 +biganswer.big. IN A 10.10.40.4 +biganswer.big. IN A 10.10.40.5 +biganswer.big. IN A 10.10.40.6 +biganswer.big. IN A 10.10.40.7 +biganswer.big. IN A 10.10.40.8 +biganswer.big. IN A 10.10.40.9 +biganswer.big. IN A 10.10.40.10 +biganswer.big. IN A 10.10.40.11 +biganswer.big. IN A 10.10.40.12 +biganswer.big. IN A 10.10.40.13 +biganswer.big. IN A 10.10.40.14 +biganswer.big. IN A 10.10.40.15 +biganswer.big. IN A 10.10.40.16 +biganswer.big. IN A 10.10.40.17 +biganswer.big. IN A 10.10.40.18 +biganswer.big. IN A 10.10.40.19 +biganswer.big. IN A 10.10.40.20 +biganswer.big. IN A 10.10.40.21 +biganswer.big. IN A 10.10.40.22 +biganswer.big. IN A 10.10.40.23 +biganswer.big. IN A 10.10.40.24 +biganswer.big. IN A 10.10.40.25 +biganswer.big. IN A 10.10.40.26 +biganswer.big. IN A 10.10.40.27 +biganswer.big. IN A 10.10.40.28 +biganswer.big. IN A 10.10.40.29 +biganswer.big. IN A 10.10.40.30 +biganswer.big. IN A 10.10.40.31 +biganswer.big. IN A 10.10.40.32 +biganswer.big. IN A 10.10.40.33 +biganswer.big. IN A 10.10.40.34 +biganswer.big. IN A 10.10.40.35 +biganswer.big. IN A 10.10.40.36 +biganswer.big. IN A 10.10.40.37 +biganswer.big. IN A 10.10.40.38 +biganswer.big. IN A 10.10.40.39 +biganswer.big. IN A 10.10.40.40 +biganswer.big. IN A 10.10.40.41 +biganswer.big. IN A 10.10.40.42 +biganswer.big. IN A 10.10.40.43 +biganswer.big. IN A 10.10.40.44 +biganswer.big. IN A 10.10.40.45 +biganswer.big. IN A 10.10.40.46 +biganswer.big. IN A 10.10.40.47 +biganswer.big. IN A 10.10.40.48 +biganswer.big. IN A 10.10.40.49 +biganswer.big. IN A 10.10.40.50 +biganswer.big. IN A 10.10.41.1 +biganswer.big. IN A 10.10.41.2 +biganswer.big. IN A 10.10.41.3 +biganswer.big. IN A 10.10.41.4 +biganswer.big. IN A 10.10.41.5 +biganswer.big. IN A 10.10.41.6 +biganswer.big. IN A 10.10.41.7 +biganswer.big. IN A 10.10.41.8 +biganswer.big. IN A 10.10.41.9 +biganswer.big. IN A 10.10.41.10 +biganswer.big. IN A 10.10.41.11 +biganswer.big. IN A 10.10.41.12 +biganswer.big. IN A 10.10.41.13 +biganswer.big. IN A 10.10.41.14 +biganswer.big. IN A 10.10.41.15 +biganswer.big. IN A 10.10.41.16 +biganswer.big. IN A 10.10.41.17 +biganswer.big. IN A 10.10.41.18 +biganswer.big. IN A 10.10.41.19 +biganswer.big. IN A 10.10.41.20 +biganswer.big. IN A 10.10.41.21 +biganswer.big. IN A 10.10.41.22 +biganswer.big. IN A 10.10.41.23 +biganswer.big. IN A 10.10.41.24 +biganswer.big. IN A 10.10.41.25 +biganswer.big. IN A 10.10.41.26 +biganswer.big. IN A 10.10.41.27 +biganswer.big. IN A 10.10.41.28 +biganswer.big. IN A 10.10.41.29 +biganswer.big. IN A 10.10.41.30 +biganswer.big. IN A 10.10.41.31 +biganswer.big. IN A 10.10.41.32 +biganswer.big. IN A 10.10.41.33 +biganswer.big. IN A 10.10.41.34 +biganswer.big. IN A 10.10.41.35 +biganswer.big. IN A 10.10.41.36 +biganswer.big. IN A 10.10.41.37 +biganswer.big. IN A 10.10.41.38 +biganswer.big. IN A 10.10.41.39 +biganswer.big. IN A 10.10.41.40 +biganswer.big. IN A 10.10.41.41 +biganswer.big. IN A 10.10.41.42 +biganswer.big. IN A 10.10.41.43 +biganswer.big. IN A 10.10.41.44 +biganswer.big. IN A 10.10.41.45 +biganswer.big. IN A 10.10.41.46 +biganswer.big. IN A 10.10.41.47 +biganswer.big. IN A 10.10.41.48 +biganswer.big. IN A 10.10.41.49 +biganswer.big. IN A 10.10.41.50 +biganswer.big. IN A 10.10.42.1 +biganswer.big. IN A 10.10.42.2 +biganswer.big. IN A 10.10.42.3 +biganswer.big. IN A 10.10.42.4 +biganswer.big. IN A 10.10.42.5 +biganswer.big. IN A 10.10.42.6 +biganswer.big. IN A 10.10.42.7 +biganswer.big. IN A 10.10.42.8 +biganswer.big. IN A 10.10.42.9 +biganswer.big. IN A 10.10.42.10 +biganswer.big. IN A 10.10.42.11 +biganswer.big. IN A 10.10.42.12 +biganswer.big. IN A 10.10.42.13 +biganswer.big. IN A 10.10.42.14 +biganswer.big. IN A 10.10.42.15 +biganswer.big. IN A 10.10.42.16 +biganswer.big. IN A 10.10.42.17 +biganswer.big. IN A 10.10.42.18 +biganswer.big. IN A 10.10.42.19 +biganswer.big. IN A 10.10.42.20 +biganswer.big. IN A 10.10.42.21 +biganswer.big. IN A 10.10.42.22 +biganswer.big. IN A 10.10.42.23 +biganswer.big. IN A 10.10.42.24 +biganswer.big. IN A 10.10.42.25 +biganswer.big. IN A 10.10.42.26 +biganswer.big. IN A 10.10.42.27 +biganswer.big. IN A 10.10.42.28 +biganswer.big. IN A 10.10.42.29 +biganswer.big. IN A 10.10.42.30 +biganswer.big. IN A 10.10.42.31 +biganswer.big. IN A 10.10.42.32 +biganswer.big. IN A 10.10.42.33 +biganswer.big. IN A 10.10.42.34 +biganswer.big. IN A 10.10.42.35 +biganswer.big. IN A 10.10.42.36 +biganswer.big. IN A 10.10.42.37 +biganswer.big. IN A 10.10.42.38 +biganswer.big. IN A 10.10.42.39 +biganswer.big. IN A 10.10.42.40 +biganswer.big. IN A 10.10.42.41 +biganswer.big. IN A 10.10.42.42 +biganswer.big. IN A 10.10.42.43 +biganswer.big. IN A 10.10.42.44 +biganswer.big. IN A 10.10.42.45 +biganswer.big. IN A 10.10.42.46 +biganswer.big. IN A 10.10.42.47 +biganswer.big. IN A 10.10.42.48 +biganswer.big. IN A 10.10.42.49 +biganswer.big. IN A 10.10.42.50 +biganswer.big. IN A 10.10.43.1 +biganswer.big. IN A 10.10.43.2 +biganswer.big. IN A 10.10.43.3 +biganswer.big. IN A 10.10.43.4 +biganswer.big. IN A 10.10.43.5 +biganswer.big. IN A 10.10.43.6 +biganswer.big. IN A 10.10.43.7 +biganswer.big. IN A 10.10.43.8 +biganswer.big. IN A 10.10.43.9 +biganswer.big. IN A 10.10.43.10 +biganswer.big. IN A 10.10.43.11 +biganswer.big. IN A 10.10.43.12 +biganswer.big. IN A 10.10.43.13 +biganswer.big. IN A 10.10.43.14 +biganswer.big. IN A 10.10.43.15 +biganswer.big. IN A 10.10.43.16 +biganswer.big. IN A 10.10.43.17 +biganswer.big. IN A 10.10.43.18 +biganswer.big. IN A 10.10.43.19 +biganswer.big. IN A 10.10.43.20 +biganswer.big. IN A 10.10.43.21 +biganswer.big. IN A 10.10.43.22 +biganswer.big. IN A 10.10.43.23 +biganswer.big. IN A 10.10.43.24 +biganswer.big. IN A 10.10.43.25 +biganswer.big. IN A 10.10.43.26 +biganswer.big. IN A 10.10.43.27 +biganswer.big. IN A 10.10.43.28 +biganswer.big. IN A 10.10.43.29 +biganswer.big. IN A 10.10.43.30 +biganswer.big. IN A 10.10.43.31 +biganswer.big. IN A 10.10.43.32 +biganswer.big. IN A 10.10.43.33 +biganswer.big. IN A 10.10.43.34 +biganswer.big. IN A 10.10.43.35 +biganswer.big. IN A 10.10.43.36 +biganswer.big. IN A 10.10.43.37 +biganswer.big. IN A 10.10.43.38 +biganswer.big. IN A 10.10.43.39 +biganswer.big. IN A 10.10.43.40 +biganswer.big. IN A 10.10.43.41 +biganswer.big. IN A 10.10.43.42 +biganswer.big. IN A 10.10.43.43 +biganswer.big. IN A 10.10.43.44 +biganswer.big. IN A 10.10.43.45 +biganswer.big. IN A 10.10.43.46 +biganswer.big. IN A 10.10.43.47 +biganswer.big. IN A 10.10.43.48 +biganswer.big. IN A 10.10.43.49 +biganswer.big. IN A 10.10.43.50 +biganswer.big. IN A 10.10.44.1 +biganswer.big. IN A 10.10.44.2 +biganswer.big. IN A 10.10.44.3 +biganswer.big. IN A 10.10.44.4 +biganswer.big. IN A 10.10.44.5 +biganswer.big. IN A 10.10.44.6 +biganswer.big. IN A 10.10.44.7 +biganswer.big. IN A 10.10.44.8 +biganswer.big. IN A 10.10.44.9 +biganswer.big. IN A 10.10.44.10 +biganswer.big. IN A 10.10.44.11 +biganswer.big. IN A 10.10.44.12 +biganswer.big. IN A 10.10.44.13 +biganswer.big. IN A 10.10.44.14 +biganswer.big. IN A 10.10.44.15 +biganswer.big. IN A 10.10.44.16 +biganswer.big. IN A 10.10.44.17 +biganswer.big. IN A 10.10.44.18 +biganswer.big. IN A 10.10.44.19 +biganswer.big. IN A 10.10.44.20 +biganswer.big. IN A 10.10.44.21 +biganswer.big. IN A 10.10.44.22 +biganswer.big. IN A 10.10.44.23 +biganswer.big. IN A 10.10.44.24 +biganswer.big. IN A 10.10.44.25 +biganswer.big. IN A 10.10.44.26 +biganswer.big. IN A 10.10.44.27 +biganswer.big. IN A 10.10.44.28 +biganswer.big. IN A 10.10.44.29 +biganswer.big. IN A 10.10.44.30 +biganswer.big. IN A 10.10.44.31 +biganswer.big. IN A 10.10.44.32 +biganswer.big. IN A 10.10.44.33 +biganswer.big. IN A 10.10.44.34 +biganswer.big. IN A 10.10.44.35 +biganswer.big. IN A 10.10.44.36 +biganswer.big. IN A 10.10.44.37 +biganswer.big. IN A 10.10.44.38 +biganswer.big. IN A 10.10.44.39 +biganswer.big. IN A 10.10.44.40 +biganswer.big. IN A 10.10.44.41 +biganswer.big. IN A 10.10.44.42 +biganswer.big. IN A 10.10.44.43 +biganswer.big. IN A 10.10.44.44 +biganswer.big. IN A 10.10.44.45 +biganswer.big. IN A 10.10.44.46 +biganswer.big. IN A 10.10.44.47 +biganswer.big. IN A 10.10.44.48 +biganswer.big. IN A 10.10.44.49 +biganswer.big. IN A 10.10.44.50 +biganswer.big. IN A 10.10.45.1 +biganswer.big. IN A 10.10.45.2 +biganswer.big. IN A 10.10.45.3 +biganswer.big. IN A 10.10.45.4 +biganswer.big. IN A 10.10.45.5 +biganswer.big. IN A 10.10.45.6 +biganswer.big. IN A 10.10.45.7 +biganswer.big. IN A 10.10.45.8 +biganswer.big. IN A 10.10.45.9 +biganswer.big. IN A 10.10.45.10 +biganswer.big. IN A 10.10.45.11 +biganswer.big. IN A 10.10.45.12 +biganswer.big. IN A 10.10.45.13 +biganswer.big. IN A 10.10.45.14 +biganswer.big. IN A 10.10.45.15 +biganswer.big. IN A 10.10.45.16 +biganswer.big. IN A 10.10.45.17 +biganswer.big. IN A 10.10.45.18 +biganswer.big. IN A 10.10.45.19 +biganswer.big. IN A 10.10.45.20 +biganswer.big. IN A 10.10.45.21 +biganswer.big. IN A 10.10.45.22 +biganswer.big. IN A 10.10.45.23 +biganswer.big. IN A 10.10.45.24 +biganswer.big. IN A 10.10.45.25 +biganswer.big. IN A 10.10.45.26 +biganswer.big. IN A 10.10.45.27 +biganswer.big. IN A 10.10.45.28 +biganswer.big. IN A 10.10.45.29 +biganswer.big. IN A 10.10.45.30 +biganswer.big. IN A 10.10.45.31 +biganswer.big. IN A 10.10.45.32 +biganswer.big. IN A 10.10.45.33 +biganswer.big. IN A 10.10.45.34 +biganswer.big. IN A 10.10.45.35 +biganswer.big. IN A 10.10.45.36 +biganswer.big. IN A 10.10.45.37 +biganswer.big. IN A 10.10.45.38 +biganswer.big. IN A 10.10.45.39 +biganswer.big. IN A 10.10.45.40 +biganswer.big. IN A 10.10.45.41 +biganswer.big. IN A 10.10.45.42 +biganswer.big. IN A 10.10.45.43 +biganswer.big. IN A 10.10.45.44 +biganswer.big. IN A 10.10.45.45 +biganswer.big. IN A 10.10.45.46 +biganswer.big. IN A 10.10.45.47 +biganswer.big. IN A 10.10.45.48 +biganswer.big. IN A 10.10.45.49 +biganswer.big. IN A 10.10.45.50 +biganswer.big. IN A 10.10.46.1 +biganswer.big. IN A 10.10.46.2 +biganswer.big. IN A 10.10.46.3 +biganswer.big. IN A 10.10.46.4 +biganswer.big. IN A 10.10.46.5 +biganswer.big. IN A 10.10.46.6 +biganswer.big. IN A 10.10.46.7 +biganswer.big. IN A 10.10.46.8 +biganswer.big. IN A 10.10.46.9 +biganswer.big. IN A 10.10.46.10 +biganswer.big. IN A 10.10.46.11 +biganswer.big. IN A 10.10.46.12 +biganswer.big. IN A 10.10.46.13 +biganswer.big. IN A 10.10.46.14 +biganswer.big. IN A 10.10.46.15 +biganswer.big. IN A 10.10.46.16 +biganswer.big. IN A 10.10.46.17 +biganswer.big. IN A 10.10.46.18 +biganswer.big. IN A 10.10.46.19 +biganswer.big. IN A 10.10.46.20 +biganswer.big. IN A 10.10.46.21 +biganswer.big. IN A 10.10.46.22 +biganswer.big. IN A 10.10.46.23 +biganswer.big. IN A 10.10.46.24 +biganswer.big. IN A 10.10.46.25 +biganswer.big. IN A 10.10.46.26 +biganswer.big. IN A 10.10.46.27 +biganswer.big. IN A 10.10.46.28 +biganswer.big. IN A 10.10.46.29 +biganswer.big. IN A 10.10.46.30 +biganswer.big. IN A 10.10.46.31 +biganswer.big. IN A 10.10.46.32 +biganswer.big. IN A 10.10.46.33 +biganswer.big. IN A 10.10.46.34 +biganswer.big. IN A 10.10.46.35 +biganswer.big. IN A 10.10.46.36 +biganswer.big. IN A 10.10.46.37 +biganswer.big. IN A 10.10.46.38 +biganswer.big. IN A 10.10.46.39 +biganswer.big. IN A 10.10.46.40 +biganswer.big. IN A 10.10.46.41 +biganswer.big. IN A 10.10.46.42 +biganswer.big. IN A 10.10.46.43 +biganswer.big. IN A 10.10.46.44 +biganswer.big. IN A 10.10.46.45 +biganswer.big. IN A 10.10.46.46 +biganswer.big. IN A 10.10.46.47 +biganswer.big. IN A 10.10.46.48 +biganswer.big. IN A 10.10.46.49 +biganswer.big. IN A 10.10.46.50 +biganswer.big. IN A 10.10.47.1 +biganswer.big. IN A 10.10.47.2 +biganswer.big. IN A 10.10.47.3 +biganswer.big. IN A 10.10.47.4 +biganswer.big. IN A 10.10.47.5 +biganswer.big. IN A 10.10.47.6 +biganswer.big. IN A 10.10.47.7 +biganswer.big. IN A 10.10.47.8 +biganswer.big. IN A 10.10.47.9 +biganswer.big. IN A 10.10.47.10 +biganswer.big. IN A 10.10.47.11 +biganswer.big. IN A 10.10.47.12 +biganswer.big. IN A 10.10.47.13 +biganswer.big. IN A 10.10.47.14 +biganswer.big. IN A 10.10.47.15 +biganswer.big. IN A 10.10.47.16 +biganswer.big. IN A 10.10.47.17 +biganswer.big. IN A 10.10.47.18 +biganswer.big. IN A 10.10.47.19 +biganswer.big. IN A 10.10.47.20 +biganswer.big. IN A 10.10.47.21 +biganswer.big. IN A 10.10.47.22 +biganswer.big. IN A 10.10.47.23 +biganswer.big. IN A 10.10.47.24 +biganswer.big. IN A 10.10.47.25 +biganswer.big. IN A 10.10.47.26 +biganswer.big. IN A 10.10.47.27 +biganswer.big. IN A 10.10.47.28 +biganswer.big. IN A 10.10.47.29 +biganswer.big. IN A 10.10.47.30 +biganswer.big. IN A 10.10.47.31 +biganswer.big. IN A 10.10.47.32 +biganswer.big. IN A 10.10.47.33 +biganswer.big. IN A 10.10.47.34 +biganswer.big. IN A 10.10.47.35 +biganswer.big. IN A 10.10.47.36 +biganswer.big. IN A 10.10.47.37 +biganswer.big. IN A 10.10.47.38 +biganswer.big. IN A 10.10.47.39 +biganswer.big. IN A 10.10.47.40 +biganswer.big. IN A 10.10.47.41 +biganswer.big. IN A 10.10.47.42 +biganswer.big. IN A 10.10.47.43 +biganswer.big. IN A 10.10.47.44 +biganswer.big. IN A 10.10.47.45 +biganswer.big. IN A 10.10.47.46 +biganswer.big. IN A 10.10.47.47 +biganswer.big. IN A 10.10.47.48 +biganswer.big. IN A 10.10.47.49 +biganswer.big. IN A 10.10.47.50 +biganswer.big. IN A 10.10.48.1 +biganswer.big. IN A 10.10.48.2 +biganswer.big. IN A 10.10.48.3 +biganswer.big. IN A 10.10.48.4 +biganswer.big. IN A 10.10.48.5 +biganswer.big. IN A 10.10.48.6 +biganswer.big. IN A 10.10.48.7 +biganswer.big. IN A 10.10.48.8 +biganswer.big. IN A 10.10.48.9 +biganswer.big. IN A 10.10.48.10 +biganswer.big. IN A 10.10.48.11 +biganswer.big. IN A 10.10.48.12 +biganswer.big. IN A 10.10.48.13 +biganswer.big. IN A 10.10.48.14 +biganswer.big. IN A 10.10.48.15 +biganswer.big. IN A 10.10.48.16 +biganswer.big. IN A 10.10.48.17 +biganswer.big. IN A 10.10.48.18 +biganswer.big. IN A 10.10.48.19 +biganswer.big. IN A 10.10.48.20 +biganswer.big. IN A 10.10.48.21 +biganswer.big. IN A 10.10.48.22 +biganswer.big. IN A 10.10.48.23 +biganswer.big. IN A 10.10.48.24 +biganswer.big. IN A 10.10.48.25 +biganswer.big. IN A 10.10.48.26 +biganswer.big. IN A 10.10.48.27 +biganswer.big. IN A 10.10.48.28 +biganswer.big. IN A 10.10.48.29 +biganswer.big. IN A 10.10.48.30 +biganswer.big. IN A 10.10.48.31 +biganswer.big. IN A 10.10.48.32 +biganswer.big. IN A 10.10.48.33 +biganswer.big. IN A 10.10.48.34 +biganswer.big. IN A 10.10.48.35 +biganswer.big. IN A 10.10.48.36 +biganswer.big. IN A 10.10.48.37 +biganswer.big. IN A 10.10.48.38 +biganswer.big. IN A 10.10.48.39 +biganswer.big. IN A 10.10.48.40 +biganswer.big. IN A 10.10.48.41 +biganswer.big. IN A 10.10.48.42 +biganswer.big. IN A 10.10.48.43 +biganswer.big. IN A 10.10.48.44 +biganswer.big. IN A 10.10.48.45 +biganswer.big. IN A 10.10.48.46 +biganswer.big. IN A 10.10.48.47 +biganswer.big. IN A 10.10.48.48 +biganswer.big. IN A 10.10.48.49 +biganswer.big. IN A 10.10.48.50 +biganswer.big. IN A 10.10.49.1 +biganswer.big. IN A 10.10.49.2 +biganswer.big. IN A 10.10.49.3 +biganswer.big. IN A 10.10.49.4 +biganswer.big. IN A 10.10.49.5 +biganswer.big. IN A 10.10.49.6 +biganswer.big. IN A 10.10.49.7 +biganswer.big. IN A 10.10.49.8 +biganswer.big. IN A 10.10.49.9 +biganswer.big. IN A 10.10.49.10 +biganswer.big. IN A 10.10.49.11 +biganswer.big. IN A 10.10.49.12 +biganswer.big. IN A 10.10.49.13 +biganswer.big. IN A 10.10.49.14 +biganswer.big. IN A 10.10.49.15 +biganswer.big. IN A 10.10.49.16 +biganswer.big. IN A 10.10.49.17 +biganswer.big. IN A 10.10.49.18 +biganswer.big. IN A 10.10.49.19 +biganswer.big. IN A 10.10.49.20 +biganswer.big. IN A 10.10.49.21 +biganswer.big. IN A 10.10.49.22 +biganswer.big. IN A 10.10.49.23 +biganswer.big. IN A 10.10.49.24 +biganswer.big. IN A 10.10.49.25 +biganswer.big. IN A 10.10.49.26 +biganswer.big. IN A 10.10.49.27 +biganswer.big. IN A 10.10.49.28 +biganswer.big. IN A 10.10.49.29 +biganswer.big. IN A 10.10.49.30 +biganswer.big. IN A 10.10.49.31 +biganswer.big. IN A 10.10.49.32 +biganswer.big. IN A 10.10.49.33 +biganswer.big. IN A 10.10.49.34 +biganswer.big. IN A 10.10.49.35 +biganswer.big. IN A 10.10.49.36 +biganswer.big. IN A 10.10.49.37 +biganswer.big. IN A 10.10.49.38 +biganswer.big. IN A 10.10.49.39 +biganswer.big. IN A 10.10.49.40 +biganswer.big. IN A 10.10.49.41 +biganswer.big. IN A 10.10.49.42 +biganswer.big. IN A 10.10.49.43 +biganswer.big. IN A 10.10.49.44 +biganswer.big. IN A 10.10.49.45 +biganswer.big. IN A 10.10.49.46 +biganswer.big. IN A 10.10.49.47 +biganswer.big. IN A 10.10.49.48 +biganswer.big. IN A 10.10.49.49 +biganswer.big. IN A 10.10.49.50 +biganswer.big. IN A 10.10.50.1 +biganswer.big. IN A 10.10.50.2 +biganswer.big. IN A 10.10.50.3 +biganswer.big. IN A 10.10.50.4 +biganswer.big. IN A 10.10.50.5 +biganswer.big. IN A 10.10.50.6 +biganswer.big. IN A 10.10.50.7 +biganswer.big. IN A 10.10.50.8 +biganswer.big. IN A 10.10.50.9 +biganswer.big. IN A 10.10.50.10 +biganswer.big. IN A 10.10.50.11 +biganswer.big. IN A 10.10.50.12 +biganswer.big. IN A 10.10.50.13 +biganswer.big. IN A 10.10.50.14 +biganswer.big. IN A 10.10.50.15 +biganswer.big. IN A 10.10.50.16 +biganswer.big. IN A 10.10.50.17 +biganswer.big. IN A 10.10.50.18 +biganswer.big. IN A 10.10.50.19 +biganswer.big. IN A 10.10.50.20 +biganswer.big. IN A 10.10.50.21 +biganswer.big. IN A 10.10.50.22 +biganswer.big. IN A 10.10.50.23 +biganswer.big. IN A 10.10.50.24 +biganswer.big. IN A 10.10.50.25 +biganswer.big. IN A 10.10.50.26 +biganswer.big. IN A 10.10.50.27 +biganswer.big. IN A 10.10.50.28 +biganswer.big. IN A 10.10.50.29 +biganswer.big. IN A 10.10.50.30 +biganswer.big. IN A 10.10.50.31 +biganswer.big. IN A 10.10.50.32 +biganswer.big. IN A 10.10.50.33 +biganswer.big. IN A 10.10.50.34 +biganswer.big. IN A 10.10.50.35 +biganswer.big. IN A 10.10.50.36 +biganswer.big. IN A 10.10.50.37 +biganswer.big. IN A 10.10.50.38 +biganswer.big. IN A 10.10.50.39 +biganswer.big. IN A 10.10.50.40 +biganswer.big. IN A 10.10.50.41 +biganswer.big. IN A 10.10.50.42 +biganswer.big. IN A 10.10.50.43 +biganswer.big. IN A 10.10.50.44 +biganswer.big. IN A 10.10.50.45 +biganswer.big. IN A 10.10.50.46 +biganswer.big. IN A 10.10.50.47 +biganswer.big. IN A 10.10.50.48 +biganswer.big. IN A 10.10.50.49 +biganswer.big. IN A 10.10.50.50 + +manytypes.big. IN TYPE65280 \# 0 +manytypes.big. IN TYPE65281 \# 0 +manytypes.big. IN TYPE65282 \# 0 +manytypes.big. IN TYPE65283 \# 0 +manytypes.big. IN TYPE65284 \# 0 +manytypes.big. IN TYPE65285 \# 0 +manytypes.big. IN TYPE65286 \# 0 +manytypes.big. IN TYPE65287 \# 0 +manytypes.big. IN TYPE65288 \# 0 +manytypes.big. IN TYPE65289 \# 0 +manytypes.big. IN TYPE65290 \# 0 +manytypes.big. IN TYPE65291 \# 0 +manytypes.big. IN TYPE65292 \# 0 +manytypes.big. IN TYPE65293 \# 0 +manytypes.big. IN TYPE65294 \# 0 +manytypes.big. IN TYPE65295 \# 0 +manytypes.big. IN TYPE65296 \# 0 +manytypes.big. IN TYPE65297 \# 0 +manytypes.big. IN TYPE65298 \# 0 +manytypes.big. IN TYPE65299 \# 0 +manytypes.big. IN TYPE65300 \# 0 +manytypes.big. IN TYPE65301 \# 0 +manytypes.big. IN TYPE65302 \# 0 +manytypes.big. IN TYPE65303 \# 0 +manytypes.big. IN TYPE65304 \# 0 +manytypes.big. IN TYPE65305 \# 0 +manytypes.big. IN TYPE65306 \# 0 +manytypes.big. IN TYPE65307 \# 0 +manytypes.big. IN TYPE65308 \# 0 +manytypes.big. IN TYPE65309 \# 0 +manytypes.big. IN TYPE65310 \# 0 +manytypes.big. IN TYPE65311 \# 0 +manytypes.big. IN TYPE65312 \# 0 +manytypes.big. IN TYPE65313 \# 0 +manytypes.big. IN TYPE65314 \# 0 +manytypes.big. IN TYPE65315 \# 0 +manytypes.big. IN TYPE65316 \# 0 +manytypes.big. IN TYPE65317 \# 0 +manytypes.big. IN TYPE65318 \# 0 +manytypes.big. IN TYPE65319 \# 0 +manytypes.big. IN TYPE65320 \# 0 +manytypes.big. IN TYPE65321 \# 0 +manytypes.big. IN TYPE65322 \# 0 +manytypes.big. IN TYPE65323 \# 0 +manytypes.big. IN TYPE65324 \# 0 +manytypes.big. IN TYPE65325 \# 0 +manytypes.big. IN TYPE65326 \# 0 +manytypes.big. IN TYPE65327 \# 0 +manytypes.big. IN TYPE65328 \# 0 +manytypes.big. IN TYPE65329 \# 0 +manytypes.big. IN TYPE65330 \# 0 +manytypes.big. IN TYPE65331 \# 0 +manytypes.big. IN TYPE65332 \# 0 +manytypes.big. IN TYPE65333 \# 0 +manytypes.big. IN TYPE65334 \# 0 +manytypes.big. IN TYPE65335 \# 0 +manytypes.big. IN TYPE65336 \# 0 +manytypes.big. IN TYPE65337 \# 0 +manytypes.big. IN TYPE65338 \# 0 +manytypes.big. IN TYPE65339 \# 0 +manytypes.big. IN TYPE65340 \# 0 +manytypes.big. IN TYPE65341 \# 0 +manytypes.big. IN TYPE65342 \# 0 +manytypes.big. IN TYPE65343 \# 0 +manytypes.big. IN TYPE65344 \# 0 +manytypes.big. IN TYPE65345 \# 0 +manytypes.big. IN TYPE65346 \# 0 +manytypes.big. IN TYPE65347 \# 0 +manytypes.big. IN TYPE65348 \# 0 +manytypes.big. IN TYPE65349 \# 0 +manytypes.big. IN TYPE65350 \# 0 +manytypes.big. IN TYPE65351 \# 0 +manytypes.big. IN TYPE65352 \# 0 +manytypes.big. IN TYPE65353 \# 0 +manytypes.big. IN TYPE65354 \# 0 +manytypes.big. IN TYPE65355 \# 0 +manytypes.big. IN TYPE65356 \# 0 +manytypes.big. IN TYPE65357 \# 0 +manytypes.big. IN TYPE65358 \# 0 +manytypes.big. IN TYPE65359 \# 0 +manytypes.big. IN TYPE65360 \# 0 +manytypes.big. IN TYPE65361 \# 0 +manytypes.big. IN TYPE65362 \# 0 +manytypes.big. IN TYPE65363 \# 0 +manytypes.big. IN TYPE65364 \# 0 +manytypes.big. IN TYPE65365 \# 0 +manytypes.big. IN TYPE65366 \# 0 +manytypes.big. IN TYPE65367 \# 0 +manytypes.big. IN TYPE65368 \# 0 +manytypes.big. IN TYPE65369 \# 0 +manytypes.big. IN TYPE65370 \# 0 +manytypes.big. IN TYPE65371 \# 0 +manytypes.big. IN TYPE65372 \# 0 +manytypes.big. IN TYPE65373 \# 0 +manytypes.big. IN TYPE65374 \# 0 +manytypes.big. IN TYPE65375 \# 0 +manytypes.big. IN TYPE65376 \# 0 +manytypes.big. IN TYPE65377 \# 0 +manytypes.big. IN TYPE65378 \# 0 +manytypes.big. IN TYPE65379 \# 0 +manytypes.big. IN TYPE65380 \# 0 +manytypes.big. IN TYPE65381 \# 0 +manytypes.big. IN TYPE65382 \# 0 +manytypes.big. IN TYPE65383 \# 0 +manytypes.big. IN TYPE65384 \# 0 +manytypes.big. IN TYPE65385 \# 0 +manytypes.big. IN TYPE65386 \# 0 +manytypes.big. IN TYPE65387 \# 0 +manytypes.big. IN TYPE65388 \# 0 +manytypes.big. IN TYPE65389 \# 0 +manytypes.big. IN TYPE65390 \# 0 +manytypes.big. IN TYPE65391 \# 0 +manytypes.big. IN TYPE65392 \# 0 +manytypes.big. IN TYPE65393 \# 0 +manytypes.big. IN TYPE65394 \# 0 +manytypes.big. IN TYPE65395 \# 0 +manytypes.big. IN TYPE65396 \# 0 +manytypes.big. IN TYPE65397 \# 0 +manytypes.big. IN TYPE65398 \# 0 +manytypes.big. IN TYPE65399 \# 0 +manytypes.big. IN TYPE65400 \# 0 +manytypes.big. IN TYPE65401 \# 0 +manytypes.big. IN TYPE65402 \# 0 +manytypes.big. IN TYPE65403 \# 0 +manytypes.big. IN TYPE65404 \# 0 +manytypes.big. IN TYPE65405 \# 0 +manytypes.big. IN TYPE65406 \# 0 +manytypes.big. IN TYPE65407 \# 0 +manytypes.big. IN TYPE65408 \# 0 +manytypes.big. IN TYPE65409 \# 0 +manytypes.big. IN TYPE65410 \# 0 +manytypes.big. IN TYPE65411 \# 0 +manytypes.big. IN TYPE65412 \# 0 +manytypes.big. IN TYPE65413 \# 0 +manytypes.big. IN TYPE65414 \# 0 +manytypes.big. IN TYPE65415 \# 0 +manytypes.big. IN TYPE65416 \# 0 +manytypes.big. IN TYPE65417 \# 0 +manytypes.big. IN TYPE65418 \# 0 +manytypes.big. IN TYPE65419 \# 0 +manytypes.big. IN TYPE65420 \# 0 +manytypes.big. IN TYPE65421 \# 0 +manytypes.big. IN TYPE65422 \# 0 +manytypes.big. IN TYPE65423 \# 0 +manytypes.big. IN TYPE65424 \# 0 +manytypes.big. IN TYPE65425 \# 0 +manytypes.big. IN TYPE65426 \# 0 +manytypes.big. IN TYPE65427 \# 0 +manytypes.big. IN TYPE65428 \# 0 +manytypes.big. IN TYPE65429 \# 0 +manytypes.big. IN TYPE65430 \# 0 +manytypes.big. IN TYPE65431 \# 0 +manytypes.big. IN TYPE65432 \# 0 +manytypes.big. IN TYPE65433 \# 0 +manytypes.big. IN TYPE65434 \# 0 +manytypes.big. IN TYPE65435 \# 0 +manytypes.big. IN TYPE65436 \# 0 +manytypes.big. IN TYPE65437 \# 0 +manytypes.big. IN TYPE65438 \# 0 +manytypes.big. IN TYPE65439 \# 0 +manytypes.big. IN TYPE65440 \# 0 +manytypes.big. IN TYPE65441 \# 0 +manytypes.big. IN TYPE65442 \# 0 +manytypes.big. IN TYPE65443 \# 0 +manytypes.big. IN TYPE65444 \# 0 +manytypes.big. IN TYPE65445 \# 0 +manytypes.big. IN TYPE65446 \# 0 +manytypes.big. IN TYPE65447 \# 0 +manytypes.big. IN TYPE65448 \# 0 +manytypes.big. IN TYPE65449 \# 0 +manytypes.big. IN TYPE65450 \# 0 +manytypes.big. IN TYPE65451 \# 0 +manytypes.big. IN TYPE65452 \# 0 +manytypes.big. IN TYPE65453 \# 0 +manytypes.big. IN TYPE65454 \# 0 +manytypes.big. IN TYPE65455 \# 0 +manytypes.big. IN TYPE65456 \# 0 +manytypes.big. IN TYPE65457 \# 0 +manytypes.big. IN TYPE65458 \# 0 +manytypes.big. IN TYPE65459 \# 0 +manytypes.big. IN TYPE65460 \# 0 +manytypes.big. IN TYPE65461 \# 0 +manytypes.big. IN TYPE65462 \# 0 +manytypes.big. IN TYPE65463 \# 0 +manytypes.big. IN TYPE65464 \# 0 +manytypes.big. IN TYPE65465 \# 0 +manytypes.big. IN TYPE65466 \# 0 +manytypes.big. IN TYPE65467 \# 0 +manytypes.big. IN TYPE65468 \# 0 +manytypes.big. IN TYPE65469 \# 0 +manytypes.big. IN TYPE65470 \# 0 +manytypes.big. IN TYPE65471 \# 0 +manytypes.big. IN TYPE65472 \# 0 +manytypes.big. IN TYPE65473 \# 0 +manytypes.big. IN TYPE65474 \# 0 +manytypes.big. IN TYPE65475 \# 0 +manytypes.big. IN TYPE65476 \# 0 +manytypes.big. IN TYPE65477 \# 0 +manytypes.big. IN TYPE65478 \# 0 +manytypes.big. IN TYPE65479 \# 0 +manytypes.big. IN TYPE65480 \# 0 +manytypes.big. IN TYPE65481 \# 0 +manytypes.big. IN TYPE65482 \# 0 +manytypes.big. IN TYPE65483 \# 0 +manytypes.big. IN TYPE65484 \# 0 +manytypes.big. IN TYPE65485 \# 0 +manytypes.big. IN TYPE65486 \# 0 +manytypes.big. IN TYPE65487 \# 0 +manytypes.big. IN TYPE65488 \# 0 +manytypes.big. IN TYPE65489 \# 0 +manytypes.big. IN TYPE65490 \# 0 +manytypes.big. IN TYPE65491 \# 0 +manytypes.big. IN TYPE65492 \# 0 +manytypes.big. IN TYPE65493 \# 0 +manytypes.big. IN TYPE65494 \# 0 +manytypes.big. IN TYPE65495 \# 0 +manytypes.big. IN TYPE65496 \# 0 +manytypes.big. IN TYPE65497 \# 0 +manytypes.big. IN TYPE65498 \# 0 +manytypes.big. IN TYPE65499 \# 0 +manytypes.big. IN TYPE65500 \# 0 +manytypes.big. IN TYPE65501 \# 0 +manytypes.big. IN TYPE65502 \# 0 +manytypes.big. IN TYPE65503 \# 0 +manytypes.big. IN TYPE65504 \# 0 +manytypes.big. IN TYPE65505 \# 0 +manytypes.big. IN TYPE65506 \# 0 +manytypes.big. IN TYPE65507 \# 0 +manytypes.big. IN TYPE65508 \# 0 +manytypes.big. IN TYPE65509 \# 0 +manytypes.big. IN TYPE65510 \# 0 +manytypes.big. IN TYPE65511 \# 0 +manytypes.big. IN TYPE65512 \# 0 +manytypes.big. IN TYPE65513 \# 0 +manytypes.big. IN TYPE65514 \# 0 +manytypes.big. IN TYPE65515 \# 0 +manytypes.big. IN TYPE65516 \# 0 +manytypes.big. IN TYPE65517 \# 0 +manytypes.big. IN TYPE65518 \# 0 +manytypes.big. IN TYPE65519 \# 0 +manytypes.big. IN TYPE65520 \# 0 +manytypes.big. IN TYPE65521 \# 0 +manytypes.big. IN TYPE65522 \# 0 +manytypes.big. IN TYPE65523 \# 0 +manytypes.big. IN TYPE65524 \# 0 +manytypes.big. IN TYPE65525 \# 0 +manytypes.big. IN TYPE65526 \# 0 +manytypes.big. IN TYPE65527 \# 0 +manytypes.big. IN TYPE65528 \# 0 +manytypes.big. IN TYPE65529 \# 0 +manytypes.big. IN TYPE65530 \# 0 +manytypes.big. IN TYPE65531 \# 0 +manytypes.big. IN TYPE65532 \# 0 +manytypes.big. IN TYPE65533 \# 0 +manytypes.big. IN TYPE65534 \# 0 +manytypes.big. IN A 10.53.0.1 diff --git a/bin/tests/system/reclimit/ns1/named.conf.in b/bin/tests/system/reclimit/ns1/named.conf.in new file mode 100644 index 0000000..c345c28 --- /dev/null +++ b/bin/tests/system/reclimit/ns1/named.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + max-records-per-type 0; + max-types-per-name 0; +}; + +zone "." { type primary; file "root.db"; }; + +zone "big." { + type primary; + file "big.db"; +}; + +zone "signed." { + type primary; + file "signed.db.signed"; +}; diff --git a/bin/tests/system/reclimit/ns1/root.db b/bin/tests/system/reclimit/ns1/root.db new file mode 100644 index 0000000..7b7c119 --- /dev/null +++ b/bin/tests/system/reclimit/ns1/root.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 60 IN SOA ns.nil. hostmaster.ns.nil. 1 0 0 0 0 +. 60 IN NS ns.nil. +ns.nil. 60 IN A 10.53.0.1 +ns.tld1. 60 IN A 10.53.0.1 +example.org. 60 IN NS direct.example.org. +direct.example.org. 60 IN A 10.53.0.2 +example.net. 60 IN NS direct.example.net. +direct.example.net. 60 IN A 10.53.0.2 +example.com. 60 IN NS direct.example.com. +direct.example.com. 60 IN A 10.53.0.4 + +big. IN NS ns.big. +ns.big. 60 IN A 10.53.0.1 + +signed. IN NS ns.signed. +ns.signed. 60 IN A 10.53.0.1 diff --git a/bin/tests/system/reclimit/ns3/hints.db b/bin/tests/system/reclimit/ns3/hints.db new file mode 100644 index 0000000..c9264bf --- /dev/null +++ b/bin/tests/system/reclimit/ns3/hints.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 60 IN NS ns.nil. +ns.nil. 60 IN A 10.53.0.1 diff --git a/bin/tests/system/reclimit/ns3/named1.conf.in b/bin/tests/system/reclimit/ns3/named1.conf.in new file mode 100644 index 0000000..295eae0 --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named1.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-queries 50; + max-recursion-depth 12; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named2.conf.in b/bin/tests/system/reclimit/ns3/named2.conf.in new file mode 100644 index 0000000..974b24b --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named2.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-depth 5; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named3.conf.in b/bin/tests/system/reclimit/ns3/named3.conf.in new file mode 100644 index 0000000..38a77ae --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named3.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-depth 100; + max-recursion-queries 50; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named4.conf.in b/bin/tests/system/reclimit/ns3/named4.conf.in new file mode 100644 index 0000000..5a06607 --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named4.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-depth 100; + max-recursion-queries 40; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named5.conf.in b/bin/tests/system/reclimit/ns3/named5.conf.in new file mode 100644 index 0000000..7cf0633 --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named5.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-depth 12; + recursion yes; + dnssec-validation yes; + max-records-per-type 0; + max-types-per-name 10; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named6.conf.in b/bin/tests/system/reclimit/ns3/named6.conf.in new file mode 100644 index 0000000..e1607e2 --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named6.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + qname-minimization disabled; + max-recursion-depth 12; + recursion yes; + dnssec-validation yes; + max-records-per-type 0; + max-types-per-name 0; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/prereq.sh b/bin/tests/system/reclimit/prereq.sh new file mode 100644 index 0000000..0d6e2b4 --- /dev/null +++ b/bin/tests/system/reclimit/prereq.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +if ! ${PERL} -MNet::DNS::Nameserver -e ''; then + echo_i "perl Net::DNS::Nameserver module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/reclimit/setup.sh b/bin/tests/system/reclimit/setup.sh new file mode 100644 index 0000000..bec8fe0 --- /dev/null +++ b/bin/tests/system/reclimit/setup.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns3/named1.conf.in ns3/named.conf + +sed -e s/big[.]/signed./g ns1/signed.db +$KEYGEN -K ns1 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed >/dev/null 2>&1 +$KEYGEN -K ns1 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed >/dev/null 2>&1 +$SIGNER -K ns1 -S -f ns1/signed.db.signed -o signed ns1/signed.db >/dev/null diff --git a/bin/tests/system/reclimit/tests.sh b/bin/tests/system/reclimit/tests.sh new file mode 100644 index 0000000..76889ec --- /dev/null +++ b/bin/tests/system/reclimit/tests.sh @@ -0,0 +1,490 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +dig_with_opts() { + $DIG -p "${PORT}" +retries=0 "$@" +} + +status=0 +n=0 + +ns3_reset() { + copy_setports $1 ns3/named.conf + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reconfig 2>&1 | sed 's/^/I:ns3 /' + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush | sed 's/^/I:ns3 /' +} + +ns3_flush() { + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush | sed 's/^/I:ns3 /' +} + +ns3_sends_aaaa_queries() { + if grep "started AAAA fetch" ns3/named.run >/dev/null; then + return 0 + else + return 1 + fi +} + +# Check whether the number of queries ans2 received from ns3 (this value is +# read from dig output stored in file $1) is as expected. The expected query +# count is variable: +# - if ns3 sends AAAA queries, the query count should equal $2, +# - if ns3 does not send AAAA queries, the query count should equal $3. +check_query_count() { + count1=$(sed 's/[^0-9]//g;' $1) + count2=$(sed 's/[^0-9]//g;' $2) + count=$((count1 + count2)) + #echo_i "count1=$count1 count2=$count2 count=$count" + expected_count_with_aaaa=$3 + expected_count_without_aaaa=$4 + + if ns3_sends_aaaa_queries; then + expected_count=$expected_count_with_aaaa + else + expected_count=$expected_count_without_aaaa + fi + + if [ $count -ne $expected_count ]; then + echo_i "count $count (actual) != $expected_count (expected)" + ret=1 + fi +} + +echo_i "set max-recursion-depth=12" + +n=$((n + 1)) +echo_i "attempt excessive-depth lookup ($n)" +ret=0 +echo "1000" >ans2/ans.limit +echo "1000" >ans4/ans.limit +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.4 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect1.example.org >dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1 +check_query_count dig.out.2.test$n dig.out.4.test$n 27 14 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "attempt permissible lookup ($n)" +ret=0 +echo "12" >ans2/ans.limit +echo "12" >ans4/ans.limit +ns3_reset ns3/named1.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.4 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect2.example.org >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1 +check_query_count dig.out.2.test$n dig.out.4.test$n 50 26 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "set max-recursion-depth=5" + +n=$((n + 1)) +echo_i "attempt excessive-depth lookup ($n)" +ret=0 +echo "12" >ans2/ans.limit +ns3_reset ns3/named2.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.4 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect3.example.org >dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1 +check_query_count dig.out.2.test$n dig.out.4.test$n 13 7 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "attempt permissible lookup ($n)" +ret=0 +echo "5" >ans2/ans.limit +echo "5" >ans4/ans.limit +ns3_reset ns3/named2.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.4 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect4.example.org >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1 +check_query_count dig.out.2.test$n dig.out.4.test$n 22 12 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "set max-recursion-depth=100, max-recursion-queries=50" + +n=$((n + 1)) +echo_i "attempt excessive-queries lookup ($n)" +ret=0 +echo "13" >ans2/ans.limit +echo "13" >ans4/ans.limit +ns3_reset ns3/named3.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.4 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect5.example.org >dig.out.1.test$n || ret=1 +if ns3_sends_aaaa_queries; then + grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1 +fi +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1 +eval count=$(cat dig.out.2.test$n) +[ $count -le 50 ] || { + ret=1 + echo_i "count ($count) !<= 50" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "attempt permissible lookup ($n)" +ret=0 +echo "12" >ans2/ans.limit +ns3_reset ns3/named3.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect6.example.org >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +eval count=$(cat dig.out.2.test$n) +[ $count -le 50 ] || { + ret=1 + echo_i "count ($count) !<= 50" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "set max-recursion-depth=100, max-recursion-queries=40" + +n=$((n + 1)) +echo_i "attempt excessive-queries lookup ($n)" +ret=0 +echo "11" >ans2/ans.limit +ns3_reset ns3/named4.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect7.example.org >dig.out.1.test$n || ret=1 +if ns3_sends_aaaa_queries; then + grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1 +fi +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +eval count=$(cat dig.out.2.test$n) +[ $count -le 40 ] || { + ret=1 + echo_i "count ($count) !<= 40" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "attempt permissible lookup ($n)" +ret=0 +echo "9" >ans2/ans.limit +ns3_reset ns3/named4.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts @10.53.0.3 indirect8.example.org >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +eval count=$(cat dig.out.2.test$n) +[ $count -le 40 ] || { + ret=1 + echo_i "count ($count) !<= 40" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "attempting NS explosion ($n)" +ret=0 +ns3_reset ns3/named4.conf.in +dig_with_opts @10.53.0.2 reset >/dev/null || ret=1 +dig_with_opts +short @10.53.0.3 ns1.1.example.net >dig.out.1.test$n || ret=1 +dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1 +eval count=$(cat dig.out.2.test$n) +[ $count -lt 50 ] || ret=1 +dig_with_opts +short @10.53.0.7 count txt >dig.out.3.test$n || ret=1 +eval count=$(cat dig.out.3.test$n) +[ $count -lt 50 ] || { + ret=1 + echo_i "count ($count) !<= 50" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking RRset that exceeds max-records-per-type ($n)" +ret=0 +dig_with_opts @10.53.0.3 biganswer.big >dig.out.1.test$n || ret=1 +grep 'status: SERVFAIL' dig.out.1.test$n >/dev/null || ret=1 + +msg="error adding 'biganswer.big/A' in './IN' (cache): too many records (must not exceed 100)" +wait_for_log 10 "$msg" ns3/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +ns3_reset ns3/named5.conf.in +dig_with_opts @10.53.0.3 biganswer.big >dig.out.2.test$n || ret=1 +grep 'status: NOERROR' dig.out.2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +check_manytypes() ( + i=$1 + name=$2 + type=$3 + expected=$4 + exname=$5 + extype=$6 + ttl=$7 + neq_ttl=$8 + + if ! dig_with_opts @10.53.0.3 IN "$type" "$name" >"dig.out.$i.$type.test$n"; then + exit 1 + fi + + if ! grep 'status: '"${expected}"'' "dig.out.$i.$type.test$n" >/dev/null; then + exit 1 + fi + + if [ -n "$ttl" ] && ! grep -q "^$exname.[[:space:]]*${ttl}[[:space:]]*IN[[:space:]]*$extype" "dig.out.$i.$type.test$n"; then + exit 1 + fi + + if [ -n "${neq_ttl}" ] && grep -q "^$exname.[[:space:]]*${neq_ttl}[[:space:]]*IN[[:space:]]*$type" "dig.out.$i.$type.test$n"; then + exit 1 + fi + + exit 0 +) + +n=$((n + 1)) +ret=0 +echo_i "checking that priority names under the max-types-per-name limit get cached ($n)" + +# Query for NXDOMAIN for items on our priority list - these should get cached +for rrtype in AAAA MX NS; do + check_manytypes 1 manytypes.big "${rrtype}" NOERROR big SOA 120 || ret=1 +done +# Wait at least 1 second +for rrtype in AAAA MX NS; do + check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +ns3_flush + +n=$((n + 1)) +ret=0 +echo_i "checking that NXDOMAIN names under the max-types-per-name limit get cached ($n)" + +# Query for 10 NXDOMAIN types +for ntype in $(seq 65270 65279); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR big SOA 120 || ret=1 +done +# Wait at least 1 second +sleep 1 +# Query for 10 NXDOMAIN types again - these should be cached +for ntype in $(seq 65270 65279); do + check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR big SOA "" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +n=$((n + 1)) +ret=0 +echo_i "checking that existing names under the max-types-per-name limit get cached ($n)" + +# Limited to 10 types - these should be cached and the previous record should be evicted +for ntype in $(seq 65280 65289); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 +done +# Wait at least one second +sleep 1 +# Limited to 10 types - these should be cached +for ntype in $(seq 65280 65289); do + check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +n=$((n + 1)) +ret=0 +echo_i "checking that NXDOMAIN names over the max-types-per-name limit don't get cached ($n)" + +# Query for 10 NXDOMAIN types +for ntype in $(seq 65270 65279); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR big SOA 0 || ret=1 +done +# Wait at least 1 second +sleep 1 +# Query for 10 NXDOMAIN types again - these should not be cached +for ntype in $(seq 65270 65279); do + check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR big SOA 0 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +n=$((n + 1)) +ret=0 +echo_i "checking that priority NXDOMAIN names over the max-types-per-name limit get cached ($n)" + +# Query for NXDOMAIN for items on our priority list - these should get cached +for rrtype in AAAA MX NS; do + check_manytypes 1 manytypes.big "${rrtype}" NOERROR big SOA 120 || ret=1 +done +# Wait at least 1 second +for rrtype in AAAA MX NS; do + check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +n=$((n + 1)) +ret=0 +echo_i "checking that priority name over the max-types-per-name get cached ($n)" + +# Query for an item on our priority list - it should get cached +check_manytypes 1 manytypes.big "A" NOERROR manytypes.big A 120 || ret=1 +# Wait at least 1 second +sleep 1 +# Query the same name again - it should be in the cache +check_manytypes 2 manytypes.big "A" NOERROR big manytypes.A "" 120 || ret=1 + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +ns3_flush + +n=$((n + 1)) +ret=0 +echo_i "checking that priority name over the max-types-per-name don't get evicted ($n)" + +# Query for an item on our priority list - it should get cached +check_manytypes 1 manytypes.big "A" NOERROR manytypes.big A 120 || ret=1 +# Query for 10 more types - this should not evict A record +for ntype in $(seq 65280 65289); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big || ret=1 +done +# Wait at least 1 second +sleep 1 +# Query the same name again - it should be in the cache +check_manytypes 2 manytypes.big "A" NOERROR manytypes.big A "" 120 || ret=1 +# This one was first in the list and should have been evicted +check_manytypes 2 manytypes.big "TYPE65280" NOERROR manytypes.big TYPE65280 120 || ret=1 + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +ns3_flush + +n=$((n + 1)) +ret=0 +echo_i "checking that non-priority types cause eviction ($n)" + +# Everything on top of that will cause the cache eviction +for ntype in $(seq 65280 65299); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 +done +# Wait at least one second +sleep 1 +# These should have TTL != 120 now +for ntype in $(seq 65290 65299); do + check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 120 || ret=1 +done +# These should have been evicted +for ntype in $(seq 65280 65289); do + check_manytypes 3 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 +done +# These should have been evicted by the previous block +for ntype in $(seq 65290 65299); do + check_manytypes 4 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +ns3_flush + +n=$((n + 1)) +ret=0 +echo_i "checking that signed names under the max-types-per-name limit get cached ($n)" + +# Go through the 10 items, this should result in 20 items (type + rrsig(type)) +for ntype in $(seq 65280 65289); do + check_manytypes 1 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 120 || ret=1 +done + +# Wait at least one second +sleep 1 + +# These should have TTL != 120 now +for ntype in $(seq 65285 65289); do + check_manytypes 2 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" "" 120 || ret=1 +done + +# These should have been evicted +for ntype in $(seq 65280 65284); do + check_manytypes 3 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 120 || ret=1 +done + +# These should have been evicted by the previous block +for ntype in $(seq 65285 65289); do + check_manytypes 4 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +if [ $status -ne 0 ]; then exit 1; fi + +n=$((n + 1)) +ret=0 +echo_i "checking that lifting the limit will allow everything to get cached ($n)" + +# Lift the limit +ns3_reset ns3/named6.conf.in + +for ntype in $(seq 65280 65534); do + check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 +done +# Wait at least one second +sleep 1 +for ntype in $(seq 65280 65534); do + check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 120 || ret=1 +done + +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/reclimit/tests_sh_reclimit.py b/bin/tests/system/reclimit/tests_sh_reclimit.py new file mode 100644 index 0000000..6a0ab31 --- /dev/null +++ b/bin/tests/system/reclimit/tests_sh_reclimit.py @@ -0,0 +1,32 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "dsset-signed.", + "ans*/ans.limit", + "ans*/ans.run", + "ns1/K*", + "ns1/signed.db", + "ns1/signed.db.signed", + ] +) + + +# The reclimit is known to be quite unstable. GL #1587 +@isctest.mark.flaky(max_runs=2) +def test_reclimit(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/redirect/conf/bad1.conf b/bin/tests/system/redirect/conf/bad1.conf new file mode 100644 index 0000000..5ff4fee --- /dev/null +++ b/bin/tests/system/redirect/conf/bad1.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "hint.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; + allow-query { 10.0.1.0; }; +/* option 'forwarders' is not allowed in 'redirect' zone '.' */ + forwarders { 1.2.3.4; }; +}; diff --git a/bin/tests/system/redirect/conf/bad2.conf b/bin/tests/system/redirect/conf/bad2.conf new file mode 100644 index 0000000..0cf0a68 --- /dev/null +++ b/bin/tests/system/redirect/conf/bad2.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "hint.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; + allow-query { 10.0.1.0; }; +/* option 'also-notify' is not allowed in 'redirect' zone '.' */ + also-notify { 1.2.3.4; }; +}; diff --git a/bin/tests/system/redirect/conf/bad3.conf b/bin/tests/system/redirect/conf/bad3.conf new file mode 100644 index 0000000..b034c5b --- /dev/null +++ b/bin/tests/system/redirect/conf/bad3.conf @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "hint.db"; +}; + +/* redirect zones must be called "." */ +zone "x" { + type redirect; + file "redirect.db"; + allow-query { 10.0.1.0; }; +}; diff --git a/bin/tests/system/redirect/conf/good1.conf b/bin/tests/system/redirect/conf/good1.conf new file mode 100644 index 0000000..c5711e5 --- /dev/null +++ b/bin/tests/system/redirect/conf/good1.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "hint.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; +}; diff --git a/bin/tests/system/redirect/conf/good2.conf b/bin/tests/system/redirect/conf/good2.conf new file mode 100644 index 0000000..f6ebd63 --- /dev/null +++ b/bin/tests/system/redirect/conf/good2.conf @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type primary; + file "primary.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; +}; diff --git a/bin/tests/system/redirect/conf/good3.conf b/bin/tests/system/redirect/conf/good3.conf new file mode 100644 index 0000000..dcdd954 --- /dev/null +++ b/bin/tests/system/redirect/conf/good3.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type secondary; + file "sec.db"; + primaries { 1.2.3.4; }; +}; + +zone "." { + type redirect; + file "redirect.db"; +}; diff --git a/bin/tests/system/redirect/conf/good4.conf b/bin/tests/system/redirect/conf/good4.conf new file mode 100644 index 0000000..e046577 --- /dev/null +++ b/bin/tests/system/redirect/conf/good4.conf @@ -0,0 +1,23 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "." { + type hint; + file "hint.db"; +}; + +zone "." { + type redirect; + file "redirect.db"; + allow-query { 10.0.1.0; }; +}; diff --git a/bin/tests/system/redirect/ns1/example.db b/bin/tests/system/redirect/ns1/example.db new file mode 100644 index 0000000..90c09d4 --- /dev/null +++ b/bin/tests/system/redirect/ns1/example.db @@ -0,0 +1,50 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns1 marka.isc.org. 0 0 0 0 1200 +@ NS ns1 +ns1 A 10.53.0.1 +excluded-good-a AAAA 2001:eeee::1 + A 1.2.3.4 +excluded-bad-a AAAA 2001:eeee::2 + A 10.0.0.1 +excluded-only AAAA 2001:eeee::3 +partially-excluded-good-a AAAA 2001:eeee::1 + AAAA 2001::1 + A 1.2.3.4 +partially-excluded-bad-a AAAA 2001:eeee::2 + AAAA 2001::2 + A 10.0.0.1 +partially-excluded-only AAAA 2001:eeee::3 + AAAA 2001::3 +a-only A 1.2.3.5 +a-and-aaaa AAAA 2001::1 + A 1.2.3.6 +aaaa-only AAAA 2001::2 +a-not-mapped A 10.0.0.2 +mx-only MX 10 ns.example. +cname-excluded-good-a CNAME excluded-good-a +cname-excluded-bad-a CNAME excluded-bad-a +cname-excluded-only CNAME excluded-only +cname-partial-excluded-good-a CNAME partial-excluded-good-a +cname-partial-excluded-bad-a CNAME partial-excluded-bad-a +cname-partial-excluded-only CNAME partial-excluded-only +cname-a-only CNAME a-only +cname-a-and-aaaa CNAME a-and-aaaa +cname-aaaa-only CNAME aaaa-only +cname-a-not-mapped CNAME a-not-mapped +cname-mx-only CNAME mx-only +cname-non-existent CNAME non-existent +ttl-less-than-600 500 A 5.6.7.8 +ttl-more-than-600 700 A 5.6.7.8 +ttl-less-than-minimum 1100 A 5.6.7.8 +ttl-more-than-minimum 1300 A 5.6.7.8 diff --git a/bin/tests/system/redirect/ns1/named.conf.in b/bin/tests/system/redirect/ns1/named.conf.in new file mode 100644 index 0000000..3b4ccad --- /dev/null +++ b/bin/tests/system/redirect/ns1/named.conf.in @@ -0,0 +1,57 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-recursion { 10.53.0.1; }; + notify yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "signed" { + type primary; + file "signed.db.signed"; +}; + +zone "nsec3" { + type primary; + file "nsec3.db.signed"; +}; + +zone "." { + type redirect; + file "redirect.db"; + allow-query { !10.53.0.2; !10.53.0.4; any; }; +}; diff --git a/bin/tests/system/redirect/ns1/redirect.db b/bin/tests/system/redirect/ns1/redirect.db new file mode 100644 index 0000000..b2a60bb --- /dev/null +++ b/bin/tests/system/redirect/ns1/redirect.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0 +@ IN NS ns.example.net +; +; NS records do not need address records in this zone as it is not in the +; normal namespace. +; +*. IN A 100.100.100.2 +*. IN AAAA 2001:ffff:ffff::100.100.100.2 diff --git a/bin/tests/system/redirect/ns1/root.db b/bin/tests/system/redirect/ns1/root.db new file mode 100644 index 0000000..6df215f --- /dev/null +++ b/bin/tests/system/redirect/ns1/root.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +example NS ns1.example. +ns1.example. A 10.53.0.1 +signed NS ns1.example. +ns1.signed. A 10.53.0.1 diff --git a/bin/tests/system/redirect/ns1/sign.sh b/bin/tests/system/redirect/ns1/sign.sh new file mode 100644 index 0000000..4b1b092 --- /dev/null +++ b/bin/tests/system/redirect/ns1/sign.sh @@ -0,0 +1,36 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=signed +infile=example.db +zonefile=signed.db + +key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone) +key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +zone=nsec3 +infile=example.db +zonefile=nsec3.db + +key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone) +key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -fk $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -3 - -g -o $zone $zonefile >/dev/null diff --git a/bin/tests/system/redirect/ns2/example.db.in b/bin/tests/system/redirect/ns2/example.db.in new file mode 100644 index 0000000..a87ae7d --- /dev/null +++ b/bin/tests/system/redirect/ns2/example.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0 +@ NS ns2 +ns2 A 10.53.0.2 +a A 10.53.0.2 diff --git a/bin/tests/system/redirect/ns2/named.conf.in b/bin/tests/system/redirect/ns2/named.conf.in new file mode 100644 index 0000000..e07d75b --- /dev/null +++ b/bin/tests/system/redirect/ns2/named.conf.in @@ -0,0 +1,59 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "." { + type redirect; + file "redirect.db"; + allow-query { !10.53.0.4; any; }; +}; + +zone "example.nil" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/redirect/ns2/redirect.db.in b/bin/tests/system/redirect/ns2/redirect.db.in new file mode 100644 index 0000000..e05d64d --- /dev/null +++ b/bin/tests/system/redirect/ns2/redirect.db.in @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0 +@ IN NS ns.example.net +; +; NS records do not need address records in this zone as it is not in the +; normal namespace. +; +*. IN A 100.100.100.1 +*. IN AAAA 2001:ffff:ffff::100.100.100.1 diff --git a/bin/tests/system/redirect/ns3/example.db b/bin/tests/system/redirect/ns3/example.db new file mode 100644 index 0000000..4cceedf --- /dev/null +++ b/bin/tests/system/redirect/ns3/example.db @@ -0,0 +1,50 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA ns3 marka.isc.org. 0 0 0 0 1200 +@ NS ns3 +ns3 A 10.53.0.3 +excluded-good-a AAAA 2001:eeee::1 + A 1.2.3.4 +excluded-bad-a AAAA 2001:eeee::2 + A 10.0.0.1 +excluded-only AAAA 2001:eeee::3 +partially-excluded-good-a AAAA 2001:eeee::1 + AAAA 2001::1 + A 1.2.3.4 +partially-excluded-bad-a AAAA 2001:eeee::2 + AAAA 2001::2 + A 10.0.0.1 +partially-excluded-only AAAA 2001:eeee::3 + AAAA 2001::3 +a-only A 1.2.3.5 +a-and-aaaa AAAA 2001::1 + A 1.2.3.6 +aaaa-only AAAA 2001::2 +a-not-mapped A 10.0.0.2 +mx-only MX 10 ns.example. +cname-excluded-good-a CNAME excluded-good-a +cname-excluded-bad-a CNAME excluded-bad-a +cname-excluded-only CNAME excluded-only +cname-partial-excluded-good-a CNAME partial-excluded-good-a +cname-partial-excluded-bad-a CNAME partial-excluded-bad-a +cname-partial-excluded-only CNAME partial-excluded-only +cname-a-only CNAME a-only +cname-a-and-aaaa CNAME a-and-aaaa +cname-aaaa-only CNAME aaaa-only +cname-a-not-mapped CNAME a-not-mapped +cname-mx-only CNAME mx-only +cname-non-existent CNAME non-existent +ttl-less-than-600 500 A 5.6.7.8 +ttl-more-than-600 700 A 5.6.7.8 +ttl-less-than-minimum 1100 A 5.6.7.8 +ttl-more-than-minimum 1300 A 5.6.7.8 diff --git a/bin/tests/system/redirect/ns3/named.conf.in b/bin/tests/system/redirect/ns3/named.conf.in new file mode 100644 index 0000000..51e590f --- /dev/null +++ b/bin/tests/system/redirect/ns3/named.conf.in @@ -0,0 +1,54 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-recursion { 10.53.0.3; }; + notify yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; + +zone "signed" { + type primary; + file "signed.db.signed"; +}; + +zone "nsec3" { + type primary; + file "nsec3.db.signed"; +}; + +zone "redirect" { + type primary; + file "redirect.db"; +}; diff --git a/bin/tests/system/redirect/ns3/redirect.db b/bin/tests/system/redirect/ns3/redirect.db new file mode 100644 index 0000000..4f2d7a6 --- /dev/null +++ b/bin/tests/system/redirect/ns3/redirect.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA a.root-servers.nil. hostmaster.example.net. 0 0 0 0 0 +@ IN NS a.root-servers.nil. +10.in-addr.arpa TXT turn off redirect +* IN A 100.100.100.1 +* IN AAAA 2001:ffff:ffff::100.100.100.1 diff --git a/bin/tests/system/redirect/ns3/root.db b/bin/tests/system/redirect/ns3/root.db new file mode 100644 index 0000000..13433ef --- /dev/null +++ b/bin/tests/system/redirect/ns3/root.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA a.root-servers.nil. marka.isc.org. 0 0 0 0 0 +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.3 +example NS ns1.example. +ns1.example. A 10.53.0.3 +signed NS ns1.example. +ns1.signed. A 10.53.0.3 +redirect NS a.root-servers.nil diff --git a/bin/tests/system/redirect/ns3/sign.sh b/bin/tests/system/redirect/ns3/sign.sh new file mode 100644 index 0000000..4b1b092 --- /dev/null +++ b/bin/tests/system/redirect/ns3/sign.sh @@ -0,0 +1,36 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=signed +infile=example.db +zonefile=signed.db + +key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone) +key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +zone=nsec3 +infile=example.db +zonefile=nsec3.db + +key1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 $zone) +key2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -3 -fk $zone) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -3 - -g -o $zone $zonefile >/dev/null diff --git a/bin/tests/system/redirect/ns4/example.db.in b/bin/tests/system/redirect/ns4/example.db.in new file mode 100644 index 0000000..8057d1b --- /dev/null +++ b/bin/tests/system/redirect/ns4/example.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns.example.net hostmaster.example.net 0 0 0 0 0 +@ NS ns4 +ns4 A 10.53.0.4 +a A 10.53.0.2 diff --git a/bin/tests/system/redirect/ns4/named.conf.in b/bin/tests/system/redirect/ns4/named.conf.in new file mode 100644 index 0000000..8937453 --- /dev/null +++ b/bin/tests/system/redirect/ns4/named.conf.in @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +controls { /* empty */ }; + +acl rfc1918 { 10/8; 192.168/16; 172.16/12; }; + +options { + query-source address 10.53.0.2; /* note this is not 10.53.0.4 */ + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + nxdomain-redirect "redirect"; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/redirect/ns4/root.hint b/bin/tests/system/redirect/ns4/root.hint new file mode 100644 index 0000000..3889a8b --- /dev/null +++ b/bin/tests/system/redirect/ns4/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.3 diff --git a/bin/tests/system/redirect/ns5/named.conf.in b/bin/tests/system/redirect/ns5/named.conf.in new file mode 100644 index 0000000..2513a45 --- /dev/null +++ b/bin/tests/system/redirect/ns5/named.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + port @PORT@; + listen-on port @PORT@ { 10.53.0.5; }; + pid-file "named.pid"; + nxdomain-redirect signed; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +// An unsigned zone that ns6 has a delegation for. +zone "unsigned." { + type primary; + file "unsigned.db"; +}; diff --git a/bin/tests/system/redirect/ns5/root.db.in b/bin/tests/system/redirect/ns5/root.db.in new file mode 100644 index 0000000..19aa61d --- /dev/null +++ b/bin/tests/system/redirect/ns5/root.db.in @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 86400 IN SOA a.root-servers.nil. hostmaster.example.net. 2019022100 1800 900 604800 86400 +. 518400 IN NS a.root-servers.nil. +a.root-servers.nil. 518400 IN A 10.53.0.5 +signed. 172800 IN NS ns.signed. +ns.signed. 172800 IN A 10.53.0.6 +unsigned. 172800 IN NS ns.unsigned. +ns.unsigned. 172800 IN A 10.53.0.5 diff --git a/bin/tests/system/redirect/ns5/sign.sh b/bin/tests/system/redirect/ns5/sign.sh new file mode 100644 index 0000000..0818d67 --- /dev/null +++ b/bin/tests/system/redirect/ns5/sign.sh @@ -0,0 +1,44 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +# We sign the zone here and move the signed zone to ns6. +# The ns5 server actually does not serve this zone but +# the DS and NS records are in the test root zone, and +# delegate to ns6. +zone=signed. +infile=signed.db.in +zonefile=signed.db + +key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone 2>/dev/null) +key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -fk $zone 2>/dev/null) + +cat $infile $key1.key $key2.key >$zonefile + +$SIGNER -P -g -O full -o $zone $zonefile >sign.ns5.signed.out + +cp signed.db.signed ../ns6 + +# Root zone. +zone=. +infile=root.db.in +zonefile=root.db + +key1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone 2>/dev/null) +key2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -fk $zone 2>/dev/null) + +# cat $infile $key1.key $key2.key > $zonefile +cat $infile dsset-signed. $key1.key $key2.key >$zonefile + +$SIGNER -P -g -O full -o $zone $zonefile >sign.ns5.root.out diff --git a/bin/tests/system/redirect/ns5/signed.db.in b/bin/tests/system/redirect/ns5/signed.db.in new file mode 100644 index 0000000..6579227 --- /dev/null +++ b/bin/tests/system/redirect/ns5/signed.db.in @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA ns.signed. hostmaster.signed. 0 0 0 0 0 +@ IN NS ns.signed. + +ns.signed. IN A 10.0.53.6 +domain.signed. IN A 10.0.53.1 + +* IN A 100.100.100.1 +* IN AAAA 2001:ffff:ffff::100.100.100.1 diff --git a/bin/tests/system/redirect/ns5/unsigned.db b/bin/tests/system/redirect/ns5/unsigned.db new file mode 100644 index 0000000..10e06ff --- /dev/null +++ b/bin/tests/system/redirect/ns5/unsigned.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA ns.unsigned. hostmaster.unsigned. 0 0 0 0 0 +@ IN NS ns.unsigned. + +ns.unsigned. IN A 10.53.0.6 +domain.unsigned. IN A 10.0.53.1 + +* IN A 100.100.100.1 +* IN AAAA 2001:ffff:ffff::100.100.100.1 diff --git a/bin/tests/system/redirect/ns6/named.conf.in b/bin/tests/system/redirect/ns6/named.conf.in new file mode 100644 index 0000000..dee2bcf --- /dev/null +++ b/bin/tests/system/redirect/ns6/named.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +options { + port @PORT@; + listen-on port @PORT@ { 10.53.0.6; }; + pid-file "named.pid"; + nxdomain-redirect unsigned; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +// A signed zone that ns5 has a delegation for. +zone "signed." { + type primary; + file "signed.db.signed"; +}; diff --git a/bin/tests/system/redirect/ns6/root.db b/bin/tests/system/redirect/ns6/root.db new file mode 100644 index 0000000..a8e6a45 --- /dev/null +++ b/bin/tests/system/redirect/ns6/root.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 86400 IN SOA a.root-servers.nil. hostmaster.example.net. 2019022100 1800 900 604800 86400 +. 518400 IN NS a.root-servers.nil. +a.root-servers.nil. 518400 IN A 10.53.0.6 +signed. 172800 IN NS ns.signed. +ns.signed. 172800 IN A 10.53.0.6 +unsigned. 172800 IN NS ns.unsigned. +ns.unsigned. 172800 IN A 10.53.0.5 diff --git a/bin/tests/system/redirect/setup.sh b/bin/tests/system/redirect/setup.sh new file mode 100644 index 0000000..5022a83 --- /dev/null +++ b/bin/tests/system/redirect/setup.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf + +cp ns2/redirect.db.in ns2/redirect.db +cp ns2/example.db.in ns2/example.db +(cd ns1 && $SHELL sign.sh) + +cp ns4/example.db.in ns4/example.db +(cd ns3 && $SHELL sign.sh) +(cd ns5 && $SHELL sign.sh) diff --git a/bin/tests/system/redirect/tests.sh b/bin/tests/system/redirect/tests.sh new file mode 100644 index 0000000..5d07490 --- /dev/null +++ b/bin/tests/system/redirect/tests.sh @@ -0,0 +1,555 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=1 + +rm -f dig.out.* + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p ${PORT}" +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +for conf in conf/good*.conf; do + echo_i "checking that $conf is accepted ($n)" + ret=0 + $CHECKCONF "$conf" || ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +for conf in conf/bad*.conf; do + echo_i "checking that $conf is rejected ($n)" + ret=0 + $CHECKCONF "$conf" >/dev/null && ret=1 + n=$((n + 1)) + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +echo_i "checking A zone redirect works for nonexist ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect updates statistics ($n)" +ret=0 +rm -f ns2/named.stats 2>/dev/null +$RNDCCMD 10.53.0.2 stats || ret=1 +PRE=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns2/named.stats) +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || ret=1 +rm -f ns2/named.stats 2>/dev/null +$RNDCCMD 10.53.0.2 stats || ret=1 +POST=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns2/named.stats) +if [ $((POST - PRE)) != 1 ]; then ret=1; fi +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect works for nonexist ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect works for nonexist ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect doesn't work for acl miss ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 a >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect doesn't work for acl miss ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect doesn't work for acl miss ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.4 any >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 aaaa >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns2.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect works for nonexist authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 a >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect works for nonexist authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect works for nonexist authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect doesn't work for acl miss authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 a >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect doesn't work for acl miss authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect doesn't work for acl miss authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.4 any >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect works for signed nonexist, DO=0 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 a >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect works for signed nonexist, DO=0 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect works for signed nonexist, DO=0 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect fails for signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 a >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect fails for signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect fails for signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 a >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 aaaa >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY zone redirect fails for nsec3 signed nonexist, DO=1 authoritative ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test$n >/dev/null || ret=1 +grep "100.100.100.2" dig.out.ns1.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns1.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking zone redirect works (with noerror) when qtype is not found ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 txt >dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that redirect zones reload correctly" +ret=0 +sleep 1 # ensure file mtime will have changed +cat ns2/example.db.in | sed -e 's/0 0 0 0 0/1 0 0 0 0/' >ns2/example.db +cat ns2/redirect.db.in | sed -e 's/0 0 0 0 0/1 0 0 0 0/' -e 's/\.1$/.2/' >ns2/redirect.db +rndc_reload ns2 10.53.0.2 +for i in 1 2 3 4 5 6 7 8 9; do + tmp=0 + $DIG $DIGOPTS +short @10.53.0.2 soa example.nil >dig.out.ns1.test$n || tmp=1 + set -- $(cat dig.out.ns1.test$n) + [ $3 = 1 ] || tmp=1 + $DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 a >dig.out.ns2.test$n || tmp=1 + grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || tmp=1 + grep "100.100.100.2" dig.out.ns2.test$n >/dev/null || tmp=1 + [ $tmp -eq 0 ] && break + sleep 1 +done +[ $tmp -eq 1 ] && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A nxdomain-redirect works for nonexist ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "nonexist. .*100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA nxdomain-redirect works for nonexist ($n)" +ret=0 +rm -f ns4/named.stats 2>/dev/null +$RNDCCMD 10.53.0.4 stats || ret=1 +PRE_RED=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns4/named.stats) +PRE_SUC=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected and resulted in a successful remote lookup$/\1/p" ns4/named.stats) +$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 aaaa >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "nonexist. .*2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA nxdomain-redirect updates statistics ($n)" +ret=0 +rm -f ns4/named.stats 2>/dev/null +$RNDCCMD 10.53.0.4 stats || ret=1 +POST_RED=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected$/\1/p" ns4/named.stats) +POST_SUC=$(sed -n -e "s/[ ]*\([0-9]*\).queries resulted in NXDOMAIN that were redirected and resulted in a successful remote lookup$/\1/p" ns4/named.stats) +if [ $((POST_RED - PRE_RED)) != 1 ]; then ret=1; fi +if [ $((POST_SUC - PRE_SUC)) != 1 ]; then ret=1; fi +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY nxdomain-redirect works for nonexist ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A nxdomain-redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA nxdomain-redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 aaaa >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY nxdomain-redirect works for signed nonexist, DO=0 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A nxdomain-redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA nxdomain-redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 aaaa >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY nxdomain-redirect fails for signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.signed. +dnssec @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking A nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking AAAA nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 aaaa >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking ANY nxdomain-redirect fails for nsec3 signed nonexist, DO=1 ($n)" +ret=0 +$DIG $DIGOPTS nonexist.nsec3. +dnssec @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "100.100.100.1" dig.out.ns4.test$n >/dev/null && ret=1 +grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null && ret=1 +grep "IN.NSEC3" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking nxdomain-redirect works (with noerror) when qtype is not found ($n)" +ret=0 +$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 txt >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking nxdomain-redirect against authoritative zone ($n)" +ret=0 +$DIG $DIGOPTS nonexist.example @10.53.0.4 -b 10.53.0.2 a >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking nxdomain-redirect against built-in RFC-1918 zone ($n)" +ret=0 +$DIG $DIGOPTS -x 10.0.0.1 @10.53.0.4 -b 10.53.0.2 >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking tld nxdomain-redirect against signed root zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.5 asdfasdfasdf >dig.out.ns5.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking tld nxdomain-redirect against unsigned root zone ($n)" +ret=0 +$DIG $DIGOPTS @10.53.0.6 asdfasdfasdf >dig.out.ns6.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns6.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking extended error is not set on allow-recursion ($n)" +ret=0 +$DIG $DIGOPTS example. @10.53.0.1 -b 10.53.0.2 soa >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1 +grep "EDE" dig.out.ns1.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/redirect/tests_sh_redirect.py b/bin/tests/system/redirect/tests_sh_redirect.py new file mode 100644 index 0000000..5f20aad --- /dev/null +++ b/bin/tests/system/redirect/tests_sh_redirect.py @@ -0,0 +1,46 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns1/K*", + "ns1/*.signed", + "ns1/dsset-nsec3.", + "ns1/dsset-signed.", + "ns1/nsec3.db", + "ns1/signed.db", + "ns2/example.db", + "ns2/named.stats", + "ns2/redirect.db", + "ns3/K*", + "ns3/*.signed", + "ns3/dsset-nsec3.", + "ns3/dsset-signed.", + "ns3/nsec3.db", + "ns3/signed.db", + "ns4/example.db", + "ns4/named.stats", + "ns5/K*", + "ns5/dsset-*", + "ns5/*.signed", + "ns5/root.db", + "ns5/sign.ns5.*", + "ns5/signed.db", + "ns6/signed.db.signed", + ] +) + + +def test_redirect(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/resolver/ans10/ans.py b/bin/tests/system/resolver/ans10/ans.py new file mode 100644 index 0000000..6e95dbb --- /dev/null +++ b/bin/tests/system/resolver/ans10/ans.py @@ -0,0 +1,152 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from __future__ import print_function +import os +import sys +import signal +import socket +import select +from datetime import datetime, timedelta +import time +import functools + +import dns, dns.message, dns.query, dns.flags +from dns.rdatatype import * +from dns.rdataclass import * +from dns.rcode import * +from dns.name import * + + +# Log query to file +def logquery(type, qname): + with open("qlog", "a") as f: + f.write("%s %s\n", type, qname) + + +############################################################################ +# Respond to a DNS query. +# If there are EDNS options present return FORMERR copying the OPT record. +# Otherwise: +# SOA gets a unsigned response. +# NS gets a unsigned response. +# A gets a unsigned response. +# All other types get a unsigned NODATA response. +############################################################################ +def create_response(msg): + m = dns.message.from_wire(msg) + qname = m.question[0].name.to_text() + rrtype = m.question[0].rdtype + typename = dns.rdatatype.to_text(rrtype) + + with open("query.log", "a") as f: + f.write("%s %s\n" % (typename, qname)) + print("%s %s" % (typename, qname), end=" ") + + if m.edns != -1 and len(m.options) != 0: + r = dns.message.make_response(m) + r.use_edns( + edns=m.edns, ednsflags=m.ednsflags, payload=m.payload, options=m.options + ) + r.set_rcode(FORMERR) + else: + r = dns.message.make_response(m) + r.set_rcode(NOERROR) + if rrtype == A: + r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) + elif rrtype == NS: + r.answer.append(dns.rrset.from_text(qname, 1, IN, NS, ".")) + elif rrtype == SOA: + r.answer.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0")) + else: + r.authority.append(dns.rrset.from_text(qname, 1, IN, SOA, ". . 0 0 0 0 0")) + r.flags |= dns.flags.AA + return r + + +def sigterm(signum, frame): + print("Shutting down now...") + os.remove("ans.pid") + running = False + sys.exit(0) + + +############################################################################ +# Main +# +# Set up responder and control channel, open the pid file, and start +# the main loop, listening for queries on the query channel or commands +# on the control channel and acting on them. +############################################################################ +ip4 = "10.53.0.10" +ip6 = "fd92:7065:b8e:ffff::10" + +try: + port = int(os.environ["PORT"]) +except: + port = 5300 + +query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +query4_socket.bind((ip4, port)) +havev6 = True +try: + query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + try: + query6_socket.bind((ip6, port)) + except: + query6_socket.close() + havev6 = False +except: + havev6 = False +signal.signal(signal.SIGTERM, sigterm) + +f = open("ans.pid", "w") +pid = os.getpid() +print(pid, file=f) +f.close() + +running = True + +print("Listening on %s port %d" % (ip4, port)) +if havev6: + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") + +if havev6: + input = [query4_socket, query6_socket] +else: + input = [query4_socket] + +while running: + try: + inputready, outputready, exceptready = select.select(input, [], []) + except select.error as e: + break + except socket.error as e: + break + except KeyboardInterrupt: + break + + for s in inputready: + if s == query4_socket or s == query6_socket: + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) + # Handle incoming queries + msg = s.recvfrom(65535) + rsp = create_response(msg[0]) + if rsp: + print(dns.rcode.to_text(rsp.rcode())) + s.sendto(rsp.to_wire(), msg[1]) + else: + print("NO RESPONSE") + if not running: + break diff --git a/bin/tests/system/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl new file mode 100644 index 0000000..079a7d9 --- /dev/null +++ b/bin/tests/system/resolver/ans2/ans.pl @@ -0,0 +1,184 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Ad hoc name server +# + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.2", + LocalPort => $localport, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + if ($qname eq "com" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("com 300 NS a.root-servers.nil.")); + } elsif ($qname eq "example.com" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.com 300 NS a.root-servers.nil.")); + } elsif ($qname eq "cname1.example.com") { + # Data for the "cname + other data / 1" test + $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 CNAME cname1.example.com")); + $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 A 1.2.3.4")); + } elsif ($qname eq "cname2.example.com") { + # Data for the "cname + other data / 2" test: same RRs in opposite order + $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4")); + $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com")); + } elsif ($qname =~ /redirect\.com/) { + $packet->push("authority", new Net::DNS::RR("redirect.com 300 NS ns.redirect.com")); + $packet->push("additional", new Net::DNS::RR("ns.redirect.com 300 A 10.53.0.6")); + } elsif ($qname =~ /\.tld1/) { + $packet->push("authority", new Net::DNS::RR("tld1 300 NS ns.tld1")); + $packet->push("additional", new Net::DNS::RR("ns.tld1 300 A 10.53.0.6")); + } elsif ($qname =~ /\.tld2/) { + $packet->push("authority", new Net::DNS::RR("tld2 300 NS ns.tld2")); + $packet->push("additional", new Net::DNS::RR("ns.tld2 300 A 10.53.0.7")); + } elsif ($qname eq "org" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("org 300 NS a.root-servers.nil.")); + } elsif ($qname eq "example.org" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.org 300 NS a.root-servers.nil.")); + } elsif (($qname eq "baddname.example.org" || $qname eq "gooddname.example.org") && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("example.org 300 NS a.root-servers.nil.")); + } elsif ($qname eq "www.example.org" || + $qname eq "badcname.example.org" || + $qname eq "goodcname.example.org" || + $qname eq "foo.baddname.example.org" || + $qname eq "foo.gooddname.example.org") { + # Data for address/alias filtering. + $packet->header->aa(1); + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 A 192.0.2.1")); + } elsif ($qtype eq "AAAA") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 AAAA 2001:db8:beef::1")); + } + } elsif ($qname eq "net" && $qtype eq "NS") { + $packet->header->aa(1); + $packet->push("answer", new Net::DNS::RR("net 300 NS a.root-servers.nil.")); + } elsif ($qname eq "noresponse.exampleudp.net") { + next; + } elsif ($qname =~ /example\.net/) { + $packet->push("authority", new Net::DNS::RR("example.net 300 NS ns.example.net")); + $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3")); + } elsif ($qname =~ /exampleudp\.net/) { + $packet->push("authority", new Net::DNS::RR("exampleudp.net 300 NS ns.exampleudp.net")); + $packet->push("additional", new Net::DNS::RR("ns.exampleudp.net 300 A 10.53.0.2")); + } elsif ($qname =~ /lame\.example\.org/) { + $packet->header->ad(0); + $packet->header->aa(0); + $packet->push("authority", new Net::DNS::RR("lame.example.org 300 NS ns.lame.example.org")); + $packet->push("additional", new Net::DNS::RR("ns.lame.example.org 300 A 10.53.0.3")); + } elsif ($qname =~ /sub\.example\.org/) { + # Data for CNAME/DNAME filtering. The final answers are + # expected to be accepted regardless of the filter setting. + $packet->push("authority", new Net::DNS::RR("sub.example.org 300 NS ns.sub.example.org")); + $packet->push("additional", new Net::DNS::RR("ns.sub.example.org 300 A 10.53.0.3")); + } elsif ($qname =~ /glue-in-answer\.example\.org/) { + $packet->push("answer", new Net::DNS::RR("ns.glue-in-answer.example.org 300 A 10.53.0.3")); + $packet->push("authority", new Net::DNS::RR("glue-in-answer.example.org 300 NS ns.glue-in-answer.example.org")); + $packet->push("additional", new Net::DNS::RR("ns.glue-in-answer.example.org 300 A 10.53.0.3")); + } elsif ($qname =~ /\.broken/ || $qname =~ /^broken/) { + # Delegation to broken TLD. + $packet->push("authority", new Net::DNS::RR("broken 300 NS ns.broken")); + $packet->push("additional", new Net::DNS::RR("ns.broken 300 A 10.53.0.4")); + } elsif ($qname =~ /\.partial-formerr/) { + $packet->header->rcode("FORMERR"); + } elsif ($qname eq "gl6412") { + if ($qtype eq "SOA") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } elsif ($qtype eq "NS") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 NS ns2" . $qname)); + $packet->push("answer", + new Net::DNS::RR($qname . " 300 NS ns3" . $qname)); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } elsif ($qname eq "a.gl6412" || $qname eq "a.a.gl6412") { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } elsif ($qname eq "ns2.gl6412") { + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 10.53.0.2")); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } elsif ($qname eq "ns3.gl6412") { + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 10.53.0.3")); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } else { + # Data for the "bogus referrals" test + $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com")); + $packet->push("additional", new Net::DNS::RR("ns.below.www.example.com 300 A 10.53.0.3")); + } + + $sock->send($packet->data); + + print "RESPONSE:\n"; + $packet->print; + print "\n"; +} diff --git a/bin/tests/system/resolver/ans3/ans.pl b/bin/tests/system/resolver/ans3/ans.pl new file mode 100644 index 0000000..02a8c1d --- /dev/null +++ b/bin/tests/system/resolver/ans3/ans.pl @@ -0,0 +1,234 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Ad hoc name server +# + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early +local $SIG{PIPE} = 'IGNORE'; + +# Flush logged output after every line +local $| = 1; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $server_addr = "10.53.0.3"; + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; +my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +sub handleQuery { + my $buf = shift; + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + $packet->header->aa(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + if ($qname eq "example.net" && $qtype eq "NS") { + $packet->push("answer", new Net::DNS::RR($qname . " 300 NS ns.example.net")); + $packet->push("additional", new Net::DNS::RR("ns.example.net 300 A 10.53.0.3")); + } elsif ($qname eq "ns.example.net") { + $packet->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.3")); + } elsif ($qname eq "nodata.example.net") { + # Do not add a SOA RRset. + } elsif ($qname eq "noresponse.example.net") { + # Do not response. + print "RESPONSE:\n"; + return ""; + } elsif ($qname eq "nxdomain.example.net") { + # Do not add a SOA RRset. + $packet->header->rcode(NXDOMAIN); + } elsif ($qname eq "www.example.net") { + # Data for address/alias filtering. + if ($qtype eq "A") { + $packet->push("answer", new Net::DNS::RR($qname . " 300 A 192.0.2.1")); + } elsif ($qtype eq "AAAA") { + $packet->push("answer", new Net::DNS::RR($qname . " 300 AAAA 2001:db8:beef::1")); + } + } elsif ($qname eq "badcname.example.net") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 CNAME badcname.example.org")); + } elsif (($qname eq "baddname.example.net" || $qname eq "gooddname.example.net") && $qtype eq "NS") { + $packet->push("authority", new Net::DNS::RR("example.net IN SOA (1 2 3 4 5)")) + } elsif ($qname eq "foo.baddname.example.net") { + $packet->push("answer", + new Net::DNS::RR("baddname.example.net" . + " 300 DNAME baddname.example.org")); + } elsif ($qname eq "foo.gooddname.example.net") { + $packet->push("answer", + new Net::DNS::RR("gooddname.example.net" . + " 300 DNAME gooddname.example.org")); + } elsif ($qname eq "goodcname.example.net") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 CNAME goodcname.example.org")); + } elsif ($qname =~ /^longcname/) { + $cname = $qname =~ s/longcname/longcnamex/r; + $packet->push("answer", new Net::DNS::RR($qname . " 300 CNAME " . $cname)); + } elsif ($qname =~ /^nodata\.example\.net$/i) { + $packet->header->aa(1); + } elsif ($qname =~ /^nxdomain\.example\.net$/i) { + $packet->header->aa(1); + $packet->header->rcode(NXDOMAIN); + } elsif ($qname =~ /lame\.example\.org/) { + $packet->header->ad(0); + $packet->header->aa(0); + $packet->push("authority", new Net::DNS::RR("lame.example.org 300 NS ns.lame.example.org")); + $packet->push("additional", new Net::DNS::RR("ns.lame.example.org 300 A 10.53.0.3")); + } elsif ($qname eq "large-referral.example.net") { + for (my $i = 1; $i < 1000; $i++) { + $packet->push("authority", new Net::DNS::RR("large-referral.example.net 300 NS ns" . $i . ".fake.redirect.com")); + } + # No glue records + } elsif ($qname eq "foo.bar.sub.tld1") { + $packet->push("answer", new Net::DNS::RR("$qname 300 TXT baz")); + } elsif ($qname eq "cname.sub.example.org") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 CNAME ok.sub.example.org")); + } elsif ($qname eq "ok.sub.example.org") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 192.0.2.1")); + } elsif ($qname eq "www.dname.sub.example.org") { + $packet->push("answer", + new Net::DNS::RR("dname.sub.example.org" . + " 300 DNAME ok.sub.example.org")); + } elsif ($qname eq "www.ok.sub.example.org") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 192.0.2.1")); + } elsif ($qname eq "foo.glue-in-answer.example.org") { + $packet->push("answer", new Net::DNS::RR($qname . " 300 A 192.0.2.1")); + } elsif ($qname eq "ns.example.net") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 A 10.53.0.3")); + } elsif ($qname =~ /\.partial-formerr/) { + $packet->push("answer", + new Net::DNS::RR($qname . " 1 A 10.53.0.3")); + } elsif ($qname eq "gl6412") { + if ($qtype eq "SOA") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } elsif ($qtype eq "NS") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 NS ns2" . $qname)); + $packet->push("answer", + new Net::DNS::RR($qname . " 300 NS ns3" . $qname)); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } elsif ($qname eq "a.gl6412" || $qname eq "a.a.gl6412") { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } elsif ($qname eq "ns2.gl6412") { + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 10.53.0.2")); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } elsif ($qname eq "ns3.gl6412") { + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . " 300 A 10.53.0.3")); + } else { + $packet->push("authority", + new Net::DNS::RR($qname . " 300 SOA . . 0 0 0 0 0")); + } + } else { + $packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4")); + } + + print "RESPONSE:\n"; + $packet->print; + + return $packet->data; +} + +# Main +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($tcpsock), 1) = 1; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($udpsock), 1)) { + printf "UDP request\n"; + my $buf; + $udpsock->recv($buf, 512); + my $result = handleQuery($buf); + my $num_chars = $udpsock->send($result); + print " Sent $num_chars bytes via UDP\n"; + } elsif (vec($rout, fileno($tcpsock), 1)) { + my $conn = $tcpsock->accept; + my $buf; + for (;;) { + my $lenbuf; + my $n = $conn->sysread($lenbuf, 2); + last unless $n == 2; + my $len = unpack("n", $lenbuf); + $n = $conn->sysread($buf, $len); + last unless $n == $len; + print "TCP request\n"; + my $result = handleQuery($buf); + $len = length($result); + if ($len != 0) { + $conn->syswrite(pack("n", $len), 2); + $n = $conn->syswrite($result, $len); + } else { + $n = 0; + } + print " Sent: $n chars via TCP\n"; + } + $conn->close; + } +} diff --git a/bin/tests/system/resolver/ans8/ans.pl b/bin/tests/system/resolver/ans8/ans.pl new file mode 100644 index 0000000..a3d06b6 --- /dev/null +++ b/bin/tests/system/resolver/ans8/ans.pl @@ -0,0 +1,177 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use IO::File; +use IO::Socket; +use Data::Dumper; +use Net::DNS; +use Net::DNS::Packet; +use strict; + +# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early +local $SIG{PIPE} = 'IGNORE'; + +# Flush logged output after every line +local $| = 1; + +my $server_addr = "10.53.0.8"; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; +my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr", + LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!"; + +print "listening on $server_addr:$localport.\n"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!";; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +sub handleUDP { + my ($buf) = @_; + my $request; + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + my $qclass = $questions[0]->qclass; + my $id = $request->header->id; + + my $response = new Net::DNS::Packet($qname, $qtype, $qclass); + $response->header->qr(1); + $response->header->aa(1); + $response->header->tc(0); + $response->header->id($id); + + # Responses to queries for no-questions/NS and ns.no-questions/A are + # _not_ malformed or truncated. + if ($qname eq "no-questions" && $qtype eq "NS") { + $response->push("answer", new Net::DNS::RR($qname . " 300 NS ns.no-questions")); + $response->push("additional", new Net::DNS::RR("ns.no-questions. 300 A 10.53.0.8")); + return $response->data; + } elsif ($qname eq "ns.no-questions") { + $response->push("answer", new Net::DNS::RR($qname . " 300 A 10.53.0.8")) + if ($qtype eq "A"); + return $response->data; + } elsif ($qname =~ /\.formerr-to-all$/) { + $response->header->rcode("FORMERR"); + return $response->data; + } + + # don't use Net::DNS to construct the header only reply as early + # versions just get it completely wrong. + + if ($qname eq "truncated.no-questions") { + # QR, AA, TC: forces TCP retry + return (pack("nnnnnn", $id, 0x8600, 0, 0, 0, 0)); + } elsif ($qname eq "tcpalso.no-questions") { + # QR, REFUSED: forces TCP retry + return (pack("nnnnnn", $id, 0x8205, 0, 0, 0, 0)); + } + # QR, AA + return (pack("nnnnnn", $id, 0x8400, 0, 0, 0, 0)); +} + +sub handleTCP { + my ($buf) = @_; + my $request; + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + my $qclass = $questions[0]->qclass; + my $id = $request->header->id; + + my @results = (); + my $response = new Net::DNS::Packet($qname, $qtype, $qclass); + + $response->header->qr(1); + $response->header->aa(1); + $response->header->id($id); + $response->push("answer", new Net::DNS::RR("$qname 300 A 1.2.3.4")); + + if ($qname eq "tcpalso.no-questions") { + # for this qname we also return a bad reply over TCP + # QR, REFUSED, no question section + push (@results, pack("nnnnnn", $id, 0x8005, 0, 0, 0, 0)); + } else { + push(@results, $response->data); + } + + return \@results; +} + +# Main +my $rin; +my $rout; +for (;;) { + $rin = ''; + vec($rin, fileno($tcpsock), 1) = 1; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($udpsock), 1)) { + printf "UDP request\n"; + my $buf; + $udpsock->recv($buf, 512); + my $result = handleUDP($buf); + my $num_chars = $udpsock->send($result); + print " Sent $num_chars bytes via UDP\n"; + } elsif (vec($rout, fileno($tcpsock), 1)) { + my $conn = $tcpsock->accept; + my $buf; + for (;;) { + my $lenbuf; + my $n = $conn->sysread($lenbuf, 2); + last unless $n == 2; + my $len = unpack("n", $lenbuf); + $n = $conn->sysread($buf, $len); + last unless $n == $len; + print "TCP request\n"; + my $result = handleTCP($buf); + foreach my $response (@$result) { + $len = length($response); + $n = $conn->syswrite(pack("n", $len), 2); + $n = $conn->syswrite($response, $len); + print " Sent: $n chars via TCP\n"; + } + } + $conn->close; + } +} diff --git a/bin/tests/system/resolver/ns1/chaostest.db b/bin/tests/system/resolver/ns1/chaostest.db new file mode 100644 index 0000000..153f31d --- /dev/null +++ b/bin/tests/system/resolver/ns1/chaostest.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ CHAOS SOA @ @ 1970010100 86400 600 86400 300 +@ CHAOS NS @ +version CHAOS TXT "CH 1.0" +hostname CHAOS TXT "unknown" diff --git a/bin/tests/system/resolver/ns1/named.conf.in b/bin/tests/system/resolver/ns1/named.conf.in new file mode 100644 index 0000000..f6637c8 --- /dev/null +++ b/bin/tests/system/resolver/ns1/named.conf.in @@ -0,0 +1,90 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + deny-answer-addresses { 192.0.2.0/24; 2001:db8:beef::/48; } + except-from { "example.org"; }; + deny-answer-aliases { "example.org"; } + except-from { "goodcname.example.net"; + "gooddname.example.net"; }; + allow-query {!10.53.0.8; any; }; + max-zone-ttl unlimited; + resolver-query-timeout 5000; # 5 seconds + attach-cache "globalcache"; + max-recursion-queries 100; +}; + +trust-anchors { }; + +server 10.53.0.3 { + tcp-only yes; +}; + +server 10.42.23.3/32 { + notify-source 10.42.22.1; + query-source address 10.42.22.1 port 0; + transfer-source 10.42.22.1; +}; + +server fd92:7065:b8e:ffff::1000 { + notify-source-v6 fd92:7065:b8e:ffff::1001; + query-source-v6 address fd92:7065:b8e:ffff::1001 port 0; + transfer-source-v6 fd92:7065:b8e:ffff::1001; +}; + +/* + * Must be first view so that there is a CH cache with name + * "globalcache" before the recursive "default"/IN view is configured. + */ +view "class" chaos { + zone "chaostest" CHAOS { + type primary; + file "chaostest.db"; + }; +}; + +/* + * Must be second view so that so that we can check we don't attach to the + * "globalcache"/CH cache. + */ +view "default" { + zone "." { + type hint; + file "root.hint"; + }; +}; + +view "alternative" { + zone "." { + type hint; + file "root.hint"; + }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/resolver/ns1/root.hint b/bin/tests/system/resolver/ns1/root.hint new file mode 100644 index 0000000..993227d --- /dev/null +++ b/bin/tests/system/resolver/ns1/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.2 diff --git a/bin/tests/system/resolver/ns11/named.conf.in b/bin/tests/system/resolver/ns11/named.conf.in new file mode 100644 index 0000000..14ed048 --- /dev/null +++ b/bin/tests/system/resolver/ns11/named.conf.in @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.11; + notify-source 10.53.0.11; + transfer-source 10.53.0.11; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.11; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; diff --git a/bin/tests/system/resolver/ns4/broken.db b/bin/tests/system/resolver/ns4/broken.db new file mode 100644 index 0000000..eb64f85 --- /dev/null +++ b/bin/tests/system/resolver/ns4/broken.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.tld. +ns A 10.53.0.4 +$TTL 5 +sub.broken. NS ns.sub.broken. +ns.sub.broken. A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns4/child.server.db b/bin/tests/system/resolver/ns4/child.server.db new file mode 100644 index 0000000..188eb4a --- /dev/null +++ b/bin/tests/system/resolver/ns4/child.server.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns +ns A 10.53.0.4 +foo TXT "From NS 4" +bar TXT "From NS 4" diff --git a/bin/tests/system/resolver/ns4/moves.db b/bin/tests/system/resolver/ns4/moves.db new file mode 100644 index 0000000..dc1c396 --- /dev/null +++ b/bin/tests/system/resolver/ns4/moves.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.server. +foo TXT "From NS 4" +bar TXT "From NS 4" diff --git a/bin/tests/system/resolver/ns4/named.conf.in b/bin/tests/system/resolver/ns4/named.conf.in new file mode 100644 index 0000000..67cbee8 --- /dev/null +++ b/bin/tests/system/resolver/ns4/named.conf.in @@ -0,0 +1,70 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "moves" { + type primary; + file "moves.db"; +}; + +zone "child.server" { + type primary; + file "child.server.db"; +}; + +zone "tld" { + type primary; + file "tld.db"; +}; + +zone "broken" { + type primary; + file "broken.db"; +}; + +zone "sourcens" { + type primary; + file "sourcens.db"; +}; + +zone "v4only.net" { + type primary; + file "v4only.net.db"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/resolver/ns4/root.db b/bin/tests/system/resolver/ns4/root.db new file mode 100644 index 0000000..3c93edc --- /dev/null +++ b/bin/tests/system/resolver/ns4/root.db @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.4 +all-cnames NS cname.tld +example.net. NS ns.example.net. +ns.example.net. A 10.53.0.6 +no-questions. NS ns.no-questions. +ns.no-questions. A 10.53.0.8 +formerr-to-all. NS ns.formerr-to-all. +ns.formerr-to-all. A 10.53.0.8 +sourcens. NS ns.sourcens. +ns.sourcens. A 10.53.0.4 +targetns. NS ns.targetns. +ns.targetns. A 10.53.0.6 +partial-formerr. NS ns.partial-formerr. +ns.partial-formerr. A 10.53.0.2 +ns.partial-formerr. A 10.53.0.3 +options-formerr. NS ns.options-formerr. +ns.options-formerr. A 10.53.0.10 diff --git a/bin/tests/system/resolver/ns4/sourcens.db b/bin/tests/system/resolver/ns4/sourcens.db new file mode 100644 index 0000000..3567cfb --- /dev/null +++ b/bin/tests/system/resolver/ns4/sourcens.db @@ -0,0 +1,91 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This zone contains a set of delegations with varying numbers of NS +; records. This is used to check that BIND is limiting the number of +; NS records it follows when resolving a delegation. It tests all +; numbers of NS records up to twice the number followed. + +$TTL 60 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns +ns A 10.53.0.4 + +target1 NS ns.fake11.targetns. + +target2 NS ns.fake21.targetns. + NS ns.fake22.targetns. + +target3 NS ns.fake31.targetns. + NS ns.fake32.targetns. + NS ns.fake33.targetns. + +target4 NS ns.fake41.targetns. + NS ns.fake42.targetns. + NS ns.fake43.targetns. + NS ns.fake44.targetns. + +target5 NS ns.fake51.targetns. + NS ns.fake52.targetns. + NS ns.fake53.targetns. + NS ns.fake54.targetns. + NS ns.fake55.targetns. + +target6 NS ns.fake61.targetns. + NS ns.fake62.targetns. + NS ns.fake63.targetns. + NS ns.fake64.targetns. + NS ns.fake65.targetns. + NS ns.fake66.targetns. + +target7 NS ns.fake71.targetns. + NS ns.fake72.targetns. + NS ns.fake73.targetns. + NS ns.fake74.targetns. + NS ns.fake75.targetns. + NS ns.fake76.targetns. + NS ns.fake77.targetns. + +target8 NS ns.fake81.targetns. + NS ns.fake82.targetns. + NS ns.fake83.targetns. + NS ns.fake84.targetns. + NS ns.fake85.targetns. + NS ns.fake86.targetns. + NS ns.fake87.targetns. + NS ns.fake88.targetns. + +target9 NS ns.fake91.targetns. + NS ns.fake92.targetns. + NS ns.fake93.targetns. + NS ns.fake94.targetns. + NS ns.fake95.targetns. + NS ns.fake96.targetns. + NS ns.fake97.targetns. + NS ns.fake98.targetns. + NS ns.fake99.targetns. + +target10 NS ns.fake101.targetns. + NS ns.fake102.targetns. + NS ns.fake103.targetns. + NS ns.fake104.targetns. + NS ns.fake105.targetns. + NS ns.fake106.targetns. + NS ns.fake107.targetns. + NS ns.fake108.targetns. + NS ns.fake109.targetns. + NS ns.fake1010.targetns. diff --git a/bin/tests/system/resolver/ns4/tld1.db b/bin/tests/system/resolver/ns4/tld1.db new file mode 100644 index 0000000..03d7908 --- /dev/null +++ b/bin/tests/system/resolver/ns4/tld1.db @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.tld. +ns A 10.53.0.4 +$TTL 5 +to-be-removed NS ns.to-be-removed +ns.to-be-removed A 10.53.0.6 +fetch.tld. NS ns.fetch.tld. +ns.fetch.tld. A 10.53.0.6 +no-edns-version.tld. NS ns.no-edns-version.tld. +ns.no-edns-version.tld. A 10.53.0.6 +edns-version.tld. NS ns.edns-version.tld. +ns.edns-version.tld. A 10.53.0.7 +cname CNAME ns7 +ns7 A 10.53.0.7 +mixedttl 10 A 10.0.0.1 +mixedttl 15 TXT a TXT record +mixedttl 20 AAAA 2001:db8::1 diff --git a/bin/tests/system/resolver/ns4/tld2.db b/bin/tests/system/resolver/ns4/tld2.db new file mode 100644 index 0000000..c3a96d9 --- /dev/null +++ b/bin/tests/system/resolver/ns4/tld2.db @@ -0,0 +1,35 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.tld. +ns A 10.53.0.4 +fetch.tld. NS ns.fetch.tld. +ns.fetch.tld. A 10.53.0.6 +fetchall 10 A 1.2.3.4 +fetchall 10 AAAA ::1 +fetchall 10 TXT A short ttl +no-edns-version.tld. NS ns.no-edns-version.tld. +ns.no-edns-version.tld. A 10.53.0.6 +edns-version.tld. NS ns.edns-version.tld. +ns.edns-version.tld. A 10.53.0.7 +cname CNAME ns7 +ns7 A 10.53.0.7 +mixedttl 10 A 10.0.0.1 +mixedttl 15 TXT a TXT record +mixedttl 20 AAAA 2001:db8::1 diff --git a/bin/tests/system/resolver/ns4/v4only.net.db b/bin/tests/system/resolver/ns4/v4only.net.db new file mode 100644 index 0000000..b097f3a --- /dev/null +++ b/bin/tests/system/resolver/ns4/v4only.net.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS v4.nameserver. + A 10.0.0.1 +* CNAME @ diff --git a/bin/tests/system/resolver/ns5/child.server.db b/bin/tests/system/resolver/ns5/child.server.db new file mode 100644 index 0000000..2517b6c --- /dev/null +++ b/bin/tests/system/resolver/ns5/child.server.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns +ns A 10.53.0.5 +foo TXT "From NS 5" +bar TXT "From NS 5" diff --git a/bin/tests/system/resolver/ns5/moves.db b/bin/tests/system/resolver/ns5/moves.db new file mode 100644 index 0000000..57f4e91 --- /dev/null +++ b/bin/tests/system/resolver/ns5/moves.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.server. +foo TXT "From NS 5" +bar TXT "From NS 5" diff --git a/bin/tests/system/resolver/ns5/named.conf.in b/bin/tests/system/resolver/ns5/named.conf.in new file mode 100644 index 0000000..32c5fa7 --- /dev/null +++ b/bin/tests/system/resolver/ns5/named.conf.in @@ -0,0 +1,61 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + querylog yes; + prefetch 4 10; + responselog yes; +}; + +include "trusted.conf"; + +server 10.53.0.7 { + edns-version 0; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "moves" { + type primary; + file "moves.db"; +}; + +zone "child.server" { + type primary; + file "child.server.db"; +}; + +include "trusted.conf"; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/resolver/ns5/root.hint b/bin/tests/system/resolver/ns5/root.hint new file mode 100644 index 0000000..3685f54 --- /dev/null +++ b/bin/tests/system/resolver/ns5/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.4 diff --git a/bin/tests/system/resolver/ns6/broken.db b/bin/tests/system/resolver/ns6/broken.db new file mode 100644 index 0000000..85b36bf --- /dev/null +++ b/bin/tests/system/resolver/ns6/broken.db @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.6 +ns0 IN A 10.53.0.6 +ns1 IN A 10.53.0.6 +ns2 IN A 10.53.0.6 +ns3 IN A 10.53.0.6 +ns4 IN A 10.53.0.6 +ns5 IN A 10.53.0.6 +ns6 IN A 10.53.0.6 +ns7 IN A 10.53.0.6 +ns8 IN A 10.53.0.6 +ns9 IN A 10.53.0.6 +$TTL 1 +@ IN A 10.53.0.6 +www.sub IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/delegation-only.db b/bin/tests/system/resolver/ns6/delegation-only.db new file mode 100644 index 0000000..b144338 --- /dev/null +++ b/bin/tests/system/resolver/ns6/delegation-only.db @@ -0,0 +1,33 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ IN SOA ns marka.isc.org. 1 0 0 0 120 +@ IN NS ns +@ IN DNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF +; +; Delegation only test CDS and CDNSKEY records. These should be +; returned even if delegation-only is set for this zone. +; +@ IN A 1.2.3.4 +@ IN AAAA c::1.2.3.4 +@ IN CDS 12023 7 2 36FB69A752615831B47EA6EF9EA4619D0FB08ABDA69EA3ED200F4C02FF4921D4 +@ IN CDNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF +; +; Delegation only test CDS and CDNSKEY records. These should be rejected +; as they are not at the zone apex. +; +a IN A 1.2.3.4 +aaaa IN AAAA c::1.2.3.4 +cds IN CDS 21366 7 1 E6C1716CFB6BDC84E84CE1AB5510DAC69173B5B2 +cdnskey IN CDNSKEY 256 3 7 AwEAAY9437GPWJHzBeR4FP6eJAie7gh2QSM6LUnbDAHvHOx8MNqgSVRM PZka2rAgivb65/MkT1lXRUegj91iRFP3iggTpCgvdUbcBjsYrdODsrwF YUMIUl1pU0lH9x7KvfFUOfSmG+Rk5UHUWuRZbNyc65Sq69iFXg5c11+8 MAkRoeDF +; +ns IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/ds.example.net.db.in b/bin/tests/system/resolver/ns6/ds.example.net.db.in new file mode 100644 index 0000000..fad382b --- /dev/null +++ b/bin/tests/system/resolver/ns6/ds.example.net.db.in @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/example.net.db.in b/bin/tests/system/resolver/ns6/example.net.db.in new file mode 100644 index 0000000..4bef728 --- /dev/null +++ b/bin/tests/system/resolver/ns6/example.net.db.in @@ -0,0 +1,34 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +@ IN MX 0 mail +ns IN A 10.53.0.6 +mail IN A 10.53.0.6 +www IN HTTPS 0 http-server +http-server IN A 10.53.0.6 +https-loop IN HTTPS 0 https-next +https-loop IN A 10.53.0.6 +https-next IN HTTPS 0 https-loop +https-next IN A 10.53.0.7 +https-cname IN HTTPS 0 cname-server +cname-server IN CNAME cname-next +cname-next IN CNAME http-server +https-cname-loop IN HTTPS 0 https-cname-loop0 +https-cname-loop0 IN CNAME https-cname-loop0 +fetch 10 IN TXT A short ttl +non-zero 10 IN TXT A short ttl +zero 0 IN TXT A zero ttl +$TTL 13 +ds IN NS ns.ds +ns.ds IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/fetch.tld.db b/bin/tests/system/resolver/ns6/fetch.tld.db new file mode 100644 index 0000000..1d59e5a --- /dev/null +++ b/bin/tests/system/resolver/ns6/fetch.tld.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.fetch.tld. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.fetch.tld. +ns.fetch.tld. A 10.53.0.6 + +@ 13 TXT A short ttl diff --git a/bin/tests/system/resolver/ns6/keygen.sh b/bin/tests/system/resolver/ns6/keygen.sh new file mode 100644 index 0000000..19a34c7 --- /dev/null +++ b/bin/tests/system/resolver/ns6/keygen.sh @@ -0,0 +1,38 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +# +# We use rsasha256 here to get a ZSK + KSK that don't fit in 512 bytes. +# +zone=ds.example.net +zonefile="${zone}.db" +infile="${zonefile}.in" +cp $infile $zonefile +ksk=$($KEYGEN -q -a rsasha256 -fk $zone) +zsk=$($KEYGEN -q -a rsasha256 -b 2048 $zone) +cat $ksk.key $zsk.key >>$zonefile +$SIGNER -P -o $zone $zonefile >/dev/null + +zone=example.net +zonefile="${zone}.db" +infile="${zonefile}.in" +cp $infile $zonefile +ksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $zone) +zsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $zone) +cat $ksk.key $zsk.key dsset-ds.example.net. >>$zonefile +$SIGNER -P -o $zone $zonefile >/dev/null + +# Configure a static key to be used by delv +keyfile_to_static_ds $ksk >../ns5/trusted.conf diff --git a/bin/tests/system/resolver/ns6/moves.db b/bin/tests/system/resolver/ns6/moves.db new file mode 100644 index 0000000..06634ee --- /dev/null +++ b/bin/tests/system/resolver/ns6/moves.db @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.server. +foo TXT "From NS 6" +bar TXT "From NS 6" diff --git a/bin/tests/system/resolver/ns6/named.conf.in b/bin/tests/system/resolver/ns6/named.conf.in new file mode 100644 index 0000000..34552af --- /dev/null +++ b/bin/tests/system/resolver/ns6/named.conf.in @@ -0,0 +1,93 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS6 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { fd92:7065:b8e:ffff::6; }; + recursion no; + dnssec-validation no; + querylog yes; + statistics-file "named.stats"; + max-udp-size 4096; + responselog no; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example.net" { + type primary; + file "example.net.db.signed"; + allow-update { any; }; +}; + +zone "ds.example.net" { + type primary; + file "ds.example.net.db.signed"; + allow-update { any; }; +}; + +zone "to-be-removed.tld" { + type primary; + file "to-be-removed.tld.db"; + allow-update { any; }; +}; + +zone "broken" { + type primary; + file "broken.db"; + allow-update { any; }; +}; + +zone "redirect.com" { + type primary; + file "redirect.com.db"; +}; + +zone "tld1" { + type primary; + file "tld1.db"; +}; + +zone "no-edns-version.tld" { + type primary; + file "no-edns-version.tld.db"; +}; + +zone "fetch.tld" { + type primary; + file "fetch.tld.db"; +}; + +zone "targetns" { + type primary; + file "targetns.db"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/resolver/ns6/no-edns-version.tld.db b/bin/tests/system/resolver/ns6/no-edns-version.tld.db new file mode 100644 index 0000000..9ab654d --- /dev/null +++ b/bin/tests/system/resolver/ns6/no-edns-version.tld.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA . . 0 0 0 0 0 +@ NS ns +ns A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/redirect.com.db b/bin/tests/system/resolver/ns6/redirect.com.db new file mode 100644 index 0000000..f79f6dd --- /dev/null +++ b/bin/tests/system/resolver/ns6/redirect.com.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.6 + +; 10.53.1.* are non-responsive IP addresses +$GENERATE 1-100 ns$.fake IN A 10.53.1.$ +$GENERATE 101-200 ns$.fake IN A 10.53.1.${-100} +$GENERATE 201-300 ns$.fake IN A 10.53.1.${-200} +$GENERATE 301-400 ns$.fake IN A 10.53.1.${-300} +$GENERATE 401-500 ns$.fake IN A 10.53.1.${-400} +$GENERATE 501-600 ns$.fake IN A 10.53.1.${-500} +$GENERATE 601-700 ns$.fake IN A 10.53.1.${-600} +$GENERATE 701-800 ns$.fake IN A 10.53.1.${-700} +$GENERATE 801-900 ns$.fake IN A 10.53.1.${-800} +$GENERATE 901-1000 ns$.fake IN A 10.53.1.${-900} diff --git a/bin/tests/system/resolver/ns6/root.db b/bin/tests/system/resolver/ns6/root.db new file mode 100644 index 0000000..35962fe --- /dev/null +++ b/bin/tests/system/resolver/ns6/root.db @@ -0,0 +1,44 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.6 +a.root-servers.nil. AAAA fd92:7065:b8e:ffff::6 +moves. NS ns.server. +server. NS ns7.server. +ns7.server. A 10.53.0.7 +; +; These two delegations are strictly not necessary as the test resolver (ns5) +; doesn't have this zone as its root. They are just done for consistency with +; the delegations in ns4/tld. +; +no-edns-version.tld. NS ns.no-edns-version.tld. +ns.no-edns-version.tld. A 10.53.0.6 +edns-version.tld. NS ns.edns-version.tld. +ns.edns-version.tld. A 10.53.0.7 +v4only.net. NS v4.nameserver. +v4.nameserver. A 10.53.0.4 +; +; Servers for regression test for GL #6412 +; They return broken NODATA responses (incorrect SOA) for the test zone. +; +gl6412. NS ns2.gl6412. +gl6412. NS ns3.gl6412. +ns2.gl6412. A 10.53.0.2 +ns3.gl6412. A 10.53.0.3 diff --git a/bin/tests/system/resolver/ns6/targetns.db b/bin/tests/system/resolver/ns6/targetns.db new file mode 100644 index 0000000..4d9496b --- /dev/null +++ b/bin/tests/system/resolver/ns6/targetns.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; In the test for checking how many NS records BIND will follow, this +; zone marks the server as the one to which the NS lookups will be +; directed. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) + NS ns +ns A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns6/tld1.db b/bin/tests/system/resolver/ns6/tld1.db new file mode 100644 index 0000000..412509b --- /dev/null +++ b/bin/tests/system/resolver/ns6/tld1.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.6 + +$GENERATE 1-21 sub IN NS sub-ns$.tld2. diff --git a/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in b/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in new file mode 100644 index 0000000..5638090 --- /dev/null +++ b/bin/tests/system/resolver/ns6/to-be-removed.tld.db.in @@ -0,0 +1,28 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.6 +ns0 IN A 10.53.0.6 +ns1 IN A 10.53.0.6 +ns2 IN A 10.53.0.6 +ns3 IN A 10.53.0.6 +ns4 IN A 10.53.0.6 +ns5 IN A 10.53.0.6 +ns6 IN A 10.53.0.6 +ns7 IN A 10.53.0.6 +ns8 IN A 10.53.0.6 +ns9 IN A 10.53.0.6 +$TTL 1 +@ IN A 10.53.0.6 +www IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns7/all-cnames.db b/bin/tests/system/resolver/ns7/all-cnames.db new file mode 100644 index 0000000..85003ee --- /dev/null +++ b/bin/tests/system/resolver/ns7/all-cnames.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. ns.server. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS cname.tld. diff --git a/bin/tests/system/resolver/ns7/edns-version.tld.db b/bin/tests/system/resolver/ns7/edns-version.tld.db new file mode 100644 index 0000000..bcfae40 --- /dev/null +++ b/bin/tests/system/resolver/ns7/edns-version.tld.db @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ SOA . . 0 0 0 0 0 +@ NS ns +ns A 10.53.0.7 diff --git a/bin/tests/system/resolver/ns7/named1.conf.in b/bin/tests/system/resolver/ns7/named1.conf.in new file mode 100644 index 0000000..170ce62 --- /dev/null +++ b/bin/tests/system/resolver/ns7/named1.conf.in @@ -0,0 +1,77 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS7 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { fd92:7065:b8e:ffff::7; }; + recursion yes; + dnssec-validation yes; + empty-zones-enable yes; + disable-empty-zone 20.172.in-addr.arpa; + /* + * check prefetch disabled + * check zero ttl not returned + */ + prefetch 0; + querylog yes; + edns-udp-size 4096; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "server" { + type primary; + file "server.db"; + allow-update { any; }; +}; + +zone "edns-version.tld" { + type primary; + file "edns-version.tld.db"; +}; + +zone "all-cnames" { + type primary; + file "all-cnames.db"; +}; + +zone "tld2" { + type primary; + file "tld2.db"; +}; + +zone "sub.tld1" { + type primary; + file "sub.tld1.db"; +}; diff --git a/bin/tests/system/resolver/ns7/named2.conf.in b/bin/tests/system/resolver/ns7/named2.conf.in new file mode 100644 index 0000000..170ce62 --- /dev/null +++ b/bin/tests/system/resolver/ns7/named2.conf.in @@ -0,0 +1,77 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS7 + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { fd92:7065:b8e:ffff::7; }; + recursion yes; + dnssec-validation yes; + empty-zones-enable yes; + disable-empty-zone 20.172.in-addr.arpa; + /* + * check prefetch disabled + * check zero ttl not returned + */ + prefetch 0; + querylog yes; + edns-udp-size 4096; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; + +zone "server" { + type primary; + file "server.db"; + allow-update { any; }; +}; + +zone "edns-version.tld" { + type primary; + file "edns-version.tld.db"; +}; + +zone "all-cnames" { + type primary; + file "all-cnames.db"; +}; + +zone "tld2" { + type primary; + file "tld2.db"; +}; + +zone "sub.tld1" { + type primary; + file "sub.tld1.db"; +}; diff --git a/bin/tests/system/resolver/ns7/root.hint b/bin/tests/system/resolver/ns7/root.hint new file mode 100644 index 0000000..3337bd5 --- /dev/null +++ b/bin/tests/system/resolver/ns7/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.6 diff --git a/bin/tests/system/resolver/ns7/server.db.in b/bin/tests/system/resolver/ns7/server.db.in new file mode 100644 index 0000000..7d5169a --- /dev/null +++ b/bin/tests/system/resolver/ns7/server.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA marka.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns7 +ns7 A 10.53.0.7 +ns A 10.53.0.5 +child NS ns.child +ns.child A 10.53.0.5 diff --git a/bin/tests/system/resolver/ns7/sub.tld1.db b/bin/tests/system/resolver/ns7/sub.tld1.db new file mode 100644 index 0000000..b2d46c6 --- /dev/null +++ b/bin/tests/system/resolver/ns7/sub.tld1.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 + +$GENERATE 1-21 @ IN NS sub-ns$.tld2. + +$GENERATE 1-21 bar IN NS bar-sub-ns$.tld2. diff --git a/bin/tests/system/resolver/ns7/tld2.db b/bin/tests/system/resolver/ns7/tld2.db new file mode 100644 index 0000000..1f31b51 --- /dev/null +++ b/bin/tests/system/resolver/ns7/tld2.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 600 +@ IN SOA ns hostmaster 1 1800 900 604800 600 +@ IN NS ns +ns IN A 10.53.0.7 + +$GENERATE 1-21 sub-ns$ IN A 10.53.0.7 +$GENERATE 1-21 bar-sub-ns$ IN A 10.53.0.3 diff --git a/bin/tests/system/resolver/ns9/named.args b/bin/tests/system/resolver/ns9/named.args new file mode 100644 index 0000000..45022e2 --- /dev/null +++ b/bin/tests/system/resolver/ns9/named.args @@ -0,0 +1,2 @@ +# this server is IPv6 only +-6 -m record -c named.conf -d 99 -D resolver-ns9 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/resolver/ns9/named.conf.in b/bin/tests/system/resolver/ns9/named.conf.in new file mode 100644 index 0000000..bfc979c --- /dev/null +++ b/bin/tests/system/resolver/ns9/named.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS9 + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { none; }; + listen-on-v6 { fd92:7065:b8e:ffff::9; }; + recursion yes; + recursive-clients 0; // regression test for [GL #4987] + dnssec-validation yes; + dual-stack-servers { fd92:7065:b8e:ffff::7; }; + qname-minimization off; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet fd92:7065:b8e:ffff::9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "root.hint"; +}; diff --git a/bin/tests/system/resolver/ns9/named.ipv6-only b/bin/tests/system/resolver/ns9/named.ipv6-only new file mode 100644 index 0000000..e69de29 diff --git a/bin/tests/system/resolver/ns9/root.hint b/bin/tests/system/resolver/ns9/root.hint new file mode 100644 index 0000000..f74fbf1 --- /dev/null +++ b/bin/tests/system/resolver/ns9/root.hint @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS a.root-servers.nil. +a.root-servers.nil. IN A 10.53.0.6 +a.root-servers.nil. IN AAAA fd92:7065:b8e:ffff::6; diff --git a/bin/tests/system/resolver/prereq.sh b/bin/tests/system/resolver/prereq.sh new file mode 100644 index 0000000..c52be9c --- /dev/null +++ b/bin/tests/system/resolver/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/resolver/setup.sh b/bin/tests/system/resolver/setup.sh new file mode 100644 index 0000000..ae64e5f --- /dev/null +++ b/bin/tests/system/resolver/setup.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=../conf.sh +. ../conf.sh + +cp ns4/tld1.db ns4/tld.db +cp ns6/to-be-removed.tld.db.in ns6/to-be-removed.tld.db +cp ns7/server.db.in ns7/server.db + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named1.conf.in ns7/named.conf +copy_setports ns9/named.conf.in ns9/named.conf +copy_setports ns11/named.conf.in ns11/named.conf + +(cd ns6 && $SHELL keygen.sh) diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh new file mode 100755 index 0000000..83dedae --- /dev/null +++ b/bin/tests/system/resolver/tests.sh @@ -0,0 +1,1046 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=../conf.sh +. ../conf.sh + +dig_with_opts() { + "${DIG}" -p "${PORT}" "${@}" +} + +rndccmd() { + "${RNDC}" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${@}" +} + +status=0 +n=0 + +n=$((n + 1)) +echo_i "checking non-cachable NXDOMAIN response handling ($n)" +ret=0 +dig_with_opts +tcp nxdomain.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking non-cachable NODATA response handling ($n)" +ret=0 +dig_with_opts +tcp nodata.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +rndccmd 10.53.0.1 stats || ret=1 # Get the responses, RTT and timeout statistics before the following timeout tests +grep -F 'responses received' ns1/named.stats >ns1/named.stats.responses-before || true +grep -F 'queries with RTT' ns1/named.stats >ns1/named.stats.rtt-before || true +mv ns1/named.stats ns1/named.stats-before + +# 'resolver-query-timeout' is set to 5 seconds in ns1, so dig with a lower +# timeout value should give up earlier than that. +n=$((n + 1)) +echo_i "checking no response handling with a shorter than resolver-query-timeout timeout ($n)" +ret=0 +dig_with_opts +tcp +tries=1 +timeout=3 noresponse.example.net @10.53.0.1 a >dig.out.ns1.test${n} && ret=1 +grep -F "no servers could be reached" dig.out.ns1.test${n} >/dev/null || ret=1 +grep -F "EDE: 22 (No Reachable Authority)" dig.out.ns1.test${n} >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# 'resolver-query-timeout' is set to 5 seconds in ns1, which is lower than the +# current single query timeout value MAX_SINGLE_QUERY_TIMEOUT of 9 seconds, so +# the "hung fetch" timer should kick in, interrupt the non-responsive query and +# send a SERVFAIL answer. +n=$((n + 1)) +echo_i "checking no response handling with a longer than resolver-query-timeout timeout ($n)" +ret=0 +dig_with_opts +tcp +tries=1 +timeout=7 noresponse.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep -F "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +grep -F "EDE: 22 (No Reachable Authority)" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that the timeout didn't skew the resolver responses counters ($n)" +ret=0 +rndccmd 10.53.0.1 stats || ret=1 +grep -F 'responses received' ns1/named.stats >ns1/named.stats.responses-after || true +grep -F 'queries with RTT' ns1/named.stats >ns1/named.stats.rtt-after || true +mv ns1/named.stats ns1/named.stats-after +diff ns1/named.stats.responses-before ns1/named.stats.responses-after >/dev/null || ret=1 +diff ns1/named.stats.rtt-before ns1/named.stats.rtt-after >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# 'resolver-query-timeout' is set to 5 seconds in ns1, so named should +# interrupt the non-responsive query and send a SERVFAIL answer before dig's +# own timeout fires, which is set to 7 seconds. This time, exampleudp.net is +# contacted using UDP transport by the resolver. +n=$((n + 1)) +echo_i "checking no response handling with a longer than resolver-query-timeout timeout (UDP recursion) ($n)" +ret=0 +dig_with_opts +tcp +tries=1 +timeout=7 noresponse.exampleudp.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep -F "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +grep -F "EDE: 22 (No Reachable Authority)" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking handling of bogus referrals ($n)" +# If the server has the "INSIST(!external)" bug, this query will kill it. +dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { + echo_i "failed" + status=$((status + 1)) +} + +n=$((n + 1)) +echo_i "check handling of cname + other data / 1 ($n)" +dig_with_opts +tcp cname1.example.com. a @10.53.0.1 >/dev/null || { + echo_i "failed" + status=$((status + 1)) +} + +n=$((n + 1)) +echo_i "check handling of cname + other data / 2 ($n)" +dig_with_opts +tcp cname2.example.com. a @10.53.0.1 >/dev/null || { + echo_i "failed" + status=$((status + 1)) +} + +n=$((n + 1)) +echo_i "check that server is still running ($n)" +dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { + echo_i "failed" + status=$((status + 1)) +} + +n=$((n + 1)) +echo_i "checking answer IPv4 address filtering (deny) ($n)" +ret=0 +dig_with_opts +tcp www.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking answer IPv6 address filtering (deny) ($n)" +ret=0 +dig_with_opts +tcp www.example.net @10.53.0.1 aaaa >dig.out.ns1.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking answer IPv4 address filtering (accept) ($n)" +ret=0 +dig_with_opts +tcp www.example.org @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking answer IPv6 address filtering (accept) ($n)" +ret=0 +dig_with_opts +tcp www.example.org @10.53.0.1 aaaa >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME target filtering (deny) ($n)" +ret=0 +dig_with_opts +tcp badcname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking CNAME target filtering (accept) ($n)" +ret=0 +dig_with_opts +tcp goodcname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking long CNAME chain target filtering (deny) ($n)" +ret=0 +dig_with_opts +tcp longcname1.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep -F "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +grep -F "max. restarts reached" dig.out.ns1.test${n} >/dev/null || ret=1 +lines=$(grep -F "CNAME" dig.out.ns1.test${n} | wc -l) +test ${lines:-1} -eq 12 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME target filtering (deny) ($n)" +ret=0 +dig_with_opts +tcp foo.baddname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "DNAME target foo.baddname.example.org denied for foo.baddname.example.net/IN" ns1/named.run >/dev/null || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME target filtering (accept) ($n)" +ret=0 +dig_with_opts +tcp foo.gooddname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking DNAME target filtering (accept due to subdomain) ($n)" +ret=0 +dig_with_opts +tcp www.dname.sub.example.org @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the resolver accepts a referral response with a non-empty ANSWER section ($n)" +ret=0 +dig_with_opts @10.53.0.1 foo.glue-in-answer.example.org. A >dig.ns1.out.${n} || ret=1 +grep "status: NOERROR" dig.ns1.out.${n} >/dev/null || ret=1 +grep "foo.glue-in-answer.example.org.*192.0.2.1" dig.ns1.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the resolver limits the number of NS records it follows in a referral response ($n)" +# ns5 is the recusor being tested. ns4 holds the sourcens zone containing +# names with varying numbers of NS records pointing to non-existent +# nameservers in the targetns zone on ns6. +ret=0 +rndccmd 10.53.0.5 flush || ret=1 # Ensure cache is empty before doing this test +count_fetches() { + actual=$(nextpartpeek ns5/named.run | grep -c " fetch: ns.fake${nscount}") + [ "${actual:-0}" -eq "${expected}" ] || return 1 + return 0 +} +for nscount in 1 2 3 4 5 6 7 8 9 10; do + # Verify number of NS records at source server + dig_with_opts +norecurse @10.53.0.4 target${nscount}.sourcens ns >dig.ns4.out.${nscount}.${n} + sourcerecs=$(grep NS dig.ns4.out.${nscount}.${n} | grep -cv ';') + test "${sourcerecs}" -eq "${nscount}" || ret=1 + test "${sourcerecs}" -eq "${nscount}" || echo_i "NS count incorrect for target${nscount}.sourcens" + + # Expected queries = 2 * number of NS records, up to a maximum of 10. + expected=$((nscount * 2)) + if [ "$expected" -gt 10 ]; then expected=10; fi + # Count the number of logged fetches + nextpart ns5/named.run >/dev/null + dig_with_opts @10.53.0.5 target${nscount}.sourcens A >dig.ns5.out.${nscount}.${n} || ret=1 + retry_quiet 5 count_fetches ns5/named.run $nscount $expected || { + echo_i "query count error: $nscount NS records: expected queries $expected, actual $actual" + ret=1 + } +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +stop_server ns4 +touch ns4/named.noaa +start_server --noclean --restart --port ${PORT} ns4 || ret=1 + +n=$((n + 1)) +echo_i "RT21594 regression test check setup ($n)" +ret=0 +# Check that "aa" is not being set by the authoritative server. +dig_with_opts +tcp . @10.53.0.4 soa >dig.ns4.out.${n} || ret=1 +grep 'flags: qr rd;' dig.ns4.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "RT21594 regression test positive answers ($n)" +ret=0 +# Check that resolver accepts the non-authoritative positive answers. +dig_with_opts +tcp . @10.53.0.5 soa >dig.ns5.out.${n} || ret=1 +grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "RT21594 regression test NODATA answers ($n)" +ret=0 +# Check that resolver accepts the non-authoritative nodata answers. +dig_with_opts +tcp . @10.53.0.5 txt >dig.ns5.out.${n} || ret=1 +grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "RT21594 regression test NXDOMAIN answers ($n)" +ret=0 +# Check that resolver accepts the non-authoritative positive answers. +dig_with_opts +tcp noexistent @10.53.0.5 txt >dig.ns5.out.${n} || ret=1 +grep "status: NXDOMAIN" dig.ns5.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +stop_server ns4 +rm ns4/named.noaa +start_server --noclean --restart --port ${PORT} ns4 || ret=1 + +n=$((n + 1)) +echo_i "check that replacement of additional data by a negative cache no data entry clears the additional RRSIGs ($n)" +ret=0 +dig_with_opts +tcp mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=1 +grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=1 +if [ $ret = 1 ]; then echo_i "mx priming failed"; fi +$NSUPDATE <dig.ns7.out.${n} || ret=2 +grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=2 +grep "ANSWER: 0" dig.ns7.out.${n} >/dev/null || ret=2 +if [ $ret = 2 ]; then echo_i "ncache priming failed"; fi +dig_with_opts +tcp mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=3 +grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=3 +dig_with_opts +tcp rrsig mail.example.net +norec @10.53.0.7 >dig.ns7.out.${n} || ret=4 +grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=4 +grep "ANSWER: 0" dig.ns7.out.${n} >/dev/null || ret=4 +if [ $ret != 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +if [ $ret != 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that update a nameservers address has immediate effects ($n)" +ret=0 +dig_with_opts +tcp TXT foo.moves @10.53.0.7 >dig.ns7.foo.${n} || ret=1 +grep "From NS 5" dig.ns7.foo.${n} >/dev/null || ret=1 +$NSUPDATE <dig.ns7.bar.${n} || ret=1 +grep "From NS 4" dig.ns7.bar.${n} >/dev/null || ret=1 + +if [ $ret != 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "checking that update a nameservers glue has immediate effects ($n)" +ret=0 +dig_with_opts +tcp TXT foo.child.server @10.53.0.7 >dig.ns7.foo.${n} || ret=1 +grep "From NS 5" dig.ns7.foo.${n} >/dev/null || ret=1 +$NSUPDATE <dig.ns7.bar.${n} || ret=1 +grep "From NS 4" dig.ns7.bar.${n} >/dev/null || ret=1 + +if [ $ret != 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "checking empty RFC 1918 reverse zones ($n)" +ret=0 +# Check that "aa" is being set by the resolver for RFC 1918 zones +# except the one that has been deliberately disabled +dig_with_opts @10.53.0.7 -x 10.1.1.1 >dig.ns4.out.1.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.1.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 192.168.1.1 >dig.ns4.out.2.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.2.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.16.1.1 >dig.ns4.out.3.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.3.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.17.1.1 >dig.ns4.out.4.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.4.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.18.1.1 >dig.ns4.out.5.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.5.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.19.1.1 >dig.ns4.out.6.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.6.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.21.1.1 >dig.ns4.out.7.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.7.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.22.1.1 >dig.ns4.out.8.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.8.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.23.1.1 >dig.ns4.out.9.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.9.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.24.1.1 >dig.ns4.out.11.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.11.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.25.1.1 >dig.ns4.out.12.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.12.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.26.1.1 >dig.ns4.out.13.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.13.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.27.1.1 >dig.ns4.out.14.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.14.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.28.1.1 >dig.ns4.out.15.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.15.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.29.1.1 >dig.ns4.out.16.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.16.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.30.1.1 >dig.ns4.out.17.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.17.${n} >/dev/null || ret=1 +dig_with_opts @10.53.0.7 -x 172.31.1.1 >dig.ns4.out.18.${n} || ret=1 +grep 'flags: qr aa rd ra;' dig.ns4.out.18.${n} >/dev/null || ret=1 +# but this one should NOT be authoritative +dig_with_opts @10.53.0.7 -x 172.20.1.1 >dig.ns4.out.19.${n} || ret=1 +grep 'flags: qr rd ra;' dig.ns4.out.19.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + status=1 +fi + +n=$((n + 1)) +echo_i "checking that removal of a delegation is honoured ($n)" +ret=0 +dig_with_opts @10.53.0.5 www.to-be-removed.tld A >dig.ns5.prime.${n} +grep "status: NOERROR" dig.ns5.prime.${n} >/dev/null || { + ret=1 + echo_i "priming failed" +} +cp ns4/tld2.db ns4/tld.db +rndc_reload ns4 10.53.0.4 tld +old= +for i in 0 1 2 3 4 5 6 7 8 9; do + foo=0 + dig_with_opts @10.53.0.5 ns$i.to-be-removed.tld A >/dev/null + dig_with_opts @10.53.0.5 www.to-be-removed.tld A >dig.ns5.out.${n} + grep "status: NXDOMAIN" dig.ns5.out.${n} >/dev/null || foo=1 + [ $foo = 0 ] && break + $NSUPDATE <dig.out.ns1.test${n} || ret=1 +grep "not subdomain of zone" ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +copy_setports ns7/named2.conf.in ns7/named.conf +rndccmd 10.53.0.7 reconfig 2>&1 | sed 's/^/ns7 /' | cat_i + +n=$((n + 1)) +echo_i "check resolution on the listening port ($n)" +ret=0 +dig_with_opts +tcp +tries=2 +time=5 mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=2 +grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=1 +grep "ANSWER: 1" dig.ns7.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + ret=1 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check prefetch (${n})" +ret=0 +# read prefetch value from config. +PREFETCH=$(sed -n "s/[[:space:]]*prefetch \([0-9]\).*/\1/p" ns5/named.conf) +dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.1.${n} || ret=1 +ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n}) +interval=$((ttl1 - PREFETCH + 1)) +# sleep so we are in prefetch range +sleep ${interval:-0} +# trigger prefetch +dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.2.${n} || ret=1 +ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) +sleep 1 +# check that prefetch occurred +dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.3.${n} || ret=1 +ttl=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.3.${n}) +test "${ttl:-0}" -gt "${ttl2:-1}" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check prefetch of validated DS's RRSIG TTL is updated (${n})" +ret=0 +dig_with_opts +dnssec @10.53.0.5 ds.example.net ds >dig.out.1.${n} || ret=1 +dsttl1=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.1.${n}) +interval=$((dsttl1 - PREFETCH + 1)) +# sleep so we are in prefetch range +sleep ${interval:-0} +# trigger prefetch +dig_with_opts @10.53.0.5 ds.example.net ds >dig.out.2.${n} || ret=1 +dsttl2=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.2.${n}) +sleep 1 +# check that prefetch occurred +dig_with_opts @10.53.0.5 ds.example.net ds +dnssec >dig.out.3.${n} || ret=1 +dsttl=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.3.${n}) +sigttl=$(awk '$4 == "RRSIG" && $5 == "DS" { print $2 }' dig.out.3.${n}) +test "${dsttl:-0}" -gt "${dsttl2:-1}" || ret=1 +test "${sigttl:-0}" -gt "${dsttl2:-1}" || ret=1 +test "${dsttl:-0}" -eq "${sigttl:-1}" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check prefetch disabled (${n})" +ret=0 +dig_with_opts @10.53.0.7 fetch.example.net txt >dig.out.1.${n} || ret=1 +ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n}) +interval=$((ttl1 - PREFETCH + 1)) +# sleep so we are in expire range +sleep ${interval:-0} +tmp_ttl=$ttl1 +no_prefetch() { + # fetch record and ensure its ttl is in range 0 < ttl < tmp_ttl. + # since prefetch is disabled, updated ttl must be a lower value than + # the previous one. + dig_with_opts @10.53.0.7 fetch.example.net txt >dig.out.2.${n} || return 1 + ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) + # check that prefetch has not occurred + if [ "$ttl2" -ge "${tmp_ttl}" ]; then + return 1 + fi + tmp_ttl=$ttl2 +} +retry_quiet 3 no_prefetch || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check prefetch qtype * (${n})" +ret=0 +dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.1.${n} || ret=1 +ttl1=$(awk '/^fetchall.tld/ { print $2 - 3; exit }' dig.out.1.${n}) +# sleep so we are in prefetch range +sleep "${ttl1:-0}" +# trigger prefetch +dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.2.${n} || ret=1 +ttl2=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.2.${n}) +sleep 1 +# check that prefetch occurred; +# note that only the first record is prefetched, +# because of the order of the records in the cache +dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.3.${n} || ret=1 +ttl3=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.3.${n}) +test "${ttl3:-0}" -gt "${ttl2:-1}" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that E was logged on EDNS queries in the query log (${n})" +ret=0 +dig_with_opts @10.53.0.5 +edns edns.fetchall.tld any >dig.out.2.${n} || ret=1 +grep "query: edns.fetchall.tld IN ANY +E" ns5/named.run >/dev/null || ret=1 +dig_with_opts @10.53.0.5 +noedns noedns.fetchall.tld any >dig.out.2.${n} || ret=1 +grep "query: noedns.fetchall.tld IN ANY" ns5/named.run >/dev/null || ret=1 +grep "query: noedns.fetchall.tld IN ANY +E" ns5/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that '-t aaaa' in .digrc does not have unexpected side effects ($n)" +ret=0 +echo "-t aaaa" >.digrc +( + HOME="$(pwd)" + export HOME + dig_with_opts @10.53.0.4 . >dig.out.1.${n} +) || ret=1 +( + HOME="$(pwd)" + export HOME + dig_with_opts @10.53.0.4 . A >dig.out.2.${n} +) || ret=1 +( + HOME="$(pwd)" + export HOME + dig_with_opts @10.53.0.4 -x 127.0.0.1 >dig.out.3.${n} +) || ret=1 +grep ';\..*IN.*AAAA$' dig.out.1.${n} >/dev/null || ret=1 +grep ';\..*IN.*A$' dig.out.2.${n} >/dev/null || ret=1 +grep 'extra type option' dig.out.2.${n} >/dev/null && ret=1 +grep ';1\.0\.0\.127\.in-addr\.arpa\..*IN.*PTR$' dig.out.3.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +edns=$($FEATURETEST --edns-version) + +n=$((n + 1)) +echo_i "check that EDNS version is logged (${n})" +ret=0 +dig_with_opts @10.53.0.5 +edns edns0.fetchall.tld any >dig.out.2.${n} || ret=1 +grep "query: edns0.fetchall.tld IN ANY +E(0)" ns5/named.run >/dev/null || ret=1 +if test "${edns:-0}" != 0; then + dig_with_opts @10.53.0.5 +edns=1 edns1.fetchall.tld any >dig.out.2.${n} || ret=1 + grep "query: edns1.fetchall.tld IN ANY +E(1)" ns5/named.run >/dev/null || ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if test "${edns:-0}" != 0; then + n=$((n + 1)) + echo_i "check that edns-version is honoured (${n})" + ret=0 + dig_with_opts @10.53.0.5 +edns no-edns-version.tld >dig.out.1.${n} || ret=1 + grep "query: no-edns-version.tld IN A -E(1)" ns6/named.run >/dev/null || ret=1 + dig_with_opts @10.53.0.5 +edns edns-version.tld >dig.out.2.${n} || ret=1 + grep "query: edns-version.tld IN A -E(0)" ns7/named.run >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "check that CNAME nameserver is logged correctly (${n})" +ret=0 +dig_with_opts soa all-cnames @10.53.0.5 >dig.out.ns5.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns5.test${n} >/dev/null || ret=1 +grep "skipping nameserver 'cname.tld' because it is a CNAME, while resolving 'all-cnames/SOA'" ns5/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that unexpected opcodes are handled correctly (${n})" +ret=0 +dig_with_opts soa all-cnames @10.53.0.5 +opcode=15 +cd +rec +ad +zflag >dig.out.ns5.test${n} || ret=1 +grep "status: NOTIMP" dig.out.ns5.test${n} >/dev/null || ret=1 +grep "flags:[^;]* qr[; ]" dig.out.ns5.test${n} >/dev/null || ret=1 +grep "flags:[^;]* ra[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 +grep "flags:[^;]* rd[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 +grep "flags:[^;]* cd[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 +grep "flags:[^;]* ad[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 +grep "flags:[^;]*; MBZ: " dig.out.ns5.test${n} >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that EDNS client subnet with non-zeroed bits is handled correctly (${n})" +ret=0 +# 0001 (IPv4) 1f (31 significant bits) 00 (0) ffffffff (255.255.255.255) +dig_with_opts soa . @10.53.0.5 +ednsopt=8:00011f00ffffffff >dig.out.ns5.test${n} || ret=1 +grep "status: FORMERR" dig.out.ns5.test${n} >/dev/null || ret=1 +grep "; EDNS: version:" dig.out.ns5.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that dig +subnet zeros address bits correctly (${n})" +ret=0 +dig_with_opts soa . @10.53.0.5 +subnet=255.255.255.255/23 >dig.out.ns5.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 +grep "CLIENT-SUBNET: 255.255.254.0/23/0" dig.out.ns5.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check zero ttl not returned for learnt non zero ttl records (${n})" +ret=0 +# use prefetch disabled server +dig_with_opts @10.53.0.7 non-zero.example.net txt >dig.out.1.${n} || ret=1 +ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}) +# sleep so we are in expire range +sleep "${ttl1:-0}" +# look for ttl = 1, allow for one miss at getting zero ttl +zerotonine="0 1 2 3 4 5 6 7 8 9" +zerotonine="$zerotonine $zerotonine $zerotonine" +for i in $zerotonine $zerotonine $zerotonine $zerotonine; do + dig_with_opts @10.53.0.7 non-zero.example.net txt >dig.out.2.${n} || ret=1 + ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) + test "${ttl2:-1}" -eq 0 && break + test "${ttl2:-1}" -ge "${ttl1:-0}" && break + "${PERL}" -e 'select(undef, undef, undef, 0.05);' +done +test "${ttl2:-1}" -eq 0 && ret=1 +test "${ttl2:-1}" -ge "${ttl1:-0}" || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check zero ttl is returned for learnt zero ttl records (${n})" +ret=0 +dig_with_opts @10.53.0.7 zero.example.net txt >dig.out.1.${n} || ret=1 +ttl=$(awk '/"A" "zero" "ttl"/ { print $2 }' dig.out.1.${n}) +test "${ttl:-1}" -eq 0 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +ad (${n})" +ret=0 +dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +ad +nodnssec +ignore +norec >dig.out.$n +grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +dnssec (${n})" +ret=0 +dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +noad +dnssec +ignore +norec >dig.out.$n +grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the resolver accepts a reply with empty question section with TC=1 and retries over TCP ($n)" +ret=0 +dig_with_opts @10.53.0.5 truncated.no-questions. a +tries=3 +time=4 >dig.ns5.out.${n} || ret=1 +grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 +grep "ANSWER: 1," dig.ns5.out.${n} >/dev/null || ret=1 +grep "1\.2\.3\.4" dig.ns5.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the resolver rejects a reply with empty question section with TC=0 ($n)" +ret=0 +dig_with_opts @10.53.0.5 not-truncated.no-questions. a +tries=3 +time=4 >dig.ns5.out.${n} || ret=1 +grep "status: NOERROR" dig.ns5.out.${n} >/dev/null && ret=1 +grep "ANSWER: 1," dig.ns5.out.${n} >/dev/null && ret=1 +grep "1\.2\.3\.4" dig.ns5.out.${n} >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +if ${FEATURETEST} --enable-querytrace; then + n=$((n + 1)) + echo_i "check that SERVFAIL is returned for an empty question section via TCP ($n)" + ret=0 + nextpart ns5/named.run >/dev/null + # bind to local address so that addresses in log messages are consistent + # between platforms + dig_with_opts @10.53.0.5 -b 10.53.0.5 tcpalso.no-questions. a +tries=2 +timeout=15 >dig.ns5.out.${n} || ret=1 + grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null || ret=1 + check_namedrun() { + nextpartpeek ns5/named.run >nextpart.out.${n} + grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section, accepting it anyway as TC=1' nextpart.out.${n} >/dev/null || return 1 + grep '(tcpalso.no-questions/A): connecting via TCP' nextpart.out.${n} >/dev/null || return 1 + grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section$' nextpart.out.${n} >/dev/null || return 1 + grep '(tcpalso.no-questions/A): nextitem' nextpart.out.${n} >/dev/null || return 1 + return 0 + } + retry_quiet 12 check_namedrun || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +n=$((n + 1)) +echo_i "checking SERVFAIL is returned when all authoritative servers return FORMERR ($n)" +ret=0 +dig_with_opts @10.53.0.5 ns.formerr-to-all. a >dig.ns5.out.${n} || ret=1 +grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking SERVFAIL is not returned if only some authoritative servers return FORMERR ($n)" +ret=0 +dig_with_opts @10.53.0.5 ns.partial-formerr. a >dig.ns5.out.${n} || ret=1 +grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check logged command line ($n)" +ret=0 +grep "running as: .* -m record " ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)" +ret=0 +dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1 +grep "status: NXDOMAIN" dig.ns1.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that the addition section for HTTPS is populated on initial query to a recursive server ($n)" +ret=0 +dig_with_opts @10.53.0.7 www.example.net https >dig.out.ns7.${n} || ret=1 +grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 +grep "flags:[^;]* ra[ ;]" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 +grep "http-server\.example\.net\..*A.*10\.53\.0\.6" dig.out.ns7.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check HTTPS loop is handled properly ($n)" +ret=0 +dig_with_opts @10.53.0.7 https-loop.example.net https >dig.out.ns7.${n} || ret=1 +grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 +grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check HTTPS -> CNAME loop is handled properly ($n)" +ret=0 +dig_with_opts @10.53.0.7 https-cname-loop.example.net https >dig.out.ns7.${n} || ret=1 +grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check HTTPS cname chains are followed ($n)" +ret=0 +dig_with_opts @10.53.0.7 https-cname.example.net https >dig.out.ns7.${n} || ret=1 +grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 +grep "ADDITIONAL: 4" dig.out.ns7.${n} >/dev/null || ret=1 +grep 'http-server\.example\.net\..*A.10\.53\.0\.6' dig.out.ns7.${n} >/dev/null || ret=1 +grep 'cname-server\.example\.net\..*CNAME.cname-next\.example\.net\.' dig.out.ns7.${n} >/dev/null || ret=1 +grep 'cname-next\.example\.net\..*CNAME.http-server\.example\.net\.' dig.out.ns7.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check ADB find loops are detected ($n)" +ret=0 +dig_with_opts +tcp +tries=1 +timeout=5 @10.53.0.1 fake.lame.example.org >dig.out.ns1.${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns1.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check handling of large referrals to unresponsive name servers ($n)" +ret=0 +dig_with_opts +timeout=15 large-referral.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 +grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 +# Check the total number of findname() calls triggered by a single query +# for large-referral.example.net/A. +findname_call_count="$(grep -c "large-referral\.example\.net.*FINDNAME" ns1/named.run || true)" +if [ "${findname_call_count}" -gt 1000 ]; then + echo_i "failed: ${findname_call_count} (> 1000) findname() calls detected for large-referral.example.net" + ret=1 +fi +# Check whether the limit of NS RRs processed for any delegation +# encountered was not exceeded. +if grep -Eq "dns_adb_createfind: started (A|AAAA) fetch for name ns21.fake.redirect.com" ns1/named.run; then + echo_i "failed: unexpected address fetch(es) were triggered for ns21.fake.redirect.com" + ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking query resolution for a domain with a valid glueless delegation chain ($n)" +ret=0 +rndccmd 10.53.0.1 flush || ret=1 +dig_with_opts foo.bar.sub.tld1 @10.53.0.1 TXT >dig.out.ns1.test${n} || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +grep "IN.*TXT.*baz" dig.out.ns1.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that correct namespace is chosen for dual-stack-servers ($n)" +ret=0 +dig_with_opts @fd92:7065:b8e:ffff::9 foo.v4only.net A >dig.out.ns9.${n} || ret=1 +grep "status: NOERROR" dig.out.ns9.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check expired TTLs with qtype * (${n})" +ret=0 +dig_with_opts +tcp @10.53.0.5 mixedttl.tld any >dig.out.1.${n} || ret=1 +ttl1=$(awk '$1 == "mixedttl.tld." && $4 == "A" { print $2 + 1 }' dig.out.1.${n}) +# sleep TTL + 1 so that record has expired +sleep "${ttl1:-0}" +dig_with_opts +tcp @10.53.0.5 mixedttl.tld any >dig.out.2.${n} || ret=1 +# check preconditions +grep "ANSWER: 3," dig.out.1.${n} >/dev/null || ret=1 +lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.1.${n} | wc -l) +test ${lines:-1} -ne 0 && ret=1 +# check behaviour (there may be 1 answer on very slow machines) +grep "ANSWER: [12]," dig.out.2.${n} >/dev/null || ret=1 +lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.2.${n} | wc -l) +test ${lines:-1} -ne 0 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check resolver behavior when FORMERR for EDNS options happens (${n})" +ret=0 +msg="resolving options-formerr/A .* server sent FORMERR with echoed DNS COOKIE" +if [ $ret != 0 ]; then echo_i "failed"; fi +nextpart ns5/named.run >/dev/null +dig_with_opts +tcp @10.53.0.5 options-formerr A >dig.out.${n} || ret=1 +grep "status: NOERROR" dig.out.${n} >/dev/null || ret=1 +nextpart ns5/named.run | grep "$msg" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "GL#4612 regression test: DS query against broken NODATA responses (${n})" +# servers ns2 and ns3 return authority SOA which matches QNAME rather than the zone +ret=0 +dig_with_opts @10.53.0.7 a.a.gl6412 DS >dig.out.${n} || ret=1 +grep "status: SERVFAIL" dig.out.${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that response codes have been logged with 'responselog yes;' ($n)" +ret=0 +grep "responselog yes;" ns5/named.conf >/dev/null || ret=1 +grep "response: version.bind CH TXT NOERROR" ns5/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog off' disables logging 'responselog yes;' ($n)" +ret=0 +rndccmd 10.53.0.5 responselog off || ret=1 +dig_with_opts @10.53.0.5 should.not.be.logged >dig.ns5.out.${n} || ret=1 +grep "response: should.not.be.logged" ns5/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog on' enables logging 'responselog yes;' ($n)" +ret=0 +grep "response: should.be.logged" ns5/named.run >/dev/null && ret=1 +rndccmd 10.53.0.5 responselog on || ret=1 +dig_with_opts @10.53.0.5 should.be.logged >dig.ns5.out.${n} || ret=1 +grep "response: should.be.logged" ns5/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that response codes have not been logged with default 'responselog' ($n)" +ret=0 +grep "responselog" ns1/named.conf >/dev/null && ret=1 +grep "response: version.bind CH TXT NOERROR" ns1/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog on' enables logging with default 'responselog' ($n)" +ret=0 +grep "response: should.be.logged" ns1/named.run >/dev/null && ret=1 +rndccmd 10.53.0.1 responselog on || ret=1 +dig_with_opts @10.53.0.1 should.be.logged >dig.ns1.out.${n} || ret=1 +grep "response: should.be.logged" ns1/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog off' disables logging with default 'responselog' ($n)" +ret=0 +rndccmd 10.53.0.1 responselog off || ret=1 +dig_with_opts @10.53.0.1 should.not.be.logged >dig.ns1.out.${n} || ret=1 +grep "response: should.not.be.logged" ns1/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that response codes have not been logged with 'responselog no;' ($n)" +ret=0 +grep "responselog no;" ns6/named.conf >/dev/null || ret=1 +grep "response: version.bind CH TXT NOERROR" ns6/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog on' enables logging with default 'responselog no;' ($n)" +ret=0 +grep "response: should.be.logged" ns6/named.run >/dev/null && ret=1 +rndccmd 10.53.0.6 responselog on || ret=1 +dig_with_opts @10.53.0.6 should.be.logged >dig.ns6.out.${n} || ret=1 +grep "response: should.be.logged" ns6/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog' toggles logging off with default 'responselog no;' ($n)" +ret=0 +rndccmd 10.53.0.6 responselog || ret=1 +dig_with_opts @10.53.0.6 toggled.should.not.be.logged >dig.ns6.out.${n} || ret=1 +grep "response: toggled.should.not.be.logged" ns6/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog' toggles logging on with default 'responselog no;' ($n)" +ret=0 +rndccmd 10.53.0.6 responselog || ret=1 +dig_with_opts @10.53.0.6 toggled.should.be.logged >dig.ns6.out.${n} || ret=1 +grep "response: toggled.should.be.logged" ns6/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that 'rndc responselog off' disables logging with default 'responselog no;' ($n)" +ret=0 +rndccmd 10.53.0.6 responselog off || ret=1 +dig_with_opts @10.53.0.6 should.not.be.logged >dig.ns6.out.${n} || ret=1 +grep "response: should.not.be.logged" ns6/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check that attach-cache with arbitrary cache name is preserved across reload ($n)" +ret=0 +# send a query, wait a second, reload the configuration, and query again. +# the TTL should indicate that the cache was still populated. +dig_with_opts +noall +answer @10.53.0.1 www.example.org >/dev/null || ret=1 +sleep 1 +rndc_reload ns1 10.53.0.1 +dig_with_opts +noall +answer @10.53.0.1 www.example.org >dig.ns1.out.${n} || ret=1 +ttl=$(awk '{print $2}' dig.ns1.out.${n}) +[ $ttl -lt 300 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "client requests recursion but it is disabled - expect EDE 20 code with REFUSED($n)" +ret=0 +dig_with_opts +recurse www.isc.org @10.53.0.11 a >dig.out.ns11.test${n} || ret=1 +grep "status: REFUSED" dig.out.ns11.test${n} >/dev/null || ret=1 +grep -F "EDE: 20 (Not Authoritative)" dig.out.ns11.test${n} >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/resolver/tests_sh_resolver.py b/bin/tests/system/resolver/tests_sh_resolver.py new file mode 100644 index 0000000..10a36ce --- /dev/null +++ b/bin/tests/system/resolver/tests_sh_resolver.py @@ -0,0 +1,44 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + ".digrc", + "dig*.out*", + "dig.*.foo.*", + "dig.*.bar.*", + "dig.*.prime.*", + "nextpart.out.*", + "ans*/ans.run", + "ans*/query.log", + "ns1/named.stats*", + "ns4/tld.db", + "ns5/trusted.conf", + "ns6/K*", + "ns6/ds.example.net.db", + "ns6/ds.example.net.db.signed", + "ns6/dsset-ds.example.net.", + "ns6/dsset-example.net.", + "ns6/example.net.db", + "ns6/example.net.db.signed", + "ns6/example.net.db.signed.jnl", + "ns6/to-be-removed.tld.db", + "ns6/to-be-removed.tld.db.jnl", + "ns7/server.db", + "ns7/server.db.jnl", + ] +) + + +def test_resolver(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rndc/gencheck.c b/bin/tests/system/rndc/gencheck.c new file mode 100644 index 0000000..61b885d --- /dev/null +++ b/bin/tests/system/rndc/gencheck.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include +#include +#include + +#define USAGE "usage: gencheck \n" + +static int +check(const char *buf, ssize_t count, size_t *start) { + const char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + ssize_t i; + + for (i = 0; i < count; i++, *start = (*start + 1) % (sizeof(chars) - 1)) + { + /* Just ignore the trailing newline */ + if (buf[i] == '\n') { + continue; + } + if (buf[i] != chars[*start]) { + return 0; + } + } + + return 1; +} + +int +main(int argc, char **argv) { + int ret; + int fd; + ssize_t count; + char buf[1024]; + size_t start; + size_t length; + + ret = EXIT_FAILURE; + fd = -1; + length = 0; + + if (argc != 2) { + fprintf(stderr, USAGE); + goto out; + } + + fd = open(argv[1], O_RDONLY); + if (fd == -1) { + goto out; + } + + start = 0; + while ((count = read(fd, buf, sizeof(buf))) != 0) { + if (count < 0) { + goto out; + } + + if (!check(buf, count, &start)) { + goto out; + } + + length += count; + } + + ret = EXIT_SUCCESS; + +out: + printf("%lu\n", (unsigned long)length); + + if (fd != -1) { + close(fd); + } + + return ret; +} diff --git a/bin/tests/system/rndc/ns2/incl.db b/bin/tests/system/rndc/ns2/incl.db new file mode 100644 index 0000000..bb8b343 --- /dev/null +++ b/bin/tests/system/rndc/ns2/incl.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; Used for testing $INCLUDE +$INCLUDE "static.db" diff --git a/bin/tests/system/rndc/ns2/named.conf.in b/bin/tests/system/rndc/ns2/named.conf.in new file mode 100644 index 0000000..e25f293 --- /dev/null +++ b/bin/tests/system/rndc/ns2/named.conf.in @@ -0,0 +1,65 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key secondkey { + secret "abcd1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; secondkey; }; +}; + + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "nil" { + type primary; + update-policy local; + file "nil.db"; + ixfr-from-differences yes; +}; + +zone "other" { + type primary; + update-policy local; + file "other.db"; +}; + +zone "static" { + type primary; + file "static.db"; +}; + +zone "incl" { + type primary; + file "incl.db"; +}; diff --git a/bin/tests/system/rndc/ns2/secondkey.conf.in b/bin/tests/system/rndc/ns2/secondkey.conf.in new file mode 100644 index 0000000..4f88153 --- /dev/null +++ b/bin/tests/system/rndc/ns2/secondkey.conf.in @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + default-key "secondkey"; +}; + +key secondkey { + secret "abcd1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; diff --git a/bin/tests/system/rndc/ns3/named.conf.in b/bin/tests/system/rndc/ns3/named.conf.in new file mode 100644 index 0000000..0c2b679 --- /dev/null +++ b/bin/tests/system/rndc/ns3/named.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key secondkey { + secret "abcd1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view all { + match-clients { any; }; + + recursion no; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; +}; + +view none { + match-clients { none; }; +}; diff --git a/bin/tests/system/rndc/ns4/named.conf.in b/bin/tests/system/rndc/ns4/named.conf.in new file mode 100644 index 0000000..0ec0cc7 --- /dev/null +++ b/bin/tests/system/rndc/ns4/named.conf.in @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +view normal { + match-clients { any; }; + + zone example { + type primary; + file "example.db"; + allow-update { any; }; + }; +}; + +view "view with a space" { + match-clients { none; }; + zone example { + in-view normal; + }; +}; diff --git a/bin/tests/system/rndc/ns5/named.conf.in b/bin/tests/system/rndc/ns5/named.conf.in new file mode 100644 index 0000000..51aacd3 --- /dev/null +++ b/bin/tests/system/rndc/ns5/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; } read-only yes; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/rndc/ns6/named.args b/bin/tests/system/rndc/ns6/named.args new file mode 100644 index 0000000..82e8771 --- /dev/null +++ b/bin/tests/system/rndc/ns6/named.args @@ -0,0 +1,3 @@ +# teardown of a huge zone with tracing enabled takes way too long +# -m none is set so that stop.pl does not timeout +-D rndc-ns6 -m none -c named.conf -d 99 -g -T maxcachesize=2097152 diff --git a/bin/tests/system/rndc/ns6/named.conf.in b/bin/tests/system/rndc/ns6/named.conf.in new file mode 100644 index 0000000..a465a20 --- /dev/null +++ b/bin/tests/system/rndc/ns6/named.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/rndc/ns7/include.db.in b/bin/tests/system/rndc/ns7/include.db.in new file mode 100644 index 0000000..011997b --- /dev/null +++ b/bin/tests/system/rndc/ns7/include.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 86400 IN SOA ns7 hostmaster 1 5 5 1814400 3600 +@ NS ns7 +ns7 A 10.53.0.7 + +text1 TXT "include 1" diff --git a/bin/tests/system/rndc/ns7/include2.db.in b/bin/tests/system/rndc/ns7/include2.db.in new file mode 100644 index 0000000..e5d1981 --- /dev/null +++ b/bin/tests/system/rndc/ns7/include2.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 86400 IN SOA ns7 hostmaster 4 5 5 1814400 3600 +@ NS ns7 +ns7 A 10.53.0.7 + +text1 TXT "include 2" diff --git a/bin/tests/system/rndc/ns7/named.conf.in b/bin/tests/system/rndc/ns7/named.conf.in new file mode 100644 index 0000000..2d4bf7f --- /dev/null +++ b/bin/tests/system/rndc/ns7/named.conf.in @@ -0,0 +1,58 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +key int { + algorithm @DEFAULT_HMAC@; + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +}; + +key ext { + algorithm @DEFAULT_HMAC@; + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +view internal { + match-clients { key "int"; }; + + zone "test" { + type primary; + update-policy { grant int zonesub any; }; + file "test.db"; + ixfr-from-differences yes; + }; +}; + +view external { + match-clients { key "ext"; }; + + zone "test" { + in-view internal; + }; +}; diff --git a/bin/tests/system/rndc/ns7/test.db.in b/bin/tests/system/rndc/ns7/test.db.in new file mode 100644 index 0000000..0bff14e --- /dev/null +++ b/bin/tests/system/rndc/ns7/test.db.in @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +$INCLUDE "include.db" diff --git a/bin/tests/system/rndc/setup.sh b/bin/tests/system/rndc/setup.sh new file mode 100644 index 0000000..557ec6c --- /dev/null +++ b/bin/tests/system/rndc/setup.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/nil.db +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/other.db +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns2/static.db + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns4/example.db + +$SHELL ${TOP_SRCDIR}/bin/tests/system/genzone.sh 2 >ns6/huge.zone.db + +cp ns7/test.db.in ns7/test.db +cp ns7/include.db.in ns7/include.db + +# we make the huge zone less huge if we're running under +# TSAN, to give the test a fighting chance not to time out. +size=1000000 +if $FEATURETEST --tsan; then + size=250000 +fi +awk 'END { for (i = 1; i <= '${size}'; i++) + printf "host%d IN A 10.53.0.6\n", i; }' >ns6/huge.zone.db + +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns2/secondkey.conf.in ns2/secondkey.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf + +keyset= +make_key() { + $RNDCCONFGEN -k key$1 -A $3 -s 10.53.0.4 -p $2 \ + >ns4/key${1}.conf 2>/dev/null + grep -E -v '(^# Start|^# End|^# Use|^[^#])' ns4/key$1.conf | cut -c3- \ + | sed 's/allow { 10.53.0.4/allow { any/' >>ns4/named.conf + key='"'key$1'";' + keyset="$keyset $key" +} + +$FEATURETEST --md5 && make_key 1 ${EXTRAPORT1} hmac-md5 +make_key 2 ${EXTRAPORT2} hmac-sha1 +make_key 3 ${EXTRAPORT3} hmac-sha224 +make_key 4 ${EXTRAPORT4} hmac-sha256 +make_key 5 ${EXTRAPORT5} hmac-sha384 +make_key 6 ${EXTRAPORT6} hmac-sha512 + +cat >>ns4/named.conf <<-EOF + +controls { + inet 10.53.0.4 port ${EXTRAPORT7} + allow { any; } keys { $keyset }; +}; +EOF diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh new file mode 100644 index 0000000..81f05a8 --- /dev/null +++ b/bin/tests/system/rndc/tests.sh @@ -0,0 +1,840 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd" +DIGOPTS="" +DIGCMD="$DIG $DIGOPTS -p ${PORT}" +RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../_common/rndc.conf -s" + +status=0 +n=0 + +n=$((n + 1)) +echo_i "preparing ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >/dev/null 2>&1 </dev/null && break + sleep 1 +done +grep "addition 1" ns2/nil.db >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking journal file is still present ($n)" +ret=0 +[ -s ns2/nil.db.jnl ] || { + echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking zone not writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >/dev/null 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 2' dig.out.1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "rndc thaw" +$RNDCCMD 10.53.0.2 thaw | sed 's/^/ns2 /' | cat_i + +wait_for_log 3 "zone_postload: zone nil/IN: done" ns2/named.run + +n=$((n + 1)) +echo_i "checking zone now writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.1.test$n 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 3' dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "rndc sync" +ret=0 +$RNDCCMD 10.53.0.2 sync nil | sed 's/^/ns2 /' | cat_i + +n=$((n + 1)) +echo_i "checking zone was dumped ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10; do + grep "addition 3" ns2/nil.db >/dev/null && break + sleep 1 +done +grep "addition 3" ns2/nil.db >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking journal file is still present ($n)" +ret=0 +[ -s ns2/nil.db.jnl ] || { + echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking zone is still writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.1.test$n 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 4' dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "rndc sync -clean" +ret=0 +$RNDCCMD 10.53.0.2 sync -clean nil | sed 's/^/ns2 /' | cat_i + +n=$((n + 1)) +echo_i "checking zone was dumped ($n)" +ret=0 +for i in 1 2 3 4 5 6 7 8 9 10; do + grep "addition 4" ns2/nil.db >/dev/null && break + sleep 1 +done +grep "addition 4" ns2/nil.db >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking journal file is deleted ($n)" +ret=0 +[ -s ns2/nil.db.jnl ] && { + echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking zone is still writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >/dev/null 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 4' dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking other journal files not removed ($n)" +ret=0 +[ -s ns2/other.db.jnl ] || { + echo_i "'test -s ns2/other.db.jnl' failed when it shouldn't have" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "cleaning all zones ($n)" +$RNDCCMD 10.53.0.2 sync -clean | sed 's/^/ns2 /' | cat_i + +n=$((n + 1)) +echo_i "checking all journals removed ($n)" +ret=0 +[ -s ns2/nil.db.jnl ] && { + echo_i "'test -s ns2/nil.db.jnl' succeeded when it shouldn't have" + ret=1 +} +[ -s ns2/other.db.jnl ] && { + echo_i "'test -s ns2/other.db.jnl' succeeded when it shouldn't have" + ret=1 +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that freezing static zones is not allowed ($n)" +ret=0 +$RNDCCMD 10.53.0.2 freeze static >rndc.out.1.test$n 2>&1 && ret=1 +grep 'not dynamic' rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that journal is removed when serial is changed before thaw ($n)" +ret=0 +sleep 1 +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.1.test$n 2>&1 <&1 | sed 's/^/ns2 /' | cat_i +for i in 1 2 3 4 5 6 7 8 9 10; do + grep "addition 6" ns2/other.db >/dev/null && break + sleep 1 +done +serial=$(awk '$3 ~ /serial/ {print $1}' ns2/other.db) +newserial=$((serial + 1)) +sed s/$serial/$newserial/ ns2/other.db >ns2/other.db.new +echo 'frozen TXT "frozen addition"' >>ns2/other.db.new +mv -f ns2/other.db.new ns2/other.db +$RNDCCMD 10.53.0.2 thaw 2>&1 | sed 's/^/ns2 /' | cat_i +sleep 1 +[ -f ns2/other.db.jnl ] && { + echo_i "'test -f ns2/other.db.jnl' succeeded when it shouldn't have" + ret=1 +} +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.2.test$n 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 6' dig.out.1.test$n >/dev/null || ret=1 +$DIGCMD @10.53.0.2 text7.other. TXT >dig.out.2.test$n || ret=1 +grep 'addition 7' dig.out.2.test$n >/dev/null || ret=1 +$DIGCMD @10.53.0.2 frozen.other. TXT >dig.out.3.test$n || ret=1 +grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that journal is kept when ixfr-from-differences is in use ($n)" +ret=0 +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.1.test$n 2>&1 <&1 | sed 's/^/ns2 /' | cat_i +for i in 1 2 3 4 5 6 7 8 9 10; do + grep "addition 6" ns2/nil.db >/dev/null && break + sleep 1 +done +serial=$(awk '$3 ~ /serial/ {print $1}' ns2/nil.db) +newserial=$((serial + 1)) +sed s/$serial/$newserial/ ns2/nil.db >ns2/nil.db.new +echo 'frozen TXT "frozen addition"' >>ns2/nil.db.new +mv -f ns2/nil.db.new ns2/nil.db +$RNDCCMD 10.53.0.2 thaw 2>&1 | sed 's/^/ns2 /' | cat_i +sleep 1 +[ -s ns2/nil.db.jnl ] || { + echo_i "'test -s ns2/nil.db.jnl' failed when it shouldn't have" + ret=1 +} +$NSUPDATE -p ${PORT} -k ns2/session.key >nsupdate.out.2.test$n 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 6' dig.out.1.test$n >/dev/null || ret=1 +$DIGCMD @10.53.0.2 text7.nil. TXT >dig.out.2.test$n || ret=1 +grep 'addition 7' dig.out.2.test$n >/dev/null || ret=1 +$DIGCMD @10.53.0.2 frozen.nil. TXT >dig.out.3.test$n || ret=1 +grep 'frozen addition' dig.out.3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# temp test +echo_i "dumping stats ($n)" +$RNDCCMD 10.53.0.2 stats +n=$((n + 1)) +echo_i "verifying adb records in named.stats ($n)" +grep "ADB stats" ns2/named.stats >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test using second key ($n)" +ret=0 +$RNDC -s 10.53.0.2 -p ${CONTROLPORT} -c ns2/secondkey.conf status >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'rndc dumpdb' with an unwritable dump-file ($n)" +ret=0 +touch ns2/named_dump.db +chmod -w ns2/named_dump.db +rndc_dumpdb ns2 2>/dev/null && ret=1 +grep -F "failed: permission denied" "rndc.out.test$n" >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'rndc dumpdb' on a empty cache ($n)" +ret=0 +rndc_dumpdb ns3 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'rndc reload' on a zone with include files ($n)" +ret=0 +grep "incl/IN: skipping load" ns2/named.run >/dev/null && ret=1 +loads=$(grep "incl/IN: starting load" ns2/named.run | wc -l) +[ "$loads" -eq 1 ] || ret=1 +$RNDCCMD 10.53.0.2 reload >/dev/null || ret=1 +for i in 1 2 3 4 5 6 7 8 9; do + tmp=0 + grep "incl/IN: skipping load" ns2/named.run >/dev/null || tmp=1 + [ $tmp -eq 0 ] && break + sleep 1 +done +[ $tmp -eq 1 ] && ret=1 +touch ns2/static.db +$RNDCCMD 10.53.0.2 reload >/dev/null || ret=1 +for i in 1 2 3 4 5 6 7 8 9; do + tmp=0 + loads=$(grep "incl/IN: starting load" ns2/named.run | wc -l) + [ "$loads" -eq 2 ] || tmp=1 + [ $tmp -eq 0 ] && break + sleep 1 +done +[ $tmp -eq 1 ] && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +if $FEATURETEST --md5; then + echo_i "testing rndc with hmac-md5 ($n)" + ret=0 + $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key1.conf status >/dev/null 2>&1 || ret=1 + for i in 2 3 4 5 6; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key${i}.conf status >/dev/null 2>&1 && ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipping rndc with hmac-md5 ($n)" +fi + +n=$((n + 1)) +echo_i "testing rndc with hmac-sha1 ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT2} -c ns4/key2.conf status >/dev/null 2>&1 || ret=1 +for i in 1 3 4 5 6; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT2} -c ns4/key${i}.conf status >/dev/null 2>&1 && ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with hmac-sha224 ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT3} -c ns4/key3.conf status >/dev/null 2>&1 || ret=1 +for i in 1 2 4 5 6; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT3} -c ns4/key${i}.conf status >/dev/null 2>&1 && ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with hmac-sha256 ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT4} -c ns4/key4.conf status >/dev/null 2>&1 || ret=1 +for i in 1 2 3 5 6; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT4} -c ns4/key${i}.conf status >/dev/null 2>&1 && ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with hmac-sha384 ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT5} -c ns4/key5.conf status >/dev/null 2>&1 || ret=1 +for i in 1 2 3 4 6; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT5} -c ns4/key${i}.conf status >/dev/null 2>&1 && ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with hmac-sha512 ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status >/dev/null 2>&1 || ret=1 +for i in 1 2 3 4 5; do + $RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key${i}.conf status >/dev/null 2>&1 2>&1 && ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing single control channel with multiple algorithms ($n)" +ret=0 +for i in 1 2 3 4 5 6; do + test $i = 1 && $FEATURETEST --have-fips-mode && continue + $RNDC -s 10.53.0.4 -p ${EXTRAPORT7} -c ns4/key${i}.conf status >/dev/null 2>&1 || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing automatic zones are reported ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status >rndc.out.1.test$n || ret=1 +grep "number of zones: 201 (200 automatic)" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with null command ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with unknown control channel command ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf obviouslynotacommand >/dev/null 2>&1 && ret=1 +# rndc: 'obviouslynotacommand' failed: unknown command +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with querylog command ($n)" +ret=0 +# first enable it with querylog on option +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf querylog on >/dev/null 2>&1 || ret=1 +grep "query logging is now on" ns4/named.run >/dev/null || ret=1 +# query for builtin and check if query was logged (without +subnet) +$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo12345.bind +qr >dig.out.1.test$n 2>&1 || ret=1 +grep "query: foo12345.bind CH TXT.*(.*)$" ns4/named.run >/dev/null || ret=1 +# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1) +$DIG +subnet=127.0.0.1 @10.53.0.4 -p ${PORT} -c ch -t txt foo12346.bind +qr >dig.out.2.test$n 2>&1 || ret=1 +grep "query: foo12346.bind CH TXT.*\[ECS 127\.0\.0\.1/32/0]" ns4/named.run >/dev/null || ret=1 +# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1/24) +$DIG +subnet=127.0.0.1/24 @10.53.0.4 -p ${PORT} -c ch -t txt foo12347.bind +qr >dig.out.3.test$n 2>&1 || ret=1 +grep "query: foo12347.bind CH TXT.*\[ECS 127\.0\.0\.0/24/0]" ns4/named.run >/dev/null || ret=1 +# query for another builtin zone and check if query was logged (with +subnet=::1) +$DIG +subnet=::1 @10.53.0.4 -p ${PORT} -c ch -t txt foo12348.bind +qr >dig.out.4.test$n 2>&1 || ret=1 +grep "query: foo12348.bind CH TXT.*\[ECS ::1/128/0]" ns4/named.run >/dev/null || ret=1 +# toggle query logging and check again +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf querylog >/dev/null 2>&1 || ret=1 +grep "query logging is now off" ns4/named.run >/dev/null || ret=1 +# query for another builtin zone and check if query was logged (without +subnet) +$DIG @10.53.0.4 -p ${PORT} -c ch -t txt foo9876.bind +qr >dig.out.5.test$n 2>&1 || ret=1 +grep "query: foo9876.bind CH TXT.*(.*)$" ns4/named.run >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +RNDCCMD4="$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf" +n=$((n + 1)) +echo_i "testing rndc nta time limits ($n)" +ret=0 +$RNDCCMD4 nta -l 2h nta1.example >rndc.out.1.test$n 2>&1 +grep "Negative trust anchor added" rndc.out.1.test$n >/dev/null || ret=1 +$RNDCCMD4 nta -l 1d nta2.example >rndc.out.2.test$n 2>&1 +grep "Negative trust anchor added" rndc.out.2.test$n >/dev/null || ret=1 +$RNDCCMD4 nta -l 1w nta3.example >rndc.out.3.test$n 2>&1 +grep "Negative trust anchor added" rndc.out.3.test$n >/dev/null || ret=1 +$RNDCCMD4 nta -l 8d nta4.example >rndc.out.4.test$n 2>&1 && ret=1 +grep "NTA lifetime cannot exceed one week" rndc.out.4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc nta -class option ($n)" +ret=0 +nextpart ns4/named.run >/dev/null +$RNDCCMD4 nta -c in nta1.example >rndc.out.1.test$n 2>&1 +nextpart ns4/named.run | grep "added NTA 'nta1.example'" >/dev/null || ret=1 +$RNDCCMD4 nta -c any nta1.example >rndc.out.2.test$n 2>&1 +nextpart ns4/named.run | grep "added NTA 'nta1.example'" >/dev/null || ret=1 +$RNDCCMD4 nta -c ch nta1.example >rndc.out.3.test$n 2>&1 +nextpart ns4/named.run | grep "added NTA 'nta1.example'" >/dev/null && ret=1 +$RNDCCMD4 nta -c fake nta1.example >rndc.out.4.test$n 2>&1 && ret=1 +nextpart ns4/named.run | grep "added NTA 'nta1.example'" >/dev/null && ret=1 +grep 'unknown class' rndc.out.4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +for i in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288; do + n=$((n + 1)) + echo_i "testing rndc buffer size limits (size=${i}) ($n)" + ret=0 + $RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf testgen ${i} 2>&1 >rndc.out.$i.test$n || ret=1 + { + actual_size=$($GENCHECK rndc.out.$i.test$n) + rc=$? + } || true + if [ "$rc" = "0" ]; then + expected_size=$((i + 1)) + if [ $actual_size != $expected_size ]; then ret=1; fi + else + ret=1 + fi + + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +done + +n=$((n + 1)) +echo_i "testing rndc -r (show result) ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf -r testgen 0 2>&1 >rndc.out.1.test$n || ret=1 +grep "ISC_R_SUCCESS 0" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "testing rndc with a token containing a space ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf -r flush '"view with a space"' 2>&1 >rndc.out.1.test$n || ret=1 +grep "not found" rndc.out.1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'rndc reconfig' with a broken config ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig >/dev/null || ret=1 +sleep 1 +mv ns4/named.conf ns4/named.conf.save +echo "error error error" >>ns4/named.conf +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig >rndc.out.1.test$n 2>&1 && ret=1 +grep "rndc: 'reconfig' failed: unexpected token" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc status reports failure ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status >rndc.out.1.test$n 2>&1 || ret=1 +grep "reload/reconfig failed" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "restore working config ($n)" +ret=0 +mv ns4/named.conf.save ns4/named.conf +sleep 1 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf reconfig >/dev/null || ret=1 +sleep 1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc status' 'reload/reconfig failure' is cleared after successful reload/reconfig ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf status >rndc.out.1.test$n 2>&1 || ret=1 +grep "reload/reconfig failed" rndc.out.1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test read-only control channel access ($n)" +ret=0 +$RNDCCMD 10.53.0.5 status >rndc.out.1.test$n 2>&1 || ret=1 +$RNDCCMD 10.53.0.5 nta -dump >rndc.out.2.test$n 2>&1 || ret=1 +$RNDCCMD 10.53.0.5 reconfig >rndc.out.3.test$n 2>&1 && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test rndc status shows running on ($n)" +ret=0 +$RNDCCMD 10.53.0.5 status >rndc.out.1.test$n 2>&1 || ret=1 +grep "^running on " rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "test 'rndc reconfig' with loading of a large zone ($n)" +ret=0 +nextpart ns6/named.run >/dev/null +cp ns6/named.conf ns6/named.conf.save +echo "zone \"huge.zone\" { type primary; file \"huge.zone.db\"; };" >>ns6/named.conf +echo_i "reloading config" +$RNDCCMD 10.53.0.6 reconfig >rndc.out.1.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +sleep 1 + +n=$((n + 1)) +echo_i "check if zone load was scheduled ($n)" +wait_for_log_peek 20 "scheduled loading new zones" ns6/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check if query for the zone returns SERVFAIL ($n)" +$DIG @10.53.0.6 -p ${PORT} -t soa huge.zone >dig.out.1.test$n || ret=1 +grep "SERVFAIL" dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "failed (ignored)" + ret=0 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "wait for the zones to be loaded ($n)" +wait_for_log_peek 60 "huge.zone/IN: loaded serial" ns6/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check if query for the zone returns NOERROR ($n)" +$DIG @10.53.0.6 -p ${PORT} -t soa huge.zone >dig.out.1.test$n || ret=1 +grep "NOERROR" dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify that the full command is logged ($n)" +ret=0 +$RNDCCMD 10.53.0.2 null with extra arguments >/dev/null 2>&1 +grep "received control channel command 'null with extra arguments'" ns2/named.run >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +mv ns6/named.conf.save ns6/named.conf +sleep 1 +$RNDCCMD 10.53.0.6 reconfig >/dev/null || ret=1 +sleep 1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc \"\"' is handled ($n)" +ret=0 +$RNDCCMD 10.53.0.2 "" >rndc.out.1.test$n 2>&1 && ret=1 +grep "rndc: '' failed: failure" rndc.out.1.test$n >/dev/null +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc -4 -6 ($n)" +ret=0 +$RNDCCMD 10.53.0.2 -4 -6 status >rndc.out.1.test$n 2>&1 && ret=1 +grep "only one of -4 and -6 allowed" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc -4 with an IPv6 server address ($n)" +ret=0 +$RNDCCMD fd92:7065:b8e:ffff::2 -4 status >rndc.out.1.test$n 2>&1 && ret=1 +grep "address family not supported" rndc.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc nta reports adding to multiple views ($n)" +ret=0 +$RNDCCMD 10.53.0.3 nta test.com >rndc.out.test$n 2>&1 || ret=1 +lines=$(cat rndc.out.test$n | wc -l) +[ ${lines:-0} -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc retransfer' of primary error message ($n)" +ret=0 +$RNDCCMD 10.53.0.2 retransfer nil >rndc.out.test$n 2>&1 && ret=1 +grep "rndc: 'retransfer' failed: failure" rndc.out.test$n >/dev/null || ret=1 +grep "retransfer: inappropriate zone type: primary" rndc.out.test$n >/dev/null || ret=1 +lines=$(cat rndc.out.test$n | wc -l) +[ ${lines:-0} -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc freeze' with in-view zones works ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf freeze >rndc.out.test$n 2>&1 || ret=1 +test -s rndc.out.test$n && sed 's/^/ns2 /' rndc.out.test$n | cat_i +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking non in-view zone instance is not writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} >/dev/null 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 3' dig.out.1.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc thaw' with in-view zones works ($n)" +ret=0 +$RNDC -s 10.53.0.4 -p ${EXTRAPORT6} -c ns4/key6.conf thaw >rndc.out.test$n 2>&1 || ret=1 +test -s rndc.out.test$n && sed 's/^/ns2 /' rndc.out.test$n | cat_i +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking non in-view zone instance is now writable ($n)" +ret=0 +$NSUPDATE -p ${PORT} >nsupdate.out.test$n 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 3' dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking initial in-view zone file is loaded ($n)" +ret=0 +TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0=" +$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT >dig.out.1.test$n || ret=1 +grep 'include 1' dig.out.1.test$n >/dev/null || ret=1 +TSIG="$DEFAULT_HMAC:ext:FrSt77yPTFx6hTs4i2tKLB9LmE0=" +$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT >dig.out.2.test$n || ret=1 +grep 'include 1' dig.out.2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "update in-view zone ($n)" +ret=0 +TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0=" +$NSUPDATE -p ${PORT} -y "$TSIG" >/dev/null 2>&1 <dig.out.1.test$n || ret=1 +grep 'addition 1' dig.out.1.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +nextpart ns7/named.run >/dev/null + +echo_i "rndc freeze" +$RNDCCMD 10.53.0.7 freeze | sed 's/^/ns7 /' | cat_i | cat_i + +wait_for_log 3 "dump_done: zone test/IN/internal: enter" ns7/named.run + +echo_i "edit zone files" +cp ns7/test.db.in ns7/test.db +cp ns7/include2.db.in ns7/include.db + +echo_i "rndc thaw" +$RNDCCMD 10.53.0.7 thaw | sed 's/^/ns7 /' | cat_i + +wait_for_log 3 "zone_postload: zone test/IN/internal: done" ns7/named.run + +echo_i "rndc reload" +$RNDCCMD 10.53.0.7 reload | sed 's/^/ns7 /' | cat_i + +wait_for_log 3 "all zones loaded" ns7/named.run + +n=$((n + 1)) +echo_i "checking zone file edits are loaded ($n)" +ret=0 +TSIG="$DEFAULT_HMAC:int:FrSt77yPTFx6hTs4i2tKLB9LmE0=" +$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT >dig.out.1.test$n || ret=1 +grep 'include 2' dig.out.1.test$n >/dev/null || ret=1 +TSIG="$DEFAULT_HMAC:ext:FrSt77yPTFx6hTs4i2tKLB9LmE0=" +$DIGCMD @10.53.0.7 -y "$TSIG" text1.test. TXT >dig.out.2.test$n || ret=1 +grep 'include 2' dig.out.2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check rndc nta -dump reports NTAs in multiple views ($n)" +ret=0 +$RNDCCMD 10.53.0.3 nta -dump >rndc.out.test$n 2>&1 || ret=1 +lines=$(cat rndc.out.test$n | wc -l) +[ ${lines:-0} -eq 2 ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/rndc/tests_cve-2023-3341.py b/bin/tests/system/rndc/tests_cve-2023-3341.py new file mode 100644 index 0000000..c195a0d --- /dev/null +++ b/bin/tests/system/rndc/tests_cve-2023-3341.py @@ -0,0 +1,71 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import socket +import time + +import pytest +import isctest + +pytest.importorskip("dns") +import dns.message + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns2/nil.db", + "ns2/other.db", + "ns2/secondkey.conf", + "ns2/static.db", + "ns4/example.db", + "ns4/key*.conf", + "ns6/huge.zone.db", + "ns7/include.db", + "ns7/test.db", + ] +) + + +def test_cve_2023_3341(control_port): + depth = 4500 + # Should not be more than isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768) + total_len = 10 + (depth * 7) - 6 + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + data = b"".join( + [ + total_len.to_bytes(4, "big"), # + b"\x00\x00\x00\x01", # + b"\x01\x41", # + ] + ) + + for i in range(depth, 0, -1): + l = (i - 1) * 7 + t = b"".join( + [ + b"\x02", # ISCCC_CCMSGTYPE_TABLE + l.to_bytes(4, "big"), # + b"\x01\x41", # + ] + ) + data = b"".join([data, t]) + + s.connect(("10.53.0.2", control_port)) + s.sendall(data) + + # Wait for named to (possibly) crash + time.sleep(10) + + msg = dns.message.make_query("version.bind", "TXT", "CH") + res = isctest.query.udp(msg, "10.53.0.2") + isctest.check.noerror(res) diff --git a/bin/tests/system/rndc/tests_sh_rndc.py b/bin/tests/system/rndc/tests_sh_rndc.py new file mode 100644 index 0000000..c7ab007 --- /dev/null +++ b/bin/tests/system/rndc/tests_sh_rndc.py @@ -0,0 +1,39 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "nsupdate.out.*", + "rndc.out.*", + "ns2/*.jnl", + "ns2/named.stats", + "ns2/named_dump.db.*", + "ns2/nil.db", + "ns2/other.db", + "ns2/secondkey.conf", + "ns2/static.db", + "ns3/all.nta", + "ns3/named_dump.db.*", + "ns3/none.nta", + "ns4/example.db", + "ns4/example.db.jnl", + "ns4/key*.conf", + "ns4/normal.nta", + "ns4/view with a space.nta", + "ns6/huge.zone.db", + "ns7/include.db", + "ns7/test.db", + "ns7/test.db.jnl", + ] +) diff --git a/bin/tests/system/rootkeysentinel/ns1/named.conf.in b/bin/tests/system/rootkeysentinel/ns1/named.conf.in new file mode 100644 index 0000000..930f3bc --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns1/named.conf.in @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rootkeysentinel/ns1/root.db.in b/bin/tests/system/rootkeysentinel/ns1/root.db.in new file mode 100644 index 0000000..cc97041 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns1/root.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA marka.isc.org. a.root.servers.nil. ( + 2018031400 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/rootkeysentinel/ns1/sign.sh b/bin/tests/system/rootkeysentinel/ns1/sign.sh new file mode 100644 index 0000000..dd33bd9 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns1/sign.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +keyname=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -n zone $zone) +keyid=$(expr ${keyname} : 'K.+[0-9][0-9][0-9]+\(.*\)') + +(cd ../ns2 && $SHELL sign.sh ${keyid:-00000}) + +cp ../ns2/dsset-example. . + +cat $infile $keyname.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +# Configure the resolving server with a static key. +keyfile_to_static_ds $keyname >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf +cp trusted.conf ../ns4/trusted.conf diff --git a/bin/tests/system/rootkeysentinel/ns2/example.db.in b/bin/tests/system/rootkeysentinel/ns2/example.db.in new file mode 100644 index 0000000..92ca3bf --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns2/example.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2018031400 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 diff --git a/bin/tests/system/rootkeysentinel/ns2/named.conf.in b/bin/tests/system/rootkeysentinel/ns2/named.conf.in new file mode 100644 index 0000000..25e4e50 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns2/named.conf.in @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "example" { + type primary; + file "example.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rootkeysentinel/ns2/sign.sh b/bin/tests/system/rootkeysentinel/ns2/sign.sh new file mode 100644 index 0000000..456c96f --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns2/sign.sh @@ -0,0 +1,40 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +oldid=$(echo ${1:-0} | sed 's/^0*//') +newid=$(printf '%05u' $(((oldid + 1000) % 65536))) +badid=$(printf '%05u' $(((oldid + 7777) % 65536))) +oldid=$(printf '%05u' $((oldid + 0))) + +. ../../conf.sh + +zone=example. +infile=example.db.in +zonefile=example.db + +keyname1=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone) +keyname2=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n zone $zone) + +cat $infile $keyname1.key $keyname2.key >$zonefile +echo root-key-sentinel-is-ta-$oldid A 10.53.0.1 >>$zonefile +echo root-key-sentinel-not-ta-$oldid A 10.53.0.2 >>$zonefile +echo root-key-sentinel-is-ta-$newid A 10.53.0.3 >>$zonefile +echo root-key-sentinel-not-ta-$newid A 10.53.0.4 >>$zonefile +echo old-is-ta CNAME root-key-sentinel-is-ta-$oldid >>$zonefile +echo old-not-ta CNAME root-key-sentinel-not-ta-$oldid >>$zonefile +echo new-is-ta CNAME root-key-sentinel-is-ta-$newid >>$zonefile +echo new-not-ta CNAME root-key-sentinel-not-ta-$newid >>$zonefile +echo bad-is-ta CNAME root-key-sentinel-is-ta-$badid >>$zonefile +echo bad-not-ta CNAME root-key-sentinel-not-ta-$badid >>$zonefile + +$SIGNER -P -g -o $zone -k $keyname1 $zonefile $keyname2 >/dev/null diff --git a/bin/tests/system/rootkeysentinel/ns3/hint.db b/bin/tests/system/rootkeysentinel/ns3/hint.db new file mode 100644 index 0000000..0018b52 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns3/hint.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/rootkeysentinel/ns3/named.conf.in b/bin/tests/system/rootkeysentinel/ns3/named.conf.in new file mode 100644 index 0000000..c9682c9 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns3/named.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + root-key-sentinel yes; +}; + +zone "." { + type hint; + file "hint.db"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rootkeysentinel/ns4/hint.db b/bin/tests/system/rootkeysentinel/ns4/hint.db new file mode 100644 index 0000000..0018b52 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns4/hint.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 diff --git a/bin/tests/system/rootkeysentinel/ns4/named.conf.in b/bin/tests/system/rootkeysentinel/ns4/named.conf.in new file mode 100644 index 0000000..6f60ffd --- /dev/null +++ b/bin/tests/system/rootkeysentinel/ns4/named.conf.in @@ -0,0 +1,33 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + root-key-sentinel no; +}; + +zone "." { + type hint; + file "hint.db"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rootkeysentinel/setup.sh b/bin/tests/system/rootkeysentinel/setup.sh new file mode 100644 index 0000000..39e1edf --- /dev/null +++ b/bin/tests/system/rootkeysentinel/setup.sh @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf + +cd ns1 +$SHELL sign.sh diff --git a/bin/tests/system/rootkeysentinel/tests.sh b/bin/tests/system/rootkeysentinel/tests.sh new file mode 100644 index 0000000..e550cf3 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/tests.sh @@ -0,0 +1,295 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p ${PORT}" + +newtest() { + n=$((n + 1)) + case $# in + 1) + echo_i "$1 ($n)" + ;; + 2) + echo_i "$1" + echo_ic "$2 ($n)" + ;; + esac + ret=0 +} + +newtest "get test ids" +$DIG $DIGOPTS . dnskey +short +rrcomm @10.53.0.1 >dig.out.ns1.test$n || ret=1 +oldid=$(sed -n 's/.*key id = //p' dig.out.ns2.test$n || ret=1 +grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check test zone resolves with 'root-key-sentinel yes;'" " (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 example SOA >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${oldid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${oldid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: SERVFAIL" dig.out.ns3.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with old ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-not-ta-${oldid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${newid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: SERVFAIL" dig.out.ns3.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with new ta, CD=1 and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${newid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${newid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect SERVFAIL)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-${badid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: SERVFAIL" dig.out.ns3.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with bad ta, CD=1 and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 +cd root-key-sentinel-is-ta-${badid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-${badid}.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-72345.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-72345.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-is-ta-1234.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 root-key-sentinel-not-ta-1234.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 old-is-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 old-not-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 new-is-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel yes;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.3 new-not-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 +grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 bad-is-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel yes;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.3 bad-not-ta.example A >dig.out.ns3.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns3.test$n >/dev/null || ret=1 +grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns3.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check test zone resolves with 'root-key-sentinel no;'" " (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 example SOA >dig.out.ns4.test$n +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${oldid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${oldid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${newid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${newid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-${badid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-${badid}.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-72345.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with out-of-range ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-72345.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-is-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-is-ta-1234.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check root-key-sentinel-not-ta with no-zero-pad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 root-key-sentinel-not-ta-1234.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 old-is-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "old-is-ta.*CNAME.root-key-sentinel-is-ta-${oldid}.example." dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with old ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 old-not-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "old-not-ta.*CNAME.root-key-sentinel-not-ta-${oldid}.example." dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 new-is-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "new-is-ta.*CNAME.root-key-sentinel-is-ta-${newid}.example." dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with new ta and" " 'root-key-sentinel no;' (expect NOERROR)" +$DIG $DIGOPTS @10.53.0.4 new-not-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "new-not-ta.*CNAME.root-key-sentinel-not-ta-${newid}.example." dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-is-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 bad-is-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "bad-is-ta.*CNAME.root-key-sentinel-is-ta-${badid}.example" dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +newtest "check CNAME to root-key-sentinel-not-ta with bad ta and" " 'root-key-sentinel no;' (expect NXDOMAIN)" +$DIG $DIGOPTS @10.53.0.4 bad-not-ta.example A >dig.out.ns4.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 +grep "bad-not-ta.*CNAME.root-key-sentinel-not-ta-${badid}.example." dig.out.ns4.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py b/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py new file mode 100644 index 0000000..2e66b58 --- /dev/null +++ b/bin/tests/system/rootkeysentinel/tests_sh_rootkeysentinel.py @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns*/dsset-*", + "ns*/trusted.conf", + "ns1/K*", + "ns1/root.db", + "ns1/root.db.signed", + "ns2/Kexample*", + "ns2/example.db", + "ns2/example.db.signed", + ] +) + + +def test_rootkeysentinel(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rpz/README b/bin/tests/system/rpz/README new file mode 100644 index 0000000..238e360 --- /dev/null +++ b/bin/tests/system/rpz/README @@ -0,0 +1,36 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The test setup for the RPZ tests prepares a query perf tool and sets up +policy zones. + +Name servers +------------ + +ns1 is the root server. + +ns2 and ns4 are authoritative servers for the various test domains. + +ns3 is the main rewriting resolver. + +ns5 and ns7 are additional rewriting resolvers. + +ns6 is a forwarding server. + + +Updating the response policy zones +---------------------------------- + +test1, test2, test3, test4, test5, and test6 are dynamic update files. These +updates are made against ns3. The script function "start_group" is called to +start an new batch of tests that may depend on certain server updates. The +function takes an optional file name and if provided the server updates are +performed before executing the test batch. diff --git a/bin/tests/system/rpz/dnsrps.c b/bin/tests/system/rpz/dnsrps.c new file mode 100644 index 0000000..f991566 --- /dev/null +++ b/bin/tests/system/rpz/dnsrps.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * -a exit(EXIT_SUCCESS) if dnsrps is available or dlopen() msg if not + * -n domain print the serial number of a domain to check if a new + * version of a policy zone is ready. + * Exit(1) if dnsrps is not available + * -w sec.ond wait for seconds, because `sleep 0.1` is not portable + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef USE_DNSRPS +#include +#else /* ifdef USE_DNSRPS */ +typedef struct { + char c[120]; +} librpz_emsg_t; +#endif /* ifdef USE_DNSRPS */ + +static bool +link_dnsrps(librpz_emsg_t *emsg); + +#define USAGE "usage: [-a] [-n domain] [-w sec.onds]\n" + +int +main(int argc, char **argv) { +#ifdef USE_DNSRPS + char cstr[sizeof("zone ") + 1024 + 10]; + librpz_clist_t *clist = NULL; + librpz_client_t *client = NULL; + librpz_rsp_t *rsp = NULL; + uint32_t serial; +#endif /* ifdef USE_DNSRPS */ + double seconds; + librpz_emsg_t emsg; + char *p; + int i; + + while ((i = getopt(argc, argv, "an:w:")) != -1) { + switch (i) { + case 'a': + if (!link_dnsrps(&emsg)) { + printf("I:%s\n", emsg.c); + return 1; + } + return 0; + + case 'n': + if (!link_dnsrps(&emsg)) { + fprintf(stderr, "## %s\n", emsg.c); + return 1; + } +#ifdef USE_DNSRPS + /* + * Get the serial number of a policy zone. + */ + clist = librpz->clist_create(&emsg, NULL, NULL, NULL, + NULL, NULL); + if (clist == NULL) { + fprintf(stderr, "## %s: %s\n", optarg, emsg.c); + return 1; + } + snprintf(cstr, sizeof(cstr), "zone %s;", optarg); + client = librpz->client_create(&emsg, clist, cstr, + true); + if (client == NULL) { + fprintf(stderr, "## %s\n", emsg.c); + librpz->clist_detach(&clist); + return 1; + } + + rsp = NULL; + if (!librpz->rsp_create(&emsg, &rsp, NULL, client, true, + false) || + rsp == NULL) + { + fprintf(stderr, "## %s\n", emsg.c); + librpz->client_detach(&client); + librpz->clist_detach(&clist); + return 1; + } + + if (!librpz->soa_serial(&emsg, &serial, optarg, rsp)) { + fprintf(stderr, "## %s\n", emsg.c); + librpz->rsp_detach(&rsp); + librpz->client_detach(&client); + librpz->clist_detach(&clist); + return 1; + } + librpz->rsp_detach(&rsp); + librpz->client_detach(&client); + librpz->clist_detach(&clist); + printf("%u\n", serial); +#else /* ifdef USE_DNSRPS */ + UNREACHABLE(); +#endif /* ifdef USE_DNSRPS */ + return 0; + + case 'w': + seconds = strtod(optarg, &p); + if (seconds <= 0 || *p != '\0') { + fprintf(stderr, USAGE); + return 1; + } + usleep((int)(seconds * 1000.0 * 1000.0)); + return 0; + + default: + fprintf(stderr, USAGE); + return 1; + } + } + fprintf(stderr, USAGE); + return 1; +} + +static bool +link_dnsrps(librpz_emsg_t *emsg) { +#ifdef USE_DNSRPS + librpz = librpz_lib_open(emsg, NULL, LIBRPZ_LIB_OPEN); + if (librpz == NULL) { + return false; + } + + return true; +#else /* ifdef USE_DNSRPS */ + snprintf(emsg->c, sizeof(emsg->c), "DNSRPS not configured"); + return false; +#endif /* ifdef USE_DNSRPS */ +} diff --git a/bin/tests/system/rpz/dnsrps.zones.in b/bin/tests/system/rpz/dnsrps.zones.in new file mode 100644 index 0000000..90789b3 --- /dev/null +++ b/bin/tests/system/rpz/dnsrps.zones.in @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# dnsrpzd configuration. + +pid-file ../dnsrpzd.pid + +# configure NOTIFY and zone transfers +port @EXTRAPORT1@; +listen-on port @EXTRAPORT1@ { 10.53.0.3; }; +allow-notify { 10.53.0.0/24; }; + +zone "bl0" {type primary; file "../ns5/bl.db"; }; +zone "bl1" {type primary; file "../ns5/bl.db"; }; +zone "bl2" {type primary; file "../ns5/bl.db"; }; +zone "bl3" {type primary; file "../ns5/bl.db"; }; +zone "bl4" {type primary; file "../ns5/bl.db"; }; +zone "bl5" {type primary; file "../ns5/bl.db"; }; +zone "bl6" {type primary; file "../ns5/bl.db"; }; +zone "bl7" {type primary; file "../ns5/bl.db"; }; +zone "bl8" {type primary; file "../ns5/bl.db"; }; +zone "bl9" {type primary; file "../ns5/bl.db"; }; +zone "bl10" {type primary; file "../ns5/bl.db"; }; +zone "bl11" {type primary; file "../ns5/bl.db"; }; +zone "bl12" {type primary; file "../ns5/bl.db"; }; +zone "bl13" {type primary; file "../ns5/bl.db"; }; +zone "bl14" {type primary; file "../ns5/bl.db"; }; +zone "bl15" {type primary; file "../ns5/bl.db"; }; +zone "bl16" {type primary; file "../ns5/bl.db"; }; +zone "bl17" {type primary; file "../ns5/bl.db"; }; +zone "bl18" {type primary; file "../ns5/bl.db"; }; +zone "bl19" {type primary; file "../ns5/bl.db"; }; + +zone "bl" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-2" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-given" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-passthru" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-no-op" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-disabled" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-nodata" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-nxdomain" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-cname" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-wildcname" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-garden" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-drop" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl-tcp-only" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; +zone "bl.tld2" {type secondary; primaries port @PORT@ { 10.53.0.3; }; }; + +zone "policy1" {type secondary; primaries port @PORT@ { 10.53.0.6; }; }; +zone "policy2" {type secondary; primaries port @PORT@ { 10.53.0.7; }; }; diff --git a/bin/tests/system/rpz/ns1/named.conf.in b/bin/tests/system/rpz/ns1/named.conf.in new file mode 100644 index 0000000..e7af61d --- /dev/null +++ b/bin/tests/system/rpz/ns1/named.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify no; + minimal-responses no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." {type primary; file "root.db";}; diff --git a/bin/tests/system/rpz/ns1/root.db b/bin/tests/system/rpz/ns1/root.db new file mode 100644 index 0000000..6bf3d5a --- /dev/null +++ b/bin/tests/system/rpz/ns1/root.db @@ -0,0 +1,42 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +. SOA ns. hostmaster.ns. ( 1 3600 1200 604800 60 ) + NS ns. +ns. A 10.53.0.1 + +; rewrite responses from this zone +tld2. NS ns.tld2. +ns.tld2. A 10.53.0.2 + +; rewrite responses from this secure zone unless dnssec requested (DO=1) +tld2s. NS ns.tld2. + +; requests come from here +tld3. NS ns.tld3. +ns.tld3. A 10.53.0.3 + +; rewrite responses from this zone +tld4. NS ns.tld4. +ns.tld4. A 10.53.0.4 + +; performance test +tld5. NS ns.tld5. +ns.tld5. A 10.53.0.5 + +; generate SERVFAIL +servfail NS ns.tld2. + +a-only.example A 1.2.3.4 +no-a-no-aaaa.example TXT placeholder +a-plus-aaaa.example A 1.2.3.4 +a-plus-aaaa.example AAAA ::1 diff --git a/bin/tests/system/rpz/ns10/hints b/bin/tests/system/rpz/ns10/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns10/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns10/named.conf.in b/bin/tests/system/rpz/ns10/named.conf.in new file mode 100644 index 0000000..2cbb6ee --- /dev/null +++ b/bin/tests/system/rpz/ns10/named.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.10; + notify-source 10.53.0.10; + transfer-source 10.53.0.10; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.10; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify no; + minimal-responses no; + recursion yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.10 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; +zone "." { type hint; file "hints"; }; + +# grafted on zones using stub and static-stub +zone "stub-nomatch." {type primary; file "stub.db"; }; +zone "static-stub-nomatch." {type primary; file "stub.db"; }; diff --git a/bin/tests/system/rpz/ns10/stub.db b/bin/tests/system/rpz/ns10/stub.db new file mode 100644 index 0000000..8ecac8c --- /dev/null +++ b/bin/tests/system/rpz/ns10/stub.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ rewrite responses from this zone + +$TTL 120 +@ SOA ns hostmaster.ns ( 1 3600 1200 604800 60 ) + NS ns +ns A 10.53.0.10 + +a3-1 A 10.53.99.99 + +a4-1 A 10.53.99.99 diff --git a/bin/tests/system/rpz/ns2/base-tld2s.db b/bin/tests/system/rpz/ns2/base-tld2s.db new file mode 100644 index 0000000..77114ec --- /dev/null +++ b/bin/tests/system/rpz/ns2/base-tld2s.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ rewrite responses from this signed zone + +$TTL 120 +@ SOA tld2s. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + NS ns + NS . ; check for RT 24985 +ns A 10.53.0.2 + + +a0-1 A 192.168.0.1 +a0-1-scname CNAME a0-1.tld2. + +a3-5 A 192.168.3.5 + +a7-2 A 192.168.7.2 diff --git a/bin/tests/system/rpz/ns2/bl.tld2.db.in b/bin/tests/system/rpz/ns2/bl.tld2.db.in new file mode 100644 index 0000000..25780b7 --- /dev/null +++ b/bin/tests/system/rpz/ns2/bl.tld2.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; primary for secondary RPZ zone + +$TTL 3600 +@ SOA rpz.tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +32.1.7.168.192.rpz-ip CNAME . diff --git a/bin/tests/system/rpz/ns2/blv2.tld2.db.in b/bin/tests/system/rpz/ns2/blv2.tld2.db.in new file mode 100644 index 0000000..123e1b4 --- /dev/null +++ b/bin/tests/system/rpz/ns2/blv2.tld2.db.in @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; primary for secondary RPZ zone + +$TTL 3600 +@ SOA rpz.tld2. hostmaster.ns.tld2. ( 2 3600 1200 604800 60 ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 diff --git a/bin/tests/system/rpz/ns2/blv3.tld2.db.in b/bin/tests/system/rpz/ns2/blv3.tld2.db.in new file mode 100644 index 0000000..b8ba587 --- /dev/null +++ b/bin/tests/system/rpz/ns2/blv3.tld2.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; primary for secondary RPZ zone + +$TTL 3600 +@ SOA rpz.tld2. hostmaster.ns.tld2. ( 3 3600 1200 604800 60 ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +32.1.7.168.192.rpz-ip CNAME . diff --git a/bin/tests/system/rpz/ns2/hints b/bin/tests/system/rpz/ns2/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns2/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns2/named.conf.in b/bin/tests/system/rpz/ns2/named.conf.in new file mode 100644 index 0000000..617edd9 --- /dev/null +++ b/bin/tests/system/rpz/ns2/named.conf.in @@ -0,0 +1,56 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify no; + minimal-responses no; + recursion yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; +zone "." { type hint; file "hints"; }; + +zone "tld2." {type primary; file "tld2.db";}; +zone "sub1.tld2." {type primary; file "tld2.db";}; +zone "subsub.sub1.tld2." {type primary; file "tld2.db";}; +zone "sub2.tld2." {type primary; file "tld2.db";}; +zone "subsub.sub2.tld2." {type primary; file "tld2.db";}; +zone "sub3.tld2." {type primary; file "tld2.db";}; +zone "subsub.sub3.tld2." {type primary; file "tld2.db";}; + +zone "tld2s." {type primary; file "tld2s.db";}; + +zone "bl.tld2." {type primary; file "bl.tld2.db"; + notify yes; notify-delay 0;}; + +# grafted on zones using stub and static-stub +zone "stub." {type primary; file "stub.db"; }; +zone "static-stub." {type primary; file "stub.db"; }; diff --git a/bin/tests/system/rpz/ns2/stub.db b/bin/tests/system/rpz/ns2/stub.db new file mode 100644 index 0000000..e4b8781 --- /dev/null +++ b/bin/tests/system/rpz/ns2/stub.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ rewrite responses from this zone + +$TTL 120 +@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + NS ns.sub1.tld2. + +a3-1 A 10.53.99.99 + +a4-1 A 10.53.99.99 diff --git a/bin/tests/system/rpz/ns2/tld2.db b/bin/tests/system/rpz/ns2/tld2.db new file mode 100644 index 0000000..c6f2556 --- /dev/null +++ b/bin/tests/system/rpz/ns2/tld2.db @@ -0,0 +1,125 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ rewrite responses from this zone + +$TTL 120 +@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + NS ns + NS . ; check for RT 24985 +ns A 10.53.0.2 + + +txt-only TXT "txt-only-tld2" + +a12 A 12.12.12.12 + AAAA 2001::12 + TXT "a12 tld2 text" +a12-cname CNAME a12 + +a0-1 A 192.168.0.1 + AAAA 2001:2::1 + TXT "a0-1 tld2 text" +a0-1-scname CNAME a0-1.tld2s. + + +a3-1 A 192.168.3.1 + AAAA 2001:2:3::1 + TXT "a3-1 tld2 text" + +a3-2 A 192.168.3.2 + AAAA 2001:2:3::2 + TXT "a3-2 tld2 text" + +a3-3 A 192.168.3.3 + AAAA 2001:2:3::3 + TXT "a3-3 tld2 text" + +a3-4 A 192.168.3.4 + AAAA 2001:2:3::4 + TXT "a3-4 tld2 text" + +a3-5 A 192.168.3.5 + AAAA 2001:2:3::5 + TXT "a3-5 tld2 text" + +a3-6 A 192.168.3.6 + AAAA 2001:2:3::6 + TXT "a3-6 tld2 text" + +a3-7 A 192.168.3.7 + AAAA 2001:2:3::7 + TXT "a3-7 tld2 text" + +a3-8 A 192.168.3.8 + AAAA 2001:2:3::8 + TXT "a3-8 tld2 text" + +a3-9 A 192.168.3.9 + AAAA 2001:2:3::9 + TXT "a3-9 tld2 text" + +a4-1 A 192.168.4.1 + AAAA 2001:2:4::1 + TXT "a4-1 tld2 text" +a4-1-aaaa AAAA 2001:2:4::1 + +a4-2 A 192.168.4.2 + AAAA 2001:2:4::2 + TXT "a4-2 tld2 text" +a4-2-cname CNAME a4-2 + +a4-3 A 192.168.4.3 + AAAA 2001:2:4::3 + TXT "a4-3 tld2 text" +a4-3-cname CNAME a4-3 + +a4-4 A 192.168.4.4 + AAAA 2001:2:4::4 + TXT "a4-4 tld2 text" + +a4-5 A 192.168.4.5 + AAAA 2001:2:4::5 + TXT "a4-5 tld2 text" +a4-5-cname CNAME a4-5 +a4-5-cname2 CNAME a4-5-cname +a4-5-cname3 CNAME a4-5-cname2 + +a4-6 A 192.168.4.6 + AAAA 2001:2:4::6 + TXT "a4-6 tld2 text" +a4-6-cname CNAME a4-6 +a4-6-cname2 CNAME a4-6-cname +a4-6-cname3 CNAME a4-6-cname2 + +a5-1-2 A 192.168.5.1 + A 192.168.5.2 + TXT "a5-1-2 tld2 text" + +a5-2 A 192.168.5.2 + TXT "a5-2 tld2 text" + +a5-3 A 192.168.5.3 + TXT "a5-3 tld2 text" + +a5-4 A 192.168.5.4 + TXT "a5-4 tld2 text" + +a6-1 A 192.168.6.1 + TXT "a6-1 tld2 text" +a6-2 A 192.168.6.2 + TXT "a6-2 tld2 text" + +a7-1 A 192.168.7.1 + TXT "a7-1 tld2 text" + +a7-2 A 192.168.7.2 + TXT "a7-2 tld2 text" diff --git a/bin/tests/system/rpz/ns3/base.db b/bin/tests/system/rpz/ns3/base.db new file mode 100644 index 0000000..f2f15a0 --- /dev/null +++ b/bin/tests/system/rpz/ns3/base.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA blx. hostmaster.ns.blx. ( 1 3600 1200 604800 60 ) + NS ns.tld3. + +; regression testing for some old crashes +example.com NS example.org. + +domain.com cname foobar.com diff --git a/bin/tests/system/rpz/ns3/broken.db.in b/bin/tests/system/rpz/ns3/broken.db.in new file mode 100644 index 0000000..80aa313 --- /dev/null +++ b/bin/tests/system/rpz/ns3/broken.db.in @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +; broken zone +foobar diff --git a/bin/tests/system/rpz/ns3/crash1 b/bin/tests/system/rpz/ns3/crash1 new file mode 100644 index 0000000..0c85191 --- /dev/null +++ b/bin/tests/system/rpz/ns3/crash1 @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + +; a bad zone that caused a crash related to dns_rdataset_disassociate() + +$TTL 120 +@ SOA crash1.tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + + NS tld2. diff --git a/bin/tests/system/rpz/ns3/crash2 b/bin/tests/system/rpz/ns3/crash2 new file mode 100644 index 0000000..ab70283 --- /dev/null +++ b/bin/tests/system/rpz/ns3/crash2 @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + +; a valid zone containing records that caused crashes + +$TTL 120 +@ SOA crash2.tld3. hostmaster.ns.tld3. ( 1 3600 1200 604800 60 ) + NS ns +ns A 10.53.0.3 + +; #24 in test1, crashed new ASSERT() in rbtdb.c +c1 A 172.16.1.24 + +; #16 in test2, crashed new ASSERT() in rbtdb.c +c2 A 172.16.1.16 diff --git a/bin/tests/system/rpz/ns3/hints b/bin/tests/system/rpz/ns3/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns3/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in new file mode 100644 index 0000000..f670b0c --- /dev/null +++ b/bin/tests/system/rpz/ns3/manual-update-rpz-2.db.in @@ -0,0 +1,22 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA bl-reload. hostmaster.ns.bl-reload. ( 2 3600 1200 604800 60 ) + NS ns.tld3. + +walled.tld2.bl-reload. 300 A 10.0.0.2 + diff --git a/bin/tests/system/rpz/ns3/manual-update-rpz.db.in b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in new file mode 100644 index 0000000..a823448 --- /dev/null +++ b/bin/tests/system/rpz/ns3/manual-update-rpz.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA manual-update-rpz. hostmaster.ns.manual-rpz-update. ( 1 3600 1200 604800 60 ) + NS ns.tld3. + +walled.tld2.manual-update-rpz. 300 A 10.0.0.1 diff --git a/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in b/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in new file mode 100644 index 0000000..c8548fc --- /dev/null +++ b/bin/tests/system/rpz/ns3/mixed-case-rpz-1.db.in @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA mixed-case-rpz. hostmaster.ns.mixed-case-rpz. ( 1 3600 1200 604800 60 ) + NS ns.tld3. + +A6-2.TLD2 CNAME . diff --git a/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in b/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in new file mode 100644 index 0000000..7d99c5a --- /dev/null +++ b/bin/tests/system/rpz/ns3/mixed-case-rpz-2.db.in @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA mixed-case-rpz. hostmaster.ns.mixed-case-rpz. ( 2 3600 1200 604800 60 ) + NS ns.tld3. + +a6-1.tld2 CNAME . +A6-2.TLD2 CNAME . diff --git a/bin/tests/system/rpz/ns3/named.conf.in b/bin/tests/system/rpz/ns3/named.conf.in new file mode 100644 index 0000000..51caae3 --- /dev/null +++ b/bin/tests/system/rpz/ns3/named.conf.in @@ -0,0 +1,163 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Main rpz test DNS server. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify yes; + minimal-responses no; + recursion yes; + dnssec-validation yes; + min-refresh-time 1; + min-retry-time 1; + + response-policy { + zone "fast-expire"; + zone "bl" max-policy-ttl 100; + zone "bl-2"; + zone "bl-given" policy given recursive-only yes; + zone "bl-passthru" policy passthru; + zone "bl-no-op" policy no-op; # obsolete for passthru + zone "bl-disabled" policy disabled; + zone "bl-nodata" policy nodata recursive-only no; + zone "bl-nxdomain" policy nxdomain; + zone "bl-cname" policy cname txt-only.tld2.; + zone "bl-wildcname" policy cname *.tld4.; + zone "bl-garden" policy cname a12.tld2.; + zone "bl-drop" policy drop; + zone "bl-tcp-only" policy tcp-only; + zone "bl.tld2"; + zone "manual-update-rpz" ede forged; + zone "mixed-case-rpz"; + } + add-soa yes + min-ns-dots 0 + qname-wait-recurse yes + min-update-interval 0 + nsdname-enable yes + nsip-enable yes + ; + + include "../dnsrps.conf"; + also-notify { 10.53.0.3 port @EXTRAPORT1@; }; + notify-delay 0; +}; + +trust-anchors { }; + +logging { category rpz { default_debug; }; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { type hint; file "hints"; }; + +zone "bl." {type primary; file "bl.db"; + allow-update {any;};}; +zone "bl-2." {type primary; file "bl-2.db"; + allow-update {any;};}; +zone "bl-given." {type primary; file "bl-given.db"; + allow-update {any;};}; +zone "bl-passthru." {type primary; file "bl-passthru.db"; + allow-update {any;};}; +zone "bl-no-op." {type primary; file "bl-no-op.db"; + allow-update {any;};}; +zone "bl-disabled." {type primary; file "bl-disabled.db"; + allow-update {any;};}; +zone "bl-nodata." {type primary; file "bl-nodata.db"; + allow-update {any;};}; +zone "bl-nxdomain." {type primary; file "bl-nxdomain.db"; + allow-update {any;};}; +zone "bl-cname." {type primary; file "bl-cname.db"; + allow-update {any;};}; +zone "bl-wildcname." {type primary; file "bl-wildcname.db"; + allow-update {any;};}; +zone "bl-garden." {type primary; file "bl-garden.db"; + allow-update {any;};}; +zone "bl-drop." {type primary; file "bl-drop.db"; + allow-update {any;};}; +zone "bl-tcp-only." {type primary; file "bl-tcp-only.db"; + allow-update {any;};}; + +zone "bl.tld2." {type secondary; file "bl.tld2.db"; primaries {10.53.0.2;}; + request-ixfr no; masterfile-format text;}; + +zone "crash1.tld2" {type primary; file "crash1"; notify no;}; +zone "crash2.tld3." {type primary; file "crash2"; notify no;}; + +zone "manual-update-rpz." { + type primary; + file "manual-update-rpz.db"; + notify no; +}; + +zone "mixed-case-rpz." { + type primary; + file "mixed-case-rpz.db"; + notify no; +}; + +zone "fast-expire." { + type secondary; + file "fast-expire.db"; + primaries { 10.53.0.5; }; + notify no; +}; + +zone "stub." { + type stub; + primaries { 10.53.0.2; }; +}; + +zone "static-stub." { + type static-stub; + server-addresses { 10.53.0.2; }; +}; + +zone "stub-nomatch." { + type stub; + primaries { 10.53.0.10; }; +}; + +zone "static-stub-nomatch." { + type static-stub; + server-addresses { 10.53.0.10; }; +}; + +# A faulty dlz configuration to check if named with response policy zones +# survives a certain class of failed configuration attempts (see GL #3880). +# "dlz" is used because the dlz processing code is located in an ideal place in +# the view configuration function for the test to cover the view reverting code. +# The "BAD" comments below are necessary, because they will be removed using +# 'sed' by tests.sh in order to activate the faulty configuration. +#BAD dlz "bad-dlz" { +#BAD database "dlopen bad-dlz.so example.org"; +#BAD }; diff --git a/bin/tests/system/rpz/ns4/hints b/bin/tests/system/rpz/ns4/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns4/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns4/named.conf.in b/bin/tests/system/rpz/ns4/named.conf.in new file mode 100644 index 0000000..a5ef523 --- /dev/null +++ b/bin/tests/system/rpz/ns4/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + session-keyfile "session.key"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify no; + minimal-responses no; + recursion yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; +zone "." { type hint; file "hints"; }; + +zone "tld4." {type primary; file "tld4.db";}; +zone "sub1.tld4." {type primary; file "tld4.db";}; +zone "subsub.sub1.tld4." {type primary; file "tld4.db";}; +zone "sub2.tld4." {type primary; file "tld4.db";}; +zone "subsub.sub2.tld4." {type primary; file "tld4.db";}; diff --git a/bin/tests/system/rpz/ns4/tld4.db b/bin/tests/system/rpz/ns4/tld4.db new file mode 100644 index 0000000..fca419c --- /dev/null +++ b/bin/tests/system/rpz/ns4/tld4.db @@ -0,0 +1,66 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ rewrite responses from this zone + +$TTL 120 +@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 ) + NS ns +ns A 10.53.0.4 + + +txt-only TXT "txt-only-tld4" + +a14 A 14.14.14.14 + AAAA 2001::14 + TXT "a14 text" +a14-cname CNAME a14 + +a0-1 A 192.168.0.1 + AAAA 2001:2::1 + TXT "a0-1 text" + +a3-1 A 192.168.3.1 + AAAA 2001:2:3::1 + TXT "a3-1 text" + +a3-2 A 192.168.3.2 + AAAA 2001:2:3::2 + TXT "a3-2 text" + +a4-1 A 192.168.4.1 + AAAA 2001:2:4::1 + TXT "a4-1 text" +a4-1-aaaa AAAA 2001:2:4::1 + +a4-2 A 192.168.4.2 + AAAA 2001:2:4::2 + TXT "a4-2 text" +a4-2-cname CNAME a4-2 + +a4-3 A 192.168.4.3 + AAAA 2001:2:4::3 + TXT "a4-3 text" +a4-3-cname CNAME a4-3 + +a4-4 A 192.168.4.4 + AAAA 2001:2:4::4 + TXT "a4-4 text" + +a3-6.tld2 A 56.56.56.56 + +a3-7.sub1.tld2 A 57.57.57.57 + +a3-8.tld2 A 58.58.58.58 + +a3-9.sub9.tld2 A 59.59.59.59 + +a3-10.tld2 A 60.60.60.60 diff --git a/bin/tests/system/rpz/ns5/empty.db.in b/bin/tests/system/rpz/ns5/empty.db.in new file mode 100644 index 0000000..a7e9144 --- /dev/null +++ b/bin/tests/system/rpz/ns5/empty.db.in @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 ) + NS . diff --git a/bin/tests/system/rpz/ns5/expire.conf.in b/bin/tests/system/rpz/ns5/expire.conf.in new file mode 100644 index 0000000..4c1c228 --- /dev/null +++ b/bin/tests/system/rpz/ns5/expire.conf.in @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +zone "fast-expire." { + type primary; + file "fast-expire.db"; + allow-transfer { any; }; + notify no; +}; diff --git a/bin/tests/system/rpz/ns5/fast-expire.db.in b/bin/tests/system/rpz/ns5/fast-expire.db.in new file mode 100644 index 0000000..cb2672e --- /dev/null +++ b/bin/tests/system/rpz/ns5/fast-expire.db.in @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ SOA fast-expire. hostmaster ( + 1 3 1 5 60 + ) + NS ns.tld3. + +expired.fast-expire. A 10.0.0.10 diff --git a/bin/tests/system/rpz/ns5/hints b/bin/tests/system/rpz/ns5/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns5/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns5/named.args b/bin/tests/system/rpz/ns5/named.args new file mode 100644 index 0000000..a872a98 --- /dev/null +++ b/bin/tests/system/rpz/ns5/named.args @@ -0,0 +1,2 @@ +# run the performance test close to real life +-c named.conf -D rpz-ns5 -gd3 -T maxcachesize=2097152 diff --git a/bin/tests/system/rpz/ns5/named.conf.in b/bin/tests/system/rpz/ns5/named.conf.in new file mode 100644 index 0000000..e24d80e --- /dev/null +++ b/bin/tests/system/rpz/ns5/named.conf.in @@ -0,0 +1,92 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test rpz performance. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + ixfr-from-differences yes; + notify-delay 0; + notify yes; + minimal-responses no; + recursion yes; + dnssec-validation yes; + + # turn rpz on or off + include "rpz-switch"; + + include "../dnsrps.conf"; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; +zone "." {type hint; file "hints"; }; + +zone "tld5." {type primary; file "tld5.db"; }; +zone "example.tld5." {type primary; file "example.db"; }; + +zone "bl0." {type primary; file "bl.db"; }; +zone "bl1." {type primary; file "bl.db"; }; +zone "bl2." {type primary; file "bl.db"; }; +zone "bl3." {type primary; file "bl.db"; }; +zone "bl4." {type primary; file "bl.db"; }; +zone "bl5." {type primary; file "bl.db"; }; +zone "bl6." {type primary; file "bl.db"; }; +zone "bl7." {type primary; file "bl.db"; }; +zone "bl8." {type primary; file "bl.db"; }; +zone "bl9." {type primary; file "bl.db"; }; +zone "bl10." {type primary; file "bl.db"; }; +zone "bl11." {type primary; file "bl.db"; }; +zone "bl12." {type primary; file "bl.db"; }; +zone "bl13." {type primary; file "bl.db"; }; +zone "bl14." {type primary; file "bl.db"; }; +zone "bl15." {type primary; file "bl.db"; }; +zone "bl16." {type primary; file "bl.db"; }; +zone "bl17." {type primary; file "bl.db"; }; +zone "bl18." {type primary; file "bl.db"; }; +zone "bl19." {type primary; file "bl.db"; }; + +zone "policy1" { + type primary; + file "empty.db"; + also-notify { 10.53.0.6; }; + allow-update { any; }; + allow-transfer { any; }; +}; + +zone "policy2" { + type primary; + file "policy2.db"; + allow-update { any; }; + allow-transfer { any; }; +}; + +include "expire.conf"; diff --git a/bin/tests/system/rpz/ns5/tld5.db b/bin/tests/system/rpz/ns5/tld5.db new file mode 100644 index 0000000..b75e72f --- /dev/null +++ b/bin/tests/system/rpz/ns5/tld5.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ performance test + +$TTL 120 +@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 ) + NS ns + NS ns1 + NS ns2 + NS ns3 +ns A 10.53.0.5 +ns1 A 10.53.0.5 +ns2 A 10.53.0.5 +ns3 A 10.53.0.5 + + +$ORIGIN example.tld5. +example.tld5. NS ns + NS ns1 +ns A 10.53.0.5 +ns1 A 10.53.0.5 + +as-ns TXT "rewritten with ip-as-ns and qname-as-ns" diff --git a/bin/tests/system/rpz/ns6/bl.tld2s.db.in b/bin/tests/system/rpz/ns6/bl.tld2s.db.in new file mode 100644 index 0000000..4538050 --- /dev/null +++ b/bin/tests/system/rpz/ns6/bl.tld2s.db.in @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ SOA rpz.tld2. hostmaster.ns.tld2. ( 3 3600 1200 604800 60 ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +32.2.7.168.192.rpz-ip A 1.1.1.1 + AAAA ::1 diff --git a/bin/tests/system/rpz/ns6/hints b/bin/tests/system/rpz/ns6/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns6/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns6/named.conf.in b/bin/tests/system/rpz/ns6/named.conf.in new file mode 100644 index 0000000..09101ee --- /dev/null +++ b/bin/tests/system/rpz/ns6/named.conf.in @@ -0,0 +1,68 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + forward only; + forwarders { 10.53.0.3; }; + minimal-responses no; + recursion yes; + dnssec-validation yes; + qname-minimization disabled; + + response-policy { + zone "policy1" min-update-interval 0; + zone "bl.tld2s" policy given; + } qname-wait-recurse yes + // add-soa yes # leave add-soa as default for unset test + nsip-enable yes + nsdname-enable yes; + + include "../dnsrps.conf"; +}; + +logging { category rpz { default_debug; }; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; + +zone "policy1" { + type secondary; + primaries { 10.53.0.5; }; + file "empty.db"; + also-notify { 10.53.0.3 port @EXTRAPORT1@; }; + notify-delay 0; + allow-transfer { any; }; +}; + +zone "bl.tld2s." { + type primary; + file "bl.tld2s.db"; +}; diff --git a/bin/tests/system/rpz/ns7/hints b/bin/tests/system/rpz/ns7/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns7/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns7/named.conf.in b/bin/tests/system/rpz/ns7/named.conf.in new file mode 100644 index 0000000..1eb209e --- /dev/null +++ b/bin/tests/system/rpz/ns7/named.conf.in @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.7; + notify-source 10.53.0.7; + transfer-source 10.53.0.7; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.7; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + minimal-responses no; + recursion yes; + dnssec-validation yes; + + response-policy { + zone "policy2" add-soa no ede none; + } qname-wait-recurse no + nsip-enable yes + nsdname-enable yes + min-update-interval 0; + + include "../dnsrps.conf"; +}; + +logging { category rpz { default_debug; }; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "../trusted.conf"; + +zone "policy2" { + type secondary; + primaries { 10.53.0.5; }; + file "policy2.db"; + also-notify { 10.53.0.3 port @EXTRAPORT1@; }; + notify-delay 0; + allow-transfer { any; }; + request-ixfr no; // force axfr on rndc reload +}; diff --git a/bin/tests/system/rpz/ns8/hints b/bin/tests/system/rpz/ns8/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns8/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns8/manual-update-rpz.db.in b/bin/tests/system/rpz/ns8/manual-update-rpz.db.in new file mode 100644 index 0000000..a823448 --- /dev/null +++ b/bin/tests/system/rpz/ns8/manual-update-rpz.db.in @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; RPZ test +; This basic file is copied to several zone files before being used. +; Its contents are also changed with nsupdate + + +$TTL 300 +@ SOA manual-update-rpz. hostmaster.ns.manual-rpz-update. ( 1 3600 1200 604800 60 ) + NS ns.tld3. + +walled.tld2.manual-update-rpz. 300 A 10.0.0.1 diff --git a/bin/tests/system/rpz/ns8/named.conf.in b/bin/tests/system/rpz/ns8/named.conf.in new file mode 100644 index 0000000..de4b2a4 --- /dev/null +++ b/bin/tests/system/rpz/ns8/named.conf.in @@ -0,0 +1,69 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Main rpz test DNS server. + */ + +options { + query-source address 10.53.0.8; + notify-source 10.53.0.8; + transfer-source 10.53.0.8; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.8; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify yes; + minimal-responses no; + recursion yes; + dnssec-validation yes; + + response-policy { + zone "manual-update-rpz"; + } + // add-soa yes // do not set testing default mode + min-ns-dots 0 + qname-wait-recurse yes + min-update-interval 0 + nsdname-enable yes + nsip-enable yes + ; + + include "../dnsrps.conf"; + also-notify { 10.53.0.8 port @EXTRAPORT1@; }; + notify-delay 0; +}; + +trust-anchors { }; + +logging { category rpz { default_debug; }; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { type hint; file "hints"; }; + +zone "manual-update-rpz." { + type primary; + file "manual-update-rpz.db"; + notify no; +}; diff --git a/bin/tests/system/rpz/ns9/hints b/bin/tests/system/rpz/ns9/hints new file mode 100644 index 0000000..b657c39 --- /dev/null +++ b/bin/tests/system/rpz/ns9/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 120 NS ns. +ns. 120 A 10.53.0.1 diff --git a/bin/tests/system/rpz/ns9/named.conf.in b/bin/tests/system/rpz/ns9/named.conf.in new file mode 100644 index 0000000..5740193 --- /dev/null +++ b/bin/tests/system/rpz/ns9/named.conf.in @@ -0,0 +1,63 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * DNS64 / RPZ server. + */ + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + statistics-file "named.stats"; + session-keyfile "session.key"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + notify yes; + minimal-responses no; + recursion yes; + dnssec-validation yes; + dns64-server "example.localdomain."; + dns64 64:ff9b::/96 { }; + response-policy { + zone "rpz"; + } + qname-wait-recurse no ; + + include "../dnsrps.conf"; + notify-delay 0; +}; + +trust-anchors { }; + +logging { category rpz { default_debug; }; }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { type hint; file "hints"; }; + +zone "rpz." { + type primary; + file "rpz.db"; + notify no; +}; diff --git a/bin/tests/system/rpz/ns9/rpz.db b/bin/tests/system/rpz/ns9/rpz.db new file mode 100644 index 0000000..7767987 --- /dev/null +++ b/bin/tests/system/rpz/ns9/rpz.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 28800 +rpz. IN SOA rpz. hostmaster.rpz. 6 10800 3600 2419200 900 +rpz. IN NS . +a-only.example CNAME *. +no-a-no-aaaa.example CNAME *. +a-plus-aaaa.example CNAME *. diff --git a/bin/tests/system/rpz/setup.sh b/bin/tests/system/rpz/setup.sh new file mode 100644 index 0000000..4aaa466 --- /dev/null +++ b/bin/tests/system/rpz/setup.sh @@ -0,0 +1,120 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# touch dnsrps-off to not test with DNSRPS + +set -e + +. ../conf.sh + +for dir in ns*; do + touch $dir/named.run + nextpart $dir/named.run >/dev/null +done + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns8/named.conf.in ns8/named.conf +copy_setports ns9/named.conf.in ns9/named.conf +copy_setports ns10/named.conf.in ns10/named.conf + +copy_setports dnsrps.zones.in dnsrps.zones + +touch dnsrps.conf +touch dnsrps.cache + +# set up test policy zones. +# bl is the main test zone +# bl-2 is used to check competing zones. +# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden, +# drop,tcp-only} are used to check policy overrides in named.conf. +# NO-OP is an obsolete synonym for PASSHTRU +for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden -drop -tcp-only; do + sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db +done +# bl zones are dynamically updated. Add one zone that is updated manually. +cp ns3/manual-update-rpz.db.in ns3/manual-update-rpz.db +cp ns8/manual-update-rpz.db.in ns8/manual-update-rpz.db + +cp ns3/mixed-case-rpz-1.db.in ns3/mixed-case-rpz.db + +# a zone that expires quickly and then can't be refreshed +cp ns5/fast-expire.db.in ns5/fast-expire.db +cp ns5/expire.conf.in ns5/expire.conf + +# $1=directory +# $2=domain name +# $3=input zone file +# $4=output file +signzone() { + KEYNAME=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -K $1 $2) + cat $1/$3 $1/$KEYNAME.key >$1/tmp + $SIGNER -P -K $1 -o $2 -f $1/$4 $1/tmp >/dev/null + sed -n -e 's/\(.*\) IN DNSKEY \([0-9]\{1,\} [0-9]\{1,\} [0-9]\{1,\}\) \(.*\)/trust-anchors {"\1" static-key \2 "\3";};/p' $1/$KEYNAME.key >>trusted.conf + DSFILENAME=dsset-${2}. + rm $DSFILENAME $1/tmp +} +signzone ns2 tld2s base-tld2s.db tld2s.db + +# Performance and a few other checks. +cat <ns5/rpz-switch +response-policy { + zone "bl0"; zone "bl1"; zone "bl2"; zone "bl3"; zone "bl4"; + zone "bl5"; zone "bl6"; zone "bl7"; zone "bl8"; zone "bl9"; + zone "bl10"; zone "bl11"; zone "bl12"; zone "bl13"; zone "bl14"; + zone "bl15"; zone "bl16"; zone "bl17"; zone "bl18"; zone "bl19"; + } recursive-only no + qname-wait-recurse no + nsip-enable yes + nsdname-enable yes + max-policy-ttl 90 + break-dnssec yes + ; +EOF + +cat <ns5/example.db +\$TTL 300 +@ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 ) + NS ns + NS ns1 +ns A 10.53.0.5 +ns1 A 10.53.0.5 +EOF + +cat <ns5/bl.db +\$TTL 300 +@ SOA . hostmaster.ns.blperf. ( 1 3600 1200 604800 60 ) + NS ns.tld5. + +; for "qname-wait-recurse no" in #35 test1 +x.servfail A 35.35.35.35 +; for "recursive-only no" in #8 test5 +a3-5.tld2 CNAME . +; for "break-dnssec" in #9 & #10 test5 +a3-5.tld2s CNAME . +; for "max-policy-ttl 90" in #17 test5 +a3-17.tld2 500 A 17.17.17.17 + +; dummy NSDNAME policy to trigger lookups +ns1.x.rpz-nsdname CNAME . +EOF + +cp ns2/bl.tld2.db.in ns2/bl.tld2.db +cp ns5/empty.db.in ns5/empty.db +cp ns5/empty.db.in ns5/policy2.db +cp ns6/bl.tld2s.db.in ns6/bl.tld2s.db diff --git a/bin/tests/system/rpz/test1 b/bin/tests/system/rpz/test1 new file mode 100644 index 0000000..3dc0375 --- /dev/null +++ b/bin/tests/system/rpz/test1 @@ -0,0 +1,99 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +server 10.53.0.3 @PORT@ + +; QNAME tests + +; NXDOMAIN +; 2, 25 +update add a0-1.tld2.bl. 300 CNAME . +; NODATA +; 3 +update add a3-1.tld2.bl. 300 CNAME *. +; and no assert-botch +; 4, 5 +update add a3-2.tld2.bl. 300 DNAME example.com. +; +; NXDOMAIN for a4-2-cname.tld2 via its target a4-2.tld2. +; 6 and 7 +update add a4-2.tld2.bl 300 CNAME . +; 8 +; NODATA for a4-3-cname.tld2 via its target a4-3.tld2. +update add a4-3.tld2.bl 300 CNAME *. +; +; replace the A for a4-1.sub1.tld2 with 12.12.12.12 +; 9 +update add a4-1.sub1.tld2.bl. 300 A 12.12.12.12 +; +; replace the A for *.sub2.tld2 with 12.12.12.12 +; 10 +update add a4-1.sub2.tld2.bl. 300 A 12.12.12.12 +; +; replace NXDOMAIN for {nxc1,nxc2}.sub1.tld2 with 12.12.12.12 using CNAMEs +; 11 +update add nxc1.sub1.tld2.bl. 300 CNAME a12.tld2. +; 12 +update add nxc2.sub1.tld2.bl. 300 CNAME a12-cname.tld2. +; +; prefer the first conflicting zone +; 13 +update add a4-4.tld2.bl. 300 A 127.4.4.1 +update add a6-1.tld2.bl. 300 CNAME a6-1.tld2. +update add a6-2.tld2.bl. 300 A 127.6.2.1 +update add a6-1.tld2.bl. 300 A 127.6.1.1 +update add a6-2.tld2.bl. 300 CNAME a6-2.tld2. +send +update add a4-4.tld2.bl-2. 300 A 127.4.4.2 +send + +; wildcard CNAME +; 16 +update add a3-6.tld2.bl. 300 CNAME *.tld4. +; 17 +update add *.sub1.tld2.bl. 300 CNAME *.tld4. +; CNAME chain +; 18 +update add a4-5.tld2.bl. 300 A 127.0.0.16 +; stop at first hit in CNAME chain +; 19 +update add a4-6.tld2.bl. 300 CNAME . +update add a4-6-cname.tld2.bl. 300 A 127.0.0.17 +; no change instead of NXDOMAIN because +norecurse +; 20 +update add a5-2.tld2.bl. 300 CNAME . +; no change instead of NODATA because +norecurse +; 21 +update add a5-3.tld2.bl. 300 CNAME *. +; 22, 23 +update add a5-4.tld2.bl. 300 DNAME example.com. +; +; assert in rbtdb.c +; 24 +update add c1.crash2.tld3.bl. 300 CNAME . +; DO=1 without signatures, DO=0 with signatures are rewritten +; 26 - 27 +update add a0-1.tld2s.bl. 300 CNAME . +; 32 +update add a3-8.tld2.bl. 300 CNAME rpz-drop. +; 33 +update add a3-9.tld2.bl. 300 CNAME rpz-tcp-only. +; 34 qname-wait-recurse yes +update add x.servfail.bl. 300 A 127.0.0.34 +send diff --git a/bin/tests/system/rpz/test2 b/bin/tests/system/rpz/test2 new file mode 100644 index 0000000..ad71e3a --- /dev/null +++ b/bin/tests/system/rpz/test2 @@ -0,0 +1,77 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' +; CNAME targets are absolute even without trailing "." + +; IP tests + +server 10.53.0.3 @PORT@ + +; NODATA a3-1.tld2 +; 1 +update add 32.1.3.168.192.rpz-ip.bl 300 CNAME *. +; +; NXDOMAIN for 192.168.4.0/24, the network of a4-1.tld2 and a4-2.tld2 +; 4 +update add 24.0.4.168.192.rpz-ip.bl 300 CNAME . +; +; old passthru in NXDOMAIN CIDR block to leave a4-1.tld2 unchanged +; 3 +update add 32.1.4.168.192.rpz-ip.bl 300 CNAME 32.1.4.168.192 +; +; NODATA for a4-3.tld2 +; 8 +update add 32.3.4.168.192.rpz-ip.bl 300 CNAME *. +; +; NXDOMAIN for IPv6 a3-1.tld2 +; 9 +update add 128.1.zz.3.2.2001.rpz-ip.bl 300 CNAME . +; +; apply the policy with the lexically smaller trigger address of 192.168.5.1 +; to an RRset of more than one A RR +; 11 +update add 32.1.5.168.192.rpz-ip.bl 300 A 127.0.0.1 +update add 32.2.5.168.192.rpz-ip.bl 300 A 127.0.0.2 +; +; prefer first conflicting IP zone for a5-3.tld2 +; 12 +update add 32.3.5.168.192.rpz-ip.bl 300 A 127.0.0.1 +send +update add 32.3.5.168.192.rpz-ip.bl-2 300 A 127.0.0.2 +send + +; prefer QNAME to IP for a5-4.tld2 +; 13, 14 +update add 32.4.5.168.192.rpz-ip.bl 300 CNAME a12.tld2. +update add a5-4.tld2.bl 300 CNAME a14.tld4. +; +; poke hole in NXDOMAIN CIDR block to leave a4-4.tld2 unchanged +; 15 +update add 32.4.4.168.192.rpz-ip.bl 300 CNAME rpz-passthru. +; +; assert in rbtdb.c +; 16 +update add 32.16.1.16.172.rpz-ip.bl 300 CNAME . +send +update add c2.crash2.tld3.bl-2 300 A 127.0.0.16 +send + +; client-IP address trigger +; 17 +update add 32.1.0.53.10.rpz-client-ip.bl 300 A 127.0.0.17 +send diff --git a/bin/tests/system/rpz/test3 b/bin/tests/system/rpz/test3 new file mode 100644 index 0000000..222b757 --- /dev/null +++ b/bin/tests/system/rpz/test3 @@ -0,0 +1,47 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +; NSDNAME tests + +server 10.53.0.3 @PORT@ + +; 3, 4, 5 +; NXDOMAIN for *.sub1.tld2 by NSDNAME +update add *.sub1.tld2.rpz-nsdname.bl. 300 CNAME . +; +; 6 +; walled garden for *.sub2.tld2 +update add *.sub2.tld2.rpz-nsdname.bl. 300 CNAME a12-cname.tld2. +; +; 7, 8 +; exempt a3-2.tld2 and anything in 192.168.0.0/24 +; also checks that IP policies are preferred over NSDNAME policies +update add a3-2.tld2.bl 300 CNAME a3-2.tld2. +update add 24.0.0.168.192.rpz-ip.bl 300 CNAME 24.0.0.168.192. +; +; 9 +; prefer QNAME policy to NSDNAME policy +update add a4-1.tld2.bl. 300 A 12.12.12.12 +; 10 +; prefer policy for largest NS name +update add ns.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.1 +update add ns.subsub.sub3.tld2.rpz-nsdname.bl. 300 A 127.0.0.2 + +; ip-as-qname rewrites all of tld5 +update add ns.tld5.bl. 300 A 12.12.12.12 +send diff --git a/bin/tests/system/rpz/test4 b/bin/tests/system/rpz/test4 new file mode 100644 index 0000000..7b95dd3 --- /dev/null +++ b/bin/tests/system/rpz/test4 @@ -0,0 +1,36 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +; NSIP tests + +server 10.53.0.3 @PORT@ + +; NXDOMAIN for all of tld2 based on its server IP address +update add 32.2.0.53.10.rpz-nsip.bl. 300 CNAME . +; +; exempt a3-2.tld2 and anything in 192.168.0.0/24 +; also checks that IP policies are preferred over NSIP policies +update add a3-2.tld2.bl 300 CNAME a3-2.tld2. +update add 24.0.0.168.192.rpz-ip.bl 300 CNAME 24.0.0.168.192. +; +; prefer NSIP policy to NSDNAME policy +update add ns.tld2.rpz-nsdname.bl. 300 CNAME 10.0.0.1 + +; ip-as-ns rewrites all of tld5 +update add 32.5.0.53.10.rpz-ip.bl. 300 A 12.12.12.12 +send diff --git a/bin/tests/system/rpz/test4a b/bin/tests/system/rpz/test4a new file mode 100644 index 0000000..83a175d --- /dev/null +++ b/bin/tests/system/rpz/test4a @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +; walled-garden NSIP tests + +server 10.53.0.3 @PORT@ + +; rewrite all of tld2 based on its server IP address +update add 32.2.0.53.10.rpz-nsip.bl. 300 A 41.41.41.41 +update add 32.2.0.53.10.rpz-nsip.bl. 300 AAAA 2041::41 +update add 32.2.0.53.10.rpz-nsip.bl. 300 TXT "NSIP walled garden" +send diff --git a/bin/tests/system/rpz/test5 b/bin/tests/system/rpz/test5 new file mode 100644 index 0000000..f30a6be --- /dev/null +++ b/bin/tests/system/rpz/test5 @@ -0,0 +1,60 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +; the policies or replacements specified in ns3/named.conf override these + +server 10.53.0.3 @PORT@ + +; 1 +update add a3-1.tld2.bl-given. 300 A 127.0.0.1 +send +; 2 +update add a3-2.tld2.bl-passthru. 300 A 127.0.0.2 +send +; 3 +update add a3-3.tld2.bl-no-op. 300 A 127.0.0.3 +send +; 4 +update add a3-4.tld2.bl-disabled. 300 A 127.0.0.4 +send +; 5 - 7 +update add a3-5.tld2.bl-nodata. 300 A 127.0.0.5 +send +; 11 +update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.11 +send +; 12 +update add a3-7.tld2.bl-cname. 300 A 127.0.0.12 +send +; 13 +update add a3-8.tld2.bl-wildcname. 300 A 127.0.0.13 +; 14 +update add *.sub9.tld2.bl-wildcname. 300 A 127.0.1.14 +send +; 15 +update add a3-15.tld2.bl-garden. 300 A 127.0.0.15 +send +; 16 +update add a3-16.tld2.bl. 300 A 127.0.0.16 +send +; 18 +update add a3-18.tld2.bl-drop. 300 A 127.0.0.18 +send +; 19 +update add a3-19.tld2.bl-tcp-only. 300 A 127.0.0.19 +send diff --git a/bin/tests/system/rpz/test6 b/bin/tests/system/rpz/test6 new file mode 100644 index 0000000..e5c2381 --- /dev/null +++ b/bin/tests/system/rpz/test6 @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + + + +; Use comment lines instead of blank lines to combine update requests into +; single requests +; Separate update requests for distinct TLDs with blank lines or 'send' +; End the file with a blank line or 'send' + +server 10.53.0.3 @PORT@ + +; Poke the radix tree a little. +update add 128.1111.2222.3333.4444.5555.6666.7777.8888.rpz-ip.bl. 300 CNAME . +update add 128.1111.2222.3333.4444.5555.6666.zz.rpz-ip.bl. 300 CNAME . +update add 128.1111.2222.3333.4444.5555.zz.8888.rpz-ip.bl. 300 CNAME . +update add 128.1111.2222.3333.4444.zz.8888.rpz-ip.bl. 300 CNAME . +update add 128.zz.3333.4444.0.0.8888.rpz-ip.bl. 300 CNAME . +update add 128.zz.3333.4444.0.7777.8888.rpz-ip.bl. 300 CNAME . +update add 128.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME . +update add 127.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME . +; +; +; regression testing for some old crashes +update add redirect.bl. 300 A 127.0.0.1 +update add *.redirect.bl. 300 A 127.0.0.1 +update add *.credirect.bl. 300 CNAME google.com. +; +send diff --git a/bin/tests/system/rpz/testlib/Makefile.am b/bin/tests/system/rpz/testlib/Makefile.am new file mode 100644 index 0000000..6271fdb --- /dev/null +++ b/bin/tests/system/rpz/testlib/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/Makefile.top + +AM_CPPFLAGS += \ + $(LIBISC_CFLAGS) \ + $(LIBDNS_CFLAGS) + +AM_CFLAGS += -Wall -pedantic + +noinst_LTLIBRARIES = libdummyrpz.la +libdummyrpz_la_SOURCES= dummylib.c test-data.c trpz.h test-data.h +libdummyrpz_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) +LDADD += -lpthread $(DLOPEN_LIBS) diff --git a/bin/tests/system/rpz/testlib/Makefile.in b/bin/tests/system/rpz/testlib/Makefile.in new file mode 100644 index 0000000..e138b58 --- /dev/null +++ b/bin/tests/system/rpz/testlib/Makefile.in @@ -0,0 +1,787 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Hey Emacs, this is -*- makefile-automake -*- file! +# vim: filetype=automake + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HOST_MACOS_TRUE@am__append_1 = \ +@HOST_MACOS_TRUE@ -Wl,-flat_namespace + +subdir = bin/tests/system/rpz/testlib +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_link_flag.m4 \ + $(top_srcdir)/m4/ax_check_openssl.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_jemalloc.m4 \ + $(top_srcdir)/m4/ax_lib_lmdb.m4 \ + $(top_srcdir)/m4/ax_posix_shell.m4 \ + $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_restore_flags.m4 \ + $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/pkg-modversion.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdummyrpz_la_LIBADD = +am_libdummyrpz_la_OBJECTS = dummylib.lo test-data.lo +libdummyrpz_la_OBJECTS = $(am_libdummyrpz_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libdummyrpz_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libdummyrpz_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/dummylib.Plo \ + ./$(DEPDIR)/test-data.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libdummyrpz_la_SOURCES) +DIST_SOURCES = $(libdummyrpz_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = test-recursive unit-recursive \ + doc-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/Makefile.top \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CURL = @CURL@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DEVELOPER_MODE = @DEVELOPER_MODE@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DNSTAP_CFLAGS = @DNSTAP_CFLAGS@ +DNSTAP_LIBS = @DNSTAP_LIBS@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FSTRM_CAPTURE = @FSTRM_CAPTURE@ +FUZZ_LDFLAGS = @FUZZ_LDFLAGS@ +FUZZ_LOG_COMPILER = @FUZZ_LOG_COMPILER@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JEMALLOC_CFLAGS = @JEMALLOC_CFLAGS@ +JEMALLOC_LIBS = @JEMALLOC_LIBS@ +JEMALLOC_VERSION = @JEMALLOC_VERSION@ +JSON_C_CFLAGS = @JSON_C_CFLAGS@ +JSON_C_LIBS = @JSON_C_LIBS@ +KRB5_CFLAGS = @KRB5_CFLAGS@ +KRB5_CONFIG = @KRB5_CONFIG@ +KRB5_LIBS = @KRB5_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBCAP_CFLAGS = @LIBCAP_CFLAGS@ +LIBCAP_LIBS = @LIBCAP_LIBS@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBNGHTTP2_CFLAGS = @LIBNGHTTP2_CFLAGS@ +LIBNGHTTP2_LIBS = @LIBNGHTTP2_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ +LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBURCU_CFLAGS = @LIBURCU_CFLAGS@ +LIBURCU_LIBS = @LIBURCU_LIBS@ +LIBUV_CFLAGS = @LIBUV_CFLAGS@ +LIBUV_LIBS = @LIBUV_LIBS@ +LIBUV_VERSION = @LIBUV_VERSION@ +LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ +LIBXML2_LIBS = @LIBXML2_LIBS@ +LIPO = @LIPO@ +LMDB_CFLAGS = @LMDB_CFLAGS@ +LMDB_LIBS = @LMDB_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MAXMINDDB_CFLAGS = @MAXMINDDB_CFLAGS@ +MAXMINDDB_LIBS = @MAXMINDDB_LIBS@ +MAXMINDDB_PREFIX = @MAXMINDDB_PREFIX@ +MKDIR_P = @MKDIR_P@ +NC = @NC@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +OPENSSL_VERSION = @OPENSSL_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROTOC_C = @PROTOC_C@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_CXX = @PTHREAD_CXX@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTEST = @PYTEST@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RCU_VERSION = @RCU_VERSION@ +READLINE_CFLAGS = @READLINE_CFLAGS@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE_DATE = @RELEASE_DATE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SPHINX_BUILD = @SPHINX_BUILD@ +STD_CFLAGS = @STD_CFLAGS@ +STD_CPPFLAGS = @STD_CPPFLAGS@ +STD_LDFLAGS = @STD_LDFLAGS@ +STRIP = @STRIP@ +TEST_CFLAGS = @TEST_CFLAGS@ +VERSION = @VERSION@ +XSLTPROC = @XSLTPROC@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4 +AM_CFLAGS = $(STD_CFLAGS) -Wall -pedantic +AM_CPPFLAGS = $(STD_CPPFLAGS) -include $(top_builddir)/config.h \ + -I$(srcdir)/include $(LIBISC_CFLAGS) $(LIBDNS_CFLAGS) +AM_LDFLAGS = $(STD_LDFLAGS) $(am__append_1) +LDADD = -lpthread $(DLOPEN_LIBS) +BUILT_SOURCES = +CLEANFILES = +@HAVE_JEMALLOC_FALSE@LIBISC_CFLAGS = -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_FALSE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_TRUE@LIBISC_CFLAGS = $(JEMALLOC_CFLAGS) \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_srcdir)/lib/isc/include \ +@HAVE_JEMALLOC_TRUE@ -I$(top_builddir)/lib/isc/include +@HAVE_JEMALLOC_FALSE@LIBISC_LIBS = $(top_builddir)/lib/isc/libisc.la +@HAVE_JEMALLOC_TRUE@LIBISC_LIBS = $(JEMALLOC_LIBS) \ +@HAVE_JEMALLOC_TRUE@ $(top_builddir)/lib/isc/libisc.la +@HAVE_DTRACE_TRUE@LIBISC_DTRACE = $(top_builddir)/lib/isc/probes.lo +LIBDNS_CFLAGS = \ + -I$(top_srcdir)/lib/dns/include \ + -I$(top_builddir)/lib/dns/include + +LIBDNS_LIBS = \ + $(top_builddir)/lib/dns/libdns.la + +@HAVE_DTRACE_TRUE@LIBDNS_DTRACE = $(top_builddir)/lib/dns/probes.lo +LIBNS_CFLAGS = \ + -I$(top_srcdir)/lib/ns/include + +LIBNS_LIBS = \ + $(top_builddir)/lib/ns/libns.la + +@HAVE_DTRACE_TRUE@LIBNS_DTRACE = $(top_builddir)/lib/ns/probes.lo +LIBISCCFG_CFLAGS = \ + -I$(top_srcdir)/lib/isccfg/include + +LIBISCCFG_LIBS = \ + $(top_builddir)/lib/isccfg/libisccfg.la + +LIBISCCC_CFLAGS = \ + -I$(top_srcdir)/lib/isccc/include/ + +LIBISCCC_LIBS = \ + $(top_builddir)/lib/isccc/libisccc.la + +noinst_LTLIBRARIES = libdummyrpz.la +libdummyrpz_la_SOURCES = dummylib.c test-data.c trpz.h test-data.h +libdummyrpz_la_LDFLAGS = -avoid-version -module -shared -export-dynamic -rpath $(abs_builddir) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.top $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bin/tests/system/rpz/testlib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign bin/tests/system/rpz/testlib/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/Makefile.top $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libdummyrpz.la: $(libdummyrpz_la_OBJECTS) $(libdummyrpz_la_DEPENDENCIES) $(EXTRA_libdummyrpz_la_DEPENDENCIES) + $(AM_V_CCLD)$(libdummyrpz_la_LINK) $(libdummyrpz_la_OBJECTS) $(libdummyrpz_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummylib.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-data.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +test-local: +unit-local: +doc-local: + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/dummylib.Plo + -rm -f ./$(DEPDIR)/test-data.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +doc: doc-am + +doc-am: doc-local + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/dummylib.Plo + -rm -f ./$(DEPDIR)/test-data.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +test: test-am + +test-am: test-local + +uninstall-am: + +unit: unit-am + +unit-am: unit-local + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir \ + doc-am doc-local dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am test-am test-local uninstall \ + uninstall-am unit-am unit-local + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/bin/tests/system/rpz/testlib/dummylib.c b/bin/tests/system/rpz/testlib/dummylib.c new file mode 100644 index 0000000..03b91b6 --- /dev/null +++ b/bin/tests/system/rpz/testlib/dummylib.c @@ -0,0 +1,2231 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Limited implementation of the DNSRPS API for testing purposes. + * + * Copyright (c) 2016-2017 Farsight Security, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "test-data.h" +#include "trpz.h" + +librpz_log_fnc_t *g_log_fnc = NULL; +const char *g_prog_nm = NULL; +bool g_scan_data_file_for_errors = true; + +typedef struct { + void *mutex_ctx; + void *log_ctx; + librpz_mutex_t *mutex_lock_fn; + librpz_mutex_t *mutex_unlock_fn; + librpz_mutex_t *mutex_destroy_fn; +} trpz_clist_t; + +typedef struct { + char *cstr; + bool uses_expired; + trpz_clist_t *pclist; +} trpz_client_t; + +typedef struct { + size_t idx; /* value only used for node iteration */ + trpz_client_t *client; + bool have_rd; + char zone[256]; + char domain[256]; + size_t zidx; + trpz_result_t rstack[LIBRPZ_RSP_STACK_DEPTH]; + size_t stack_idx; + trpz_zone_t *all_zones; + trpz_result_t *all_nodes; + size_t num_zones, num_nodes; + ssize_t last_zone; + ssize_t *base_zones; + size_t nbase_zones; +} trpz_rsp_t; + +librpz_log_level_t g_log_level = LIBRPZ_LOG_TRACE2; +FILE *g_log_outf = NULL; + +static int +apply_all_updates(trpz_rsp_t *trsp); +static void +clear_all_updates(trpz_rsp_t *trsp); + +static bool +domain_ntop(const u_char *src, char *dst, size_t dstsiz); +static bool +domain_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen, + bool lower); + +void +trpz_set_log(librpz_log_fnc_t *new_log, const char *prog_nm); +void +trpz_vlog(librpz_log_level_t level, void *ctx, const char *p, va_list args) + LIBRPZ_PF(3, 0); +void +trpz_log(librpz_log_level_t level, void *ctx, const char *p, ...) + LIBRPZ_PF(3, 4); +librpz_log_level_t +trpz_log_level_val(librpz_log_level_t level); +void +trpz_vpemsg(librpz_emsg_t *emsg, const char *p, va_list args) LIBRPZ_PF(2, 0); +void +trpz_pemsg(librpz_emsg_t *emsg, const char *fmt, ...) LIBRPZ_PF(2, 3); +librpz_clist_t * +trpz_clist_create(librpz_emsg_t *emsg, librpz_mutex_t *lock, + librpz_mutex_t *unlock, librpz_mutex_t *mutex_destroy, + void *mutex_ctx, void *log_ctx); +void +trpz_clist_detach(librpz_clist_t **clistp); +bool +trpz_connect(librpz_emsg_t *emsg, librpz_client_t *client, bool optional); +librpz_client_t * +trpz_client_create(librpz_emsg_t *emsg, librpz_clist_t *clist, const char *cstr, + bool use_expired); +void +trpz_client_detach(librpz_client_t **clientp); +bool +trpz_rsp_create(librpz_emsg_t *emsg, librpz_rsp_t **rspp, int *min_ns_dotsp, + librpz_client_t *client, bool have_rd, bool have_do); +void +trpz_rsp_detach(librpz_rsp_t **rspp); +bool +trpz_rsp_push(librpz_emsg_t *emsg, librpz_rsp_t *rsp); +bool +trpz_rsp_pop(librpz_emsg_t *emsg, librpz_result_t *result, librpz_rsp_t *rsp); +bool +trpz_rsp_pop_discard(librpz_emsg_t *emsg, librpz_rsp_t *rsp); +bool +trpz_rsp_domain(librpz_emsg_t *emsg, librpz_domain_buf_t *owner, + librpz_rsp_t *rsp); +bool +trpz_rsp_result(librpz_emsg_t *emsg, librpz_result_t *result, bool recursed, + const librpz_rsp_t *rsp); +bool +trpz_rsp_soa(librpz_emsg_t *emsg, uint32_t *ttlp, librpz_rr_t **rrp, + librpz_domain_buf_t *origin, librpz_result_t *result, + librpz_rsp_t *rsp); +bool +trpz_rsp_rr(librpz_emsg_t *emsg, uint16_t *typep, uint16_t *classp, + uint32_t *ttlp, librpz_rr_t **rrp, librpz_result_t *result, + const uint8_t *qname, size_t qname_size, librpz_rsp_t *rsp); +bool +trpz_ck_domain(librpz_emsg_t *emsg, const uint8_t *domain, size_t domain_size, + librpz_trig_t trig, librpz_result_id_t hit_id, bool recursed, + librpz_rsp_t *rsp); +bool +trpz_ck_ip(librpz_emsg_t *emsg, const void *addr, uint family, + librpz_trig_t trig, librpz_result_id_t hit_id, bool recursed, + librpz_rsp_t *rsp); +bool +trpz_rsp_clientip_prefix(librpz_emsg_t *emsg, librpz_prefix_t *prefix, + librpz_rsp_t *rsp); +bool +trpz_have_trig(librpz_trig_t trig, bool ipv6, const librpz_rsp_t *rsp); +bool +trpz_rsp_forget_zone(librpz_emsg_t *emsg, librpz_cznum_t znum, + librpz_rsp_t *rsp); +char * +trpz_vers_stats(librpz_emsg_t *emsg, librpz_rsp_t *rsp); +bool +trpz_soa_serial(librpz_emsg_t *emsg, uint32_t *serialp, const char *domain_nm, + librpz_rsp_t *rsp); +const char * +trpz_policy2str(librpz_policy_t policy, char *buf, size_t buf_size); + +#define BASE_ZONE_ANY -1 +#define BASE_ZONE_INVALID -2 + +librpz_0_t LIBRPZ_DEF = { + .dnsrpzd_path = "test-only", + .version = "0.0", + .log_level_val = trpz_log_level_val, + .set_log = trpz_set_log, + .vpemsg = trpz_vpemsg, + .pemsg = trpz_pemsg, + .vlog = trpz_vlog, + .log = trpz_log, + .clist_create = trpz_clist_create, + .clist_detach = trpz_clist_detach, + .client_create = trpz_client_create, + .connect = trpz_connect, + .client_detach = trpz_client_detach, + .rsp_create = trpz_rsp_create, + .rsp_detach = trpz_rsp_detach, + .rsp_result = trpz_rsp_result, + .have_trig = trpz_have_trig, + .rsp_domain = trpz_rsp_domain, + .rsp_rr = trpz_rsp_rr, + .rsp_soa = trpz_rsp_soa, + .soa_serial = trpz_soa_serial, + .rsp_push = trpz_rsp_push, + .rsp_pop = trpz_rsp_pop, + .rsp_pop_discard = trpz_rsp_pop_discard, + .rsp_forget_zone = trpz_rsp_forget_zone, + .ck_ip = trpz_ck_ip, + .ck_domain = trpz_ck_domain, + .policy2str = trpz_policy2str, +}; + +/* + * Returns whether or not searching in the specified zone, by index, is + * permitted. A client/RSP state can support a variable number of configured + * zones. + */ +static bool +has_base_zone(trpz_rsp_t *trsp, ssize_t zone) { + size_t n; + + if (trsp == NULL || trsp->base_zones == NULL || trsp->nbase_zones == 0) + { + return false; + } + + for (n = 0; n < trsp->nbase_zones; n++) { + if (trsp->base_zones[n] == BASE_ZONE_ANY || + trsp->base_zones[n] == zone) + { + return true; + } + } + + return false; +} + +static bool +pack_soa_record(unsigned char *rdatap, size_t rbufsz, size_t *rdlenp, + const rpz_soa_t *psoa) { + size_t needed = (sizeof(uint32_t) * 5) + strlen(psoa->mname) + 2 + + strlen(psoa->rname) + 2; + size_t mlen = 0, rlen = 0, used = 0; + + if (needed > rbufsz) { + return false; + } + + if (!domain_pton2(psoa->mname, rdatap, rbufsz, &rlen, true)) { + return false; + } + + if (!domain_pton2(psoa->rname, rdatap + rlen, rbufsz - rlen, &mlen, + true)) + { + return false; + } + + used = rlen + mlen; + + rdatap += rlen + mlen; + ISC_U32TO8_BE(rdatap, psoa->serial); + rdatap += 4; + ISC_U32TO8_BE(rdatap, psoa->refresh); + rdatap += 4; + ISC_U32TO8_BE(rdatap, psoa->retry); + rdatap += 4; + ISC_U32TO8_BE(rdatap, psoa->expire); + rdatap += 4; + ISC_U32TO8_BE(rdatap, psoa->minimum); + used += (4 * 5); + + SET_IF_NOT_NULL(rdlenp, used); + + return true; +} + +static void +do_log(librpz_log_level_t level, void *ctx, const char *fmt, va_list args) + LIBRPZ_PF(3, 0); +static void +do_log(librpz_log_level_t level, void *ctx, const char *fmt, va_list args) { + if (level > g_log_level) { + return; + } + + if (g_log_fnc != NULL) { + char lbuf[8192] = { 0 }; + + vsnprintf(lbuf, sizeof(lbuf) - 1, fmt, args); + g_log_fnc(level, ctx, lbuf); + return; + } + + if (g_log_outf == NULL) { + return; + } + + vfprintf(g_log_outf, fmt, args); + fprintf(g_log_outf, "\n"); + return; +} + +void +trpz_vlog(librpz_log_level_t level, void *ctx, const char *p, va_list args) { + do_log(level, ctx, p, args); + return; +} + +void +trpz_log(librpz_log_level_t level, void *ctx, const char *p, ...) { + va_list ap; + + va_start(ap, p); + trpz_vlog(level, ctx, p, ap); + va_end(ap); + + return; +} + +void +trpz_set_log(librpz_log_fnc_t *new_log, const char *prog_nm) { + assert(new_log != NULL || prog_nm != NULL); + + if (new_log != NULL) { + g_log_fnc = new_log; + } + + if (prog_nm != NULL) { + g_prog_nm = prog_nm; + } +} + +librpz_log_level_t +trpz_log_level_val(librpz_log_level_t level) { + if (level >= LIBRPZ_LOG_INVALID) { + return g_log_level; + } + + g_log_level = (level < LIBRPZ_LOG_FATAL) ? LIBRPZ_LOG_FATAL : level; + + return g_log_level; +} + +void +trpz_vpemsg(librpz_emsg_t *emsg, const char *p, va_list args) { + if (emsg == NULL) { + return; + } + + vsnprintf(emsg->c, sizeof(emsg->c), p, args); + emsg->c[sizeof(emsg->c) - 1] = 0; + return; +} + +void +trpz_pemsg(librpz_emsg_t *emsg, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + trpz_vpemsg(emsg, fmt, ap); + va_end(ap); + + return; +} + +/* + * Scan the data file for errors and log anything found that's critically + * wrong. + */ +static void +scan_data_file_for_errors(void *lctx) { + char *updfile = NULL, *fname = NULL, *last = NULL; + char *tmp = NULL; + + updfile = getenv("DNSRPS_TEST_UPDATE_FILE"); + if (updfile == NULL) { + return; + } + + tmp = strdup(updfile); + if (tmp == NULL) { + return; + } + + fname = strtok_r(tmp, ":", &last); + + while (fname) { + char *errp = NULL; + int ret; + + ret = sanity_check_data_file(fname, &errp); + + if ((ret < 0) && errp) { + trpz_log(LIBRPZ_LOG_ERROR, lctx, "%s", errp); + free(errp); + } + + fname = strtok_r(NULL, ":", &last); + } + free(tmp); + + return; +} + +librpz_clist_t * +trpz_clist_create(librpz_emsg_t *emsg, librpz_mutex_t *lock, + librpz_mutex_t *unlock, librpz_mutex_t *mutex_destroy, + void *mutex_ctx, void *log_ctx) { + trpz_clist_t *result = NULL; + + result = calloc(1, sizeof(*result)); + if (result == NULL) { + trpz_pemsg(emsg, "calloc: %s", strerror(errno)); + return NULL; + } + + result->mutex_ctx = mutex_ctx; + result->log_ctx = log_ctx; + result->mutex_lock_fn = lock; + result->mutex_unlock_fn = unlock; + result->mutex_destroy_fn = mutex_destroy; + + if (g_scan_data_file_for_errors) { + scan_data_file_for_errors(log_ctx); + } + + return (librpz_clist_t *)result; +} + +void +trpz_clist_detach(librpz_clist_t **clistp) { + if (clistp != NULL && *clistp != NULL) { + librpz_clist_t *clist = *clistp; + *clistp = NULL; + free(clist); + } + + return; +} + +bool +trpz_connect(librpz_emsg_t *emsg, librpz_client_t *client, bool optional) { + UNUSED(optional); + + if (client == NULL) { + trpz_pemsg(emsg, "Can't connect to null client"); + return false; + } + + return true; +} + +const char * +trpz_policy2str(librpz_policy_t policy, char *buf, size_t buf_size) { + const char *pname = NULL; + + if (buf == NULL || buf_size == 0) { + return NULL; + } + + switch (policy) { + case LIBRPZ_POLICY_UNDEFINED: + pname = "UNDEFINED"; + break; + case LIBRPZ_POLICY_DELETED: + pname = "DELETED"; + break; + case LIBRPZ_POLICY_PASSTHRU: + pname = "PASSTHRU"; + break; + case LIBRPZ_POLICY_DROP: + pname = "DROP"; + break; + case LIBRPZ_POLICY_TCP_ONLY: + pname = "TCP-ONLY"; + break; + case LIBRPZ_POLICY_NXDOMAIN: + pname = "NXDOMAIN"; + break; + case LIBRPZ_POLICY_NODATA: + pname = "NODATA"; + break; + case LIBRPZ_POLICY_RECORD: + pname = "RECORD"; + break; + case LIBRPZ_POLICY_GIVEN: + pname = "GIVEN"; + break; + case LIBRPZ_POLICY_DISABLED: + pname = "DISABLED"; + break; + case LIBRPZ_POLICY_CNAME: + pname = "CNAME"; + break; + default: + pname = "UNKNOWN"; + break; + } + + strncpy(buf, pname, buf_size); + buf[buf_size - 1] = 0; + return buf; +} + +/* + * Get the entire set of zones configured by the config string, + * and bind then to the specified RSP state. + * + * The array of active zone indices is returned by the function on success, + * or NULL on failure. The total number of zones is stored in pnzones. + */ +static ssize_t * +get_cstr_zones(const char *cstr, trpz_rsp_t *trsp, size_t *pnzones) { + char tmpc[8192] = { 0 }; + char *tptr = tmpc, *tok = NULL; + size_t nzones = 0, cur_idx = 0; + ssize_t *result = NULL; + unsigned long zflags = 0; + + result = calloc(trsp->num_zones + 1, sizeof(*result)); + if (result == NULL) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + if (cstr == NULL) { + result[0] = BASE_ZONE_ANY; + *pnzones = 1; + return result; + } + + strncpy(tmpc, cstr, sizeof(tmpc) - 1); + *pnzones = 0; + + while (tptr != NULL && *tptr != '\0') { + tok = strsep(&tptr, ";\n"); + + while (isspace((unsigned char)*tok)) { + tok++; + } + + if (strncasecmp(tok, "zone ", 5) == 0) { + char zcmd[1024] = { 0 }; + char *qend = NULL; + size_t zind = 0, old_zct = trsp->num_zones; + unsigned long zopts = 0; + + tok += 5; + + while (isspace((unsigned char)*tok)) { + tok++; + } + + if (*tok == '"') { + qend = strchr(++tok, '"'); + if (qend == NULL) { + fprintf(stderr, "Error parsing cstr " + "contents!\n"); + free(result); + return NULL; + } + + *qend++ = 0; + + if (tok[strlen(tok) - 1] == '.') { + tok[strlen(tok) - 1] = 0; + } + + } else { + qend = tok; + } + + while (*qend != '\0' && !isspace((unsigned char)*qend)) + { + qend++; + } + + if (*qend != '\0') { + *qend++ = '\0'; + zopts = parse_zone_options(qend); + } + + snprintf(zcmd, sizeof(zcmd) - 1, "zone %s 1", tok); + + if (apply_update(zcmd, &(trsp->all_nodes), + &(trsp->num_nodes), &(trsp->all_zones), + &(trsp->num_zones), 0, zopts, + NULL) < 0) + { + fprintf(stderr, "Internal error {%s}!\n", zcmd); + free(result); + return NULL; + } + + if (trsp->num_zones > old_zct) { + result = realloc(result, + ((trsp->num_zones + 1) * + sizeof(*result))); + if (result == NULL) { + perror("realloc"); + exit(EXIT_FAILURE); + } + } + + for (zind = 0; zind < trsp->num_zones; zind++) { + if (!strcmp(trsp->all_zones[zind].name, tok)) { + break; + } + } + + if (zind == trsp->num_zones) { + free(result); + return NULL; + } + + result[cur_idx++] = zind; + *pnzones = cur_idx; + nzones++; + } else { + unsigned long flags; + + flags = parse_zone_options(tok); + zflags |= (flags & (ZOPT_QNAME_AS_NS | ZOPT_IP_AS_NS | + ZOPT_RECURSIVE_ONLY | + ZOPT_NOT_RECURSIVE_ONLY | + ZOPT_NO_QNAME_WAIT_RECURSE | + ZOPT_NO_NSIP_WAIT_RECURSE)); + } + + tok = NULL; + } + + if (nzones == 0) { + free(result); + return NULL; + } + + if (zflags != 0) { + size_t n; + + for (n = 0; n < trsp->num_zones; n++) { + if (zflags & ZOPT_QNAME_AS_NS) { + trsp->all_zones[n].qname_as_ns = true; + } + + if (zflags & ZOPT_IP_AS_NS) { + trsp->all_zones[n].ip_as_ns = true; + } + + if (zflags & ZOPT_RECURSIVE_ONLY) { + trsp->all_zones[n].not_recursive_only = false; + } else if (zflags & ZOPT_NOT_RECURSIVE_ONLY) { + trsp->all_zones[n].not_recursive_only = true; + } + + if (zflags & ZOPT_NO_QNAME_WAIT_RECURSE) { + trsp->all_zones[n].no_qname_wait_recurse = true; + } + + if (zflags & ZOPT_NO_NSIP_WAIT_RECURSE) { + trsp->all_zones[n].no_nsip_wait_recurse = true; + } + } + } + + return result; +} + +librpz_client_t * +trpz_client_create(librpz_emsg_t *emsg, librpz_clist_t *clist, const char *cstr, + bool use_expired) { + trpz_client_t *result = NULL; + + if (clist == NULL) { + trpz_pemsg(emsg, "clist was NULL\n"); + return NULL; + } + + result = calloc(1, sizeof(*result)); + if (result == NULL) { + trpz_pemsg(emsg, "calloc: %s", strerror(errno)); + return NULL; + } + + result->cstr = strdup(cstr); + if (result->cstr == NULL) { + trpz_pemsg(emsg, "strdup: %s", strerror(errno)); + free(result); + return NULL; + } + + result->uses_expired = use_expired; + result->pclist = (trpz_clist_t *)clist; + + return (librpz_client_t *)result; +} + +void +trpz_client_detach(librpz_client_t **clientp) { + if (clientp != NULL && *clientp != NULL) { + trpz_client_t *client = (trpz_client_t *)(*clientp); + if (client->cstr != NULL) { + free(client->cstr); + } + free(client); + } + + return; +} + +/* + * If the DNSRPS_TEST_UPDATE_FILE env variable is set, + * load the current list of test nodes from the specified data file. + * + * Any existing nodes are first destroyed. + */ +static int +apply_all_updates(trpz_rsp_t *trsp) { + char *updfile = NULL, *fname = NULL, *last = NULL; + char *tmp = NULL; + + updfile = getenv("DNSRPS_TEST_UPDATE_FILE"); + if (updfile == NULL) { + return 0; + } + + tmp = strdup(updfile); + if (tmp == NULL) { + return -1; + } + + fname = strtok_r(updfile, ":", &last); + while (fname != NULL) { + char *errp = NULL; + int ret; + + ret = load_all_updates(fname, &trsp->all_nodes, + &trsp->num_nodes, &trsp->all_zones, + &trsp->num_zones, &errp); + + if (errp != NULL) { + fprintf(stderr, "Error loading updates: %s\n", errp); + free(errp); + } + + if (ret < 0) { + free(tmp); + return -1; + } + + fname = strtok_r(NULL, ":", &last); + } + free(tmp); + + return 0; +} + +static void +clear_all_updates(trpz_rsp_t *trsp) { + if (trsp == NULL) { + return; + } + + if (trsp->all_zones != NULL) { + free(trsp->all_zones); + } + + trsp->all_zones = NULL; + trsp->num_zones = 0; + + if (trsp->all_nodes != NULL) { + size_t n; + + for (n = 0; n < trsp->num_nodes; n++) { + if (trsp->all_nodes[n].canonical != NULL) { + free(trsp->all_nodes[n].canonical); + } + if (trsp->all_nodes[n].dname != NULL) { + free(trsp->all_nodes[n].dname); + } + if (trsp->all_nodes[n].rrs) { + size_t m; + + for (m = 0; m < trsp->all_nodes[n].nrrs; m++) { + if (trsp->all_nodes[n].rrs[m].rdata) { + free(trsp->all_nodes[n] + .rrs[m] + .rdata); + } + } + + free(trsp->all_nodes[n].rrs); + } + } + + free(trsp->all_nodes); + } + + trsp->all_nodes = NULL; + trsp->num_nodes = 0; + + return; +} + +/* + * Start a set of RPZ queries for a single DNS response. + */ +bool +trpz_rsp_create(librpz_emsg_t *emsg, librpz_rsp_t **rspp, int *min_ns_dotsp, + librpz_client_t *client, bool have_rd, bool have_do) { + trpz_client_t *cli = (trpz_client_t *)client; + trpz_rsp_t *result = NULL; + + UNUSED(min_ns_dotsp); + UNUSED(have_do); + + if (client == NULL) { + trpz_pemsg(emsg, "client was NULL"); + return false; + } else if (rspp == NULL) { + trpz_pemsg(emsg, "rspp was NULL"); + return false; + } else if (cli->cstr == NULL) { + trpz_pemsg(emsg, "no valid policy zone specified"); + return false; + } + + result = calloc(1, sizeof(*result)); + if (result == NULL) { + trpz_pemsg(emsg, "calloc: %s", strerror(errno)); + return false; + } + + result->idx = 0; + result->client = cli; + result->have_rd = have_rd; + result->stack_idx = 1; + result->last_zone = -1; + + assert(*rspp == NULL); + + clear_all_updates(result); + result->base_zones = get_cstr_zones(cli->cstr, result, + &(result->nbase_zones)); + + if (result->base_zones == NULL) { + trpz_pemsg(emsg, "no valid policy zone specified"); + clear_all_updates(result); + free(result); + return false; + } + + if (apply_all_updates(result) < 0) { + trpz_pemsg(emsg, "internal error loading test data 1"); + clear_all_updates(result); + free(result->base_zones); + free(result); + return false; + } + + *rspp = (librpz_rsp_t *)result; + + return true; +} + +bool +trpz_rsp_push(librpz_emsg_t *emsg, librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + + UNUSED(emsg); + + if (trsp->stack_idx == 0) { + memset(&(trsp->rstack[0]), 0, sizeof(trsp->rstack[0]) * 2); + trsp->stack_idx++; + return true; + } else if (trsp->stack_idx >= LIBRPZ_RSP_STACK_DEPTH) { + return false; + } + + memmove(&(trsp->rstack[1]), &(trsp->rstack[0]), + (trsp->stack_idx * sizeof(trsp->rstack[0]))); + trsp->stack_idx++; + + return true; +} + +bool +trpz_rsp_pop(librpz_emsg_t *emsg, librpz_result_t *result, librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + + UNUSED(emsg); + + if (trsp->stack_idx <= 1) { + return false; + } + + memmove(&(trsp->rstack[0]), &(trsp->rstack[1]), + ((trsp->stack_idx - 1) * sizeof(trsp->rstack[0]))); + memmove(result, &(trsp->rstack[0].result), sizeof(*result)); + trsp->stack_idx--; + + return true; +} + +bool +trpz_rsp_pop_discard(librpz_emsg_t *emsg, librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + + UNUSED(emsg); + + if (trsp->stack_idx == 0) { + return false; + } else if (trsp->stack_idx == 1) { + return true; + } + + if (trsp->stack_idx > 1) { + memmove(&(trsp->rstack[1]), &(trsp->rstack[2]), + ((trsp->stack_idx - 2) * sizeof(trsp->rstack[0]))); + } + + trsp->stack_idx--; + + return true; +} + +void +trpz_rsp_detach(librpz_rsp_t **rspp) { + if (rspp != NULL && *rspp != NULL) { + trpz_rsp_t *trsp = (trpz_rsp_t *)*rspp; + *rspp = NULL; + clear_all_updates(trsp); + if (trsp->base_zones != NULL) { + free(trsp->base_zones); + } + free(trsp); + } + + return; +} + +bool +trpz_rsp_domain(librpz_emsg_t *emsg, librpz_domain_buf_t *owner, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + const char *tstr = ""; + char tmpname[256] = { 0 }; + size_t osz = 0; + uint32_t n; + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL"); + return false; + } else if (trsp->stack_idx == 0) { + trpz_pemsg(emsg, "domain not found [1]"); + return false; + } else if (trsp->rstack[0].result.policy == LIBRPZ_POLICY_UNDEFINED) { + trpz_pemsg(emsg, "domain not found [2]"); + return false; + } + + if (trsp->all_zones[trsp->rstack[0].result.dznum].forgotten) { + trpz_pemsg(emsg, "domain not found [3]"); + memset(owner, 0, sizeof(*owner)); + return true; + } + + switch (trsp->rstack[0].result.trig) { + case LIBRPZ_TRIG_CLIENT_IP: + tstr = "rpz-client-ip."; + break; + case LIBRPZ_TRIG_IP: + tstr = "rpz-ip."; + break; + case LIBRPZ_TRIG_NSDNAME: + tstr = "rpz-nsdname."; + break; + case LIBRPZ_TRIG_NSIP: + tstr = "rpz-nsip."; + break; + default: + break; + } + + n = snprintf(tmpname, sizeof(tmpname), "%s.%s%s", trsp->rstack[0].dname, + tstr, trsp->all_zones[trsp->rstack[0].result.dznum].name); + if (n > sizeof(tmpname)) { + trpz_pemsg(emsg, "%s truncated", tmpname); + return false; + } + + if (!domain_pton2(tmpname, owner->d, sizeof(owner->d), &osz, true)) { + trpz_pemsg(emsg, "unable to read hostname from rsp!"); + return false; + } + + owner->size = osz; + return true; +} + +bool +trpz_rsp_result(librpz_emsg_t *emsg, librpz_result_t *result, bool recursed, + const librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + + UNUSED(recursed); + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL!"); + return false; + } else if (result == NULL) { + trpz_pemsg(emsg, "result was NULL"); + return false; + } + + if (trsp->stack_idx == 0) { + memset(result, 0, sizeof(*result)); + result->policy = LIBRPZ_POLICY_UNDEFINED; + } else { + if (trsp->rstack[0].result.policy && trsp->rstack[0].nrrs && + (trsp->rstack[0].result.policy != LIBRPZ_POLICY_DISABLED)) + { + trsp->rstack[0].result.next_rr = + trsp->rstack[0].rrs[0].rrn; + } + + trsp->rstack[0].rridx = 0; + + memmove(result, &(trsp->rstack[0].result), sizeof(*result)); + + if (result->policy && trsp->rstack[0].poverride) { + result->policy = trsp->rstack[0].poverride; + } + } + + return true; +} + +bool +trpz_rsp_soa(librpz_emsg_t *emsg, uint32_t *ttlp, librpz_rr_t **rrp, + librpz_domain_buf_t *origin, librpz_result_t *result, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + librpz_rr_t *rres = NULL; + rpz_soa_t tmpsoa; + unsigned char *rdbuf = NULL; + char tmp_rname[1024] = { 0 }; + size_t rdlen = 0; + + UNUSED(ttlp); + + if (result == NULL) { + trpz_pemsg(emsg, "result was NULL!"); + return false; + } else if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL!"); + return false; + } + + if (trsp->zidx >= trsp->num_zones) { + trpz_pemsg(emsg, "bad zone"); + return false; + } + + rdbuf = calloc(1024, 1); + if (rdbuf == NULL) { + trpz_pemsg(emsg, "calloc: %s", strerror(errno)); + return false; + } + + rres = (librpz_rr_t *)rdbuf; + + rres->type = htons(6); + rres->class = htons(1); + rres->ttl = htonl(60); + + memmove(&tmpsoa, &g_soa_record, sizeof(tmpsoa)); + tmpsoa.serial = trsp->all_zones[result->dznum].serial; + tmpsoa.mname = trsp->all_zones[result->dznum].name; + + snprintf(tmp_rname, sizeof(tmp_rname) - 1, "hostmaster.ns.%s", + tmpsoa.mname); + tmpsoa.rname = tmp_rname; + + if (tmpsoa.serial == 0) { + tmpsoa.serial = time(NULL); + } + + if (!pack_soa_record(rres->rdata, 1024 - sizeof(*rres), &rdlen, + &tmpsoa)) + { + trpz_pemsg(emsg, "Error packing SOA reply"); + free(rdbuf); + return false; + } + + rres->rdlength = htons(rdlen); + + if (origin != NULL) { + uint8_t *buf = NULL; + int nbytes; + + if ((nbytes = wdns_str_to_name(tmpsoa.mname, &buf, 1)) < 0) { + trpz_pemsg(emsg, "Error packing domain"); + free(rdbuf); + return false; + } + + memset(origin, 0, sizeof(*origin)); + memmove(origin->d, buf, nbytes); + origin->size = nbytes; + free(buf); + } + + if (rrp != NULL) { + *rrp = rres; + } else { + free(rdbuf); + } + + return true; +} + +/* + * Compare a query domain against a record, allowing for the possibility of + * a wildcard match. + */ +static int +domain_cmp(const char *query, const char *record, bool *wildp) { + const char *end = NULL; + size_t cmplen; + + end = record + strlen(record); + + cmplen = end - record; + + *wildp = false; + + if (record != NULL && *record == '*' && record[1] == '.') { + const char *rptr = record + 2; + + if ((cmplen - 2) < strlen(query)) { + const char *qptr = NULL; + + qptr = query + strlen(query) - (cmplen - 2); + + if (strncmp(qptr, rptr, (cmplen - 2)) == 0) { + *wildp = true; + return 0; + } + } + } + + if (strlen(query) > cmplen) { + return 1; + } else if (strlen(query) < cmplen) { + return -1; + } + + return strncmp(record, query, cmplen); +} + +/* + * Count the number of labels in the given domain name. + */ +static size_t +count_labels(const char *domain) { + const char *dptr = NULL; + size_t result = 1; + + if (domain == NULL || *domain == '\0') { + return 0; + } + + dptr = domain + strlen(domain); + + while (1) { + while ((dptr >= domain) && (*dptr != '.')) { + dptr--; + } + + if (dptr <= domain) { + break; + } + + result++; + dptr--; + } + + return result; +} + +/* + * Does the newly found result supercede the old result in precedence? + * This function is used to determine whether a match on the result stack + * should be overwritten by another match of higher precedence - or whether + * the old match should remain, as-is. + * + * 1. "CNAME or DNAME Chain Position" Precedence Rule + * 2. "RPZ Ordering" Precedence Rule [zone order] + * 3. "Domain Name Matching" Precedence Rule [QNAME/NSDNAME - label count] + * 4. "Trigger Type" Precedence Rule + * 5. "Name Order" Precedence Rule [NSDNAME] + * 6. "Prefix Length" Precedence Rule + * 7. "IP Address Order" Precedence Rule + */ +static bool +result_supercedes(const trpz_result_t *new, const trpz_result_t *old) { + size_t nsz, osz; + + if (old == NULL || old->result.policy == 0 || old->dname == NULL || + old->dname[0] == '\0') + { + return true; + } + + if (new->result.dznum < old->result.dznum) { + return true; + } else if (new->result.dznum > old->result.dznum) { + return false; + } + + nsz = count_labels(new->dname); + osz = count_labels(old->dname); + + /* More matching labels is better. */ + if (nsz > osz) { + return true; + } else if (nsz < osz) { + return false; + } + + if (new->result.trig < old->result.trig) { + return true; + } else if (new->result.trig > old->result.trig) { + return false; + } + + return true; +} + +static bool +result_supercedes_address(const trpz_result_t *new, const trpz_result_t *old) { + if (old == NULL || old->result.policy == 0 || old->dname == NULL || + old->dname[0] == '\0') + { + return true; + } + + if (new->result.dznum < old->result.dznum) { + return true; + } else if (new->result.dznum > old->result.dznum) { + return false; + } + + if (new->result.trig < old->result.trig) { + return true; + } else if (new->result.trig > old->result.trig) { + return false; + } + + if ((new->flags &NODE_FLAG_IPV6_ADDRESS) && + !(old->flags & NODE_FLAG_IPV6_ADDRESS)) + { + return true; + } + + /* + * XXX: this is broken. Needs proper address comparison. For + * example, by most specific prefix match. + */ + if (strcmp(old->dname, new->dname) < 0) { + return false; + } + + return true; +} + +bool +trpz_ck_domain(librpz_emsg_t *emsg, const uint8_t *domain, size_t domain_size, + librpz_trig_t trig, librpz_result_id_t hit_id, bool recursed, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + char dname[256] = { 0 }; + librpz_trig_t toverride = LIBRPZ_TRIG_BAD; + ssize_t fidx = -1, nfidx = -1; + bool wild; + size_t n; + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL!"); + return false; + } else if (domain == NULL || domain_size == 0) { + trpz_pemsg(emsg, "domain was empty"); + return false; + } else if (trig != LIBRPZ_TRIG_QNAME && trig != LIBRPZ_TRIG_NSDNAME) { + trpz_pemsg(emsg, "invalid trigger type"); + return false; + } else if (!domain_ntop(domain, dname, sizeof(dname))) { + trpz_pemsg(emsg, "domain was invalid"); + return false; + } + + if (trsp->stack_idx == 0) { + trsp->stack_idx = 1; + } + + for (n = 0; n < trsp->num_nodes; n++) { + int pos = 0; + + if (!trsp->have_rd && + !trsp->all_zones[trsp->all_nodes[n].result.dznum] + .not_recursive_only) + { + continue; + } + + if (pos || + ((trig == trsp->all_nodes[n].result.trig) && + (!domain_cmp(dname, trsp->all_nodes[n].dname, &wild)))) + { + if ((trsp->all_zones[trsp->all_nodes[n].result.dznum] + .no_qname_wait_recurse || + trsp->all_zones[trsp->all_nodes[n].result.dznum] + .not_recursive_only || + recursed) && + has_base_zone(trsp, + trsp->all_nodes[n].result.dznum) && + !trsp->all_zones[trsp->all_nodes[n].result.dznum] + .forgotten) + { + if (fidx < 0) { + fidx = n; + toverride = LIBRPZ_TRIG_BAD; + } + } + if (!wild) { + break; + } + + /* + * Some inelegant special handling for qname_as_ns + * feature. + */ + } else if (trsp->all_zones[trsp->all_nodes[n].result.dznum] + .qname_as_ns && + (((trig == LIBRPZ_TRIG_QNAME) && + (trsp->all_nodes[n].result.trig == + LIBRPZ_TRIG_NSDNAME)) || + ((trig == LIBRPZ_TRIG_NSDNAME) && + (trsp->all_nodes[n].result.trig == + LIBRPZ_TRIG_QNAME)))) + { + if (!domain_cmp(dname, trsp->all_nodes[n].dname, &wild)) + { + if (recursed && + has_base_zone( + trsp, + trsp->all_nodes[n].result.dznum) && + !trsp->all_zones[trsp->all_nodes[n] + .result.dznum] + .forgotten) + { + if (fidx < 0) { + fidx = n; + toverride = trig; + } + } + if (!wild) { + break; + } + } + } + } + + if (!trsp->have_rd && (fidx < 0) && (nfidx < 0)) { + goto out; + } + + if (recursed && (fidx < 0) && trsp->rstack[0].hidden_policy) { + if (trsp->rstack[0].result.trig <= trig) { + trsp->rstack[0].result.policy = + trsp->rstack[0].hidden_policy; + trsp->rstack[0].result.zpolicy = + trsp->rstack[0].hidden_policy; + trsp->rstack[0].hidden_policy = LIBRPZ_POLICY_UNDEFINED; + return true; + } + } + + if (fidx >= 0) { + bool disabled = false; + + if (!result_supercedes(&(trsp->all_nodes[fidx]), + &(trsp->rstack[0]))) + { + return true; + } + + strncpy(trsp->domain, dname, sizeof(trsp->domain)); + memmove(&(trsp->rstack[0]), &(trsp->all_nodes[fidx]), + sizeof(trsp->rstack[0])); + trsp->rstack[0].result.hit_id = hit_id; + trsp->last_zone = trsp->rstack[0].result.dznum; + + if (trsp->all_zones[trsp->rstack[0].result.dznum].flags) { + unsigned long flags = + trsp->all_zones[trsp->rstack[0].result.dznum] + .flags; + librpz_policy_t force_policy = 0; + + if (flags & ZOPT_POLICY_NODATA) { + force_policy = LIBRPZ_POLICY_NODATA; + } else if (flags & ZOPT_POLICY_PASSTHRU) { + force_policy = LIBRPZ_POLICY_PASSTHRU; + } else if (flags & ZOPT_POLICY_NXDOMAIN) { + force_policy = LIBRPZ_POLICY_NXDOMAIN; + } else if (flags & ZOPT_POLICY_DROP) { + force_policy = LIBRPZ_POLICY_DROP; + } else if (flags & ZOPT_POLICY_TCP_ONLY) { + force_policy = LIBRPZ_POLICY_TCP_ONLY; + } else if (flags & ZOPT_POLICY_DISABLED) { + disabled = true; + } + + if (force_policy) { + trsp->rstack[0].result.policy = force_policy; + trsp->rstack[0].result.zpolicy = force_policy; + trsp->rstack[0].poverride = force_policy; + } + } + + if (toverride) { + trsp->rstack[0].result.trig = toverride; + } + + if (disabled) { + trsp->rstack[0].poverride = LIBRPZ_POLICY_DISABLED; + } else if (!recursed) { + ssize_t m; + + /* + * If recursed is not set, then an earlier zone of + * higher precedence may not contain a rule of + * trigger types rpz-ip, rpz-nsip, or rpz-nsdname - + * which are by nature post-recursion rules. + */ + for (m = trsp->all_nodes[fidx].result.dznum - 1; m >= 0; + m--) + { + if (trsp->all_zones[m] + .has_triggers[0][LIBRPZ_TRIG_IP] || + trsp->all_zones[m] + .has_triggers[1][LIBRPZ_TRIG_IP] || + trsp->all_zones[m] + .has_triggers[0][LIBRPZ_TRIG_NSIP] || + trsp->all_zones[m] + .has_triggers[1][LIBRPZ_TRIG_NSIP] || + trsp->all_zones[m] + .has_triggers[0] + [LIBRPZ_TRIG_NSDNAME]) + { + trsp->rstack[0].result.policy = + LIBRPZ_POLICY_UNDEFINED; + break; + } + } + } + + return true; + } else if (nfidx >= 0) { + strncpy(trsp->domain, dname, sizeof(trsp->domain)); + memmove(&(trsp->rstack[0]), &(trsp->all_nodes[nfidx]), + sizeof(trsp->rstack[0])); + trsp->last_zone = trsp->all_nodes[nfidx].result.dznum; + trsp->rstack[0].hidden_policy = trsp->rstack[0].result.policy; + trsp->rstack[0].result.hit_id = hit_id; + trsp->rstack[0].result.policy = LIBRPZ_POLICY_UNDEFINED; + trsp->rstack[0].result.zpolicy = LIBRPZ_POLICY_UNDEFINED; + return true; + } + +out: + if (trsp->rstack[0].result.policy == LIBRPZ_POLICY_UNDEFINED) { + memset(&(trsp->rstack[0]), 0, sizeof(trsp->rstack[0])); + } + + return true; +} + +static void +rpzify_ipv6_str(char *buf) { + char tmpb[512] = { 0 }, *tptr = NULL; + + strncpy(tmpb, buf, sizeof(tmpb) - 1); + memset(buf, 0, strlen(buf)); + tptr = tmpb + strlen(tmpb); + + strcat(buf, "128."); + + while (tptr > tmpb) { + if (*tptr == ':') { + strcat(buf, tptr + 1); + strcat(buf, "."); + } + + tptr--; + + if ((*tptr == ':') && (tptr[0] == tptr[1])) { + strcat(buf, "zz"); + } + + if (tptr[1] == ':') { + tptr[1] = 0; + } + } + + strcat(buf, tptr); + + return; +} + +static uint32_t +get_mask(unsigned char prefix) { + uint32_t result = 0; + unsigned char n; + + if (prefix == 0) { + return 0; + } else if (prefix >= 32) { + return ~(0); + } + + for (n = 1; n < prefix; n++) { + result |= (1 << n); + } + + return result; +} + +/* XXX: this is broken for handling subnet masks in IPv6. */ +static int +address_cmp(const char *addrstr, const void *addr, uint family, + unsigned int *pmask) { + char abuf[256] = { 0 }; + int ipstr[8] = { 0 }; + unsigned int nmask = 32; + + if (family == AF_INET6) { + if (inet_ntop(AF_INET6, addr, abuf, sizeof(abuf)) == 0) { + return -1; + } + + rpzify_ipv6_str(abuf); + } else if (family == AF_INET) { + char newstr[32] = { 0 }; + in_addr_t a1, a2; + + if (sscanf(addrstr, "%d.%d.%d.%d.%d", &ipstr[0], &ipstr[1], + &ipstr[2], &ipstr[3], &ipstr[4]) == 5) + { + nmask = ipstr[0]; + if (nmask > 32) { + return -1; + } + } else if (sscanf(addrstr, "%d.%d.%d.%d", &ipstr[1], &ipstr[2], + &ipstr[3], &ipstr[4]) != 4) + { + perror("bad address format"); + return -1; + } + + if (ipstr[1] > 255 || ipstr[2] > 255 || ipstr[3] > 255 || + ipstr[4] > 255 || ipstr[1] < 0 || ipstr[2] < 0 || + ipstr[3] < 0 || ipstr[4] < 0) + { + perror("bad address format"); + return -1; + } + + sprintf(newstr, "%u.%u.%u.%u", ipstr[4], ipstr[3], ipstr[2], + ipstr[1]); + + a1 = inet_addr(newstr); + if (a1 == INADDR_NONE) { + perror("inet_addr"); + return -1; + } else { + uint32_t m; + + memmove(&a2, addr, sizeof(uint32_t)); + m = get_mask(nmask); + + if (pmask != NULL) { + *pmask = nmask; + } + + return ((a1 & m) == (a2 & m)) ? 0 : 1; + } + + } else { + return -1; + } + + if (strcmp(addrstr, abuf) == 0) { + if (pmask != NULL) { + *pmask = nmask; + } + + return 0; + } + + return 1; +} + +bool +trpz_ck_ip(librpz_emsg_t *emsg, const void *addr, uint family, + librpz_trig_t trig, librpz_result_id_t hit_id, bool recursed, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + size_t n, last_mask = 0; + ssize_t fidx = -1, nfidx = -1; + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL!"); + return false; + } else if (addr == NULL) { + trpz_pemsg(emsg, "addr was empty"); + return false; + } else if (trig != LIBRPZ_TRIG_IP && trig != LIBRPZ_TRIG_CLIENT_IP && + trig != LIBRPZ_TRIG_NSIP) + { + trpz_pemsg(emsg, "trigger type not supported for IP"); + return false; + } + + if (trsp->stack_idx == 0) { + trsp->stack_idx = 1; + } + + /* The final match is the most specifically-matching netmask. */ + for (n = 0; n < trsp->num_nodes; n++) { + unsigned int mask = 0; + bool amatch = false; + + if (!trsp->have_rd && + !trsp->all_zones[trsp->all_nodes[n].result.dznum] + .not_recursive_only) + { + continue; + } + + if (trsp->all_zones[trsp->all_nodes[n].result.dznum].ip_as_ns && + (((trig == LIBRPZ_TRIG_IP) && + (trsp->all_nodes[n].result.trig == LIBRPZ_TRIG_NSIP)) || + ((trig == LIBRPZ_TRIG_NSIP) && + (trsp->all_nodes[n].result.trig == LIBRPZ_TRIG_IP))) && + !address_cmp(trsp->all_nodes[n].dname, addr, family, &mask)) + { + amatch = true; + } else if (trsp->all_nodes[n].match_trig != trig) { + continue; + } + + if (amatch || + !address_cmp(trsp->all_nodes[n].dname, addr, family, &mask)) + { + if ((trsp->all_zones[trsp->all_nodes[n].result.dznum] + .no_qname_wait_recurse || + trsp->all_zones[trsp->all_nodes[n].result.dznum] + .not_recursive_only || + recursed) && + has_base_zone(trsp, + trsp->all_nodes[n].result.dznum) && + !trsp->all_zones[trsp->all_nodes[n].result.dznum] + .forgotten) + { + if (mask > last_mask) { + last_mask = mask; + fidx = n; + } + + } else if ((nfidx < 0) && !recursed && + has_base_zone( + trsp, + trsp->all_nodes[n].result.dznum) && + !trsp->all_zones[trsp->all_nodes[n] + .result.dznum] + .forgotten) + { + nfidx = n; + } + } + } + + if (!trsp->have_rd && (fidx < 0) && (nfidx < 0)) { + goto out; + } + + if (recursed && (fidx < 0) && trsp->rstack[0].hidden_policy) { + if (trsp->rstack[0].result.trig <= trig) { + trsp->rstack[0].result.policy = + trsp->rstack[0].hidden_policy; + trsp->rstack[0].result.zpolicy = + trsp->rstack[0].hidden_policy; + trsp->rstack[0].hidden_policy = LIBRPZ_POLICY_UNDEFINED; + return true; + } + } + + if (fidx >= 0) { + bool disabled = false; + + if (!result_supercedes_address(&(trsp->all_nodes[fidx]), + &(trsp->rstack[0]))) + { + return true; + } + + memmove(&(trsp->rstack[0]), &(trsp->all_nodes[fidx]), + sizeof(trsp->rstack[0])); + trsp->rstack[0].result.hit_id = hit_id; + trsp->last_zone = trsp->rstack[0].result.dznum; + + if (trsp->all_zones[trsp->rstack[0].result.dznum].flags) { + unsigned long flags = + trsp->all_zones[trsp->rstack[0].result.dznum] + .flags; + librpz_policy_t force_policy = 0; + + if (flags & ZOPT_POLICY_NODATA) { + force_policy = LIBRPZ_POLICY_NODATA; + } else if (flags & ZOPT_POLICY_PASSTHRU) { + force_policy = LIBRPZ_POLICY_PASSTHRU; + } else if (flags & ZOPT_POLICY_NXDOMAIN) { + force_policy = LIBRPZ_POLICY_NXDOMAIN; + } else if (flags & ZOPT_POLICY_DROP) { + force_policy = LIBRPZ_POLICY_DROP; + } else if (flags & ZOPT_POLICY_TCP_ONLY) { + force_policy = LIBRPZ_POLICY_TCP_ONLY; + } else if (flags & ZOPT_POLICY_DISABLED) { + disabled = true; + } + + if (force_policy) { + trsp->rstack[0].result.policy = force_policy; + trsp->rstack[0].result.zpolicy = force_policy; + trsp->rstack[0].poverride = force_policy; + } + } + + if (disabled) { + trsp->rstack[0].poverride = LIBRPZ_POLICY_DISABLED; + } + + return true; + } else if (nfidx >= 0) { + memmove(&(trsp->rstack[0]), &(trsp->all_nodes[nfidx]), + sizeof(trsp->rstack[0])); + trsp->last_zone = trsp->rstack[0].result.dznum; + trsp->rstack[0].result.hit_id = hit_id; + trsp->rstack[0].hidden_policy = trsp->rstack[0].result.policy; + trsp->rstack[0].result.policy = LIBRPZ_POLICY_UNDEFINED; + trsp->rstack[0].result.zpolicy = LIBRPZ_POLICY_UNDEFINED; + return true; + } + +out: + if (trig == LIBRPZ_TRIG_NSIP) { + bool needs_wait = false; + + for (n = 0; n < trsp->num_zones; n++) { + if (trsp->all_zones[n].no_nsip_wait_recurse) { + needs_wait = true; + break; + } + } + + if (!needs_wait) { + usleep(100); + } + } + + if (trsp->rstack[0].result.policy == LIBRPZ_POLICY_UNDEFINED) { + memset(&(trsp->rstack[0]), 0, sizeof(trsp->rstack[0])); + trsp->rstack[0].result.trig = trig; + } + + return true; +} + +bool +trpz_soa_serial(librpz_emsg_t *emsg, uint32_t *serialp, const char *domain_nm, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + size_t n, dlen; + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL"); + return false; + } else if (domain_nm == NULL) { + trpz_pemsg(emsg, "domain_nm was NULL"); + return false; + } else if (serialp == NULL) { + trpz_pemsg(emsg, "serialp was NULL"); + return false; + } + + dlen = strlen(domain_nm); + + if (dlen > 0U && domain_nm[dlen - 1] == '.') { + dlen--; + } + + for (n = 0; n < trsp->num_zones; n++) { + if (dlen != strlen(trsp->all_zones[n].name)) { + continue; + } else if (!has_base_zone(trsp, n)) { + continue; + } + + if ((strlen(trsp->all_zones[n].name) == dlen) && + (!strncmp(trsp->all_zones[n].name, domain_nm, dlen))) + { + if (!trsp->all_zones[n].serial) { + trsp->all_zones[n].serial = time(NULL); + } + + *serialp = trsp->all_zones[n].serial; + return true; + } + } + + trpz_pemsg(emsg, "zone not found"); + return false; +} + +static bool +domain_ntop(const u_char *src, char *dst, size_t dstsiz) { + const unsigned char *sptr = src; + char *dptr = dst, *dend = dst + dstsiz; + + if (dst == NULL || dstsiz == 0) { + return false; + } + + memset(dst, 0, dstsiz); + + while (*sptr) { + if ((dptr + *sptr) > dend) { + return false; + } + + if (sptr != src) { + *dptr++ = '.'; + } + + memmove(dptr, sptr + 1, *sptr); + dptr += *sptr; + sptr += *sptr; + sptr++; + } + + return true; +} + +static bool +domain_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen, + bool lower) { + unsigned char *dptr = dst; + const unsigned char *dend = dst + dstsiz; + char *tmps = NULL, *tok = NULL, *tptr = NULL; + + UNUSED(lower); + + if (src == NULL || dst == NULL || dstsiz == 0) { + return false; + } + + memset(dst, 0, dstsiz); + + tmps = strdup(src); + if (tmps == NULL) { + perror("strdup"); + return false; + } + + tptr = tmps; + + SET_IF_NOT_NULL(dstlen, 0); + + while (tptr && *tptr) { + tok = strsep(&tptr, "."); + + if ((dptr + strlen(tok) + 1) > dend) { + free(tmps); + return false; + } + + *dptr++ = strlen(tok); + memmove(dptr, tok, strlen(tok)); + dptr += strlen(tok); + + if (dstlen != NULL) { + (*dstlen) += (1 + strlen(tok)); + } + } + + if (dptr >= dend) { + free(tmps); + return false; + } + + *dptr = 0; + + if (dstlen != NULL) { + (*dstlen)++; + } + + free(tmps); + + return true; +} + +/* XXX: needs IPv6 support. */ +bool +trpz_rsp_clientip_prefix(librpz_emsg_t *emsg, librpz_prefix_t *prefix, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + unsigned int cbytes[5] = { 0 }; + uint8_t *aptr = NULL; + + if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL"); + return false; + } else if (prefix == NULL) { + trpz_pemsg(emsg, "prefix was NULL"); + return false; + } + + memset(prefix, 0, sizeof(*prefix)); + + if (trsp->rstack[0].result.trig != LIBRPZ_TRIG_CLIENT_IP) { + return true; + } + + if (sscanf(trsp->rstack[0].dname, "%u.%u.%u.%u.%u", &cbytes[0], + &cbytes[1], &cbytes[2], &cbytes[3], &cbytes[4]) != 5) + { + char abuf[64] = { 0 }; + int family = 0; + + if (sscanf(trsp->rstack[0].dname, "%u.", &cbytes[0]) != 1) { + return true; + } + + if (get_address_info(trsp->rstack[0].dname, &family, abuf, NULL, + NULL) < 0) + { + return true; + } else if (family != AF_INET6) { + return true; + } + + aptr = (uint8_t *)&(prefix->addr.in6); + memset(aptr, 0, sizeof(prefix->addr.in6)); + + if (inet_pton(AF_INET6, abuf, aptr) != 1) { + return true; + } + + prefix->family = AF_INET6; + prefix->len = cbytes[0]; + + return true; + } + + prefix->family = AF_INET; + prefix->len = cbytes[0]; + + if (prefix->len <= 24) { + cbytes[1] = 0; + } + + if (prefix->len <= 16) { + cbytes[2] = 0; + } + + if (prefix->len == 86) { + cbytes[3] = 0; + } + + aptr = (uint8_t *)&(prefix->addr.in); + *aptr++ = cbytes[4]; + *aptr++ = cbytes[3]; + *aptr++ = cbytes[2]; + *aptr++ = cbytes[1]; + + return true; +} + +bool +trpz_have_trig(librpz_trig_t trig, bool ipv6, const librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + size_t ind = ipv6 ? 1 : 0; + + if (rsp == NULL) { + return false; + } + + /* No hit, so look in all zones for trigger. */ + if (trsp->stack_idx == 0 || trsp->rstack[0].result.policy == 0) { + ssize_t max_z = (trsp->last_zone >= 0) + ? trsp->last_zone + : (ssize_t)trsp->num_zones - 0; + + for (ssize_t n = 0; n < max_z; n++) { + if (!trsp->have_rd && + !trsp->all_zones[n].not_recursive_only) + { + continue; + } else if (trsp->all_zones[n].has_triggers[ind][trig]) { + return true; + } else if (trsp->all_zones[n].ip_as_ns && + (((trig == LIBRPZ_TRIG_IP) && + trsp->all_zones[n] + .has_triggers[ind] + [LIBRPZ_TRIG_NSIP]) || + ((trig == LIBRPZ_TRIG_NSIP) && + trsp->all_zones[n] + .has_triggers[ind] + [LIBRPZ_TRIG_IP]))) + { + return true; + } else if (trsp->all_zones[n].qname_as_ns && + (((trig == LIBRPZ_TRIG_QNAME) && + trsp->all_zones[n].has_triggers + [ind][LIBRPZ_TRIG_NSDNAME]) || + ((trig == LIBRPZ_TRIG_NSDNAME) && + trsp->all_zones[n] + .has_triggers[ind] + [LIBRPZ_TRIG_QNAME]))) + { + return true; + } + } + + return false; + } + + /* Special case of first base zone. */ + if (trsp->rstack[0].result.dznum == 0 && + (trig > trsp->rstack[0].result.trig)) + { + return false; + } + + /* Otherwise check lower zones (of higher precedence). */ + for (size_t n = 0; n <= (trsp->rstack[0].result.dznum); n++) { + if (!trsp->have_rd && !trsp->all_zones[n].not_recursive_only) { + continue; + } else if (trsp->all_zones[n].has_triggers[ind][trig]) { + return true; + } else if (trsp->all_zones[n].ip_as_ns && + (((trig == LIBRPZ_TRIG_IP) && + trsp->all_zones[n] + .has_triggers[ind][LIBRPZ_TRIG_NSIP]) || + ((trig == LIBRPZ_TRIG_NSIP) && + trsp->all_zones[n] + .has_triggers[ind][LIBRPZ_TRIG_IP]))) + { + return true; + } else if (trsp->all_zones[n].qname_as_ns && + (((trig == LIBRPZ_TRIG_QNAME) && + trsp->all_zones[n] + .has_triggers[ind][LIBRPZ_TRIG_NSDNAME]) || + ((trig == LIBRPZ_TRIG_NSDNAME) && + trsp->all_zones[n] + .has_triggers[ind][LIBRPZ_TRIG_QNAME]))) + { + return true; + } + } + + return false; +} + +bool +trpz_rsp_rr(librpz_emsg_t *emsg, uint16_t *typep, uint16_t *classp, + uint32_t *ttlp, librpz_rr_t **rrp, librpz_result_t *result, + const uint8_t *qname, size_t qname_size, librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + trpz_result_t *last_result = NULL; + + if (result == NULL) { + trpz_pemsg(emsg, "result was NULL"); + return false; + } else if (rsp == NULL) { + trpz_pemsg(emsg, "rsp was NULL"); + return false; + } + + last_result = &(trsp->rstack[0]); + + if (last_result->rridx < last_result->nrrs) { + trpz_rr_t *this_rr = &(last_result->rrs[last_result->rridx]); + + if (classp != NULL) { + *classp = this_rr->class; + } + + if (ttlp != NULL) { + *ttlp = 3600; + } + + SET_IF_NOT_NULL(typep, this_rr->type); + + if (rrp != NULL) { + uint8_t *copy_src = NULL, *nrdata = NULL; + size_t to_copy, needed; + + copy_src = this_rr->rdata; + to_copy = this_rr->rdlength; + + /* If there's CNAME wild card expansion */ + if (qname != NULL && qname_size != 0 && + (this_rr->type == ns_t_cname) && + (this_rr->rdlength > 2)) + { + if (this_rr->rdata[0] == 1 && + this_rr->rdata[1] == '*') + { + char tmpexp[256] = { 0 }, + tmpexp2[256] = { 0 }, tmpexp3[256]; + + wdns_domain_to_str(this_rr->rdata, + this_rr->rdlength, + tmpexp); + wdns_domain_to_str(qname, qname_size, + tmpexp2); + + if (tmpexp2[strlen(tmpexp2) - 1] == '.') + { + tmpexp2[strlen(tmpexp2) - 1] = + 0; + } + + if (strncmp(tmpexp, "*.", 2) == 0) { + int nrd; + uint32_t n = snprintf( + tmpexp3, + sizeof(tmpexp3), + "%s.%s", tmpexp2, + &tmpexp[2]); + if (n > sizeof(tmpexp3)) { + trpz_pemsg( + emsg, + "%s truncated", + tmpexp3); + return false; + } + nrd = wdns_str_to_name( + tmpexp3, &nrdata, 1); + if (nrd < 0) { + trpz_pemsg( + emsg, + "Error packing " + "domain"); + return false; + } + to_copy = nrd; + copy_src = nrdata; + } + } + } + + needed = sizeof(**rrp) + to_copy; + + *rrp = calloc(1, needed); + if (*rrp == NULL) { + trpz_pemsg(emsg, "calloc: %s", strerror(errno)); + if (nrdata != NULL) { + free(nrdata); + } + return false; + } + + (*rrp)->type = htons(this_rr->type); + (*rrp)->class = htons(this_rr->class); + (*rrp)->ttl = htonl(this_rr->ttl); + (*rrp)->rdlength = htons(to_copy); + memmove((*rrp)->rdata, copy_src, to_copy); + if (nrdata != NULL) { + free(nrdata); + } + } + + result->next_rr = this_rr->rrn; + trsp->rstack[0].result.next_rr = this_rr->rrn; + last_result->rridx++; + } else { + SET_IF_NOT_NULL(typep, ns_t_invalid); + + if (rrp != NULL) { + *rrp = NULL; + } + + result->next_rr = 0; + trsp->rstack[0].result.next_rr = 0; + } + + return true; +} + +bool +trpz_rsp_forget_zone(librpz_emsg_t *emsg, librpz_cznum_t znum, + librpz_rsp_t *rsp) { + trpz_rsp_t *trsp = (trpz_rsp_t *)rsp; + + if (znum >= trsp->num_zones) { + trpz_pemsg(emsg, "invalid zone number"); + return false; + } else if (trsp->all_zones[znum].forgotten) { + trpz_pemsg(emsg, "zone already forgotten"); + return false; + } + + trsp->all_zones[znum].forgotten = true; + + return true; +} diff --git a/bin/tests/system/rpz/testlib/test-data.c b/bin/tests/system/rpz/testlib/test-data.c new file mode 100644 index 0000000..591ecdb --- /dev/null +++ b/bin/tests/system/rpz/testlib/test-data.c @@ -0,0 +1,1491 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Limited implementation of the DNSRPS API for testing purposes. + * + * Copyright (c) 2016-2017 Farsight Security, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "test-data.h" + +const rpz_soa_t g_soa_record = { "a.rpz-ns.dns-nod.net", + "nod-admin.fsi.io", + 12345, + 3600, + 1200, + 604800, + 60 }; + +int +wdns_str_to_name(const char *str, uint8_t **pbuf, bool downcase); + +static char * +str_printf(const char *fmt, ...) { + va_list ap; + char tbuf[8192], *result = NULL; + + va_start(ap, fmt); + vsnprintf(tbuf, sizeof(tbuf) - 1, fmt, ap); + tbuf[sizeof(tbuf) - 1] = 0; + va_end(ap); + + result = strdup(tbuf); + if (result == NULL) { + perror("strdup"); + } + + return result; +} + +/* + * Given a config-ready RPZ IP address, determine its family and normal + * canonical representation. + */ +int +get_address_info(const char *astr, int *pfamily, char *pbuf, + const char *optname, char **errp) { + char tmpc[512] = { 0 }; + char *tok = NULL, *tptr = tmpc, *last_tok = NULL; + size_t lcount = 0, bcount = 0; + unsigned int prefix = 0, values[16] = { 0 }, hex_values[16] = { 0 }; + bool is_ipv6 = false; + + if (astr == NULL || pfamily == NULL || pbuf == NULL) { + return -1; + } + + strncpy(tmpc, astr, sizeof(tmpc) - 1); + + while ((tok = strsep(&tptr, "."))) { + char *eptr = NULL; + unsigned long val; + + lcount++; + last_tok = tok; + + errno = 0; + val = strtoul(tok, &eptr, 10); + + if (errno != 0 || *eptr != '\0') { + bool bad = false; + + bcount++; + errno = 0; + eptr = NULL; + val = strtoul(tok, &eptr, 16); + + if (errno || *eptr != '\0') { + if (strcmp(tok, "zz") == 0) { + val = ~0; + is_ipv6 = true; + } else { + bad = true; + } + } + + if (!bad && (lcount > 1)) { + hex_values[lcount - 2] = val; + } + } else { + if (val > 255) { + bcount++; + } + + if (lcount == 1) { + prefix = val; + } else if (lcount > 1) { + unsigned int hexval; + values[lcount - 2] = val; + + /* + * All integer strings are valid hex + * strings, but decimal values are longer, + * so we have to check for overflow when + * reading as hex. + */ + errno = 0; + hexval = strtoul(tok, &eptr, 16); + if (errno != 0) { + return -1; + } + hex_values[lcount - 2] = hexval; + } + } + } + + if (last_tok && (strncmp(last_tok, "rpz-", 4) == 0)) { + lcount--; + bcount--; + } + + /* Not acceptable for either address family. */ + if (lcount > 9) { + return -1; + } + + *pfamily = (!is_ipv6 && (lcount == 5)) ? AF_INET : AF_INET6; + + /* + * For AF_INET we expect exactly 4 "good" (0<->255) octets and the + * subnet mask. + */ + if (*pfamily == AF_INET) { + if (prefix > 32) { + if (errp != NULL) { + *errp = str_printf( + "invalid rpz IP address \"%s\"; " + "invalid prefix length of %u", + (optname ? optname : astr), prefix); + } + + return -1; + } else if (bcount > 0) { + return -1; + } + + sprintf(pbuf, "%u.%u.%u.%u", values[3], values[2], values[1], + values[0]); + } else { + size_t n; + + if (prefix > 128) { + if (errp != NULL) { + *errp = str_printf( + "invalid rpz IP address \"%s\"; " + "invalid prefix length of %u", + (optname ? optname : astr), prefix); + } + + return -1; + } + + *pbuf = 0; + + /* + * Walk the values backward. Account for :: and discard + * chunks > 2 octets. + */ + for (n = lcount - 1; n > 0; n--) { + if (hex_values[n - 1] == ~0U) { + strcat(pbuf, ":"); + } else { + if (hex_values[n - 1] > 0xffff) { + return -1; + } else if (n > 1) { + sprintf(&pbuf[strlen(pbuf)], + "%x:", hex_values[n - 1]); + } else { + sprintf(&pbuf[strlen(pbuf)], "%x", + hex_values[n - 1]); + } + } + } + } + + return 0; +} + +rpz_soa_t * +parse_serial(unsigned char *rdata, size_t rdlen) { + rpz_soa_t *result = NULL; + char dname[WDNS_PRESLEN_NAME]; + size_t mlen, rlen; + uint32_t *uptr = NULL; + + result = calloc(1, sizeof(*result)); + if (result == NULL) { + perror("calloc"); + return NULL; + } + + mlen = wdns_domain_to_str(rdata, rdlen, dname); + result->mname = strdup(dname); + rlen = wdns_domain_to_str(rdata + mlen, rdlen - mlen, dname); + result->rname = strdup(dname); + uptr = (uint32_t *)(rdata + mlen + rlen); + result->serial = ntohl(*uptr); + uptr++; + result->refresh = ntohl(*uptr); + uptr++; + result->retry = ntohl(*uptr); + uptr++; + result->expire = ntohl(*uptr); + uptr++; + result->minimum = ntohl(*uptr); + + return result; +} + +size_t +wdns_domain_to_str(const uint8_t *src, size_t src_len, char *dst) { + size_t bytes_read = 0; + size_t bytes_remaining = src_len; + uint8_t oclen; + + if (src == NULL) { + return 0; + } + + oclen = *src; + while (bytes_remaining > 0 && oclen != 0) { + src++; + bytes_remaining--; + + bytes_read += oclen + 1 /* length octet */; + + while (oclen-- && bytes_remaining > 0) { + uint8_t c = *src++; + bytes_remaining--; + + if (c == '.' || c == '\\') { + *dst++ = '\\'; + *dst++ = c; + } else if (c >= '!' && c <= '~') { + *dst++ = c; + } else { + snprintf(dst, 5, "\\%.3d", c); + dst += 4; + } + } + *dst++ = '.'; + oclen = *src; + } + if (bytes_read == 0) { + *dst++ = '.'; + } + bytes_read++; + + *dst = '\0'; + return bytes_read; +} + +/* Add parsed update specification to maintained list of nodes. */ +static trpz_result_t * +apply_update_to_set(trpz_result_t **results, size_t *pnresults, + trpz_zone_t **pzones, const char *node, size_t zidx, + uint32_t ttl, librpz_trig_t trigger, librpz_policy_t policy, + int *modified, unsigned long flags, char **errp) { + size_t n; + int family = 0; + + UNUSED(flags); + + *modified = 0; + + switch (trigger) { + case LIBRPZ_TRIG_QNAME: + case LIBRPZ_TRIG_NSDNAME: + (*pzones)[zidx].has_triggers[0][trigger] = 1; + break; + case LIBRPZ_TRIG_CLIENT_IP: + case LIBRPZ_TRIG_IP: + case LIBRPZ_TRIG_NSIP: { + char abuf[128]; + + if (get_address_info(node, &family, abuf, NULL, errp) < 0) { + fprintf(stderr, + "Error in determining IP address type: %s\n", + node); + return NULL; + } else if (family == AF_INET) { + (*pzones)[zidx].has_triggers[0][trigger] = 1; + } else { + (*pzones)[zidx].has_triggers[1][trigger] = 1; + } + + } break; + default: + break; + } + + for (n = 0; n < *pnresults; n++) { + trpz_result_t *rptr = &((*results)[n]); + + if (rptr->result.cznum != zidx) { + continue; + } + + if (!strcmp(rptr->dname, node)) { + if (rptr->result.trig == trigger && + rptr->result.policy == policy && rptr->ttl == ttl) + { + return rptr; + } + + rptr->result.trig = trigger; + rptr->result.policy = policy; + rptr->result.zpolicy = policy; + rptr->ttl = ttl; + *modified = 1; + return rptr; + } + } + + /* No match. Instead, append. */ + (*pnresults)++; + + *results = realloc(*results, (*pnresults * sizeof(**results))); + if (*results == NULL) { + perror("realloc"); + return NULL; + } + + memset(&((*results)[*pnresults - 1]), 0, sizeof(**results)); + (*results)[*pnresults - 1].dname = strdup(node); + (*results)[*pnresults - 1].ttl = ttl; + (*results)[*pnresults - 1].result.trig = trigger; + (*results)[*pnresults - 1].result.policy = policy; + (*results)[*pnresults - 1].result.zpolicy = policy; + (*results)[*pnresults - 1].result.cznum = zidx; + (*results)[*pnresults - 1].result.dznum = zidx; + (*results)[*pnresults - 1].result.log = 1; + (*results)[*pnresults - 1].poverride = policy; + (*results)[*pnresults - 1].match_trig = trigger; + + if (family == AF_INET6) { + (*results)[*pnresults - 1].flags |= NODE_FLAG_IPV6_ADDRESS; + } + + *modified = 1; + return &((*results)[*pnresults - 1]); +} + +/* + * Add a parsed RR value that is maintained in conjunction with record policy + * items. + */ +static int +add_other_rr(trpz_result_t *node, const char *rrtype, const char *val, + uint32_t ttl, int *modified) { + trpz_rr_t nrec = { 0 }; + size_t n; + static atomic_uint_fast32_t rrn = 1; + + *modified = 0; + + nrec.class = ns_c_in; + nrec.ttl = ttl; + nrec.rrn = atomic_fetch_add_relaxed(&rrn, 1); + + if (!strcasecmp(rrtype, "A")) { + uint32_t addr; + + if (inet_pton(AF_INET, val, &addr) != 1) { + fprintf(stderr, + "Error determining policy record IPv4 address: " + "%s\n", + val); + return -1; + } + + nrec.type = ns_t_a; + nrec.rdlength = sizeof(uint32_t); + + nrec.rdata = malloc(nrec.rdlength); + if (nrec.rdata == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + memmove(nrec.rdata, &addr, nrec.rdlength); + } else if (!strcasecmp(rrtype, "AAAA")) { + char addr[16] = { 0 }; + + if (inet_pton(AF_INET6, val, addr) != 1) { + fprintf(stderr, + "Error determining policy record IPv6 address: " + "%s\n", + val); + return -1; + } + + nrec.type = ns_t_aaaa; + nrec.rdlength = sizeof(addr); + + nrec.rdata = malloc(nrec.rdlength); + if (nrec.rdata == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + memmove(nrec.rdata, addr, nrec.rdlength); + } else if (!strcasecmp(rrtype, "TXT")) { + nrec.type = ns_t_txt; + nrec.rdlength = 1 + strlen(val); + + nrec.rdata = calloc(nrec.rdlength, 1); + if (nrec.rdata == NULL) { + perror("calloc"); + exit(EXIT_FAILURE); + } + + nrec.rdata[0] = nrec.rdlength - 1; + memmove(&(nrec.rdata[1]), val, nrec.rdlength - 1); + } else if (!strcasecmp(rrtype, "CNAME")) { + int ret; + + nrec.type = ns_t_cname; + ret = wdns_str_to_name(val, &(nrec.rdata), 1); + + if (ret <= 0) { + fprintf(stderr, + "Error processing CNAME policy record data " + "(%d)!\n", + ret); + return -1; + } + + nrec.rdlength = ret; + } else if (!strcasecmp(rrtype, "DNAME")) { + int ret; + + nrec.type = ns_t_dname; + ret = wdns_str_to_name(val, &(nrec.rdata), 1); + + if (ret <= 0) { + fprintf(stderr, + "Error processing DNAME policy record data " + "(%d)!\n", + ret); + return -1; + } + + nrec.rdlength = ret; + } else { + fprintf(stderr, + "Error: unsupported policy record type: \"%s\"\n", + rrtype); + return -1; + } + + for (n = 0; n < node->nrrs; n++) { + trpz_rr_t *rptr = &(node->rrs[n]); + + /* Same thing. Don't replace. */ + if (rptr->type == nrec.type && rptr->class == nrec.class && + rptr->ttl == nrec.ttl && rptr->rdlength == nrec.rdlength && + !memcmp(rptr->rdata, nrec.rdata, nrec.rdlength)) + { + free(nrec.rdata); + return n + 1; + } + } + + node->nrrs++; + + node->rrs = realloc(node->rrs, (node->nrrs * sizeof(*(node->rrs)))); + if (node->rrs == NULL) { + perror("realloc"); + exit(EXIT_FAILURE); + } + + memset(&(node->rrs[node->nrrs - 1]), 0, sizeof(node->rrs[0])); + node->rrs[node->nrrs - 1] = nrec; + *modified = 1; + + return node->nrrs; +} + +void +reverse_labels(const char *str, char *pbuf) { + const char *sptr = str, *end = NULL; + + if (sptr == NULL || *sptr == 0) { + return; + } + + sptr += (strlen(sptr) - 1); + end = sptr + 1; + *pbuf = 0; + + if (*sptr == '.') { + sptr--; + end--; + } + + while (sptr >= str) { + if ((*sptr != '.') && (sptr != str)) { + sptr--; + continue; + } + + if (sptr == str) { + strncat(pbuf, sptr, (end - sptr)); + break; + } + + strncat(pbuf, sptr + 1, (end - (sptr + 1))); + strcat(pbuf, "."); + end = sptr--; + } + + if (pbuf[strlen(pbuf) - 1] == '.') { + pbuf[strlen(pbuf) - 1] = 0; + } + + return; +} + +/* Parse trailing zone options as specified in a cstr line */ +unsigned long +parse_zone_options(const char *str) { + char tmpstr[8192] = { 0 }; + char *tok = NULL, *sptr = NULL; + unsigned long result = 0; + + if (str == NULL || *str == 0) { + return 0; + } + + strncpy(tmpstr, str, sizeof(tmpstr) - 1); + + tok = strtok_r(tmpstr, " ", &sptr); + + while (tok) { + if (!strcasecmp(tok, "policy")) { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "passthru")) { + result |= ZOPT_POLICY_PASSTHRU; + } else if (!strcasecmp(tok, "drop")) { + result |= ZOPT_POLICY_DROP; + } else if (!strcasecmp(tok, "tcp-only")) { + result |= ZOPT_POLICY_TCP_ONLY; + } else if (!strcasecmp(tok, "nxdomain")) { + result |= ZOPT_POLICY_NXDOMAIN; + } else if (!strcasecmp(tok, "nodata")) { + result |= ZOPT_POLICY_NODATA; + } else if (!strcasecmp(tok, "given")) { + result |= ZOPT_POLICY_GIVEN; + } else if (!strcasecmp(tok, "disabled")) { + result |= ZOPT_POLICY_DISABLED; + } else if (!strcasecmp(tok, "no-op")) { + ; + } + } else { + if (!strcasecmp(tok, "max-policy-ttl")) { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + } else if (!strcasecmp(tok, "recursive-only")) { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "yes")) { + result |= ZOPT_RECURSIVE_ONLY; + } else if (!strcasecmp(tok, "no")) { + result |= ZOPT_NOT_RECURSIVE_ONLY; + } + + } else { + if (!strcasecmp(tok, "qname-as-ns")) { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "yes")) { + result |= ZOPT_QNAME_AS_NS; + } + + } else if (!strcasecmp(tok, "ip-as-ns")) { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "yes")) { + result |= ZOPT_IP_AS_NS; + } + + } else if (!strcasecmp(tok, + "qname-wait-recurse")) + { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "no")) { + result |= + ZOPT_NO_QNAME_WAIT_RECURSE; + } + + } else if (!strcasecmp(tok, + "nsip-wait-recurse")) + { + tok = strtok_r(NULL, " ", &sptr); + if (tok == NULL) { + break; + } + + if (!strcasecmp(tok, "no")) { + result |= + ZOPT_NO_NSIP_WAIT_RECURSE; + } + } + } + } + + tok = strtok_r(NULL, " ", &sptr); + } + + /* LIBRPZ_POLICY_CNAME, */ + return result; +} + +/* + * Parse an update string and attempt to add any relevant data to the node + * and policy RR tables. + */ +int +apply_update(const char *updstr, trpz_result_t **presults, size_t *pnresults, + trpz_zone_t **pzones, size_t *pnzones, int is_static, + unsigned long flags, char **errp) { + trpz_result_t *res = NULL; + char cmdbuf[64] = { 0 }, nodebuf[256] = { 0 }, rrbuf[32] = { 0 }, + databuf[256] = { 0 }; + char *nend = NULL; + librpz_policy_t policy = LIBRPZ_POLICY_UNDEFINED; + librpz_trig_t trig = LIBRPZ_TRIG_QNAME; + unsigned int ttl; + ssize_t n, zidx = -1; + size_t ndlen = 0, last_matchlen = 0; + int nfield, zupd = 0; + + nfield = sscanf(updstr, "%63s %255s %u %31s %255s", cmdbuf, nodebuf, + &ttl, rrbuf, databuf); + if (nfield < 1) { + return -1; + } + + /* + * Special case for handling zone additions; here the 'ttl' field + * becomes a serial. + */ + if (!strcasecmp(cmdbuf, "zone")) { + trpz_zone_t *zptr = NULL; + bool qname_as_ns = false, ip_as_ns = false, + not_recursive_only = false, do_inc = false; + bool no_qname_as_ns = false, no_ip_as_ns = false, + recursive_only = false, no_nsip_wait_recurse = false; + + if (nfield < 3) { + return -1; + } + + if (!strcasecmp(rrbuf, "qname_as_ns")) { + qname_as_ns = true; + } else if (!strcasecmp(rrbuf, "ip_as_ns")) { + ip_as_ns = true; + } else if (!strcasecmp(rrbuf, "not_recursive_only")) { + not_recursive_only = true; + } else if (!strcasecmp(rrbuf, "inc")) { + do_inc = true; + } else if (!strcasecmp(rrbuf, "no_qname_as_ns")) { + no_qname_as_ns = true; + } else if (!strcasecmp(rrbuf, "no_ip_as_ns")) { + no_ip_as_ns = true; + } else if (!strcasecmp(rrbuf, "recursive_only")) { + recursive_only = true; + } else if (!strcasecmp(rrbuf, "no_nsip_wait_recurse")) { + no_nsip_wait_recurse = true; + } + + if (flags & ZOPT_RECURSIVE_ONLY) { + recursive_only = true; + not_recursive_only = false; + } else if (flags & ZOPT_NOT_RECURSIVE_ONLY) { + recursive_only = false; + not_recursive_only = true; + } + + if (flags & ZOPT_NO_NSIP_WAIT_RECURSE) { + no_nsip_wait_recurse = true; + } + + for (n = 0; (size_t)n < *pnzones; n++) { + if (!strcmp((*pzones)[n].name, nodebuf)) { + /* + * Force override of serial. But only if + * serial is non-zero. + */ + if (ttl) { + if (do_inc) { + (*pzones)[n].serial += ttl; + } else { + (*pzones)[n].serial = ttl; + } + } + + (*pzones)[n].has_update = 0; + + if (qname_as_ns) { + (*pzones)[n].qname_as_ns = true; + } + + if (ip_as_ns) { + (*pzones)[n].ip_as_ns = true; + } + + if (no_qname_as_ns) { + (*pzones)[n].qname_as_ns = false; + } + + if (no_ip_as_ns) { + (*pzones)[n].ip_as_ns = false; + } + + if (not_recursive_only) { + (*pzones)[n].not_recursive_only = true; + } + + if (recursive_only) { + (*pzones)[n].not_recursive_only = false; + } + + if (flags & ZOPT_NO_QNAME_WAIT_RECURSE) { + (*pzones)[n].no_qname_wait_recurse = + true; + } + + if (no_nsip_wait_recurse) { + (*pzones)[n].no_nsip_wait_recurse = + true; + } + + return 0; + } + } + + (*pnzones)++; + + *pzones = realloc(*pzones, (*pnzones * sizeof(**pzones))); + if (*pzones == NULL) { + perror("realloc"); + exit(EXIT_FAILURE); + } + + zptr = &(*pzones)[*pnzones - 1]; + *zptr = (trpz_zone_t){ + .serial = ttl, + .qname_as_ns = qname_as_ns, + .ip_as_ns = ip_as_ns, + .flags = flags, + .not_recursive_only = not_recursive_only, + }; + + if (qname_as_ns) { + (*pzones)[n].qname_as_ns = true; + } + + if (ip_as_ns) { + (*pzones)[n].ip_as_ns = true; + } + + if (flags & ZOPT_NO_QNAME_WAIT_RECURSE) { + (*pzones)[n].no_qname_wait_recurse = true; + } + + if (no_nsip_wait_recurse) { + (*pzones)[n].no_nsip_wait_recurse = true; + } + + strncpy(zptr->name, nodebuf, LIBRPZ_MAXDOMAIN + 1); + if (zptr->name[strlen(zptr->name) - 1] == '.') { + zptr->name[strlen(zptr->name) - 1] = 0; + } + + return 0; + } else if (nfield != 5) { + return -1; + } + + if (strcasecmp(cmdbuf, "add")) { + fprintf(stderr, "Warning: only update add action is currently " + "supported!\n"); + return -1; + } + + if (!strcasecmp(rrbuf, "A")) { + policy = LIBRPZ_POLICY_RECORD; + } else if (!strcasecmp(rrbuf, "CNAME")) { + if (!strcmp(databuf, ".")) { + policy = LIBRPZ_POLICY_NXDOMAIN; + } else if (!strcmp(databuf, "*.")) { + policy = LIBRPZ_POLICY_NODATA; + } else if (!strcasecmp(databuf, "rpz-passthru.")) { + policy = LIBRPZ_POLICY_PASSTHRU; + } else if (!strcasecmp(databuf, "rpz-drop.")) { + policy = LIBRPZ_POLICY_DROP; + } else if (!strcasecmp(databuf, "rpz-tcp-only.")) { + policy = LIBRPZ_POLICY_TCP_ONLY; + } else { + policy = LIBRPZ_POLICY_RECORD; + } + + } else if (!strcasecmp(rrbuf, "TXT")) { + char *ftext = NULL; + + ftext = strstr(updstr, databuf); + if (ftext == NULL) { + fprintf(stderr, "Error parsing TXT record: \"%s\"\n", + updstr); + return -1; + } + + if (*ftext == '"') { + *ftext++ = 0; + + if (ftext[strlen(ftext) - 1] == '"') { + ftext[strlen(ftext) - 1] = 0; + } + } + + strncpy(databuf, ftext, sizeof(databuf)); + databuf[sizeof(databuf) - 1] = 0; + policy = LIBRPZ_POLICY_RECORD; + } else if (!strcasecmp(rrbuf, "DNAME")) { + policy = LIBRPZ_POLICY_RECORD; + } else if (!strcasecmp(rrbuf, "AAAA")) { + policy = LIBRPZ_POLICY_RECORD; + } else { + fprintf(stderr, + "Warning: target \"%s\" is not currently supported!\n", + rrbuf); + return -1; + } + + if (policy == LIBRPZ_POLICY_UNDEFINED) { + fprintf(stderr, "Error: could not determine appropriate policy " + "for update!\n"); + return -1; + } + + for (n = 0; (size_t)n < *pnzones; n++) { + const char *zptr = nodebuf; + size_t cmplen; + + zptr += strlen(zptr) - 1; + + if (*zptr == '.') { + zptr--; + } + + cmplen = strlen((*pzones)[n].name); + + if ((*pzones)[n].name[cmplen - 1] == '.') { + cmplen--; + } + + zptr -= (cmplen - 1); + + if ((zptr <= nodebuf) || (*(zptr - 1) != '.')) { + continue; + } + + if (!strncmp((*pzones)[n].name, zptr, cmplen)) { + /* + * We don't break immediately after a match because + * there might be a better one yet. + */ + if (cmplen > last_matchlen) { + ndlen = strlen(nodebuf) - cmplen; + + if (nodebuf[strlen(nodebuf) - 1] == '.') { + ndlen--; + } + + /* + * Account for the period between the node name + * and zone name. + */ + ndlen--; + zidx = n; + last_matchlen = cmplen; + } + } + } + + if (memmem(nodebuf, ndlen, ".rpz-", 5)) { + char *tptr = nodebuf + ndlen - 1; + size_t slen; + + while (strncmp(tptr, ".rpz-", 5)) { + tptr--; + } + + slen = nodebuf + ndlen - tptr; + nend = tptr; + + if (slen == 7 && !memcmp(tptr, ".rpz-ip", 7)) { + trig = LIBRPZ_TRIG_IP; + } else if (slen == 9 && !memcmp(tptr, ".rpz-nsip", 9)) { + trig = LIBRPZ_TRIG_NSIP; + } else if (slen == 14 && !memcmp(tptr, ".rpz-client-ip", 14)) { + trig = LIBRPZ_TRIG_CLIENT_IP; + } else if (slen == 12 && !memcmp(tptr, ".rpz-nsdname", 12)) { + trig = LIBRPZ_TRIG_NSDNAME; + } else { + fprintf(stderr, "Warning: unknown suffix \"%s\"\n", + tptr); + nend = NULL; + } + + /* We saved the trigger value, so shave that part off. */ + *tptr = 0; + } + + if (zidx == -1) { + return 0; + } + + nodebuf[ndlen] = 0; + + /* + * The original, deprecated PASSTHRU encoding of a CNAME pointing + * to the trigger QNAME might still be in use in local, private + * policy zones, and so it is still recognized by RPZ subscriber + * implementations as of 2016. + */ + if ((policy == LIBRPZ_POLICY_RECORD) && !strcasecmp(rrbuf, "cname")) { + char tmpname[512] = { 0 }; + + strncpy(tmpname, databuf, sizeof(tmpname) - 1); + + if ((nodebuf[strlen(nodebuf) - 1] == '.') && + (tmpname[strlen(tmpname) - 1] != '.')) + { + size_t tlen = strlen(tmpname); + + tmpname[tlen] = '.'; + tmpname[tlen + 1] = 0; + } else if ((nodebuf[strlen(nodebuf) - 1] != '.') && + (tmpname[strlen(tmpname) - 1] == '.')) + { + tmpname[strlen(tmpname) - 1] = 0; + } + + /* A special case of PASSTHRU (with trailing characters) */ + if (nend != NULL && + (strlen(databuf) == (size_t)(nend - nodebuf)) && + !strncmp(databuf, nodebuf, (nend - nodebuf))) + { + policy = LIBRPZ_POLICY_PASSTHRU; + } + + if (!strcmp(nodebuf, tmpname)) { + policy = LIBRPZ_POLICY_PASSTHRU; + } + } + + res = apply_update_to_set(presults, pnresults, pzones, nodebuf, zidx, + ttl, trig, policy, &zupd, flags, errp); + + if (res) { + if (zupd && !is_static) { + (*pzones)[zidx].has_update = 1; + } else if (is_static) { + res->flags |= NODE_FLAG_STATIC_DATA; + } + + if (policy == LIBRPZ_POLICY_RECORD) { + /* + * Policy/RR change does not seem to prompt zone + * serial increment. (has_update) + */ + if (add_other_rr(res, rrbuf, databuf, ttl, &zupd) < 0) { + fprintf(stderr, + "Error: could not add policy record %s " + "/ %s\n", + rrbuf, databuf); + return -1; + } + } + } + + return 0; +} + +/* + * XXX: memory leak. Also, does not properly preserve "static" node entries, + * as envisioned. + */ +static void +free_nodes(trpz_result_t **presults, size_t *pnresults) { + size_t n, tot; + + if (presults == NULL || *presults == NULL) { + if (pnresults != NULL) { + *pnresults = 0; + } + return; + } + + tot = *pnresults; + + for (n = tot; n > 0; n--) { + trpz_result_t *res = &((*presults)[n - 1]); + size_t m; + + if (res->canonical != NULL) { + free(res->canonical); + } + + if (res->dname != NULL) { + free(res->dname); + } + + for (m = 0; m < res->nrrs; m++) { + if (res->rrs[m].rdata != NULL) { + free(res->rrs[m].rdata); + } + } + + if (res->rrs != NULL) { + free(res->rrs); + } + } + + free(*presults); + *presults = NULL; + *pnresults = 0; + + return; +} + +/* + * Perform only sanity checking on a data file's contents. + * + * Note that this function only really exists to facilitate the logging of error + * messages that may be expected to occur upon encounter with certain invalid + * node data in unit tests. + * + * fname is the pathname of the data file to be checked. + * errp is a pointer to an error string that may be set if this function fails. + * It is the responsibility of the caller to free this pointer if it is returned + * non-NULL. + * + * This function returns 0 on success, or -1 on failure, possibly setting *errp + * on failure. + */ +int +sanity_check_data_file(const char *fname, char **errp) { + FILE *f = NULL; + int result = -1; + + SET_IF_NOT_NULL(errp, NULL); + + f = fopen(fname, "r"); + if (f == NULL) { + fprintf(stderr, "couldn't sanity check %s\n", fname); + perror("fopen"); + return -1; + } + + while (!feof(f)) { + char line[1024] = { 0 }, cmdbuf[64] = { 0 }, + nodebuf[256] = { 0 }, rrbuf[32] = { 0 }, + databuf[256] = { 0 }; + char *lptr = line; + int nfield; + unsigned int ttl; + + if (!fgets(line, sizeof(line) - 1, f)) { + break; + } + + if (!line[0]) { + continue; + } + + if (line[strlen(line) - 1] == '\n') { + line[strlen(line) - 1] = 0; + } + + if (!line[0] || line[0] == ';') { + continue; + } + + while (*lptr && !isspace((unsigned char)*lptr)) { + lptr++; + } + + *lptr++ = 0; + + if (!strcasecmp(line, "server") || !strcasecmp(line, "send") || + !strcasecmp(line, "wipe") || + !strcasecmp(line, "rollback") || + !strcasecmp(line, "restart")) + { + continue; + } else if (strcasecmp(line, "static") && + strcasecmp(line, "update")) + { + if (errp != NULL) { + *errp = str_printf("Found unknown instruction " + "directive: \"%s\"\n", + line); + } + + goto out; + } + + while (isspace((unsigned char)*lptr)) { + lptr++; + } + + nfield = sscanf(lptr, "%63s %255s %u %31s %255s", cmdbuf, + nodebuf, &ttl, rrbuf, databuf); + + /* We don't care about checking zones - only node entries. */ + if (nfield != 5) { + continue; + } + + if (strcasecmp(cmdbuf, "add")) { + continue; + } + + if (strcasecmp(rrbuf, "A") && strcasecmp(rrbuf, "CNAME") && + strcasecmp(rrbuf, "TXT") && strcasecmp(rrbuf, "DNAME") && + strcasecmp(rrbuf, "AAAA")) + { + if (errp != NULL) { + *errp = str_printf("Target \"%s\" is not " + "currently supported!\n", + rrbuf); + } + + goto out; + } + + if (strstr(nodebuf, ".rpz-")) { + char abuf[64], tmpname[512]; + char *tptr = nodebuf; + size_t slen; + int family; + + while (strncmp(tptr, ".rpz-", 5)) { + tptr++; + } + + slen = nodebuf + strlen(nodebuf) - tptr; + + if (!(slen >= 8 && !memcmp(tptr, ".rpz-ip.", 8)) && + !(slen >= 10 && !memcmp(tptr, ".rpz-nsip.", 10)) && + !(slen >= 15 && + !memcmp(tptr, ".rpz-client-ip.", 15)) && + !(slen >= 13 && !memcmp(tptr, ".rpz-nsdname.", 13))) + { + continue; + } + + strncpy(tmpname, nodebuf, sizeof(tmpname) - 1); + tmpname[sizeof(tmpname) - 1] = 0; + + *tptr = 0; + + if (get_address_info(nodebuf, &family, abuf, tmpname, + errp) < 0) + { + goto out; + } + } + } + + result = 0; + +out: + fclose(f); + + return result; +} + +/* Load a database of nodes from a given filename. */ +int +load_all_updates(const char *fname, trpz_result_t **presults, size_t *pnresults, + trpz_zone_t **pzones, size_t *pnzones, char **errp) { + FILE *f = NULL; + + f = fopen(fname, "r"); + if (f == NULL) { + fprintf(stderr, "couldn't load updates from %s\n", fname); + perror("fopen"); + return -1; + } + + while (!feof(f)) { + char line[1024] = { 0 }; + char *lptr = line; + int is_static = 0; + + if (!fgets(line, sizeof(line) - 1, f)) { + break; + } + + if (!line[0]) { + continue; + } + + if (line[strlen(line) - 1] == '\n') { + line[strlen(line) - 1] = 0; + } + + if (!line[0]) { + strcpy(line, "send"); + } + + if (!line[0] || line[0] == ';') { + continue; + } + + while (*lptr && !isspace((unsigned char)*lptr)) { + lptr++; + } + + *lptr++ = 0; + + if (!strcasecmp(line, "server")) { + continue; + } else if (!strcasecmp(line, "send")) { + size_t n; + + for (n = 0; n < *pnzones; n++) { + if ((*pzones)[n].has_update) { + (*pzones)[n].serial += 1; + (*pzones)[n].rollback += 1; + (*pzones)[n].has_update = 0; + } + } + + continue; + } else if (!strcasecmp(line, "wipe") || + !strcasecmp(line, "rollback")) + { + size_t n; + int rollback; + + rollback = strcasecmp(line, "rollback") == 0; + + free_nodes(presults, pnresults); + + /* Now push forward the serial by # rollback */ + for (n = 0; n < *pnzones; n++) { + if (rollback) { + (*pzones)[n].serial += + (*pzones)[n].rollback; + (*pzones)[n].rollback = 0; + } + + memset((*pzones)[n].has_triggers, 0, + sizeof((*pzones)[n].has_triggers)); + } + + continue; + } else if (!strcasecmp(line, "static")) { + is_static = 1; + } else if (!strcasecmp(line, "restart")) { + size_t n; + + for (n = 0; n < *pnzones; n++) { + (*pzones)[n].serial = 1; + (*pzones)[n].rollback = 0; + } + + continue; + } else if (strcasecmp(line, "update")) { + fprintf(stderr, + "Warning: skipping unknown instruction " + "directive: \"%s\"\n", + line); + continue; + } + + /* Everything here is an update */ + while (isspace((unsigned char)*lptr)) { + lptr++; + } + + if (apply_update(lptr, presults, pnresults, pzones, pnzones, + is_static, 0, errp) == -1) + { + fprintf(stderr, + "Error: could not apply update \"%s\"\n", lptr); + fclose(f); + return -1; + } + } + + fclose(f); + + return 0; +} + +#define WDNS_MAXLEN_NAME 255 +int +wdns_str_to_name(const char *str, uint8_t **pbuf, bool downcase) { + const char *p = NULL; + size_t label_len; + ssize_t slen; + uint8_t c, *oclen = NULL, *data = NULL; + int res = -1; + + assert(pbuf != NULL); + + p = str; + slen = strlen(str); + + if (slen == 1 && *p == '.') { + *pbuf = malloc(1); + if (*pbuf == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } + *pbuf[0] = 0; + return 1; + } + + res = 0; + *pbuf = malloc(WDNS_MAXLEN_NAME); + if (*pbuf == NULL) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + data = *pbuf; + label_len = 0; + oclen = data++; + res++; + + for (;;) { + c = *p++; + label_len++; + + /* Will the wire name become too long? */ + if (res >= WDNS_MAXLEN_NAME) { + goto out; + } + + if (slen == 0) { + /* end of input */ + *oclen = --label_len; + *data++ = '\0'; + res++; + break; + } + + if (c >= 'A' && c <= 'Z') { + /* an upper case letter; downcase it */ + if (downcase) { + c |= 0x20; + } + *data++ = c; + res++; + } else if (c == '\\' && !isdigit((unsigned char)*p)) { + /* an escaped character */ + if (slen <= 0) { + goto out; + } + *data++ = *p; + res++; + p++; + slen--; + } else if (c == '\\' && slen >= 3) { + /* an escaped octet */ + char d[4]; + char *endptr = NULL; + long int val; + + d[0] = *p++; + d[1] = *p++; + d[2] = *p++; + d[3] = '\0'; + slen -= 3; + if (!isdigit((unsigned char)d[0]) || + !isdigit((unsigned char)d[1]) || + !isdigit((unsigned char)d[2])) + { + goto out; + } + val = strtol(d, &endptr, 10); + if (endptr != NULL && *endptr == '\0' && val >= 0 && + val <= 255) + { + uint8_t uval; + + uval = (uint8_t)val; + *data++ = uval; + res++; + } else { + goto out; + } + } else if (c == '\\') { + /* should not occur */ + goto out; + } else if (c == '.') { + /* end of label */ + *oclen = --label_len; + if (label_len == 0) { + goto out; + } + oclen = data++; + if (slen > 1) { + res++; + } + label_len = 0; + } else if (c != '\0') { + *data++ = c; + res++; + } + + slen--; + } + + return res; + +out: + free(*pbuf); + *pbuf = NULL; + return -1; +} diff --git a/bin/tests/system/rpz/testlib/test-data.h b/bin/tests/system/rpz/testlib/test-data.h new file mode 100644 index 0000000..63ae0f6 --- /dev/null +++ b/bin/tests/system/rpz/testlib/test-data.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Limited implementation of the DNSRPS API for testing purposes. + * + * Copyright (c) 2016-2017 Farsight Security, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LIBRPZ_LIB_OPEN 2 +#include + +#if __NAMESER < 19991006 +/* + * If the new API is not available define the values we use. + */ + +#define ns_c_in 1 + +#define ns_t_invalid 0 +#define ns_t_a 1 +#define ns_t_cname 5 +#define ns_t_txt 16 +#define ns_t_aaaa 28 +#define ns_t_dname 39 + +#endif + +#include "trpz.h" + +#define NODE_FLAG_IPV6_ADDRESS 0x1 +#define NODE_FLAG_STATIC_DATA 0x2 + +#define ZOPT_POLICY_PASSTHRU 0x0001 +#define ZOPT_POLICY_DROP 0x0002 +#define ZOPT_POLICY_TCP_ONLY 0x0004 +#define ZOPT_POLICY_NXDOMAIN 0x0008 +#define ZOPT_POLICY_NODATA 0x0010 +#define ZOPT_POLICY_GIVEN 0x0020 +#define ZOPT_POLICY_DISABLED 0x0040 + +#define ZOPT_RECURSIVE_ONLY 0x0100 +#define ZOPT_NOT_RECURSIVE_ONLY 0x0200 +#define ZOPT_QNAME_AS_NS 0x0400 +#define ZOPT_IP_AS_NS 0x0800 + +#define ZOPT_QNAME_WAIT_RECURSE 0x1000 +#define ZOPT_NO_QNAME_WAIT_RECURSE 0x2000 +#define ZOPT_NO_NSIP_WAIT_RECURSE 0x4000 + +typedef struct { + char name[256]; + uint32_t serial; + int has_update; + size_t rollback; + int has_triggers[2][LIBRPZ_TRIG_NSIP + 1]; + bool forgotten; + bool qname_as_ns, ip_as_ns; + bool not_recursive_only; + bool no_qname_wait_recurse, no_nsip_wait_recurse; + unsigned long flags; +} trpz_zone_t; + +typedef struct { + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t rdlength; + uint8_t *rdata; + unsigned int rrn; +} trpz_rr_t; + +typedef struct { + char *canonical; + char *dname; + librpz_result_t result; + uint32_t ttl; + trpz_rr_t *rrs; + size_t nrrs, rridx; + librpz_policy_t poverride, hidden_policy; + unsigned long flags; + librpz_trig_t match_trig; +} trpz_result_t; + +#define DECL_NODE(canon, name, policy, znum, trig) \ + { canon, name, { 0, 0, policy, policy, znum, znum, trig, true } }, + +#define NUM_ZONES_SNAPSHOT1 20 + +extern const rpz_soa_t g_soa_record; + +#define WDNS_PRESLEN_NAME 1025 +extern size_t +wdns_domain_to_str(const uint8_t *src, size_t src_len, char *dst); +extern int +wdns_str_to_name(const char *str, uint8_t **pbuf, bool downcase); + +extern void +reverse_labels(const char *str, char *pbuf); + +extern rpz_soa_t * +parse_serial(unsigned char *rdata, size_t rdlen); + +extern int +load_all_updates(const char *fname, trpz_result_t **presults, size_t *pnresults, + trpz_zone_t **pzones, size_t *pnzones, char **errp); +extern int +apply_update(const char *updstr, trpz_result_t **presults, size_t *pnresults, + trpz_zone_t **pzones, size_t *pnzones, int is_static, + unsigned long flags, char **errp); +extern int +sanity_check_data_file(const char *fname, char **errp); + +extern unsigned long +parse_zone_options(const char *str); + +extern int +get_address_info(const char *astr, int *pfamily, char *pbuf, + const char *optname, char **errp); diff --git a/bin/tests/system/rpz/testlib/trpz.h b/bin/tests/system/rpz/testlib/trpz.h new file mode 100644 index 0000000..96ffce0 --- /dev/null +++ b/bin/tests/system/rpz/testlib/trpz.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Limited implementation of the DNSRPS API for testing purposes. + * + * Copyright (c) 2016-2017 Farsight Security, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TRPZ_H +#define TRPZ_H + +#include +#include +#include + +#define TARGET_ZONE "rpz-test.example.com" + +/* This should be in the librpz.h include. */ +union socku { + struct sockaddr sa; + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + struct sockaddr_un sun; +}; + +typedef struct { + const char *mname; + const char *rname; + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; +} rpz_soa_t; + +#endif diff --git a/bin/tests/system/rpz/tests.sh b/bin/tests/system/rpz/tests.sh new file mode 100644 index 0000000..df7b798 --- /dev/null +++ b/bin/tests/system/rpz/tests.sh @@ -0,0 +1,926 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# test response policy zones (RPZ) + +# touch dnsrps-off to not test with DNSRPS +# touch dnsrps-only to not test with classic RPZ + +. ../conf.sh + +ns=10.53.0 +ns1=$ns.1 # root, defining the others +ns2=$ns.2 # authoritative server whose records are rewritten +ns3=$ns.3 # main rewriting resolver +ns4=$ns.4 # another authoritative server that is rewritten +ns5=$ns.5 # another rewriting resolver +ns6=$ns.6 # a forwarding server +ns7=$ns.7 # another rewriting resolver +ns8=$ns.8 # another rewriting resolver +ns9=$ns.9 # another rewriting resolver +ns10=$ns.10 # authoritative server + +HAVE_CORE= + +status=0 +t=0 + +export DNSRPS_TEST_UPDATE_FILE=$(pwd)/dnsrps.cache +SAVE_RESULTS= +ARGS= +if grep 'dnsrps-enable yes;' dnsrps.conf >/dev/null; then + MODE=dnsrps +else + MODE=native +fi + +USAGE="$0: [-S]" +while getopts "S:" c; do + case $c in + S) + SAVE_RESULTS=-S + ARGS="$ARGS -S" + ;; + *) + echo "$USAGE" 1>&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) +if test "$#" -ne 0; then + echo "$USAGE" 1>&2 + exit 1 +fi +# really quit on control-C +trap 'exit 1' 1 2 15 + +TS='%H:%M:%S ' +TS= +comment() { + if test -n "$TS"; then + date "+${TS}$*" | cat_i + fi +} + +DNSRPSCMD=./dnsrps +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +if test -x "$DNSRPSCMD"; then + WAIT_CMD="$DNSRPSCMD -w 0.1" + TEN_SECS=100 +else + WAIT_CMD="sleep 1" + TEN_SECS=10 +fi + +digcmd() { + if test "$1" = TCP; then + shift + fi + # Default to +noauth and @$ns3 + # Also default to -bX where X is the @value so that OS X will choose + # the right IP source address. + digcmd_args=$(echo "+nocookie +noadd +time=2 +tries=1 -p ${PORT} $*" \ + | sed -e "/@/!s/.*/& @$ns3/" \ + -e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \ + -e '/+n?o?auth/!s/.*/+noauth &/') + #echo_i "dig $digcmd_args 1>&2 + $DIG $digcmd_args || return +} + +# set DIGNM=file name for dig output +GROUP_NM= +TEST_NUM=0 +make_dignm() { + TEST_NUM=$((TEST_NUM + 1)) + DIGNM=dig.out$GROUP_NM-$TEST_NUM + while test -f $DIGNM; do + DIGNM="$DIGNM+" + done +} + +setret() { + ret=1 + status=$((status + 1)) + echo_i "$*" +} + +# set $SN to the SOA serial number of a zone +# $1=domain +# $2=DNS server and client IP address +get_sn() { + SOA=$($DIG -p ${PORT} +short +norecurse soa "$1" "@$2" "-b$2") + SN=$(expr "$SOA" : '[^ ]* [^ ]* \([^ ]*\) .*' || true) + test "$SN" != "" && return + echo_i "no serial number from \`dig -p ${PORT} soa $1 @$2\` in \"$SOA\"" + exit 1 +} + +get_sn_fast() { + RSN=$($DNSRPSCMD -n "$1") + #echo "dnsrps serial for $1 is $RSN" + if test -z "$RSN"; then + echo_i "dnsrps failed to get SOA serial number for $1" + exit 1 + fi +} + +# check that dnsrps provider has zones loaded +# $1=domain +# $2=DNS server IP address +FZONES=$(sed -n -e 's/^zone "\(.*\)".*\(10.53.0..\).*/Z=\1;M=\2/p' dnsrps.zones) +dnsrps_loaded() { + test "$MODE" = dnsrps || return 0 + n=0 + for V in $FZONES; do + eval "$V" + get_sn $Z $M + while true; do + get_sn_fast "$Z" + if test "$SN" -eq "0$RSN"; then + #echo "$Z @$M serial=$SN" + break + fi + n=$((n + 1)) + if test "$n" -gt $TEN_SECS; then + echo_i "dnsrps serial for $Z is $RSN instead of $SN" + exit 1 + fi + $WAIT_CMD + done + done +} + +# check the serial number in an SOA to ensure that a policy zone has +# been (re)loaded +# $1=serial number +# $2=domain +# $3=DNS server +ck_soa() { + n=0 + while true; do + if test "$MODE" = dnsrps; then + get_sn_fast "$2" + test "$RSN" -eq "$1" && return + else + get_sn "$2" "$3" + test "$SN" -eq "$1" && return + fi + n=$((n + 1)) + if test "$n" -gt $TEN_SECS; then + echo_i "got serial number \"$SN\" instead of \"$1\" from $2 @$3" + return + fi + $WAIT_CMD + done +} + +# (re)load the response policy zones with the rules in the file $TEST_FILE +load_db() { + if test -n "$TEST_FILE"; then + copy_setports $TEST_FILE tmp + + for ZONE in bl0 bl1 bl2 bl3 bl4 bl5 bl6 bl7 bl8 bl9 bl10 bl11 bl12 bl13 bl14 bl15 bl16 bl17 bl18 bl19; do + produce_librpz_rules ns5 $ZONE bl + done + + produce_librpz_rules ns2 bl.tld2 bl.tld2 + cat tmp >>$DNSRPS_TEST_UPDATE_FILE + + if $NSUPDATE -v tmp; then + : + $RNDCCMD $ns3 sync + else + echo_i "failed to update policy zone with $TEST_FILE" + $RNDCCMD $ns3 sync + exit 1 + fi + rm -f tmp + fi +} + +# restart name server +# $1 ns number +# $2 rebuild bl rpz zones if "rebuild-bl-rpz" +restart() { + # try to ensure that the server really has stopped + # and won't mess with ns$1/name.pid + if test -z "$HAVE_CORE" -a -f ns$1/named.pid; then + $RNDCCMD $ns$1 halt >/dev/null 2>&1 + if test -f ns$1/named.pid; then + sleep 1 + PID=$(cat ns$1/named.pid 2>/dev/null) + if test -n "$PID"; then + echo_i "killing ns$1 server $PID" + kill -9 $PID + fi + fi + fi + rm -f ns$1/*.jnl + if [ "$2" = "rebuild-bl-rpz" ]; then + if test -f ns$1/base.db; then + for NM in ns$1/bl*.db; do + cp -f ns$1/base.db $NM + done + fi + fi + start_server --noclean --restart --port ${PORT} ns$1 + load_db + dnsrps_loaded + sleep 1 +} + +# $1=server and irrelevant args +# $2=error message +ckalive() { + CKALIVE_NS=$(expr "$1" : '.*@ns\([1-9]\).*' || true) + if test -z "$CKALIVE_NS"; then + CKALIVE_NS=3 + fi + eval CKALIVE_IP=\$ns$CKALIVE_NS + $RNDCCMD $CKALIVE_IP status >/dev/null 2>&1 && return 0 + HAVE_CORE=yes + setret "$2" + # restart the server to avoid stalling waiting for it to stop + restart $CKALIVE_NS "rebuild-bl-rpz" + return 0 +} + +ckstats() { + HOST=$1 + LABEL="$2" + NSDIR="$3" + EXPECTED="$4" + $RNDCCMD $HOST stats + NEW_CNT=$(sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \ + $NSDIR/named.stats | tail -1) + eval "OLD_CNT=\$${NSDIR}_CNT" + NEW_CNT=$((NEW_CNT)) + OLD_CNT=$((OLD_CNT)) + GOT=$((NEW_CNT - OLD_CNT)) + if test "$GOT" -ne "$EXPECTED"; then + setret "wrong $LABEL $NSDIR statistics of $GOT instead of $EXPECTED" + fi + eval "${NSDIR}_CNT=$NEW_CNT" +} + +ckstatsrange() { + HOST=$1 + LABEL="$2" + NSDIR="$3" + MIN="$4" + MAX="$5" + $RNDCCMD $HOST stats + NEW_CNT=$(sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \ + $NSDIR/named.stats | tail -1) + eval "OLD_CNT=\$${NSDIR}_CNT" + NEW_CNT=$((NEW_CNT)) + OLD_CNT=$((OLD_CNT)) + GOT=$((NEW_CNT - OLD_CNT)) + if test "$GOT" -lt "$MIN" -o "$GOT" -gt "$MAX"; then + setret "wrong $LABEL $NSDIR statistics of $GOT instead of ${MIN}..${MAX}" + fi + eval "${NSDIR}_CNT=$NEW_CNT" +} + +add_librpz_rule() { + echo $1 >>$DNSRPS_TEST_UPDATE_FILE +} + +produce_librpz_rules() { + # echo "Producing rules for $1" + ZONEFILE=$1/$3.db + cat $ZONEFILE | grep -E -v '^;' | grep -E '\<(A|CNAME)\>' | awk -v zone=$2 '{ if (NF == 4) {print "static add "$1"."zone" "$2" "$3" "$4} else if (NF == 3) {print "static add "$1"."zone" 300 "$2" "$3}}' >>$DNSRPS_TEST_UPDATE_FILE +} + +# $1=message +# $2=optional test file name +start_group() { + ret=0 + t=$((t + 1)) + test -n "$1" && date "+${TS}checking $1 (${t})" | cat_i + TEST_FILE=$2 + if test -n "$TEST_FILE"; then + GROUP_NM="-$TEST_FILE" + load_db + else + GROUP_NM= + fi + dnsrps_loaded + TEST_NUM=0 +} + +end_group() { + if test -n "$TEST_FILE"; then + # remove the previous set of test rules + copy_setports $TEST_FILE tmp + add_librpz_rule "rollback" + sed -e 's/[ ]add[ ]/ delete /' tmp | $NSUPDATE + rm -f tmp + TEST_FILE= + fi + ckalive $ns3 "failed; ns3 server crashed and restarted" + dnsrps_loaded + GROUP_NM= +} + +clean_result() { + if test -z "$SAVE_RESULTS"; then + rm -f $* + fi +} + +# $1=dig args +# $2=other dig output file +ckresult() { + #ckalive "$1" "server crashed by 'dig $1'" || return 1 + expr "$1" : 'TCP ' >/dev/null && tcp=1 || tcp=0 + digarg=${1#TCP } + + if grep "flags:.* aa .*ad;" $DIGNM; then + setret "'dig $digarg' AA and AD set;" + elif grep "flags:.* aa .*ad;" $DIGNM; then + setret "'dig $digarg' AD set;" + fi + + if $PERL ../digcomp.pl $DIGNM $2 >/dev/null; then + grep -q 'Truncated, retrying in TCP' $DIGNM && trunc=1 || trunc=0 + if [ "$tcp" -ne "$trunc" ]; then + setret "'dig $digarg' wrong; no or unexpected truncation in $DIGNM" + else + clean_result ${DIGNM}* + fi + return 0 + fi + setret "'dig $digarg' wrong; diff $DIGNM $2" + return 0 +} + +# check only that the server does not crash +# $1=target domain +# $2=optional query type +nocrash() { + digcmd $* >/dev/null + ckalive "$*" "server crashed by 'dig $*'" +} + +# check rewrite to NXDOMAIN +# $1=target domain +# $2=optional query type +nxdomain() { + make_dignm + digcmd $* \ + | sed -e 's/^[a-z].* IN CNAME /;xxx &/' \ + -e 's/^[a-z].* IN RRSIG /;xxx &/' \ + >$DIGNM + ckresult "$*" proto.nxdomain +} + +# check rewrite to NODATA +# $1=target domain +# $2=optional query type +nodata() { + make_dignm + digcmd $* \ + | sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM + ckresult "$*" proto.nodata +} + +# check rewrite to an address +# modify the output so that it is easily compared, but save the original line +# $1=IPv4 address +# $2=digcmd args +# $3=optional TTL +addr() { + ADDR=$1 + make_dignm + digcmd $2 >$DIGNM + #ckalive "$2" "server crashed by 'dig $2'" || return 1 + ADDR_ESC=$(echo "$ADDR" | sed -e 's/\./\\./g') + ADDR_TTL=$(sed -n -e "s/^[-.a-z0-9]\{1,\}[ ]*\([0-9]*\) IN AA* ${ADDR_ESC}\$/\1/p" $DIGNM) + if test -z "$ADDR_TTL"; then + setret "'dig $2' wrong; no address $ADDR record in $DIGNM" + return 0 + fi + if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then + setret "'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM" + return 0 + fi + clean_result ${DIGNM}* +} + +# Check that a response is not rewritten +# Use $ns1 instead of the authority for most test domains, $ns2 to prevent +# spurious differences for `dig +norecurse` +# $1=optional "TCP" +# remaining args for dig +nochange() { + make_dignm + digcmd $* >$DIGNM + digcmd $* @$ns1 >${DIGNM}_OK + ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK +} + +nochange_ns10() { + make_dignm + digcmd $* >$DIGNM + digcmd $* @$ns10 >${DIGNM}_OK + ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK +} + +# check against a 'here document' +here() { + make_dignm + sed -e 's/^[ ]*//' >${DIGNM}_OK + digcmd $* >$DIGNM + ckresult "$*" ${DIGNM}_OK +} + +# check dropped response +DROPPED='^;; no servers could be reached' +drop() { + make_dignm + digcmd $* >$DIGNM || true + if grep "$DROPPED" $DIGNM >/dev/null; then + clean_result ${DIGNM}* + return 0 + fi + setret "'dig $1' wrong; response in $DIGNM" + return 0 +} + +nsd() { + $NSUPDATE -p ${PORT} <proto.nxdomain || return 1 + grep "status: NXDOMAIN" proto.nxdomain >/dev/null || return 1 + return 0 +} + +# +# generate prototype NODATA response to compare against. +# +make_proto_nodata() { + digcmd txt-only.tld2 @$ns2 >proto.nodata || return 1 + grep "status: NOERROR" proto.nodata >/dev/null || return 1 + return 0 +} + +# ensure that the fast-expire zone is populated before we begin testing +$RNDCCMD $ns3 retransfer fast-expire + +# make prototype files to check against rewritten results +retry_quiet 10 make_proto_nxdomain +retry_quiet 10 make_proto_nodata + +start_group "QNAME rewrites" test1 + +nochange . # 1 do not crash or rewrite root +nxdomain a0-1.tld2 # 2 +nodata a3-1.tld2 # 3 +nodata a3-2.tld2 # 4 nodata at DNAME itself +nochange sub.a3-2.tld2 # 5 miss where DNAME might work +nxdomain a4-2.tld2 # 6 rewrite based on CNAME target +nxdomain a4-2-cname.tld2 # 7 +nodata a4-3-cname.tld2 # 8 +addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement +addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard +addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME +addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain +addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone +nochange a6-1.tld2 # 14 +addr 127.6.2.1 a6-2.tld2 # 15 +addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME +addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME +addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain +addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain +nochange a5-2.tld2 +norecurse # 20 check that RD=1 is required +nochange a5-3.tld2 +norecurse # 21 +nochange a5-4.tld2 +norecurse # 22 +nochange sub.a5-4.tld2 +norecurse # 23 +nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c +nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures +nxdomain a0-1.tld2s +nodnssec # 26 simple DO=0 with signatures +nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures +nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain +nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain +nochange a0-1.tld2s srv +auth +dnssec # 30 no write for DNSSEC and no record +nxdomain a0-1.tld2s srv +nodnssec # 31 +drop a3-8.tld2 any # 32 drop +nochange TCP a3-9.tld2 # 33 tcp-only +here x.servfail <<'EOF' # 34 qname-wait-recurse yes + ;; status: SERVFAIL, x +EOF +addr 35.35.35.35 "x.servfail @$ns5" # 35 qname-wait-recurse no +end_group +ckstats $ns3 test1 ns3 22 +ckstats $ns5 test1 ns5 1 +ckstats $ns6 test1 ns6 0 + +start_group "NXDOMAIN/NODATA action on QNAME trigger" test1 +nxdomain a0-1.tld2 @$ns6 # 1 +nodata a3-1.tld2 @$ns6 # 2 +nodata a3-2.tld2 @$ns6 # 3 nodata at DNAME itself +nxdomain a4-2.tld2 @$ns6 # 4 rewrite based on CNAME target +nxdomain a4-2-cname.tld2 @$ns6 # 5 +nodata a4-3-cname.tld2 @$ns6 # 6 +addr 12.12.12.12 "a4-1.sub1.tld2 @$ns6" # 7 A replacement +addr 12.12.12.12 "a4-1.sub2.tld2 @$ns6" # 8 A replacement with wildcard +addr 127.4.4.1 "a4-4.tld2 @$ns6" # 9 prefer 1st conflicting QNAME zone +addr 12.12.12.12 "nxc1.sub1.tld2 @$ns6" # 10 replace NXDOMAIN w/ CNAME +addr 12.12.12.12 "nxc2.sub1.tld2 @$ns6" # 11 replace NXDOMAIN w/ CNAME chain +addr 127.6.2.1 "a6-2.tld2 @$ns6" # 12 +addr 56.56.56.56 "a3-6.tld2 @$ns6" # 13 wildcard CNAME +addr 57.57.57.57 "a3-7.sub1.tld2 @$ns6" # 14 wildcard CNAME +addr 127.0.0.16 "a4-5-cname3.tld2 @$ns6" # 15 CNAME chain +addr 127.0.0.17 "a4-6-cname3.tld2 @$ns6" # 16 stop short in CNAME chain +nxdomain c1.crash2.tld3 @$ns6 # 17 assert in rbtdb.c +nxdomain a0-1.tld2 +dnssec @$ns6 # 18 simple DO=1 without sigs +nxdomain a0-1s-cname.tld2s +dnssec @$ns6 # 19 +drop a3-8.tld2 any @$ns6 # 20 drop +end_group +ckstatsrange $ns3 test1 ns3 22 30 +ckstats $ns5 test1 ns5 0 +ckstats $ns6 test1 ns6 0 + +start_group "IP rewrites" test2 +nodata a3-1.tld2 # 1 NODATA +nochange a3-2.tld2 # 2 no policy record so no change +nochange a4-1.tld2 # 3 obsolete PASSTHRU record style +nxdomain a4-2.tld2 # 4 +nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite +nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite +nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite +nodata a4-3.tld2 # 8 +nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy +nochange a4-1-aaaa.tld2 -taaaa # 10 +addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address +addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone +nochange a5-4.tld2 +norecurse # 13 check that RD=1 is required for #14 +addr 14.14.14.14 a5-4.tld2 # 14 prefer QNAME to IP +nochange a4-4.tld2 # 15 PASSTHRU +nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c +addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger +nxdomain a7-1.tld2 # 18 secondary policy zone (RT34450) +# updating an response zone policy +cp ns2/blv2.tld2.db.in ns2/bl.tld2.db +rndc_reload ns2 $ns2 bl.tld2 +add_librpz_rule "update zone bl.tld2 1 inc" +ck_soa 2 bl.tld2 $ns3 +add_librpz_rule "wipe" +produce_librpz_rules ns2 bl.tld2 bl.tld2 +nochange a7-1.tld2 # 19 PASSTHRU +# ensure that a clock tick has occurred so that named will do the reload +sleep 1 +cp ns2/blv3.tld2.db.in ns2/bl.tld2.db +rndc_reload ns2 $ns2 bl.tld2 +add_librpz_rule "update zone bl.tld2 1 inc" +ck_soa 3 bl.tld2 $ns3 +produce_librpz_rules ns2 bl.tld2 bl.tld2 +nxdomain a7-1.tld2 # 20 secondary policy zone (RT34450) +end_group +ckstats $ns3 test2 ns3 12 + +# check that IP addresses for previous group were deleted from the radix tree +start_group "radix tree deletions" +nochange a3-1.tld2 +nochange a3-2.tld2 +nochange a4-1.tld2 +nochange a4-2.tld2 +nochange a4-2.tld2 -taaaa +nochange a4-2.tld2 -ttxt +nochange a4-2.tld2 -tany +nochange a4-3.tld2 +nochange a3-1.tld2 -tAAAA +nochange a4-1-aaaa.tld2 -tAAAA +nochange a5-1-2.tld2 +end_group +ckstats $ns3 'radix tree deletions' ns3 0 + +# these tests assume "min-ns-dots 0" +start_group "NSDNAME rewrites" test3 +nextpart ns3/named.run >/dev/null +nochange a3-1.tld2 # 1 +nochange a3-1.tld2 +dnssec # 2 this once caused problems +nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME +nxdomain a3-1.subsub.sub1.tld2 # 4 +nxdomain a3-1.subsub.sub1.tld2 -tany # 5 +addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2 +nochange a3-2.tld2. # 7 exempt rewrite by name +nochange a0-1.tld2. # 8 exempt rewrite by address block +addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME +addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME +addr 127.0.0.2 a3-1.subsub.sub3.tld2 # 11 +nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash + +nxdomain a3-1.stub # 13 +nxdomain a3-1.static-stub # 14 +nochange_ns10 a3-1.stub-nomatch # 15 +nochange_ns10 a3-1.static-stub-nomatch # 16 +nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" \ + && setret "seen: unrecognized NS rpz_rrset_find() failed: glue" +end_group +ckstats $ns3 test3 ns3 9 + +# these tests assume "min-ns-dots 0" +start_group "NSIP rewrites" test4 +nextpart ns3/named.run >/dev/null +nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2 +nochange a3-2.tld2. # 2 exempt rewrite by name +nochange a0-1.tld2. # 3 exempt rewrite by address block +nochange a3-1.tld4 # 4 different NS IP address +nxdomain a4-1.stub # 5 +nxdomain a4-1.static-stub # 6 +nochange_ns10 a4-1.stub-nomatch # 7 +nochange_ns10 a4-1.static-stub-nomatch # 8 +nextpart ns3/named.run | grep -q "unrecognized NS rpz_rrset_find() failed: glue" \ + && setret "seen: unrecognized NS rpz_rrset_find() failed: glue" +end_group + +start_group "walled garden NSIP rewrites" test4a +addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2 +addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2 +here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2 + ;; status: NOERROR, x + a3-1.tld2. x IN TXT "NSIP walled garden" +EOF +end_group +ckstats $ns3 test4 ns3 6 + +# policies in ./test5 overridden by response-policy{} in ns3/named.conf +# and in ns5/named.conf +start_group "policy overrides" test5 +addr 127.0.0.1 a3-1.tld2 # 1 bl-given +nochange a3-2.tld2 # 2 bl-passthru +nochange a3-3.tld2 # 3 bl-no-op (obsolete for passthru) +nochange a3-4.tld2 # 4 bl-disabled +nodata a3-5.tld2 # 5 bl-nodata zone recursive-only no +nodata a3-5.tld2 +norecurse # 6 bl-nodata zone recursive-only no +nodata a3-5.tld2 # 7 bl-nodata not needed +nxdomain a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata global recursive-only no +nxdomain a3-5.tld2s @$ns5 # 9 bl-nodata global break-dnssec +nxdomain a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata global break-dnssec +nxdomain a3-6.tld2 # 11 bl-nxdomain +here a3-7.tld2 -tany <<'EOF' # 12 + ;; status: NOERROR, x + a3-7.tld2. x IN CNAME txt-only.tld2. + txt-only.tld2. x IN TXT "txt-only-tld2" +EOF +addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname +addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname +addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2 +addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100 +addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90 +drop a3-18.tld2 any # 18 bl-drop +nxdomain TCP a3-19.tld2 # 19 bl-tcp-only +end_group +ckstats $ns3 test5 ns3 12 +ckstats $ns5 test5 ns5 4 + +# check that miscellaneous bugs are still absent +add_librpz_rule "wipe" +start_group "crashes" test6 +for Q in RRSIG SIG ANY 'ANY +dnssec'; do + nocrash a3-1.tld2 -t$Q + nocrash a3-2.tld2 -t$Q + nocrash a3-5.tld2 -t$Q + nocrash www.redirect -t$Q + nocrash www.credirect -t$Q +done + +# This is not a bug, because any data leaked by writing 24.4.3.2.10.rpz-ip +# (or whatever) is available by publishing "foo A 10.2.3.4" and then +# resolving foo. +# nxdomain 32.3.2.1.127.rpz-ip +end_group +ckstats $ns3 bugs ns3 8 + +# Ensure ns3 manages to transfer the fast-expire zone before shutdown. +nextpartreset ns3/named.run +wait_for_log 20 "zone fast-expire/IN: transferred serial 1" ns3/named.run + +# reconfigure the ns5 primary server without the fast-expire zone, so +# it can't be refreshed on ns3, and will expire in 5 seconds. +cat /dev/null >ns5/expire.conf +rndc_reconfig ns5 10.53.0.5 + +# restart the main test RPZ server to see if that creates a core file +if test -z "$HAVE_CORE"; then + stop_server --use-rndc --port ${CONTROLPORT} ns3 + add_librpz_rule "restart" + restart 3 "rebuild-bl-rpz" + HAVE_CORE=$(find ns* -name '*core*' -print) + test -z "$HAVE_CORE" || setret "found $HAVE_CORE; memory leak?" +fi + +# look for complaints from lib/dns/rpz.c and bin/name/query.c +for runfile in ns*/named.run; do + EMSGS=$(nextpart $runfile | grep -E -l 'invalid rpz|rpz.*failed' || true) + if test -n "$EMSGS"; then + setret "error messages in $runfile starting with:" + grep -E 'invalid rpz|rpz.*failed' ns*/named.run \ + | sed -e '10,$d' -e 's/^//' | cat_i + fi +done + +if [ native = "$MODE" ]; then + # restart the main test RPZ server with a bad zone. + t=$((t + 1)) + echo_i "checking that ns3 with broken rpz does not crash (${t})" + stop_server --use-rndc --port ${CONTROLPORT} ns3 + cp ns3/broken.db.in ns3/bl.db + restart 3 # do not rebuild rpz zones + nocrash a3-1.tld2 -tA + stop_server --use-rndc --port ${CONTROLPORT} ns3 + restart 3 "rebuild-bl-rpz" + + t=$((t + 1)) + echo_i "checking if rpz survives a certain class of failed reconfiguration attempts (${t})" + sed -e "s/^#BAD//" ns3/named.conf.tmp + copy_setports ns3/named.conf.tmp ns3/named.conf + rm ns3/named.conf.tmp + $RNDCCMD $ns3 reconfig >/dev/null 2>&1 && setret "failed" + sleep 1 + copy_setports ns3/named.conf.in ns3/named.conf + $RNDCCMD $ns3 reconfig || setret "failed" + + t=$((t + 1)) + echo_i "checking the configured extended DNS error code (EDE) (${t})" + $DIG -p ${PORT} @$ns3 walled.tld2 >dig.out.$t || setret "failed" + grep -F "EDE: 4 (Forged Answer)" dig.out.$t >/dev/null || setret "failed" + + # reload a RPZ zone that is now deliberately broken. + t=$((t + 1)) + echo_i "checking rpz failed update will keep previous rpz rules (${t})" + $DIG -p ${PORT} @$ns3 walled.tld2 >dig.out.$t.before || setret "failed" + grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.before >/dev/null || setret "failed" + cp ns3/broken.db.in ns3/manual-update-rpz.db + rndc_reload ns3 $ns3 manual-update-rpz + sleep 1 + # ensure previous RPZ rules still apply. + $DIG -p ${PORT} @$ns3 walled.tld2 >dig.out.$t.after || setret "failed" + grep "walled\.tld2\..*IN.*A.*10\.0\.0\.1" dig.out.$t.after >/dev/null || setret "failed" + + t=$((t + 1)) + echo_i "checking the default (unset) extended DNS error code (EDE) (${t})" + $DIG -p ${PORT} @$ns3 a6-2.tld2. A >dig.out.$t || setret "failed" + grep -F "EDE: " dig.out.$t >/dev/null && setret "failed" + + t=$((t + 1)) + echo_i "checking reload of a mixed-case RPZ zone (${t})" + # First, a sanity check: the A6-2.TLD2.mixed-case-rpz RPZ record should + # cause a6-2.tld2 NOERROR answers to be rewritten to NXDOMAIN answers. + $DIG -p ${PORT} @$ns3 a6-2.tld2. A >dig.out.$t.before || setret "failed" + grep "status: NXDOMAIN" dig.out.$t.before >/dev/null || setret "failed" + # Add a sibling name (a6-1.tld2.mixed-case-rpz, with "tld2" in lowercase + # rather than uppercase) before A6-2.TLD.mixed-case-rpz. + nextpart ns3/named.run >/dev/null + cp ns3/mixed-case-rpz-2.db.in ns3/mixed-case-rpz.db + rndc_reload ns3 $ns3 mixed-case-rpz + wait_for_log 20 "rpz: mixed-case-rpz: reload done" ns3/named.run + # a6-2.tld2 NOERROR answers should still be rewritten to NXDOMAIN answers. + # (The bug we try to trigger here caused a6-2.tld2.mixed-case-rpz to be + # erroneously removed from the summary RPZ database after reload.) + $DIG -p ${PORT} @$ns3 a6-2.tld2. A >dig.out.$t.after || setret "failed" + grep "status: NXDOMAIN" dig.out.$t.after >/dev/null || setret "failed" +fi + +t=$((t + 1)) +echo_i "checking that ttl values are not zeroed when qtype is '*' (${t})" +$DIG +noall +answer -p ${PORT} @$ns3 any a3-2.tld2 >dig.out.$t || setret "failed" +ttl=$(awk '/a3-2 tld2 text/ {print $2}' dig.out.$t) +if test ${ttl:=0} -eq 0; then setret "failed"; fi + +t=$((t + 1)) +echo_i "checking rpz updates/transfers with parent nodes added after children (${t})" +# regression test for RT #36272: the success condition +# is the secondary server not crashing. +for i in 1 2 3 4 5; do + nsd $ns5 add example.com.policy1. '*.example.com.policy1.' + nsd $ns5 delete example.com.policy1. '*.example.com.policy1.' +done +for i in 1 2 3 4 5; do + nsd $ns5 add '*.example.com.policy1.' example.com.policy1. + nsd $ns5 delete '*.example.com.policy1.' example.com.policy1. +done + +t=$((t + 1)) +echo_i "checking that going from an empty policy zone works (${t})" +nsd $ns5 add '*.x.servfail.policy2.' x.servfail.policy2. +add_librpz_rule "update add *.x.servfail.policy2 300 CNAME ." +sleep 1 +rndc_reload ns7 $ns7 policy2 +$DIG z.x.servfail -p ${PORT} @$ns7 >dig.out.${t} || setret "failed" +grep NXDOMAIN dig.out.${t} >/dev/null || setret "failed" + +t=$((t + 1)) +echo_i "checking that 'ede none' works same way as when \"ede\" is unset (${t})" +$DIG z.x.servfail -p ${PORT} @$ns7 >dig.out.${t} || setret "failed" +grep -F "EDE: " dig.out.${t} >/dev/null && setret "failed" + +t=$((t + 1)) +echo_i "checking that 'add-soa no' at rpz zone level works (${t})" +$DIG z.x.servfail -p ${PORT} @$ns7 >dig.out.${t} || setret "failed" +grep "SOA" dig.out.${t} >/dev/null && setret "failed" + +if [ native = "$MODE" ]; then + t=$((t + 1)) + echo_i "checking that 'add-soa yes' at response-policy level works (${t})" + $DIG walled.tld2 -p ${PORT} +noall +add @$ns3 >dig.out.${t} || setret "failed" + grep "^manual-update-rpz\..*60.*SOA" dig.out.${t} >/dev/null || setret "failed" +fi + +if [ native = "$MODE" ]; then + t=$((t + 1)) + echo_i "reconfiguring server with 'add-soa no' (${t})" + cp ns3/named.conf ns3/named.conf.tmp + sed -e "s/add-soa yes/add-soa no/g" ns3/named.conf + rndc_reconfig ns3 $ns3 + echo_i "checking that 'add-soa no' at response-policy level works (${t})" + $DIG walled.tld2 -p ${PORT} +noall +add @$ns3 >dig.out.${t} || setret "failed" + grep "^manual-update-rpz\..*SOA" dig.out.${t} >/dev/null && setret "failed" +fi + +if [ native = "$MODE" ]; then + t=$((t + 1)) + echo_i "checking that 'add-soa unset' works (${t})" + $DIG walled.tld2 -p ${PORT} +noall +add @$ns8 >dig.out.${t} || setret "failed" + grep "^manual-update-rpz\..*60.*SOA" dig.out.${t} >/dev/null || setret "failed" +fi + +# dnsrps does not allow NS RRs in policy zones, so this check +# with dnsrps results in no rewriting. +if [ native = "$MODE" ]; then + t=$((t + 1)) + echo_i "checking rpz with delegation fails correctly (${t})" + $DIG -p ${PORT} @$ns3 ns example.com >dig.out.$t || setret "failed" + grep "status: SERVFAIL" dig.out.$t >/dev/null || setret "failed" + + t=$((t + 1)) + echo_i "checking policies from expired zone are no longer in effect ($t)" + $DIG -p ${PORT} @$ns3 a expired >dig.out.$t || setret "failed" + grep "expired.*10.0.0.10" dig.out.$t >/dev/null && setret "failed" + grep "fast-expire/IN: response-policy zone expired" ns3/named.run >/dev/null || setret "failed" +fi + +# RPZ 'CNAME *.' (NODATA) trumps DNS64. Test against various DNS64 scenarios. +produce_librpz_rules ns9 rpz rpz +for label in a-only no-a-no-aaaa a-plus-aaaa; do + for type in AAAA A; do + t=$((t + 1)) + case $label in + a-only) + echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A-only (${t})" + ;; + no-a-no-aaaa) + echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with no A or AAAA (${t})" + ;; + a-plus-aaaa) + echo_i "checking rpz 'CNAME *.' (NODATA) with dns64, $type lookup with A and AAAA (${t})" + ;; + esac + ret=0 + $DIG ${label}.example -p ${PORT} $type @10.53.0.9 >dig.out.${t} || setret "failed" + grep "status: NOERROR" dig.out.$t >/dev/null || ret=1 + grep "ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 2$" dig.out.$t >/dev/null || ret=1 + grep "^rpz" dig.out.$t >/dev/null || ret=1 + [ $ret -eq 0 ] || echo_i "failed" + status=$((status + ret)) + done +done + +if [ native = "$MODE" ]; then + t=$((t + 1)) + echo_i "checking that rewriting CD=1 queries handles pending data correctly (${t})" + $RNDCCMD $ns3 flush + $RNDCCMD $ns6 flush + $DIG a7-2.tld2s -p ${PORT} @$ns6 +cd >dig.out.${t} || setret "failed" + grep -w "1.1.1.1" dig.out.${t} >/dev/null || setret "failed" +fi + +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/rpz/tests_sh_rpz.py b/bin/tests/system/rpz/tests_sh_rpz.py new file mode 100644 index 0000000..6857138 --- /dev/null +++ b/bin/tests/system/rpz/tests_sh_rpz.py @@ -0,0 +1,64 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out*", + "dnsrps.cache", + "dnsrps.conf", + "dnsrps.zones", + "proto.*", + "trusted.conf", + "ns2/K*", + "ns2/bl.tld2.db", + "ns2/tld2s.db", + "ns3/bl-2.db", + "ns3/bl-cname.db", + "ns3/bl-disabled.db", + "ns3/bl-drop.db", + "ns3/bl-garden.db", + "ns3/bl-given.db", + "ns3/bl-no-op.db", + "ns3/bl-nodata.db", + "ns3/bl-nxdomain.db", + "ns3/bl-passthru.db", + "ns3/bl-tcp-only.db", + "ns3/bl-wildcname.db", + "ns3/bl.db", + "ns3/bl.tld2.db", + "ns3/fast-expire.db", + "ns3/manual-update-rpz.db", + "ns3/mixed-case-rpz.db", + "ns3/named.conf.tmp", + "ns3/named.stats", + "ns5/bl.db", + "ns5/empty.db", + "ns5/empty.db.jnl", + "ns5/example.db", + "ns5/expire.conf", + "ns5/fast-expire.db", + "ns5/named.stats", + "ns5/policy2.db", + "ns5/policy2.db.jnl", + "ns5/rpz-switch", + "ns6/bl.tld2s.db", + "ns6/empty.db", + "ns6/named.stats", + "ns7/policy2.db", + "ns8/manual-update-rpz.db", + ] +) + + +def test_rpz(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rpz/tests_sh_rpz_dnsrps.py b/bin/tests/system/rpz/tests_sh_rpz_dnsrps.py new file mode 100644 index 0000000..4b8b43a --- /dev/null +++ b/bin/tests/system/rpz/tests_sh_rpz_dnsrps.py @@ -0,0 +1,77 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = [ + isctest.mark.dnsrps_enabled, + pytest.mark.extra_artifacts( + [ + "dig.out*", + "dnsrps.cache", + "dnsrps.conf", + "dnsrps.zones", + "proto.*", + "trusted.conf", + "ns2/K*", + "ns2/bl.tld2.db", + "ns2/tld2s.db", + "ns3/bl-2.db", + "ns3/bl-cname.db", + "ns3/bl-disabled.db", + "ns3/bl-drop.db", + "ns3/bl-garden.db", + "ns3/bl-given.db", + "ns3/bl-no-op.db", + "ns3/bl-nodata.db", + "ns3/bl-nxdomain.db", + "ns3/bl-passthru.db", + "ns3/bl-tcp-only.db", + "ns3/bl-wildcname.db", + "ns3/bl.db", + "ns3/bl.tld2.db", + "ns3/fast-expire.db", + "ns3/manual-update-rpz.db", + "ns3/mixed-case-rpz.db", + "ns3/named.conf.tmp", + "ns3/named.stats", + "ns5/bl.db", + "ns5/empty.db", + "ns5/empty.db.jnl", + "ns5/example.db", + "ns5/expire.conf", + "ns5/fast-expire.db", + "ns5/named.stats", + "ns5/policy2.db", + "ns5/policy2.db.jnl", + "ns5/rpz-switch", + "ns6/bl.tld2s.db", + "ns6/empty.db", + "ns6/named.stats", + "ns7/policy2.db", + "ns8/manual-update-rpz.db", + ] + ), +] + + +def test_rpz_dnsrps(run_tests_sh): + with open("dnsrps.conf", "w", encoding="utf-8") as conf: + conf.writelines( + [ + "dnsrps-options { log-level 3 };" + "dnsrps-enable yes;" + 'dnsrps-library "../../rpz/testlib/.libs/libdummyrpz.so";' + ] + ) + run_tests_sh() diff --git a/bin/tests/system/rpzextra/ns2/allowed.db b/bin/tests/system/rpzextra/ns2/allowed.db new file mode 100644 index 0000000..57a733c --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/allowed.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA ns1 root.allowed. 2020040101 4h 1h 1w 60 +@ IN NS ns1 +ns1 IN A 10.53.0.2 +@ IN A 10.53.0.2 +www IN A 10.53.0.2 diff --git a/bin/tests/system/rpzextra/ns2/baddomain.db b/bin/tests/system/rpzextra/ns2/baddomain.db new file mode 100644 index 0000000..3946da3 --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/baddomain.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA ns1 root.baddomain. ( + 2020040101 + 4h + 1h + 1w + 60 +) + + IN NS ns1 + +ns1 IN A 10.53.0.2 + +baddomain. IN A 10.53.0.2 +www IN A 10.53.0.3 diff --git a/bin/tests/system/rpzextra/ns2/gooddomain.db b/bin/tests/system/rpzextra/ns2/gooddomain.db new file mode 100644 index 0000000..1fb720c --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/gooddomain.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA ns1 root.gooddomain. ( + 2020040101 + 4h + 1h + 1w + 60 +) + + IN NS ns1 + +ns1 IN A 10.53.0.2 + +gooddomain. IN A 10.53.0.2 +www IN A 10.53.0.3 diff --git a/bin/tests/system/rpzextra/ns2/named.conf.j2 b/bin/tests/system/rpzextra/ns2/named.conf.j2 new file mode 100644 index 0000000..6317563 --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/named.conf.j2 @@ -0,0 +1,57 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + listen-on { 10.53.0.2; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; +}; + +zone "allowed" { + type primary; + file "allowed.db"; + allow-transfer { none; }; +}; + +zone "baddomain" { + type primary; + file "baddomain.db"; + allow-transfer { none; }; +}; + +zone "gooddomain" { + type primary; + file "gooddomain.db"; + allow-transfer { none; }; +}; + +zone "rpz-external.local" { + type primary; + file "rpz-external.local.db"; + allow-transfer { any; }; +}; diff --git a/bin/tests/system/rpzextra/ns2/rpz-external.local.db b/bin/tests/system/rpzextra/ns2/rpz-external.local.db new file mode 100644 index 0000000..b3ab69e --- /dev/null +++ b/bin/tests/system/rpzextra/ns2/rpz-external.local.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-external.local root.rpz-external.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME . +*.allowed IN CNAME . diff --git a/bin/tests/system/rpzextra/ns3/external-rpz.local.db b/bin/tests/system/rpzextra/ns3/external-rpz.local.db new file mode 100644 index 0000000..aad6b89 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/external-rpz.local.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz.local root.rpz.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. + +gooddomain IN CNAME . +*.gooddomain IN CNAME . diff --git a/bin/tests/system/rpzextra/ns3/first-rpz.local.db b/bin/tests/system/rpzextra/ns3/first-rpz.local.db new file mode 100644 index 0000000..4203ca1 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/first-rpz.local.db @@ -0,0 +1,29 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz.local root.rpz.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. + +baddomain IN CNAME . +*.baddomain IN CNAME . diff --git a/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db new file mode 100644 index 0000000..471030c --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/fourth-rpz-extra.local.db @@ -0,0 +1,32 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. + +gooddomain IN CNAME . +*.gooddomain IN CNAME . + +baddomain IN CNAME . +*.baddomain IN CNAME . diff --git a/bin/tests/system/rpzextra/ns3/named.args b/bin/tests/system/rpzextra/ns3/named.args new file mode 100644 index 0000000..f4fe28f --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/named.args @@ -0,0 +1 @@ + -m record -c named.conf -d 99 -f -D rpzextra-ns3 -T maxcachesize=2097152 diff --git a/bin/tests/system/rpzextra/ns3/named.conf.j2 b/bin/tests/system/rpzextra/ns3/named.conf.j2 new file mode 100644 index 0000000..cd459bc --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/named.conf.j2 @@ -0,0 +1,147 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + listen-on { 10.53.0.3; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; + recursion yes; + allow-recursion { any; }; + empty-zones-enable false; + response-policy { + zone "rpz-extra.local"; + }; +}; + +logging { + channel rpz_passthru { + file "rpz_passthru.txt" versions 3 size 5m; + print-time yes; + print-category yes; + print-severity yes; + severity info; + }; + + channel rpz_log { + file "rpz.txt" versions 3 size 20m; + print-time yes; + print-category yes; + print-severity yes; + severity info; + }; + + category rpz { rpz_log; default_debug; }; + category rpz-passthru { rpz_passthru; default_debug; }; +}; + +view "first" { + match-clients { 10.53.0.1; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz.local" { + type primary; + file "first-rpz.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; + response-policy { + zone "rpz.local"; + }; +}; + +view "second" { + match-clients { 10.53.0.2; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-external.local" { + type secondary; + primaries { 10.53.0.2; }; + file "second-rpz-external.local.db"; + allow-query { 10.53.0.2; }; + }; + response-policy { + zone "rpz-external.local"; + }; +}; + +view "third" { + match-clients { 10.53.0.3; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-extra.local" { + type primary; + file "third-rpz-extra.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; +}; + +view "fourth" { + match-clients { 10.53.0.4; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz-extra.local" { + type primary; + file "fourth-rpz-extra.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; +}; + +view "external" { + match-clients { any; }; + zone "." { + type hint; + file "root.db"; + }; + zone "rpz.local" { + type primary; + file "external-rpz.local.db"; + allow-transfer { none; }; + allow-query { localhost; }; + }; + zone "rpz-external.local" { + type secondary; + masterfile-format text; + primaries { 10.53.0.2; }; + file "external-rpz-external.local.db"; + allow-query { 10.53.0.5; }; + }; + response-policy { + zone "rpz-external.local"; + zone "rpz.local"; + }; +}; diff --git a/bin/tests/system/rpzextra/ns3/root.db b/bin/tests/system/rpzextra/ns3/root.db new file mode 100644 index 0000000..ca49988 --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/root.db @@ -0,0 +1,30 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS ns1.allowed + + +allowed. NS ns1.allowed. +ns1.allowed. A 10.53.0.2 + +baddomain. NS ns1.baddomain. +ns1.baddomain. A 10.53.0.2 + +gooddomain. NS ns1.gooddomain. +ns1.gooddomain. A 10.53.0.2 diff --git a/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db new file mode 100644 index 0000000..a8b46fa --- /dev/null +++ b/bin/tests/system/rpzextra/ns3/third-rpz-extra.local.db @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA localhost.rpz-extra.local root.rpz-extra.local. ( + 2020022500 ; serial number + 60 ; refresh every minute + 60 ; retry every minute + 432000 ; expire in 5 days + 60 ; negative caching ttl, 1 minute +) + + + IN NS LOCALHOST. + +allowed IN CNAME rpz-passthru. +*.allowed IN CNAME rpz-passthru. diff --git a/bin/tests/system/rpzextra/tests_rpzextra.py b/bin/tests/system/rpzextra/tests_rpzextra.py new file mode 100644 index 0000000..33b6d15 --- /dev/null +++ b/bin/tests/system/rpzextra/tests_rpzextra.py @@ -0,0 +1,146 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import isctest +from isctest.compat import dns_rcode + +import dns.message + +pytestmark = pytest.mark.extra_artifacts( + [ + "ns3/*-rpz-external.local.db", + "ns3/rpz*.txt", + ] +) + + +@pytest.mark.parametrize( + "qname,source,rcode", + [ + # For 10.53.0.1 source IP: + # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - gooddomain.com is allowed + # - allowed. is allowed + ("baddomain.", "10.53.0.1", dns.rcode.NXDOMAIN), + ("gooddomain.", "10.53.0.1", dns.rcode.NOERROR), + ("allowed.", "10.53.0.1", dns.rcode.NOERROR), + # For 10.53.0.2 source IP: + # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN + # - baddomain.com is allowed + # - gooddomain.com is allowed + ("baddomain.", "10.53.0.2", dns.rcode.NOERROR), + ("gooddomain.", "10.53.0.2", dns.rcode.NOERROR), + ("allowed.", "10.53.0.2", dns.rcode.NXDOMAIN), + # For 10.53.0.3 source IP: + # - gooddomain.com is allowed + # - baddomain.com is allowed + # - allowed. is allowed + ("baddomain.", "10.53.0.3", dns.rcode.NOERROR), + ("gooddomain.", "10.53.0.3", dns.rcode.NOERROR), + ("allowed.", "10.53.0.3", dns.rcode.NOERROR), + # For 10.53.0.4 source IP: + # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - allowed. is allowed + ("baddomain.", "10.53.0.4", dns.rcode.NXDOMAIN), + ("gooddomain.", "10.53.0.4", dns.rcode.NXDOMAIN), + ("allowed.", "10.53.0.4", dns.rcode.NOERROR), + # For 10.53.0.5 (any) source IP: + # - baddomain.com is allowed + # - gooddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # - allowed.com isn't allowed (CNAME .), should return NXDOMAIN + ("baddomain.", "10.53.0.5", dns.rcode.NOERROR), + ("gooddomain.", "10.53.0.5", dns.rcode.NXDOMAIN), + ("allowed.", "10.53.0.5", dns.rcode.NXDOMAIN), + ], +) +def test_rpz_multiple_views(qname, source, rcode): + # Wait for the rpz-external.local zone transfer + msg = dns.message.make_query("rpz-external.local", "SOA") + isctest.query.tcp( + msg, + ip="10.53.0.3", + source="10.53.0.2", + expected_rcode=dns_rcode.NOERROR, + ) + isctest.query.tcp( + msg, + ip="10.53.0.3", + source="10.53.0.5", + expected_rcode=dns_rcode.NOERROR, + ) + + msg = dns.message.make_query(qname, "A") + res = isctest.query.udp(msg, "10.53.0.3", source=source, expected_rcode=rcode) + if rcode == dns.rcode.NOERROR: + assert res.answer == [dns.rrset.from_text(qname, 300, "IN", "A", "10.53.0.2")] + + +def test_rpz_passthru_logging(): + resolver_ip = "10.53.0.3" + + # Should generate a log entry into rpz_passthru.txt + msg_allowed = dns.message.make_query("allowed.", "A") + res_allowed = isctest.query.udp( + msg_allowed, resolver_ip, source="10.53.0.1", expected_rcode=dns.rcode.NOERROR + ) + assert res_allowed.answer == [ + dns.rrset.from_text("allowed.", 300, "IN", "A", "10.53.0.2") + ] + + # Should also generate a log entry into rpz_passthru.txt + msg_allowed_any = dns.message.make_query("allowed.", "ANY") + res_allowed_any = isctest.query.udp( + msg_allowed_any, + resolver_ip, + source="10.53.0.1", + expected_rcode=dns.rcode.NOERROR, + ) + assert res_allowed_any.answer == [ + dns.rrset.from_text("allowed.", 300, "IN", "NS", "ns1.allowed."), + dns.rrset.from_text("allowed.", 300, "IN", "A", "10.53.0.2"), + ] + # The comparison above doesn't compare the TTL values, and we want to + # make sure that the "passthru" rpz doesn't cap the TTL with max-policy-ttl. + assert res_allowed_any.answer[0].ttl > 200 + assert res_allowed_any.answer[1].ttl > 200 + + # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN + # Should generate a log entry into rpz.txt + msg_not_allowed = dns.message.make_query("baddomain.", "A") + res_not_allowed = isctest.query.udp( + msg_not_allowed, + resolver_ip, + source="10.53.0.1", + expected_rcode=dns.rcode.NXDOMAIN, + ) + isctest.check.nxdomain(res_not_allowed) + + rpz_passthru_logfile = os.path.join("ns3", "rpz_passthru.txt") + rpz_logfile = os.path.join("ns3", "rpz.txt") + + assert os.path.isfile(rpz_passthru_logfile) + assert os.path.isfile(rpz_logfile) + + with open(rpz_passthru_logfile, encoding="utf-8") as log_file: + line = log_file.read() + assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line + + with open(rpz_logfile, encoding="utf-8") as log_file: + line = log_file.read() + assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line + assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line diff --git a/bin/tests/system/rpzrecurse/README b/bin/tests/system/rpzrecurse/README new file mode 100644 index 0000000..5936e05 --- /dev/null +++ b/bin/tests/system/rpzrecurse/README @@ -0,0 +1,124 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +These tests check RPZ recursion behavior (including skipping +recursion when appropriate). + +The general structure of the tests is: + +* The resolver (ns2) with an unqualified view containing the policy + zones, the response-policy statement, and a root hint zone + +* The auth server that contains two authoritative zones, l1.l0 and + l2.l1.l0, both delegated to itself. l2.l1.l0 specifies a non-existent + zone data file and so will generate SERVFAILs for any queries to it. + +The l2.l1.l0 zone was chosen to generate SERVFAIL responses because RPZ +evaluation will use that error response whenever it encounters it during +processing, thus making it a binary indicator for whether or not +recursion was attempted. This also allows us to not worry about having +to craft 'ip', 'nsdname', and 'nsip' rules that matched the queries. + +Each test is intended to be fed a number of queries constructed as +qXX.l2.l1.l0, where XX is the 1-based query sequence number (e.g. the +first query of each test is q01.l2.l1.l0). + +For all the tests the triggers are constructed as follows: +client-ip - match 127.0.0.1/32 +ip - match 255.255.255.255/32 (does not matter due to SERVFAIL) +nsdname - match ns.example.org (also does not matter) +nsip - match 255.255.255.255/32 (also does not matter) +qname - match qXX.l2.l1.l0, where XX is the query sequence number that +is intended to be matched by this qname rule. + +Here's the detail on the test cases: + +Group 1 - testing skipping recursion for a single policy zone with only +records that allow recursion to be skipped + +Test 1a: + 1 policy zone containing 1 'client-ip' trigger + 1 query, expected to skip recursion + +Test 1b: + 1 policy zone containing 1 'qname' trigger (q01) + 2 queries, q01 is expected to skip recursion, q02 is expected to + recurse + +Test 1c: + 1 policy zone containing both a 'client-ip' and 'qname' trigger (q02) + 1 query, expected to skip recursion + +Group 2 - testing skipping recursion with multiple policy zones when all +zones have only trigger types eligible to skip recursion with + +Test 2a: + 32 policy zones, each containing 1 'qname' trigger (qNN, where NN is + the zone's sequence 1-based sequence number formatted to 2 digits, + so each of the first 32 queries should match a different zone) + 33 queries, the first 32 of which are expected to skip recursion + while the 33rd is expected to recurse + +Group 3 - Testing interaction of triggers that require recursion when in +a single zone, both alone and with triggers that allow recursion to be +skipped + +Test 3a: + 1 policy zone containing 1 'ip' trigger + 1 query, expected to recurse + +Test 3b: + 1 policy zone containing 1 'nsdname' trigger + 1 query, expected to recurse + +Test 3c: + 1 policy zone containing 1 'nsip' trigger + 1 query, expected to recurse + +Test 3d: + 1 policy zone containing 1 'ip' trigger and 1 'qname' trigger (q02) + 2 queries, the first should not recurse and the second should recurse + +Test 3e: + 1 policy zone containing 1 'nsdname' trigger and 1 'qname' trigger + (q02) + 2 queries, the first should not recurse and the second should recurse + +Test 3f: + 1 policy zone containing 1 'nsip' trigger and 1 'qname' trigger (q02) + 2 queries, the first should not recurse and the second should recurse + +Group 4 - contains 32 subtests designed to verify that recursion is +skippable for only the appropriate zones based on the order specified in +the 'response-policy' statement + +Tests 4aa to 4bf: + 32 policy zones per test, one of which is configured with 1 'ip' + trigger and one 'qname' trigger while the others are configured + only with 1 'qname' trigger. The zone with both triggers starts + listed first and is moved backwards by one position with each + test. The 'qname' triggers in the zones are structured so that + the zones are tested starting with the first zone and the 'ip' + trigger is tested before the 'qname' trigger for that zone. + 33 queries per test, where the number expected to skip recursion + matches the test sequence number: e.g. 1 skip for 4aa, 26 skips + for 4az, and 32 skips for 4bf + +Group 5 - This test verifies that the "pivot" policy zone for whether or +not recursion can be skipped is the first listed zone with applicable +trigger types rather than a later listed zone. + +Test 5a: + 5 policy zones, the 1st, 3rd, and 5th configured with 1 'qname' + trigger each (q01, q04, and q06, respectively), the 2nd and 4th + each configured with an 'ip' and 'qname' trigger (q02 and q05, + respectively for the 'qname' triggers + 6 queries, of which only q01 and q02 are expected to skip recursion diff --git a/bin/tests/system/rpzrecurse/ans5/ans.pl b/bin/tests/system/rpzrecurse/ans5/ans.pl new file mode 100644 index 0000000..9c5efb3 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ans5/ans.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.5", + LocalPort => $localport, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + my $donotrespond = 0; + + $packet->header->aa(1); + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 A 10.53.0.5")); + #} elsif ($qtype eq "AAAA") { + #$packet->push("answer", + #new Net::DNS::RR($qname . + #" 300 AAAA 2001:db8:beef::1")); + } elsif ($qtype eq "NS") { + $donotrespond = 1; + } + + if ($donotrespond == 0) { + $sock->send($packet->data); + print "RESPONSE:\n"; + $packet->print; + print "\n"; + } else { + print "DROP:\n"; + } +} diff --git a/bin/tests/system/rpzrecurse/ns1/db.l0 b/bin/tests/system/rpzrecurse/ns1/db.l0 new file mode 100644 index 0000000..e6077fc --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/db.l0 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 10.53.0.1 +l1 NS ns.l1 +ns.l1 A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns1/db.l1.l0 b/bin/tests/system/rpzrecurse/ns1/db.l1.l0 new file mode 100644 index 0000000..f51d5f7 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/db.l1.l0 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 10.53.0.1 +l2 NS ns.l2 +ns.l2 A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns1/example.com.db b/bin/tests/system/rpzrecurse/ns1/example.com.db new file mode 100644 index 0000000..3bd11ec --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/example.com.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA ns.example.com. root.example.com. 1 3600 3600 3600 3600 +@ NS ns.example.com. + +ns.example.com. A 10.53.0.1 +@ A 1.2.3.4 +www A 1.2.3.5 diff --git a/bin/tests/system/rpzrecurse/ns1/example.db b/bin/tests/system/rpzrecurse/ns1/example.db new file mode 100644 index 0000000..0e71776 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/example.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA root.example. example. 1 3600 3600 3600 3600 +@ IN NS ns.example. +www IN CNAME cname +cname IN A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns1/named.conf.in b/bin/tests/system/rpzrecurse/ns1/named.conf.in new file mode 100644 index 0000000..4fbb35a --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/named.conf.in @@ -0,0 +1,75 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + querylog yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "test.example.org" { + type primary; + file "example.db"; +}; + +zone "l0" { + type primary; + file "db.l0"; +}; + +zone "l1.l0" { + type primary; + file "db.l1.l0"; +}; + +zone "l2.l1.l0" { + type primary; + file "does-not-exist"; +}; + +zone "test1.example.net" { + type primary; + file "test1.example.net.db"; +}; + +zone "test2.example.net" { + type primary; + file "test2.example.net.db"; +}; + +zone "example.com" { + type primary; + file "example.com.db"; +}; diff --git a/bin/tests/system/rpzrecurse/ns1/root.db b/bin/tests/system/rpzrecurse/ns1/root.db new file mode 100644 index 0000000..51be203 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA muks.isc.org. a.root.servers.nil. ( + 2010 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +@ NS ns.example. +ns.example. A 10.53.0.1 + +l0. NS ns.l0. +ns.l0. A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns1/test1.example.net.db b/bin/tests/system/rpzrecurse/ns1/test1.example.net.db new file mode 100644 index 0000000..66ca007 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/test1.example.net.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA root.example. example. 1 3600 3600 3600 3600 +@ NS ns.example. +ns.example. A 10.53.0.1 +test1.example.net. A 1.2.3.4 +www.test1.example.net. A 5.6.7.8 diff --git a/bin/tests/system/rpzrecurse/ns1/test2.example.net.db b/bin/tests/system/rpzrecurse/ns1/test2.example.net.db new file mode 100644 index 0000000..57db115 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns1/test2.example.net.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +@ IN SOA root.example. example. 1 3600 3600 3600 3600 +@ NS ns.example. +ns.example. A 10.53.0.1 +test2.example.net. A 8.7.6.5 +www.test2.example.net. A 4.3.2.1 diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip1 b/bin/tests/system/rpzrecurse/ns2/db.clientip1 new file mode 100644 index 0000000..f0d53d2 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.clientip1 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +32.4.0.53.10.rpz-client-ip A 10.53.0.2 +24.0.0.53.10.rpz-client-ip A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip2 b/bin/tests/system/rpzrecurse/ns2/db.clientip2 new file mode 100644 index 0000000..dfcc341 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.clientip2 @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +24.0.0.53.10.rpz-client-ip A 10.53.0.3 diff --git a/bin/tests/system/rpzrecurse/ns2/db.clientip21 b/bin/tests/system/rpzrecurse/ns2/db.clientip21 new file mode 100644 index 0000000..4ce2af1 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.clientip21 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +32.3.0.53.10.rpz-client-ip A 10.53.0.1 +31.2.0.53.10.rpz-client-ip CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/db.given b/bin/tests/system/rpzrecurse/ns2/db.given new file mode 100644 index 0000000..d464a53 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.given @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN given.zone. +$TTL 3600 +@ IN SOA ns.given.zone. hostmaster.given.zone. 1 600 300 604800 3600 + IN NS ns.given.zone. + +ns.given.zone. IN A 127.0.0.1 +; this should be ignored as it matches an earlier passthru entry. +example.com CNAME . +; this should be ignored as it matches an earlier wildcard passthru entry. +www.example.com CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength b/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength new file mode 100644 index 0000000..f496670 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.invalidprefixlength @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +1000.4.0.53.10.rpz-client-ip A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns2/db.log1 b/bin/tests/system/rpzrecurse/ns2/db.log1 new file mode 100644 index 0000000..495885b --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.log1 @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +32.4.0.53.10.rpz-client-ip A 10.53.0.4 diff --git a/bin/tests/system/rpzrecurse/ns2/db.log2 b/bin/tests/system/rpzrecurse/ns2/db.log2 new file mode 100644 index 0000000..91ff8c5 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.log2 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +32.4.0.53.10.rpz-client-ip A 10.53.0.4 +32.3.0.53.10.rpz-client-ip A 10.53.0.3 diff --git a/bin/tests/system/rpzrecurse/ns2/db.log3 b/bin/tests/system/rpzrecurse/ns2/db.log3 new file mode 100644 index 0000000..65ed980 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.log3 @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +32.4.0.53.10.rpz-client-ip A 10.53.0.4 +32.3.0.53.10.rpz-client-ip A 10.53.0.3 +32.2.0.53.10.rpz-client-ip A 10.53.0.2 diff --git a/bin/tests/system/rpzrecurse/ns2/db.passthru b/bin/tests/system/rpzrecurse/ns2/db.passthru new file mode 100644 index 0000000..eac3533 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.passthru @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN passthru.zone. +$TTL 3600 +@ IN SOA ns.passthru.zone. hostmaster.passthru.zone. 1 600 300 604800 3600 + IN NS ns.passthru.zone. + +ns.passthru.zone. IN A 127.0.0.1 + +example.com CNAME rpz-passthru. +*.example.com CNAME rpz-passthru. diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard1 b/bin/tests/system/rpzrecurse/ns2/db.wildcard1 new file mode 100644 index 0000000..3e5c78f --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard1 @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +*.test1.example.net CNAME . +test1.example.net CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard2a b/bin/tests/system/rpzrecurse/ns2/db.wildcard2a new file mode 100644 index 0000000..3e5c78f --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2a @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +*.test1.example.net CNAME . +test1.example.net CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard2b b/bin/tests/system/rpzrecurse/ns2/db.wildcard2b new file mode 100644 index 0000000..f8e6123 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard2b @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +*.test2.example.net CNAME . +test2.example.net CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/db.wildcard3 b/bin/tests/system/rpzrecurse/ns2/db.wildcard3 new file mode 100644 index 0000000..5354c04 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/db.wildcard3 @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 60 +@ IN SOA root.ns ns 1996072700 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +*.test1.example.net CNAME . diff --git a/bin/tests/system/rpzrecurse/ns2/named.clientip.conf b/bin/tests/system/rpzrecurse/ns2/named.clientip.conf new file mode 100644 index 0000000..a9ec4ca --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.clientip.conf @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "clientip1"; + zone "clientip2"; + } qname-wait-recurse no + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "clientip1" { type primary; file "db.clientip1"; }; + zone "clientip2" { type primary; file "db.clientip2"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf b/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf new file mode 100644 index 0000000..39b67d8 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.clientip2.conf @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + servfail-ttl 0; + + # policy configuration to be tested + response-policy { + zone "clientip21"; + } qname-wait-recurse no + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "clientip21" { type primary; file "db.clientip21"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.conf.header.in b/bin/tests/system/rpzrecurse/ns2/named.conf.header.in new file mode 100644 index 0000000..3973eba --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.conf.header.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + querylog yes; + + # let ns3 start dnsrpzd + include "../dnsrps.conf"; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + diff --git a/bin/tests/system/rpzrecurse/ns2/named.default.conf b/bin/tests/system/rpzrecurse/ns2/named.default.conf new file mode 100644 index 0000000..929b88f --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.default.conf @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf b/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf new file mode 100644 index 0000000..2f2b735 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.invalidprefixlength.conf @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "invalidprefixlength"; + }; + + # policy zones to be tested + zone "invalidprefixlength" { type primary; file "db.invalidprefixlength"; }; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.log.conf b/bin/tests/system/rpzrecurse/ns2/named.log.conf new file mode 100644 index 0000000..a19367e --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.log.conf @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "log1" log no; + zone "log2" log yes; + zone "log3"; # missing log clause + } qname-wait-recurse no + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "log1" { type primary; file "db.log1"; }; + zone "log2" { type primary; file "db.log2"; }; + zone "log3" { type primary; file "db.log3"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.max.conf b/bin/tests/system/rpzrecurse/ns2/named.max.conf new file mode 100644 index 0000000..b07783b --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.max.conf @@ -0,0 +1,161 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "max1"; + zone "max2"; + zone "max3"; + zone "max4"; + zone "max5"; + zone "max6"; + zone "max7"; + zone "max8"; + zone "max9"; + zone "max10"; + zone "max11"; + zone "max12"; + zone "max13"; + zone "max14"; + zone "max15"; + zone "max16"; + zone "max17"; + zone "max18"; + zone "max19"; + zone "max20"; + zone "max21"; + zone "max22"; + zone "max23"; + zone "max24"; + zone "max25"; + zone "max26"; + zone "max27"; + zone "max28"; + zone "max29"; + zone "max30"; + zone "max31"; + zone "max32"; + zone "max33"; + zone "max34"; + zone "max35"; + zone "max36"; + zone "max37"; + zone "max38"; + zone "max39"; + zone "max40"; + zone "max41"; + zone "max42"; + zone "max43"; + zone "max44"; + zone "max45"; + zone "max46"; + zone "max47"; + zone "max48"; + zone "max49"; + zone "max50"; + zone "max51"; + zone "max52"; + zone "max53"; + zone "max54"; + zone "max55"; + zone "max56"; + zone "max57"; + zone "max58"; + zone "max59"; + zone "max60"; + zone "max61"; + zone "max62"; + zone "max63"; + zone "max64"; + } qname-wait-recurse no + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "max1" { type primary; file "db.max1.local"; }; + zone "max2" { type primary; file "db.max2.local"; }; + zone "max3" { type primary; file "db.max3.local"; }; + zone "max4" { type primary; file "db.max4.local"; }; + zone "max5" { type primary; file "db.max5.local"; }; + zone "max6" { type primary; file "db.max6.local"; }; + zone "max7" { type primary; file "db.max7.local"; }; + zone "max8" { type primary; file "db.max8.local"; }; + zone "max9" { type primary; file "db.max9.local"; }; + zone "max10" { type primary; file "db.max10.local"; }; + zone "max11" { type primary; file "db.max11.local"; }; + zone "max12" { type primary; file "db.max12.local"; }; + zone "max13" { type primary; file "db.max13.local"; }; + zone "max14" { type primary; file "db.max14.local"; }; + zone "max15" { type primary; file "db.max15.local"; }; + zone "max16" { type primary; file "db.max16.local"; }; + zone "max17" { type primary; file "db.max17.local"; }; + zone "max18" { type primary; file "db.max18.local"; }; + zone "max19" { type primary; file "db.max19.local"; }; + zone "max20" { type primary; file "db.max20.local"; }; + zone "max21" { type primary; file "db.max21.local"; }; + zone "max22" { type primary; file "db.max22.local"; }; + zone "max23" { type primary; file "db.max23.local"; }; + zone "max24" { type primary; file "db.max24.local"; }; + zone "max25" { type primary; file "db.max25.local"; }; + zone "max26" { type primary; file "db.max26.local"; }; + zone "max27" { type primary; file "db.max27.local"; }; + zone "max28" { type primary; file "db.max28.local"; }; + zone "max29" { type primary; file "db.max29.local"; }; + zone "max30" { type primary; file "db.max30.local"; }; + zone "max31" { type primary; file "db.max31.local"; }; + zone "max32" { type primary; file "db.max32.local"; }; + zone "max33" { type primary; file "db.max33.local"; }; + zone "max34" { type primary; file "db.max34.local"; }; + zone "max35" { type primary; file "db.max35.local"; }; + zone "max36" { type primary; file "db.max36.local"; }; + zone "max37" { type primary; file "db.max37.local"; }; + zone "max38" { type primary; file "db.max38.local"; }; + zone "max39" { type primary; file "db.max39.local"; }; + zone "max40" { type primary; file "db.max40.local"; }; + zone "max41" { type primary; file "db.max41.local"; }; + zone "max42" { type primary; file "db.max42.local"; }; + zone "max43" { type primary; file "db.max43.local"; }; + zone "max44" { type primary; file "db.max44.local"; }; + zone "max45" { type primary; file "db.max45.local"; }; + zone "max46" { type primary; file "db.max46.local"; }; + zone "max47" { type primary; file "db.max47.local"; }; + zone "max48" { type primary; file "db.max48.local"; }; + zone "max49" { type primary; file "db.max49.local"; }; + zone "max50" { type primary; file "db.max50.local"; }; + zone "max51" { type primary; file "db.max51.local"; }; + zone "max52" { type primary; file "db.max52.local"; }; + zone "max53" { type primary; file "db.max53.local"; }; + zone "max54" { type primary; file "db.max54.local"; }; + zone "max55" { type primary; file "db.max55.local"; }; + zone "max56" { type primary; file "db.max56.local"; }; + zone "max57" { type primary; file "db.max57.local"; }; + zone "max58" { type primary; file "db.max58.local"; }; + zone "max59" { type primary; file "db.max59.local"; }; + zone "max60" { type primary; file "db.max60.local"; }; + zone "max61" { type primary; file "db.max61.local"; }; + zone "max62" { type primary; file "db.max62.local"; }; + zone "max63" { type primary; file "db.max63.local"; }; + zone "max64" { type primary; file "db.max64.local"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf new file mode 100644 index 0000000..23ef4eb --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard1.conf @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "wildcard1" policy NXDOMAIN; + } qname-wait-recurse yes + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "wildcard1" { type primary; file "db.wildcard1"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf new file mode 100644 index 0000000..b570b47 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard2.conf @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "wildcard2a" policy NXDOMAIN; + zone "wildcard2b" policy NXDOMAIN; + } qname-wait-recurse yes + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "wildcard2a" { type primary; file "db.wildcard2a"; }; + zone "wildcard2b" { type primary; file "db.wildcard2b"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf new file mode 100644 index 0000000..befb7d2 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard3.conf @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { + zone "wildcard3" policy NXDOMAIN; + } qname-wait-recurse yes + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "wildcard3" { type primary; file "db.wildcard3"; }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf b/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf new file mode 100644 index 0000000..e18f496 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/named.wildcard4.conf @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +# common configuration +include "named.conf.header"; + +view "recursive" { + # policy configuration to be tested + response-policy { + zone "passthru.zone" policy passthru; + zone "given.zone" policy given; + } qname-wait-recurse yes + nsdname-enable yes + nsip-enable yes; + + # policy zones to be tested + zone "passthru.zone" { type primary; file "db.passthru"; }; + zone "given.zone" { type primary; file "db.given"; }; + + zone "." { + type hint; + file "root.hint"; + }; + + recursion yes; + dnssec-validation yes; +}; diff --git a/bin/tests/system/rpzrecurse/ns2/root.hint b/bin/tests/system/rpzrecurse/ns2/root.hint new file mode 100644 index 0000000..ced47f3 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns2/root.hint @@ -0,0 +1,14 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 999999 +. IN NS ns.example. +ns.example. IN A 10.53.0.1 diff --git a/bin/tests/system/rpzrecurse/ns3/example.db b/bin/tests/system/rpzrecurse/ns3/example.db new file mode 100644 index 0000000..201a174 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/example.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +@ SOA . . 0 0 0 0 0 +@ NS ns +ns A 10.53.0.3 +child NS ns.child +ns.child A 10.53.0.4 diff --git a/bin/tests/system/rpzrecurse/ns3/named1.conf.in b/bin/tests/system/rpzrecurse/ns3/named1.conf.in new file mode 100644 index 0000000..3159c63 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/named1.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + response-policy { zone "policy"; } + qname-wait-recurse yes + nsip-enable yes + nsdname-enable yes; + + include "../dnsrps.conf"; +}; + +trust-anchors { }; + +zone "policy" { type primary; file "policy.db"; }; + +zone "example.tld" { type primary; file "example.db"; }; + +zone "." { type primary; file "root.db"; }; diff --git a/bin/tests/system/rpzrecurse/ns3/named2.conf.in b/bin/tests/system/rpzrecurse/ns3/named2.conf.in new file mode 100644 index 0000000..2370b43 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/named2.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + response-policy { zone "policy"; } nsip-wait-recurse no + qname-wait-recurse yes + nsip-enable yes + nsdname-enable yes; + + include "../dnsrps.conf"; +}; + +trust-anchors { }; + +zone "policy" { type primary; file "policy.db"; }; + +zone "example.tld" { type primary; file "example.db"; }; + +zone "." { type primary; file "root.db"; }; diff --git a/bin/tests/system/rpzrecurse/ns3/named3.conf.in b/bin/tests/system/rpzrecurse/ns3/named3.conf.in new file mode 100644 index 0000000..af57689 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/named3.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "../../_common/rndc.key"; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + response-policy { zone "policy"; } nsdname-wait-recurse no + nsdname-enable yes; + + include "../dnsrps.conf"; +}; + +trust-anchors { }; + +zone "policy" { type primary; file "policy.db"; }; + +zone "example.tld" { type primary; file "example.db"; }; + +zone "." { type primary; file "root.db"; }; diff --git a/bin/tests/system/rpzrecurse/ns3/policy.db b/bin/tests/system/rpzrecurse/ns3/policy.db new file mode 100644 index 0000000..526d75c --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/policy.db @@ -0,0 +1,15 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +@ SOA . . 0 0 0 0 0 +@ NS . +32.100.0.53.10.rpz-nsip CNAME . diff --git a/bin/tests/system/rpzrecurse/ns3/root.db b/bin/tests/system/rpzrecurse/ns3/root.db new file mode 100644 index 0000000..665953d --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns3/root.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +@ SOA . . 0 0 0 0 0 +@ NS ns +ns A 10.53.0.3 +foo NS foo.ns5 +ns5.foo A 10.53.0.5 diff --git a/bin/tests/system/rpzrecurse/ns4/child.example.db b/bin/tests/system/rpzrecurse/ns4/child.example.db new file mode 100644 index 0000000..47a90fb --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns4/child.example.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 0 +@ SOA . . 0 0 0 0 0 +@ NS ns +ns A 10.53.0.4 +foo NS ns.foo +foo NS ns.foo. +ns.foo A 10.53.0.5 diff --git a/bin/tests/system/rpzrecurse/ns4/named.conf.in b/bin/tests/system/rpzrecurse/ns4/named.conf.in new file mode 100644 index 0000000..b8d87b9 --- /dev/null +++ b/bin/tests/system/rpzrecurse/ns4/named.conf.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +controls { /* empty */ }; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "child.example.tld" { type primary; file "child.example.db"; }; diff --git a/bin/tests/system/rpzrecurse/prereq.sh b/bin/tests/system/rpzrecurse/prereq.sh new file mode 100644 index 0000000..c52be9c --- /dev/null +++ b/bin/tests/system/rpzrecurse/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MNet::DNS -e ''; then + echo_i "perl Net::DNS module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/rpzrecurse/setup.sh b/bin/tests/system/rpzrecurse/setup.sh new file mode 100644 index 0000000..eae0743 --- /dev/null +++ b/bin/tests/system/rpzrecurse/setup.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# touch dnsrps-off to not test with DNSRPS + +set -e + +. ../conf.sh + +$PERL testgen.pl + +copy_setports ns1/named.conf.in ns1/named.conf + +copy_setports ns2/named.conf.header.in ns2/named.conf.header +copy_setports ns2/named.default.conf ns2/named.conf + +copy_setports ns3/named1.conf.in ns3/named.conf + +copy_setports ns4/named.conf.in ns4/named.conf + +touch dnsrps.conf +touch dnsrps.cache + +# setup policy zones for a 64-zone test +i=1 +while test $i -le 64; do + echo "\$TTL 60" >ns2/db.max$i.local + echo "@ IN SOA root.ns ns 1996072700 3600 1800 86400 60" >>ns2/db.max$i.local + echo " NS ns" >>ns2/db.max$i.local + echo "ns A 127.0.0.1" >>ns2/db.max$i.local + + j=1 + while test $j -le $i; do + echo "name$j A 10.53.0.$i" >>ns2/db.max$i.local + j=$((j + 1)) + done + i=$((i + 1)) +done diff --git a/bin/tests/system/rpzrecurse/testgen.pl b/bin/tests/system/rpzrecurse/testgen.pl new file mode 100755 index 0000000..4131bd9 --- /dev/null +++ b/bin/tests/system/rpzrecurse/testgen.pl @@ -0,0 +1,343 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +my $boilerplate_header = <<'EOB'; +# common configuration +include "named.conf.header"; + +view "recursive" { + zone "." { + type hint; + file "root.hint"; + }; + + # policy configuration to be tested + response-policy { +EOB + +my $no_option = <<'EOB'; + } nsdname-enable yes nsip-enable yes; + + # policy zones to be tested +EOB + +my $qname_wait_recurse = <<'EOB'; + } nsdname-enable yes nsip-enable yes qname-wait-recurse no; + + # policy zones to be tested +EOB + +my $boilerplate_end = <<'EOB'; +}; +EOB + +my $policy_option = $qname_wait_recurse; + +my $serialnum = "1"; +my $policy_zone_header = <<'EOH'; +$TTL 60 +@ IN SOA root.ns ns SERIAL 3600 1800 86400 60 + NS ns +ns A 127.0.0.1 +EOH + +sub policy_client_ip { + return "32.1.0.0.127.rpz-client-ip CNAME .\n"; +} + +sub policy_qname { + my $query_nbr = shift; + return sprintf "q%02d.l2.l1.l0 CNAME .\n", $query_nbr; +} + +sub policy_ip { + return "32.255.255.255.255.rpz-ip CNAME .\n"; +} + +sub policy_nsdname { + return "ns.example.org.rpz-nsdname CNAME .\n"; +} + +sub policy_nsip { + return "32.255.255.255.255.rpz-ip CNAME .\n"; +} + +my %static_triggers = ( + 'client-ip' => \&policy_client_ip, + 'ip' => \&policy_ip, + 'nsdname' => \&policy_nsdname, + 'nsip' => \&policy_nsip, +); + +sub mkconf { + my $case_id = shift; + my $n_queries = shift; + + { # generate the query list + my $query_list_filename = "ns2/$case_id.queries"; + my $query_list_fh; + + open $query_list_fh, ">$query_list_filename" or die; + + for( my $i = 1; $i <= $n_queries; $i++ ) { + print $query_list_fh sprintf "q%02d.l2.l1.l0\n", $i; + } + } + + my @zones; + + { # generate the conf file + my $conf_filename = "ns2/named.$case_id.conf"; + + my $conf_fh; + + open $conf_fh, ">$conf_filename" or die; + + print $conf_fh $boilerplate_header; + + my $zone_seq = 0; + + @zones = map { + [ + sprintf( "$case_id.%02d.policy.local", $zone_seq++ ), + $_, + ]; + } @_; + + print $conf_fh map { qq{ zone "$_->[0]";\n} } @zones; + + print $conf_fh $policy_option; + + print $conf_fh map { qq{ zone "$_->[0]" { type primary; file "db.$_->[0]"; };\n} } @zones; + + print $conf_fh $boilerplate_end; + } + + # generate the policy zone contents + foreach my $policy_zone_info( @zones ) { + my $policy_zone_name = $policy_zone_info->[0]; + my $policy_zone_contents = $policy_zone_info->[1]; + + my $policy_zone_filename = "ns2/db.$policy_zone_name"; + my $policy_zone_fh; + + open $policy_zone_fh, ">$policy_zone_filename" or die; + + my $header = $policy_zone_header; + $header =~ s/SERIAL/$serialnum/; + print $policy_zone_fh $header; + + foreach my $trigger( @$policy_zone_contents ) { + if( exists $static_triggers{$trigger} ) { + # matches a trigger type with a static value + print $policy_zone_fh $static_triggers{$trigger}->(); + } + else { + # a qname trigger, where what was specified is the query number it should match + print $policy_zone_fh policy_qname( $trigger ); + } + } + } +} + +mkconf( + '1a', + 1, + [ 'client-ip' ], +); + +mkconf( + '1b', + 2, + [ 1 ], +); + +mkconf( + '1c', + 1, + [ 'client-ip', 2 ], +); + +mkconf( + '2a', + 33, + map { [ $_ ]; } 1 .. 32 +); + +mkconf( + '3a', + 1, + [ 'ip' ], +); + +mkconf( + '3b', + 1, + [ 'nsdname' ], +); + +mkconf( + '3c', + 1, + [ 'nsip' ], +); + +mkconf( + '3d', + 2, + [ 'ip', 1 ] +); + +mkconf( + '3e', + 2, + [ 'nsdname', 1 ] +); + +mkconf( + '3f', + 2, + [ 'nsip', 1 ] +); + +{ + my $seq_code = 'aa'; + my $seq_nbr = 0; + + while( $seq_nbr < 32 ) { + + mkconf( + "4$seq_code", + 33, + ( map { [ $_ ]; } 1 .. $seq_nbr ), + [ 'ip', $seq_nbr + 2 ], + ( map { [ $_ + 2 ]; } ($seq_nbr + 1) .. 31 ), + ); + + $seq_code++; + $seq_nbr++; + } +} + +mkconf( + '5a', + 6, + [ 1 ], + [ 2, 'ip' ], + [ 4 ], + [ 5, 'ip' ], + [ 6 ], +); + +$policy_option = $no_option; + +mkconf( + '6a', + 0, + [ ], +); + +$serialnum = "2"; +mkconf( + '6b', + 0, + [ 'nsdname' ], +); + +$serialnum = "3"; +mkconf( + '6c', + 0, + [ ], +); + +__END__ + +0x01 - has client-ip + 32.1.0.0.127.rpz-client-ip CNAME . +0x02 - has qname + qX.l2.l1.l0 CNAME . +0x10 - has ip + 32.255.255.255.255.rpz-ip CNAME . +0x20 - has nsdname + ns.example.org.rpz-nsdname CNAME . +0x40 - has nsip + 32.255.255.255.255.rpz-nsip CNAME . + +$case.$seq.policy.local + +case 1a = 0x01 + .q01 = (00,0x01)=-r +case 1b = 0x02 + .q01 = (00,0x02)=-r + .q02 = (--,----)=+r +case 1c = 0x03 + .q01 = (00,0x01)=-r + +case 2a = 0x03{32} + .q01 = (00,0x02)=-r + .q02 = (01,0x02)=-r + ... + .q31 = (30,0x02)=-r + .q32 = (31,0x02)=-r + .q33 = (--,----)=+r + +case 3a = 0x10 + .q01 = (00,0x10)=+r +case 3b = 0x20 + .q01 = (00,0x20)=+r +case 3c = 0x40 + .q01 = (00,0x40)=+r +case 3d = 0x12 + .q01 = (00,0x10)=+r + .q02 = (00,0x02)=-r +case 3e = 0x22 + .q01 = (00,0x20)=+r + .q02 = (00,0x02)=-r +case 3f = 0x42 + .q01 = (00,0x40)=+r + .q02 = (00,0x02)=-r + +case 4aa = 0x12,0x02{31} + .q01 = (00,0x10)=+r + .q02 = (00,0x02)=-r + .q03 = (01,0x02)=+r + ... + .q32 = (30,0x02)=+r + .q33 = (31,0x02)=+r +case 4__ = 0x02{n(1->30)},0x12,0x02{31-n} + .q01 = (00,0x02)=-r + ... + .q(n+1) = (n,0x10)=+r + .q(n+2) = (n,0x02)=-r + ... + .q33 = (31,0x02)=+r +case 4bf = 0x02{31},0x12 + .q01 = (00,0x02)=-r + .q02 = (01,0x02)=-r + ... + .q31 = (30,0x02)=-r + .q32 = (31,0x10)=+r + .q33 = (31,0x02)=-r + +case 5a = 0x02,0x12,0x02,0x12,0x02 + .q01 = (00,0x02)=-r + .q02 = (01,0x02)=-r + .q03 = (01,0x10)=+r + .q04 = (02,0x02)=+r + .q05 = (03,0x02)=+r + .q06 = (04,0x02)=+r + diff --git a/bin/tests/system/rpzrecurse/tests.sh b/bin/tests/system/rpzrecurse/tests.sh new file mode 100644 index 0000000..ec6b143 --- /dev/null +++ b/bin/tests/system/rpzrecurse/tests.sh @@ -0,0 +1,535 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# touch dnsrps-off to not test with DNSRPS +# touch dnsrps-only to not test with classic RPZ + +. ../conf.sh + +status=0 + +t=0 + +export DNSRPS_TEST_UPDATE_FILE=$(pwd)/dnsrps.cache +ARGS= +if grep 'dnsrps-enable yes;' dnsrps.conf >/dev/null; then + MODE=dnsrps +else + MODE=native +fi + +USAGE="$0: [-S]" +while getopts "S:" c; do + case $c in + S) + SAVE_RESULTS=-S + ARGS="$ARGS -S" + ;; + *) + echo "$USAGE" 1>&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) +if test "$#" -ne 0; then + echo "$USAGE" 1>&2 + exit 1 +fi +# really quit on control-C +trap 'exit 1' 1 2 15 + +DNSRPSCMD=../rpz/dnsrps +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists) +run_server() { + TESTNAME=$1 + + start_server_rules $1 $2 + echo_i "stopping resolver" + stop_server --use-rndc --port ${CONTROLPORT} ns2 + + sleep 1 + + echo_i "starting resolver using named.$TESTNAME.conf" + cp -f ns2/named.$TESTNAME.conf ns2/named.conf + start_server --noclean --restart --port ${PORT} ns2 + sleep 3 +} + +start_server_rules() { + FCONF=ns2/named.$1.conf + + cat /dev/null >$DNSRPS_TEST_UPDATE_FILE + cat $FCONF | grep 'zone ' | grep ' primary' | while read LINE; do + ZONE=$(echo $LINE | sed 's/.*zone "//g' | awk -F '"' '{print $1}') + DBFILE=$(echo $LINE | sed 's/.*file "//g' | awk -F '"' '{print $1}') + cat ns2/$DBFILE | grep -E -v '^;' | grep -E '\<(A|CNAME)\>' | awk -v zone=$ZONE '{ if (NF == 4) {print "static add "$1"."zone" "$2" "$3" "$4} else if (NF == 3) {print "static add "$1"."zone" 300 "$2" "$3}}' >>$DNSRPS_TEST_UPDATE_FILE + done +} + +produce_librpz_rules() { + ZONEFILE=$1/$3.db + cat $ZONEFILE | grep -E -v '^;' | grep -E '\<(A|CNAME)\>' | awk -v zone=$2 '{ if (NF == 4) {print "static add "$1"."zone" "$2" "$3" "$4} else if (NF == 3) {print "static add "$1"."zone" 300 "$2" "$3}}' >>$DNSRPS_TEST_UPDATE_FILE +} + +run_query() { + TESTNAME=$1 + LINE=$2 + + NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1) + $DIG $DIGOPTS $NAME a @10.53.0.2 -p ${PORT} -b 127.0.0.1 >dig.out.${t} + grep "status: SERVFAIL" dig.out.${t} >/dev/null 2>&1 && return 1 + return 0 +} + +# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists) +# $2 = line number in query file to test (the name to query is taken from this line) +expect_norecurse() { + TESTNAME=$1 + LINE=$2 + + NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1) + t=$((t + 1)) + echo_i "testing $NAME doesn't recurse (${t})" + add_test_marker 10.53.0.2 + run_query $TESTNAME $LINE || { + echo_i "test ${t} failed" + status=1 + } +} + +# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists) +# $2 = line number in query file to test (the name to query is taken from this line) +expect_recurse() { + TESTNAME=$1 + LINE=$2 + + NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1) + t=$((t + 1)) + echo_i "testing $NAME recurses (${t})" + add_test_marker 10.53.0.2 + run_query $TESTNAME $LINE && { + echo_i "test ${t} failed" + status=1 + } + return 0 +} + +add_test_marker() { + for ns in $@; do + $RNDCCMD $ns null ---- test ${t} ---- + done +} + +t=$((t + 1)) +echo_i "testing that l1.l0 exists without RPZ (${t})" +add_test_marker 10.53.0.2 +$DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p ${PORT} >dig.out.${t} +grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test ${t} failed" + status=1 +} + +t=$((t + 1)) +echo_i "testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})" +add_test_marker 10.53.0.2 +$DIG $DIGOPTS l2.l1.l0 ns @10.53.0.2 -p ${PORT} >dig.out.${t} +grep "status: SERVFAIL" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test ${t} failed" + status=1 +} + +# Group 1 +run_server 1a +expect_norecurse 1a 1 +run_server 1b +expect_norecurse 1b 1 +expect_recurse 1b 2 +run_server 1c +expect_norecurse 1c 1 + +# Group 2 +run_server 2a +for n in 1 2 3 4 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; do + expect_norecurse 2a $n +done +expect_recurse 2a 33 + +# Group 3 +run_server 3a +expect_recurse 3a 1 +run_server 3b +expect_recurse 3b 1 +run_server 3c +expect_recurse 3c 1 +run_server 3d +expect_norecurse 3d 1 +expect_recurse 3d 2 +run_server 3e +expect_norecurse 3e 1 +expect_recurse 3e 2 +run_server 3f +expect_norecurse 3f 1 +expect_recurse 3f 2 + +# Group 4 +testlist="aa ap bf" +values="1 16 32" +# Uncomment the following to test every skip value instead of +# only a sample of values +# +#testlist="aa ab ac ad ae af ag ah ai aj ak al am an ao ap \ +# aq ar as at au av aw ax ay az ba bb bc bd be bf" +#values="1 2 3 4 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" +set -- $values +for n in $testlist; do + run_server 4$n + ni=$1 + t=$((t + 1)) + echo_i "testing that ${ni} of 33 queries skip recursion (${t})" + add_test_marker 10.53.0.2 + c=0 + for i in 1 2 3 4 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; do + run_query 4$n $i || c=$((c + 1)) + done + skipped=$((33 - c)) + if [ $skipped != $ni ]; then + echo_i "test $t failed (actual=$skipped, expected=$ni)" + status=1 + fi + shift +done + +# Group 5 +run_server 5a +expect_norecurse 5a 1 +expect_norecurse 5a 2 +expect_recurse 5a 3 +expect_recurse 5a 4 +expect_recurse 5a 5 +expect_recurse 5a 6 + +# Group 6 +echo_i "check recursive behavior consistency during policy update races" +run_server 6a +sleep 1 +t=$((t + 1)) +echo_i "running dig to cache CNAME record (${t})" +add_test_marker 10.53.0.1 10.53.0.2 +$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME >dig.out.${t} +sleep 1 +echo_i "suspending authority server" +PID=$(cat ns1/named.pid) +kill -STOP $PID +echo_i "adding an NSDNAME policy" +cp ns2/db.6a.00.policy.local ns2/saved.policy.local +cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i +test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true +sleep 1 +t=$((t + 1)) +echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})" +add_test_marker 10.53.0.2 +$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 >dig.out.${t} & +sleep 1 +echo_i "removing the NSDNAME policy" +cp ns2/db.6c.00.policy.local ns2/db.6a.00.policy.local +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i +test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true +sleep 1 +echo_i "resuming authority server" +PID=$(cat ns1/named.pid) +kill -CONT $PID +add_test_marker 10.53.0.1 +for n in 1 2 3 4 5 6 7 8 9; do + sleep 1 + [ -s dig.out.${t} ] || continue + grep "status: .*," dig.out.${t} >/dev/null 2>&1 && break +done +grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test ${t} failed" + status=1 +} + +echo_i "check recursive behavior consistency during policy removal races" +cp ns2/saved.policy.local ns2/db.6a.00.policy.local +run_server 6a +sleep 1 +t=$((t + 1)) +echo_i "running dig to cache CNAME record (${t})" +add_test_marker 10.53.0.1 10.53.0.2 +$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME >dig.out.${t} +sleep 1 +echo_i "suspending authority server" +PID=$(cat ns1/named.pid) +kill -STOP $PID +echo_i "adding an NSDNAME policy" +cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local +$RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i +test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true +sleep 1 +t=$((t + 1)) +echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})" +add_test_marker 10.53.0.2 +$DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 >dig.out.${t} & +sleep 1 +echo_i "removing the policy zone" +cp ns2/named.default.conf ns2/named.conf +rndc_reconfig ns2 10.53.0.2 +test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true +sleep 1 +echo_i "resuming authority server" +PID=$(cat ns1/named.pid) +kill -CONT $PID +add_test_marker 10.53.0.1 +for n in 1 2 3 4 5 6 7 8 9; do + sleep 1 + [ -s dig.out.${t} ] || continue + grep "status: .*," dig.out.${t} >/dev/null 2>&1 && break +done +grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test ${t} failed" + status=1 +} + +# Check maximum number of RPZ zones (64) +t=$((t + 1)) +echo_i "testing maximum number of RPZ zones (${t})" +add_test_marker 10.53.0.2 +run_server max +i=1 +while test $i -le 64; do + $DIG $DIGOPTS name$i a @10.53.0.2 -p ${PORT} -b 10.53.0.1 >dig.out.${t}.${i} + grep "^name$i.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.$i" dig.out.${t}.${i} >/dev/null 2>&1 || { + echo_i "test $t failed: didn't get expected answer from policy zone $i" + status=1 + } + i=$((i + 1)) +done + +# Check CLIENT-IP behavior +t=$((t + 1)) +echo_i "testing CLIENT-IP behavior (${t})" +add_test_marker 10.53.0.2 +run_server clientip +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t} +grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed: query failed" + status=1 +} +grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.2" dig.out.${t} >/dev/null 2>&1 || { + echo_i "test $t failed: didn't get expected answer" + status=1 +} + +# Check CLIENT-IP behavior #2 +t=$((t + 1)) +echo_i "testing CLIENT-IP behavior #2 (${t})" +add_test_marker 10.53.0.2 +run_server clientip2 +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.1 >dig.out.${t}.1 +grep "status: SERVFAIL" dig.out.${t}.1 >/dev/null 2>&1 || { + echo_i "test $t failed: query failed" + status=1 +} +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >dig.out.${t}.2 +grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null 2>&1 || { + echo_i "test $t failed: query failed" + status=1 +} +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >dig.out.${t}.3 +grep "status: NOERROR" dig.out.${t}.3 >/dev/null 2>&1 || { + echo_i "test $t failed: query failed" + status=1 +} +grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.1" dig.out.${t}.3 >/dev/null 2>&1 || { + echo_i "test $t failed: didn't get expected answer" + status=1 +} +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t}.4 +grep "status: SERVFAIL" dig.out.${t}.4 >/dev/null 2>&1 || { + echo_i "test $t failed: query failed" + status=1 +} + +# Check RPZ log clause +t=$((t + 1)) +echo_i "testing RPZ log clause (${t})" +add_test_marker 10.53.0.2 +run_server log +cur=$(awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run) +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t} +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >>dig.out.${t} +$DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >>dig.out.${t} +sed -n "$cur,"'$p' /dev/null && { + echo_ic "failed: unexpected rewrite message for policy zone log1 was logged" + status=1 +} +sed -n "$cur,"'$p' /dev/null || { + echo_ic "failed: expected rewrite message for policy zone log2 was not logged" + status=1 +} +sed -n "$cur,"'$p' /dev/null || { + echo_ic "failed: expected rewrite message for policy zone log3 was not logged" + status=1 +} + +# Check wildcard behavior + +t=$((t + 1)) +echo_i "testing wildcard behavior with 1 RPZ zone (${t})" +add_test_marker 10.53.0.2 +run_server wildcard1 +$DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1 +grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} +$DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2 +grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} + +t=$((t + 1)) +echo_i "testing wildcard behavior with 2 RPZ zones (${t})" +add_test_marker 10.53.0.2 +run_server wildcard2 +$DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1 +grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} +$DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2 +grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} + +t=$((t + 1)) +echo_i "testing wildcard behavior with 1 RPZ zone and no non-wildcard triggers (${t})" +add_test_marker 10.53.0.2 +run_server wildcard3 +$DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1 +grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} +$DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2 +grep "status: NOERROR" dig.out.${t}.2 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} + +t=$((t + 1)) +echo_i "testing wildcard passthru before explicit drop (${t})" +add_test_marker 10.53.0.2 +run_server wildcard4 +$DIG $DIGOPTS example.com a @10.53.0.2 -p ${PORT} >dig.out.${t}.1 +grep "status: NOERROR" dig.out.${t}.1 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} +$DIG $DIGOPTS www.example.com a @10.53.0.2 -p ${PORT} >dig.out.${t}.2 +grep "status: NOERROR" dig.out.${t}.2 >/dev/null || { + echo_i "test ${t} failed" + status=1 +} + +if [ "$MODE" = "native" ]; then + # Check for invalid prefix length error + t=$((t + 1)) + echo_i "testing for invalid prefix length error (${t})" + add_test_marker 10.53.0.2 + run_server invalidprefixlength + grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run >/dev/null || { + echo_ic "failed: expected that invalid prefix length error would be logged" + status=1 + } +fi + +if [ "$MODE" = "native" ]; then + t=$((t + 1)) + echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)" + add_test_marker 10.53.0.2 10.53.0.3 + echo_i "timing 'nsip-wait-recurse yes' (default)" + produce_librpz_rules ns3 policy policy + ret=0 + t1=$($PERL -e 'print time()."\n";') + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.yes.$t + t2=$($PERL -e 'print time()."\n";') + p1=$((t2 - t1)) + echo_i "elapsed time $p1 seconds" + + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush + copy_setports ns3/named2.conf.in ns3/named.conf + nextpart ns3/named.run >/dev/null + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null + wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1 + + echo_i "timing 'nsip-wait-recurse no'" + echo "update zone policy 0 no_nsip_wait_recurse" >$DNSRPS_TEST_UPDATE_FILE + t3=$($PERL -e 'print time()."\n";') + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.no.$t + t4=$($PERL -e 'print time()."\n";') + p2=$((t4 - t3)) + echo_i "elapsed time $p2 seconds" + + if test $p1 -le $p2; then ret=1; fi + if test $ret != 0; then echo_i "failed"; fi + status=$((status + ret)) + + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush + # restore original named.conf + copy_setports ns3/named1.conf.in ns3/named.conf + nextpart ns3/named.run >/dev/null + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null + wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1 + + t=$((t + 1)) + echo_i "checking 'nsdname-wait-recurse no' is faster than 'nsdname-wait-recurse yes' ($t)" + add_test_marker 10.53.0.2 10.53.0.3 + echo_i "timing 'nsdname-wait-recurse yes' (default)" + ret=0 + t1=$($PERL -e 'print time()."\n";') + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.yes.$t + t2=$($PERL -e 'print time()."\n";') + p1=$((t2 - t1)) + echo_i "elapsed time $p1 seconds" + + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush + copy_setports ns3/named3.conf.in ns3/named.conf + nextpart ns3/named.run >/dev/null + $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null + wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1 + + echo_i "timing 'nsdname-wait-recurse no'" + t3=$($PERL -e 'print time()."\n";') + $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.no.$t + t4=$($PERL -e 'print time()."\n";') + p2=$((t4 - t3)) + echo_i "elapsed time $p2 seconds" + + if test $p1 -le $p2; then ret=1; fi + if test $ret != 0; then echo_i "failed"; fi + status=$((status + ret)) +fi + +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py new file mode 100644 index 0000000..983c6c3 --- /dev/null +++ b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse.py @@ -0,0 +1,29 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "dnsrps.cache", + "dnsrps.conf", + "ans*/ans.run", + "ns2/*.queries", + "ns2/*.local", + "ns2/named.*.conf", + "ns2/named.conf.header", + ] +) + + +def test_rpzrecurse(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse_dnsrps.py b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse_dnsrps.py new file mode 100644 index 0000000..a32d70c --- /dev/null +++ b/bin/tests/system/rpzrecurse/tests_sh_rpzrecurse_dnsrps.py @@ -0,0 +1,42 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = [ + isctest.mark.dnsrps_enabled, + pytest.mark.extra_artifacts( + [ + "dig.out.*", + "dnsrps.cache", + "dnsrps.conf", + "ans*/ans.run", + "ns2/*.queries", + "ns2/*.local", + "ns2/named.*.conf", + "ns2/named.conf.header", + ] + ), +] + + +def test_rpzrecurse_dnsrps(run_tests_sh): + with open("dnsrps.conf", "w", encoding="utf-8") as conf: + conf.writelines( + [ + "dnsrps-options { log-level 3 };" + "dnsrps-enable yes;" + 'dnsrps-library "../../rpz/testlib/.libs/libdummyrpz.so";' + ] + ) + run_tests_sh() diff --git a/bin/tests/system/rrchecker/tests_rrchecker.py b/bin/tests/system/rrchecker/tests_rrchecker.py new file mode 100644 index 0000000..e788353 --- /dev/null +++ b/bin/tests/system/rrchecker/tests_rrchecker.py @@ -0,0 +1,183 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os + +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "tempzone", + ] +) + + +@pytest.mark.parametrize( + "option,expected_result", + [ + ("-C", ["HS", "CH", "IN"]), + ( + "-T", + [ + "A", + "A6", + "AAAA", + "AFSDB", + "AMTRELAY", + "APL", + "ATMA", + "AVC", + "CAA", + "CDNSKEY", + "CDS", + "CERT", + "CNAME", + "CSYNC", + "DHCID", + "DLV", + "DNAME", + "DNSKEY", + "DOA", + "DS", + "EID", + "EUI48", + "EUI64", + "GID", + "GPOS", + "HINFO", + "HIP", + "HTTPS", + "IPSECKEY", + "ISDN", + "KEY", + "KX", + "L32", + "L64", + "LOC", + "LP", + "MB", + "MD", + "MF", + "MG", + "MINFO", + "MR", + "MX", + "NAPTR", + "NID", + "NIMLOC", + "NINFO", + "NS", + "NSAP", + "NSAP-PTR", + "NSEC", + "NSEC3", + "NSEC3PARAM", + "NULL", + "NXT", + "OPENPGPKEY", + "PTR", + "PX", + "RESINFO", + "RKEY", + "RP", + "RRSIG", + "RT", + "SIG", + "SINK", + "SMIMEA", + "SOA", + "SPF", + "SRV", + "SSHFP", + "SVCB", + "TA", + "TALINK", + "TLSA", + "TXT", + "UID", + "UINFO", + "UNSPEC", + "URI", + "WALLET", + "WKS", + "X25", + "ZONEMD", + ], + ), + ("-P", []), + ], +) +def test_rrchecker_list_standard_names(option, expected_result): + stdout = isctest.run.cmd([os.environ["RRCHECKER"], option]).stdout.decode("utf-8") + values = [line for line in stdout.split("\n") if line.strip()] + + assert sorted(values) == sorted(expected_result) + + +def run_rrchecker(option, rr_class, rr_type, rr_rest): + rrchecker_output = ( + isctest.run.cmd( + [os.environ["RRCHECKER"], option], + input_text=f"{rr_class} {rr_type} {rr_rest}".encode("utf-8"), + ) + .stdout.decode("utf-8") + .strip() + ) + return rrchecker_output.split() + + +@pytest.mark.parametrize("option", ["-p", "-u"]) +def test_rrchecker_conversions(option): + tempzone_file = "tempzone" + with open(tempzone_file, "w", encoding="utf-8") as file: + isctest.run.cmd( + [ + os.environ["SHELL"], + os.environ["TOP_SRCDIR"] + "/bin/tests/system/genzone.sh", + "0", + ], + stdout=file, + ) + checkzone_output = isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + ".", + tempzone_file, + ], + ).stdout.decode("utf-8") + checkzone_output = [ + line for line in checkzone_output.splitlines() if not line.startswith(";") + ] + + for rr in checkzone_output: + rr_parts_orig = rr.split() + assert len(rr_parts_orig) >= 4, f"invalid rr: {rr}" + rr_class_orig, rr_type_orig, rr_rest_orig = ( + rr_parts_orig[2], + rr_parts_orig[3], + " ".join(rr_parts_orig[4:]), + ) + rr_class, rr_type, rr_rest = rr_class_orig, rr_type_orig, rr_rest_orig + if option == "-u": + rr_class, rr_type, *rr_rest = run_rrchecker( + "-u", rr_class_orig, rr_type_orig, rr_rest_orig + ) + rr_rest = " ".join(rr_rest) + + rr_class, rr_type, *rr_rest = run_rrchecker("-p", rr_class, rr_type, rr_rest) + + assert rr_class_orig == rr_class + assert rr_type_orig == rr_type + assert rr_rest_orig == " ".join(rr_rest) diff --git a/bin/tests/system/rrl/ns1/named.conf.j2 b/bin/tests/system/rrl/ns1/named.conf.j2 new file mode 100644 index 0000000..a71e1ee --- /dev/null +++ b/bin/tests/system/rrl/ns1/named.conf.j2 @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + notify no; + recursion yes; + dnssec-validation yes; +}; + +trust-anchors { }; + +zone "." {type primary; file "root.db";}; diff --git a/bin/tests/system/rrl/ns1/root.db b/bin/tests/system/rrl/ns1/root.db new file mode 100644 index 0000000..68265fe --- /dev/null +++ b/bin/tests/system/rrl/ns1/root.db @@ -0,0 +1,27 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns. hostmaster.ns. ( 1 3600 1200 604800 60 ) +@ NS ns. +ns. A 10.53.0.1 +. A 10.53.0.1 + +; limit responses from here +tld2. NS ns.tld2. +ns.tld2. A 10.53.0.2 + +; limit recursion to here +tld3. NS ns.tld3. +ns.tld3. A 10.53.0.3 + +; generate SERVFAIL +tld4. NS ns.tld3. diff --git a/bin/tests/system/rrl/ns2/hints b/bin/tests/system/rrl/ns2/hints new file mode 100644 index 0000000..a1d435e --- /dev/null +++ b/bin/tests/system/rrl/ns2/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 0 NS ns1. +ns1. 0 A 10.53.0.1 diff --git a/bin/tests/system/rrl/ns2/named.conf.j2 b/bin/tests/system/rrl/ns2/named.conf.j2 new file mode 100644 index 0000000..298d370 --- /dev/null +++ b/bin/tests/system/rrl/ns2/named.conf.j2 @@ -0,0 +1,67 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + statistics-file "named.stats"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + notify no; + recursion yes; + dnssec-validation yes; + + rate-limit { + responses-per-second 2; + all-per-second 50; + slip 3; + exempt-clients { 10.53.0.7; }; + + // small enough to force a table expansion + min-table-size 75; + }; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* + * These log settings have no effect unless "-g" is removed from ../../start.pl + */ +logging { + channel debug { + file "log-debug"; + print-category yes; print-severity yes; severity debug 10; + }; + channel queries { + file "log-queries"; + print-category yes; print-severity yes; severity info; + }; + category rate-limit { debug; queries; }; + category queries { debug; queries; }; +}; + +zone "." { type hint; file "hints"; }; + +zone "tld2."{ type primary; file "tld2.db"; }; diff --git a/bin/tests/system/rrl/ns2/tld2.db b/bin/tests/system/rrl/ns2/tld2.db new file mode 100644 index 0000000..a1a832b --- /dev/null +++ b/bin/tests/system/rrl/ns2/tld2.db @@ -0,0 +1,42 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; rate limit response from this zone + +$TTL 120 +@ SOA tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) + NS ns + NS . +ns A 10.53.0.2 + +; basic rate limiting +a1 A 192.0.2.1 + +; wildcards +*.a2 A 192.0.2.2 + +; a3 is in tld3 + +; a4 does not exist to give NXDOMAIN + +; a5 for TCP requests +a5 A 192.0.2.5 + +; a6 for whitelisted clients +a6 A 192.0.2.6 + +; a7 for SERVFAIL + +; a8 for NODATA +a8 A 192.0.2.8 + +; a9 for all-per-second limit +$GENERATE 101-180 all$.a9 A 192.0.2.8 diff --git a/bin/tests/system/rrl/ns3/hints b/bin/tests/system/rrl/ns3/hints new file mode 100644 index 0000000..a1d435e --- /dev/null +++ b/bin/tests/system/rrl/ns3/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 0 NS ns1. +ns1. 0 A 10.53.0.1 diff --git a/bin/tests/system/rrl/ns3/named.conf.j2 b/bin/tests/system/rrl/ns3/named.conf.j2 new file mode 100644 index 0000000..4bc0d6f --- /dev/null +++ b/bin/tests/system/rrl/ns3/named.conf.j2 @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + notify no; + recursion yes; + dnssec-validation yes; + + // check that all of the options are parsed without limiting anything + rate-limit { + responses-per-second 200; + referrals-per-second 220; + nodata-per-second 230; + nxdomains-per-second 240; + errors-per-second 250; + all-per-second 700; + ipv4-prefix-length 24; + ipv6-prefix-length 64; + qps-scale 10; + window 1; + max-table-size 1000; + log-only no; + min-table-size 0; + }; + +}; + +trust-anchors { }; + +zone "." { type hint; file "hints"; }; + +zone "tld3."{ type primary; file "tld3.db"; }; diff --git a/bin/tests/system/rrl/ns3/tld3.db b/bin/tests/system/rrl/ns3/tld3.db new file mode 100644 index 0000000..a534c6e --- /dev/null +++ b/bin/tests/system/rrl/ns3/tld3.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; rate limit response from this zone + +$TTL 120 +@ SOA tld3. hostmaster.ns.tld3. ( 1 3600 1200 604800 60 ) + NS ns + NS . +ns A 10.53.0.3 + +*.a3 A 192.0.3.3 diff --git a/bin/tests/system/rrl/ns4/hints b/bin/tests/system/rrl/ns4/hints new file mode 100644 index 0000000..a1d435e --- /dev/null +++ b/bin/tests/system/rrl/ns4/hints @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 0 NS ns1. +ns1. 0 A 10.53.0.1 diff --git a/bin/tests/system/rrl/ns4/named.conf.j2 b/bin/tests/system/rrl/ns4/named.conf.j2 new file mode 100644 index 0000000..bb169f0 --- /dev/null +++ b/bin/tests/system/rrl/ns4/named.conf.j2 @@ -0,0 +1,69 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + session-keyfile "session.key"; + pid-file "named.pid"; + statistics-file "named.stats"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + notify no; + recursion yes; + dnssec-validation yes; + max-udp-size 4096; + + rate-limit { + responses-per-second 2; + all-per-second 50; + slip 3; + exempt-clients { 10.53.0.7; }; + log-only yes; + + // small enough to force a table expansion + min-table-size 75; + }; +}; + +trust-anchors { }; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +/* + * These log settings have no effect unless "-g" is removed from ../../start.pl + */ +logging { + channel debug { + file "log-debug"; + print-category yes; print-severity yes; severity debug 10; + }; + channel queries { + file "log-queries"; + print-category yes; print-severity yes; severity info; + }; + category rate-limit { debug; queries; }; + category queries { debug; queries; }; +}; + +zone "." { type hint; file "hints"; }; + +zone "tld4."{ type primary; file "tld4.db"; }; diff --git a/bin/tests/system/rrl/ns4/tld4.db b/bin/tests/system/rrl/ns4/tld4.db new file mode 100644 index 0000000..a7bc319 --- /dev/null +++ b/bin/tests/system/rrl/ns4/tld4.db @@ -0,0 +1,45 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; rate limit response from this zone + +$TTL 120 +@ SOA tld4. hostmaster.ns.tld4. ( 1 3600 1200 604800 60 ) + NS ns + NS . +ns A 10.53.0.2 + +; basic rate limiting +a1 A 192.0.2.1 + +; wildcards +*.a2 A 192.0.2.2 + +; a3 is in tld3 + +; a4 does not exist to give NXDOMAIN + +; a5 for TCP requests +a5 A 192.0.2.5 + +; a6 for whitelisted clients +a6 A 192.0.2.6 + +; a7 for SERVFAIL + +; a8 for NODATA +a8 A 192.0.2.8 + +; a9 for all-per-second limit +$GENERATE 101-180 all$.a9 A 192.0.2.8 + +; oversized TXT record +$GENERATE 1-100 big 1 TXT "txt$" diff --git a/bin/tests/system/rrl/tests.sh b/bin/tests/system/rrl/tests.sh new file mode 100644 index 0000000..72c12c9 --- /dev/null +++ b/bin/tests/system/rrl/tests.sh @@ -0,0 +1,278 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# test response rate limiting + +. ../conf.sh + +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" + +#set -x + +ns1=10.53.0.1 # root, defining the others +ns2=10.53.0.2 # test server +ns3=10.53.0.3 # secondary test server +ns4=10.53.0.4 # log-only test server +ns7=10.53.0.7 # whitelisted client + +USAGE="$0: [-x]" +while getopts "x" c; do + case $c in + x) set -x ;; + *) + echo "$USAGE" 1>&2 + exit 1 + ;; + esac +done +shift $((OPTIND - 1)) +if test "$#" -ne 0; then + echo "$USAGE" 1>&2 + exit 1 +fi +# really quit on control-C +trap 'exit 1' 1 2 15 + +ret=0 +setret() { + ret=1 + echo_i "$*" +} + +# Wait until soon after the start of a second to make results consistent. +# The start of a second credits a rate limit. +# This would be far easier in C or by assuming a modern version of perl. +sec_start() { + START=$(date) + while true; do + NOW=$(date) + if test "$START" != "$NOW"; then + return + fi + $PERL -e 'select(undef, undef, undef, 0.05)' || true + done +} + +# turn off ${HOME}/.digrc +HOME=/dev/null +export HOME + +# $1=number of tests $2=target domain $3=dig options +QNUM=1 +burst() { + BURST_LIMIT=$1 + shift + BURST_DOM_BASE="$1" + shift + + XCNT=$CNT + CNT='XXX' + eval FILENAME="mdig.out-$BURST_DOM_BASE" + CNT=$XCNT + + DOMS="" + CNTS=$($PERL -e 'for ( $i = 0; $i < '$BURST_LIMIT'; $i++) { printf "%03d\n", '$QNUM' + $i; }') + for CNT in $CNTS; do + eval BURST_DOM="$BURST_DOM_BASE" + DOMS="$DOMS $BURST_DOM" + done + ARGS="+burst +nocookie +continue +time=1 +tries=1 -p ${PORT} $* @$ns2 $DOMS" + $MDIG $ARGS 2>&1 \ + | tee -a full-$FILENAME \ + | sed -n -e '/^;; AUTHORITY/,/^$/d' \ + -e '/^;; ADDITIONAL/,/^$/d' \ + -e 's/^[^;].* \([^ ]\{1,\}\)$/\1/p' \ + -e 's/;; flags.* tc .*/TC/p' \ + -e 's/;; .* status: NXDOMAIN.*/NXDOMAIN/p' \ + -e 's/;; .* status: NOERROR.*/NOERROR/p' \ + -e 's/;; .* status: SERVFAIL.*/SERVFAIL/p' \ + -e 's/response failed with timed out.*/drop/p' \ + -e 's/;; communications error to.*/drop/p' >>$FILENAME & + QNUM=$((QNUM + BURST_LIMIT)) +} + +# compare integers $1 and $2; ensure the difference is no more than $3 +range() { + $PERL -e 'if (abs(int($ARGV[0]) - int($ARGV[1])) > int($ARGV[2])) { exit(1) }' $1 $2 $3 +} + +# $1=domain $2=IP address $3=# of IP addresses $4=TC $5=drop +# $6=NXDOMAIN $7=SERVFAIL or other errors +ck_result() { + # wait to the background mdig calls to complete. + wait + BAD=no + ADDRS=$(grep -E "^$2$" mdig.out-$1 2>/dev/null | wc -l) + # count simple truncated and truncated NXDOMAIN as TC + TC=$(grep -E "^TC|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l) + DROP=$(grep -E "^drop$" mdig.out-$1 2>/dev/null | wc -l) + # count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN + NXDOMAIN=$(grep -E "^NXDOMAIN|NXDOMAINTC$" mdig.out-$1 2>/dev/null | wc -l) + SERVFAIL=$(grep -E "^SERVFAIL$" mdig.out-$1 2>/dev/null | wc -l) + NOERROR=$(grep -E "^NOERROR$" mdig.out-$1 2>/dev/null | wc -l) + + range $ADDRS "$3" 1 \ + || setret "$ADDRS instead of $3 '$2' responses for $1" \ + && BAD=yes + + range $TC "$4" 1 \ + || setret "$TC instead of $4 truncation responses for $1" \ + && BAD=yes + + range $DROP "$5" 1 \ + || setret "$DROP instead of $5 dropped responses for $1" \ + && BAD=yes + + range $NXDOMAIN "$6" 1 \ + || setret "$NXDOMAIN instead of $6 NXDOMAIN responses for $1" \ + && BAD=yes + + range $SERVFAIL "$7" 1 \ + || setret "$SERVFAIL instead of $7 error responses for $1" \ + && BAD=yes + + range $NOERROR "$8" 1 \ + || setret "$NOERROR instead of $8 NOERROR responses for $1" \ + && BAD=yes + + if test -z "$BAD"; then + rm -f mdig.out-$1 + fi +} + +ckstats() { + LABEL="$1" + shift + TYPE="$1" + shift + EXPECTED="$1" + shift + C=$(cat ns2/named.stats \ + | sed -n -e "s/[ ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" \ + | tail -1) + C=$((C)) + + range "$C" $EXPECTED 1 \ + || setret "wrong $LABEL $TYPE statistics of $C instead of $EXPECTED" +} + +######### +sec_start + +# Tests of referrals to "." must be done before the hints are loaded. +burst 5 a1.tld3 +norec +# basic rate limiting +burst 3 a1.tld2 +# delay allows an additional response. +sleep 1 +burst 10 a1.tld2 +# Request 30 different qnames to try a wildcard. +burst 30 'y.x$CNT.a2.tld2' + +# IP TC drop NXDOMAIN SERVFAIL NOERROR +# referrals to "." +ck_result a1.tld3 x 0 1 2 0 0 2 +# check 13 results including 1 second delay that allows an additional response +ck_result a1.tld2 192.0.2.1 3 4 6 0 0 8 + +# Check the wildcard answers. +# The zone origin name of the 30 requests is counted. +ck_result 'y.x*.a2.tld2' 192.0.2.2 2 10 18 0 0 12 + +######### +sec_start + +burst 10 'x.a3.tld3' +burst 10 'y$CNT.a3.tld3' +burst 10 'z$CNT.a4.tld2' + +# 10 identical recursive responses are limited +ck_result 'x.a3.tld3' 192.0.3.3 2 3 5 0 0 5 + +# 10 different recursive responses are not limited +ck_result 'y*.a3.tld3' 192.0.3.3 10 0 0 0 0 10 + +# 10 different NXDOMAIN responses are limited based on the parent name. +# We count 13 responses because we count truncated NXDOMAIN responses +# as both truncated and NXDOMAIN. +ck_result 'z*.a4.tld2' x 0 3 5 5 0 0 + +$RNDCCMD $ns2 stats +ckstats first dropped 36 +ckstats first truncated 21 + +######### +sec_start + +burst 10 a5.tld2 +tcp +burst 10 a6.tld2 -b $ns7 +burst 10 a7.tld4 +burst 2 a8.tld2 -t AAAA +burst 2 a8.tld2 -t TXT +burst 2 a8.tld2 -t SPF + +# IP TC drop NXDOMAIN SERVFAIL NOERROR +# TCP responses are not rate limited +ck_result a5.tld2 192.0.2.5 10 0 0 0 0 10 + +# whitelisted client is not rate limited +ck_result a6.tld2 192.0.2.6 10 0 0 0 0 10 + +# Errors such as SERVFAIL are rate limited. +ck_result a7.tld4 x 0 0 8 0 2 0 + +# NODATA responses are counted as the same regardless of qtype. +ck_result a8.tld2 x 0 2 2 0 0 4 + +$RNDCCMD $ns2 stats +ckstats second dropped 46 +ckstats second truncated 23 + +######### +sec_start + +# IP TC drop NXDOMAIN SERVFAIL NOERROR +# all-per-second +# The qnames are all unique but the client IP address is constant. +QNUM=101 +burst 60 'all$CNT.a9.tld2' + +ck_result 'a*.a9.tld2' 192.0.2.8 50 0 10 0 0 50 + +$RNDCCMD $ns2 stats +ckstats final dropped 56 +ckstats final truncated 23 + +######### +sec_start + +# check that "would limit" is emitted for "log-only yes;" +DIGOPTS="+nocookie +nosearch +time=1 +tries=1 +ignore -p ${PORT}" +$DIG $DIGOPTS @$ns4 A a7.tld4 >dig.out.a7.tld 2>/dev/null +# skip this check if query takes over 500ms +if grep -E ';; Query time: [1-4]?[0-9]?[0-9] msec' dig.out.a7.tld >/dev/null 2>&1; then + for i in 1 2 3 4 5; do + $DIG $DIGOPTS @$ns4 A a7.tld4 >/dev/null 2>&1 & + done + wait + grep "would limit" ns4/named.run >/dev/null 2>&1 || setret "\"would limit\" not found in log file." +fi + +# regression test for GL #2839 +DIGOPTS="+bufsize=4096 +ignore -p ${PORT}" +$DIG $DIGOPTS @$ns4 TXT big.tld4 >/dev/null 2>&1 + +echo_i "exit status: $ret" +[ $ret -eq 0 ] || exit 1 diff --git a/bin/tests/system/rrl/tests_sh_rrl.py b/bin/tests/system/rrl/tests_sh_rrl.py new file mode 100644 index 0000000..99be723 --- /dev/null +++ b/bin/tests/system/rrl/tests_sh_rrl.py @@ -0,0 +1,29 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +import isctest.mark + +pytestmark = pytest.mark.extra_artifacts( + [ + "*mdig.out*", + "dig.out.*", + "ns*/log-*", + "ns2/named.stats", + ] +) + + +# The rrl is known to be quite unstable. GL #172 +@isctest.mark.flaky(max_runs=2) +def test_rrl(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rrsetorder/ns1/named.conf.j2 b/bin/tests/system/rrsetorder/ns1/named.conf.j2 new file mode 100644 index 0000000..2f1850d --- /dev/null +++ b/bin/tests/system/rrsetorder/ns1/named.conf.j2 @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; + notify no; + rrset-order { + name "fixed.example" order fixed; + name "random.example" order random; + name "cyclic.example" order cyclic; + name "none.example" order none; + type NS order random; + order cyclic; + }; +}; + +zone "." { + type primary; + file "root.db"; + notify explicit; + also-notify { 10.53.0.2; }; +}; diff --git a/bin/tests/system/rrsetorder/ns1/root.db b/bin/tests/system/rrsetorder/ns1/root.db new file mode 100644 index 0000000..094eec7 --- /dev/null +++ b/bin/tests/system/rrsetorder/ns1/root.db @@ -0,0 +1,51 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 3600 +. SOA hostmaster.isc.org. a.root-servers.nil. ( + 2000042100 + 600 + 600 + 1200 + 600 ) +. NS a.root-servers.nil. +. NS cyclic.example. +a.root-servers.nil. A 10.53.0.1 +; +fixed.example. A 1.2.3.4 +fixed.example. A 1.2.3.3 +fixed.example. A 1.2.3.1 +fixed.example. A 1.2.3.2 +; +random.example. A 1.2.3.1 +random.example. A 1.2.3.2 +random.example. A 1.2.3.3 +random.example. A 1.2.3.4 +; +cyclic.example. A 1.2.3.4 +cyclic.example. A 1.2.3.3 +cyclic.example. A 1.2.3.2 +cyclic.example. A 1.2.3.1 +; +cyclic2.example. A 1.2.3.4 +cyclic2.example. A 1.2.3.3 +cyclic2.example. A 1.2.3.2 +cyclic2.example. A 1.2.3.1 +; +nomatch.example. A 1.2.3.1 +nomatch.example. A 1.2.3.2 +nomatch.example. A 1.2.3.3 +nomatch.example. A 1.2.3.4 +; +none.example. A 1.2.3.1 +none.example. A 1.2.3.2 +none.example. A 1.2.3.3 +none.example. A 1.2.3.4 diff --git a/bin/tests/system/rrsetorder/ns2/named.conf.j2 b/bin/tests/system/rrsetorder/ns2/named.conf.j2 new file mode 100644 index 0000000..164400a --- /dev/null +++ b/bin/tests/system/rrsetorder/ns2/named.conf.j2 @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; + rrset-order { + name "fixed.example" order fixed; + name "random.example" order random; + name "cyclic.example" order cyclic; + name "none.example" order none; + type NS order random; + order cyclic; + }; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/rrsetorder/ns3/named.conf.j2 b/bin/tests/system/rrsetorder/ns3/named.conf.j2 new file mode 100644 index 0000000..cdab83e --- /dev/null +++ b/bin/tests/system/rrsetorder/ns3/named.conf.j2 @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + rrset-order { + name "fixed.example" order fixed; + name "random.example" order random; + name "cyclic.example" order cyclic; + name "none.example" order none; + type NS order random; + order cyclic; + }; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/rrsetorder/ns4/named.conf.j2 b/bin/tests/system/rrsetorder/ns4/named.conf.j2 new file mode 100644 index 0000000..5187aa8 --- /dev/null +++ b/bin/tests/system/rrsetorder/ns4/named.conf.j2 @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; + rrset-order { + class IN type A name "host.example.com" order random; + }; + +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/rrsetorder/ns5/named.conf.j2 b/bin/tests/system/rrsetorder/ns5/named.conf.j2 new file mode 100644 index 0000000..f7a2486 --- /dev/null +++ b/bin/tests/system/rrsetorder/ns5/named.conf.j2 @@ -0,0 +1,32 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + notify yes; +}; + +trust-anchors { }; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; diff --git a/bin/tests/system/rrsetorder/reference.dig.out.fixed.good b/bin/tests/system/rrsetorder/reference.dig.out.fixed.good new file mode 100644 index 0000000..eaf9c63 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.fixed.good @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.3 +1.2.3.1 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good1 b/bin/tests/system/rrsetorder/reference.dig.out.random.good1 new file mode 100644 index 0000000..c272c75 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good1 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.2 +1.2.3.3 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good10 b/bin/tests/system/rrsetorder/reference.dig.out.random.good10 new file mode 100644 index 0000000..6a39e3f --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good10 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.3 +1.2.3.4 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good11 b/bin/tests/system/rrsetorder/reference.dig.out.random.good11 new file mode 100644 index 0000000..efbc792 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good11 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.4 +1.2.3.1 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good12 b/bin/tests/system/rrsetorder/reference.dig.out.random.good12 new file mode 100644 index 0000000..c859a2e --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good12 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.4 +1.2.3.3 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good13 b/bin/tests/system/rrsetorder/reference.dig.out.random.good13 new file mode 100644 index 0000000..49bf54b --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good13 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.1 +1.2.3.2 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good14 b/bin/tests/system/rrsetorder/reference.dig.out.random.good14 new file mode 100644 index 0000000..974aa89 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good14 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.1 +1.2.3.4 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good15 b/bin/tests/system/rrsetorder/reference.dig.out.random.good15 new file mode 100644 index 0000000..e8deb67 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good15 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.2 +1.2.3.1 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good16 b/bin/tests/system/rrsetorder/reference.dig.out.random.good16 new file mode 100644 index 0000000..f467087 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good16 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.2 +1.2.3.4 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good17 b/bin/tests/system/rrsetorder/reference.dig.out.random.good17 new file mode 100644 index 0000000..6082a25 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good17 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.4 +1.2.3.1 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good18 b/bin/tests/system/rrsetorder/reference.dig.out.random.good18 new file mode 100644 index 0000000..07eefa0 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good18 @@ -0,0 +1,4 @@ +1.2.3.3 +1.2.3.4 +1.2.3.2 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good19 b/bin/tests/system/rrsetorder/reference.dig.out.random.good19 new file mode 100644 index 0000000..a5530c6 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good19 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.1 +1.2.3.2 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good2 b/bin/tests/system/rrsetorder/reference.dig.out.random.good2 new file mode 100644 index 0000000..00da93a --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good2 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.2 +1.2.3.4 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good20 b/bin/tests/system/rrsetorder/reference.dig.out.random.good20 new file mode 100644 index 0000000..6dcf6da --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good20 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.1 +1.2.3.3 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good21 b/bin/tests/system/rrsetorder/reference.dig.out.random.good21 new file mode 100644 index 0000000..9dcc63f --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good21 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.2 +1.2.3.1 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good22 b/bin/tests/system/rrsetorder/reference.dig.out.random.good22 new file mode 100644 index 0000000..4c51aa6 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good22 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.2 +1.2.3.3 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good23 b/bin/tests/system/rrsetorder/reference.dig.out.random.good23 new file mode 100644 index 0000000..eaf9c63 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good23 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.3 +1.2.3.1 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good24 b/bin/tests/system/rrsetorder/reference.dig.out.random.good24 new file mode 100644 index 0000000..c25c756 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good24 @@ -0,0 +1,4 @@ +1.2.3.4 +1.2.3.3 +1.2.3.2 +1.2.3.1 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good3 b/bin/tests/system/rrsetorder/reference.dig.out.random.good3 new file mode 100644 index 0000000..4d50059 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good3 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.3 +1.2.3.2 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good4 b/bin/tests/system/rrsetorder/reference.dig.out.random.good4 new file mode 100644 index 0000000..0b34afa --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good4 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.3 +1.2.3.4 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good5 b/bin/tests/system/rrsetorder/reference.dig.out.random.good5 new file mode 100644 index 0000000..efe0e25 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good5 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.4 +1.2.3.2 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good6 b/bin/tests/system/rrsetorder/reference.dig.out.random.good6 new file mode 100644 index 0000000..d2ca6fc --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good6 @@ -0,0 +1,4 @@ +1.2.3.1 +1.2.3.4 +1.2.3.3 +1.2.3.2 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good7 b/bin/tests/system/rrsetorder/reference.dig.out.random.good7 new file mode 100644 index 0000000..0d8312a --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good7 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.1 +1.2.3.3 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good8 b/bin/tests/system/rrsetorder/reference.dig.out.random.good8 new file mode 100644 index 0000000..3b27693 --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good8 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.1 +1.2.3.4 +1.2.3.3 diff --git a/bin/tests/system/rrsetorder/reference.dig.out.random.good9 b/bin/tests/system/rrsetorder/reference.dig.out.random.good9 new file mode 100644 index 0000000..61192af --- /dev/null +++ b/bin/tests/system/rrsetorder/reference.dig.out.random.good9 @@ -0,0 +1,4 @@ +1.2.3.2 +1.2.3.3 +1.2.3.1 +1.2.3.4 diff --git a/bin/tests/system/rrsetorder/tests.sh b/bin/tests/system/rrsetorder/tests.sh new file mode 100644 index 0000000..844fefe --- /dev/null +++ b/bin/tests/system/rrsetorder/tests.sh @@ -0,0 +1,524 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +DIGOPTS="+nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short +nocookie" + +dig_cmd() { + # shellcheck disable=SC2086 + "$DIG" $DIGOPTS -p "${PORT}" "$@" | grep -v '^;' +} + +status=0 + +GOOD_RANDOM="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24" +GOOD_RANDOM_NO=24 + +if grep "^#define DNS_RDATASET_FIXED" "$TOP_BUILDDIR/config.h" >/dev/null 2>&1; then + test_fixed=true +else + echo_i "Order 'fixed' disabled at compile time" + test_fixed=false +fi + +# +# +# +if $test_fixed; then + echo_i "Checking order fixed (primary)" + ret=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + dig_cmd @10.53.0.1 fixed.example >dig.out.fixed || ret=1 + diff dig.out.fixed reference.dig.out.fixed.good >/dev/null || ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "Checking order fixed behaves as cyclic when disabled (primary)" + ret=0 + matches=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.1 fixed.example >dig.out.fixed || ret=1 + if [ $i -le 4 ]; then + cp dig.out.fixed dig.out.$j + else + diff dig.out.fixed dig.out.$j >/dev/null && matches=$((matches + 1)) + fi + done + diff dig.out.0 dig.out.1 >/dev/null && ret=1 + diff dig.out.0 dig.out.2 >/dev/null && ret=1 + diff dig.out.0 dig.out.3 >/dev/null && ret=1 + diff dig.out.1 dig.out.2 >/dev/null && ret=1 + diff dig.out.1 dig.out.3 >/dev/null && ret=1 + diff dig.out.2 dig.out.3 >/dev/null && ret=1 + if [ $matches -ne 16 ]; then ret=1; fi + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +# +# +# +echo_i "Checking order cyclic (primary + additional)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.1 cyclic.example >dig.out.cyclic || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic dig.out.$j + else + diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +echo_i "Checking order cyclic (primary)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.1 cyclic2.example >dig.out.cyclic2 || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic2 dig.out.$j + else + diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +echo_i "Checking order random (primary)" +ret=0 +for i in $GOOD_RANDOM; do + eval match$i=0 +done +for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9; do + dig_cmd @10.53.0.1 random.example >dig.out.random || ret=1 + match=0 + for j in $GOOD_RANDOM; do + eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true" + if [ $match -eq 1 ]; then break; fi + done + if [ $match -eq 0 ]; then ret=1; fi +done +match=0 +for i in $GOOD_RANDOM; do + eval "match=\$((match + match$i))" +done +echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples" +if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order none (primary)" +ret=0 +# Fetch the "reference" response and ensure it contains the expected records. +dig_cmd @10.53.0.1 none.example >dig.out.none || ret=1 +for i in 1 2 3 4; do + grep -F -q 1.2.3.$i dig.out.none || ret=1 +done +# Ensure 20 further queries result in the same response as the "reference" one. +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + dig_cmd @10.53.0.1 none.example >dig.out.test$i || ret=1 + diff dig.out.none dig.out.test$i >/dev/null || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +if $test_fixed; then + echo_i "Checking order fixed (secondary)" + ret=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + dig_cmd @10.53.0.2 fixed.example >dig.out.fixed || ret=1 + diff dig.out.fixed reference.dig.out.fixed.good || ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +# +# +# +echo_i "Checking order cyclic (secondary + additional)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.2 cyclic.example >dig.out.cyclic || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic dig.out.$j + else + diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +echo_i "Checking order cyclic (secondary)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.2 cyclic2.example >dig.out.cyclic2 || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic2 dig.out.$j + else + diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order random (secondary)" +ret=0 +for i in $GOOD_RANDOM; do + eval match$i=0 +done +for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9; do + dig_cmd @10.53.0.2 random.example >dig.out.random || ret=1 + match=0 + for j in $GOOD_RANDOM; do + eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true" + if [ $match -eq 1 ]; then break; fi + done + if [ $match -eq 0 ]; then ret=1; fi +done +match=0 +for i in $GOOD_RANDOM; do + eval "match=\$((match + match$i))" +done +echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples" +if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order none (secondary)" +ret=0 +# Fetch the "reference" response and ensure it contains the expected records. +dig_cmd @10.53.0.2 none.example >dig.out.none || ret=1 +for i in 1 2 3 4; do + grep -F -q 1.2.3.$i dig.out.none || ret=1 +done +# Ensure 20 further queries result in the same response as the "reference" one. +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + dig_cmd @10.53.0.2 none.example >dig.out.test$i || ret=1 + diff dig.out.none dig.out.test$i >/dev/null || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Shutting down secondary" + +stop_server ns2 + +echo_i "Checking for secondary's on disk copy of zone" + +if [ ! -f ns2/root.bk ]; then + echo_i "failed" + status=$((status + 1)) +fi + +echo_i "Re-starting secondary" + +start_server --noclean --restart --port ${PORT} ns2 + +# +# +# +if $test_fixed; then + echo_i "Checking order fixed (secondary loaded from disk)" + ret=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + dig_cmd @10.53.0.2 fixed.example >dig.out.fixed || ret=1 + diff dig.out.fixed reference.dig.out.fixed.good || ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +# +# +# +echo_i "Checking order cyclic (secondary + additional, loaded from disk)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.2 cyclic.example >dig.out.cyclic || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic dig.out.$j + else + diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +echo_i "Checking order cyclic (secondary loaded from disk)" +ret=0 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.2 cyclic2.example >dig.out.cyclic2 || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic2 dig.out.$j + else + diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order random (secondary loaded from disk)" +ret=0 +for i in $GOOD_RANDOM; do + eval match$i=0 +done +for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9; do + dig_cmd @10.53.0.2 random.example >dig.out.random || ret=1 + match=0 + for j in $GOOD_RANDOM; do + eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true" + if [ $match -eq 1 ]; then break; fi + done + if [ $match -eq 0 ]; then ret=1; fi +done +match=0 +for i in $GOOD_RANDOM; do + eval "match=\$((match + match$i))" +done +echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples" +if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order none (secondary loaded from disk)" +ret=0 +# Fetch the "reference" response and ensure it contains the expected records. +dig_cmd @10.53.0.2 none.example >dig.out.none || ret=1 +for i in 1 2 3 4; do + grep -F -q 1.2.3.$i dig.out.none || ret=1 +done +# Ensure 20 further queries result in the same response as the "reference" one. +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + dig_cmd @10.53.0.2 none.example >dig.out.test$i || ret=1 + diff dig.out.none dig.out.test$i >/dev/null || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +if $test_fixed; then + echo_i "Checking order fixed (cache)" + ret=0 + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do + dig_cmd @10.53.0.3 fixed.example >dig.out.fixed || ret=1 + diff dig.out.fixed reference.dig.out.fixed.good || ret=1 + done + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +fi + +# +# +# +echo_i "Checking order cyclic (cache + additional)" +ret=0 +# prime acache +dig_cmd @10.53.0.3 cyclic.example >dig.out.cyclic || ret=1 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.3 cyclic.example >dig.out.cyclic || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic dig.out.$j + else + diff dig.out.cyclic dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# +# +echo_i "Checking order cyclic (cache)" +ret=0 +# prime acache +dig_cmd @10.53.0.3 cyclic2.example >dig.out.cyclic2 || ret=1 +matches=0 +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + j=$((i % 4)) + dig_cmd @10.53.0.3 cyclic2.example >dig.out.cyclic2 || ret=1 + if [ $i -le 4 ]; then + cp dig.out.cyclic2 dig.out.$j + else + diff dig.out.cyclic2 dig.out.$j >/dev/null && matches=$((matches + 1)) + fi +done +diff dig.out.0 dig.out.1 >/dev/null && ret=1 +diff dig.out.0 dig.out.2 >/dev/null && ret=1 +diff dig.out.0 dig.out.3 >/dev/null && ret=1 +diff dig.out.1 dig.out.2 >/dev/null && ret=1 +diff dig.out.1 dig.out.3 >/dev/null && ret=1 +diff dig.out.2 dig.out.3 >/dev/null && ret=1 +if [ $matches -ne 16 ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order random (cache)" +ret=0 +for i in $GOOD_RANDOM; do + eval match$i=0 +done +for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9; do + dig_cmd @10.53.0.3 random.example >dig.out.random || ret=1 + match=0 + for j in $GOOD_RANDOM; do + eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true" + if [ $match -eq 1 ]; then break; fi + done + if [ $match -eq 0 ]; then ret=1; fi +done +match=0 +for i in $GOOD_RANDOM; do + eval "match=\$((match + match$i))" +done +echo_i "Random selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples" +if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking order none (cache)" +ret=0 +# Fetch the "reference" response and ensure it contains the expected records. +dig_cmd @10.53.0.3 none.example >dig.out.none || ret=1 +for i in 1 2 3 4; do + grep -F -q 1.2.3.$i dig.out.none || ret=1 +done +# Ensure 20 further queries result in the same response as the "reference" one. +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + dig_cmd @10.53.0.3 none.example >dig.out.test$i || ret=1 + diff dig.out.none dig.out.test$i >/dev/null || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking default order (cache)" +ret=0 +for i in $GOOD_RANDOM; do + eval match$i=0 +done +for i in a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 9; do + dig_cmd @10.53.0.5 random.example >dig.out.random || ret=1 + match=0 + for j in $GOOD_RANDOM; do + eval "diff dig.out.random reference.dig.out.random.good$j >/dev/null && match$j=1 match=1 || true" + if [ $match -eq 1 ]; then break; fi + done + if [ $match -eq 0 ]; then ret=1; fi +done +match=0 +for i in $GOOD_RANDOM; do + eval "match=\$((match + match$i))" +done +echo_i "Default selection return $match of ${GOOD_RANDOM_NO} possible orders in 36 samples" +if [ $match -lt $((GOOD_RANDOM_NO / 3)) ]; then ret=1; fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "Checking default order no match in rrset-order (cache)" +ret=0 +# Fetch the "reference" response and ensure it contains the expected records. +dig_cmd @10.53.0.4 nomatch.example >dig.out.nomatch || ret=1 +for i in 1 2 3 4; do + grep -F -q 1.2.3.$i dig.out.nomatch || ret=1 +done +# Ensure 20 further queries result in the same response as the "reference" one. +for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do + dig_cmd @10.53.0.4 nomatch.example >dig.out.test$i || ret=1 + diff dig.out.nomatch dig.out.test$i >/dev/null || ret=1 +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py b/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py new file mode 100644 index 0000000..f23dd09 --- /dev/null +++ b/bin/tests/system/rrsetorder/tests_sh_rrsetorder.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "ns2/root.bk", + ] +) + + +def test_rrsetorder(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/rsabigexponent/README.md b/bin/tests/system/rsabigexponent/README.md new file mode 100644 index 0000000..44afdbd --- /dev/null +++ b/bin/tests/system/rsabigexponent/README.md @@ -0,0 +1,39 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The `rsabigexponent` test is used to `check max-rsa-exponent-size`. + +We only run this test on builds without PKCS#11, as we have control over +the RSA exponent size with plain OpenSSL. We have not explored how to do +this with PKCS#11, which would require generating such a key and then +signing a zone with it. Additionally, even with control of the exponent +size with PKCS#11, generating a DNSKEY with this property and signing +such a zone would be slow and undesirable for each test run; instead, we +use a pregenerated DNSKEY and a saved signed zone. These are located in +`rsabigexponent/ns2` and currently use RSASHA1 for the `DNSKEY` +algorithm; however, that may need to be changed in the future. + +To generate the `DNSKEY` used in this test, we used `bigkey.c`, as +dnssec-keygen is not capable of generating such keys. + +Do **not** remove `bigkey.c` as it may be needed to generate a new +`DNSKEY` for testing purposes. + +`bigkey` is used to both test that we are not running under PKCS#11 and +generate a `DNSKEY` key with a large RSA exponent. + +To regenerate `ns2/example.db.bad` comment out the range test in +opensslrsa_parse before signing the zone with a ZSK key generated +by `bigkey`. + + if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) { + DST_RET(ISC_R_RANGE); + } diff --git a/bin/tests/system/rsabigexponent/bigkey.c b/bin/tests/system/rsabigexponent/bigkey.c new file mode 100644 index 0000000..0961849 --- /dev/null +++ b/bin/tests/system/rsabigexponent/bigkey.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DST_KEY_INTERNAL + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +dst_key_t *key; +dns_fixedname_t fname; +dns_name_t *name; +unsigned int bits = 2048U; +isc_mem_t *mctx; +isc_log_t *log_; +isc_logconfig_t *logconfig; +int level = ISC_LOG_WARNING; +isc_logdestination_t destination; +char filename[255]; +isc_result_t result; +isc_buffer_t buf; +RSA *rsa; +BIGNUM *e; +EVP_PKEY *pkey; + +#define CHECK(op, msg) \ + do { \ + result = (op); \ + if (result != ISC_R_SUCCESS) { \ + fprintf(stderr, \ + "fatal error: %s returns %s at file %s line " \ + "%d\n", \ + msg, isc_result_totext(result), __FILE__, \ + __LINE__); \ + ERR_clear_error(); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) + +int +main(int argc, char **argv) { + UNUSED(argc); + UNUSED(argv); + + rsa = RSA_new(); + e = BN_new(); + pkey = EVP_PKEY_new(); + + if ((rsa == NULL) || (e == NULL) || (pkey == NULL) || + !EVP_PKEY_set1_RSA(pkey, rsa)) + { + fprintf(stderr, "fatal error: basic OpenSSL failure\n"); + ERR_clear_error(); + exit(EXIT_FAILURE); + } + + /* e = 0x1000000000001 */ + BN_set_bit(e, 0); + BN_set_bit(e, 48); + + if (RSA_generate_key_ex(rsa, bits, e, NULL)) { + BN_free(e); + RSA_free(rsa); + } else { + fprintf(stderr, + "fatal error: RSA_generate_key_ex() fails " + "at file %s line %d\n", + __FILE__, __LINE__); + ERR_clear_error(); + exit(EXIT_FAILURE); + } + + isc_mem_create(&mctx); + CHECK(dst_lib_init(mctx, NULL), "dst_lib_init()"); + isc_log_create(mctx, &log_, &logconfig); + isc_log_setcontext(log_); + dns_log_init(log_); + dns_log_setcontext(log_); + isc_log_settag(logconfig, "bigkey"); + + destination.file.stream = stderr; + destination.file.name = NULL; + destination.file.versions = ISC_LOG_ROLLNEVER; + destination.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, level, + &destination, + ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL); + + CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL), "isc_log_" + "usechannel(" + ")"); + name = dns_fixedname_initname(&fname); + isc_buffer_constinit(&buf, "example.", strlen("example.")); + isc_buffer_add(&buf, strlen("example.")); + CHECK(dns_name_fromtext(name, &buf, dns_rootname, 0, NULL), "dns_name_" + "fromtext(" + "\"example." + "\")"); + + CHECK(dst_key_buildinternal(name, DNS_KEYALG_RSASHA256, bits, + DNS_KEYOWNER_ZONE, DNS_KEYPROTO_DNSSEC, + dns_rdataclass_in, pkey, mctx, &key), + "dst_key_buildinternal(...)"); + + CHECK(dst_key_tofile(key, DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, NULL), + "dst_key_tofile()"); + isc_buffer_init(&buf, filename, sizeof(filename) - 1); + isc_buffer_clear(&buf); + CHECK(dst_key_buildfilename(key, 0, NULL, &buf), "dst_key_" + "buildfilename()"); + printf("%s\n", filename); + dst_key_free(&key); + + isc_log_destroy(&log_); + isc_log_setcontext(NULL); + dns_log_setcontext(NULL); + dst_lib_destroy(); + isc_mem_destroy(&mctx); + return 0; +} + +/*! \file */ diff --git a/bin/tests/system/rsabigexponent/ns1/named.conf.in b/bin/tests/system/rsabigexponent/ns1/named.conf.in new file mode 100644 index 0000000..4a9822d --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns1/named.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rsabigexponent/ns1/root.db.in b/bin/tests/system/rsabigexponent/ns1/root.db.in new file mode 100644 index 0000000..a85d814 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns1/root.db.in @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2012050600 ; serial + 3600 ; refresh + 1200 ; retry + 604800 ; expire + 60 ; minimum + ) +@ NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 +; +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/rsabigexponent/ns1/sign.sh b/bin/tests/system/rsabigexponent/ns1/sign.sh new file mode 100755 index 0000000..a4242a3 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns1/sign.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=. +infile=root.db.in +zonefile=root.db + +cp ../ns2/dsset-example.in dsset-example. + +keyname=$($KEYGEN -q -a RSASHA256 -b 2048 -n zone $zone) + +cat $infile $keyname.key >$zonefile + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +# Configure the resolving server with a static key. +keyfile_to_static_ds $keyname >trusted.conf +cp trusted.conf ../ns2/trusted.conf +cp trusted.conf ../ns3/trusted.conf + +cd ../ns2 && $SHELL -e ./sign.sh diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key new file mode 100644 index 0000000..60ff187 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 51650, for example. +; Created: 20220721024334 (Thu Jul 21 12:43:34 2022) +; Publish: 20220721024334 (Thu Jul 21 12:43:34 2022) +; Activate: 20220721024334 (Thu Jul 21 12:43:34 2022) +example. IN DNSKEY 257 3 8 AwEAAeeXAGBcXxSNj5X/PWT8XDBk4U9OUkZ7YKQBf2IN3V6OZomt/s3F UWIh70Wot+z1Ld3Rfswq1DjCaWNRFOMhs+9j3Fhc46wMZ4pnsDW1nLHk 2TnQRdrbiuhLkQy5oNMjSRxu924XLw5ylsuqjxE7vXcCeKSFe674roSq wo39atWsTJMDz0FQGxlPucnXai0nHoCeC7+u1s+wLaGcpNSZlsab7Zny FD4HZ3HKUCJw/Jjr5CZjqal9KdmWSC1SINRtlAN6PX5VSiNEncnYMCdj iv+ZhRGn+aHh1BmEWomGbAm2Jjw5mrYMgDs9lJRc5Vtg0YXb9OkYvxNF V4QGw1oeF+M= diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private new file mode 100644 index 0000000..d38a0b3 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+51650.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 55cAYFxfFI2Plf89ZPxcMGThT05SRntgpAF/Yg3dXo5mia3+zcVRYiHvRai37PUt3dF+zCrUOMJpY1EU4yGz72PcWFzjrAxnimewNbWcseTZOdBF2tuK6EuRDLmg0yNJHG73bhcvDnKWy6qPETu9dwJ4pIV7rviuhKrCjf1q1axMkwPPQVAbGU+5yddqLScegJ4Lv67Wz7AtoZyk1JmWxpvtmfIUPgdnccpQInD8mOvkJmOpqX0p2ZZILVIg1G2UA3o9flVKI0SdydgwJ2OK/5mFEaf5oeHUGYRaiYZsCbYmPDmatgyAOz2UlFzlW2DRhdv06Ri/E0VXhAbDWh4X4w== +PublicExponent: AQAB +PrivateExponent: QaMgBa+YeRxIElS1g14tCMBGxXHmyrgkI0eTYWiZkbedYy8v1QU0NDJ2/NC9VEkHF2PNYrNO08lyEiaEW32NYG92n4qwMm6PmAAcRpSzFQ5N7N9VNRrdK0pjkW45IS5Shd8DfK3QdfFPQOkVxGYgpE7Mf6Cfde9gkxRMsO6erXEud6KyBm8kwBR/ipDeUQvpyGkZEQPjLxJG6REjMVhPKTzCV+82DWEf+Ok/3Uxa94+ocAbySHAV3j4YcWpVGWT002gc6CGk8c6TsPYnDkfKQ3moPQZijH7F8zrARtoobCX9TsMFhBqReceZrbzN7en2cZGR5MSISzoTNSr4rGo6aQ== +Prime1: 8AV9EllWtclD62XHo95Z3h7JJ9t2gY7fUFG0WMbkI0Wj6kcr7k3bFfLj7GEJ1qgVW4Qpu7XnBvPB9hnqoCkbHLzc8ws1D2tY+PsXzvw9IxoXNM/eCobeulu/rYhJl2PcpY9bPcaaR0hldGoCHdFYSo8oi+C5hfRtIMVjnDtHSmk= +Prime2: 9wHRxgyHjtl8ro9HAkvujxFkhChm4xLxIRM8pfZ+D1VHpzFRD3/RK8CVYVRB8GsQoFRygHBMOW1oHqynN9jddvJrQbHOqFZAbQQlesp0jRPd9Mm6q0cDwYcD4apscB2CUrUswMzoD3H4saIjGnitCsG/t+sLTvuK/giuMdS2Tms= +Exponent1: pnSH+pOuiL+dtMCPJVvsoxhilJukodD9mewv0GmOic+gD7dwBgJEcAJUgvgBJLbIqQENGDrcj3u5Bf2PM6eOP+3SpVMeZyUhPPqV1lwj4hYUBfIqoM5L5J4AXk5oCu+cc8zpj/wNvmW8xnFGKnumaX7Ctc8Rmo6ap+F8ZTrPBBE= +Exponent2: txXZKIRnAkJAwZ6f0pr3w4Hv0GmmAZArvQlmPdncDH94sfvDCssB/v0rfE4Y5hxl4YFWsc8LINHwiDQPajzLwvvi9nnWJT5xWJznLwHbrCparbPNMmFb7lmmTeGlqOCmlamG942qQLCI1xnIDTn/gWalNaz539xhZPSIMZVqX+s= +Coefficient: eK9cQKFRLaU4udqB8t8KSQxlNl0x9J+9bcaEzn0+579LrZUZvspfiR4DNGwr9qK+PWk+CU7/6xsWbq2zbKIEWucoR97t+E8Zhx00GCDbiu/QI2wviEcYbB2udznRv1WSIDoCWf2TXeh5G2E2ugt5F4+b56qMXmT7IudxYGPtQCY= +Created: 20220721024334 +Publish: 20220721024334 +Activate: 20220721024334 diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key new file mode 100644 index 0000000..a1f14c9 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.key @@ -0,0 +1,2 @@ +; This is a zone-signing key, keyid 52810, for example. +example. IN DNSKEY 256 3 8 BwEAAAAAAAHYYy161+wCg6yFHRlyex8oVkcK+K2SBUryI1+DEKzjusH6 yLfzzlJCPGrubmD+jseKYwXfzelJkRQbMDjWbMYLHKytuPtwnJMSeVh+ a/Ore6oVPXy716EYpsEBSmVjfQyS0mGHpwrYk4QaKjJDM7Q173EFl/sE eXjHqInlzOgJbXqsCrSfA94anSt42DGhJeeIfQ8b3vqD/nCnA6C7khIt AWlfJto7d42Ev8tckjr3CrTW9tn9pHb2DKeh85rKeJBBLMYQU3jfF5KH EEsjztLGMnPLlXTteh8wKrk/0IJrot17w0FR0H2v8oG3xDXxfhJ0OeTW 7dtBHD6ISgqeJ9zt diff --git a/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private new file mode 100644 index 0000000..bbb5ad9 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/Xexample.+008+52810.private @@ -0,0 +1,10 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 2GMtetfsAoOshR0ZcnsfKFZHCvitkgVK8iNfgxCs47rB+si3885SQjxq7m5g/o7HimMF383pSZEUGzA41mzGCxysrbj7cJyTEnlYfmvzq3uqFT18u9ehGKbBAUplY30MktJhh6cK2JOEGioyQzO0Ne9xBZf7BHl4x6iJ5czoCW16rAq0nwPeGp0reNgxoSXniH0PG976g/5wpwOgu5ISLQFpXybaO3eNhL/LXJI69wq01vbZ/aR29gynofOayniQQSzGEFN43xeShxBLI87SxjJzy5V07XofMCq5P9CCa6Lde8NBUdB9r/KBt8Q18X4SdDnk1u3bQRw+iEoKnifc7Q== +PublicExponent: AQAAAAAAAQ== +PrivateExponent: aD+JLNdCtAk1++UwcGdPslSoWq2szZHGrY+I+YfhfcBZrPP13exC40hgUgRNuYJOaJ3WMpgsKI4p8YDVNttF6LI7WNBURQhmBSwquB5BWWkoh7uR4PfKWGB0ZkDwUQcA2IdMVS4+QAKVQMmUXGnXhQI1p8duAORZp0gE71VsHTEzwf5AIEG2+f/oCjDsMJN0J7X3qktJr5ho64aMHyHf5+yKk6fFcy7wfC175SkIZ53uBfpCsFXkgq8YukXfcyoG5o4FUHheGnDwkVOzviEUHk8xweJnNNRbV6n/ck9AXzq3VSA9BbrXtRzZmre/L6tJvEnbH0EycwDkxCMlOSqGbQ== +Prime1: /hnW5M2vzAoAjx2wum98YZZ6gv1IpV88c4HDLA3vY79Qxd8FYanldxPNjgQJEPjHD5hG6tGN+cjZdXv/X+sk5j3fmCB7RKwMKcoD8A/jyH2JaQLTbXm6EBd1BCMIN+w3W+A2E6evYYyINLwMUwqRlUcAaD8HoDLK8iz6iAUhFss= +Prime2: 2gEuuug1PDnbWWFVzzMUrVXiRiFqJVTTvR3AjJVJNZPwAL4FMenh98rtI3s1zSB6P4RSyvRJ6YMOAT0ZrMxviJy76EExGgCB5F4w7g67I7VGPuA1tLn5kt5j9j5wQmdq1yMG5QpCJWr7bxjSDYvIzy2sZjZ/KTuHGtUzFUnHrCc= +Exponent1: MaDlpmDYxZ2QvM+cp58Bj160u+21qIA/UZ2ysh6102uQmYHm92481z2+AvCJuq2PpkuROMd/4i2w7L0RbfZ2MYzUFndLZ8NgmNDjNDfUzeRQl2KQdAOLK4DNXmf3mKwLO0Sbj/pxgj0vYAe9gcU4Pe8ukVuSX0nkehbDi4cjfr0= +Exponent2: cNHFlVCwvEPNVnpQCZS3iqF/D3HN8FtP2st0CrYbjQI8DYpcQUWVMqUqdqFOkYM0/qadpkX+JMlPJTjJZ8YDYYWIZGSC2ruMPIxB7DayVDBbgugmsC1isZjyApdQ44xtdNVyMYmcYeHUz5gR1x/eWdGNyjzMEvfbEjXIKbRykAM= +Coefficient: ovH/7MP64Dai8draXD3t+jl6UTchig+LDwXA2GvlZY0HVP+9yvE49VSKhoYxolL/ZmabIgzzOAyJ66SyYq31ozxbpKrBGiFdzAbgkJgFIbdYMgfLHXNkH1vissGeY0KdS5ee6sKDfk1VmE94UOVHi11oslvnTiG2RF/I3koYV7Q= diff --git a/bin/tests/system/rsabigexponent/ns2/dsset-example.in b/bin/tests/system/rsabigexponent/ns2/dsset-example.in new file mode 100644 index 0000000..9ad254b --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/dsset-example.in @@ -0,0 +1 @@ +example. IN DS 51650 8 2 F225122667540159A30620B2D0888036BDF76276D245DE3453C883F0C3276705 diff --git a/bin/tests/system/rsabigexponent/ns2/example.db.bad b/bin/tests/system/rsabigexponent/ns2/example.db.bad new file mode 100644 index 0000000..b105978 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/example.db.bad @@ -0,0 +1,156 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +example. 300 IN SOA mname1. . ( + 2012050601 ; serial + 3600 ; refresh (1 hour) + 600 ; retry (10 minutes) + 604800 ; expire (1 week) + 3600 ; minimum (1 hour) + ) + 300 RRSIG SOA 8 1 300 ( + 20361231235959 20000101000000 52810 example. + IfZrUTjdr4Ull5MSQW4eHxrub6X5O8VWB3vG + kg6TBT8f2Aw4hLcwT0X47xRqL9nU1kKA3qpu + mi71wqiZPbYI+suHYGuqRO/V6YujdQRpLhGS + gTpLmETa46unkMDY6sze41AlCyzR79yaDxVS + +pS2V1AVYzQzzeswJXHwSLO5HKtClPL3izpV + AJD1+dL0UZRs9yOqbxU1RgvASPFEt+1Wd2p6 + qwyeadJ7PB0PL7QQXSDsQ09Ms1BGoKq5p6Os + HtgXPo+aZQR2gczm3Yals9I1tZnk/ZM86aS0 + 63NrEEUQycMNCr100WgWzYQzO90SmJMqpdeZ + fxzlRQbY7jN4qRbM7A== ) + 300 NS ns2.example. + 300 RRSIG NS 8 1 300 ( + 20361231235959 20000101000000 52810 example. + VUPhDucH6rlx93V13b7OSAQ6fE/9jlxhCTXv + peBD69WOa4jZHMZf60gqy10gLVMx35gZdEaU + cJqaBcAniSwPY3a7mxclMja7fmuCB9wcSbiP + pwk5KIYSgIvoWp3ro2I19C0IDQDVWtH1xqdQ + Dv+3MV39Zpf0AnXB05mBopI2DQI9mYHCnmis + F3pfcfs+h/ipyodE5kccBBRvtfKWHly342Xe + azHKM4eyuGj9NLwuwsoVgnyQ3I9hrKVAiUjS + fQ4cxyBVhh+Wb1/VrVSbX+X9VNzQ04mcREHS + yXIPoIQBNju3dyOSTQ+VIeasRvRU8nqMS/1f + oeqj5ehTjtfejF6Jfw== ) + 300 NSEC a.example. NS SOA RRSIG NSEC DNSKEY + 300 RRSIG NSEC 8 1 300 ( + 20361231235959 20000101000000 52810 example. + bG90DOCaN7BhihvtCUs2eJhSHkRaV582ROQi + AbamawevX8NQGJeVpHb3t5ekQuK5EWjLFr6i + bga5TpeP8HOv3lDb8w7kb7xOrHycw5Sizws5 + PZTvtuty9nT6dZ9h4pfLNTbW+SBV904xv3JT + ZlXoxtm4JAdmKUcGiCFLjMvwbQ5SKEZq27uN + 9xCeY0CPkQmiGbTrySYFyNZsBBsL2OI5ec2V + TbQVSDhnnEhbVdMb8Yh2sTt9H/CT1yG2s4U9 + a9ccxguFzt6mk+f5ZL+WKgxkTOMOrZW3dyiI + x53dNQyZN/tczibox/LLG/SaET5wR/V5gDsh + 9DObfc9u1+of/H0lhg== ) + 300 DNSKEY 257 3 8 ( + AwEAAeeXAGBcXxSNj5X/PWT8XDBk4U9OUkZ7 + YKQBf2IN3V6OZomt/s3FUWIh70Wot+z1Ld3R + fswq1DjCaWNRFOMhs+9j3Fhc46wMZ4pnsDW1 + nLHk2TnQRdrbiuhLkQy5oNMjSRxu924XLw5y + lsuqjxE7vXcCeKSFe674roSqwo39atWsTJMD + z0FQGxlPucnXai0nHoCeC7+u1s+wLaGcpNSZ + lsab7ZnyFD4HZ3HKUCJw/Jjr5CZjqal9KdmW + SC1SINRtlAN6PX5VSiNEncnYMCdjiv+ZhRGn + +aHh1BmEWomGbAm2Jjw5mrYMgDs9lJRc5Vtg + 0YXb9OkYvxNFV4QGw1oeF+M= + ) ; KSK; alg = RSASHA256 ; key id = 51650 + 300 DNSKEY 256 3 8 ( + BwEAAAAAAAHYYy161+wCg6yFHRlyex8oVkcK + +K2SBUryI1+DEKzjusH6yLfzzlJCPGrubmD+ + jseKYwXfzelJkRQbMDjWbMYLHKytuPtwnJMS + eVh+a/Ore6oVPXy716EYpsEBSmVjfQyS0mGH + pwrYk4QaKjJDM7Q173EFl/sEeXjHqInlzOgJ + bXqsCrSfA94anSt42DGhJeeIfQ8b3vqD/nCn + A6C7khItAWlfJto7d42Ev8tckjr3CrTW9tn9 + pHb2DKeh85rKeJBBLMYQU3jfF5KHEEsjztLG + MnPLlXTteh8wKrk/0IJrot17w0FR0H2v8oG3 + xDXxfhJ0OeTW7dtBHD6ISgqeJ9zt + ) ; ZSK; alg = RSASHA256 ; key id = 52810 + 300 RRSIG DNSKEY 8 1 300 ( + 20361231235959 20000101000000 52810 example. + O4q1oueEgPoWHhrLiobGvMQLS2KHN+xxSddf + y6fqksqivRLgj0633fnEZrFtc44YueV+L4gQ + kaoWCCpR0yQH4BOw4p3FVjEgl+jXLzIc7amw + ZfKAnSOtMoTaBCQ2hN8b2ducUHgKV7ta9bca + lO0wuqqp2OOO/n9S3YMBVfrCW4jL2w1QPC+b + lm/4ka8OwqKKGAcO0d/nGeOPJZnfbddSzqEQ + C3j1tGavwBC4RAGilxw3XoyoICDp0LQR7M9a + tWAxYmMfilEEfpip9R3HhCa+ynIVsHP8yTXE + dlWM3LUZePm44aV38YeObJpRMkb8sO5VrbZn + 8hJoIs3eyguC4HKKTg== ) + 300 RRSIG DNSKEY 8 1 300 ( + 20361231235959 20000101000000 51650 example. + Eaw79mOoImGg+ymMJ+9paoanUgR/Od0Pxv/X + mevid1TRbssSc2KynAToxSXRcOQwRQjto9sC + qj0pOekPPmW1I6DRlMOGDS6l0Uuk51GvUuRD + Xbr19BG73mcPuKfYHNbx6cUHvBlPilnjM803 + m9E8DK6Ba9uo/MNhgtWoWj8wQxqP2YS+HW3v + bOv/p4en9Dc5ft6ATtSYj84ejuPAKnfVbleI + fJW+qIQ7q9A24xEZ4QlWuRovjsoASVsuLnX+ + X4sQYlWBIPMQYQ8RIN1CgSRPGb603pAq9ru6 + ySpjlxHQRtdOGBNJleg9Wz612rHRd3x7BM+8 + /Lvz31Ot/JSh3u4DSQ== ) +a.example. 300 IN A 10.0.0.1 + 300 RRSIG A 8 2 300 ( + 20361231235959 20000101000000 52810 example. + zp4L0Um0guehtT+4GQaMeYx5PiwEbSRyi7sg + Xv2uFn/wFML/Df0PgCxCYkWKL2Db/j15IZON + uz2CNRG7lDMZsb+JgyLZ6R3OuSKjwzA++kUu + 8ExPpdrFHxZFMPefkU1vjf7E1yt4/aSaO23T + m0F6yFHcVfBE1DElG1vLWO6cWtSIMKjXOo15 + Zy2hHhT/7jKhqcHnwwCBHLuV9/e9OmI34H7I + Sd3Ik8dnNEjRTVbLem3tQMfQ9ZfYDHPHli+z + Z5dGgPmpyNPq5bfs7O5uCO5cNCbouFdEnc6O + DA9QiyOGba8w7vI1gHMvA+rWPpA+fTGgrVRq + 7bTfa0jTOsybR8rZjg== ) + 300 NSEC ns2.example. A RRSIG NSEC + 300 RRSIG NSEC 8 2 300 ( + 20361231235959 20000101000000 52810 example. + oh6oqdC9OIoO0jIN0x9MIBlYlzAg2LFYffrP + QlgPAtPn8A9cPCxU2i6hJ1ubqc6o1LVD7LH6 + GVj842Ytys1uO2Nwf9xXS4gbchJ6NE9IjQh6 + IoBNmlgdfprzJEJlEFx73dytakfcjc+hIj8t + b14Lu2/5BBDSamw+uVyeV8Wg2jNdrN7UEqyA + ccnhLPWHAOtspzxrmCrBDPc6Geelu8KzARs5 + qOZ/p9CKffmKL/65K/N8WWKQWVNI22tAbiWT + J1t3BNkOLUSKMvEVLFcgStV4QtFcQrSB96Hu + D2rSbAGsH5Ujmz4GTxhOSqd8OJ7XDEWlhZod + LhUBltfjmakorhGqqg== ) +ns2.example. 300 IN A 10.53.0.2 + 300 RRSIG A 8 2 300 ( + 20361231235959 20000101000000 52810 example. + sDlETJwDoWqYZdcwYBW/l+Ot4Tb3mSXJvW3R + 1fsoiq/obWZeC+bU2MszckcZKPET2CRqBD+c + uLCcOhZrcH0m25Y02SAzOOG2V12KNvWVznSz + bZw+/+ucYhxhiNKherdwpHOAdjlhG//zFHDy + sAxmrtjWO2DT9pv1Hd/Hm3aGgAYTs0ryyeyo + k05sTgdr43APFkX4SNoNXGUEt8E0uMghIvhi + mgKSQ45fZFsZeUiEfwvtQ8uAuDNOLWK49Bw5 + 184QrQ/NZ3YVyJercg7wm/jFMVkgxggiOl2q + ZCLadaSQNnsvtbwgyTktRJb5YovzZEQrH7O0 + vW/DAN1Cqa1nXw/kZA== ) + 300 NSEC example. A RRSIG NSEC + 300 RRSIG NSEC 8 2 300 ( + 20361231235959 20000101000000 52810 example. + DyLuymW3Bv6irCLzfUGnz2cy1XctqfW7ycLc + 7wgDzDLNvJ6tqr8tjHKMdCODJDiG+lR5oFo7 + 8RA604OYcmJjLIAMj3fCxzBkIlH5SXRcJ86X + a8U6oXrgt6IvUMC2crdWMVgVnSWlqBS4TNNg + QhUa+vt+Em8ce3fveqh1tXm1hzysSroOQtMk + HOPAtwYR9XP4mTdbC43AU/67jsYPqXq59lm4 + sE1tmnVdhXuOk7yNAt8O2CSZGGZl5bYMC4On + IgWZP7liebXAmhmXpHbBf5/BaE9dVfvWzYTT + 4wUch+f8TDwwyTqumrlrPsVnvkQ9V0LwODox + PxWWxFAznmUMEtlo3g== ) diff --git a/bin/tests/system/rsabigexponent/ns2/example.db.in b/bin/tests/system/rsabigexponent/ns2/example.db.in new file mode 100644 index 0000000..a2a6964 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/example.db.in @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2012050601 ; serial + 3600 ; refresh + 600 ; retry + 604800 ; expire + 3600 ; minimum + ) + NS ns2 +ns2 A 10.53.0.2 + +a A 10.0.0.1 diff --git a/bin/tests/system/rsabigexponent/ns2/named.conf.in b/bin/tests/system/rsabigexponent/ns2/named.conf.in new file mode 100644 index 0000000..267daa6 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/named.conf.in @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db.bad"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rsabigexponent/ns2/sign.sh b/bin/tests/system/rsabigexponent/ns2/sign.sh new file mode 100755 index 0000000..9ecf6c3 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns2/sign.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../../conf.sh + +zone=example. +infile=example.db.in +outfile=example.db.bad + +for i in Xexample.+008+51650.key Xexample.+008+51650.private \ + Xexample.+008+52810.key Xexample.+008+52810.private; do + cp $i $(echo $i | sed s/X/K/) +done + +$SIGNER -g -s 20000101000000 -e 20361231235959 -o $zone \ + $infile Kexample.+008+52810.key \ + >/dev/null 2>signer.err || true diff --git a/bin/tests/system/rsabigexponent/ns3/named.conf.in b/bin/tests/system/rsabigexponent/ns3/named.conf.in new file mode 100644 index 0000000..6504886 --- /dev/null +++ b/bin/tests/system/rsabigexponent/ns3/named.conf.in @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + notify yes; + dnssec-validation yes; + max-rsa-exponent-size 35; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/rsabigexponent/options.conf.j2.manual b/bin/tests/system/rsabigexponent/options.conf.j2.manual new file mode 100644 index 0000000..3113d02 --- /dev/null +++ b/bin/tests/system/rsabigexponent/options.conf.j2.manual @@ -0,0 +1,16 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + max-rsa-exponent-size @max_rsa_exponent_size@; +}; diff --git a/bin/tests/system/rsabigexponent/setup.sh b/bin/tests/system/rsabigexponent/setup.sh new file mode 100644 index 0000000..b7c2801 --- /dev/null +++ b/bin/tests/system/rsabigexponent/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns3/named.conf.in ns3/named.conf + +cd ns1 && $SHELL -e sign.sh diff --git a/bin/tests/system/rsabigexponent/tests_rsabigexponent.py b/bin/tests/system/rsabigexponent/tests_rsabigexponent.py new file mode 100644 index 0000000..571fe2f --- /dev/null +++ b/bin/tests/system/rsabigexponent/tests_rsabigexponent.py @@ -0,0 +1,62 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import os +import subprocess + +import dns.message +import pytest + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "options.conf", + "ns*/dsset-*", + "ns*/K*", + "ns*/trusted.conf", + "ns*/*.signed", + "ns1/root.db", + "ns2/signer.err", + ] +) + +CHECKCONF = os.environ["CHECKCONF"] + + +@pytest.mark.parametrize("exponent_size", [0, 35, 666, 1024, 2048, 3072, 4096]) +def test_max_rsa_exponent_size_good(exponent_size, templates): + templates.render("options.conf", {"max_rsa_exponent_size": exponent_size}) + isctest.run.cmd([CHECKCONF, "options.conf"]) + + +@pytest.mark.parametrize("exponent_size", [1, 34, 4097]) +def test_max_rsa_exponent_size_bad(exponent_size, templates): + templates.render("options.conf", {"max_rsa_exponent_size": exponent_size}) + with pytest.raises(subprocess.CalledProcessError): + isctest.run.cmd([CHECKCONF, "options.conf"], log_stdout=True) + + +def test_rsa_big_exponent_keys_cant_load(): + with open("ns2/signer.err", encoding="utf-8") as file: + assert ( + "dnssec-signzone: fatal: cannot load dnskey Kexample.+008+52810.key: out of range" + in file.read() + ) + + +def test_rsa_big_exponent_keys_cant_validate(): + msg = dns.message.make_query("a.example.", "A") + res2 = isctest.query.tcp(msg, "10.53.0.2") + isctest.check.noerror(res2) + res3 = isctest.query.tcp(msg, "10.53.0.3") + isctest.check.servfail(res3) diff --git a/bin/tests/system/run.gdb b/bin/tests/system/run.gdb new file mode 100644 index 0000000..60981e1 --- /dev/null +++ b/bin/tests/system/run.gdb @@ -0,0 +1 @@ +thread apply all bt full diff --git a/bin/tests/system/run.sh b/bin/tests/system/run.sh new file mode 100755 index 0000000..c6d0485 --- /dev/null +++ b/bin/tests/system/run.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Run a single system test using the pytest runner. This is a simple wrapper +# around pytest for convenience. +# + +if [ -z "$1" ] || [ ! -d "$1" ]; then + echo "Usage: $0 system_test_dir [pytest_args]" + exit 2 +fi + +system_test_dir="$1" +shift + +( + cd "$system_test_dir" || exit 2 + /usr/bin/env python3 -m pytest "$@" +) diff --git a/bin/tests/system/runtime/README b/bin/tests/system/runtime/README new file mode 100644 index 0000000..9272f12 --- /dev/null +++ b/bin/tests/system/runtime/README @@ -0,0 +1,13 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +Tests of runtime checks, e.g., that named prevents duplicate processes +from running. diff --git a/bin/tests/system/runtime/ctrl-chars b/bin/tests/system/runtime/ctrl-chars new file mode 100644 index 0000000..4ce1650 --- /dev/null +++ b/bin/tests/system/runtime/ctrl-chars @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/bin/tests/system/runtime/long-cmd-line b/bin/tests/system/runtime/long-cmd-line new file mode 100644 index 0000000..e691a71 --- /dev/null +++ b/bin/tests/system/runtime/long-cmd-line @@ -0,0 +1 @@ +-m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage -m usage diff --git a/bin/tests/system/runtime/ns2/named-alt1.conf.in b/bin/tests/system/runtime/ns2/named-alt1.conf.in new file mode 100644 index 0000000..4c0312a --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt1.conf.in @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + directory "./nope"; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; diff --git a/bin/tests/system/runtime/ns2/named-alt2.conf.in b/bin/tests/system/runtime/ns2/named-alt2.conf.in new file mode 100644 index 0000000..71b7e09 --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt2.conf.in @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + managed-keys-directory "./nope"; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; diff --git a/bin/tests/system/runtime/ns2/named-alt3.conf.in b/bin/tests/system/runtime/ns2/named-alt3.conf.in new file mode 100644 index 0000000..fb79924 --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt3.conf.in @@ -0,0 +1,22 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + new-zones-directory "./nope"; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; diff --git a/bin/tests/system/runtime/ns2/named-alt4.conf.in b/bin/tests/system/runtime/ns2/named-alt4.conf.in new file mode 100644 index 0000000..722316f --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt4.conf.in @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + dnssec-validation no; +}; diff --git a/bin/tests/system/runtime/ns2/named-alt5.conf.in b/bin/tests/system/runtime/ns2/named-alt5.conf.in new file mode 100644 index 0000000..db85f44 --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt5.conf.in @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + dnssec-validation no; +}; + +zone "ipv4-only-servers" { + type secondary; + primaries { 10.53.0.3; }; +}; + +zone "ipv6-only-servers" { + type secondary; + primaries { fd92:7065:b8e:ffff::2; }; +}; diff --git a/bin/tests/system/runtime/ns2/named-alt9.conf.in b/bin/tests/system/runtime/ns2/named-alt9.conf.in new file mode 100644 index 0000000..f0ebcd3 --- /dev/null +++ b/bin/tests/system/runtime/ns2/named-alt9.conf.in @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + port @PORT@; + pid-file "named9.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; +}; diff --git a/bin/tests/system/runtime/ns2/named1.conf.in b/bin/tests/system/runtime/ns2/named1.conf.in new file mode 100644 index 0000000..d8b3148 --- /dev/null +++ b/bin/tests/system/runtime/ns2/named1.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { fd92:7065:b8e:ffff::2; }; + recursion no; + notify yes; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; diff --git a/bin/tests/system/runtime/setup.sh b/bin/tests/system/runtime/setup.sh new file mode 100644 index 0000000..a0fc0d0 --- /dev/null +++ b/bin/tests/system/runtime/setup.sh @@ -0,0 +1,25 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns2/named1.conf.in ns2/named.conf + +copy_setports ns2/named-alt1.conf.in ns2/named-alt1.conf +copy_setports ns2/named-alt2.conf.in ns2/named-alt2.conf +copy_setports ns2/named-alt3.conf.in ns2/named-alt3.conf +copy_setports ns2/named-alt4.conf.in ns2/named-alt4.conf +copy_setports ns2/named-alt5.conf.in ns2/named-alt5.conf + +mkdir ns2/nope +chmod 555 ns2/nope diff --git a/bin/tests/system/runtime/tests.sh b/bin/tests/system/runtime/tests.sh new file mode 100644 index 0000000..29438e2 --- /dev/null +++ b/bin/tests/system/runtime/tests.sh @@ -0,0 +1,256 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" +NAMED_DEFAULT_ARGS="-m record -d 99 -g" + +kill_named() { + pidfile="${1}" + if [ ! -r "${pidfile}" ]; then + return 1 + fi + + pid=$(cat "${pidfile}" 2>/dev/null) + if [ "${pid:+set}" = "set" ]; then + kill -15 "${pid}" >/dev/null 2>&1 + retries=10 + while [ "$retries" -gt 0 ]; do + if ! kill -0 "${pid}" >/dev/null 2>&1; then + break + fi + sleep 1 + retries=$((retries - 1)) + done + # Timed-out + if [ "$retries" -eq 0 ]; then + echo_i "failed to kill named ($pidfile)" + return 1 + fi + fi + rm -f "${pidfile}" + return 0 +} + +check_named_log() { + grep "$@" >/dev/null 2>&1 +} + +run_named() ( + dir="$1" + shift + run="$1" + shift + if cd "$dir" >/dev/null 2>&1; then + "${NAMED}" "$@" ${NAMED_DEFAULT_ARGS} >>"$run" 2>&1 & + echo $! + fi +) + +check_pid() ( + ! kill -0 "${1}" >/dev/null 2>&1 +) + +status=0 +n=0 + +n=$((n + 1)) +echo_i "verifying that named started normally ($n)" +ret=0 +[ -s ns2/named.pid ] || ret=1 +grep "unable to listen on any configured interface" ns2/named.run >/dev/null && ret=1 +grep "another named process" ns2/named.run >/dev/null && ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to reconfigure if working directory is not writable ($n)" +ret=0 +copy_setports ns2/named-alt1.conf.in ns2/named.conf +$RNDCCMD 10.53.0.2 reconfig >rndc.out.$n 2>&1 && ret=1 +grep "failed: permission denied" rndc.out.$n >/dev/null 2>&1 || ret=1 +sleep 1 +grep "[^-]directory './nope' is not writable" ns2/named.run >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to reconfigure if managed-keys-directory is not writable ($n)" +ret=0 +copy_setports ns2/named-alt2.conf.in ns2/named.conf +$RNDCCMD 10.53.0.2 reconfig >rndc.out.$n 2>&1 && ret=1 +grep "failed: permission denied" rndc.out.$n >/dev/null 2>&1 || ret=1 +sleep 1 +grep "managed-keys-directory './nope' is not writable" ns2/named.run >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to reconfigure if new-zones-directory is not writable ($n)" +ret=0 +copy_setports ns2/named-alt3.conf.in ns2/named.conf +$RNDCCMD 10.53.0.2 reconfig >rndc.out.$n 2>&1 && ret=1 +grep "failed: permission denied" rndc.out.$n >/dev/null 2>&1 || ret=1 +sleep 1 +grep "new-zones-directory './nope' is not writable" ns2/named.run >/dev/null 2>&1 || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named recovers when configuration file is valid again ($n)" +ret=0 +copy_setports ns2/named1.conf.in ns2/named.conf +$RNDCCMD 10.53.0.2 reconfig >rndc.out.$n 2>&1 || ret=1 +[ -s ns2/named.pid ] || ret=1 +kill_named ns2/named.pid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to start if working directory is not writable ($n)" +ret=0 +testpid=$(run_named ns2 named$n.run -c named-alt1.conf -D runtime-ns2-extra-4) +test -n "$testpid" || ret=1 +retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1 +grep "[^-]directory './nope' is not writable" ns2/named$n.run >/dev/null 2>&1 || ret=1 +kill_named ns2/named.pid && ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to start if managed-keys-directory is not writable ($n)" +ret=0 +testpid=$(run_named ns2 named$n.run -c named-alt2.conf -D runtime-ns2-extra-5) +test -n "$testpid" || ret=1 +retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1 +grep "managed-keys-directory './nope' is not writable" ns2/named$n.run >/dev/null 2>&1 || ret=1 +kill_named named.pid && ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named refuses to start if new-zones-directory is not writable ($n)" +ret=0 +testpid=$(run_named ns2 named$n.run -c named-alt3.conf -D runtime-ns2-extra-6) +test -n "$testpid" || ret=1 +retry_quiet 10 check_named_log "exiting (due to fatal error)" ns2/named$n.run || ret=1 +grep "new-zones-directory './nope' is not writable" ns2/named$n.run >/dev/null 2>&1 || ret=1 +kill_named ns2/named.pid && ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named logs control characters in octal notation ($n)" +ret=0 +INSTANCE_NAME="runtime-ns2-extra-7-$(cat ctrl-chars)" +testpid=$(run_named ns2 named$n.run -c named-alt4.conf -D "${INSTANCE_NAME}") +test -n "$testpid" || ret=1 +retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1 +grep 'running as.*\\177\\033' ns2/named$n.run >/dev/null || ret=1 +kill_named ns2/named.pid || ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named escapes special characters in the logs ($n)" +ret=0 +INSTANCE_NAME="runtime-ns2-extra-8-$;" +testpid=$(run_named ns2 named$n.run -c named-alt4.conf -D "${INSTANCE_NAME}") +test -n "$testpid" || ret=1 +retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1 +grep 'running as.*\\$\\;' ns2/named$n.run >/dev/null || ret=1 +kill_named ns2/named.pid || ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named logs an ellipsis when the command line is larger than 8k bytes ($n)" +ret=0 +LONG_CMD_LINE=$(cat long-cmd-line) +# shellcheck disable=SC2086 +testpid=$(run_named ns2 named$n.run $LONG_CMD_LINE -c "named-alt4.conf") +test -n "$testpid" || ret=1 +retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1 +grep "running as.*\.\.\.$" ns2/named$n.run >/dev/null || ret=1 +kill_named ns2/named.pid || ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named log missing IPv4 primaries in -4 mode ($n)" +ret=0 +INSTANCE_NAME="missing-primaries-ipv4-only-mode" +testpid=$(run_named ns2 named$n.run -c named-alt5.conf -D "${INSTANCE_NAME}" -4) +test -n "$testpid" || ret=1 +retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1 +grep "IPv6 disabled and no IPv4 primaries" ns2/named$n.run >/dev/null || ret=1 +kill_named ns2/named.pid || ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "checking that named log missing IPv6 primaries in -6 mode ($n)" +ret=0 +INSTANCE_NAME="missing-primaries-ipv4-only-mode" +testpid=$(run_named ns2 named$n.run -c named-alt5.conf -D "${INSTANCE_NAME}" -6) +test -n "$testpid" || ret=1 +retry_quiet 60 check_named_log "running$" ns2/named$n.run || ret=1 +grep "IPv4 disabled and no IPv6 primaries" ns2/named$n.run >/dev/null || ret=1 +kill_named ns2/named.pid || ret=1 +test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 +if [ $ret -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verifying that named switches UID ($n)" +if [ "$(id -u)" -eq 0 ]; then + ret=0 + { + TEMP_NAMED_DIR=$(mktemp -d "$(pwd)/ns2/tmp.XXXXXXXX") + rc=$? + } || true + if [ "$rc" -eq 0 ]; then + copy_setports ns2/named-alt9.conf.in "${TEMP_NAMED_DIR}/named-alt9.conf" + chown -R nobody: "${TEMP_NAMED_DIR}" + chmod 0700 "${TEMP_NAMED_DIR}" + testpid=$(run_named "${TEMP_NAMED_DIR}" "${TEMP_NAMED_DIR}/named$n.run" -u nobody -c named-alt9.conf) + test -n "$testpid" || ret=1 + retry_quiet 60 check_named_log "running$" "${TEMP_NAMED_DIR}/named$n.run" || ret=1 + [ -s "${TEMP_NAMED_DIR}/named9.pid" ] || ret=1 + grep "loading configuration: permission denied" "${TEMP_NAMED_DIR}/named$n.run" >/dev/null && ret=1 + kill_named "${TEMP_NAMED_DIR}/named9.pid" || ret=1 + test -n "$testpid" || ret=1 + test -n "$testpid" && retry_quiet 10 check_pid $testpid || ret=1 + else + echo_i "mktemp failed" + ret=1 + fi + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) +else + echo_i "skipped, not running as root" +fi + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/runtime/tests_sh_runtime.py b/bin/tests/system/runtime/tests_sh_runtime.py new file mode 100644 index 0000000..dee5d64 --- /dev/null +++ b/bin/tests/system/runtime/tests_sh_runtime.py @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "rndc.out.*", + "ns2/named-alt*.conf", + "ns2/named*.run", + "ns2/nope", + "ns2/tmp.*", + ] +) + + +def test_runtime(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/send.pl b/bin/tests/system/send.pl new file mode 100644 index 0000000..62b4f7a --- /dev/null +++ b/bin/tests/system/send.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# +# Send a file to a given address and port using TCP. Used for +# configuring the test server in ans.pl. +# + +use IO::File; +use IO::Socket; + +@ARGV == 2 or die "usage: send.pl host port [file ...]\n"; + +my $host = shift @ARGV; +my $port = shift @ARGV; + +my $sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, + Proto => "tcp",) or die "$!"; +while (<>) { + $sock->syswrite($_, length $_); +} + +$sock->close; diff --git a/bin/tests/system/serve-stale/ans2/ans.pl b/bin/tests/system/serve-stale/ans2/ans.pl new file mode 100644 index 0000000..6fac57c --- /dev/null +++ b/bin/tests/system/serve-stale/ans2/ans.pl @@ -0,0 +1,362 @@ +#!/usr/bin/env perl + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +use strict; +use warnings; + +use IO::File; +use IO::Socket; +use Getopt::Long; +use Net::DNS; +use Time::HiRes qw(usleep nanosleep); + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +# If send_response is set, the server will respond, otherwise the query will +# be dropped. +my $send_response = 1; +# If slow_response is set, a lookup for the CNAME target (target.example) is +# delayed. Other lookups will not be delayed. +my $slow_response = 0; + +my $localaddr = "10.53.0.2"; + +my $localport = int($ENV{'PORT'}); +if (!$localport) { $localport = 5300; } + +my $udpsock = IO::Socket::INET->new(LocalAddr => "$localaddr", + LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!"; + +# +# Delegations +# +my $SOA = "example 300 IN SOA . . 0 0 0 0 300"; +my $NS = "example 300 IN NS ns.example"; +my $A = "ns.example 300 IN A $localaddr"; +my $ssSOA = "delegated.serve.stale 300 IN SOA . . 0 0 0 0 300"; +my $ssNS = "delegated.serve.stale 300 IN NS ns.delegated.serve.stale"; +my $ssA = "ns.delegated.serve.stale 300 IN A $localaddr"; + +# +# Slow delegation +# +my $slowSOA = "slow 300 IN SOA . . 0 0 0 0 300"; +my $slowNS = "slow 300 IN NS ns.slow"; +my $slowA = "ns.slow 300 IN A $localaddr"; +my $slowTXT = "data.slow 2 IN TXT \"A slow text record with a 2 second ttl\""; +my $slownegSOA = "slow 2 IN SOA . . 0 0 0 0 300"; + +# +# Records to be TTL stretched +# +my $TXT = "data.example 2 IN TXT \"A text record with a 2 second ttl\""; +my $LONGTXT = "longttl.example 600 IN TXT \"A text record with a 600 second ttl\""; +my $CAA = "othertype.example 2 IN CAA 0 issue \"ca1.example.net\""; +my $negSOA = "example 2 IN SOA . . 0 0 0 0 300"; +my $ssnegSOA = "delegated.serve.stale 2 IN SOA . . 0 0 0 0 300"; +my $CNAME = "cname.example 7 IN CNAME target.example"; +my $TARGET = "target.example 9 IN A $localaddr"; +my $SHORTCNAME = "shortttl.cname.example 1 IN CNAME longttl.target.example"; +my $LONGTARGET = "longttl.target.example 600 IN A $localaddr"; + +sub reply_handler { + my ($qname, $qclass, $qtype) = @_; + my ($rcode, @ans, @auth, @add); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + # Control whether we send a response or not. + # We always respond to control commands. + if ($qname eq "enable" ) { + if ($qtype eq "TXT") { + $send_response = 1; + my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\""); + push @ans, $rr; + } + $rcode = "NOERROR"; + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); + } elsif ($qname eq "disable" ) { + if ($qtype eq "TXT") { + $send_response = 0; + my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\""); + push @ans, $rr; + } + $rcode = "NOERROR"; + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); + } elsif ($qname eq "slowdown" ) { + if ($qtype eq "TXT") { + $send_response = 1; + $slow_response = 1; + my $rr = new Net::DNS::RR("$qname 0 $qclass TXT \"$send_response\""); + push @ans, $rr; + } + $rcode = "NOERROR"; + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); + } + + # If we are not responding to queries we are done. + return if (!$send_response); + + if (index($qname, "latency") == 0) { + # simulate network latency before answering + print " Sleeping 50 milliseconds\n"; + select(undef, undef, undef, 0.05); + } + + # Construct the response and send it. + if ($qname eq "ns.example" ) { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($A); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($SOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "example") { + if ($qtype eq "NS") { + my $rr = new Net::DNS::RR($NS); + push @auth, $rr; + $rr = new Net::DNS::RR($A); + push @add, $rr; + } elsif ($qtype eq "SOA") { + my $rr = new Net::DNS::RR($SOA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($SOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "nodata.example") { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "data.example") { + if ($qtype eq "TXT") { + my $rr = new Net::DNS::RR($TXT); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "a-only.example") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR("a-only.example 2 IN A $localaddr"); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "cname.example") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($CNAME); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "target.example") { + if ($slow_response) { + print " Sleeping 3 seconds\n"; + sleep(3); + } + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($TARGET); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "shortttl.cname.example") { + my $rr = new Net::DNS::RR($SHORTCNAME); + push @ans, $rr; + $rcode = "NOERROR"; + } elsif ($qname eq "longttl.target.example") { + if ($slow_response) { + print " Sleeping 3 seconds\n"; + sleep(3); + } + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($LONGTARGET); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "longttl.example") { + if ($qtype eq "TXT") { + my $rr = new Net::DNS::RR($LONGTXT); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "nxdomain.example") { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + $rcode = "NXDOMAIN"; + } elsif ($qname eq "othertype.example") { + if ($qtype eq "CAA") { + my $rr = new Net::DNS::RR($CAA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($negSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "ns.delegated.serve.stale" ) { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($ssA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($ssSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "delegated.serve.stale") { + if ($qtype eq "NS") { + my $rr = new Net::DNS::RR($ssNS); + push @auth, $rr; + $rr = new Net::DNS::RR($ssA); + push @add, $rr; + } elsif ($qtype eq "SOA") { + my $rr = new Net::DNS::RR($ssSOA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($ssSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "www.delegated.serve.stale") { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR("www.delegated.serve.stale 2 IN A 10.53.0.99"); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($ssnegSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "ns.slow" ) { + if ($qtype eq "A") { + my $rr = new Net::DNS::RR($slowA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($slowSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "slow") { + if ($qtype eq "NS") { + my $rr = new Net::DNS::RR($slowNS); + push @auth, $rr; + $rr = new Net::DNS::RR($slowA); + push @add, $rr; + } elsif ($qtype eq "SOA") { + my $rr = new Net::DNS::RR($slowSOA); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($slowSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "data.slow") { + if ($slow_response) { + print " Sleeping 3 seconds\n"; + sleep(3); + # only one time + $slow_response = 0; + } + if ($qtype eq "TXT") { + my $rr = new Net::DNS::RR($slowTXT); + push @ans, $rr; + } else { + my $rr = new Net::DNS::RR($slownegSOA); + push @auth, $rr; + } + $rcode = "NOERROR"; + } else { + my $rr = new Net::DNS::RR($SOA); + push @auth, $rr; + $rcode = "NXDOMAIN"; + } + + # mark the answer as authoritative (by setting the 'aa' flag) + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); +} + +GetOptions( + 'port=i' => \$localport, +); + +my $rin; +my $rout; + +for (;;) { + $rin = ''; + vec($rin, fileno($udpsock), 1) = 1; + + select($rout = $rin, undef, undef, undef); + + if (vec($rout, fileno($udpsock), 1)) { + my ($buf, $request, $err); + $udpsock->recv($buf, 512); + + if ($Net::DNS::VERSION > 0.68) { + $request = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($request, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + my @questions = $request->question; + my $qname = $questions[0]->qname; + my $qclass = $questions[0]->qclass; + my $qtype = $questions[0]->qtype; + my $id = $request->header->id; + + my ($rcode, $ans, $auth, $add, $headermask) = reply_handler($qname, $qclass, $qtype); + + if (!defined($rcode)) { + print " Silently ignoring query\n"; + next; + } + + my $reply = Net::DNS::Packet->new(); + $reply->header->qr(1); + $reply->header->aa(1) if $headermask->{'aa'}; + $reply->header->id($id); + $reply->header->rcode($rcode); + $reply->push("question", @questions); + $reply->push("answer", @$ans) if $ans; + $reply->push("authority", @$auth) if $auth; + $reply->push("additional", @$add) if $add; + + my $num_chars = $udpsock->send($reply->data); + print " Sent $num_chars bytes via UDP\n"; + } +} diff --git a/bin/tests/system/serve-stale/ns1/named1.conf.in b/bin/tests/system/serve-stale/ns1/named1.conf.in new file mode 100644 index 0000000..5b20f4a --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/named1.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation no; + max-stale-ttl 3600; + stale-answer-ttl 4; + stale-answer-enable yes; + stale-cache-enable yes; + stale-refresh-time 30; + servfail-ttl 0; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns1/named2.conf.in b/bin/tests/system/serve-stale/ns1/named2.conf.in new file mode 100644 index 0000000..d0bfdbe --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/named2.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation no; + max-stale-ttl 3600; + stale-answer-ttl 4; + stale-answer-enable yes; + stale-cache-enable yes; + stale-refresh-time 0; + servfail-ttl 0; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns1/named3.conf.in b/bin/tests/system/serve-stale/ns1/named3.conf.in new file mode 100644 index 0000000..2207863 --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/named3.conf.in @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation no; + max-stale-ttl 20; + stale-answer-ttl 3; + stale-answer-enable yes; + stale-cache-enable yes; + servfail-ttl 0; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns1/named4.conf.in b/bin/tests/system/serve-stale/ns1/named4.conf.in new file mode 100644 index 0000000..9bf2f76 --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/named4.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion yes; + dnssec-validation no; + max-stale-ttl 20; + stale-answer-ttl 3; + stale-answer-enable yes; + stale-cache-enable yes; + stale-refresh-time 0; + servfail-ttl 0; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "stale.test" { + type primary; + file "stale.test.db"; +}; diff --git a/bin/tests/system/serve-stale/ns1/root.db b/bin/tests/system/serve-stale/ns1/root.db new file mode 100644 index 0000000..e36f2b0 --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/root.db @@ -0,0 +1,20 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 SOA . . 0 0 0 0 0 +. 300 NS ns.nil. +ns.nil. 300 A 10.53.0.1 +example. 300 NS ns.example. +ns.example. 300 A 10.53.0.2 +slow. 300 NS ns.slow. +ns.slow. 300 A 10.53.0.2 +stale. 300 NS ns.stale. +ns.stale. 300 A 10.53.0.6 diff --git a/bin/tests/system/serve-stale/ns1/stale.test.db b/bin/tests/system/serve-stale/ns1/stale.test.db new file mode 100644 index 0000000..d389e7c --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/stale.test.db @@ -0,0 +1,19 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN stale.test. +stale.test. 300 SOA . . 0 0 0 0 0 +stale.test. 300 NS ns.stale.test. +ns.stale.test. 300 A 10.53.0.1 +cname1.stale.test. 1 CNAME a1.stale.test. +a1.stale.test. 1 A 192.0.2.1 +cname2.stale.test. 1 CNAME a2.stale.test. +a2.stale.test. 300 A 192.0.2.2 diff --git a/bin/tests/system/serve-stale/ns3/named.conf.in b/bin/tests/system/serve-stale/ns3/named.conf.in new file mode 100644 index 0000000..16b3e04 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named.conf.in @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + qname-minimization off; + + stale-answer-enable yes; + stale-cache-enable yes; + stale-refresh-time 30; + stale-answer-client-timeout 0; + max-cache-ttl 24h; +}; + +zone "." { + type hint; + file "root.db"; +}; + +zone "serve.stale" IN { + type primary; + notify no; + file "serve.stale.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named1.conf.in b/bin/tests/system/serve-stale/ns3/named1.conf.in new file mode 100644 index 0000000..5c7dddd --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named1.conf.in @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dump-file "named_dump3.db"; + stale-cache-enable yes; + dnssec-validation no; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named2.conf.in b/bin/tests/system/serve-stale/ns3/named2.conf.in new file mode 100644 index 0000000..51a70a8 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named2.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test default stale-answer-client-timeout value + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-refresh-time 0; + stale-answer-client-timeout 0; + max-stale-ttl 3600; + resolver-query-timeout 30000; # 30 seconds + qname-minimization disabled; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named3.conf.in b/bin/tests/system/serve-stale/ns3/named3.conf.in new file mode 100644 index 0000000..cef5e52 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named3.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test disable of stale-answer-client-timeout. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-refresh-time 0; + max-stale-ttl 3600; + resolver-query-timeout 10000; # 10 seconds +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named4.conf.in b/bin/tests/system/serve-stale/ns3/named4.conf.in new file mode 100644 index 0000000..abc1eb7 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named4.conf.in @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test stale-answer-client-timeout 0. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout 0; + stale-refresh-time 0; + resolver-query-timeout 10000; # 10 seconds + max-stale-ttl 3600; + recursive-clients 10; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named5.conf.in b/bin/tests/system/serve-stale/ns3/named5.conf.in new file mode 100644 index 0000000..b695901 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named5.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test stale-answer-client-timeout 0. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout 0; + stale-refresh-time 4; + resolver-query-timeout 10000; # 10 seconds + max-stale-ttl 3600; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named6.conf.in b/bin/tests/system/serve-stale/ns3/named6.conf.in new file mode 100644 index 0000000..307c3bc --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named6.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable no; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-refresh-time 4; + resolver-query-timeout 10000; # 10 seconds + fetches-per-zone 1 fail; + fetches-per-server 1 fail; + max-stale-ttl 3600; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named7.conf.in b/bin/tests/system/serve-stale/ns3/named7.conf.in new file mode 100644 index 0000000..12d9ee3 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named7.conf.in @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Test serve-stale interaction with fetch-limits (dual-mode). + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + /* + * stale-answer-enable is not strictly required because serving + * stale answers is enabled in the test via rndc. + */ + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-refresh-time 4; + resolver-query-timeout 10000; # 10 seconds + fetches-per-zone 1 fail; + fetches-per-server 1 fail; + max-stale-ttl 3600; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named8.conf.in b/bin/tests/system/serve-stale/ns3/named8.conf.in new file mode 100644 index 0000000..a468041 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named8.conf.in @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-client-timeout 0; + prefetch 2 8; + dns64 2001:aaaa::/96 { + clients { any; }; + mapped { any; }; + }; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named9.conf.in b/bin/tests/system/serve-stale/ns3/named9.conf.in new file mode 100644 index 0000000..cb09713 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named9.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout 0; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; + +zone "serve.stale" IN { + type primary; + notify no; + file "serve.stale.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/root.db b/bin/tests/system/serve-stale/ns3/root.db new file mode 100644 index 0000000..bbf039c --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/root.db @@ -0,0 +1,13 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 NS ns.nil. +ns.nil. 300 A 10.53.0.1 diff --git a/bin/tests/system/serve-stale/ns3/serve.stale.db b/bin/tests/system/serve-stale/ns3/serve.stale.db new file mode 100644 index 0000000..09a6965 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/serve.stale.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +serve.stale. IN SOA ns.serve.stale. matthijs.isc.org. 1 0 0 0 0 +serve.stale. IN NS ns.serve.stale. +ns.serve.stale. IN A 10.53.0.6 + +$ORIGIN serve.stale. +test IN NS nss1.example.nxd. +test IN NS nss2.example.nxd. + +delegated IN NS ns2.delegated.serve.stale. +ns2.delegated IN A 10.53.0.2 diff --git a/bin/tests/system/serve-stale/ns4/named.conf.in b/bin/tests/system/serve-stale/ns4/named.conf.in new file mode 100644 index 0000000..ac7dd99 --- /dev/null +++ b/bin/tests/system/serve-stale/ns4/named.conf.in @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + dump-file "named_dump.db"; + stale-answer-enable no; + stale-cache-enable yes; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns5/named.conf.in b/bin/tests/system/serve-stale/ns5/named.conf.in new file mode 100644 index 0000000..9874728 --- /dev/null +++ b/bin/tests/system/serve-stale/ns5/named.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation no; + dump-file "named_dump.db"; + stale-answer-enable yes; + stale-cache-enable no; + max-cache-ttl 24h; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns6/named.conf.in b/bin/tests/system/serve-stale/ns6/named.conf.in new file mode 100644 index 0000000..ddc5afe --- /dev/null +++ b/bin/tests/system/serve-stale/ns6/named.conf.in @@ -0,0 +1,45 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion no; +}; + +zone "stale" IN { + type primary; + notify no; + file "stale.db"; +}; + +zone "serve.stale" IN { + type primary; + notify no; + file "serve.stale.db"; +}; diff --git a/bin/tests/system/serve-stale/ns6/serve.stale.db b/bin/tests/system/serve-stale/ns6/serve.stale.db new file mode 100644 index 0000000..2b17c68 --- /dev/null +++ b/bin/tests/system/serve-stale/ns6/serve.stale.db @@ -0,0 +1,16 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +serve.stale. IN SOA ns.serve.stale. matthijs.isc.org. 1 0 0 0 0 +serve.stale. IN NS ns.serve.stale. +ns.serve.stale. IN A 10.53.0.6 + +test IN TXT "Oops, I did it again" diff --git a/bin/tests/system/serve-stale/ns6/stale.db b/bin/tests/system/serve-stale/ns6/stale.db new file mode 100644 index 0000000..4ae0068 --- /dev/null +++ b/bin/tests/system/serve-stale/ns6/stale.db @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +stale. IN SOA ns.stale. matthijs.isc.org. 1 0 0 0 0 +stale. IN NS ns.stale. +ns.stale. IN A 10.53.0.6 + +serve.stale. IN NS ns.serve.stale. +ns.serve.stale. IN A 10.53.0.6 diff --git a/bin/tests/system/serve-stale/prereq.sh b/bin/tests/system/serve-stale/prereq.sh new file mode 100644 index 0000000..7411c8a --- /dev/null +++ b/bin/tests/system/serve-stale/prereq.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +if ! ${PERL} -MTime::HiRes -e ''; then + echo_i "perl Time::HiRes module is required" + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/serve-stale/setup.sh b/bin/tests/system/serve-stale/setup.sh new file mode 100644 index 0000000..ad6073a --- /dev/null +++ b/bin/tests/system/serve-stale/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named1.conf.in ns1/named.conf +copy_setports ns3/named.conf.in ns3/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh new file mode 100755 index 0000000..3e32670 --- /dev/null +++ b/bin/tests/system/serve-stale/tests.sh @@ -0,0 +1,2538 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s" +DIG="$DIG +time=12 +tries=1" + +max_stale_ttl=$(sed -ne 's,^[[:space:]]*max-stale-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c) +stale_answer_ttl=$(sed -ne 's,^[[:space:]]*stale-answer-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c) + +status=0 +n=0 + +# +# First test server with serve-stale options set. +# +echo_i "test server with serve-stale options set" + +n=$((n + 1)) +echo_i "prime cache longttl.example TXT ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TXT ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache othertype.example CAA ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nxdomain.example TXT ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify prime cache statistics ($n)" +ret=0 +rm -f ns1/named.stats +$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1 +[ -f ns1/named.stats ] || ret=1 +cp ns1/named.stats ns1/named.stats.$n +# Check first 10 lines of Cache DB statistics. After prime queries, we expect +# two active TXT, one active Others, one nxrrset TXT, and one NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1 +grep "1 Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "2 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 !TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +# Run rndc dumpdb, test whether the stale data has correct comment printed. +# The max-stale-ttl is 3600 seconds, so the comment should say the data is +# stale for somewhere between 3500-3599 seconds. +echo_i "check rndc dump stale data.example ($n)" +rndc_dumpdb ns1 || ret=1 +awk '/; stale since [0-9]*/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \ + | grep "; stale since [0-9]* data\.example.*3[56]...*TXT.*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1 +# Also make sure the not expired data does not have a stale comment. +awk '/; authanswer/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \ + | grep "; authanswer longttl\.example.*[56]...*TXT.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sending queries for tests $((n + 1))-$((n + 5))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 4)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 5)) & + +wait + +n=$((n + 1)) +echo_i "check stale data.example TXT ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check non-stale longttl.example TXT ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "EDE" dig.out.test$n >/dev/null && ret=1 +grep "longttl\.example\..*59[0-9].*IN.*TXT.*A text record with a 600 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify stale cache statistics ($n)" +ret=0 +rm -f ns1/named.stats +$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1 +[ -f ns1/named.stats ] || ret=1 +cp ns1/named.stats ns1/named.stats.$n +# Check first 10 lines of Cache DB statistics. After serve-stale queries, we +# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one +# stale NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1 +grep "1 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #!TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +# Test stale-refresh-time when serve-stale is enabled via configuration. +# Steps for testing stale-refresh-time option (default). +# 1. Prime cache data.example txt +# 2. Disable responses from authoritative server. +# 3. Sleep for TTL duration so rrset TTL expires (2 sec) +# 4. Query data.example +# 5. Check if response come from stale rrset (4 sec TTL) +# 6. Enable responses from authoritative server. +# 7. Query data.example +# 8. Check if response come from stale rrset, since the query +# is still within stale-refresh-time window. +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 1-3 done above. + +# Step 4. +n=$((n + 1)) +echo_i "sending query for test ($n)" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 + +# Step 5. +echo_i "check stale data.example TXT (stale-refresh-time) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 6. +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 7. +echo_i "sending query for test $((n + 1))" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true + +# Step 8. +n=$((n + 1)) +echo_i "check stale data.example TXT comes from cache (stale-refresh-time) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Test interaction with local zone +# + +n=$((n + 1)) +echo_i "check that serve-stale does not recurse for local authoritative zone ($n)" +ret=0 + +num=0 +threshold=10 +while [ $num -lt $threshold ]; do + + echo_i "dig test.serve.stale TXT ($n)" + $DIG -p ${PORT} @10.53.0.3 test.serve.stale TXT >dig.out.test$n.$num || ret=1 + grep "status: SERVFAIL" dig.out.test$n.$num >/dev/null || ret=1 + if [ $ret != 0 ]; then num=$threshold; fi + + sleep 1 + num=$((num + 1)) +done +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Test disabling serve-stale via rndc. +# + +n=$((n + 1)) +echo_i "updating ns1/named.conf ($n)" +ret=0 +copy_setports ns1/named2.conf.in ns1/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns1 10.53.0.1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc serve-stale off' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale off || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# no stale answers are used and the authoritative queries timed out. So no EDE 3 +# is not sent but EDE 22 is sent. + +n=$((n + 1)) +echo_i "check stale data.example TXT (serve-stale off) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA (serve-stale off) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT (serve-stale off) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT (serve-stale off) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Test enabling serve-stale via rndc. +# +n=$((n + 1)) +echo_i "running 'rndc serve-stale on' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale on || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +n=$((n + 1)) +echo_i "check stale data.example TXT (serve-stale on) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA (serve-stale on) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT (serve-stale on) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT (serve-stale on) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc serve-stale off' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale off || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc serve-stale reset' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale reset || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +n=$((n + 1)) +echo_i "check stale data.example TXT (serve-stale reset) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA (serve-stale reset) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT (serve-stale reset) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT (serve-stale reset) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc serve-stale off' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale off || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Update named.conf. +# Test server with low max-stale-ttl. +# +echo_i "test server with serve-stale options set, low max-stale-ttl" + +n=$((n + 1)) +echo_i "updating ns1/named.conf ($n)" +ret=0 +copy_setports ns1/named3.conf.in ns1/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns1 10.53.0.1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "flush cache, re-enable serve-stale and query again ($n)" +ret=0 +$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1 +$RNDCCMD 10.53.0.1 serve-stale on >rndc.out.test$n.2 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache longttl.example TXT (low max-stale-ttl) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TXT (low max-stale-ttl) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache othertype.example CAA (low max-stale-ttl) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT (low max-stale-ttl) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nxdomain.example TXT (low max-stale-ttl) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Keep track of time so we can access these RRset later, when we expect them +# to become ancient. +t1=$($PERL -e 'print time()') + +n=$((n + 1)) +echo_i "verify prime cache statistics (low max-stale-ttl) ($n)" +ret=0 +rm -f ns1/named.stats +$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1 +[ -f ns1/named.stats ] || ret=1 +cp ns1/named.stats ns1/named.stats.$n +# Check first 10 lines of Cache DB statistics. After prime queries, we expect +# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1 +grep "2 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 !TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +n=$((n + 1)) +echo_i "check stale data.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA (low max-stale-ttl) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*3.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*3.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify stale cache statistics (low max-stale-ttl) ($n)" +ret=0 +rm -f ns1/named.stats +$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1 +[ -f ns1/named.stats ] || ret=1 +cp ns1/named.stats ns1/named.stats.$n +# Check first 10 lines of Cache DB statistics. After serve-stale queries, we +# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one +# stale NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1 +grep "1 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #!TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1 + +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +# Retrieve max-stale-ttl value. +interval_to_ancient=$(grep 'max-stale-ttl' ns1/named3.conf.in | awk '{ print $2 }' | tr -d ';') +# We add 2 seconds to it since this is the ttl value of the records being +# tested. +interval_to_ancient=$((interval_to_ancient + 2)) +t2=$($PERL -e 'print time()') +elapsed=$((t2 - t1)) + +# If elapsed time so far is less than max-stale-ttl + 2 seconds, then we sleep +# enough to ensure that we'll ask for ancient RRsets in the next queries. +if [ $elapsed -lt $interval_to_ancient ]; then + sleep $((interval_to_ancient - elapsed)) +fi + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# stale-answer is enabled, but with a very low TTL so the following answer have +# been removed from the stale cache. Hence, no EDE 3 anymore, but EDE 22. + +n=$((n + 1)) +echo_i "check ancient data.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check ancient othertype.example CAA (low max-stale-ttl) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check ancient nodata.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check ancient nxdomain.example TXT (low max-stale-ttl) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test stale-refresh-time when serve-stale is enabled via rndc. +# Steps for testing stale-refresh-time option (default). +# 1. Prime cache data.example txt +# 2. Disable responses from authoritative server. +# 3. Sleep for TTL duration so rrset TTL expires (2 sec) +# 4. Query data.example +# 5. Check if response come from stale rrset (3 sec TTL) +# 6. Enable responses from authoritative server. +# 7. Query data.example +# 8. Check if response come from stale rrset, since the query +# is within stale-refresh-time window. +n=$((n + 1)) +echo_i "flush cache, enable responses from authoritative server ($n)" +ret=0 +$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 1. +n=$((n + 1)) +echo_i "prime cache data.example TXT (stale-refresh-time rndc) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 2. +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 3. +sleep 2 + +# Step 4. +n=$((n + 1)) +echo_i "sending query for test ($n)" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 + +# Step 5. +echo_i "check stale data.example TXT (stale-refresh-time rndc) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 6. +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 7. +echo_i "sending query for test $((n + 1))" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true + +# Step 8. +n=$((n + 1)) +echo_i "check stale data.example TXT comes from cache (stale-refresh-time rndc) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Steps for testing stale-refresh-time option (disabled). +# 1. Prime cache data.example txt +# 2. Disable responses from authoritative server. +# 3. Sleep for TTL duration so rrset TTL expires (2 sec) +# 4. Query data.example +# 5. Check if response come from stale rrset (3 sec TTL) +# 6. Enable responses from authoritative server. +# 7. Query data.example +# 8. Check if response come from stale rrset, since the query +# is within stale-refresh-time window. +n=$((n + 1)) +echo_i "updating ns1/named.conf ($n)" +ret=0 +copy_setports ns1/named4.conf.in ns1/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns1 10.53.0.1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "flush cache, enable responses from authoritative server ($n)" +ret=0 +$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 1. +n=$((n + 1)) +echo_i "prime cache data.example TXT (stale-refresh-time disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 2. +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 3. +sleep 2 + +# Step 4. +n=$((n + 1)) +echo_i "sending query for test ($n)" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1 + +# Step 5. +echo_i "check stale data.example TXT (stale-refresh-time disabled) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 6. +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Step 7. +echo_i "sending query for test $((n + 1))" +$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true + +# Step 8. +n=$((n + 1)) +echo_i "check data.example TXT comes from authoritative (stale-refresh-time disabled) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Now test server with no serve-stale options set. +# +echo_i "test server with no serve-stale options set" + +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named1.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "restart ns3" +stop_server --use-rndc --port ${CONTROLPORT} ns3 +start_server --noclean --restart --port ${PORT} ns3 + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache longttl.example TXT (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 longttl.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TXT (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache othertype.example CAA (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nxdomain.example TXT (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify prime cache statistics (max-stale-ttl default) ($n)" +ret=0 +rm -f ns3/named.stats +$RNDCCMD 10.53.0.3 stats >/dev/null 2>&1 +[ -f ns3/named.stats ] || ret=1 +cp ns3/named.stats ns3/named.stats.$n +# Check first 10 lines of Cache DB statistics. After prime queries, we expect +# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n >ns3/named.stats.$n.cachedb || ret=1 +grep "2 TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 Others" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 !TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 NXDOMAIN" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# no stale answers are used and the authoritative queries timed out. So no EDE 3 +# is not sent but EDE 22 is sent. + +n=$((n + 1)) +echo_i "check fail of data.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of othertype.example CAA (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nodata.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nxdomain.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify stale cache statistics (max-stale-ttl default) ($n)" +ret=0 +rm -f ns3/named.stats +$RNDCCMD 10.53.0.3 stats >/dev/null 2>&1 +[ -f ns3/named.stats ] || ret=1 +cp ns3/named.stats ns3/named.stats.$n +# Check first 10 lines of Cache DB statistics. After last queries, we expect +# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale +# NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n >ns3/named.stats.$n.cachedb || ret=1 +grep "1 TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #Others" ns3/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #!TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1 + +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +n=$((n + 1)) +echo_i "check 'rndc serve-stale on' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale on >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep "_default: stale cache enabled; stale answers enabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +# Check that if we don't have stale data for a domain name, we will +# not answer anything until the resolver query timeout. +n=$((n + 1)) +echo_i "check notincache.example TXT times out (max-stale-ttl default) ($n)" +ret=0 +$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 notfound.example TXT >dig.out.test$n 2>&1 && ret=1 +grep "timed out" dig.out.test$n >/dev/null || ret=1 +grep ";; no servers could be reached" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) & +$DIG -p ${PORT} @10.53.0.3 notfound.example TXT >dig.out.test$((n + 5)) & + +wait + +n=$((n + 1)) +echo_i "check data.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*30.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check othertype.example CAA (max-stale-ttl default) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "example\..*30.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check nodata.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*30.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check nxdomain.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The notfound.example check is different than nxdomain.example because +# we didn't send a prime query to add notfound.example to the cache. +# Independently, EDE 22 is sent as the authoritative server doesn't respond. +n=$((n + 1)) +echo_i "check notfound.example TXT (max-stale-ttl default) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# +# Now test server with serve-stale answers disabled. +# +echo_i "test server with serve-stale disabled" + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache longttl.example TTL (serve-stale answers disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.4 longttl.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TTL (serve-stale answers disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.4 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache othertype.example CAA (serve-stale answers disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.4 othertype.example CAA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT (serve-stale answers disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.4 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nxdomain.example TXT (serve-stale answers disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify prime cache statistics (serve-stale answers disabled) ($n)" +ret=0 +rm -f ns4/named.stats +$RNDCCMD 10.53.0.4 stats >/dev/null 2>&1 +[ -f ns4/named.stats ] || ret=1 +cp ns4/named.stats ns4/named.stats.$n +# Check first 10 lines of Cache DB statistics. After prime queries, we expect +# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1 +grep "2 TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 Others" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 !TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 NXDOMAIN" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.4 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.4 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.4 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.4 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# no stale answers are used and the authoritative queries timed out. So no EDE 3 +# is not sent but EDE 22 is sent. + +n=$((n + 1)) +echo_i "check fail of data.example TXT (serve-stale answers disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of othertype.example TXT (serve-stale answers disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nodata.example TXT (serve-stale answers disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nxdomain.example TXT (serve-stale answers disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify stale cache statistics (serve-stale answers disabled) ($n)" +ret=0 +rm -f ns4/named.stats +$RNDCCMD 10.53.0.4 stats >/dev/null 2>&1 +[ -f ns4/named.stats ] || ret=1 +cp ns4/named.stats ns4/named.stats.$n +# Check first 10 lines of Cache DB statistics. After last queries, we expect +# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale +# NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1 +grep "1 TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #Others" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 #!TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +# Dump the cache. +n=$((n + 1)) +echo_i "dump the cache (serve-stale answers disabled) ($n)" +ret=0 +rndc_dumpdb ns4 -cache || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "stop ns4" +stop_server --use-rndc --port ${CONTROLPORT} ns4 + +# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older. Since +# max-stale-ttl defaults to a week, we need to adjust the date by one week and +# five minutes. +LASTWEEK=$(TZ=UTC perl -e 'my $now = time(); + my $oneWeekAgo = $now - 604800; + my $fiveMinutesAgo = $oneWeekAgo - 300; + my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5]; + printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);') + +echo_i "mock the cache date to $LASTWEEK (serve-stale answers disabled) ($n)" +ret=0 +sed -E "s/DATE [0-9]{14}/DATE $LASTWEEK/g" ns4/named_dump.db.test$n >ns4/named_dump.db.out || ret=1 +cp ns4/named_dump.db.out ns4/named_dump.db +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "start ns4" +start_server --noclean --restart --port ${PORT} ns4 + +n=$((n + 1)) +echo_i "verify ancient cache statistics (serve-stale answers disabled) ($n)" +ret=0 +rm -f ns4/named.stats +$RNDCCMD 10.53.0.4 stats #> /dev/null 2>&1 +[ -f ns4/named.stats ] || ret=1 +cp ns4/named.stats ns4/named.stats.$n +# Check first 10 lines of Cache DB statistics. After last queries, we expect +# everything to be removed or scheduled to be removed. +grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1 +grep "#TXT" ns4/named.stats.$n.cachedb >/dev/null && ret=1 +grep "#Others" ns4/named.stats.$n.cachedb >/dev/null && ret=1 +grep "#!TXT" ns4/named.stats.$n.cachedb >/dev/null && ret=1 +grep "#NXDOMAIN" ns4/named.stats.$n.cachedb >/dev/null && ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +# +# Test the server with stale-cache disabled. +# +echo_i "test server with serve-stale cache disabled" + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache longttl.example TXT (serve-stale cache disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.5 longttl.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TXT (serve-stale cache disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.5 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache othertype.example CAA (serve-stale cache disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.5 othertype.example CAA >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT (serve-stale cache disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.5 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nxdomain.example TXT (serve-stale cache disabled) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT >dig.out.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify prime cache statistics (serve-stale cache disabled) ($n)" +ret=0 +rm -f ns5/named.stats +$RNDCCMD 10.53.0.5 stats >/dev/null 2>&1 +[ -f ns5/named.stats ] || ret=1 +cp ns5/named.stats ns5/named.stats.$n +# Check first 10 lines of Cache DB statistics. After serve-stale queries, +# we expect two active TXT RRsets, one active Others, one nxrrset TXT, and +# one NXDOMAIN. +grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1 +grep "2 TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 Others" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +grep "1 !TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.5 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep "_default: stale cache disabled; stale answers unavailable" rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +sleep 2 + +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.5 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.5 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.5 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# no stale answers are used and the authoritative queries timed out. So no EDE 3 +# is not sent but EDE 22 is sent. + +n=$((n + 1)) +echo_i "check fail of data.example TXT (serve-stale cache disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of othertype.example CAA (serve-stale cache disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nodata.example TXT (serve-stale cache disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check fail of nxdomain.example TXT (serve-stale cache disabled) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 22 (No Reachable Authority)" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer)" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "verify stale cache statistics (serve-stale cache disabled) ($n)" +ret=0 +rm -f ns5/named.stats +$RNDCCMD 10.53.0.5 stats >/dev/null 2>&1 +[ -f ns5/named.stats ] || ret=1 +cp ns5/named.stats ns5/named.stats.$n +# Check first 10 lines of Cache DB statistics. After serve-stale queries, +# we expect one active TXT (longttl) and the rest to be expired from cache, +# but since we keep everything for 5 minutes (RBTDB_VIRTUAL) in the cache +# after expiry, they still show up in the stats. +grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1 +grep -F "1 Others" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +grep -F "2 TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +grep -F "1 !TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +# Dump the cache. +n=$((n + 1)) +echo_i "dump the cache (serve-stale cache disabled) ($n)" +ret=0 +rndc_dumpdb ns5 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) +# Check that expired records are not dumped. +ret=0 +grep "; expired (awaiting cleanup)" ns5/named_dump.db.test$n && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Dump the cache including expired entries. +n=$((n + 1)) +echo_i "dump the cache including expired entries (serve-stale cache disabled) ($n)" +ret=0 +rndc_dumpdb ns5 -expired || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Check that expired records are dumped. +echo_i "check rndc dump expired data.example ($n)" +ret=0 +awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \ + | grep "; expired (awaiting cleanup) data\.example\..*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1 +awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \ + | grep "; expired (awaiting cleanup) nodata\.example\." >/dev/null 2>&1 || ret=1 +awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \ + | grep "; expired (awaiting cleanup) nxdomain\.example\." >/dev/null 2>&1 || ret=1 +awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \ + | grep "; expired (awaiting cleanup) othertype\.example\." >/dev/null 2>&1 || ret=1 +# Also make sure the not expired data does not have an expired comment. +awk '/; authanswer/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \ + | grep "; authanswer longttl\.example.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "stop ns5" +stop_server --use-rndc --port ${CONTROLPORT} ns5 + +# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older. +cp ns5/named_dump.db.test$n ns5/named_dump.db +FIVEMINUTESAGO=$(TZ=UTC perl -e 'my $now = time(); + my $fiveMinutesAgo = 300; + my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5]; + printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);') + +n=$((n + 1)) +echo_i "mock the cache date to $FIVEMINUTESAGO (serve-stale cache disabled) ($n)" +ret=0 +sed -E "s/DATE [0-9]{14}/DATE $FIVEMINUTESAGO/g" ns5/named_dump.db >ns5/named_dump.db.out || ret=1 +cp ns5/named_dump.db.out ns5/named_dump.db +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "start ns5" +start_server --noclean --restart --port ${PORT} ns5 + +n=$((n + 1)) +echo_i "verify ancient cache statistics (serve-stale cache disabled) ($n)" +ret=0 +rm -f ns5/named.stats +$RNDCCMD 10.53.0.5 stats #> /dev/null 2>&1 +[ -f ns5/named.stats ] || ret=1 +cp ns5/named.stats ns5/named.stats.$n +# Check first 10 lines of Cache DB statistics. After last queries, we expect +# everything to be removed or scheduled to be removed. +grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1 +grep -F "#TXT" ns5/named.stats.$n.cachedb >/dev/null && ret=1 +grep -F "#Others" ns5/named.stats.$n.cachedb >/dev/null && ret=1 +grep -F "#!TXT" ns5/named.stats.$n.cachedb >/dev/null && ret=1 +status=$((status + ret)) +if [ $ret != 0 ]; then echo_i "failed"; fi + +############################################# +# Test for stale-answer-client-timeout off. # +############################################# +echo_i "test stale-answer-client-timeout (off)" + +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named3.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Send a query, auth server is disabled, we will enable it after a while in +# order to receive an answer before resolver-query-timeout expires. Since +# stale-answer-client-timeout is disabled we must receive an answer from +# authoritative server. +echo_i "sending query for test $((n + 2))" +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 2)) & +sleep 3 + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Wait until dig is done. +wait + +n=$((n + 1)) +echo_i "check data.example TXT comes from authoritative server (stale-answer-client-timeout off) ($n)" +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +check_server_responds() { + $DIG -p ${PORT} @10.53.0.3 version.bind txt ch >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 +} + +############################################################## +# Test for stale-answer-client-timeout off and CNAME record. # +############################################################## +echo_i "test stale-answer-client-timeout (0) and CNAME record" + +n=$((n + 1)) +echo_i "prime cache shortttl.cname.example (stale-answer-client-timeout off) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "shortttl\.cname\.example\..*1.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n >/dev/null || ret=1 +grep "longttl\.target\.example\..*600.*IN.*A.*10\.53\.0\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 1 + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale shortttl.cname.example comes from cache (stale-answer-client-timeout off) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A >dig.out.test$n || ret=1 +wait_for_log 5 "shortttl.cname.example A resolver failure, stale answer used" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "shortttl\.cname\.example\..*3.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n >/dev/null || ret=1 +# We can't reliably test the TTL of the longttl.target.example A record. +grep "longttl\.target\.example\..*IN.*A.*10\.53\.0\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check server is alive or restart ($n)" +ret=0 +$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + echo_i "restart ns3" + start_server --noclean --restart --port ${PORT} serve-stale ns3 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check server is alive or restart ($n)" +ret=0 +$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + echo_i "restart ns3" + start_server --noclean --restart --port ${PORT} serve-stale ns3 +fi +status=$((status + ret)) + +############################################# +# Test for stale-answer-client-timeout 0. # +############################################# +echo_i "test stale-answer-client-timeout (0)" + +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named4.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "restart ns3" +stop_server --use-rndc --port ${CONTROLPORT} ns3 +start_server --noclean --restart --port ${PORT} ns3 + +n=$((n + 1)) +echo_i "prime cache data.example TXT (stale-answer-client-timeout 0)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache nodata.example TXT (stale-answer-client-timeout 0)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n + 1)) +ret=0 +echo_i "check stale nodata.example TXT comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "nodata.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1 +grep "example\..*3.*IN.*SOA" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +wait_for_rrset_refresh() { + $DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + grep "EDE" dig.out.test$n >/dev/null && return 1 + grep "ANSWER: 1," dig.out.test$n >/dev/null || return 1 + grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || return 1 +} + +# This test ensures that after we get stale data due to +# stale-answer-client-timeout 0, enabling the authoritative server will allow +# the RRset to be updated. +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0) ($n)" +retry_quiet 10 wait_for_rrset_refresh || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +wait_for_nodata_refresh() { + $DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || return 1 + grep "status: NOERROR" dig.out.test$n >/dev/null || return 1 + grep "ANSWER: 0," dig.out.test$n >/dev/null || return 1 + grep "example\..*[12].*IN.*SOA" dig.out.test$n >/dev/null || return 1 + return 0 +} + +n=$((n + 1)) +ret=0 +echo_i "check stale nodata.example TXT was refreshed (stale-answer-client-timeout 0) ($n)" +retry_quiet 10 wait_for_nodata_refresh || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +#################################################################### +# Test for stale-answer-client-timeout 0 and recursive-clients 10. # +# CVE-2023-2911, GL #4089 # +# ################################################################## +echo_i "test stale-answer-client-timeout (0) and recursive-clients 10" + +n=$((n + 1)) +echo_i "prime cache data.slow TXT (stale-answer-client-timeout 0) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.slow TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Run the following check twice. Sometimes a priming query interrupts the first +# attempt to exceed the quota. +attempt=0 +while [ $ret -eq 0 ] && [ $attempt -lt 2 ]; do + n=$((n + 1)) + echo_i "slow down response from authoritative server ($n)" + ret=0 + $DIG -p ${PORT} @10.53.0.2 slowdown TXT >dig.out.test$n || ret=1 + grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 + grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + # Let the data.slow TTL expire + sleep 2 + + n=$((n + 1)) + echo_i "check that named survives reaching recursive-clients quota (stale-answer-client-timeout 0) ($n)" + ret=0 + num=0 + # Attempt to exceed the configured value of 'recursive-clients 10;' by running + # 20 parallel queries for the stale domain which has slow auth. + while [ $num -lt 20 ]; do + $DIG +tries=1 +timeout=10 -p ${PORT} @10.53.0.3 data.slow TXT >/dev/null 2>&1 & + num=$((num + 1)) + done + # Let the dig processes finish. + wait + retry_quiet 5 check_server_responds || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + attempt=$((attempt + 1)) +done + +# Restart ns3 to avoid the exceeded recursive-clients limit from previous check +# to interfere with subsequent checks. +echo_i "restart ns3" +stop_server --use-rndc --port ${CONTROLPORT} ns3 +start_server --noclean --restart --port ${PORT} ns3 + +############################################################ +# Test for stale-answer-client-timeout 0 and CNAME record. # +############################################################ +echo_i "test stale-answer-client-timeout (0) and CNAME record" + +n=$((n + 1)) +echo_i "prime cache cname1.stale.test A (stale-answer-client-timeout 0) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "cname1\.stale\.test\..*1.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +grep "a1\.stale\.test\..*1.*IN.*A.*192\.0\.2\.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 1 + +n=$((n + 1)) +ret=0 +echo_i "check stale cname1.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A >dig.out.test$n || ret=1 +wait_for_log 5 "cname1.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "cname1\.stale\.test\..*3.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +grep "a1\.stale\.test\..*3.*IN.*A.*192\.0\.2\.1" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check server is alive or restart ($n)" +ret=0 +$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + echo_i "restart ns3" + start_server --noclean --restart --port ${PORT} ns3 +fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache cname2.stale.test A (stale-answer-client-timeout 0) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "cname2\.stale\.test\..*1.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +grep "a2\.stale\.test\..*300.*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow CNAME record in the RRSET to become stale. +sleep 1 + +n=$((n + 1)) +ret=0 +echo_i "check stale cname2.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1 +wait_for_log 5 "cname2.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1 +grep "cname2\.stale\.test\..*3.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1 +# We can't reliably test the TTL of the a2.stale.test A record. +grep "a2\.stale\.test\..*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check server is alive or restart ($n)" +ret=0 +$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then + echo_i "failed" + echo_i "restart ns3" + start_server --noclean --restart --port ${PORT} ns3 +fi +status=$((status + ret)) + +#################################################################### +# Test for stale-answer-client-timeout 0 and stale-refresh-time 4. # +#################################################################### +echo_i "test stale-answer-client-timeout (0) and stale-refresh-time (4)" + +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named5.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "flush cache, enable responses from authoritative server ($n)" +ret=0 +$RNDCCMD 10.53.0.3 flushtree example >rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "prime cache data.example TXT (stale-answer-client-timeout 0, stale-refresh-time 4) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# This test ensures that after we get stale data due to +# stale-answer-client-timeout 0, enabling the authoritative server will allow +# the RRset to be updated. +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +retry_quiet 10 wait_for_rrset_refresh || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow stale-refresh-time to be activated. +n=$((n + 1)) +ret=0 +echo_i "wait until resolver query times out, activating stale-refresh-time" +wait_for_log 15 "data.example/TXT stale refresh failed: timed out" ns3/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache within stale-refresh-time (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT query within stale refresh time" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# We give BIND some time to ensure that after we enable authoritative server, +# this RRset is still not refreshed because it was hit during +# stale-refresh-time window. +sleep 1 + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT was not refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT query within stale refresh time" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# After the refresh-time-window, the RRset will be refreshed. +sleep 4 + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE" dig.out.test$n >/dev/null && ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +#################################################################### +# Test serve-stale's interaction with fetch limits (cache only) # +################################################################# +echo_i "test serve-stale's interaction with fetch-limits (cache only)" + +# We update the named configuration to enable fetch-limits. The fetch-limits +# are set to 1, which is ridiciously low, but that is because for this test we +# want to reach the fetch-limits. +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named6.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Disable responses from authoritative server. If we can't resolve the example +# zone, fetch limits will be reached. +n=$((n + 1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Allow RRset to become stale. +sleep 2 + +# Turn on serve-stale. +n=$((n + 1)) +echo_i "running 'rndc serve-stale on' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale on || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Hit the fetch-limits. We burst the name server with a small batch of queries. +# Only 2 queries are required to hit the fetch-limits. The first query will +# start to resolve, the second one hit the fetch-limits. +burst() { + num=${1} + rm -f burst.input.$$ + while [ $num -gt 0 ]; do + num=$((num - 1)) + echo "fetch${num}.example A" >>burst.input.$$ + done + $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 -b ${EXTRAPORT8} burst.input.$$ + rm -f burst.input.$$ +} + +wait_for_fetchlimits() { + burst 2 + # We expect a query for nx.example to fail because fetch-limits for + # the domain 'example.' (and everything below) has been reached. + $DIG -p ${PORT} +tries=1 +timeout=1 @10.53.0.3 nx.example >dig.out.test$n || return 1 + grep "status: SERVFAIL" dig.out.test$n >/dev/null || return 1 +} + +n=$((n + 1)) +echo_i "hit fetch limits ($n)" +ret=0 +retry_quiet 10 wait_for_fetchlimits || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Expect stale data now (because fetch-limits for the domain 'example.' (and +# everything below) has been reached. But we have a stale RRset for +# 'data.example/TXT' that can be used. +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache (fetch-limits) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT resolver failure, stale answer used" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# The previous query should not have started the stale-refresh-time window. +n=$((n + 1)) +ret=0 +echo_i "check stale data.example TXT comes from cache again (fetch-limits) ($n)" +nextpart ns3/named.run >/dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1 +wait_for_log 5 "data.example TXT resolver failure, stale answer used" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +######################################################################## +# Test serve-stale's interaction with fetch limits (dual-mode) # +######################################################################## +echo_i "test serve-stale's interaction with fetch limits (dual-mode)" + +# Update named configuration so that ns3 becomes a recursive resolver which is +# also a secondary server for the root zone. +n=$((n + 1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named7.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Flush the cache to ensure the example/NS RRset cached during previous tests +# does not override the authoritative delegation found in the root zone. +n=$((n + 1)) +echo_i "flush cache ($n)" +ret=0 +$RNDCCMD 10.53.0.3 flush >rndc.out.test$n 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Test that after flush, serve-stale configuration is not reset. +n=$((n + 1)) +echo_i "check serve-stale configuration is not reset after flush ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1 +grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# Query name server with low fetch limits. The authoritative server (ans2) is +# not responding. Sending queries for multiple names in the 'example' zone +# in parallel causes the fetch limit for that zone (set to 1) to be +# reached. This should not trigger a crash. +echo_i "sending queries for tests $((n + 1))-$((n + 4))..." +$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) & +$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) & +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) & +$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) & + +wait + +# Expect SERVFAIL for the entries not in cache. +n=$((n + 1)) +echo_i "check stale data.example TXT (fetch-limits dual-mode) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale othertype.example CAA (fetch-limits dual-mode) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nodata.example TXT (fetch-limits dual-mode) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check stale nxdomain.example TXT (fetch-limits dual-mode) ($n)" +ret=0 +grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check DNS64 processing of a stale negative answer ($n)" +ret=0 +# configure ns3 with dns64 +copy_setports ns3/named8.conf.in ns3/named.conf +rndc_reload ns3 10.53.0.3 +# flush cache, enable ans2 responses, make sure serve-stale is on +$RNDCCMD 10.53.0.3 flush >rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1 +$RNDCCMD 10.53.0.3 serve-stale on >rndc.out.test$n.2 2>&1 || ret=1 +# prime the cache with an AAAA NXRRSET response +$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA >dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep "2001:aaaa" dig.out.1.test$n >/dev/null || ret=1 +# disable responses from the auth server +$DIG -p ${PORT} @10.53.0.2 txt disable >/dev/null || ret=1 +# wait two seconds for the previous answer to become stale +sleep 2 +# resend the query and wait in the background; we should get a stale answer +$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA >dig.out.2.test$n & +# re-enable queries after a pause, so the server gets a real answer too +sleep 2 +$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1 +wait +grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep "2001:aaaa" dig.out.2.test$n >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "check serve-stale (stale-answer-client-timeout 0) with a delegation ($n)" +ret=0 +# configure ns3 with stale-answer-client-timeout 0 and a delegated zone +copy_setports ns3/named9.conf.in ns3/named.conf +rndc_reload ns3 10.53.0.3 +# flush cache, enable ans2 responses, make sure serve-stale is on +$RNDCCMD 10.53.0.3 flush >rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1 +$RNDCCMD 10.53.0.3 serve-stale on >rndc.out.test$n.2 2>&1 || ret=1 +# prime the cache with the A response +$DIG -p ${PORT} @10.53.0.3 www.delegated.serve.stale >dig.out.1.test$n || ret=1 +grep -F "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1 +grep -F "10.53.0.99" dig.out.1.test$n >/dev/null || ret=1 +# disable responses from the auth server +$DIG -p ${PORT} @10.53.0.2 txt disable >/dev/null || ret=1 +# wait two seconds for the previous answer to become stale +sleep 2 +# resend the query; we should immediately get a stale answer +$DIG -p ${PORT} @10.53.0.3 www.delegated.serve.stale >dig.out.2.test$n || ret=1 +grep -F "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1 +grep -F "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.2.test$n >/dev/null || ret=1 +grep -F "10.53.0.99" dig.out.2.test$n >/dev/null || ret=1 +# re-enable responses +$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/serve-stale/tests_sh_serve_stale.py b/bin/tests/system/serve-stale/tests_sh_serve_stale.py new file mode 100644 index 0000000..18b84e8 --- /dev/null +++ b/bin/tests/system/serve-stale/tests_sh_serve_stale.py @@ -0,0 +1,28 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "ans*/ans.run", + "ns*/named.stats*", + "ns*/named_dump*", + "ns*/named.stats*", + "ns*/root.bk", + ] +) + + +def test_serve_stale(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/sfcache/README b/bin/tests/system/sfcache/README new file mode 100644 index 0000000..91b2126 --- /dev/null +++ b/bin/tests/system/sfcache/README @@ -0,0 +1,19 @@ +Copyright (C) Internet Systems Consortium, Inc. ("ISC") + +SPDX-License-Identifier: MPL-2.0 + +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 https://mozilla.org/MPL/2.0/. + +See the COPYRIGHT file distributed with this work for additional +information regarding copyright ownership. + +The test setup for the SERVFAIL ncache tests has a secure root. + +ns1 is the root server. + +ns2 is an authoritative server for the various test domains. + +ns5 is a caching-only server, configured with the an incorrect trusted +key for the root. It is used for testing failure cases. diff --git a/bin/tests/system/sfcache/ns1/named.conf.in b/bin/tests/system/sfcache/ns1/named.conf.in new file mode 100644 index 0000000..4a9822d --- /dev/null +++ b/bin/tests/system/sfcache/ns1/named.conf.in @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS1 + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/sfcache/ns1/root.db.in b/bin/tests/system/sfcache/ns1/root.db.in new file mode 100644 index 0000000..1deb998 --- /dev/null +++ b/bin/tests/system/sfcache/ns1/root.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 +example2. NS ns2.example2. +ns2.example2. A 10.53.0.2 diff --git a/bin/tests/system/sfcache/ns1/sign.sh b/bin/tests/system/sfcache/ns1/sign.sh new file mode 100644 index 0000000..04414d2 --- /dev/null +++ b/bin/tests/system/sfcache/ns1/sign.sh @@ -0,0 +1,38 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +zone=. +infile=root.db.in +zonefile=root.db + +(cd ../ns2 && $SHELL sign.sh) + +cp "../ns2/dsset-example." . + +keyname=$($KEYGEN -q -a "${DEFAULT_ALGORITHM}" -b "${DEFAULT_BITS}" -n zone $zone) + +cat "$infile" "$keyname.key" >"$zonefile" + +$SIGNER -P -g -o $zone $zonefile >/dev/null + +# Configure the resolving server with a static key. +keyfile_to_static_ds "$keyname" >trusted.conf +cp trusted.conf ../ns2/trusted.conf + +# ...or with an initializing key. +keyfile_to_initial_ds "$keyname" >managed.conf diff --git a/bin/tests/system/sfcache/ns2/example.db.in b/bin/tests/system/sfcache/ns2/example.db.in new file mode 100644 index 0000000..c035ee8 --- /dev/null +++ b/bin/tests/system/sfcache/ns2/example.db.in @@ -0,0 +1,103 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 + +; Used for testing ANY queries +foo TXT "testing" +foo A 10.0.1.0 + +bad-cname CNAME a +bad-dname DNAME @ + +; Used for testing CNAME queries +cname1 CNAME cname1-target +cname1-target TXT "testing cname" + +cname2 CNAME cname2-target +cname2-target TXT "testing cname" + +; Used for testing DNAME queries +dname1 DNAME dname1-target +foo.dname1-target TXT "testing dname" + +dname2 DNAME dname2-target +foo.dname2-target TXT "testing dname" + +; A secure subdomain +secure NS ns.secure +ns.secure A 10.53.0.3 + +; An insecure subdomain +insecure NS ns.insecure +ns.insecure A 10.53.0.3 + +; A secure subdomain we're going to inject bogus data into +bogus NS ns.bogus +ns.bogus A 10.53.0.3 + +; A dynamic secure subdomain +dynamic NS dynamic +dynamic A 10.53.0.3 + +; A insecure subdomain +mustbesecure NS ns.mustbesecure +ns.mustbesecure A 10.53.0.3 + +; A rfc2535 signed zone w/ CNAME +rfc2535 NS ns.rfc2535 +ns.rfc2535 A 10.53.0.3 + +z A 10.0.0.26 + +keyless NS ns.keyless +ns.keyless A 10.53.0.3 + +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 + +optout NS ns.optout +ns.optout A 10.53.0.3 + +nsec3-unknown NS ns.nsec3-unknown +ns.nsec3-unknown A 10.53.0.3 + +optout-unknown NS ns.optout-unknown +ns.optout-unknown A 10.53.0.3 + +multiple NS ns.multiple +ns.multiple A 10.53.0.3 + +*.wild A 10.0.0.27 + +rsasha256 NS ns.rsasha256 +ns.rsasha256 A 10.53.0.3 + +rsasha512 NS ns.rsasha512 +ns.rsasha512 A 10.53.0.3 + +kskonly NS ns.kskonly +ns.kskonly A 10.53.0.3 diff --git a/bin/tests/system/sfcache/ns2/named.conf.in b/bin/tests/system/sfcache/ns2/named.conf.in new file mode 100644 index 0000000..7052ac6 --- /dev/null +++ b/bin/tests/system/sfcache/ns2/named.conf.in @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + recursion no; + notify yes; + dnssec-validation yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "example" { + type primary; + file "example.db.signed"; + allow-update { any; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/sfcache/ns2/sign.sh b/bin/tests/system/sfcache/ns2/sign.sh new file mode 100644 index 0000000..2f85059 --- /dev/null +++ b/bin/tests/system/sfcache/ns2/sign.sh @@ -0,0 +1,28 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +zone=example. +infile=example.db.in +zonefile=example.db + +keyname1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +keyname2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -P -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null diff --git a/bin/tests/system/sfcache/ns5/named.conf.in b/bin/tests/system/sfcache/ns5/named.conf.in new file mode 100644 index 0000000..36bfb96 --- /dev/null +++ b/bin/tests/system/sfcache/ns5/named.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + servfail-ttl 30; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/sfcache/ns5/sign.sh b/bin/tests/system/sfcache/ns5/sign.sh new file mode 100644 index 0000000..7d70bea --- /dev/null +++ b/bin/tests/system/sfcache/ns5/sign.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../../conf.sh + +set -e + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".") + +keyfile_to_static_ds "$keyname" >trusted.conf diff --git a/bin/tests/system/sfcache/setup.sh b/bin/tests/system/sfcache/setup.sh new file mode 100644 index 0000000..a51b814 --- /dev/null +++ b/bin/tests/system/sfcache/setup.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +copy_setports ns1/named.conf.in ns1/named.conf +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns5/named.conf.in ns5/named.conf + +cd ns1 && $SHELL sign.sh && cd .. +cd ns5 && $SHELL sign.sh && cd .. diff --git a/bin/tests/system/sfcache/tests.sh b/bin/tests/system/sfcache/tests.sh new file mode 100644 index 0000000..a01b269 --- /dev/null +++ b/bin/tests/system/sfcache/tests.sh @@ -0,0 +1,107 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +# shellcheck source=conf.sh +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +dig_with_opts() { + "$DIG" +tcp +noadd +nosea +nostat +nocmd -p "$PORT" "$@" +} + +rndc_with_opts() { + "$RNDC" -c ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" +} + +echo_i "checking DNSSEC SERVFAIL is cached ($n)" +ret=0 +dig_with_opts +dnssec foo.example. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +rndc_dumpdb ns5 -all +awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db.test$n >sfcache.$n +grep "^; foo.example/A" sfcache.$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking SERVFAIL is returned from cache ($n)" +ret=0 +dig_with_opts +dnssec foo.example. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking that +cd bypasses cache check ($n)" +ret=0 +dig_with_opts +dnssec +cd foo.example. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "switching to non-dnssec SERVFAIL tests" +ret=0 +rndc_with_opts 10.53.0.5 flush 2>&1 | sed 's/^/I:ns5 /' +rndc_dumpdb ns5 -all +mv ns5/named_dump.db.test$n ns5/named_dump.db.test$n.1 +awk '/SERVFAIL/ { next; out=1 } /Zone/ { out=0 } { if (out) print }' ns5/named_dump.db.test$n.1 >sfcache.$n.1 +[ -s "sfcache.$n.1" ] && ret=1 +echo_i "checking SERVFAIL is cached ($n)" +dig_with_opts bar.example2. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +rndc_dumpdb ns5 -all +mv ns5/named_dump.db.test$n ns5/named_dump.db.test$n.2 +awk '/Zone/{out=0} { if (out) print } /SERVFAIL/{out=1}' ns5/named_dump.db.test$n.2 >sfcache.$n.2 +grep "^; bar.example2/A" sfcache.$n.2 >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking SERVFAIL is returned from cache ($n)" +ret=0 +nextpart ns5/named.run >/dev/null +dig_with_opts bar.example2. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +nextpart ns5/named.run >ns5/named.run.part$n +grep 'servfail cache hit bar.example2/A (CD=0)' ns5/named.run.part$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking cache is bypassed with +cd query ($n)" +ret=0 +dig_with_opts +cd bar.example2. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +nextpart ns5/named.run >ns5/named.run.part$n +grep 'servfail cache hit' ns5/named.run.part$n >/dev/null && ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking cache is used for subsequent +cd query ($n)" +ret=0 +dig_with_opts +dnssec bar.example2. a @10.53.0.5 >dig.out.ns5.test$n || ret=1 +grep "SERVFAIL" dig.out.ns5.test$n >/dev/null || ret=1 +nextpart ns5/named.run >ns5/named.run.part$n +grep 'servfail cache hit bar.example2/A (CD=1)' ns5/named.run.part$n >/dev/null || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/sfcache/tests_sh_sfcache.py b/bin/tests/system/sfcache/tests_sh_sfcache.py new file mode 100644 index 0000000..043c526 --- /dev/null +++ b/bin/tests/system/sfcache/tests_sh_sfcache.py @@ -0,0 +1,33 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "dig.out.*", + "rndc.out.*", + "sfcache.*", + "ns*/*.db", + "ns*/*.signed", + "ns*/dsset-*", + "ns*/K*.key", + "ns*/K*.private", + "ns*/managed.conf", + "ns*/trusted.conf", + "ns5/named.run.*", + "ns5/named_dump*", + ] +) + + +def test_sfcache(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/shutdown/ns1/named.conf.j2 b/bin/tests/system/shutdown/ns1/named.conf.j2 new file mode 100644 index 0000000..f0f5210 --- /dev/null +++ b/bin/tests/system/shutdown/ns1/named.conf.j2 @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + listen-on { 10.53.0.1; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; + recursion yes; + allow-recursion { any; }; +}; + +# Delegate .test domain to 10.53.0.2 +zone "." { + type primary; + file "root.db"; + allow-transfer { none; }; +}; diff --git a/bin/tests/system/shutdown/ns1/root.db b/bin/tests/system/shutdown/ns1/root.db new file mode 100644 index 0000000..60f1b30 --- /dev/null +++ b/bin/tests/system/shutdown/ns1/root.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +@ IN SOA a.root. root.test. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) + +. IN NS a.root. +a.root. IN A 10.53.0.1 + +test IN NS ns1.test +ns1.test IN A 10.53.0.2 diff --git a/bin/tests/system/shutdown/ns2/named.conf.j2 b/bin/tests/system/shutdown/ns2/named.conf.j2 new file mode 100644 index 0000000..2ed91dc --- /dev/null +++ b/bin/tests/system/shutdown/ns2/named.conf.j2 @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + listen-on { 10.53.0.2; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; +}; + +# 10.53.0.2 is authoritative for .test domain +zone "test" { + type primary; + file "test.db"; + allow-transfer { none; }; +}; diff --git a/bin/tests/system/shutdown/ns2/test.db b/bin/tests/system/shutdown/ns2/test.db new file mode 100644 index 0000000..91c16ec --- /dev/null +++ b/bin/tests/system/shutdown/ns2/test.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 + +@ IN SOA ns1 root.test. 2020040101 4h 1h 1w 60 +@ IN NS ns1 +ns1 IN A 10.53.0.2 +@ IN A 10.53.0.2 +www IN A 10.53.0.2 diff --git a/bin/tests/system/shutdown/resolver/named.conf.j2 b/bin/tests/system/shutdown/resolver/named.conf.j2 new file mode 100644 index 0000000..5007579 --- /dev/null +++ b/bin/tests/system/shutdown/resolver/named.conf.j2 @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +logging { + channel basic { + file "named.run"; + severity debug 999; + print-time yes; + }; + category default { basic; }; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + listen-on { 10.53.0.3; }; + pid-file "named.pid"; + notify no; + dnssec-validation no; + allow-query { any; }; + allow-recursion { any; }; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/shutdown/resolver/root.db b/bin/tests/system/shutdown/resolver/root.db new file mode 100644 index 0000000..88e0ba8 --- /dev/null +++ b/bin/tests/system/shutdown/resolver/root.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA a.root. root.root. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. IN NS a.root. +a.root. IN A 10.53.0.1 diff --git a/bin/tests/system/shutdown/tests_shutdown.py b/bin/tests/system/shutdown/tests_shutdown.py new file mode 100755 index 0000000..bbfab34 --- /dev/null +++ b/bin/tests/system/shutdown/tests_shutdown.py @@ -0,0 +1,192 @@ +#!/usr/bin/python3 + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +from concurrent.futures import ThreadPoolExecutor, as_completed +import os +import random +import signal +import subprocess +from string import ascii_lowercase as letters +import time + +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import dns.exception + +import isctest + +pytestmark = pytest.mark.extra_artifacts( + [ + "resolver/named.conf", + "resolver/named.run", + ] +) + + +def do_work(named_proc, resolver_ip, instance, kill_method, n_workers, n_queries): + """Creates a number of A queries to run in parallel + in order simulate a slightly more realistic test scenario. + + The main idea of this function is to create and send a bunch + of A queries to a target named instance and during this process + a request for shutting down named will be issued. + + In the process of shutting down named, a couple control connections + are created (by launching rndc) to ensure that the crash was fixed. + + if kill_method=="rndc" named will be asked to shutdown by + means of rndc stop. + if kill_method=="sigterm" named will be killed by SIGTERM on + POSIX systems. + + :param named_proc: named process instance + :type named_proc: subprocess.Popen + + :param resolver_ip: target resolver's IP address + :type resolver_ip: str + + :param instance: the named instance to send RNDC commands to + :type instance: isctest.instance.NamedInstance + + :kill_method: "rndc" or "sigterm" + :type kill_method: str + + :param n_workers: Number of worker threads to create + :type n_workers: int + + :param n_queries: Total number of queries to send + :type n_queries: int + """ + + # helper function, 'command' is the rndc command to run + def launch_rndc(command): + try: + instance.rndc(command, log=False) + return 0 + except isctest.rndc.RNDCException: + return -1 + + # We're going to execute queries in parallel by means of a thread pool. + # dnspython functions block, so we need to circumvent that. + with ThreadPoolExecutor(n_workers + 1) as executor: + # Helper dict, where keys=Future objects and values are tags used + # to process results later. + futures = {} + + # 50% of work will be A queries. + # 1 work will be rndc stop. + # Remaining work will be rndc status (so we test parallel control + # connections that were crashing named). + shutdown = True + for i in range(n_queries): + if i < (n_queries // 2): + # Half work will be standard A queries. + # Among those we split 50% queries relname='www', + # 50% queries relname=random characters + if random.randrange(2) == 1: + tag = "good" + relname = "www" + else: + tag = "bad" + length = random.randint(4, 10) + relname = "".join( + letters[random.randrange(len(letters))] for i in range(length) + ) + + qname = relname + ".test" + msg = dns.message.make_query(qname, "A") + futures[ + executor.submit( + isctest.query.udp, msg, resolver_ip, timeout=1, attempts=1 + ) + ] = tag + elif shutdown: # We attempt to stop named in the middle + shutdown = False + if kill_method == "rndc": + futures[executor.submit(launch_rndc, "stop")] = "stop" + else: + futures[executor.submit(named_proc.terminate)] = "kill" + else: + # We attempt to send couple rndc commands while named is + # being shutdown + futures[executor.submit(launch_rndc, "-t 5 status")] = "status" + + ret_code = -1 + for future in as_completed(futures): + try: + result = future.result() + # If tag is "stop", result is an instance of + # subprocess.CompletedProcess, then we check returncode + # attribute to know if rncd stop command finished successfully. + # + # if tag is "kill" then the main function will check if + # named process exited gracefully after SIGTERM signal. + if futures[future] == "stop": + ret_code = result + except dns.exception.Timeout: + pass + + if kill_method == "rndc": + assert ret_code == 0 + + +def wait_for_proc_termination(proc, max_timeout=10): + for _ in range(max_timeout): + if proc.poll() is not None: + return True + time.sleep(1) + + proc.send_signal(signal.SIGABRT) + for _ in range(max_timeout): + if proc.poll() is not None: + return True + time.sleep(1) + + return False + + +# We test named shutting down using two methods: +# Method 1: using rndc ctop +# Method 2: killing with SIGTERM +# In both methods named should exit gracefully. +@pytest.mark.parametrize( + "kill_method", + ["rndc", "sigterm"], +) +def test_named_shutdown(kill_method): + resolver_ip = "10.53.0.3" + + cfg_dir = "resolver" + + named_cmdline = isctest.run.get_named_cmdline(cfg_dir) + instance = isctest.instance.NamedInstance("resolver", num=3) + + with open(os.path.join(cfg_dir, "named.run"), "ab") as named_log: + with subprocess.Popen( + named_cmdline, cwd=cfg_dir, stderr=named_log + ) as named_proc: + try: + isctest.check.named_alive(named_proc, resolver_ip) + do_work( + named_proc, + resolver_ip, + instance, + kill_method, + n_workers=12, + n_queries=16, + ) + assert wait_for_proc_termination(named_proc) + assert named_proc.returncode == 0, "named crashed" + finally: # Ensure named is terminated in case of an exception + named_proc.kill() diff --git a/bin/tests/system/smartsign/child.db b/bin/tests/system/smartsign/child.db new file mode 100644 index 0000000..878df45 --- /dev/null +++ b/bin/tests/system/smartsign/child.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 60 ; 1 minute +child.parent.nil IN SOA ns.child.parent.nil. hostmaster.parent.nil. ( + 1 ; serial + 2000 ; refresh (33 minutes 20 seconds) + 2000 ; retry (33 minutes 20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns.child.parent.nil. +$ORIGIN child.parent.nil. +$TTL 300 ; 5 minutes +ns A 10.53.0.3 diff --git a/bin/tests/system/smartsign/parent.db b/bin/tests/system/smartsign/parent.db new file mode 100644 index 0000000..a5484e3 --- /dev/null +++ b/bin/tests/system/smartsign/parent.db @@ -0,0 +1,31 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 ; 5 minutes +parent.nil IN SOA ns1.parent.nil. hostmaster.parent.nil. ( + 1 ; serial + 2000 ; refresh (33 minutes 20 seconds) + 2000 ; retry (33 minutes 20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns1.parent.nil. + NS ns2.parent.nil. +$ORIGIN parent.nil. +$TTL 3600 ; 1 hour +a A 1.1.1.1 +$TTL 300 ; 5 minutes +ns1 A 10.53.0.1 +ns2 A 10.53.0.2 + +child NS ns.child +ns.child A 10.53.0.3 diff --git a/bin/tests/system/smartsign/tests.sh b/bin/tests/system/smartsign/tests.sh new file mode 100644 index 0000000..70a4dc7 --- /dev/null +++ b/bin/tests/system/smartsign/tests.sh @@ -0,0 +1,420 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 + +pzone=parent.nil +pfile=parent.db + +czone=child.parent.nil +cfile=child.db + +echo_i "generating child's keys" +# active zsk +czsk1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -L 30 $czone) + +# not yet published or active +czsk2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P none -A none $czone) + +# published but not active +czsk3=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -A none $czone) + +# inactive +czsk4=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now-24h -A now-24h -I now $czone) + +# active in 12 hours, inactive 12 hours after that... +czsk5=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -P now+12h -A now+12h -I now+24h $czone) + +# explicit successor to czk5 +# (suppressing warning about lack of removal date) +czsk6=$($KEYGEN -q -S $czsk5 -i 6h 2>/dev/null) + +# active ksk +cksk1=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -L 30 $czone) + +# published but not YET active; will be active in 20 seconds +cksk2=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone) +# $SETTIME moved after other $KEYGENs + +echo_i "revoking key" +# revoking key changes its ID +cksk3=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $czone) +cksk4=$($REVOKE $cksk3) + +echo_i "setting up sync key" +cksk5=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -P now+1mo -A now+1mo -Psync now $czone) + +echo_i "and future sync key" +cksk6=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk -P now+1mo -A now+1mo -Psync now+1mo $czone) + +echo_i "generating parent keys" +pzsk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} $pzone) +pksk=$($KEYGEN -q -a ${DEFAULT_ALGORITHM} -fk $pzone) + +echo_i "setting child's activation time" +# using now+30s to fix RT 24561 +$SETTIME -A now+30s $cksk2 >/dev/null + +echo_i "signing child zone" +czoneout=$($SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile) + +echo_i "signing parent zone" +pzoneout=$($SIGNER -Sg -o $pzone $pfile) + +czactive=$(keyfile_to_key_id $czsk1) +czgenerated=$(keyfile_to_key_id $czsk2) +czpublished=$(keyfile_to_key_id $czsk3) +czinactive=$(keyfile_to_key_id $czsk4) +czpredecessor=$(keyfile_to_key_id $czsk5) +czsuccessor=$(keyfile_to_key_id $czsk6) +ckactive=$(keyfile_to_key_id $cksk1) +ckpublished=$(keyfile_to_key_id $cksk2) +ckprerevoke=$(keyfile_to_key_id $cksk3) +ckrevoked=$(keyfile_to_key_id $cksk4) + +pzid=$(keyfile_to_key_id $pzsk) +pkid=$(keyfile_to_key_id $pksk) + +echo_i "checking dnssec-signzone output matches expectations" +ret=0 +echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' >/dev/null || ret=1 +echo "$pzoneout" | grep 'ZSKs: 1 active, 0 stand-by, 0 revoked' >/dev/null || ret=1 +echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' >/dev/null || ret=1 +echo "$czoneout" | grep 'ZSKs: 1 active, 2 stand-by, 0 revoked' >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "parent $pzoneout" + echo_i "child $czoneout" + echo_i "failed" +fi +status=$((status + ret)) + +echo_i "rechecking dnssec-signzone output with -x" +ret=0 +# use an alternate output file so -x doesn't interfere with later checks +pzoneout=$($SIGNER -Sxg -o $pzone -f ${pfile}2.signed $pfile) +czoneout=$($SIGNER -Sxg -e now+1d -X now+2d -o $czone -f ${cfile}2.signed $cfile) +echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' >/dev/null || ret=1 +echo "$pzoneout" | grep 'ZSKs: 1 active, 0 present, 0 revoked' >/dev/null || ret=1 +echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' >/dev/null || ret=1 +echo "$czoneout" | grep 'ZSKs: 1 active, 2 present, 0 revoked' >/dev/null || ret=1 +if [ $ret != 0 ]; then + echo_i "parent $pzoneout" + echo_i "child $czoneout" + echo_i "failed" +fi +status=$((status + ret)) + +echo_i "checking parent zone DNSKEY set" +ret=0 +grep "key id = $pzid" $pfile.signed >/dev/null || { + ret=1 + echo_i "missing expected parent ZSK id = $pzid" +} +grep "key id = $pkid" $pfile.signed >/dev/null || { + ret=1 + echo_i "missing expected parent KSK id = $pkid" +} +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking parent zone DS records" +ret=0 +awk '$2 == "DS" {print $3}' $pfile.signed >dsset.out +grep -w "$ckactive" dsset.out >/dev/null || ret=1 +grep -w "$ckpublished" dsset.out >/dev/null || ret=1 +# revoked key should not be there, hence the && +grep -w "$ckprerevoke" dsset.out >/dev/null && ret=1 +grep -w "$ckrevoked" dsset.out >/dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking child zone DNSKEY set" +ret=0 +grep "key id = $ckactive\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child KSK id = $ckactive" +} +grep "key id = $ckpublished\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child prepublished KSK id = $ckpublished" +} +grep "key id = $ckrevoked\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child revoked KSK id = $ckrevoked" +} +grep "key id = $czactive\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child ZSK id = $czactive" +} +grep "key id = $czpublished\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child prepublished ZSK id = $czpublished" +} +grep "key id = $czinactive\$" $cfile.signed >/dev/null || { + ret=1 + echo_i "missing expected child inactive ZSK id = $czinactive" +} +# should not be there, hence the && +grep "key id = $ckprerevoke\$" $cfile.signed >/dev/null && { + ret=1 + echo_i "found unexpected child pre-revoke ZSK id = $ckprerevoke" +} +grep "key id = $czgenerated\$" $cfile.signed >/dev/null && { + ret=1 + echo_i "found unexpected child generated ZSK id = $czgenerated" +} +grep "key id = $czpredecessor\$" $cfile.signed >/dev/null && { + echo_i "found unexpected ZSK predecessor id = $czpredecessor (ignored)" +} +grep "key id = $czsuccessor\$" $cfile.signed >/dev/null && { + echo_i "found unexpected ZSK successor id = $czsuccessor (ignored)" +} +#grep "key id = $czpredecessor\$" $cfile.signed > /dev/null && ret=1 +#grep "key id = $czsuccessor\$" $cfile.signed > /dev/null && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking key TTLs are correct" +ret=0 +grep "${czone}. 30 IN" ${czsk1}.key >/dev/null 2>&1 || ret=1 +grep "${czone}. 30 IN" ${cksk1}.key >/dev/null 2>&1 || ret=1 +grep "${czone}. IN" ${czsk2}.key >/dev/null 2>&1 || ret=1 +$SETTIME -L 45 ${czsk2} >/dev/null +grep "${czone}. 45 IN" ${czsk2}.key >/dev/null 2>&1 || ret=1 +$SETTIME -L 0 ${czsk2} >/dev/null +grep "${czone}. IN" ${czsk2}.key >/dev/null 2>&1 || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking key TTLs were imported correctly" +ret=0 +awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 30 {r = 1} END {exit r}' \ + ${cfile}.signed || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "re-signing and checking imported TTLs again" +ret=0 +$SETTIME -L 15 ${czsk2} >/dev/null +czoneout=$($SIGNER -Sg -e now+1d -X now+2d -o $czone $cfile) +awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 15 {r = 1} END {exit r}' \ + ${cfile}.signed || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# There is some weirdness in Solaris 10 (Generic_120011-14), which +# is why the next section has all those echo $ret > /dev/null;sync +# commands +echo_i "checking child zone signatures" +ret=0 +# check DNSKEY signatures first +awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed >dnskey.sigs +sub=0 +grep -w "$ckactive" dnskey.sigs >/dev/null || sub=1 +if [ $sub != 0 ]; then + echo_i "missing ckactive $ckactive (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckrevoked" dnskey.sigs >/dev/null || sub=1 +if [ $sub != 0 ]; then + echo_i "missing ckrevoke $ckrevoke (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czactive" dnskey.sigs >/dev/null || sub=1 +if [ $sub != 0 ]; then + echo_i "missing czactive $czactive (dnskey)" + ret=1 +fi +# should not be there: +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckprerevoke" dnskey.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckprerevoke $ckprerevoke (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckpublished" dnskey.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckpublished $ckpublished (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czpublished" dnskey.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czpublished $czpublished (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czinactive" dnskey.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czinactive $czinactive (dnskey)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czgenerated" dnskey.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czgenerated $czgenerated (dnskey)" + ret=1 +fi +# now check other signatures first +awk '$2 == "RRSIG" && $3 != "DNSKEY" && $3 != "CDNSKEY" && $3 != "CDS" { getline; print $3 }' $cfile.signed | sort -un >other.sigs +# should not be there: +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckactive" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckactive $ckactive (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckpublished" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckpublished $ckpublished (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckprerevoke" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckprerevoke $ckprerevoke (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$ckrevoked" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found ckrevoked $ckrevoked (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czpublished" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czpublished $czpublished (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czinactive" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czinactive $czinactive (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czgenerated" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czgenerated $czgenerated (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czpredecessor" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czpredecessor $czpredecessor (other)" + ret=1 +fi +echo $ret >/dev/null +sync +sub=0 +grep -w "$czsuccessor" other.sigs >/dev/null && sub=1 +if [ $sub != 0 ]; then + echo_i "found czsuccessor $czsuccessor (other)" + ret=1 +fi +if [ $ret != 0 ]; then + sed 's/^/I:dnskey sigs: /' /dev/null \ + | awk '$4 == "RRSIG" && $5 == "DNSKEY" {print $9; exit}' \ + | cut -c1-10) +soa_expiry=$($CHECKZONE -o - $czone $cfile.signed 2>/dev/null \ + | awk '$4 == "RRSIG" && $5 == "SOA" {print $9; exit}' \ + | cut -c1-10) +[ $dnskey_expiry -gt $soa_expiry ] || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "waiting 30 seconds for key activation" +sleep 30 +echo_i "re-signing child zone" +czoneout2=$($SIGNER -Sg -o $czone -f $cfile.new $cfile.signed) +mv $cfile.new $cfile.signed + +echo_i "checking dnssec-signzone output matches expectations" +ret=0 +echo "$czoneout2" | grep 'KSKs: 2 active, 0 stand-by, 1 revoked' >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking child zone signatures again" +ret=0 +awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed >dnskey.sigs +grep -w "$ckpublished" dnskey.sigs >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "checking sync record publication" +ret=0 +awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed || ret=1 +awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +# this also checks that the future sync record is not yet published +echo_i "checking sync record deletion" +ret=0 +$SETTIME -P now -A now -Dsync now ${cksk5} >/dev/null +$SIGNER -Sg -o $czone -f $cfile.new $cfile.signed >/dev/null +mv $cfile.new $cfile.signed +awk 'BEGIN { r=1 } $2 == "CDNSKEY" { r=0 } END { exit r }' $cfile.signed && ret=1 +awk 'BEGIN { r=1 } $2 == "CDS" { r=0 } END { exit r }' $cfile.signed && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/smartsign/tests_sh_smartsign.py b/bin/tests/system/smartsign/tests_sh_smartsign.py new file mode 100644 index 0000000..68b0bf4 --- /dev/null +++ b/bin/tests/system/smartsign/tests_sh_smartsign.py @@ -0,0 +1,27 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "*.signed", + "K*", + "dnskey.sigs", + "dsset-*", + "dsset.out", + "other.sigs", + ] +) + + +def test_smartsign(run_tests_sh): + run_tests_sh() diff --git a/bin/tests/system/sortlist/ns1/example.db b/bin/tests/system/sortlist/ns1/example.db new file mode 100644 index 0000000..b68e215 --- /dev/null +++ b/bin/tests/system/sortlist/ns1/example.db @@ -0,0 +1,37 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 ; 5 minutes +@ IN SOA ns1.example. hostmaster.example. ( + 2000042795 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +example. NS ns1.example. +ns1.example. A 10.53.0.1 + +; Let's see what the sortlist picks out of this... +a A 1.1.1.1 +a A 1.1.1.5 +a A 1.1.1.2 +a A 192.168.3.1 +a A 1.1.1.3 +a A 192.168.1.1 +a A 1.1.1.4 + +b A 10.53.0.1 +b A 10.53.0.2 +b A 10.53.0.3 +b A 10.53.0.4 +b A 10.53.0.5 + diff --git a/bin/tests/system/sortlist/ns1/named.conf.in b/bin/tests/system/sortlist/ns1/named.conf.in new file mode 100644 index 0000000..1a0b3ad --- /dev/null +++ b/bin/tests/system/sortlist/ns1/named.conf.in @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; + + sortlist { + { 10.53.0.1; // IF 10.53.0.1 + { + !1.1.1.4; !1.1.1.2; !1.1.1.3; !1.1.1.1; // sort these last, + 192.168.3/24; // this first + { 192.168.2/24; 192.168.1/24; }; }; }; // and these next + { { 10.53.0.2; 10.53.0.3; }; }; // Prefer self + 10.53.0.4; // BIND 8 compat + { 10.53.0.5; 10.53.0.5; }; // BIND 8 compat + }; +}; + +zone "." { + type primary; + file "root.db"; +}; + +zone "example" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/sortlist/ns1/root.db b/bin/tests/system/sortlist/ns1/root.db new file mode 100644 index 0000000..17780d1 --- /dev/null +++ b/bin/tests/system/sortlist/ns1/root.db @@ -0,0 +1,24 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/sortlist/setup.sh b/bin/tests/system/sortlist/setup.sh new file mode 100644 index 0000000..82240a7 --- /dev/null +++ b/bin/tests/system/sortlist/setup.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf diff --git a/bin/tests/system/sortlist/tests_sortlist.py b/bin/tests/system/sortlist/tests_sortlist.py new file mode 100644 index 0000000..f5c68c8 --- /dev/null +++ b/bin/tests/system/sortlist/tests_sortlist.py @@ -0,0 +1,53 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns.message + +import pytest + +import isctest + + +def test_sortlist(): + """Test two-element sortlist statement""" + msg = dns.message.make_query("a.example.", "A") + resp = isctest.query.tcp(msg, "10.53.0.1", source="10.53.0.1") + sortlist = [ + "192.168.3.1", + "192.168.1.1", + "1.1.1.5", + "1.1.1.1", + "1.1.1.3", + "1.1.1.2", + "1.1.1.4", + ] + rrset = dns.rrset.from_text_list("a.example.", 300, "IN", "A", sortlist) + assert len(resp.answer) == 1 + assert resp.answer[0] == rrset + assert list(resp.answer[0].items) == list(rrset.items) + + +@pytest.mark.parametrize( + "source_ip,possible_results", + [ + ("10.53.0.2", ["10.53.0.2", "10.53.0.3"]), + ("10.53.0.3", ["10.53.0.2", "10.53.0.3"]), + ("10.53.0.4", ["10.53.0.4"]), + ("10.53.0.5", ["10.53.0.5"]), + ], +) +def test_sortlist_compat(possible_results, source_ip): + """Test one-element sortlist statement and undocumented BIND 8 features""" + msg = dns.message.make_query("b.example.", "A") + resp = isctest.query.tcp(msg, "10.53.0.1", source=source_ip) + assert ( + resp.answer[0][0].to_text() in possible_results + ), f"{possible_results} not found" diff --git a/bin/tests/system/spf/ns1/named.conf.j2 b/bin/tests/system/spf/ns1/named.conf.j2 new file mode 100644 index 0000000..d25251a --- /dev/null +++ b/bin/tests/system/spf/ns1/named.conf.j2 @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion no; + dnssec-validation no; + notify yes; + ixfr-from-differences yes; +}; + +zone "spf" { + type primary; + file "spf.db"; +}; + +zone "warn" { + type primary; + file "spf.db"; + check-spf warn; +}; + +zone "nowarn" { + type primary; + file "spf.db"; + check-spf ignore; +}; diff --git a/bin/tests/system/spf/ns1/spf.db b/bin/tests/system/spf/ns1/spf.db new file mode 100644 index 0000000..9527b1b --- /dev/null +++ b/bin/tests/system/spf/ns1/spf.db @@ -0,0 +1,18 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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 https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +@ 0 IN SOA . . 0 0 0 0 0 +@ 0 IN NS . +@ 0 IN TXT "v=spf1 -all" +@ 0 IN SPF "v=spf1 -all" +x 0 IN TXT "v=spf1" +y 0 IN SPF "v=spf1" +y 0 IN TXT "a non spf record" diff --git a/bin/tests/system/spf/tests_spf_zones.py b/bin/tests/system/spf/tests_spf_zones.py new file mode 100644 index 0000000..550704b --- /dev/null +++ b/bin/tests/system/spf/tests_spf_zones.py @@ -0,0 +1,32 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + + +@pytest.mark.requires_zones_loaded("ns1") +def test_spf_log(servers): + for msg in ( + "zone spf/IN: 'y.spf' found type SPF record but no SPF TXT record found", + "zone warn/IN: 'y.warn' found type SPF record but no SPF TXT record found", + "zone spf/IN: loaded serial 0", + "zone warn/IN: loaded serial 0", + "zone nowarn/IN: loaded serial 0", + ): + servers["ns1"].log.expect(msg) + + for msg in ( + "zone nowarn/IN: 'y.nowarn' found type SPF record but no SPF TXT record found", + "zone spf/IN: 'spf' found type SPF record but no SPF TXT record found", + "zone warn/IN: 'warn' found type SPF record but no SPF TXT record found", + "zone nowarn/IN: 'nowarn' found type SPF record but no SPF TXT record found", + ): + servers["ns1"].log.prohibit(msg) diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl new file mode 100755 index 0000000..d4a0b40 --- /dev/null +++ b/bin/tests/system/start.pl @@ -0,0 +1,444 @@ +#!/usr/bin/perl -w + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# 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 https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# Framework for starting test servers. +# Based on the type of server specified, check for port availability, remove +# temporary files, start the server, and verify that the server is running. +# If a server is specified, start it. Otherwise, start all servers for test. + +use strict; +use warnings; + +use Cwd ':DEFAULT', 'abs_path'; +use English '-no_match_vars'; +use Getopt::Long; +use Time::HiRes 'sleep'; # allows sleeping fractional seconds + +# Usage: +# perl start.pl [--noclean] [--restart] [--port port] [--taskset cpus] test [server [options]] +# +# --noclean Do not cleanup files in server directory. +# +# --restart Indicate that the server is being restarted, so get the +# server to append output to an existing log file instead of +# starting a new one. +# +# --port port Specify the default port being used by the server to answer +# queries (default 5300). This script will interrogate the +# server on this port to see if it is running. (Note: for +# "named" nameservers, this can be overridden by the presence +# of the file "named.port" in the server directory containing +# the number of the query port.) +# +# --taskset cpus Use taskset to signal which cpus can be used. For example +# cpus=fff0 means all cpus aexcept for 0, 1, 2, and 3 are +# eligible. +# +# test Name of the test directory. +# +# server Name of the server directory. This will be of the form +# "nsN" or "ansN", where "N" is an integer between 1 and 8. +# If not given, the script will start all the servers in the +# test directory. +# +# options Alternate options for the server. +# +# NOTE: options must be specified with '-- "