components/krb5/patches/035-multi-master.patch
author Will Fiveash <will.fiveash@oracle.com>
Wed, 24 Feb 2016 10:43:57 -0600
changeset 5490 9bf0bc57423a
child 5969 96bac9fbcfbd
permissions -rw-r--r--
PSARC/2015/144 Kerberos 1.13 Delivery to Userland 19153034 Add MIT Kerberos to the Userland Consolidation

#
# This patch provides support in kadmin and kpropd to work in a
# multi-master environment.
#
# Note that we have discussed support for this with MIT in the past but
# they have been reticent to add such support.  It is possible that
# support for this may be introduced at a later time at which point we
# should look at modifying/deleting this patch.
# Patch source: in-house
#
diff -u -r old/src/kadmin/cli/kadmin.c new/src/kadmin/cli/kadmin.c
--- old/src/kadmin/cli/kadmin.c	2015-05-28 15:10:45.129616302 -0500
+++ new/src/kadmin/cli/kadmin.c	2015-05-29 13:32:41.901105712 -0500
@@ -268,7 +268,7 @@
     char **db_args = NULL;
     int db_args_size = 0;
     char *db_name = NULL;
-    char *svcname, *realm;
+    char **svcnames = NULL, *realm;
 
     memset(&params, 0, sizeof(params));
 
@@ -380,11 +380,6 @@
     params.mask |= KADM5_CONFIG_REALM;
     params.realm = def_realm;
 
-    if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)
-        svcname = KADM5_ADMIN_SERVICE;
-    else
-        svcname = NULL;
-
     /*
      * Set cc to an open credentials cache, either specified by the -c
      * argument or the default.
@@ -515,13 +510,15 @@
     if (ccache_name) {
         printf(_("Authenticating as principal %s with existing "
                  "credentials.\n"), princstr);
-        retval = kadm5_init_with_creds(context, princstr, cc, svcname, &params,
+        retval = kadm5_init_with_creds_mm(context, princstr, cc, svcnames,
+                                       &params,
                                        KADM5_STRUCT_VERSION,
                                        KADM5_API_VERSION_4, db_args, &handle);
     } else if (use_anonymous) {
         printf(_("Authenticating as principal %s with password; "
                  "anonymous requested.\n"), princstr);
-        retval = kadm5_init_anonymous(context, princstr, svcname, &params,
+        retval = kadm5_init_anonymous_mm(context, princstr, svcnames,
+                                      &params,
                                       KADM5_STRUCT_VERSION,
                                       KADM5_API_VERSION_4, db_args, &handle);
     } else if (use_keytab) {
@@ -531,17 +528,20 @@
         else
             printf(_("Authenticating as principal %s with default keytab.\n"),
                    princstr);
-        retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname,
+        retval = kadm5_init_with_skey_mm(context, princstr, keytab_name,
+                                      svcnames,
                                       &params, KADM5_STRUCT_VERSION,
                                       KADM5_API_VERSION_4, db_args, &handle);
     } else {
         printf(_("Authenticating as principal %s with password.\n"),
                princstr);
-        retval = kadm5_init_with_password(context, princstr, password, svcname,
+        retval = kadm5_init_with_password_mm(context, princstr, password,
+                                          svcnames,
                                           &params, KADM5_STRUCT_VERSION,
                                           KADM5_API_VERSION_4, db_args,
                                           &handle);
     }
+    free_srv_names(svcnames);
     if (retval) {
         com_err(whoami, retval, _("while initializing %s interface"), whoami);
         if (retval == KADM5_BAD_CLIENT_PARAMS ||
diff -u -r old/src/lib/kadm5/admin.h new/src/lib/kadm5/admin.h
--- old/src/lib/kadm5/admin.h	2015-05-28 15:10:45.095122403 -0500
+++ new/src/lib/kadm5/admin.h	2015-05-28 15:34:35.800877732 -0500
@@ -345,6 +345,51 @@
                                      krb5_ui_4 api_version,
                                      char **db_args,
                                      void **server_handle);
+kadm5_ret_t kadm5_init_with_creds_mm(krb5_context context,
+                                     char *client_name,
+                                     krb5_ccache ccache,
+                                     char **svcnames,
+                                     kadm5_config_params *params,
+                                     krb5_ui_4 struct_version,
+                                     krb5_ui_4 api_version,
+                                     char **db_args,
+                                     void **server_handle);
+kadm5_ret_t kadm5_init_with_password_mm(krb5_context context,
+                                        char *client_name,
+                                        char *pass,
+                                        char **svcnames,
+                                        kadm5_config_params *params,
+                                        krb5_ui_4 struct_version,
+                                        krb5_ui_4 api_version,
+                                        char **db_args,
+                                        void **server_handle);
+kadm5_ret_t kadm5_init_anonymous_mm(krb5_context context,
+                                    char *client_name,
+                                    char **svcnames,
+                                    kadm5_config_params *params,
+                                    krb5_ui_4 struct_version,
+                                    krb5_ui_4 api_version,
+                                    char **db_args,
+                                    void **server_handle);
+kadm5_ret_t kadm5_init_mm(krb5_context context,
+                          char *client_name,
+                          char *pass,
+                          char **svcnames,
+                          kadm5_config_params *params,
+                          krb5_ui_4 struct_version,
+                          krb5_ui_4 api_version,
+                          char **db_args,
+                          void **server_handle);
+kadm5_ret_t kadm5_init_with_skey_mm(krb5_context context,
+                                    char *client_name,
+                                    char *keytab,
+                                    char **svcnames,
+                                    kadm5_config_params *params,
+                                    krb5_ui_4 struct_version,
+                                    krb5_ui_4 api_version,
+                                    char **db_args,
+                                    void **server_handle);
+
 kadm5_ret_t    kadm5_lock(void *server_handle);
 kadm5_ret_t    kadm5_unlock(void *server_handle);
 kadm5_ret_t    kadm5_flush(void *server_handle);
diff -u -r old/src/lib/kadm5/clnt/client_init.c new/src/lib/kadm5/clnt/client_init.c
--- old/src/lib/kadm5/clnt/client_init.c	2015-05-28 15:10:45.192975632 -0500
+++ new/src/lib/kadm5/clnt/client_init.c	2015-06-02 10:33:51.639341637 -0500
@@ -55,7 +55,7 @@
 
 static kadm5_ret_t
 init_any(krb5_context context, char *client_name, enum init_type init_type,
-         char *pass, krb5_ccache ccache_in, char *service_name,
+         char *pass, krb5_ccache ccache_in, char **service_names,
          kadm5_config_params *params, krb5_ui_4 struct_version,
          krb5_ui_4 api_version, char **db_args, void **server_handle);
 
@@ -87,8 +87,25 @@
                       krb5_ui_4 api_version, char **db_args,
                       void **server_handle)
 {
+    char *svcnames[2];
+
+    svcnames[0] = service_name;
+    svcnames[1] = NULL;
+
+    return init_any(context, client_name, INIT_CREDS, NULL, ccache,
+                    svcnames, params, struct_version, api_version, db_args,
+                    server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_creds_mm(krb5_context context, char *client_name,
+                      krb5_ccache ccache, char **svcnames,
+                      kadm5_config_params *params, krb5_ui_4 struct_version,
+                      krb5_ui_4 api_version, char **db_args,
+                      void **server_handle)
+{
     return init_any(context, client_name, INIT_CREDS, NULL, ccache,
-                    service_name, params, struct_version, api_version, db_args,
+                    svcnames, params, struct_version, api_version, db_args,
                     server_handle);
 }
 
@@ -99,7 +116,24 @@
                          krb5_ui_4 api_version, char **db_args,
                          void **server_handle)
 {
-    return init_any(context, client_name, INIT_PASS, pass, NULL, service_name,
+    char *svcnames[2];
+
+    svcnames[0] = service_name;
+    svcnames[1] = NULL;
+
+    return init_any(context, client_name, INIT_PASS, pass, NULL, svcnames,
+                    params, struct_version, api_version, db_args,
+                    server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_password_mm(krb5_context context, char *client_name,
+                         char *pass, char **svcnames,
+                         kadm5_config_params *params, krb5_ui_4 struct_version,
+                         krb5_ui_4 api_version, char **db_args,
+                         void **server_handle)
+{
+    return init_any(context, client_name, INIT_PASS, pass, NULL, svcnames,
                     params, struct_version, api_version, db_args,
                     server_handle);
 }
@@ -110,8 +144,24 @@
                      krb5_ui_4 struct_version, krb5_ui_4 api_version,
                      char **db_args, void **server_handle)
 {
+    char *svcnames[2];
+
+    svcnames[0] = service_name;
+    svcnames[1] = NULL;
+
+    return init_any(context, client_name, INIT_ANONYMOUS, NULL, NULL,
+                    svcnames, params, struct_version, api_version,
+                    db_args, server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_anonymous_mm(krb5_context context, char *client_name,
+                     char **svcnames, kadm5_config_params *params,
+                     krb5_ui_4 struct_version, krb5_ui_4 api_version,
+                     char **db_args, void **server_handle)
+{
     return init_any(context, client_name, INIT_ANONYMOUS, NULL, NULL,
-                    service_name, params, struct_version, api_version,
+                    svcnames, params, struct_version, api_version,
                     db_args, server_handle);
 }
 
@@ -121,7 +171,23 @@
            krb5_ui_4 struct_version, krb5_ui_4 api_version, char **db_args,
            void **server_handle)
 {
-    return init_any(context, client_name, INIT_PASS, pass, NULL, service_name,
+    char *svcnames[2];
+
+    svcnames[0] = service_name;
+    svcnames[1] = NULL;
+
+    return init_any(context, client_name, INIT_PASS, pass, NULL, svcnames,
+                    params, struct_version, api_version, db_args,
+                    server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_mm(krb5_context context, char *client_name, char *pass,
+           char **svcnames, kadm5_config_params *params,
+           krb5_ui_4 struct_version, krb5_ui_4 api_version, char **db_args,
+           void **server_handle)
+{
+    return init_any(context, client_name, INIT_PASS, pass, NULL, svcnames,
                     params, struct_version, api_version, db_args,
                     server_handle);
 }
@@ -133,8 +199,25 @@
                      krb5_ui_4 api_version, char **db_args,
                      void **server_handle)
 {
+    char *svcnames[2];
+
+    svcnames[0] = service_name;
+    svcnames[1] = NULL;
+
     return init_any(context, client_name, INIT_SKEY, keytab, NULL,
-                    service_name, params, struct_version, api_version, db_args,
+                    svcnames, params, struct_version, api_version, db_args,
+                    server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_skey_mm(krb5_context context, char *client_name,
+                     char *keytab, char **svcnames,
+                     kadm5_config_params *params, krb5_ui_4 struct_version,
+                     krb5_ui_4 api_version, char **db_args,
+                     void **server_handle)
+{
+    return init_any(context, client_name, INIT_SKEY, keytab, NULL,
+                    svcnames, params, struct_version, api_version, db_args,
                     server_handle);
 }
 
@@ -338,7 +421,7 @@
 	}
 
 	/*
-	 * iprop fallback logic: 
+	 * iprop fallback logic:
 	 *    - if iprop_port is configured, connect to iprop_port
 	 *    - if not, query remote rpc/bind
 	 *    - if that fails, try consuming iprop service on kadmin port
@@ -506,9 +589,35 @@
 	return (code);
 }
 
+/* utility function used below */
+static void
+clean_up(kadm5_server_handle_t handle,
+         krb5_principal *server,
+         krb5_ccache *ccache)
+{
+    if (handle->destroy_cache && handle->cache_name) {
+        if (krb5_cc_resolve(handle->context,
+                            handle->cache_name, &ccache) == 0)
+            (void) krb5_cc_destroy (handle->context, ccache);
+    }
+
+    free(handle->cache_name);
+    handle->cache_name = NULL;
+
+    if (handle->clnt && handle->clnt->cl_auth)
+        AUTH_DESTROY(handle->clnt->cl_auth);
+    if (handle->clnt) {
+        clnt_destroy(handle->clnt);
+        handle->clnt = NULL;
+    }
+
+    krb5_free_principal(handle->context, *server);
+    *server = NULL;
+}
+
 static kadm5_ret_t
 init_any(krb5_context context, char *client_name, enum init_type init_type,
-         char *pass, krb5_ccache ccache_in, char *svcname,
+         char *pass, krb5_ccache ccache_in, char **svcnames_in,
          kadm5_config_params *params_in, krb5_ui_4 struct_version,
          krb5_ui_4 api_version, char **db_args, void **server_handle)
 {
@@ -526,6 +635,10 @@
 
     int code = 0;
     generic_ret *r;
+    char **kadmin_srv_names = NULL;
+    char *tmp_srv_names[2] = {NULL, NULL};
+    char **svcname_ptr;
+    int i;
 
     initialize_ovk_error_table();
 /*      initialize_adb_error_table(); */
@@ -593,34 +706,56 @@
     if (code)
         goto error;
 
-    /* NULL svcname means use host-based. */
-    if (svcname == NULL) {
-	char **kadmin_srv_names;
+    if (svcnames_in == NULL || svcnames_in[0] == NULL) {
+        if (params_in && params_in->mask & KADM5_CONFIG_ADMIN_SERVER &&
+            params_in->admin_server != NULL) {
+            /* User passed in a admin server host name so use that */
+            if (asprintf(&tmp_srv_names[0], "%s@%s", KADM5_ADMIN_HOST_SERVICE,
+                         params_in->admin_server) == -1) {
+                code = ENOMEM;
+                goto error;
+            }
+            svcname_ptr = tmp_srv_names;
+        } else {
+            /* Otherwise punt and get the admin server names. */
+            code = kadm5_get_adm_host_srv_names(context, handle->params.realm,
+                                                &kadmin_srv_names);
+            if (code)
+                goto error;
+            svcname_ptr = kadmin_srv_names;
+        }
+    } else {
+        svcname_ptr = svcnames_in;
+    }
 
-	code = kadm5_get_adm_host_srv_names(context, handle->params.realm,
-	    &kadmin_srv_names);
-        if (code)
-            goto error;
-	svcname = strdup(kadmin_srv_names[0]);
-	free_srv_names(kadmin_srv_names);
-	if (svcname == NULL) {
-	    code = ENOMEM;
-            goto error;
-	}
+    for (i = 0; svcname_ptr[i]; i++) {
+        /* Get credentials. */
+        code = get_init_creds(handle, client, init_type, pass, ccache_in,
+                              svcname_ptr[i], handle->params.realm, &server);
+        if (code) {
+            if (code == KADM5_SECURE_PRINC_MISSING ||
+                code == KRB5_ERR_BAD_HOSTNAME) {
+                /* clean up for another go around */
+                clean_up(handle, &server, &ccache);
+                continue;
+            } else
+                goto error;
+        }
+
+        code = _kadm5_initialize_rpcsec_gss_handle(handle, client_name,
+                                                   svcname_ptr[i]);
+        if (code) {
+            /* clean up for another go around */
+            clean_up(handle, &server, &ccache);
+        } else {
+            /* inited the rpcsec_gss handle, can stop looping now */
+            break;
+        }
     }
 
-    /* Get credentials. */
-    code = get_init_creds(handle, client, init_type, pass, ccache_in,
-                          svcname, handle->params.realm, &server);
     if (code)
         goto error;
 
-    code = _kadm5_initialize_rpcsec_gss_handle(handle, client_name,
-                                               svcname);
-    if (code != 0) {
-        goto error;
-    }
-
     *server_handle = (void *) handle;
 
     goto cleanup;
@@ -653,6 +788,8 @@
     krb5_free_principal(handle->context, server);
     if (code)
         free(handle);
+    free_srv_names(kadmin_srv_names);
+    free(tmp_srv_names[0]);
 
     return code;
 }
@@ -665,46 +802,43 @@
 {
     kadm5_ret_t code;
     krb5_ccache ccache = NULL;
-    krb5_principal cprinc;
     char svcbuf[BUFSIZ], *service, *host, *svcname, *save;
+    char strtok_buf[BUFSIZ];
 
     *server_out = NULL;
 
-    /*
-     * Convert the RPCSEC_GSS version to the host based version as this
-     * is what gic expects.
-     */
-    if ((svcname = strdup(svcname_in)) == NULL) {
-	code = ENOMEM;
-	goto error;
-    }
-    if ((service = strtok_r(svcname, "@", &save)) != NULL) {
-	if ((host = strtok_r(NULL, "@", &save)) != NULL) {
-	    char *str = NULL;
-	    /*
-	     * We want the canonical name here, via sname_to_principal.
-	     */
-	    code = krb5_sname_to_principal(handle->context, host, service,
-		KRB5_NT_SRV_HST, &cprinc);
-	    if (code) {
-		free(svcname);
-		goto error;
-	    }
-	    code = krb5_unparse_name_flags(handle->context, cprinc,
-		KRB5_PRINCIPAL_UNPARSE_NO_REALM, &str);
-	    krb5_free_principal(handle->context, cprinc);
-	    if (code) {
-		free(svcname);
-		goto error;
-	    }
-	    (void) strncpy(svcbuf, str, sizeof(svcbuf));
-	    krb5_free_unparsed_name(handle->context, str);
-	}
+    if (strpbrk(svcname_in, "@") == NULL) {
+        svcname = svcname_in;
     } else {
-	strncpy(svcbuf, svcname, sizeof(svcbuf));
-	svcbuf[sizeof(svcname)-1] = '\0';
+        /*
+         * Convert the RPCSEC_GSS version to the host based version as this
+         * is what gic expects.
+         */
+        (void) strlcpy(strtok_buf, svcname_in, sizeof(strtok_buf));
+        service = strtok_r(strtok_buf, "@", &save);
+        if ((host = strtok_r(NULL, "@", &save)) != NULL) {
+            char *str = NULL;
+            krb5_principal cprinc;
+            /*
+             * We want the canonical name here, via sname_to_principal.
+             */
+            code = krb5_sname_to_principal(handle->context, host, service,
+                                           KRB5_NT_SRV_HST, &cprinc);
+            if (code)
+                goto error;
+
+            code = krb5_unparse_name_flags(handle->context, cprinc,
+                                           KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+                                           &str);
+            krb5_free_principal(handle->context, cprinc);
+            if (code)
+                goto error;
+
+            (void) strlcpy(svcbuf, str, sizeof(svcbuf));
+            krb5_free_unparsed_name(handle->context, str);
+            svcname = svcbuf;
+        }
     }
-    free(svcname);
 
     /*
      * Acquire a service ticket for svcname@realm for client, using password
@@ -741,7 +875,7 @@
     }
     handle->lhandle->cache_name = handle->cache_name;
 
-    code = gic_iter(handle, init_type, ccache, client, pass, svcbuf, realm,
+    code = gic_iter(handle, init_type, ccache, client, pass, svcname, realm,
                     server_out);
     /* Improved error messages */
     if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) code = KADM5_BAD_PASSWORD;
diff -u -r old/src/lib/kadm5/clnt/libkadm5clnt_mit.exports new/src/lib/kadm5/clnt/libkadm5clnt_mit.exports
--- old/src/lib/kadm5/clnt/libkadm5clnt_mit.exports	2015-02-11 21:16:43.000000000 -0600
+++ new/src/lib/kadm5/clnt/libkadm5clnt_mit.exports	2015-05-28 15:34:35.828495806 -0500
@@ -31,6 +31,11 @@
 kadm5_init_with_creds
 kadm5_init_with_password
 kadm5_init_with_skey
+kadm5_init_mm
+kadm5_init_anonymous_mm
+kadm5_init_with_creds_mm
+kadm5_init_with_password_mm
+kadm5_init_with_skey_mm
 kadm5_lock
 kadm5_modify_policy
 kadm5_modify_principal
diff -u -r old/src/lib/kadm5/srv/server_init.c new/src/lib/kadm5/srv/server_init.c
--- old/src/lib/kadm5/srv/server_init.c	2015-05-28 15:10:45.100182433 -0500
+++ new/src/lib/kadm5/srv/server_init.c	2015-05-29 12:40:47.354397224 -0500
@@ -97,6 +97,29 @@
                       server_handle);
 }
 
+/*
+ * The following *_mm() functions are also defined here because kadmin.local
+ * shares the same source as kadmin.  One difference however is that
+ * kadmin.local links with libkadm5srv_mit.so instead of libkadm5clnt_mit.so so
+ * these functions must also be defined here.  Given kadmin.local can only
+ * operate on one server, the *_mm() functions just pass in the first server in
+ * the list of service_names.
+ */
+kadm5_ret_t kadm5_init_with_password_mm(krb5_context context,
+                                        char *client_name,
+                                        char *pass, char **service_names,
+                                        kadm5_config_params *params,
+                                        krb5_ui_4 struct_version,
+                                        krb5_ui_4 api_version,
+                                        char **db_args,
+                                        void **server_handle)
+{
+    return kadm5_init_with_password(context, client_name, pass,
+                                    service_names ? service_names[0] : NULL,
+                                    params, struct_version, api_version,
+                                    db_args, server_handle);
+}
+
 kadm5_ret_t kadm5_init_anonymous(krb5_context context, char *client_name,
                                  char *service_name,
                                  kadm5_config_params *params,
@@ -110,6 +133,20 @@
                       server_handle);
 }
 
+kadm5_ret_t kadm5_init_anonymous_mm(krb5_context context, char *client_name,
+                                 char **service_names,
+                                 kadm5_config_params *params,
+                                 krb5_ui_4 struct_version,
+                                 krb5_ui_4 api_version,
+                                 char **db_args,
+                                 void **server_handle)
+{
+    return kadm5_init_anonymous(context, client_name,
+                                service_names ? service_names[0] : NULL,
+                                params, struct_version, api_version,
+                                db_args, server_handle);
+}
+
 kadm5_ret_t kadm5_init_with_creds(krb5_context context,
                                   char *client_name,
                                   krb5_ccache ccache,
@@ -133,6 +170,22 @@
                       server_handle);
 }
 
+kadm5_ret_t kadm5_init_with_creds_mm(krb5_context context,
+                                  char *client_name,
+                                  krb5_ccache ccache,
+                                  char **service_names,
+                                  kadm5_config_params *params,
+                                  krb5_ui_4 struct_version,
+                                  krb5_ui_4 api_version,
+                                  char **db_args,
+                                  void **server_handle)
+{
+    return kadm5_init_with_creds(context, client_name, ccache,
+                                 service_names ? service_names[0] : NULL,
+                                 params, struct_version, api_version,
+                                 db_args, server_handle);
+}
+
 
 kadm5_ret_t kadm5_init_with_skey(krb5_context context, char *client_name,
                                  char *keytab, char *service_name,
@@ -155,6 +208,20 @@
                       server_handle);
 }
 
+kadm5_ret_t kadm5_init_with_skey_mm(krb5_context context, char *client_name,
+                                 char *keytab, char **service_names,
+                                 kadm5_config_params *params,
+                                 krb5_ui_4 struct_version,
+                                 krb5_ui_4 api_version,
+                                 char **db_args,
+                                 void **server_handle)
+{
+    return kadm5_init_with_skey(context, client_name, keytab,
+                                service_names ? service_names[0] : NULL,
+                                params, struct_version, api_version, db_args,
+                                server_handle);
+}
+
 kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass,
                        char *service_name,
                        kadm5_config_params *params_in,
diff -u -r old/src/slave/kpropd.c new/src/slave/kpropd.c
--- old/src/slave/kpropd.c	2015-05-28 15:10:45.194095824 -0500
+++ new/src/slave/kpropd.c	2015-05-29 12:17:56.397347156 -0500
@@ -609,7 +609,7 @@
     kadm5_ret_t retval;
     krb5_principal iprop_svc_principal;
     void *server_handle = NULL;
-    char *iprop_svc_princstr = NULL, *master_svc_princstr = NULL;
+    char *iprop_svc_princstr = NULL, **master_svc_princstrs = NULL;
     unsigned int pollin, backoff_time;
     int backoff_cnt = 0, reinit_cnt = 0;
     struct timeval iprop_start, iprop_end;
@@ -639,22 +639,9 @@
     params.mask |= KADM5_CONFIG_REALM;
     params.realm = def_realm;
 
-    if (master_svc_princstr == NULL) {
-#if 0
-        retval = kadm5_get_kiprop_host_srv_name(kpropd_context, def_realm,
-                                                &master_svc_princstr);
-        if (retval) {
-            com_err(progname, retval,
-                    _("%s: unable to get kiprop host based "
-                      "service name for realm %s\n"),
-                    progname, def_realm);
-            return retval;
-        }
-#endif
-        char **kiprop_srv_names;
-
+    if (master_svc_princstrs == NULL) {
         retval = kadm5_get_kiprop_host_srv_names(kpropd_context, def_realm,
-						 &kiprop_srv_names);
+						 &master_svc_princstrs);
         if (retval) {
             com_err(progname, retval,
                     _("%s: unable to get kiprop host based "
@@ -662,15 +649,6 @@
                     progname, def_realm);
             return retval;
 	}
-        master_svc_princstr = strdup(kiprop_srv_names[0]);
-	free_srv_names(kiprop_srv_names);
-	if (master_svc_princstr == NULL) {
-            com_err(progname, retval,
-                    _("%s: unable to allocate memory for kiprop host based "
-                      "service name for realm %s\n"),
-                    progname, def_realm);
-            return ENOMEM;
-	}
     }
 
     retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME,
@@ -714,9 +692,9 @@
         fprintf(stderr, _("Initializing kadm5 as client %s\n"),
                 iprop_svc_princstr);
     }
-    retval = kadm5_init_with_skey(kpropd_context, iprop_svc_princstr,
+    retval = kadm5_init_with_skey_mm(kpropd_context, iprop_svc_princstr,
                                   srvtab,
-                                  master_svc_princstr,
+                                  master_svc_princstrs,
                                   &params,
                                   KADM5_STRUCT_VERSION,
                                   KADM5_API_VERSION_4,
@@ -1014,7 +992,7 @@
     syslog(LOG_ERR, _("ERROR returned by master KDC, bailing.\n"));
 done:
     free(iprop_svc_princstr);
-    free(master_svc_princstr);
+    free_srv_names(master_svc_princstrs);
     krb5_free_default_realm(kpropd_context, def_realm);
     kadm5_destroy(server_handle);
     krb5_free_context(kpropd_context);