From f64a709a81286759e88a34c7ef192e1cdbe164ea Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzeleny@redhat.com>
Date: Tue, 5 Jun 2012 08:43:40 -0400
Subject: [PATCH 3/8] Primary server support: krb5 adaptation

This patch adds support for the primary server functionality
into krb5 provider. No secondary servers are added at the moment,
just the basic support is in place.
---
 src/providers/krb5/krb5_common.c |  133 +++++++++++++++++++++++++-------------
 src/providers/krb5/krb5_common.h |    4 +-
 src/providers/krb5/krb5_init.c   |    4 +-
 3 files changed, 93 insertions(+), 48 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index ebdbe55c2da5a15ce1a9e0f67eb006ddc4fe7493..e6c81316bc1d5d59c72023ea3a120b3b96b89098 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -428,15 +428,15 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server)
     return;
 }
 
-
-int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-                      const char *service_name, const char *servers,
-                      const char *realm, struct krb5_service **_service)
+errno_t krb5_servers_init(struct be_ctx *ctx,
+                          struct krb5_service *service,
+                          const char *service_name,
+                          const char *servers,
+                          bool primary)
 {
     TALLOC_CTX *tmp_ctx;
-    struct krb5_service *service;
     char **list = NULL;
-    int ret;
+    errno_t ret;
     int i;
     char *port_str;
     long port;
@@ -444,42 +444,14 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     char *endptr;
     struct servent *servent;
 
-    tmp_ctx = talloc_new(memctx);
+    tmp_ctx = talloc_new(NULL);
     if (!tmp_ctx) {
         return ENOMEM;
     }
 
-    service = talloc_zero(tmp_ctx, struct krb5_service);
-    if (!service) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    ret = be_fo_add_service(ctx, service_name);
-    if (ret != EOK) {
-        DEBUG(1, ("Failed to create failover service!\n"));
-        goto done;
-    }
-
-    service->name = talloc_strdup(service, service_name);
-    if (!service->name) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    service->realm = talloc_strdup(service, realm);
-    if (!service->realm) {
-        ret = ENOMEM;
-        goto done;
-    }
-
-    if (!servers) {
-        servers = BE_SRV_IDENTIFIER;
-    }
-
     ret = split_on_separator(tmp_ctx, servers, ',', true, &list, NULL);
     if (ret != EOK) {
-        DEBUG(1, ("Failed to parse server list!\n"));
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to parse server list!\n"));
         goto done;
     }
 
@@ -496,11 +468,11 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
             ret = be_fo_add_srv_server(ctx, service_name, service_name, NULL,
                                        BE_FO_PROTO_UDP, true, NULL);
             if (ret) {
-                DEBUG(0, ("Failed to add server\n"));
+                DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
                 goto done;
             }
 
-            DEBUG(6, ("Added service lookup\n"));
+            DEBUG(SSSDBG_TRACE_FUNC, ("Added service lookup\n"));
             continue;
         }
 
@@ -515,26 +487,26 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
                 port = strtol(port_str, &endptr, 10);
                 if (errno != 0) {
                     ret = errno;
-                    DEBUG(1, ("strtol failed on [%s]: [%d][%s].\n", port_str,
+                    DEBUG(SSSDBG_CRIT_FAILURE, ("strtol failed on [%s]: [%d][%s].\n", port_str,
                               ret, strerror(ret)));
                     goto done;
                 }
                 if (*endptr != '\0') {
-                    DEBUG(1, ("Found additional characters [%s] in port number "
+                    DEBUG(SSSDBG_CRIT_FAILURE, ("Found additional characters [%s] in port number "
                               "[%s].\n", endptr, port_str));
                     ret = EINVAL;
                     goto done;
                 }
 
                 if (port < 1 || port > 65535) {
-                    DEBUG(1, ("Illegal port number [%d].\n", port));
+                    DEBUG(SSSDBG_CRIT_FAILURE, ("Illegal port number [%d].\n", port));
                     ret = EINVAL;
                     goto done;
                 }
             } else if (isalpha(*port_str)) {
                 servent = getservbyname(port_str, NULL);
                 if (servent == NULL) {
-                    DEBUG(1, ("getservbyname cannot find service [%s].\n",
+                    DEBUG(SSSDBG_CRIT_FAILURE, ("getservbyname cannot find service [%s].\n",
                               port_str));
                     ret = EINVAL;
                     goto done;
@@ -542,7 +514,7 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
 
                 port = servent->s_port;
             } else {
-                DEBUG(1, ("Unsupported port specifier in [%s].\n", list[i]));
+                DEBUG(SSSDBG_CRIT_FAILURE, ("Unsupported port specifier in [%s].\n", list[i]));
                 ret = EINVAL;
                 goto done;
             }
@@ -551,11 +523,82 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
         ret = be_fo_add_server(ctx, service_name, server_spec, (int) port,
                                list[i], true);
         if (ret && ret != EEXIST) {
-            DEBUG(0, ("Failed to add server\n"));
+            DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
             goto done;
         }
 
-        DEBUG(6, ("Added Server %s\n", list[i]));
+        DEBUG(SSSDBG_TRACE_FUNC, ("Added Server %s\n", list[i]));
+    }
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+                      const char *service_name,
+                      const char *primary_servers,
+                      const char *secondary_servers,
+                      const char *realm, struct krb5_service **_service)
+{
+    TALLOC_CTX *tmp_ctx;
+    struct krb5_service *service;
+    int ret;
+
+    tmp_ctx = talloc_new(memctx);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    service = talloc_zero(tmp_ctx, struct krb5_service);
+    if (!service) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = be_fo_add_service(ctx, service_name);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to create failover service!\n"));
+        goto done;
+    }
+
+    service->name = talloc_strdup(service, service_name);
+    if (!service->name) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    service->realm = talloc_strdup(service, realm);
+    if (!service->realm) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    if (!primary_servers) {
+        if (secondary_servers) {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  ("No primary servers defined but secondary are present, "
+                   "setting secondary servers as primary\n"));
+            primary_servers = secondary_servers;
+            secondary_servers = NULL;
+        } else {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  ("No primary or secondary servers defined but secondary are present, "
+                   "setting secondary servers as primary\n"));
+            primary_servers = BE_SRV_IDENTIFIER;
+        }
+    }
+
+    ret = krb5_servers_init(ctx, service, service_name, primary_servers, true);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    if (secondary_servers) {
+        ret = krb5_servers_init(ctx, service, service_name, secondary_servers, false);
+        if (ret != EOK) {
+            goto done;
+        }
     }
 
     ret = be_fo_service_add_callback(memctx, ctx, service_name,
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 950505f1208f164f9267aacbf49da136b3cc0073..dd5e0cec3b736b101c0a836233d3ddd72910e700 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -146,7 +146,9 @@ errno_t write_krb5info_file(const char *realm, const char *kdc,
                             const char *service);
 
 int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-                      const char *service_name, const char *servers,
+                      const char *service_name,
+                      const char *primary_servers,
+                      const char *secondary_servers,
                       const char *realm, struct krb5_service **_service);
 
 void remove_krb5_info_files_callback(void *pvt);
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 3c39d847e0b22a03ca95182e64c1b7b46a17bd90..74a1407548c6ac21d927083d59d60f87bd34a07e 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -111,7 +111,7 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
     }
 
     ret = krb5_service_init(ctx, bectx, SSS_KRB5KDC_FO_SRV, krb5_servers,
-                            krb5_realm, &ctx->service);
+                            NULL, krb5_realm, &ctx->service);
     if (ret != EOK) {
         DEBUG(0, ("Failed to init KRB5 failover service!\n"));
         return ret;
@@ -124,7 +124,7 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         ctx->kpasswd_service = NULL;
     } else {
         ret = krb5_service_init(ctx, bectx, SSS_KRB5KPASSWD_FO_SRV,
-                                krb5_kpasswd_servers, krb5_realm,
+                                krb5_kpasswd_servers, NULL, krb5_realm,
                                 &ctx->kpasswd_service);
         if (ret != EOK) {
             DEBUG(0, ("Failed to init KRB5KPASSWD failover service!\n"));
-- 
1.7.7.6

