]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4326] Checkpoint: code done, need UT & doc
authorFrancis Dupont <fdupont@isc.org>
Tue, 3 Mar 2026 10:59:45 +0000 (11:59 +0100)
committerFrancis Dupont <fdupont@isc.org>
Sat, 23 May 2026 17:53:48 +0000 (19:53 +0200)
src/hooks/d2/gss_tsig/gss_tsig_api.cc
src/hooks/d2/gss_tsig/gss_tsig_api.h
src/hooks/d2/gss_tsig/gss_tsig_cfg.cc
src/hooks/d2/gss_tsig/gss_tsig_cfg.h
src/hooks/d2/gss_tsig/gss_tsig_context.h

index c304da20bc36e1b987dcfc633d5048c506667828..662289c85262dde02f90471d4c9175a152888017 100644 (file)
@@ -266,6 +266,8 @@ GssApiCred::inquire(GssApiName& name, gss_cred_usage_t& cred_usage,
     }
 }
 
+bool GssApiSecCtx::ignore_bad_direction_ = false;
+
 GssApiSecCtx::GssApiSecCtx(gss_ctx_id_t sec_ctx)
     : GssApiLastError(), sec_ctx_(sec_ctx) {
 }
@@ -357,9 +359,20 @@ GssApiSecCtx::verify(GssApiBuffer& gmessage, GssApiBuffer& gsig) {
     OM_uint32 major = gss_verify_mic(&minor, sec_ctx_, gmessage.getPtr(),
                                      gsig.getPtr(), 0);
     if (major != GSS_S_COMPLETE) {
+        string err_msg = gssApiErrMsg(major, minor);
+        // Should use minor == G_BAD_DIRECTION but the code point is
+        // in a generated include not provided by all packages.
+        if (ignore_bad_direction_ && (major == GSS_S_BAD_MIC) &&
+#ifdef G_BAD_DIRECTION
+            (minor == G_BAD_DIRECTION)
+#else
+            (err_msg.find("wrong direction") != string::npos)
+#endif
+            ) {
+            return;
+        }
         setLastError(major);
-        isc_throw(GssApiError, "gss_verify_mic failed with "
-                  << gssApiErrMsg(major, minor));
+        isc_throw(GssApiError, "gss_verify_mic failed with " << err_msg);
     }
 }
 
index 259e4755d4d909df92dd88ab89f24b3ef017b14c..b730d8d00501a3d5a4c5e389b97137e60378620c 100644 (file)
@@ -289,6 +289,13 @@ typedef boost::shared_ptr<GssApiCred> GssApiCredPtr;
 /// @note: some methods should be const but this does not match the API.
 class GssApiSecCtx : public boost::noncopyable, public GssApiLastError {
 public:
+    /// @brief Ignore bad direction flag.
+    ///
+    /// @note: when true (default is false) verify accepts
+    /// messages sent in the wrong direction as Microsoft servers
+    /// sending DNS update responses when prerequisities fail.
+    static bool ignore_bad_direction_;
+
     /// @brief Constructor.
     ///
     /// @param sec_ctx The GSS-API security context.
index d3113a0a7e5de614467da0c799a85ae38c7fc741..4969b9885c4d3f6da88a0e9780d3dd17f43af316 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <dns/name.h>
 #include <gss_tsig_cfg.h>
+#include <gss_tsig_context.h>
 #include <stats/stats_mgr.h>
 
 #include <limits>
@@ -285,26 +286,27 @@ DnsServer::toElement() const {
 }
 
 const SimpleKeywords GssTsigCfg::GLOBAL_PARAMETERS = {
-    { "server-principal",   Element::string },
-    { "client-principal",   Element::string },
-    { "client-keytab",      Element::string },
-    { "credentials-cache",  Element::string },
-    { "gss-replay-flag",    Element::boolean },
-    { "gss-sequence-flag",  Element::boolean },
-    { "tkey-lifetime",      Element::integer },
-    { "rekey-interval",     Element::integer },
-    { "retry-interval",     Element::integer },
-    { "tkey-protocol",      Element::string },
-    { "fallback",           Element::boolean },
-    { "exchange-timeout",   Element::integer },
-    { "servers",            Element::list },
-    { "user-context",       Element::map },
-    { "comment",            Element::string }
+    { "server-principal",      Element::string },
+    { "client-principal",      Element::string },
+    { "client-keytab",         Element::string },
+    { "credentials-cache",     Element::string },
+    { "gss-replay-flag",       Element::boolean },
+    { "gss-sequence-flag",     Element::boolean },
+    { "tkey-lifetime",         Element::integer },
+    { "rekey-interval",        Element::integer },
+    { "retry-interval",        Element::integer },
+    { "tkey-protocol",         Element::string },
+    { "fallback",              Element::boolean },
+    { "exchange-timeout",      Element::integer },
+    { "ignore-bad-direction",  Element::boolean },
+    { "servers",               Element::list },
+    { "user-context",          Element::map },
+    { "comment",               Element::string }
 };
 
 GssTsigCfg::GssTsigCfg()
     : servers_(), servers_rev_map_(), client_keytab_(""), creds_cache_(""),
-      max_tkey_lifetime_(0) {
+      max_tkey_lifetime_(0), ignore_bad_direction_(false) {
 }
 
 GssTsigCfg::~GssTsigCfg() {
@@ -463,6 +465,13 @@ GssTsigCfg::configure(ConstElementPtr params) {
         }
     }
 
+    ConstElementPtr ignore_bad_direction = params->get("ignore-bad-direction");
+    if (ignore_bad_direction) {
+        bool val = ignore_bad_direction->boolValue();
+        ignore_bad_direction_ = val;
+        GssApiSecCtx::ignore_bad_direction_ = val;
+    }
+
     ConstElementPtr servers = params->get("servers");
     if (!servers) {
         return;
index 220bb0a58abd5aa82f8720843045bf8b070cc6e9..965c8647672d1ed5c4c6897d224beabf2e20268e 100644 (file)
@@ -532,6 +532,20 @@ public:
         max_tkey_lifetime_ = max_tkey_lifetime;
     }
 
+    /// @brief Get the ignore bad direction flag.
+    ///
+    /// @return the ignore bad direction flag.
+    bool getIgnoreBadDirection() const {
+        return (ignore_bad_direction_);
+    }
+
+    /// @brief Set the ignore bad direction flag.
+    ///
+    /// @param ignore_bad_direction A new ignore bad direction.
+    void setIgnoreBadDirection(bool ignore_bad_direction) {
+        ignore_bad_direction_ = ignore_bad_direction;
+    }
+
 private:
     /// @brief The DNS server list.
     DnsServerList servers_;
@@ -547,6 +561,9 @@ private:
 
     /// @brief The maximum TKEY lifetime.
     uint32_t max_tkey_lifetime_;
+
+    /// @brief The ignore bad direction flag.
+    bool ignore_bad_direction_;
 };
 
 } // end of namespace isc::gss_tsig
index 6761a48b0ce7f5691bbacca8a0863707cec15351..9b50cc26e6c552d857bcc0d67eee58ff000c8c1d 100644 (file)
@@ -70,7 +70,7 @@ public:
     sign(const uint16_t qid, const void* const data,
          const size_t data_len) override;
 
-    /// @brief a DNS message.
+    /// @brief Verify a DNS message.
     ///
     /// See @c isc::dns::TSIGContext::verify().
     ///