]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnssecinfra.hh
Merge pull request #14240 from PowerDNS/dependabot/pip/pdns/dnsdistdist/docs/requests...
[thirdparty/pdns.git] / pdns / dnssecinfra.hh
index d3a437d5bb2c989b2b7b98d52bd6ecff2bb3f4e1..9614ee1373d0e0cf3f1de8d48bd39bfb8ea1cdd5 100644 (file)
@@ -36,16 +36,38 @@ class DNSCryptoKeyEngine
 {
   public:
     explicit DNSCryptoKeyEngine(unsigned int algorithm) : d_algorithm(algorithm) {}
-    virtual ~DNSCryptoKeyEngine() {};
+    virtual ~DNSCryptoKeyEngine() = default;
     [[nodiscard]] virtual string getName() const = 0;
 
     using stormap_t = std::map<std::string, std::string>;
     using storvector_t = std::vector<std::pair<std::string, std::string>>;
     virtual void create(unsigned int bits)=0;
 
-    virtual void createFromPEMFile(DNSKEYRecordContent& /* drc */, const std::string& /* filename */, std::FILE& /* inputFile */)
+    virtual void createFromPEMFile(DNSKEYRecordContent& /* drc */, std::FILE& /* inputFile */, const std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt)
     {
-      throw std::runtime_error("Can't create key from PEM file");
+      if (filename.has_value()) {
+        throw std::runtime_error("Can't create key from PEM file `" + filename->get() + "`");
+      }
+
+      throw std::runtime_error("Can't create key from PEM contents");
+    }
+
+    /**
+     * \brief Creates a key engine from a PEM string.
+     *
+     * Receives PEM contents and creates a key engine.
+     *
+     * \param[in] drc Key record contents to be populated.
+     *
+     * \param[in] contents The PEM string contents.
+     *
+     * \return A key engine populated with the contents of the PEM string.
+     */
+    void createFromPEMString(DNSKEYRecordContent& drc, const std::string& contents)
+    {
+      // NOLINTNEXTLINE(*-cast): POSIX APIs.
+      pdns::UniqueFilePtr inputFile{fmemopen(const_cast<char*>(contents.data()), contents.length(), "r")};
+      createFromPEMFile(drc, *inputFile);
     }
 
     [[nodiscard]] virtual storvector_t convertToISCVector() const =0;
@@ -56,6 +78,25 @@ class DNSCryptoKeyEngine
       throw std::runtime_error(getName() + ": Conversion to PEM not supported");
     };
 
+    /**
+     * \brief Converts the key into a PEM string.
+     *
+     * \return A string containing the key's PEM contents.
+     */
+    [[nodiscard]] auto convertToPEMString() const -> std::string
+    {
+      const size_t buflen = 4096;
+
+      std::string output{};
+      output.resize(buflen);
+      pdns::UniqueFilePtr outputFile{fmemopen(output.data(), output.length() - 1, "w")};
+      convertToPEMFile(*outputFile);
+      std::fflush(outputFile.get());
+      output.resize(std::ftell(outputFile.get()));
+
+      return output;
+    };
+
     [[nodiscard]] virtual std::string sign(const std::string& msg) const =0;
 
     [[nodiscard]] virtual std::string hash(const std::string& msg) const
@@ -103,10 +144,30 @@ class DNSCryptoKeyEngine
      */
     static std::unique_ptr<DNSCryptoKeyEngine> makeFromPEMFile(DNSKEYRecordContent& drc, uint8_t algorithm, std::FILE& inputFile, const std::string& filename);
 
+    /**
+     * \brief Creates a key engine from a PEM string.
+     *
+     * Receives PEM contents and creates a key engine corresponding to the algorithm
+     * requested.
+     *
+     * \param[in] drc Key record contents to be populated.
+     *
+     * \param[in] algorithm Which algorithm to use. See
+     * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
+     *
+     * \param[in] contents The PEM contents.
+     *
+     * \return A key engine corresponding to the requested algorithm and populated with
+     * the contents of the PEM string.
+     */
+    static std::unique_ptr<DNSCryptoKeyEngine> makeFromPEMString(DNSKEYRecordContent& drc, uint8_t algorithm, const std::string& contents);
+
     static std::unique_ptr<DNSCryptoKeyEngine> makeFromISCString(DNSKEYRecordContent& drc, const std::string& content);
     static std::unique_ptr<DNSCryptoKeyEngine> makeFromPublicKeyString(unsigned int algorithm, const std::string& raw);
     static std::unique_ptr<DNSCryptoKeyEngine> make(unsigned int algorithm);
     static bool isAlgorithmSupported(unsigned int algo);
+    static bool isAlgorithmSwitchedOff(unsigned int algo);
+    static void switchOffAlgorithm(unsigned int algo);
     static bool isDigestSupported(uint8_t digest);
 
     using maker_t = std::unique_ptr<DNSCryptoKeyEngine> (unsigned int);
@@ -116,6 +177,9 @@ class DNSCryptoKeyEngine
     static vector<pair<uint8_t, string>> listAllAlgosWithBackend();
     static bool testAll();
     static bool testOne(int algo);
+    static bool verifyOne(unsigned int algo);
+    static bool testVerify(unsigned int algo, maker_t* verifier);
+    static string listSupportedAlgoNames();
 
   private:
     using makers_t = std::map<unsigned int, maker_t *>;
@@ -130,6 +194,8 @@ class DNSCryptoKeyEngine
       static allmakers_t s_allmakers;
       return s_allmakers;
     }
+    // Must be set before going multi-threaded and not changed after that
+    static std::unordered_set<unsigned int> s_switchedOff;
 
   protected:
     const unsigned int d_algorithm;
@@ -182,8 +248,8 @@ private:
 
   DNSKEYRecordContent d_dnskey;
   std::shared_ptr<DNSCryptoKeyEngine> d_key;
-  uint16_t d_flags;
-  uint8_t d_algorithm;
+  uint16_t d_flags{0};
+  uint8_t d_algorithm{0};
 };
 
 
@@ -204,12 +270,12 @@ struct CanonicalCompare
 };
 
 struct sharedDNSSECRecordCompare {
-    bool operator() (const shared_ptr<DNSRecordContent>& a, const shared_ptr<DNSRecordContent>& b) const {
+    bool operator() (const shared_ptr<const DNSRecordContent>& a, const shared_ptr<const DNSRecordContent>& b) const {
       return a->serialize(g_rootdnsname, true, true) < b->serialize(g_rootdnsname, true, true);
     }
 };
 
-typedef std::set<std::shared_ptr<DNSRecordContent>, sharedDNSSECRecordCompare> sortedRecords_t;
+typedef std::set<std::shared_ptr<const DNSRecordContent>, sharedDNSSECRecordCompare> sortedRecords_t;
 
 string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, const sortedRecords_t& signRecords, bool processRRSIGLabels = false, bool includeRRSIG_RDATA = true);