Commit 9abdda5d authored by Chuck Lever's avatar Chuck Lever Committed by J. Bruce Fields

sunrpc: Extract target name into svc_cred

NFSv4.0 callback needs to know the GSS target name the client used
when it established its lease. That information is available from
the GSS context created by gssproxy. Make it available in each
svc_cred.

Note this will also give us access to the real target service
principal name (which is typically "nfs", but spec does not require
that).
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent a1a23777
...@@ -1979,8 +1979,10 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source) ...@@ -1979,8 +1979,10 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL); target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
target->cr_raw_principal = kstrdup(source->cr_raw_principal, target->cr_raw_principal = kstrdup(source->cr_raw_principal,
GFP_KERNEL); GFP_KERNEL);
if ((source->cr_principal && ! target->cr_principal) || target->cr_targ_princ = kstrdup(source->cr_targ_princ, GFP_KERNEL);
(source->cr_raw_principal && ! target->cr_raw_principal)) 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; return -ENOMEM;
target->cr_flavor = source->cr_flavor; target->cr_flavor = source->cr_flavor;
...@@ -2057,6 +2059,7 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2) ...@@ -2057,6 +2059,7 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
|| (!gid_eq(cr1->cr_gid, cr2->cr_gid)) || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
|| !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
return false; return false;
/* XXX: check that cr_targ_princ fields match ? */
if (cr1->cr_principal == cr2->cr_principal) if (cr1->cr_principal == cr2->cr_principal)
return true; return true;
if (!cr1->cr_principal || !cr2->cr_principal) if (!cr1->cr_principal || !cr2->cr_principal)
......
...@@ -31,6 +31,7 @@ struct svc_cred { ...@@ -31,6 +31,7 @@ struct svc_cred {
/* name of form servicetype@hostname, passed down by /* name of form servicetype@hostname, passed down by
* rpc.svcgssd, or computed from the above: */ * rpc.svcgssd, or computed from the above: */
char *cr_principal; char *cr_principal;
char *cr_targ_princ;
struct gss_api_mech *cr_gss_mech; struct gss_api_mech *cr_gss_mech;
}; };
...@@ -39,6 +40,7 @@ static inline void init_svc_cred(struct svc_cred *cred) ...@@ -39,6 +40,7 @@ static inline void init_svc_cred(struct svc_cred *cred)
cred->cr_group_info = NULL; cred->cr_group_info = NULL;
cred->cr_raw_principal = NULL; cred->cr_raw_principal = NULL;
cred->cr_principal = NULL; cred->cr_principal = NULL;
cred->cr_targ_princ = NULL;
cred->cr_gss_mech = NULL; cred->cr_gss_mech = NULL;
} }
...@@ -48,6 +50,7 @@ static inline void free_svc_cred(struct svc_cred *cred) ...@@ -48,6 +50,7 @@ static inline void free_svc_cred(struct svc_cred *cred)
put_group_info(cred->cr_group_info); put_group_info(cred->cr_group_info);
kfree(cred->cr_raw_principal); kfree(cred->cr_raw_principal);
kfree(cred->cr_principal); kfree(cred->cr_principal);
kfree(cred->cr_targ_princ);
gss_mech_put(cred->cr_gss_mech); gss_mech_put(cred->cr_gss_mech);
init_svc_cred(cred); init_svc_cred(cred);
} }
......
...@@ -234,6 +234,35 @@ static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) ...@@ -234,6 +234,35 @@ static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
return 0; 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 * Public functions
*/ */
...@@ -262,6 +291,7 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -262,6 +291,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
*/ */
.exported_context_token.len = GSSX_max_output_handle_sz, .exported_context_token.len = GSSX_max_output_handle_sz,
.mech.len = GSS_OID_MAX_LEN, .mech.len = GSS_OID_MAX_LEN,
.targ_name.display_name.len = GSSX_max_princ_sz,
.src_name.display_name.len = GSSX_max_princ_sz .src_name.display_name.len = GSSX_max_princ_sz
}; };
struct gssx_res_accept_sec_context res = { struct gssx_res_accept_sec_context res = {
...@@ -275,6 +305,7 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -275,6 +305,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
.rpc_cred = NULL, /* FIXME ? */ .rpc_cred = NULL, /* FIXME ? */
}; };
struct xdr_netobj client_name = { 0 , NULL }; struct xdr_netobj client_name = { 0 , NULL };
struct xdr_netobj target_name = { 0, NULL };
int ret; int ret;
if (data->in_handle.len != 0) if (data->in_handle.len != 0)
...@@ -285,8 +316,6 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -285,8 +316,6 @@ int gssp_accept_sec_context_upcall(struct net *net,
if (ret) if (ret)
return ret; return ret;
/* use nfs/ for targ_name ? */
ret = gssp_call(net, &msg); ret = gssp_call(net, &msg);
gssp_free_receive_pages(&arg); gssp_free_receive_pages(&arg);
...@@ -304,6 +333,7 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -304,6 +333,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
kfree(rctxh.mech.data); kfree(rctxh.mech.data);
} }
client_name = rctxh.src_name.display_name; client_name = rctxh.src_name.display_name;
target_name = rctxh.targ_name.display_name;
} }
if (res.options.count == 1) { if (res.options.count == 1) {
...@@ -325,32 +355,22 @@ int gssp_accept_sec_context_upcall(struct net *net, ...@@ -325,32 +355,22 @@ int gssp_accept_sec_context_upcall(struct net *net,
} }
/* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */ /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */
if (data->found_creds && client_name.data != NULL) { if (data->found_creds) {
char *c; if (client_name.data) {
data->creds.cr_raw_principal =
data->creds.cr_raw_principal = kstrndup(client_name.data, gssp_stringify(&client_name);
client_name.len, GFP_KERNEL); data->creds.cr_principal =
gssp_stringify(&client_name);
data->creds.cr_principal = kstrndup(client_name.data, gssp_hostbased_service(&data->creds.cr_principal);
client_name.len, GFP_KERNEL); }
if (data->creds.cr_principal) { if (target_name.data) {
/* terminate and remove realm part */ data->creds.cr_targ_princ =
c = strchr(data->creds.cr_principal, '@'); gssp_stringify(&target_name);
if (c) { gssp_hostbased_service(&data->creds.cr_targ_princ);
*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;
}
} }
} }
kfree(client_name.data); kfree(client_name.data);
kfree(target_name.data);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment