[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