[SSSD] [PATCH] Read KDC info from file instead from environment

Sumit Bose sbose at redhat.com
Thu Nov 19 17:32:33 UTC 2009


Hi,

this patch changes the way the locator plugin finds out about the KDC.
Now the information is written to a file which is read by the plugin.

Two thing will be address in different patches.

- the enviroment variables are still sent to the client. I haven't
  removed them in this patch, because it would introduce a dependency to
  other not-committed patches. I thought it might be easier this way.
- integration of the fail-over framework.

bye,
Sumit
-------------- next part --------------
>From cee867db56fb09b28c33e855f4a853e75075a044 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 19 Nov 2009 17:53:38 +0100
Subject: [PATCH] Read KDC info from file instead from environment

Then name or IP adress of the KDC is written into the pubconf directory
into a file named kdcinfo.REALM. The locator plugin will then read this
file and pass the data to the kerberos libraries.
---
 contrib/sssd.spec.in                          |    3 +
 server/Makefile.am                            |    4 +-
 server/conf_macros.m4                         |   17 ++++
 server/configure.ac                           |    1 +
 server/krb5_plugin/sssd_krb5_locator_plugin.c |  122 +++++++++++++++++++------
 server/providers/krb5/krb5_common.c           |  104 ++++++++++++++++++---
 server/providers/krb5/krb5_common.h           |    4 +
 7 files changed, 209 insertions(+), 46 deletions(-)

diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 173d049..1251fe5 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -28,6 +28,7 @@ Requires(postun): /sbin/service
 %define sssdstatedir %{_localstatedir}/lib/sss
 %define dbpath %{sssdstatedir}/db
 %define pipepath %{sssdstatedir}/pipes
+%define pubconfpath %{sssdstatedir}/pubconf
 
 ### Build Dependencies ###
 
@@ -80,6 +81,7 @@ KRB5_LIBS=-lkrb5 \
     --without-tests \
     --with-db-path=%{dbpath} \
     --with-pipe-path=%{pipepath} \
+    --with-pubconf-path=%{pubconfpath} \
     --with-init-dir=%{_initrddir} \
     --enable-nsslibdir=/%{_lib}
 
@@ -138,6 +140,7 @@ rm -rf $RPM_BUILD_ROOT
 %dir %{sssdstatedir}
 %attr(700,root,root) %dir %{dbpath}
 %attr(755,root,root) %dir %{pipepath}
+%attr(755,root,root) %dir %{pubconfpath}
 %attr(700,root,root) %dir %{pipepath}/private
 %attr(750,root,root) %dir %{_var}/log/%{name}
 %attr(700,root,root) %dir %{_sysconfdir}/sssd
diff --git a/server/Makefile.am b/server/Makefile.am
index 196486a..2ebbcfb 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -22,6 +22,7 @@ pidpath = @pidpath@
 pipepath = @pipepath@
 initdir = @initdir@
 logpath = @logpath@
+pubconfpath = @pubconfpath@
 
 AM_CFLAGS =
 if WANT_AUX_INFO
@@ -723,7 +724,8 @@ installsssddirs::
     $(DESTDIR)$(dbpath) \
     $(DESTDIR)$(pidpath) \
     $(DESTDIR)$(initdir) \
-    $(DESTDIR)$(logpath)
+    $(DESTDIR)$(logpath) \
+    $(DESTDIR)$(pubconfpath)
 
 install-exec-hook: installsssddirs
 	if [ "$(DESTDIR)" = "" ]; then \
diff --git a/server/conf_macros.m4 b/server/conf_macros.m4
index 0990e50..86ccf5d 100644
--- a/server/conf_macros.m4
+++ b/server/conf_macros.m4
@@ -66,6 +66,23 @@ AC_DEFUN([WITH_LOG_PATH],
     AC_DEFINE_UNQUOTED(LOG_PATH, "$config_logpath", [Where to store log files for the SSSD])
   ])
 
+AC_DEFUN([WITH_PUBCONF_PATH],
+  [ AC_ARG_WITH([pubconf-path],
+                [AC_HELP_STRING([--with-pubconf-path=PATH],
+                                [Where to store pubconf files for the SSSD [/var/lib/sss/pubconf]]
+                               )
+                ]
+               )
+    config_pubconfpath="\"VARDIR\"/lib/sss/pubconf"
+    pubconfpath="${localstatedir}/lib/sss/pubconf"
+    if test x"$with_pubconf_path" != x; then
+        config_pubconfpath=$with_pubconf_path
+        pubconfpath=$with_pubconf_path
+    fi
+    AC_SUBST(pubconfpath)
+    AC_DEFINE_UNQUOTED(PUBCONF_PATH, "$config_pubconfpath", [Where to store pubconf files for the SSSD])
+  ])
+
 AC_DEFUN([WITH_PIPE_PATH],
   [ AC_ARG_WITH([pipe-path],
                 [AC_HELP_STRING([--with-pipe-path=PATH],
diff --git a/server/configure.ac b/server/configure.ac
index 1a94158..696a5a4 100644
--- a/server/configure.ac
+++ b/server/configure.ac
@@ -45,6 +45,7 @@ WITH_DB_PATH
 WITH_PLUGIN_PATH
 WITH_PID_PATH
 WITH_LOG_PATH
+WITH_PUBCONF_PATH
 WITH_PIPE_PATH
 WITH_INIT_DIR
 WITH_SHADOW_UTILS_PATH
diff --git a/server/krb5_plugin/sssd_krb5_locator_plugin.c b/server/krb5_plugin/sssd_krb5_locator_plugin.c
index a30586c..5e79733 100644
--- a/server/krb5_plugin/sssd_krb5_locator_plugin.c
+++ b/server/krb5_plugin/sssd_krb5_locator_plugin.c
@@ -27,12 +27,14 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <netdb.h>
-
+#include <sys/stat.h>
+#include <fcntl.h>
 
 #include <krb5/locate_plugin.h>
 
 #include "providers/krb5/krb5_common.h"
 
+#define BUFSIZE 512
 #define SSSD_KRB5_LOCATOR_DEBUG "SSSD_KRB5_LOCATOR_DEBUG"
 #define DEBUG_KEY "[sssd_krb5_locator] "
 #define PLUGIN_DEBUG(body) do { \
@@ -67,33 +69,60 @@ void debug_fn(const char *format, ...)
     free(s);
 }
 
-krb5_error_code sssd_krb5_locator_init(krb5_context context,
-                                       void **private_data)
+static int get_kdcinfo(const char *realm, struct sssd_ctx *ctx)
 {
-    struct sssd_ctx *ctx;
-    const char *dummy;
     int ret;
+    char *kdcinfo_name = NULL;
+    size_t len;
+    uint8_t buf[BUFSIZE + 1];
+    uint8_t *p;
+    int fd = -1;
+
+    len = strlen(realm) + strlen(KDCINFO_TMPL);
+
+    kdcinfo_name = calloc(1, len + 1);
+    if (kdcinfo_name == NULL) {
+        PLUGIN_DEBUG(("malloc failed.\n"));
+        return ENOMEM;
+    }
 
-    ctx = calloc(1,sizeof(struct sssd_ctx));
-    if (ctx == NULL) return ENOMEM;
+    ret = snprintf(kdcinfo_name, len, KDCINFO_TMPL, realm);
+    if (ret < 0) {
+        PLUGIN_DEBUG(("snprintf failed"));
+        ret = EINVAL;
+    }
+    kdcinfo_name[len] = '\0';
 
-    dummy = getenv(SSSD_KRB5_LOCATOR_DEBUG);
-    if (dummy == NULL) {
-        ctx->debug = false;
-    } else {
-        ctx->debug = true;
-        PLUGIN_DEBUG(("sssd_krb5_locator_init called\n"));
+    fd = open(kdcinfo_name, O_RDONLY);
+    if (fd == -1) {
+        PLUGIN_DEBUG(("open failed [%d][%s].\n", errno, strerror(errno)));
+        ret = errno;
+        goto done;
     }
 
-    dummy = getenv(SSSD_KRB5_REALM);
-    if (dummy == NULL) goto failed;
-    ctx->sssd_realm = strdup(dummy);
-    if (ctx->sssd_realm == NULL) goto failed;
+    len = BUFSIZE;
+    p = buf;
+    memset(buf, 0, BUFSIZE+1);
+    while (len != 0 && (ret = read(fd, p, len)) != 0) {
+        if (ret == -1) {
+            if (errno == EINTR) continue;
+            PLUGIN_DEBUG(("read failed [%d][%s].\n", errno, strerror(errno)));
+            close(fd);
+            goto done;
+        }
 
-    dummy = getenv(SSSD_KRB5_KDC);
-    if (dummy == NULL) goto failed;
+        len -= ret;
+        p += ret;
+    }
+    close(fd);
 
-    ret = getaddrinfo(dummy, "kerberos", NULL, &ctx->sssd_kdc_addrinfo);
+    if (len == 0) {
+        PLUGIN_DEBUG(("Content of kdcinfo file [%s] is [%d] or larger.\n",
+                      kdcinfo_name, BUFSIZE));
+    }
+    PLUGIN_DEBUG(("Found kdcinfo [%s].\n", buf));
+
+    ret = getaddrinfo((char *) buf, "kerberos", NULL, &ctx->sssd_kdc_addrinfo);
     if (ret != 0) {
         PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", ret,
                                                         gai_strerror(ret)));
@@ -101,20 +130,43 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context,
             PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", errno,
                                                             strerror(errno)));
         }
-        goto failed;
+        goto done;
     }
 
-    *private_data = ctx;
+    ctx->sssd_realm = strdup(realm);
+    if (ctx->sssd_realm == NULL) {
+        PLUGIN_DEBUG(("strdup failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
 
-    return 0;
-failed:
-    freeaddrinfo(ctx->sssd_kdc_addrinfo);
-    free(ctx->sssd_realm);
-    free(ctx);
 
-    private_data = NULL;
 
-    return EINVAL;
+done:
+    free(kdcinfo_name);
+    return ret;
+}
+
+krb5_error_code sssd_krb5_locator_init(krb5_context context,
+                                       void **private_data)
+{
+    struct sssd_ctx *ctx;
+    const char *dummy;
+
+    ctx = calloc(1,sizeof(struct sssd_ctx));
+    if (ctx == NULL) return ENOMEM;
+
+    dummy = getenv(SSSD_KRB5_LOCATOR_DEBUG);
+    if (dummy == NULL) {
+        ctx->debug = false;
+    } else {
+        ctx->debug = true;
+        PLUGIN_DEBUG(("sssd_krb5_locator_init called\n"));
+    }
+
+    *private_data = ctx;
+
+    return 0;
 }
 
 void sssd_krb5_locator_close(void *private_data)
@@ -150,6 +202,18 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
     if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
     ctx = (struct sssd_ctx *) private_data;
 
+    if (ctx->sssd_realm == NULL || strcmp(ctx->sssd_realm, realm) != 0) {
+        freeaddrinfo(ctx->sssd_kdc_addrinfo);
+        ctx->sssd_kdc_addrinfo = NULL;
+        free(ctx->sssd_realm);
+        ctx->sssd_realm = NULL;
+        ret = get_kdcinfo(realm, ctx);
+        if (ret != EOK) {
+            PLUGIN_DEBUG(("get_kdcinfo failed.\n"));
+            return KRB5_PLUGIN_NO_HANDLE;
+        }
+    }
+
     PLUGIN_DEBUG(("sssd_realm[%s] requested realm[%s] family[%d] socktype[%d] "
                   "locate_service[%d]\n", ctx->sssd_realm, realm, family,
                                           socktype, svc));
diff --git a/server/providers/krb5/krb5_common.c b/server/providers/krb5/krb5_common.c
index 30878de..36e87f6 100644
--- a/server/providers/krb5/krb5_common.c
+++ b/server/providers/krb5/krb5_common.c
@@ -48,18 +48,6 @@ errno_t check_and_export_options(struct dp_option *opts,
     const char *dummy;
     struct stat stat_buf;
 
-    dummy = dp_opt_get_cstring(opts, KRB5_KDC);
-    if (dummy == NULL) {
-        DEBUG(1, ("No KDC configured, "
-                  "using kerberos defaults from /etc/krb5.conf"));
-    } else {
-        ret = setenv(SSSD_KRB5_KDC, dummy, 1);
-        if (ret != EOK) {
-            DEBUG(2, ("setenv %s failed, authentication might fail.\n",
-                      SSSD_KRB5_KDC));
-        }
-    }
-
     realm = dp_opt_get_cstring(opts, KRB5_REALM);
     if (realm == NULL) {
         ret = dp_opt_set_string(opts, KRB5_REALM, dom->name);
@@ -69,10 +57,17 @@ errno_t check_and_export_options(struct dp_option *opts,
         }
         realm = dom->name;
     }
-    ret = setenv(SSSD_KRB5_REALM, realm, 1);
-    if (ret != EOK) {
-        DEBUG(2, ("setenv %s failed, authentication might fail.\n",
-                  SSSD_KRB5_REALM));
+
+    dummy = dp_opt_get_cstring(opts, KRB5_KDC);
+    if (dummy == NULL) {
+        DEBUG(1, ("No KDC configured, "
+                  "using kerberos defaults from /etc/krb5.conf"));
+    } else {
+        ret = write_kdcinfo_file(realm, dummy);
+        if (ret != EOK) {
+            DEBUG(1, ("write_kdcinfo_file failed, "
+                      "using kerberos defaults from /etc/krb5.conf"));
+        }
     }
 
     dummy = dp_opt_get_cstring(opts, KRB5_CCACHEDIR);
@@ -155,3 +150,80 @@ done:
 
     return ret;
 }
+
+errno_t write_kdcinfo_file(const char *realm, const char *kdc)
+{
+    int ret;
+    int fd = -1;
+    char *tmp_name = NULL;
+    char *kdcinfo_name = NULL;
+    TALLOC_CTX *tmp_ctx = NULL;
+    int kdc_len;
+
+    if (realm == NULL || *realm == '\0' || kdc == NULL || *kdc == '\0') {
+        DEBUG(1, ("Missing or empty realm or kdc.\n"));
+        return EINVAL;
+    }
+
+    kdc_len = strlen(kdc);
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(1, ("talloc_new failed.\n"));
+        return ENOMEM;
+    }
+
+    tmp_name = talloc_asprintf(tmp_ctx, PUBCONF_PATH"/.kdcinfo_dummy_XXXXXX");
+    if (tmp_name == NULL) {
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    kdcinfo_name = talloc_asprintf(tmp_ctx, KDCINFO_TMPL, realm);
+    if (kdcinfo_name == NULL) {
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    fd = mkstemp(tmp_name);
+    if (fd == -1) {
+        DEBUG(1, ("mkstemp failed [%d][%s].\n", errno, strerror(errno)));
+        ret = errno;
+        goto done;
+    }
+
+    ret = write(fd, kdc, kdc_len);
+    if (ret == -1) {
+        DEBUG(1, ("write failed [%d][%s].\n", errno, strerror(errno)));
+        goto done;
+    }
+    if (ret != kdc_len) {
+        DEBUG(1, ("Partial write occured, this should never happen.\n"));
+        ret = EINTR;
+        goto done;
+    }
+
+    ret = fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+    if (ret == -1) {
+        DEBUG(1, ("fchmod failed [%d][%s].\n", errno, strerror(errno)));
+        goto done;
+    }
+
+    ret = close(fd);
+    if (ret == -1) {
+        DEBUG(1, ("close failed [%d][%s].\n", errno, strerror(errno)));
+        goto done;
+    }
+
+    ret = rename(tmp_name, kdcinfo_name);
+    if (ret == -1) {
+        DEBUG(1, ("rename failed [%d][%s].\n", errno, strerror(errno)));
+        goto done;
+    }
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/server/providers/krb5/krb5_common.h b/server/providers/krb5/krb5_common.h
index cb60f42..f5fe2bb 100644
--- a/server/providers/krb5/krb5_common.h
+++ b/server/providers/krb5/krb5_common.h
@@ -37,6 +37,8 @@
 #define SSSD_KRB5_REALM "SSSD_KRB5_REALM"
 #define SSSD_KRB5_CHANGEPW_PRINCIPLE "SSSD_KRB5_CHANGEPW_PRINCIPLE"
 
+#define KDCINFO_TMPL PUBCONF_PATH"/kdcinfo.%s"
+
 enum krb5_opts {
     KRB5_KDC = 0,
     KRB5_REALM,
@@ -55,4 +57,6 @@ errno_t check_and_export_options(struct dp_option *opts,
 
 errno_t krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
                          const char *conf_path, struct dp_option **_opts);
+
+errno_t write_kdcinfo_file(const char *realm, const char *kdc);
 #endif /* __KRB5_COMMON_H__ */
-- 
1.6.2.5



More information about the sssd-devel mailing list