diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 9b569af695ab631525e91981747b0edc876dab7b..ac225a79376c0388e1fbe6c910ab9e200ac5ad8c 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1237,21 +1237,28 @@ struct svc_export * rqst_exp_get_by_name(struct svc_rqst *rqstp, struct vfsmount *mnt, struct dentry *dentry) { - return exp_get_by_name(rqstp->rq_client, mnt, dentry, - &rqstp->rq_chandle); + struct auth_domain *clp; + + clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; + return exp_get_by_name(clp, mnt, dentry, &rqstp->rq_chandle); } struct svc_export * rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) { - return exp_find(rqstp->rq_client, fsid_type, fsidv, - &rqstp->rq_chandle); + struct auth_domain *clp; + + clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; + return exp_find(clp, fsid_type, fsidv, &rqstp->rq_chandle); } struct svc_export * rqst_exp_parent(struct svc_rqst *rqstp, struct vfsmount *mnt, struct dentry *dentry) { + struct auth_domain *clp; + + clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; return exp_parent(rqstp->rq_client, mnt, dentry, &rqstp->rq_chandle); } diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 45aa21ce678420821953a8e9b5c7e1e442cce6f4..2cf9a9a2d89c4cd47b236a12e56c92f6cc842110 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -587,6 +587,15 @@ idmap_lookup(struct svc_rqst *rqstp, return ret; } +static char * +rqst_authname(struct svc_rqst *rqstp) +{ + struct auth_domain *clp; + + clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client; + return clp->name; +} + static int idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, uid_t *id) @@ -600,7 +609,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen return -EINVAL; memcpy(key.name, name, namelen); key.name[namelen] = '\0'; - strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname)); + strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); if (ret == -ENOENT) ret = -ESRCH; /* nfserr_badname */ @@ -620,7 +629,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) }; int ret; - strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname)); + strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item); if (ret == -ENOENT) return sprintf(name, "%u", id); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 180e068ea064d6ff8e19d7640118fc9abbaa2cae..22cb5be79ad0be2f98d85d6a0d9ab5a08764028e 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -120,8 +120,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) int data_left = fh->fh_size/4; error = nfserr_stale; - if (rqstp->rq_client == NULL) - goto out; if (rqstp->rq_vers > 2) error = nfserr_badhandle; if (rqstp->rq_vers == 4 && fh->fh_size == 0) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 705a90aa345efde08df2ee899513fc6df0bb6d5c..8531a70da73d2526d7e110c92baa6fddb9152212 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -249,6 +249,7 @@ struct svc_rqst { */ /* Catering to nfsd */ struct auth_domain * rq_client; /* RPC peer info */ + struct auth_domain * rq_gssclient; /* "gss/"-style peer info */ struct svc_cacherep * rq_cacherep; /* cache info */ struct knfsd_fh * rq_reffh; /* Referrence filehandle, used to * determine what device number diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index de92619b0826066f7809c1ef264a029e0a7b84d2..22e1ef8e200e9634b91de1b33f8d729a2d565039 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -127,6 +127,7 @@ extern struct auth_domain *auth_unix_lookup(struct in_addr addr); extern int auth_unix_forget_old(struct auth_domain *dom); extern void svcauth_unix_purge(void); extern void svcauth_unix_info_release(void *); +extern int svcauth_unix_set_client(struct svc_rqst *rqstp); static inline unsigned long hash_str(char *name, int bits) { diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7a3e1758bea15b681a6ef0a0ce0b2b5069dba5e7..e4b3de08b0403471bc450a2bced88a1ab560955e 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -913,10 +913,23 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) struct gss_svc_data *svcdata = rqstp->rq_auth_data; struct rsc *rsci = svcdata->rsci; struct rpc_gss_wire_cred *gc = &svcdata->clcred; + int stat; - rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc); - if (rqstp->rq_client == NULL) + /* + * A gss export can be specified either by: + * export *(sec=krb5,rw) + * or by + * export gss/krb5(rw) + * The latter is deprecated; but for backwards compatibility reasons + * the nfsd code will still fall back on trying it if the former + * doesn't work; so we try to make both available to nfsd, below. + */ + rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc); + if (rqstp->rq_gssclient == NULL) return SVC_DENIED; + stat = svcauth_unix_set_client(rqstp); + if (stat == SVC_DROP) + return stat; return SVC_OK; } @@ -1088,7 +1101,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) svc_putnl(resv, GSS_SEQ_WIN); if (svc_safe_putnetobj(resv, &rsip->out_token)) goto drop; - rqstp->rq_client = NULL; } goto complete; case RPC_GSS_PROC_DESTROY: @@ -1319,6 +1331,9 @@ svcauth_gss_release(struct svc_rqst *rqstp) if (rqstp->rq_client) auth_domain_put(rqstp->rq_client); rqstp->rq_client = NULL; + if (rqstp->rq_gssclient) + auth_domain_put(rqstp->rq_gssclient); + rqstp->rq_gssclient = NULL; if (rqstp->rq_cred.cr_group_info) put_group_info(rqstp->rq_cred.cr_group_info); rqstp->rq_cred.cr_group_info = NULL; diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index d9fdf2e4d24294a266e9b0476cd6b4e392c74828..411479411b21052a3e138c5109880abd881b77b4 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -638,7 +638,7 @@ static int unix_gid_find(uid_t uid, struct group_info **gip, } } -static int +int svcauth_unix_set_client(struct svc_rqst *rqstp) { struct sockaddr_in *sin = svc_addr_in(rqstp); @@ -673,6 +673,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) return SVC_OK; } +EXPORT_SYMBOL(svcauth_unix_set_client); + static int svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) {