]> git.hungrycats.org Git - linux/commitdiff
[PATCH] kNFSd: Move auth domain lookup into svcauth
authorNeil Brown <neilb@cse.unsw.edu.au>
Fri, 11 Oct 2002 12:39:30 +0000 (05:39 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 11 Oct 2002 12:39:30 +0000 (05:39 -0700)
Instead of doing the lookup from ipaddr to domain inside
the nfs server, (and also when lockd calls into nfsd) it is
now done at the rpc authentication level which is a more
sensible place for it.

Note that both AUTH_UNIX and AUTH_NULL do the same lookup.

So that the rpc layer knows that nfsd and lockd both uses the
name space of domains (while other hypothetical services may
not) we introduce a 'class' for each service which svc_auth combines
with the IP address when doing a lookup.

fs/lockd/svc.c
fs/nfsd/lockd.c
fs/nfsd/nfsfh.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
include/linux/sunrpc/svc.h
net/sunrpc/svcauth_unix.c

index cfef0f0feff86bd1eb20b4856b4c9459d44b988c..1f515cfb294b4c38e157991fe771b751314cf20c 100644 (file)
@@ -389,5 +389,6 @@ struct svc_program  nlmsvc_program = {
        .pg_nvers       = NLM_NRVERS,           /* number of entries in nlmsvc_version */
        .pg_vers        = nlmsvc_version,       /* version table */
        .pg_name        = "lockd",              /* service name */
+       .pg_class       = "nfsd",               /* share authentication with nfsd */
        .pg_stats       = &nlmsvc_stats,        /* stats table */
 };
index a3f9df90d9f2dfbe2c13ce124fb362f0e47b99e6..5da1ed2e8ccd0bc9b4925f8ac9b31e70297f87c5 100644 (file)
@@ -32,18 +32,12 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
        fh.fh_export = NULL;
 
        exp_readlock();
-       rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
-       if (rqstp->rq_client == NULL)
-               nfserr = nfserr_stale;
-       else
-               nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
+       nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
        if (!nfserr) {
                dget(filp->f_dentry);
                mntget(filp->f_vfsmnt);
        }
        fh_put(&fh);
-       if (rqstp->rq_client)
-               auth_domain_put(rqstp->rq_client);
        rqstp->rq_client = NULL;
        exp_readunlock();
        /* nlm and nfsd don't share error codes.
index 70d84e36fadccd2f8de41a4a02e56c16ac18bceb..d3f021582efd01ac5cd01ed722d2ff869ae28dff 100644 (file)
@@ -103,6 +103,8 @@ 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)
index 65f455e529ba51eb4b7dd63bbacfce4ca392375b..1044a94d69aea93cc9d8dfb25730cac5503799ac 100644 (file)
@@ -206,10 +206,6 @@ nfsd(struct svc_rqst *rqstp)
                /* Lock the export hash tables for reading. */
                exp_readlock();
 
-               /* Validate the client's address. This will also defeat
-                * port probes on port 2049 by unauthorized clients.
-                */
-               rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
                /* Process request with signals blocked.  */
                spin_lock_irq(&current->sig->siglock);
                siginitsetinv(&current->blocked, ALLOWED_SIGS);
@@ -219,10 +215,6 @@ nfsd(struct svc_rqst *rqstp)
                svc_process(serv, rqstp);
 
                /* Unlock export hash tables */
-               if (rqstp->rq_client) {
-                       auth_domain_put(rqstp->rq_client);
-                       rqstp->rq_client = NULL;
-               }
                exp_readunlock();
                update_thread_usage(atomic_read(&nfsd_busy));
                atomic_dec(&nfsd_busy);
@@ -369,5 +361,6 @@ struct svc_program          nfsd_program = {
        .pg_nvers               = NFSD_NRVERS,          /* nr of entries in nfsd_version */
        .pg_vers                = nfsd_version,         /* version table */
        .pg_name                = "nfsd",               /* program name */
+       .pg_class               = "nfsd",               /* authentication class */
        .pg_stats               = &nfsd_svcstats,       /* version table */
 };
index 61c7bd03d3f0e5ad02a56360b2c54ac164fd848a..7069a472a095b4682cac60238b9ad2801ce5a2bf 100644 (file)
@@ -154,7 +154,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
                        struct dentry *mounts = dget(dentry);
                        while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
                                ;
-                       exp2 = exp_get_by_name(rqstp->rq_client, mnt, mounts);
+                       exp2 = exp_get_by_name(exp->ex_client, mnt, mounts);
                        if (exp2 && EX_CROSSMNT(exp2)) {
                                /* successfully crossed mount point */
                                exp = exp2;
index 57c5a49d2b0ab08b4260d6abfde101fa8dea0592..95e6b8d20fd13da77e5277bce457eaecdb8a13b2 100644 (file)
@@ -142,6 +142,7 @@ struct svc_program {
        unsigned int            pg_nvers;       /* number of versions */
        struct svc_version **   pg_vers;        /* version array */
        char *                  pg_name;        /* service name */
+       char *                  pg_class;       /* class name: services sharing authentication */
        struct svc_stat *       pg_stats;       /* rpc statistics */
 };
 
index c5e7e20c44c406fa8e5910e801afe22a003728f0..ce13795dcbcb6b2f83aaa662bd46c0ffce82c76f 100644 (file)
@@ -201,6 +201,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
 {
        struct svc_buf  *argp = &rqstp->rq_argbuf;
        struct svc_buf  *resp = &rqstp->rq_resbuf;
+       int             rv=0;
+       struct ip_map key, *ipm;
 
        if ((argp->len -= 3) < 0) {
                return SVC_GARBAGE;
@@ -224,12 +226,45 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
        /* Put NULL verifier */
        svc_putu32(resp, RPC_AUTH_NULL);
        svc_putu32(resp, 0);
-       return SVC_OK;
+
+       key.m_class = rqstp->rq_server->sv_program->pg_class;
+       key.m_addr = rqstp->rq_addr.sin_addr;
+
+       ipm = ip_map_lookup(&key, 0);
+
+       rqstp->rq_client = NULL;
+
+       if (ipm)
+               switch (cache_check(&ip_map_cache, &ipm->h)) {
+               case -EAGAIN:
+                       rv = SVC_DROP;
+                       break;
+               case -ENOENT:
+                       rv = SVC_OK; /* rq_client is NULL */
+                       break;
+               case 0:
+                       rqstp->rq_client = &ipm->m_client->h;
+                       cache_get(&rqstp->rq_client->h);
+                       ip_map_put(&ipm->h, &ip_map_cache);
+                       rv = SVC_OK;
+                       break;
+               default: BUG();
+               }
+       else rv = SVC_DROP;
+
+       if (rqstp->rq_client == NULL && proc != 0)
+               *authp = rpc_autherr_badcred;
+
+       return rv;
 }
 
 static int
 svcauth_null_release(struct svc_rqst *rqstp)
 {
+       if (rqstp->rq_client)
+               auth_domain_put(rqstp->rq_client);
+       rqstp->rq_client = NULL;
+
        return 0; /* don't drop */
 }
 
@@ -250,6 +285,8 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
        struct svc_cred *cred = &rqstp->rq_cred;
        u32             *bufp = argp->buf, slen, i;
        int             len   = argp->len;
+       int             rv=0;
+       struct ip_map key, *ipm;
 
        if ((len -= 3) < 0)
                return SVC_GARBAGE;
@@ -285,7 +322,34 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp, int proc)
        svc_putu32(resp, RPC_AUTH_NULL);
        svc_putu32(resp, 0);
 
-       return SVC_OK;
+       key.m_class = rqstp->rq_server->sv_program->pg_class;
+       key.m_addr = rqstp->rq_addr.sin_addr;
+
+       ipm = ip_map_lookup(&key, 0);
+
+       rqstp->rq_client = NULL;
+
+       if (ipm)
+               switch (cache_check(&ip_map_cache, &ipm->h)) {
+               case -EAGAIN:
+                       rv = SVC_DROP;
+                       break;
+               case -ENOENT:
+                       rv = SVC_OK; /* rq_client is NULL */
+                       break;
+               case 0:
+                       rqstp->rq_client = &ipm->m_client->h;
+                       cache_get(&rqstp->rq_client->h);
+                       ip_map_put(&ipm->h, &ip_map_cache);
+                       rv = SVC_OK;
+                       break;
+               default: BUG();
+               }
+       else rv = SVC_DROP;
+
+       if (rqstp->rq_client == NULL && proc != 0)
+               goto badcred;
+       return rv;
 
 badcred:
        *authp = rpc_autherr_badcred;
@@ -297,6 +361,10 @@ svcauth_unix_release(struct svc_rqst *rqstp)
 {
        /* Verifier (such as it is) is already in place.
         */
+       if (rqstp->rq_client)
+               auth_domain_put(rqstp->rq_client);
+       rqstp->rq_client = NULL;
+
        return 0;
 }