On Wed, 2015-11-25 at 14:34 +1000, Fraser Tweedale wrote:
> On Tue, Nov 24, 2015 at 02:36:17PM -0500, Simo Sorce wrote:
> > On Tue, 2015-11-24 at 17:34 +0100, Jan Cholasta wrote:
> > > On 24.11.2015 17:30, Simo Sorce wrote:
> > > > On Tue, 2015-11-24 at 09:14 +0100, Jan Cholasta wrote:
> > > >> On 24.11.2015 09:06, Petr Spacek wrote:
> > > >>> On 24.11.2015 07:32, Jan Cholasta wrote:
> > > >>>> On 23.11.2015 21:18, Simo Sorce wrote:
> > > >>>>> Fixes #2203 by reading the server name from /etc/ipa/default.conf 
> > > >>>>> if not
> > > >>>>> provided on the command line.
> > > >>>>>
> > > >>>>> Simo.
> > > >>>>
> > > >>>> Just a thought: it would be nice if we had libipaconfig and used it 
> > > >>>> everywhere
> > > >>>> (the framework, ipa-getkeytab, certmonger, ...). I don't like that 
> > > >>>> there are
> > > >>>> at least 3 ipa config parser implementations now, each with its own 
> > > >>>> quirks.
> > > >>>
> > > >>> Yeah, define a Augeas grammar for IPA config and call it. There is C 
> > > >>> and
> > > >>> Python binding in RHEL 7.2 already.
> > > >>
> > > >> This won't be sufficient, as it should go beyond just parsing the 
> > > >> config
> > > >> file - there are dynamic defaults and backward compatiblity support
> > > >> which should be the same everywhere too.
> > > >
> > > > This is a much bigger task, that someone keen on big refactoring may
> > > > undertake, but I do not think we should delay this useful feature for
> > > > that. It will be really easy to change this code to use whatever other
> > > > ipa library when it materializes.
> > > >
> > > > For now this patch stands IMHO.
> > > 
> > > Sure, I'm not suggesting otherwise.
> > 
> > Rebased patch that includes proper spec file buildrequires.
> > 
> > Simo.
> > 
> Tested and works as expected (great usability win IMO).
> 
> Man page should be updated accordingly.
> 
> Cheers,
> Fraser

Attached new patch that includes manpage changes.

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York
From 482b29614989a68d67e0eccf53f1fe8c5382527e Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Mon, 23 Nov 2015 14:50:04 -0500
Subject: [PATCH] Support sourcing the IPA server name from config

Use ding-libs to parse /etc/ipa/default.conf to find the IPA server
to contact by default.

Signed-off-by: Simo Sorce <s...@redhat.com>

Ticket: https://fedorahosted.org/freeipa/ticket/2203
---
 freeipa.spec.in                |  1 +
 ipa-client/Makefile.am         |  4 ++
 ipa-client/configure.ac        | 28 +++++++++++++
 ipa-client/ipa-getkeytab.c     | 93 +++++++++++++++++++++++++++++++++++++++++-
 ipa-client/man/ipa-getkeytab.1 | 12 +++---
 5 files changed, 132 insertions(+), 6 deletions(-)

diff --git a/freeipa.spec.in b/freeipa.spec.in
index d66b0ffe9eeb061c19642995aa19459673d61dec..5524576054ad77f7263e02642d1ae795aeb7077e 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -97,6 +97,7 @@ BuildRequires:  python-kdcproxy >= 0.3
 BuildRequires:  python-six
 BuildRequires:  python-jwcrypto
 BuildRequires:  custodia
+BuildRequires:  libini_config-devel >= 1.2.0
 
 # Build dependencies for unit tests
 BuildRequires:  libcmocka-devel
diff --git a/ipa-client/Makefile.am b/ipa-client/Makefile.am
index 0da351c6a28a4e2a216bec3f85d0500e4aef47ff..6c426779530f216b11dff0764132221ea2793289 100644
--- a/ipa-client/Makefile.am
+++ b/ipa-client/Makefile.am
@@ -15,6 +15,7 @@ export AM_CFLAGS
 KRB5_UTIL_DIR=../util
 KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
 ASN1_UTIL_DIR=../asn1
+IPA_CONF_FILE=$(sysconfdir)/ipa/default.conf
 
 AM_CPPFLAGS =							\
 	-I.							\
@@ -27,11 +28,13 @@ AM_CPPFLAGS =							\
 	-DLIBEXECDIR=\""$(libexecdir)"\"			\
 	-DDATADIR=\""$(datadir)"\"				\
 	-DLOCALEDIR=\""$(localedir)"\"				\
+	-DIPACONFFILE=\""$(IPA_CONF_FILE)"\"			\
 	$(KRB5_CFLAGS)						\
 	$(OPENLDAP_CFLAGS)					\
 	$(SASL_CFLAGS)						\
 	$(POPT_CFLAGS)						\
 	$(WARN_CFLAGS)						\
+	$(INI_CFLAGS)						\
 	$(NULL)
 
 sbin_PROGRAMS =			\
@@ -53,6 +56,7 @@ ipa_getkeytab_LDADD = 		\
 	$(SASL_LIBS)		\
 	$(POPT_LIBS)		\
 	$(LIBINTL_LIBS)         \
+	$(INI_LIBS)		\
 	$(NULL)
 
 ipa_rmkeytab_SOURCES =		\
diff --git a/ipa-client/configure.ac b/ipa-client/configure.ac
index 78da8e6e413b8becbd4c75422abffb670050f446..943c3f1b62f6a4947335178e9bcf1d45434a7e90 100644
--- a/ipa-client/configure.ac
+++ b/ipa-client/configure.ac
@@ -192,6 +192,34 @@ LIBS="$SAVELIBS"
 AC_SUBST(LIBINTL_LIBS)
 
 dnl ---------------------------------------------------------------------------
+dnl - Check for libini_config
+dnl ---------------------------------------------------------------------------
+PKG_CHECK_MODULES([LIBINI_CONFIG], [ini_config >= 1.2.0], [have_libini_config=1], [have_libini_config=])
+if test x$have_libini_config = x; then
+    AC_MSG_WARN([Could not find LIBINI_CONFIG headers])
+else
+    INI_CONFIG_CFLAGS="`$PKG_CONFIG --cflags ini_config`"
+    INI_CONFIG_LIBS="`$PKG_CONFIG --libs ini_config`"
+    AC_CHECK_LIB(ini_config, ini_config_file_open, [],
+                 [AC_MSG_WARN([ini_config library must support ini_config_file_open])],
+                 [$INI_CONFIG_LIBS])
+    AC_CHECK_LIB(ini_config, ini_config_augment, [],
+                 [AC_MSG_WARN([ini_config library must support ini_config_augment])],
+                 [$INI_CONFIG_LIBS])
+fi
+
+if test x$have_libini_config = x1; then
+    INI_CFLAGS="$INI_CONFIG_CFLAGS"
+    INI_LIBS="$INI_CONFIG_LIBS"
+else
+    AC_MSG_ERROR([ini_config development packages not available])
+fi
+
+AC_SUBST(INI_LIBS)
+AC_SUBST(INI_CFLAGS)
+
+
+dnl ---------------------------------------------------------------------------
 dnl - Set the data install directory since we don't use pkgdatadir
 dnl ---------------------------------------------------------------------------
 
diff --git a/ipa-client/ipa-getkeytab.c b/ipa-client/ipa-getkeytab.c
index a006b78a80166a2aa418e1221f2b80f32c872439..3592d9970412e91fa62b6ca8310a9511c4235656 100644
--- a/ipa-client/ipa-getkeytab.c
+++ b/ipa-client/ipa-getkeytab.c
@@ -36,6 +36,7 @@
 #include <ldap.h>
 #include <sasl/sasl.h>
 #include <popt.h>
+#include <ini_configobj.h>
 
 #include "config.h"
 
@@ -596,6 +597,81 @@ static char *ask_password(krb5_context krbctx)
     return password;
 }
 
+struct ipa_config {
+    const char *server_name;
+};
+
+static int config_from_file(struct ini_cfgobj *cfgctx)
+{
+    struct ini_cfgfile *fctx = NULL;
+    char **errors = NULL;
+    int ret;
+
+    ret = ini_config_file_open(IPACONFFILE, 0, &fctx);
+    if (ret) {
+        fprintf(stderr, _("Failed to open config file %s\n"), IPACONFFILE);
+        return ret;
+    }
+
+    ret = ini_config_parse(fctx,
+                           INI_STOP_ON_ANY,
+                           INI_MS_MERGE | INI_MV1S_ALLOW | INI_MV2S_ALLOW,
+                           INI_PARSE_NOWRAP,
+                           cfgctx);
+    if (ret) {
+        fprintf(stderr, _("Failed to parse config file %s\n"), IPACONFFILE);
+        if (ini_config_error_count(cfgctx)) {
+            ini_config_get_errors(cfgctx, &errors);
+            if (errors) {
+                ini_config_print_errors(stderr, errors);
+                ini_config_free_errors(errors);
+            }
+        }
+        ini_config_file_destroy(fctx);
+        return ret;
+    }
+
+    ini_config_file_destroy(fctx);
+    return 0;
+}
+
+int read_ipa_config(struct ipa_config **ipacfg)
+{
+    struct ini_cfgobj *cfgctx = NULL;
+    struct value_obj *obj = NULL;
+    int ret;
+
+    *ipacfg = calloc(1, sizeof(struct ipa_config));
+    if (!*ipacfg) {
+        return ENOMEM;
+    }
+
+    ret = ini_config_create(&cfgctx);
+    if (ret) {
+        return ENOENT;
+    }
+
+    ret = config_from_file(cfgctx);
+    if (ret) {
+        ini_config_destroy(cfgctx);
+        return EINVAL;
+    }
+
+    ret = ini_get_config_valueobj("global", "server", cfgctx,
+                                  INI_GET_LAST_VALUE, &obj);
+    if (ret != 0 || obj == NULL) {
+        /* if called on an IPA server we need to look for 'host' instead */
+        ret = ini_get_config_valueobj("global", "host", cfgctx,
+                                      INI_GET_LAST_VALUE, &obj);
+    }
+
+    if (ret == 0 && obj != NULL) {
+        (*ipacfg)->server_name = ini_get_string_config_value(obj, &ret);
+    }
+
+    return 0;
+}
+
 int main(int argc, const char *argv[])
 {
 	static const char *server = NULL;
@@ -688,7 +764,7 @@ int main(int argc, const char *argv[])
 		exit (0);
 	}
 
-	if (ret != -1 || !server || !principal || !keytab || permitted_enctypes) {
+	if (ret != -1 || !principal || !keytab || permitted_enctypes) {
 		if (!quiet) {
 			poptPrintUsage(pc, stderr, 0);
 		}
@@ -703,6 +779,21 @@ int main(int argc, const char *argv[])
 		exit(10);
 	}
 
+    if (!server) {
+        struct ipa_config *ipacfg = NULL;
+
+        ret = read_ipa_config(&ipacfg);
+        if (ret == 0) {
+            server = ipacfg->server_name;
+            ipacfg->server_name = NULL;
+        }
+        free(ipacfg);
+        if (!server) {
+            fprintf(stderr, _("Server name not provided and unavailable\n"));
+            exit(2);
+        }
+    }
+
     if (askpass && retrieve) {
         fprintf(stderr, _("Incompatible options provided (-r and -P)\n"));
         exit(2);
diff --git a/ipa-client/man/ipa-getkeytab.1 b/ipa-client/man/ipa-getkeytab.1
index bb84ad8f2b29f0753d48f480fc571ed6122ba539..1c270729e1ea224fb74271ad03dfb51c62d70465 100644
--- a/ipa-client/man/ipa-getkeytab.1
+++ b/ipa-client/man/ipa-getkeytab.1
@@ -21,7 +21,7 @@
 .SH "NAME"
 ipa\-getkeytab \- Get a keytab for a Kerberos principal
 .SH "SYNOPSIS"
-ipa\-getkeytab \fB\-s\fR \fIipaserver\fR \fB\-p\fR \fIprincipal\-name\fR \fB\-k\fR \fIkeytab\-file\fR [ \fB\-e\fR encryption\-types ] [ \fB\-q\fR ] [ \fB\-D\fR|\fB\-\-binddn\fR \fIBINDDN\fR ] [ \fB\-w|\-\-bindpw\fR ] [ \fB\-P\fR|\fB\-\-password\fR \fIPASSWORD\fR ] [ \fB\-r\fR ]
+ipa\-getkeytab \fB\-p\fR \fIprincipal\-name\fR \fB\-k\fR \fIkeytab\-file\fR [ \fB\-e\fR \fIencryption\-types\fR ] [ \fB\-s\fR \fIipaserver\fR ] [ \fB\-q\fR ] [ \fB\-D\fR|\fB\-\-binddn\fR \fIBINDDN\fR ] [ \fB\-w|\-\-bindpw\fR ] [ \fB\-P\fR|\fB\-\-password\fR \fIPASSWORD\fR ] [ \fB\-r\fR ]
 
 .SH "DESCRIPTION"
 Retrieves a Kerberos \fIkeytab\fR.
@@ -50,9 +50,6 @@ This renders all other keytabs for that principal invalid.
 This is used during IPA client enrollment to retrieve a host service principal and store it in /etc/krb5.keytab. It is possible to retrieve the keytab without Kerberos credentials if the host was pre\-created with a one\-time password. The keytab can be retrieved by binding as the host and authenticating with this one\-time password. The \fB\-D|\-\-binddn\fR and \fB\-w|\-\-bindpw\fR options are used for this authentication.
 .SH "OPTIONS"
 .TP
-\fB\-s ipaserver\fR
-The IPA server to retrieve the keytab from (FQDN).
-.TP
 \fB\-p principal\-name\fR
 The non\-realm part of the full principal name.
 .TP
@@ -73,6 +70,11 @@ des\-hmac\-sha1
 des\-cbc\-md5
 des\-cbc\-crc
 .TP
+\fB\-s ipaserver\fR
+The IPA server to retrieve the keytab from (FQDN). If this option is not
+provided the server name is read from the IPA configuration file
+(/etc/ipa/default.conf)
+.TP
 \fB\-q\fR
 Quiet mode. Only errors are displayed.
 .TP
@@ -105,7 +107,7 @@ keytab must have access to the keys for this operation to succeed.
 Add and retrieve a keytab for the NFS service principal on
 the host foo.example.com and save it in the file /tmp/nfs.keytab and retrieve just the des\-cbc\-crc key.
 
-   # ipa\-getkeytab \-s ipaserver.example.com \-p nfs/foo.example.com \-k /tmp/nfs.keytab \-e des\-cbc\-crc
+   # ipa\-getkeytab \-p nfs/foo.example.com \-k /tmp/nfs.keytab \-e des\-cbc\-crc
 
 Add and retrieve a keytab for the ldap service principal on
 the host foo.example.com and save it in the file /tmp/ldap.keytab.
-- 
2.5.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to