Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68e76ad0 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Trond Myklebust
Browse files

nfsd: pass client principal name in rsc downcall



Two principals are involved in krb5 authentication: the target, who we
authenticate *to* (normally the name of the server, like
nfs/server.citi.umich.edu@CITI.UMICH.EDU), and the source, we we
authenticate *as* (normally a user, like bfields@UMICH.EDU)

In the case of NFSv4 callbacks, the target of the callback should be the
source of the client's setclientid call, and the source should be the
nfs server's own principal.

Therefore we allow svcgssd to pass down the name of the principal that
just authenticated, so that on setclientid we can store that principal
name with the new client, to be used later on callbacks.

Signed-off-by: default avatarOlga Kornievskaia <aglo@citi.umich.edu>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 34769fc4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@
#include <linux/mutex.h>
#include <linux/lockd/bind.h>
#include <linux/module.h>
#include <linux/sunrpc/svcauth_gss.h>

#define NFSDDBG_FACILITY                NFSDDBG_PROC

@@ -377,6 +378,7 @@ free_client(struct nfs4_client *clp)
	shutdown_callback_client(clp);
	if (clp->cl_cred.cr_group_info)
		put_group_info(clp->cl_cred.cr_group_info);
	kfree(clp->cl_principal);
	kfree(clp->cl_name.data);
	kfree(clp);
}
@@ -696,6 +698,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	unsigned int 		strhashval;
	struct nfs4_client	*conf, *unconf, *new;
	__be32 			status;
	char			*princ;
	char                    dname[HEXDIR_LEN];
	
	if (!check_name(clname))
@@ -783,6 +786,14 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
	}
	copy_verf(new, &clverifier);
	new->cl_addr = sin->sin_addr.s_addr;
	princ = svc_gss_principal(rqstp);
	if (princ) {
		new->cl_principal = kstrdup(princ, GFP_KERNEL);
		if (new->cl_principal == NULL) {
			free_client(new);
			goto out;
		}
	}
	copy_cred(&new->cl_cred, &rqstp->rq_cred);
	gen_confirm(new);
	gen_callback(new, setclid);
+1 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ struct nfs4_client {
	nfs4_verifier		cl_verifier; 	/* generated by client */
	time_t                  cl_time;        /* time of last lease renewal */
	__be32			cl_addr; 	/* client ipaddress */
	char			*cl_principal;	/* setclientid principal name */
	struct svc_cred		cl_cred; 	/* setclientid principal */
	clientid_t		cl_clientid;	/* generated by server */
	nfs4_verifier		cl_confirm;	/* generated by server */
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ int gss_svc_init(void);
void gss_svc_shutdown(void);
int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
u32 svcauth_gss_flavor(struct auth_domain *dom);
char *svc_gss_principal(struct svc_rqst *);

#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_SVCAUTH_GSS_H */
+23 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ struct rsc {
	struct svc_cred		cred;
	struct gss_svc_seq_data	seqdata;
	struct gss_ctx		*mechctx;
	char			*client_name;
};

static struct cache_head *rsc_table[RSC_HASHMAX];
@@ -346,6 +347,7 @@ static void rsc_free(struct rsc *rsci)
		gss_delete_sec_context(&rsci->mechctx);
	if (rsci->cred.cr_group_info)
		put_group_info(rsci->cred.cr_group_info);
	kfree(rsci->client_name);
}

static void rsc_put(struct kref *ref)
@@ -383,6 +385,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
	tmp->handle.data = NULL;
	new->mechctx = NULL;
	new->cred.cr_group_info = NULL;
	new->client_name = NULL;
}

static void
@@ -397,6 +400,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
	spin_lock_init(&new->seqdata.sd_lock);
	new->cred = tmp->cred;
	tmp->cred.cr_group_info = NULL;
	new->client_name = tmp->client_name;
	tmp->client_name = NULL;
}

static struct cache_head *
@@ -486,6 +491,15 @@ static int rsc_parse(struct cache_detail *cd,
		status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
		if (status)
			goto out;

		/* get client name */
		len = qword_get(&mesg, buf, mlen);
		if (len > 0) {
			rsci.client_name = kstrdup(buf, GFP_KERNEL);
			if (!rsci.client_name)
				goto out;
		}

	}
	rsci.h.expiry_time = expiry;
	rscp = rsc_update(&rsci, rscp);
@@ -913,6 +927,15 @@ struct gss_svc_data {
	struct rsc			*rsci;
};

char *svc_gss_principal(struct svc_rqst *rqstp)
{
	struct gss_svc_data *gd = (struct gss_svc_data *)rqstp->rq_auth_data;

	if (gd && gd->rsci)
		return gd->rsci->client_name;
	return NULL;
}

static int
svcauth_gss_set_client(struct svc_rqst *rqstp)
{