From 827c611c801122042d9ca34be2eb5d11a04bb87b Mon Sep 17 00:00:00 2001
From: Ariel Barria <olivares73@hotmail.com>
Date: Mon, 13 May 2013 17:45:33 -0500
Subject: [PATCH] fall back to defaults from krb5.conf if the realm is not
 specified  explicitly in sssd.conf

Make the krb5_realm option optional and fall back to getting
the realm of system defaults.

https://fedorahosted.org/sssd/ticket/570
---
 src/man/sssd-ipa.5.xml           |  6 ++++--
 src/man/sssd-krb5.5.xml          |  6 ++++--
 src/providers/ipa/ipa_common.c   | 14 ++++++------
 src/providers/krb5/krb5_common.c | 46 ++++++++++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |  2 ++
 src/providers/krb5/krb5_init.c   | 13 ++++++++----
 6 files changed, 72 insertions(+), 15 deletions(-)

diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
index ad8ba08613473654e8bd5bdd8ec65436bbe5a9f2..dc36556c67ceed27fc8421c76f44474e614e1531 100644
--- a/src/man/sssd-ipa.5.xml
+++ b/src/man/sssd-ipa.5.xml
@@ -367,8 +367,10 @@
                     <term>krb5_realm (string)</term>
                     <listitem>
                         <para>
-                            The name of the Kerberos realm. This is optional and
-                            defaults to the value of <quote>ipa_domain</quote>.
+                            The name of the Kerberos realm. This is optional.
+                        </para>
+                        <para>
+                            Default: System defaults, see <filename>/etc/krb5.conf</filename>
                         </para>
                         <para>
                             The name of the Kerberos realm has a special
diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index 731d772544bca553958a8e0099de9a537a39fe87..3787117b48264e6077b84540c69adb0803bf2fd4 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -103,8 +103,10 @@
                     <term>krb5_realm (string)</term>
                     <listitem>
                         <para>
-                            The name of the Kerberos realm. This option is required
-                            and must be specified.
+                            The name of the Kerberos realm. This option is optional.
+                        </para>
+                        <para>
+                            Default: System defaults, see <filename>/etc/krb5.conf</filename>
                         </para>
                     </listitem>
                 </varlistentry>
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index baece274ed48b9446806bf1103789b2ace9c0d95..86b5194789b8acb8a75676d99ba91490921d1e16 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -94,20 +94,20 @@ int ipa_get_options(TALLOC_CTX *memctx,
     }
 
     /* First check whether the realm has been manually specified */
-    realm = dp_opt_get_string(opts->basic, IPA_KRB5_REALM);
-    if (!realm) {
+    ret = krb5_get_realm(memctx, opts->basic, &realm);
+    if (ret != EOK) {
         /* No explicit krb5_realm, use the IPA domain, transform to upper-case */
         realm = get_uppercase_realm(opts, domain);
         if (!realm) {
             ret = ENOMEM;
             goto done;
         }
+    }
 
-        ret = dp_opt_set_string(opts->basic, IPA_KRB5_REALM,
-                                realm);
-        if (ret != EOK) {
-            goto done;
-        }
+    ret = dp_opt_set_string(opts->basic, IPA_KRB5_REALM, realm);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
+        goto done;
     }
 
     ret = EOK;
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index c6865c09960463b8648957cb777d0d2b4e7b1dde..8071560e8521084f919d8c929a30034320f038c1 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -919,3 +919,49 @@ errno_t compare_principal_realm(const char *upn, const char *realm,
 
     return EOK;
 }
+errno_t krb5_get_realm(TALLOC_CTX *mem_ctx, struct dp_option *opts,
+                       char **_realm)
+{
+    int ret;
+    char *krb5_realm;
+    char *default_realm = NULL;
+    krb5_error_code kerr = 0;
+    krb5_context krb_ctx = NULL;
+
+    krb5_realm = dp_opt_get_string(opts, KRB5_REALM);
+
+    if (krb5_realm == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE,
+             ("Missing krb5_realm option, will use libkrb default\n"));
+        kerr = krb5_init_context(&krb_ctx);
+        if (kerr) {
+            DEBUG(SSSDBG_OP_FAILURE, ("Failed to init kerberos context\n"));
+            return kerr;
+        }
+        kerr = krb5_get_default_realm(krb_ctx, &default_realm);
+        if (kerr) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                 ("Failed to get default realm name: %s\n",
+                  sss_krb5_get_error_message(krb_ctx, kerr)));
+            ret = kerr;
+            goto fail;
+        }
+        krb5_realm = talloc_strdup(mem_ctx, default_realm);
+        krb5_free_default_realm(krb_ctx, default_realm);
+        if (!krb5_realm) {
+            ret = KRB5KRB_ERR_GENERIC;
+            goto fail;
+        }
+        *_realm = krb5_realm;
+    }
+
+    DEBUG(SSSDBG_TRACE_INTERNAL, ("got krb5_realm: [%s]\n", krb5_realm));
+
+    if (krb_ctx) krb5_free_context(krb_ctx);
+
+    return EOK;
+
+    fail:
+        if (krb_ctx) krb5_free_context(krb_ctx);
+        return ret;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 85049360d729d5f4ab0063d7a9a81a28322f2393..2cf7c98a981738daed38a8df9b058a21945acfc1 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -182,6 +182,8 @@ errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx,
 errno_t compare_principal_realm(const char *upn, const char *realm,
                                 bool *different_realm);
 
+errno_t krb5_get_realm(TALLOC_CTX *mem_ctx, struct dp_option *opts,
+                       char **_realm);
 
 int sssm_krb5_auth_init(struct be_ctx *bectx,
                         struct bet_ops **ops,
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 1821d5b3421cc04b1a0ba0104a2ac070ac23519f..26b02a4986776c7e0394091390be522a5927441d 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -102,10 +102,15 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     krb5_servers = dp_opt_get_string(ctx->opts, KRB5_KDC);
     krb5_backup_servers = dp_opt_get_string(ctx->opts, KRB5_BACKUP_KDC);
 
-    krb5_realm = dp_opt_get_string(ctx->opts, KRB5_REALM);
-    if (krb5_realm == NULL) {
-        DEBUG(0, ("Missing krb5_realm option!\n"));
-        return EINVAL;
+    ret = krb5_get_realm(ctx, krb5_options->opts, &krb5_realm);
+    if (ret != EOK) {
+        return ret;
+    }
+    ret = dp_opt_set_string(krb5_options->opts, KRB5_REALM, krb5_realm);
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("dp_opt_set_string failed.\n"));
+        return ret;
     }
 
     ret = krb5_service_init(ctx, bectx, SSS_KRB5KDC_FO_SRV, krb5_servers,
-- 
1.8.1.4

