Logo Search packages:      
Sourcecode: nfs-user-server version File versions  Download package

ugidd.c

/* UNFSD - copyright Mark A Shand, May 1988.
 * This software maybe be used for any purpose provided
 * the above copyright notice is retained.  It is supplied
 * as is, with no warranty expressed or implied.
 *
 * Authors: Mark A. Shand
 *          Olaf Kirch <okir@monad.swb.de>
 */

#include "site.h"

/* Only compile ugidd if nfs server has support for it. */
#ifdef ENABLE_UGID_DAEMON

#include "system.h"
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include "ugid.h"
#include "logging.h"
#include "haccess.h"
#ifdef HAVE_LIBWRAP_BUG
#include <syslog.h>
#endif


static void ugidprog_1(struct svc_req *rqstp, SVCXPRT *transp);
static void usage(void);

#ifndef HAVE_RPCGEN_C
#define authenticate_1_svc    authenticate_1
#define name_uid_1_svc        name_uid_1
#define group_gid_1_svc       group_gid_1
#define uid_name_1_svc        uid_name_1
#define gid_group_1_svc       gid_group_1
#endif


static struct option longopts[] = {
      { "debug", 0, 0, 'd' },
      { NULL, 0, 0, 0 }
};

int
main(argc, argv)
int   argc;
char  **argv;
{
      SVCXPRT     *transp;
      int   c, longind;
      int   foreground = 0;

#ifndef HOSTS_ACCESS
      fprintf(stderr,
            "\n *** WARNING: This copy of ugidd has been compiled without\n"
            " *** support for host_access checking. This is very risky.\n"
            " *** Please consider recompiling it with access checking.\n");
      sleep(1);
#endif

      while ((c = getopt_long(argc, argv, "d", longopts, &longind)) != EOF) {
            switch (c) {
            case 'd':
                  foreground = 1;
                  enable_logging("ugid");
                  break;
            default:
                  usage();
            }
      }

        (void)pmap_unset(UGIDPROG, UGIDVERS);

        transp = svcudp_create(RPC_ANYSOCK);
        if (transp == NULL) {
                (void)fprintf(stderr, "cannot create udp service.\n");
                exit(1);
        }
        if (!svc_register(transp, UGIDPROG, UGIDVERS, ugidprog_1, IPPROTO_UDP)) {
                fprintf(stderr, "unable to register (UGIDPROG, UGIDVERS, UDP)\n");
                exit(1);
        }

        transp = svctcp_create(RPC_ANYSOCK, 0, 0);
        if (transp == NULL) {
                fprintf(stderr, "cannot create tcp service.\n");
                exit(1);
        }
        if (!svc_register(transp, UGIDPROG, UGIDVERS, ugidprog_1, IPPROTO_TCP)) {
                fprintf(stderr, "unable to register (UGIDPROG, UGIDVERS, TCP)\n");
                exit(1);
        }

      if (!foreground) {
            if ((c = fork()) > 0)
                  exit(0);
            if (c < 0) {
                  fprintf(stderr, "ugidd: cannot fork: %s\n",
                                    strerror(errno));
                  exit(-1);
            }
            close(0);
            close(1);
            close(2);
#ifdef HAVE_SETSID
            setsid();
#else
            {
                  int fd;

                  if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
                        ioctl(fd, TIOCNOTTY, (char *) NULL);
                        close(fd);
                  }
            }
#endif
      }

      log_open("ugidd", foreground);

      svc_run();
      Dprintf(L_ERROR, "svc_run returned\n");
      return 1;
}

static void
usage()
{
      fprintf(stderr, "rpc.ugidd: [-d]\n");
      exit (2);
}

static void
ugidprog_1(struct svc_req *rqstp, SVCXPRT *transp)
{
      union {
            int authenticate_1_arg;
            ugname name_uid_1_arg;
            ugname group_gid_1_arg;
            int uid_name_1_arg;
            int gid_group_1_arg;
      } argument;
      char        *result;
      xdrproc_t   xdr_argument, xdr_result;
      char        *(*local)();

      if (!client_checkaccess("rpc.ugidd", svc_getcaller(transp), 1))
            return;

      switch (rqstp->rq_proc) {
      case NULLPROC:
            svc_sendreply(transp, (xdrproc_t) xdr_void, (char *) NULL);
            return;

      case AUTHENTICATE:
            xdr_argument = (xdrproc_t) xdr_int;
            xdr_result   = (xdrproc_t) xdr_int;
            local = (char *(*)()) authenticate_1_svc;
            break;

      case NAME_UID:
            xdr_argument = (xdrproc_t) xdr_ugname;
            xdr_result   = (xdrproc_t) xdr_int;
            local = (char *(*)()) name_uid_1_svc;
            break;

      case GROUP_GID:
            xdr_argument = (xdrproc_t) xdr_ugname;
            xdr_result = (xdrproc_t) xdr_int;
            local = (char *(*)()) group_gid_1_svc;
            break;

      case UID_NAME:
            xdr_argument = (xdrproc_t) xdr_int;
            xdr_result = (xdrproc_t) xdr_ugname;
            local = (char *(*)()) uid_name_1_svc;
            break;

      case GID_GROUP:
            xdr_argument = (xdrproc_t) xdr_int;
            xdr_result = (xdrproc_t) xdr_ugname;
            local = (char *(*)()) gid_group_1_svc;
            break;

      default:
            svcerr_noproc(transp);
            return;
      }
      bzero((char *)&argument, sizeof(argument));
      if (!svc_getargs(transp, xdr_argument, &argument)) {
            svcerr_decode(transp);
            return;
      }
      result = (*local)(&argument, rqstp);
      if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
            svcerr_systemerr(transp);
      }
      if (!svc_freeargs(transp, xdr_argument, &argument)) {
            (void)fprintf(stderr, "unable to free arguments\n");
            exit(1);
      }
}

int *
authenticate_1_svc(argp, rqstp)
      int *argp;
      struct svc_req *rqstp;
{
      static int res;
      int   s;
      struct sockaddr_in      sendaddr, destaddr;
      int   dummy;
      short lport;

      bzero(&res, sizeof res);
      destaddr = *svc_getcaller(rqstp->rq_xprt);
      destaddr.sin_port = htons(*argp);
      if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
            goto bad;
      setsockopt(s, SOL_SOCKET, SO_LINGER, 0, 0);
      bzero((char *) &sendaddr, sizeof sendaddr);
      /* find a reserved port */
      lport = IPPORT_RESERVED - 1;
      sendaddr.sin_family = AF_INET;
      sendaddr.sin_addr.s_addr = INADDR_ANY;
      for (;;)
      {
            sendaddr.sin_port = htons((u_short)lport);
            if (bind(s, (struct sockaddr *)&sendaddr, sizeof sendaddr) >= 0)
                  break;
            if (errno != EADDRINUSE && EADDRNOTAVAIL)
                  goto bad;
            lport--;
            if (lport <= IPPORT_RESERVED / 2)
                  /* give up */
                  break;
      }
      if (sendto(s, &dummy, sizeof dummy, 0,
                  (struct sockaddr *)&destaddr, sizeof destaddr) < 0)
            goto bad;

      close(s);
      res = 0;
      return (&res);
    bad:
      close(s);
      res = errno == 0 ? -1 : errno;
      return (&res);
}

int *
name_uid_1_svc(argp, rqstp)
      ugname *argp;
      struct svc_req *rqstp;
{
      static int res;
      struct passwd     *pw;

      bzero(&res, sizeof(res));
      if ((pw = getpwnam(*argp)) == NULL)
            res = NOBODY;
      else
            res = pw->pw_uid;

      return (&res);
}


int *
group_gid_1_svc(argp, rqstp)
      ugname *argp;
      struct svc_req *rqstp;
{
      static int res;
      struct group      *gr;

      bzero(&res, sizeof(res));
      if ((gr = getgrnam(*argp)) == NULL)
            res = NOBODY;
      else
            res = gr->gr_gid;

      return (&res);
}


ugname *
uid_name_1_svc(argp, rqstp)
      int *argp;
      struct svc_req *rqstp;
{
      static ugname res;
      struct passwd     *pw;

      bzero(&res, sizeof(res));
      if ((pw = getpwuid(*argp)) == NULL)
            res = "";
      else
            res = pw->pw_name;

      return (&res);
}


ugname *
gid_group_1_svc(argp, rqstp)
      int *argp;
      struct svc_req *rqstp;
{
      static ugname res;
      struct group      *gr;

      bzero(&res, sizeof(res));
      if ((gr = getgrgid(*argp)) == NULL)
            res = "";
      else
            res = gr->gr_name;

      return (&res);
}



#else /* ENABLE_UGID_DAEMON */

#include <stdio.h>

int
main(argc, argv)
      int   argc;
      char  **argv;
{
      fprintf(stderr, 
      "\nThis copy of the Universal NFS server has been compiled without\n");
      fprintf(stderr, "support for the ugidd RPC uid/gid map daemon.\n");
      fprintf(stderr, "This is a dummy program.\n");
      return 1;
}

#endif /* ENABLE_UGID_DAEMON */

Generated by  Doxygen 1.6.0   Back to index