URL: https://github.com/SSSD/sssd/pull/5647
Author: elkoniu
 Title: #5647: krb5_child: Honor Kerberos keytab location
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/5647/head:pr5647
git checkout pr5647
From 55bc356e2e45dd800c62da2b670ad569a6db0daf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= <ppola...@redhat.com>
Date: Sun, 23 May 2021 03:41:03 +0200
Subject: [PATCH] krb5_child: Honor Kerberos keytab location

Kerberos keytab location can be specified per domain in sssd.conf.
If it is not specified - default path is used: /etc/krb5.keytab
The problem is that default path itself can be redefined for kerberos
by adding entry in krb5.conf:

  [libdefaults]
  default_keytab_name = /<PATH>/krb5.keytab

krb5_child will still use /etc/krb5.keytab as default value which
will cause an error.

This patch adds config checking to krb5_child.
If keytab parameter will be set to /etc/krb5.keytab,
krb5_child will validate it against krb5.conf and eventually
overwritte with value presented there.
---
 src/man/sssd-krb5.5.xml                 |  2 +-
 src/providers/ad/ad_opts.c              |  2 +-
 src/providers/krb5/krb5_child.c         | 61 +++++++++++++++++++++++--
 src/providers/krb5/krb5_child_handler.c |  4 +-
 src/providers/krb5/krb5_opts.c          |  2 +-
 5 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index e46d1fbf0c..4a415ac143 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -244,7 +244,7 @@
                             credentials obtained from KDCs.
                         </para>
                         <para>
-                            Default: /etc/krb5.keytab
+                            Default: System keytab, normally <filename>/etc/krb5.keytab</filename>
                         </para>
                     </listitem>
                 </varlistentry>
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index e7295567a0..ed65d78c0e 100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -173,7 +173,7 @@ struct dp_option ad_def_krb5_opts[] = {
     { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
     { "krb5_ccname_template", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
-    { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
+    { "krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_validate", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "krb5_kpasswd", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_backup_kpasswd", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index fbd0555190..713e90f833 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -2503,9 +2503,13 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
 
         SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
         if (len > size - p) return EINVAL;
-        kr->keytab = talloc_strndup(pd, (char *)(buf + p), len);
-        if (kr->keytab == NULL) return ENOMEM;
-        p += len;
+
+        if (len > 0) {
+            kr->keytab = talloc_strndup(pd, (char *)(buf + p), len);
+            p += len;
+        } else {
+            kr->keytab = NULL;
+        }
 
         ret = unpack_authtok(pd->authtok, buf, size, &p);
         if (ret) {
@@ -2516,7 +2520,7 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
               "ccname: [%s] old_ccname: [%s] keytab: [%s]\n",
               kr->ccname,
               kr->old_ccname ? kr->old_ccname : "not set",
-              kr->keytab);
+              kr->keytab ? kr->keytab : "not set");
     } else {
         kr->ccname = NULL;
         kr->old_ccname = NULL;
@@ -3154,6 +3158,49 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
     return kerr;
 }
 
+static krb5_error_code check_keytab_name(struct krb5_req *kr)
+{
+    krb5_error_code kerr;
+    char krb5_conf_keytab[MAX_KEYTAB_NAME_LEN];
+    char *path_start = NULL;
+
+    if (kr->keytab == NULL && (
+        kr->pd->cmd == SSS_PAM_AUTHENTICATE ||
+        kr->pd->cmd == SSS_PAM_PREAUTH ||
+        kr->pd->cmd == SSS_CMD_RENEW ||
+        kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM ||
+        kr->pd->cmd == SSS_PAM_CHAUTHTOK)) {
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Missing krb5_keytab option for domain, looking for default one\n");
+
+        kerr = krb5_kt_default_name(kr->ctx, krb5_conf_keytab, sizeof(krb5_conf_keytab));
+        if (kerr != 0) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Unable to get default keytab location from krb.conf\n");
+            return kerr;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "krb5_kt_default_name() returned: %s\n",
+              krb5_conf_keytab);
+
+        /* krb5_kt_default_name() can return file path with "FILE:" prefix,
+           it need to be removed */
+        if (0 == strncmp(krb5_conf_keytab, "FILE:", strlen("FILE:"))) {
+            path_start = krb5_conf_keytab + strlen("FILE:");
+        } else {
+            path_start = krb5_conf_keytab;
+        }
+
+        kr->keytab = talloc_strndup(kr->pd, path_start, strlen(path_start));
+
+        DEBUG(SSSDBG_TRACE_FUNC, "krb5_child will default to: %s\n", path_start);
+    }
+
+    return 0;
+}
+
 static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
                                              uint32_t offline)
 {
@@ -3172,6 +3219,12 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
         return kerr;
     }
 
+    kerr = check_keytab_name(kr);
+    if (kerr != 0) {
+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
+        return kerr;
+    }
+
     kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
     if (kerr != 0) {
         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index f601bb7b8e..778e38fc8e 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -119,8 +119,8 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
 
     keytab = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_KEYTAB);
     if (keytab == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, "Missing keytab option.\n");
-        return EINVAL;
+        DEBUG(SSSDBG_TRACE_FUNC, "krb5_keytab not set for domain in sssd.conf\n");
+        keytab = "";
     }
 
     validate = dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) ? 1 : 0;
diff --git a/src/providers/krb5/krb5_opts.c b/src/providers/krb5/krb5_opts.c
index 47a101bdb5..a72617e623 100644
--- a/src/providers/krb5/krb5_opts.c
+++ b/src/providers/krb5/krb5_opts.c
@@ -29,7 +29,7 @@ struct dp_option default_krb5_opts[] = {
     { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
     { "krb5_ccname_template", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
-    { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
+    { "krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "krb5_kpasswd", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_backup_kpasswd", DP_OPT_STRING, NULL_STRING, NULL_STRING },
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to