target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
        target->cr_raw_principal = kstrdup(source->cr_raw_principal,
                                                                GFP_KERNEL);
-       if ((source->cr_principal && ! target->cr_principal) ||
-           (source->cr_raw_principal && ! target->cr_raw_principal))
+       target->cr_targ_princ = kstrdup(source->cr_targ_princ, GFP_KERNEL);
+       if ((source->cr_principal && !target->cr_principal) ||
+           (source->cr_raw_principal && !target->cr_raw_principal) ||
+           (source->cr_targ_princ && !target->cr_targ_princ))
                return -ENOMEM;
 
        target->cr_flavor = source->cr_flavor;
                || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
                || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
                return false;
+       /* XXX: check that cr_targ_princ fields match ? */
        if (cr1->cr_principal == cr2->cr_principal)
                return true;
        if (!cr1->cr_principal || !cr2->cr_principal)
 
        /* name of form servicetype@hostname, passed down by
         * rpc.svcgssd, or computed from the above: */
        char                    *cr_principal;
+       char                    *cr_targ_princ;
        struct gss_api_mech     *cr_gss_mech;
 };
 
        cred->cr_group_info = NULL;
        cred->cr_raw_principal = NULL;
        cred->cr_principal = NULL;
+       cred->cr_targ_princ = NULL;
        cred->cr_gss_mech = NULL;
 }
 
                put_group_info(cred->cr_group_info);
        kfree(cred->cr_raw_principal);
        kfree(cred->cr_principal);
+       kfree(cred->cr_targ_princ);
        gss_mech_put(cred->cr_gss_mech);
        init_svc_cred(cred);
 }
 
        return 0;
 }
 
+static char *gssp_stringify(struct xdr_netobj *netobj)
+{
+       return kstrndup(netobj->data, netobj->len, GFP_KERNEL);
+}
+
+static void gssp_hostbased_service(char **principal)
+{
+       char *c;
+
+       if (!*principal)
+               return;
+
+       /* terminate and remove realm part */
+       c = strchr(*principal, '@');
+       if (c) {
+               *c = '\0';
+
+               /* change service-hostname delimiter */
+               c = strchr(*principal, '/');
+               if (c)
+                       *c = '@';
+       }
+       if (!c) {
+               /* not a service principal */
+               kfree(*principal);
+               *principal = NULL;
+       }
+}
+
 /*
  * Public functions
  */
                 */
                .exported_context_token.len = GSSX_max_output_handle_sz,
                .mech.len = GSS_OID_MAX_LEN,
+               .targ_name.display_name.len = GSSX_max_princ_sz,
                .src_name.display_name.len = GSSX_max_princ_sz
        };
        struct gssx_res_accept_sec_context res = {
                .rpc_cred = NULL, /* FIXME ? */
        };
        struct xdr_netobj client_name = { 0 , NULL };
+       struct xdr_netobj target_name = { 0, NULL };
        int ret;
 
        if (data->in_handle.len != 0)
        if (ret)
                return ret;
 
-       /* use nfs/ for targ_name ? */
-
        ret = gssp_call(net, &msg);
 
        gssp_free_receive_pages(&arg);
                        kfree(rctxh.mech.data);
                }
                client_name = rctxh.src_name.display_name;
+               target_name = rctxh.targ_name.display_name;
        }
 
        if (res.options.count == 1) {
        }
 
        /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */
-       if (data->found_creds && client_name.data != NULL) {
-               char *c;
-
-               data->creds.cr_raw_principal = kstrndup(client_name.data,
-                                               client_name.len, GFP_KERNEL);
-
-               data->creds.cr_principal = kstrndup(client_name.data,
-                                               client_name.len, GFP_KERNEL);
-               if (data->creds.cr_principal) {
-                       /* terminate and remove realm part */
-                       c = strchr(data->creds.cr_principal, '@');
-                       if (c) {
-                               *c = '\0';
-
-                               /* change service-hostname delimiter */
-                               c = strchr(data->creds.cr_principal, '/');
-                               if (c) *c = '@';
-                       }
-                       if (!c) {
-                               /* not a service principal */
-                               kfree(data->creds.cr_principal);
-                               data->creds.cr_principal = NULL;
-                       }
+       if (data->found_creds) {
+               if (client_name.data) {
+                       data->creds.cr_raw_principal =
+                                       gssp_stringify(&client_name);
+                       data->creds.cr_principal =
+                                       gssp_stringify(&client_name);
+                       gssp_hostbased_service(&data->creds.cr_principal);
+               }
+               if (target_name.data) {
+                       data->creds.cr_targ_princ =
+                                       gssp_stringify(&target_name);
+                       gssp_hostbased_service(&data->creds.cr_targ_princ);
                }
        }
        kfree(client_name.data);
+       kfree(target_name.data);
 
        return ret;
 }