home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / netkit-a.06 / netkit-a / NetKit-A-0.06 / nfs-server-2.0 / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-27  |  6.7 KB  |  247 lines

  1. /*
  2.  * dispatch.c    This file contains the function dispatch table.
  3.  *
  4.  * Authors:    Donald J. Becker, <becker@super.org>
  5.  *        Rick Sladkey, <jrs@world.std.com>
  6.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  7.  *
  8.  *        This software maybe be used for any purpose provided
  9.  *        the above copyright notice is retained.  It is supplied
  10.  *        as is, with no warranty expressed or implied.
  11.  */
  12.  
  13. #include "nfsd.h"
  14.  
  15. union argument_types     argument;
  16. union result_types    result;
  17. clnt_param        *cp;
  18.  
  19. extern int
  20.     nfsd_nfsproc_null_2(), nfsd_nfsproc_getattr_2(), nfsd_nfsproc_setattr_2(),
  21.     nfsd_nfsproc_root_2(), nfsd_nfsproc_lookup_2(), nfsd_nfsproc_readlink_2(),
  22.     nfsd_nfsproc_read_2(), nfsd_nfsproc_writecache_2(), nfsd_nfsproc_write_2(),
  23.     nfsd_nfsproc_create_2(), nfsd_nfsproc_remove_2(), nfsd_nfsproc_rename_2(),
  24.     nfsd_nfsproc_link_2(), nfsd_nfsproc_symlink_2(), nfsd_nfsproc_mkdir_2(),
  25.     nfsd_nfsproc_rmdir_2(), nfsd_nfsproc_readdir_2(), nfsd_nfsproc_statfs_2();
  26.  
  27. /* Allow the following to be over-ridden at compile time. */
  28.  
  29. #ifndef ROOT_UID
  30. #define ROOT_UID    0        /* Root user's ID. */
  31. #endif
  32.  
  33. #ifndef NOBODY_UID
  34. #define NOBODY_UID    ((uid_t) 65534)    /* The unprivileged user. */
  35. #endif
  36.  
  37. #ifndef NOBODY_GID
  38. #define NOBODY_GID    ((gid_t) 65534)    /* The unprivileged group. */
  39. #endif
  40.  
  41. uid_t eff_uid = 0;            /* Current effective IDs. */
  42. gid_t eff_gid = 0;
  43. GETGROUPS_T last_gids[NGRPS];        /* Current supplementary gids. */
  44. int last_len = -1;
  45.  
  46. /*
  47.  * This is a dispatch table to simplify error checking,
  48.  * and supply return attributes for NFS functions.
  49.  */
  50.  
  51. #ifdef __STDC__
  52. #define CONCAT(a,b)    a##b
  53. #define CONCAT3(a,b,c)    a##b##c
  54. #define STRING(a)    #a
  55. #else
  56. #define CONCAT(a,b)    a/**/b
  57. #define CONCAT3(a,b,c)    a/**/b/**/c
  58. #define STRING(a)    "a"
  59. #endif
  60.  
  61. #define table_ent(auth, ro, cred, res_type, arg_type, funct) {    \
  62.     auth, ro, cred, sizeof(res_type), sizeof(arg_type),    \
  63.     CONCAT(xdr_,res_type), CONCAT(xdr_,arg_type),        \
  64.     CONCAT3(nfsd_nfsproc_,funct,_2), STRING(funct),        \
  65.     CONCAT(pr_,arg_type)                    \
  66. }
  67.  
  68. #define nil    char
  69. #define xdr_nil    xdr_void
  70. #define pr_nil    pr_void
  71. #define pr_char    pr_void
  72.  
  73. struct dispatch_entry {
  74.     int    authenticate;        /* zero if op perm. to any    */
  75.     int    read_only;        /* zero if op perm. on RO FS    */
  76.     int    credentials;        /* zero if no creditials needed    */
  77.     int    res_size, arg_size;    /* sizeof the res/arg structs    */
  78.     bool_t    (*xdr_result)();
  79.     bool_t    (*xdr_argument)();
  80.     int    (*funct)();        /* function handler        */
  81.     char    *name;            /* name of function        */
  82.     char    *(*log_print)();    /* ptr to debug handler        */
  83. };
  84.  
  85. static struct dispatch_entry dtable[] = {
  86.     table_ent(0,0,0,nil,nil,null),
  87.     table_ent(1,0,1,attrstat,nfs_fh,getattr),
  88.     table_ent(1,1,1,attrstat,sattrargs,setattr),
  89.     table_ent(0,0,0,nil,nil,root),
  90.     table_ent(1,0,1,diropres,diropargs,lookup),
  91.     table_ent(1,0,1,readlinkres,nfs_fh,readlink),
  92.     table_ent(1,0,1,readres,readargs,read),
  93.     table_ent(0,0,0,nil,nil,writecache),
  94.     table_ent(1,1,1,attrstat,writeargs,write),
  95.     table_ent(1,1,1,diropres,createargs,create),
  96.     table_ent(1,1,1,nfsstat,diropargs,remove),
  97.     table_ent(1,1,1,nfsstat,renameargs,rename),
  98.     table_ent(1,1,1,nfsstat,linkargs,link),
  99.     table_ent(1,1,1,nfsstat,symlinkargs,symlink),
  100.     table_ent(1,1,1,diropres,createargs,mkdir),
  101.     table_ent(1,1,1,nfsstat,diropargs,rmdir),
  102.     table_ent(1,0,1,readdirres,readdirargs,readdir),
  103.     table_ent(1,0,0,statfsres,nfs_fh,statfs),
  104. };
  105.  
  106. static _PRO( void set_ids, (struct svc_req *rqstp) );
  107.  
  108. void nfs_dispatch(rqstp, transp)
  109. struct svc_req *rqstp;
  110. SVCXPRT *transp;
  111. {
  112.     unsigned int proc_index = rqstp->rq_proc;
  113.     struct dispatch_entry *dent;
  114.  
  115.     if (proc_index >= (sizeof(dtable) / sizeof(dtable[0]))) {
  116.         svcerr_noproc(transp);
  117.         return;
  118.     }
  119.     dent = &dtable[proc_index];
  120.  
  121.     memset(&argument, 0, dent->arg_size);
  122.     if (!svc_getargs(transp, dent->xdr_argument, &argument)) {
  123.         svcerr_decode(transp);
  124.         return;
  125.     }
  126.     /* Clear the result structure. */
  127.     memset(&result, 0, dent->res_size);
  128.  
  129.     /* Log the call. */
  130.     log_call(rqstp, dent->name, dent->log_print(&argument));
  131.  
  132.     /* Initialize our variables for determining the attributes of
  133.        the file system in nfsd.c */
  134.     svc_rqstp = rqstp;
  135.     client_authenticate = dent->authenticate;
  136.  
  137. #ifdef READ_ONLY
  138.     /* Punt a write-type request if we are READ_ONLY. */
  139.     if (dent->read_only) {
  140.         result.nfsstat = NFSERR_ROFS;
  141.         goto report_status;
  142.     }
  143. #endif
  144.  
  145.     /* Establish the credentials and set the effective user IDs. */
  146.     if (dent->credentials)
  147.         set_ids(rqstp);
  148.  
  149.     /* Do the function call itself. */
  150.     result.nfsstat = (*dent->funct) (&argument);
  151.  
  152. #ifdef READ_ONLY
  153. report_status:
  154. #endif
  155.     dprintf(1, "result: %d\n", result.nfsstat);
  156.  
  157.     if (/* result.nfsstat >= 0 && */ /* nfsstat is unsigned? */
  158.       !svc_sendreply(transp, dent->xdr_result, (caddr_t) & result)) {
  159.         svcerr_systemerr(transp);
  160.     }
  161.     if (!svc_freeargs(transp, dent->xdr_argument, &argument)) {
  162.         dprintf(0, "unable to free RPC arguments, exiting\n");
  163.         exit(1);
  164.     }
  165. }
  166.  
  167. static void set_ids(rqstp)
  168. struct svc_req *rqstp;
  169. {
  170.     uid_t cred_uid;
  171.     gid_t cred_gid;
  172.     int cred_len;
  173.     GETGROUPS_T *cred_gids;
  174.     GETGROUPS_T fake_gid;
  175.  
  176.     if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  177.         struct authunix_parms *unix_cred;
  178.  
  179.         unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
  180.         cred_uid = unix_cred->aup_uid;
  181.         cred_gid = unix_cred->aup_gid;
  182.         cred_len = unix_cred->aup_len;
  183.         cred_gids = unix_cred->aup_gids;
  184.     } else {
  185.         cred_uid = NOBODY_UID;
  186.         cred_gid = NOBODY_GID;
  187.         /* Construct a list of one gid. */
  188.         cred_len = 1;
  189.         cred_gids = &fake_gid;
  190.         fake_gid = cred_gid;
  191.     }
  192.  
  193.     /* To set any IDs we first need to be root. What a pain. */
  194.  
  195.     /* First set the group ID. */
  196.     if (eff_gid != cred_gid) {
  197.         if (eff_uid != ROOT_UID) {
  198.             if (seteuid(ROOT_UID) < 0)
  199.                 dprintf(0, "Unable to seteuid %d: %s\n",
  200.                     ROOT_UID, strerror(errno));
  201.             else
  202.                 eff_uid = ROOT_UID;
  203.         }
  204.         if (setegid(cred_gid) < 0)
  205.             dprintf(0, "Unable to setegid %d: %s\n",
  206.                 cred_gid, strerror(errno));
  207.         else
  208.             eff_gid = cred_gid;
  209.     }
  210.  
  211. #ifdef HAVE_SETGROUPS
  212.     /* Next set the supplementary group IDs if possible. */
  213.     if (cred_len < 0 || cred_len > NGRPS)
  214.         dprintf(0, "Negative or huge cred_len: %d\n", cred_len);
  215.     else if (cred_len != last_len
  216.         || memcmp(cred_gids, last_gids, last_len*sizeof(gid_t))) {
  217.         if (eff_uid != ROOT_UID) {
  218.             if (seteuid(ROOT_UID) < 0)
  219.                 dprintf(0, "Unable to seteuid %d: %s\n",
  220.                     ROOT_UID, strerror(errno));
  221.             else
  222.                 eff_uid = ROOT_UID;
  223.         }
  224.         if (setgroups(cred_len, cred_gids) < 0)
  225.             dprintf(0, "Unable to setgroups: %s\n",
  226.                 strerror(errno));
  227.         else {
  228.             memcpy(last_gids, cred_gids, cred_len*sizeof(gid_t));
  229.             last_len = cred_len;
  230.         }
  231.     }
  232. #endif /* HAVE_SETGROUPS */
  233.  
  234.     /* Finally, set the user ID. */
  235.     if (eff_uid != cred_uid) {
  236.         if (eff_uid != ROOT_UID && seteuid(ROOT_UID) < 0)
  237.             dprintf(0, "Unable to seteuid %d: %s\n",
  238.                 ROOT_UID, strerror(errno));
  239.         if (seteuid(cred_uid) < 0)
  240.             dprintf(0, "Unable to seteuid %d: %s\n",
  241.                 cred_uid, strerror(errno));
  242.         else
  243.             eff_uid = cred_uid;
  244.     }
  245. }
  246.  
  247.