components/krb5/patches/035-multi-master.patch
changeset 5490 9bf0bc57423a
child 5969 96bac9fbcfbd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/krb5/patches/035-multi-master.patch	Wed Feb 24 10:43:57 2016 -0600
@@ -0,0 +1,692 @@
+#
+# 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);