From 69c4c688ed0d27d6184b5c2378a7816b05cb3cfb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20=C4=8Cech?= <pcech@redhat.com>
Date: Tue, 28 Mar 2017 14:35:22 +0200
Subject: [PATCH] UTIL: Set udp_preference_limit=0 in krb5 snippet

We add udp_preference_limit = 0 to krb5 snippet if ad provider is
used. This option enable TCP connection before UDP, when sending
a message to the KDC.

Resolves:
https://pagure.io/SSSD/sssd/issue/3254
---
 src/providers/ad/ad_subdomains.c   |  2 +-
 src/providers/ipa/ipa_subdomains.c |  2 +-
 src/tests/cmocka/test_utils.c      | 12 ++++-----
 src/util/domain_info_utils.c       | 55 +++++++++++++++++++++++++++++---------
 src/util/util.h                    |  3 ++-
 5 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 749c5b42f..280aa54c2 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -702,7 +702,7 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx)
                                     "will not be created.\n");
     }
 
-    ret = sss_write_krb5_conf_snippet(path, canonicalize);
+    ret = sss_write_krb5_conf_snippet(path, canonicalize, true);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
         /* Just continue */
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index e052f9847..7f8bcdbad 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -117,7 +117,7 @@ ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx)
     ret = sss_write_krb5_conf_snippet(
                           dp_opt_get_string(ctx->ipa_id_ctx->ipa_options->basic,
                                             IPA_KRB5_CONFD_PATH),
-                          canonicalize);
+                          canonicalize, false);
     if (ret != EOK) {
         DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
         /* Just continue */
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
index 25508b172..7cbb395da 100644
--- a/src/tests/cmocka/test_utils.c
+++ b/src/tests/cmocka/test_utils.c
@@ -1350,16 +1350,16 @@ void test_sss_write_krb5_conf_snippet(void **state)
     char *file;
     char *file_krb5_libdefaults;
 
-    ret = sss_write_krb5_conf_snippet(NULL, false);
+    ret = sss_write_krb5_conf_snippet(NULL, false, false);
     assert_int_equal(ret, EINVAL);
 
-    ret = sss_write_krb5_conf_snippet("abc", false);
+    ret = sss_write_krb5_conf_snippet("abc", false, false);
     assert_int_equal(ret, EINVAL);
 
-    ret = sss_write_krb5_conf_snippet("", false);
+    ret = sss_write_krb5_conf_snippet("", false, false);
     assert_int_equal(ret, EOK);
 
-    ret = sss_write_krb5_conf_snippet("none", false);
+    ret = sss_write_krb5_conf_snippet("none", false, false);
     assert_int_equal(ret, EOK);
 
     cwd = getcwd(buf, PATH_MAX);
@@ -1375,11 +1375,11 @@ void test_sss_write_krb5_conf_snippet(void **state)
                    "%s/%s/krb5_libdefaults", cwd, TESTS_PATH);
     assert_true(ret > 0);
 
-    ret = sss_write_krb5_conf_snippet(path, true);
+    ret = sss_write_krb5_conf_snippet(path, true, true);
     assert_int_equal(ret, EOK);
 
     /* Check if writing a second time will work as well */
-    ret = sss_write_krb5_conf_snippet(path, true);
+    ret = sss_write_krb5_conf_snippet(path, true, true);
     assert_int_equal(ret, EOK);
 
 #ifdef HAVE_KRB5_LOCALAUTH_PLUGIN
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
index 1aacfa283..35636a533 100644
--- a/src/util/domain_info_utils.c
+++ b/src/util/domain_info_utils.c
@@ -734,15 +734,14 @@ static errno_t sss_write_krb5_localauth_snippet(const char *path)
 #endif
 }
 
-#define KRB5_LIBDEFAUTLS_CONFIG \
-"[libdefaults]\n" \
-" canonicalize = true\n"
-
-static errno_t sss_write_krb5_libdefaults_snippet(const char *path)
+static errno_t sss_write_krb5_libdefaults_snippet(const char *path,
+                                                  bool canonicalize,
+                                                  bool udp_limit)
 {
     int ret;
     TALLOC_CTX *tmp_ctx = NULL;
     const char *file_name;
+    char *file_contents;
 
     tmp_ctx = talloc_new(NULL);
     if (tmp_ctx == NULL) {
@@ -760,19 +759,51 @@ static errno_t sss_write_krb5_libdefaults_snippet(const char *path)
     DEBUG(SSSDBG_FUNC_DATA, "File for KRB5 kibdefaults configuration is [%s]\n",
                              file_name);
 
-    ret = sss_write_krb5_snippet_common(file_name, KRB5_LIBDEFAUTLS_CONFIG);
+    file_contents = talloc_strdup(tmp_ctx, "[libdefaults]\n");
+    if (file_contents == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "talloc_asprintf failed while creating the content\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    if (canonicalize == true) {
+        file_contents = talloc_asprintf_append(file_contents,
+                                               " canonicalize = true\n");
+        if (file_contents == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "talloc_asprintf failed while appending to the content\n");
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    if (udp_limit == true) {
+        file_contents = talloc_asprintf_append(file_contents,
+                                               " udp_preference_limit = 0\n");
+        if (file_contents == NULL) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "talloc_asprintf failed while appending to the content\n");
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    ret = sss_write_krb5_snippet_common(file_name, file_contents);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "sss_write_krb5_snippet_common failed.\n");
         goto done;
     }
 
+
 done:
 
     talloc_free(tmp_ctx);
     return ret;
 }
 
-errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize)
+errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize,
+                                    bool udp_limit)
 {
     errno_t ret;
     errno_t err;
@@ -794,12 +825,10 @@ errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize)
         goto done;
     }
 
-    if (canonicalize) {
-        ret = sss_write_krb5_libdefaults_snippet(path);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE, "sss_write_krb5_libdefaults_snippet failed.\n");
-            goto done;
-        }
+    ret = sss_write_krb5_libdefaults_snippet(path, canonicalize, udp_limit);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sss_write_krb5_libdefaults_snippet failed.\n");
+        goto done;
     }
 
     ret = EOK;
diff --git a/src/util/util.h b/src/util/util.h
index 81d5e9b67..9b64dead8 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -582,7 +582,8 @@ errno_t sss_get_domain_mappings_content(TALLOC_CTX *mem_ctx,
 
 errno_t sss_write_domain_mappings(struct sss_domain_info *domain);
 
-errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize);
+errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize,
+                                    bool udp_limit);
 
 errno_t get_dom_names(TALLOC_CTX *mem_ctx,
                       struct sss_domain_info *start_dom,
