>From eb2791078e2b4cb473da7d94937ba359f7edd3f6 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Tue, 5 Jun 2012 15:07:10 -0400
Subject: [PATCH 10/12] Primary server support: new options in krb5 provider

This patch adds support for new config options krb5_backup_server and
krb5_backup_kpasswd. The description of this option's functionality
is included in man page in one of previous patches.
---
 src/config/SSSDConfig/__init__.py.in     |    2 ++
 src/config/SSSDConfigTest.py             |    6 ++++++
 src/config/etc/sssd.api.d/sssd-ad.conf   |    2 ++
 src/config/etc/sssd.api.d/sssd-ipa.conf  |    2 ++
 src/config/etc/sssd.api.d/sssd-krb5.conf |    2 ++
 src/man/sssd-krb5.5.xml                  |    4 ++--
 src/man/sssd-ldap.5.xml                  |    2 +-
 src/providers/ad/ad_opts.h               |    3 +++
 src/providers/ipa/ipa_opts.h             |    3 +++
 src/providers/krb5/krb5_common.h         |    2 ++
 src/providers/krb5/krb5_init.c           |   17 +++++++++++++----
 src/providers/krb5/krb5_opts.h           |    2 ++
 src/providers/ldap/ldap_opts.h           |    1 +
 src/providers/ldap/sdap.h                |    1 +
 14 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 48568843376b6cfa182ca8d1a1e706e023173952..c6ccbff0cca107889c573a4b2323bd3f7c343f93 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -145,6 +145,7 @@ option_strings = {
     # [provider/krb5]
     'krb5_kdcip' : _('Kerberos server address'),
     'krb5_server' : _('Kerberos server address'),
+    'krb5_backup_server' : _('Kerberos backup server address'),
     'krb5_realm' : _('Kerberos realm'),
     'krb5_auth_timeout' : _('Authentication timeout'),
 
@@ -163,6 +164,7 @@ option_strings = {
 
     # [provider/krb5/chpass]
     'krb5_kpasswd' : _('Server where the change password service is running if not on the KDC'),
+    'krb5_backup_kpasswd' : _('Server where the change password service is running if not on the KDC'),
 
     # [provider/ldap]
     'ldap_uri' : _('ldap_uri, The URI of the LDAP server'),
diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 95cb00995e3d42290c9d575b6cf5c2a2b7da3a12..eefbe786a9c9cce8882b070f687627dae73a76d1 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -581,8 +581,10 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
         backup_list = control_list[:]
         control_list.extend(
             ['krb5_server',
+             'krb5_backup_server',
              'krb5_realm',
              'krb5_kpasswd',
+             'krb5_backup_kpasswd',
              'krb5_ccachedir',
              'krb5_ccname_template',
              'krb5_keytab',
@@ -736,9 +738,11 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
         options = domain.list_provider_options('krb5', 'auth')
         control_list = [
             'krb5_server',
+            'krb5_backup_server',
             'krb5_kdcip',
             'krb5_realm',
             'krb5_kpasswd',
+            'krb5_backup_kpasswd',
             'krb5_ccachedir',
             'krb5_ccname_template',
             'krb5_keytab',
@@ -915,9 +919,11 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
         backup_list = control_list[:]
         control_list.extend(
             ['krb5_server',
+             'krb5_backup_server',
              'krb5_kdcip',
              'krb5_realm',
              'krb5_kpasswd',
+             'krb5_backup_kpasswd',
              'krb5_ccachedir',
              'krb5_ccname_template',
              'krb5_keytab',
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 6c323399e58fcebccb09539bb3779f4c2994d054..763ea0d460c73d35e6fdfed3cf149a9ec7231641 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -23,6 +23,7 @@ ldap_sasl_authid = str, None, false
 ldap_sasl_minssf = int, None, false
 krb5_kdcip = str, None, false
 krb5_server = str, None, false
+krb5_backup_server = str, None, false
 krb5_realm = str, None, false
 krb5_auth_timeout = int, None, false
 krb5_canonicalize = bool, None, false
@@ -120,3 +121,4 @@ krb5_fast_principal = str, None, false
 
 [provider/ad/chpass]
 krb5_kpasswd = str, None, false
+krb5_backup_kpasswd = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index fa380a672db031abf7b3337a2909400c1841817c..cf16ea6e9dd8edae753bee8d893b8a51255c5ce9 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -29,9 +29,11 @@ ldap_sasl_authid = str, None, false
 ldap_sasl_minssf = int, None, false
 krb5_kdcip = str, None, false
 krb5_server = str, None, false
+krb5_backup_server = str, None, false
 krb5_realm = str, None, false
 krb5_auth_timeout = int, None, false
 krb5_kpasswd = str, None, false
+krb5_backup_kpasswd = str, None, false
 krb5_canonicalize = bool, None, false
 ldap_krb5_keytab = str, None, false
 ldap_krb5_init_creds = bool, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-krb5.conf b/src/config/etc/sssd.api.d/sssd-krb5.conf
index c52df1a6d9cd20eecfb13c5cea446fa7b61d4280..3a36f5efb5e9ee8733489580dbf0a7d08aa0acc9 100644
--- a/src/config/etc/sssd.api.d/sssd-krb5.conf
+++ b/src/config/etc/sssd.api.d/sssd-krb5.conf
@@ -1,9 +1,11 @@
 [provider/krb5]
 krb5_kdcip = str, None, false
 krb5_server = str, None, false
+krb5_backup_server = str, None, false
 krb5_realm = str, None, true
 krb5_auth_timeout = int, None, false
 krb5_kpasswd = str, None, false
+krb5_backup_kpasswd = str, None, false
 
 [provider/krb5/auth]
 krb5_ccachedir = str, None, false
diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
index efc84e2402d2e826c845cb2a4f2abd1a1628c127..f4fd1cb73941e23d8e39d234bf8fd2ae8ae54554 100644
--- a/src/man/sssd-krb5.5.xml
+++ b/src/man/sssd-krb5.5.xml
@@ -71,7 +71,7 @@
             for details on the configuration of a SSSD domain.
             <variablelist>
                 <varlistentry>
-                    <term>krb5_server (string)</term>
+                    <term>krb5_server, krb5_backup_server (string)</term>
                     <listitem>
                         <para>
                             Specifies the comma-separated list of IP addresses or hostnames
@@ -110,7 +110,7 @@
                 </varlistentry>
 
                 <varlistentry>
-                    <term>krb5_kpasswd (string)</term>
+                    <term>krb5_kpasswd, krb5_backup_kpasswd (string)</term>
                     <listitem>
                         <para>
                             If the change password service is not running on the
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 93d5783af3876b7dc40c3e5376d94061bde61ee0..e7d49c96fb74c089f4340c758e59ca11f06a9325 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -1474,7 +1474,7 @@
                 </varlistentry>
 
                 <varlistentry>
-                    <term>krb5_server (string)</term>
+                    <term>krb5_server, krb5_backup_server (string)</term>
                     <listitem>
                         <para>
                             Specifies the comma-separated list of IP addresses or hostnames
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index 41491ddc2bee060388a6ff49862c0dbe40825702..458e7ea4d717d300e8f407d514100e43974d40e3 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -83,6 +83,7 @@ struct dp_option ad_def_ldap_opts[] = {
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "ldap_pwd_policy", DP_OPT_STRING, { "none" }, NULL_STRING },
@@ -123,6 +124,7 @@ struct dp_option ad_def_ldap_opts[] = {
 
 struct dp_option ad_def_krb5_opts[] = {
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
     { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
@@ -130,6 +132,7 @@ struct dp_option ad_def_krb5_opts[] = {
     { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, 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 },
     { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 4925c599f33a4f86da6419a2ae570c6cc0706ebb..bf1b7a33d9e7b6f0a6be3d165168843e46d13691 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -96,6 +96,7 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ldap_pwd_policy", DP_OPT_STRING, { "none" } , NULL_STRING },
@@ -241,6 +242,7 @@ struct sdap_attr_map ipa_selinux_user_map[] = {
 
 struct dp_option ipa_def_krb5_opts[] = {
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
     { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
@@ -248,6 +250,7 @@ struct dp_option ipa_def_krb5_opts[] = {
     { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, 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 },
     { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 337fcf55fe5bd09550e44aec3aef3a70280bfe3a..51bd26773aeab8cd117425f19269974759f12ff8 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -49,6 +49,7 @@
 
 enum krb5_opts {
     KRB5_KDC = 0,
+    KRB5_BACKUP_KDC,
     KRB5_REALM,
     KRB5_CCACHEDIR,
     KRB5_CCNAME_TMPL,
@@ -56,6 +57,7 @@ enum krb5_opts {
     KRB5_KEYTAB,
     KRB5_VALIDATE,
     KRB5_KPASSWD,
+    KRB5_BACKUP_KPASSWD,
     KRB5_STORE_PASSWORD_IF_OFFLINE,
     KRB5_RENEWABLE_LIFETIME,
     KRB5_LIFETIME,
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 60c18a8f0cc095e99d227ac58cf9633d36ad09a5..a7b06fdf1004aa6199196ae2d1433e49eb4d0e46 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -61,7 +61,9 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     struct krb5_ctx *ctx = NULL;
     int ret;
     const char *krb5_servers;
+    const char *krb5_backup_servers;
     const char *krb5_kpasswd_servers;
+    const char *krb5_backup_kpasswd_servers;
     const char *krb5_realm;
     const char *errstr;
     int errval;
@@ -98,9 +100,7 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     ctx->opts = krb5_options->opts;
 
     krb5_servers = dp_opt_get_string(ctx->opts, KRB5_KDC);
-    if (krb5_servers == NULL) {
-        DEBUG(SSSDBG_CONF_SETTINGS, ("Missing krb5_server option, using service discovery!\n"));
-    }
+    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) {
@@ -109,13 +109,22 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     }
 
     ret = krb5_service_init(ctx, bectx, SSS_KRB5KDC_FO_SRV, krb5_servers,
-                            NULL, krb5_realm, &ctx->service);
+                            krb5_backup_servers, krb5_realm, &ctx->service);
     if (ret != EOK) {
         DEBUG(0, ("Failed to init KRB5 failover service!\n"));
         return ret;
     }
 
     krb5_kpasswd_servers = dp_opt_get_string(ctx->opts, KRB5_KPASSWD);
+    krb5_backup_kpasswd_servers = dp_opt_get_string(ctx->opts,
+                                                       KRB5_BACKUP_KPASSWD);
+    if (krb5_kpasswd_servers == NULL && krb5_backup_kpasswd_servers != NULL) {
+        DEBUG(SSSDBG_CONF_SETTINGS, ("kpasswd server wasn't specified but "
+                                     "backup kpasswd given. Using it as primary\n"));
+        krb5_kpasswd_servers = krb5_backup_kpasswd_servers;
+        krb5_backup_kpasswd_servers = NULL;
+    }
+
     if (krb5_kpasswd_servers == NULL && krb5_servers != NULL) {
         DEBUG(0, ("Missing krb5_kpasswd option and KDC set explicitly, "
                   "will use KDC for pasword change operations!\n"));
diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h
index 9de93b0cd725b15210263b282514af94f9dd9473..dc9b176485a53d7a5bad5c90ae6b9c8ae71a6873 100644
--- a/src/providers/krb5/krb5_opts.h
+++ b/src/providers/krb5/krb5_opts.h
@@ -27,6 +27,7 @@
 
 struct dp_option default_krb5_opts[] = {
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_ccachedir", DP_OPT_STRING, { DEFAULT_CCACHE_DIR }, NULL_STRING },
     { "krb5_ccname_template", DP_OPT_STRING, { DEFAULT_CCNAME_TEMPLATE }, NULL_STRING},
@@ -34,6 +35,7 @@ struct dp_option default_krb5_opts[] = {
     { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, 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 },
     { "krb5_store_password_if_offline", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING },
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index 9be6a0f65ff1e169398df42eabf5c9cbebb698eb..4e876bdcc55b001fa62c861a94e7721f1e7ff357 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -76,6 +76,7 @@ struct dp_option default_basic_opts[] = {
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
     { "krb5_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+    { "krb5_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ldap_pwd_policy", DP_OPT_STRING, { "none" }, NULL_STRING },
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 70b4e6ada58e4b53130272758e1294270f4622e9..01c33e42117281dbebebfdd8240d468d657ae522 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -194,6 +194,7 @@ enum sdap_basic_opt {
     SDAP_KRB5_KEYTAB,
     SDAP_KRB5_KINIT,
     SDAP_KRB5_KDC,
+    SDAP_KRB5_BACKUP_KDC,
     SDAP_KRB5_REALM,
     SDAP_KRB5_CANONICALIZE,
     SDAP_PWD_POLICY,
-- 
1.7.7.6

