138460Smckusick /* 238460Smckusick * Copyright (c) 1989 The Regents of the University of California. 338460Smckusick * All rights reserved. 438460Smckusick * 538460Smckusick * This code is derived from software contributed to Berkeley by 6*51667Smckusick * Herb Hasler and Rick Macklem at The University of Guelph. 738460Smckusick * 842703Sbostic * %sccs.include.redist.c% 938460Smckusick */ 1038460Smckusick 1138460Smckusick #ifndef lint 1238460Smckusick char copyright[] = 1338460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 1438460Smckusick All rights reserved.\n"; 1538460Smckusick #endif not lint 1638460Smckusick 1738460Smckusick #ifndef lint 18*51667Smckusick static char sccsid[] = "@(#)mountd.c 5.15 (Berkeley) 11/12/91"; 1938460Smckusick #endif not lint 2038460Smckusick 21*51667Smckusick #include <pwd.h> 22*51667Smckusick #include <grp.h> 23*51667Smckusick #include <unistd.h> 24*51667Smckusick #include <stdlib.h> 25*51667Smckusick #include <fcntl.h> 2638460Smckusick #include <sys/param.h> 2738460Smckusick #include <sys/ioctl.h> 2838460Smckusick #include <sys/stat.h> 2939681Smckusick #include <sys/file.h> 30*51667Smckusick #include <sys/ucred.h> 3138460Smckusick #include <sys/mount.h> 3238460Smckusick #include <sys/socket.h> 3338460Smckusick #include <sys/errno.h> 3442038Sbostic #include <sys/signal.h> 3542038Sbostic #include <stdio.h> 3642038Sbostic #include <string.h> 3742038Sbostic #include <syslog.h> 3838460Smckusick #include <netdb.h> 3938460Smckusick #include <rpc/rpc.h> 4038460Smckusick #include <rpc/pmap_clnt.h> 4138460Smckusick #include <rpc/pmap_prot.h> 42*51667Smckusick #ifdef ISO 43*51667Smckusick #include <netiso/iso.h> 44*51667Smckusick #endif 4538460Smckusick #include <nfs/rpcv2.h> 4638460Smckusick #include <nfs/nfsv2.h> 4739681Smckusick #include "pathnames.h" 4838460Smckusick 49*51667Smckusick #define DEF_NAME "default" 50*51667Smckusick 51*51667Smckusick #define MNT_HOST 0 52*51667Smckusick #define MNT_GROUP 1 53*51667Smckusick #define MNT_ISO 2 54*51667Smckusick 55*51667Smckusick struct namelist { 56*51667Smckusick char name[RPCMNT_NAMELEN+1]; 57*51667Smckusick struct namelist *next; 5838460Smckusick }; 59*51667Smckusick struct namegrp { 60*51667Smckusick char gname[RPCMNT_NAMELEN+1]; 61*51667Smckusick struct namegrp *next; 62*51667Smckusick struct namelist *names; 63*51667Smckusick }; 6438460Smckusick /* 6538460Smckusick * Structures for keeping the mount list and export list 6638460Smckusick */ 6738460Smckusick struct mountlist { 6844015Smckusick struct mountlist *ml_next; 6938460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 7038460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 7138460Smckusick }; 7238460Smckusick 7338460Smckusick struct exportlist { 7438460Smckusick struct exportlist *ex_next; 7538460Smckusick struct exportlist *ex_prev; 7638460Smckusick struct grouplist *ex_groups; 77*51667Smckusick int ex_defset; 7838460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 7938460Smckusick }; 8038460Smckusick 81*51667Smckusick union grouptypes { 82*51667Smckusick struct hostent *gt_hostent; 83*51667Smckusick struct groupnames *gt_grpname; 84*51667Smckusick #ifdef ISO 85*51667Smckusick struct sockaddr_iso *gt_isoaddr; 86*51667Smckusick #endif 87*51667Smckusick }; 88*51667Smckusick 8938460Smckusick struct grouplist { 90*51667Smckusick int type; 91*51667Smckusick int exflags; 92*51667Smckusick struct ucred anoncr; 93*51667Smckusick union grouptypes gr_ptr; 9438460Smckusick struct grouplist *gr_next; 9538460Smckusick }; 9638460Smckusick 97*51667Smckusick struct al_mnt { 98*51667Smckusick struct al_mnt *al_next; 99*51667Smckusick fsid_t al_mnted; 100*51667Smckusick }; 101*51667Smckusick 102*51667Smckusick struct groupnames { 103*51667Smckusick char gn_name[RPCMNT_NAMELEN+1]; 104*51667Smckusick struct grouplist *gn_glist; 105*51667Smckusick struct groupnames *gn_next; 106*51667Smckusick }; 107*51667Smckusick 10838460Smckusick /* Global defs */ 10946709Sbostic int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 110*51667Smckusick void get_exportlist(), send_umntall(), nextfield(), do_opt(); 111*51667Smckusick void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp(); 112*51667Smckusick void get_group(), get_host(), do_group(); 113*51667Smckusick char *realpath(); 114*51667Smckusick #ifdef ISO 115*51667Smckusick struct iso_addr *iso_addr(); 116*51667Smckusick #endif 11738460Smckusick struct exportlist exphead; 11844015Smckusick struct mountlist *mlhead; 119*51667Smckusick struct groupnames *grpnames; 12038460Smckusick char exname[MAXPATHLEN]; 121*51667Smckusick struct ucred def_anon = { 122*51667Smckusick (u_short) 1, 123*51667Smckusick (uid_t) -2, 124*51667Smckusick 1, 125*51667Smckusick (gid_t) -2, 126*51667Smckusick }; 12744015Smckusick int root_only = 1; 12838460Smckusick extern int errno; 129*51667Smckusick struct al_mnt *al_head = (struct al_mnt *)0; 13038460Smckusick #ifdef DEBUG 13138460Smckusick int debug = 1; 13238460Smckusick #else 13338460Smckusick int debug = 0; 13438460Smckusick #endif 13538460Smckusick 13638460Smckusick /* 13738460Smckusick * Mountd server for NFS mount protocol as described in: 13839681Smckusick * NFS: Network File System Protocol Specification, RFC1094, Appendix A 13944015Smckusick * The optional arguments are the exports file name 14039681Smckusick * default: _PATH_EXPORTS 14144015Smckusick * and "-n" to allow nonroot mount. 14238460Smckusick */ 14338460Smckusick main(argc, argv) 14438460Smckusick int argc; 14544015Smckusick char **argv; 14638460Smckusick { 14738460Smckusick SVCXPRT *transp; 14844015Smckusick int c; 14944015Smckusick extern int optind; 15044015Smckusick extern char *optarg; 15138460Smckusick 15244015Smckusick while ((c = getopt(argc, argv, "n")) != EOF) 15344015Smckusick switch (c) { 15444015Smckusick case 'n': 15544015Smckusick root_only = 0; 15644015Smckusick break; 15744015Smckusick default: 15844015Smckusick fprintf(stderr, "Usage: mountd [-n] [export_file]\n"); 15944015Smckusick exit(1); 16044015Smckusick }; 16144015Smckusick argc -= optind; 16244015Smckusick argv += optind; 163*51667Smckusick grpnames = (struct groupnames *)0; 16444015Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 16544015Smckusick mlhead = (struct mountlist *)0; 16644015Smckusick if (argc == 1) { 16744015Smckusick strncpy(exname, *argv, MAXPATHLEN-1); 16844015Smckusick exname[MAXPATHLEN-1] = '\0'; 16944015Smckusick } else 17044015Smckusick strcpy(exname, _PATH_EXPORTS); 17144338Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 172*51667Smckusick if (debug) 173*51667Smckusick fprintf(stderr,"Getting export list.\n"); 17444015Smckusick get_exportlist(); 175*51667Smckusick if (debug) 176*51667Smckusick fprintf(stderr,"Getting mount list.\n"); 17744015Smckusick get_mountlist(); 178*51667Smckusick if (debug) 179*51667Smckusick fprintf(stderr,"Here we go.\n"); 18038460Smckusick if (debug == 0) { 18144690Skarels daemon(0, 0); 18238460Smckusick signal(SIGINT, SIG_IGN); 18338460Smckusick signal(SIGQUIT, SIG_IGN); 18438460Smckusick } 18538460Smckusick signal(SIGHUP, get_exportlist); 18644015Smckusick signal(SIGTERM, send_umntall); 18740494Smckusick { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 18840494Smckusick if (pidfile != NULL) { 18940494Smckusick fprintf(pidfile, "%d\n", getpid()); 19040494Smckusick fclose(pidfile); 19140494Smckusick } 19240494Smckusick } 19338460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 19438460Smckusick syslog(LOG_ERR, "Can't create socket"); 19538460Smckusick exit(1); 19638460Smckusick } 19738460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 198*51667Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, 199*51667Smckusick IPPROTO_UDP)) { 20038460Smckusick syslog(LOG_ERR, "Can't register mount"); 20138460Smckusick exit(1); 20238460Smckusick } 20338460Smckusick svc_run(); 20438460Smckusick syslog(LOG_ERR, "Mountd died"); 20544690Skarels exit(1); 20638460Smckusick } 20738460Smckusick 20838460Smckusick /* 20938460Smckusick * The mount rpc service 21038460Smckusick */ 21138460Smckusick mntsrv(rqstp, transp) 21238460Smckusick register struct svc_req *rqstp; 21338460Smckusick register SVCXPRT *transp; 21438460Smckusick { 21539681Smckusick register struct grouplist *grp; 21639681Smckusick register u_long **addrp; 21738460Smckusick register struct exportlist *ep; 21838460Smckusick nfsv2fh_t nfh; 21938460Smckusick struct authunix_parms *ucr; 22038460Smckusick struct stat stb; 22138460Smckusick struct hostent *hp; 22239681Smckusick u_long saddr; 223*51667Smckusick char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN]; 22438460Smckusick int bad = ENOENT; 225*51667Smckusick int found, matched; 22638460Smckusick int omask; 22739681Smckusick uid_t uid = -2; 22838460Smckusick 22938460Smckusick /* Get authorization */ 23038460Smckusick switch (rqstp->rq_cred.oa_flavor) { 23138460Smckusick case AUTH_UNIX: 23238460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 23339681Smckusick uid = ucr->aup_uid; 23439681Smckusick break; 23538460Smckusick case AUTH_NULL: 23638460Smckusick default: 23739681Smckusick break; 23838460Smckusick } 23938460Smckusick 24039681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 24139681Smckusick hp = (struct hostent *)0; 24238460Smckusick switch (rqstp->rq_proc) { 24339681Smckusick case NULLPROC: 24439681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 24539681Smckusick syslog(LOG_ERR, "Can't send reply"); 24639681Smckusick return; 24738460Smckusick case RPCMNT_MOUNT: 248*51667Smckusick if ((uid != 0 && root_only) || uid == -2) { 24939681Smckusick svcerr_weakauth(transp); 25039681Smckusick return; 25139681Smckusick } 252*51667Smckusick if (!svc_getargs(transp, xdr_dir, rpcpath)) { 25338460Smckusick svcerr_decode(transp); 25438460Smckusick return; 25538460Smckusick } 25638460Smckusick 257*51667Smckusick /* 258*51667Smckusick * Get the real pathname and make sure it is a directory 259*51667Smckusick * that exists. 260*51667Smckusick */ 261*51667Smckusick if (realpath(rpcpath, dirpath) == 0 || stat(dirpath, &stb) < 0 262*51667Smckusick || (stb.st_mode&S_IFMT) != S_IFDIR) { 263*51667Smckusick chdir("/"); /* Just in case realpath doesn't */ 264*51667Smckusick if (debug) 265*51667Smckusick fprintf(stderr,"stat failed on %s\n",dirpath); 26638460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 26738460Smckusick syslog(LOG_ERR, "Can't send reply"); 26838460Smckusick return; 26938460Smckusick } 27038460Smckusick 27138460Smckusick /* Check in the exports list */ 27238460Smckusick omask = sigblock(sigmask(SIGHUP)); 27338460Smckusick ep = exphead.ex_next; 274*51667Smckusick found = FALSE; 275*51667Smckusick matched = FALSE; 276*51667Smckusick while (ep != NULL && !found && !matched) { 277*51667Smckusick struct grouplist *tgrp; 278*51667Smckusick if (debug) 279*51667Smckusick fprintf(stderr,"dirp=[%s]\n",ep->ex_dirp); 28038460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 281*51667Smckusick if (ep->ex_defset) 282*51667Smckusick grp = (struct grouplist *)0; 283*51667Smckusick else 28438460Smckusick grp = ep->ex_groups; 285*51667Smckusick if (grp == NULL) { 286*51667Smckusick if (debug) 287*51667Smckusick fprintf(stderr,"grp is null\n"); 288*51667Smckusick found = TRUE; 289*51667Smckusick } 290*51667Smckusick while (grp && !found) { 291*51667Smckusick matched = TRUE; 292*51667Smckusick if (debug) 293*51667Smckusick fprintf(stderr,"type = [%d]\n",grp->type); 294*51667Smckusick if (grp->type == MNT_GROUP) { 295*51667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 296*51667Smckusick if (tgrp) 297*51667Smckusick addrp = (u_long **) 298*51667Smckusick tgrp->gr_ptr.gt_hostent->h_addr_list; 299*51667Smckusick while(tgrp && !found) { 300*51667Smckusick if (debug) 301*51667Smckusick fprintf(stderr, "cmp [%d] [%d]\n", 302*51667Smckusick **addrp,saddr); 303*51667Smckusick if (**addrp == saddr) { 304*51667Smckusick found = TRUE; 305*51667Smckusick hp = tgrp->gr_ptr.gt_hostent; 306*51667Smckusick break; 307*51667Smckusick } 308*51667Smckusick if (*++addrp == NULL) { 309*51667Smckusick tgrp = tgrp->gr_next; 310*51667Smckusick if (tgrp == NULL) 31138460Smckusick break; 312*51667Smckusick addrp = (u_long **)tgrp-> 313*51667Smckusick gr_ptr.gt_hostent->h_addr_list; 314*51667Smckusick } 315*51667Smckusick } 316*51667Smckusick } else if (grp->type == MNT_HOST) { 317*51667Smckusick addrp = (u_long **) 318*51667Smckusick grp->gr_ptr.gt_hostent->h_addr_list; 319*51667Smckusick while (*addrp) { 320*51667Smckusick if (debug) 321*51667Smckusick fprintf(stderr, "cmp [%d] [%d]\n", 322*51667Smckusick **addrp,saddr); 323*51667Smckusick if (**addrp == saddr) { 324*51667Smckusick found = TRUE; 325*51667Smckusick hp = grp->gr_ptr.gt_hostent; 326*51667Smckusick break; 327*51667Smckusick } 328*51667Smckusick addrp++; 329*51667Smckusick } 33038460Smckusick } 331*51667Smckusick grp = grp->gr_next; 332*51667Smckusick } 33338460Smckusick } 33438460Smckusick ep = ep->ex_next; 33538460Smckusick } 336*51667Smckusick if (!found) { 33738460Smckusick bad = EACCES; 33838460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 33938460Smckusick syslog(LOG_ERR, "Can't send reply"); 340*51667Smckusick sigsetmask(omask); 34138460Smckusick return; 342*51667Smckusick } else { 343*51667Smckusick /* Get the file handle */ 344*51667Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 345*51667Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 346*51667Smckusick bad = errno; 347*51667Smckusick fprintf(stderr, 348*51667Smckusick "Couldn't get file handle for %s.\n", 349*51667Smckusick dirpath); 350*51667Smckusick if (!svc_sendreply(transp, xdr_long, 351*51667Smckusick (caddr_t)&bad)) 352*51667Smckusick syslog(LOG_ERR, "Can't send reply"); 353*51667Smckusick sigsetmask(omask); 354*51667Smckusick return; 355*51667Smckusick } 356*51667Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 35738460Smckusick syslog(LOG_ERR, "Can't send reply"); 358*51667Smckusick if (hp == NULL) 359*51667Smckusick hp = gethostbyaddr((caddr_t)&saddr, 360*51667Smckusick sizeof(saddr), AF_INET); 361*51667Smckusick if (hp) 362*51667Smckusick add_mlist(hp->h_name, dirpath); 363*51667Smckusick else 364*51667Smckusick add_mlist(inet_ntoa(transp->xp_raddr.sin_addr), 365*51667Smckusick dirpath); 366*51667Smckusick if (debug) 367*51667Smckusick fprintf(stderr,"Mount successfull.\n"); 36838460Smckusick } 369*51667Smckusick sigsetmask(omask); 37038460Smckusick return; 37138460Smckusick case RPCMNT_DUMP: 37238460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 37338460Smckusick syslog(LOG_ERR, "Can't send reply"); 37438460Smckusick return; 37538460Smckusick case RPCMNT_UMOUNT: 376*51667Smckusick if ((uid != 0 && root_only) || uid == -2) { 37739681Smckusick svcerr_weakauth(transp); 37839681Smckusick return; 37939681Smckusick } 38038460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 38138460Smckusick svcerr_decode(transp); 38238460Smckusick return; 38338460Smckusick } 38438460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 38538460Smckusick syslog(LOG_ERR, "Can't send reply"); 38644015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 38744015Smckusick if (hp) 38844015Smckusick del_mlist(hp->h_name, dirpath); 389*51667Smckusick del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath); 39038460Smckusick return; 39138460Smckusick case RPCMNT_UMNTALL: 392*51667Smckusick if ((uid != 0 && root_only) || uid == -2) { 39339681Smckusick svcerr_weakauth(transp); 39439681Smckusick return; 39539681Smckusick } 39638460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 39738460Smckusick syslog(LOG_ERR, "Can't send reply"); 39844015Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 39944015Smckusick if (hp) 40044015Smckusick del_mlist(hp->h_name, (char *)0); 401*51667Smckusick del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)0); 40238460Smckusick return; 40338460Smckusick case RPCMNT_EXPORT: 40438460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 40538460Smckusick syslog(LOG_ERR, "Can't send reply"); 40638460Smckusick return; 40738460Smckusick default: 40838460Smckusick svcerr_noproc(transp); 40938460Smckusick return; 41038460Smckusick } 41138460Smckusick } 41238460Smckusick 41338460Smckusick /* 41438460Smckusick * Xdr conversion for a dirpath string 41538460Smckusick */ 41638460Smckusick xdr_dir(xdrsp, dirp) 41738460Smckusick XDR *xdrsp; 41838460Smckusick char *dirp; 41938460Smckusick { 42038460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 42138460Smckusick } 42238460Smckusick 42338460Smckusick /* 42438460Smckusick * Xdr routine to generate fhstatus 42538460Smckusick */ 42638460Smckusick xdr_fhs(xdrsp, nfh) 42738460Smckusick XDR *xdrsp; 42838460Smckusick nfsv2fh_t *nfh; 42938460Smckusick { 43038460Smckusick int ok = 0; 43138460Smckusick 43238460Smckusick if (!xdr_long(xdrsp, &ok)) 43338460Smckusick return (0); 43438460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 43538460Smckusick } 43638460Smckusick 43738460Smckusick xdr_mlist(xdrsp, cp) 43838460Smckusick XDR *xdrsp; 43938460Smckusick caddr_t cp; 44038460Smckusick { 44144015Smckusick register struct mountlist *mlp; 44238460Smckusick int true = 1; 44338460Smckusick int false = 0; 44438460Smckusick char *strp; 44538460Smckusick 44644015Smckusick mlp = mlhead; 44744015Smckusick while (mlp) { 44844015Smckusick if (!xdr_bool(xdrsp, &true)) 44944015Smckusick return (0); 45044015Smckusick strp = &mlp->ml_host[0]; 45144015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 45244015Smckusick return (0); 45344015Smckusick strp = &mlp->ml_dirp[0]; 45444015Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 45544015Smckusick return (0); 45644015Smckusick mlp = mlp->ml_next; 45738460Smckusick } 45838460Smckusick if (!xdr_bool(xdrsp, &false)) 45938460Smckusick return (0); 46038460Smckusick return (1); 46138460Smckusick } 46238460Smckusick 46338460Smckusick /* 46438460Smckusick * Xdr conversion for export list 46538460Smckusick */ 46638460Smckusick xdr_explist(xdrsp, cp) 46738460Smckusick XDR *xdrsp; 46838460Smckusick caddr_t cp; 46938460Smckusick { 47038460Smckusick register struct exportlist *ep; 471*51667Smckusick register struct grouplist *grp, *tgrp; 47238460Smckusick int true = 1; 47338460Smckusick int false = 0; 47438460Smckusick char *strp; 47538460Smckusick int omask; 47638460Smckusick 47738460Smckusick omask = sigblock(sigmask(SIGHUP)); 47838460Smckusick ep = exphead.ex_next; 47938460Smckusick while (ep != NULL) { 48038460Smckusick if (!xdr_bool(xdrsp, &true)) 48138460Smckusick goto errout; 48238460Smckusick strp = &ep->ex_dirp[0]; 48338460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 48438460Smckusick goto errout; 48538460Smckusick grp = ep->ex_groups; 48638460Smckusick while (grp != NULL) { 487*51667Smckusick if (grp->type == MNT_GROUP) { 488*51667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 489*51667Smckusick while (tgrp) { 490*51667Smckusick if (!xdr_bool(xdrsp, &true)) 491*51667Smckusick goto errout; 492*51667Smckusick strp = tgrp->gr_ptr.gt_hostent->h_name; 493*51667Smckusick if (!xdr_string(xdrsp, &strp, 494*51667Smckusick RPCMNT_NAMELEN)) 495*51667Smckusick goto errout; 496*51667Smckusick tgrp = tgrp->gr_next; 497*51667Smckusick } 498*51667Smckusick } else if (grp->type == MNT_HOST) { 499*51667Smckusick if (!xdr_bool(xdrsp, &true)) 500*51667Smckusick goto errout; 501*51667Smckusick strp = grp->gr_ptr.gt_hostent->h_name; 502*51667Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 503*51667Smckusick goto errout; 504*51667Smckusick } 50538460Smckusick grp = grp->gr_next; 50638460Smckusick } 50738460Smckusick if (!xdr_bool(xdrsp, &false)) 50838460Smckusick goto errout; 50938460Smckusick ep = ep->ex_next; 51038460Smckusick } 51138460Smckusick sigsetmask(omask); 51238460Smckusick if (!xdr_bool(xdrsp, &false)) 51338460Smckusick return (0); 51438460Smckusick return (1); 51538460Smckusick errout: 51638460Smckusick sigsetmask(omask); 51738460Smckusick return (0); 51838460Smckusick } 51938460Smckusick 52038460Smckusick #define LINESIZ 10240 52138460Smckusick char line[LINESIZ]; 52238460Smckusick 52338460Smckusick /* 52438460Smckusick * Get the export list 52538460Smckusick */ 52646709Sbostic void 52738460Smckusick get_exportlist() 52838460Smckusick { 529*51667Smckusick struct grouplist *grp, *tgrp; 530*51667Smckusick struct al_mnt *al_mp, *t_almp; 53138460Smckusick register struct exportlist *ep, *ep2; 532*51667Smckusick struct groupnames *t_gn, *t_gn2; 533*51667Smckusick struct ucred anoncr; 53438460Smckusick FILE *inf; 53538460Smckusick char *cp, *endcp; 53639681Smckusick char savedc; 537*51667Smckusick int len, dirplen, def_set; 538*51667Smckusick int exflags; 53938460Smckusick 54038460Smckusick /* 54138460Smckusick * First, get rid of the old list 54238460Smckusick */ 54338460Smckusick ep = exphead.ex_next; 54438460Smckusick while (ep != NULL) { 54538460Smckusick ep2 = ep; 54638460Smckusick ep = ep->ex_next; 54744015Smckusick free_exp(ep2); 54838460Smckusick } 549*51667Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 55038460Smckusick 551*51667Smckusick t_gn = grpnames; 552*51667Smckusick while(t_gn != NULL) { 553*51667Smckusick t_gn2 = t_gn; 554*51667Smckusick t_gn = t_gn->gn_next; 555*51667Smckusick free_grp(t_gn2); 556*51667Smckusick } 557*51667Smckusick grpnames = (struct groupnames *)0; 558*51667Smckusick 559*51667Smckusick al_mp = al_head; 560*51667Smckusick while (al_mp) { 561*51667Smckusick t_almp = al_mp; 562*51667Smckusick al_mp = al_mp->al_next; 563*51667Smckusick free((caddr_t)t_almp); 564*51667Smckusick } 565*51667Smckusick al_head = (struct al_mnt *)0; 566*51667Smckusick 56738460Smckusick /* 56838460Smckusick * Read in the exports file and build the list, calling 569*51667Smckusick * mount() as we go along to push the export rules into the kernel. 57038460Smckusick */ 57138460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 57238460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 57338460Smckusick exit(2); 57438460Smckusick } 57538460Smckusick while (fgets(line, LINESIZ, inf)) { 576*51667Smckusick def_set = TRUE; 577*51667Smckusick if (debug) 578*51667Smckusick fprintf(stderr,"Got line %s\n",line); 57938460Smckusick cp = line; 58038460Smckusick nextfield(&cp, &endcp); 581*51667Smckusick if (*cp == '#') 582*51667Smckusick goto nextline; 583*51667Smckusick if (*cp != '/') { 584*51667Smckusick /* create group listing of names */ 585*51667Smckusick get_group(cp, ep); 586*51667Smckusick goto nextline; 58745271Smckusick } 588*51667Smckusick exflags = MNT_EXPORTED; 589*51667Smckusick anoncr = def_anon; 59044015Smckusick 59144015Smckusick /* 59244015Smckusick * Create new exports list entry 59344015Smckusick */ 59438460Smckusick len = endcp-cp; 59538460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 596*51667Smckusick /* 597*51667Smckusick * See if this directory is already in the list. 598*51667Smckusick */ 599*51667Smckusick ep = exphead.ex_next; 600*51667Smckusick while (ep) { 601*51667Smckusick if (!strcmp(ep->ex_dirp, cp)) 602*51667Smckusick break; 603*51667Smckusick ep = ep->ex_next; 604*51667Smckusick } 605*51667Smckusick if (ep == (struct exportlist *)0) { 606*51667Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 607*51667Smckusick if (ep == NULL) 608*51667Smckusick goto err; 609*51667Smckusick ep->ex_next = (struct exportlist *)0; 610*51667Smckusick ep->ex_prev = (struct exportlist *)0; 611*51667Smckusick ep->ex_groups = (struct grouplist *)0; 612*51667Smckusick ep->ex_defset = FALSE; 613*51667Smckusick bcopy(cp, ep->ex_dirp, len); 614*51667Smckusick ep->ex_dirp[len] = '\0'; 615*51667Smckusick } 61644015Smckusick dirplen = len; 617*51667Smckusick if (debug) 618*51667Smckusick fprintf(stderr, "Making new ep. [%s]\n", 619*51667Smckusick ep->ex_dirp); 62045271Smckusick } else { 621*51667Smckusick syslog(LOG_ERR, "Bad Exports File line: %s\n", line); 622*51667Smckusick goto nextline; 62345271Smckusick } 62438460Smckusick cp = endcp; 62538460Smckusick nextfield(&cp, &endcp); 62638460Smckusick len = endcp-cp; 62738460Smckusick while (len > 0) { 62839681Smckusick savedc = *endcp; 62939681Smckusick *endcp = '\0'; 63045271Smckusick if (len > RPCMNT_NAMELEN) 63145271Smckusick goto more; 63245271Smckusick if (*cp == '-') { 633*51667Smckusick do_opt(cp + 1, ep, &exflags, &anoncr); 634*51667Smckusick exflags |= MNT_EXPORTED; 635*51667Smckusick def_set = TRUE; 636*51667Smckusick if (debug) 637*51667Smckusick fprintf(stderr, "got r=%d, ex=%d\n", 638*51667Smckusick anoncr.cr_uid,exflags); 63945271Smckusick goto more; 640*51667Smckusick } else { 641*51667Smckusick def_set = FALSE; 642*51667Smckusick if (*cp == '$') { 643*51667Smckusick do_group(cp + 1, endcp, &grp); 644*51667Smckusick grp->type = MNT_GROUP; 645*51667Smckusick } else { 646*51667Smckusick get_host(cp, endcp, ep, &grp); 64738460Smckusick } 648*51667Smckusick if (grp != NULL) { 649*51667Smckusick grp->exflags = exflags; 650*51667Smckusick grp->anoncr = anoncr; 651*51667Smckusick grp->gr_next = ep->ex_groups; 652*51667Smckusick ep->ex_groups = grp; 653*51667Smckusick } 65438460Smckusick } 65545271Smckusick more: 65638460Smckusick cp = endcp; 65739681Smckusick *cp = savedc; 65838460Smckusick nextfield(&cp, &endcp); 65945271Smckusick len = endcp - cp; 66038460Smckusick } 661*51667Smckusick if (def_set == TRUE) { 662*51667Smckusick if (ep->ex_defset == TRUE) 663*51667Smckusick syslog(LOG_ERR, "Default specified again dir:%s\n", 664*51667Smckusick ep->ex_dirp); 665*51667Smckusick else { 666*51667Smckusick struct hostent *hpe; 667*51667Smckusick 668*51667Smckusick ep->ex_defset = TRUE; 669*51667Smckusick if (debug) 670*51667Smckusick fprintf(stderr,"Adding a default entry\n"); 671*51667Smckusick /* add a default group and make the grp list NULL */ 672*51667Smckusick hpe = (struct hostent *)malloc(sizeof(struct hostent)); 673*51667Smckusick if (hpe == NULL) { 674*51667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 675*51667Smckusick exit(2); 676*51667Smckusick } 677*51667Smckusick tgrp = (struct grouplist *) 678*51667Smckusick malloc(sizeof(struct grouplist)); 679*51667Smckusick if (tgrp == NULL) { 680*51667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 681*51667Smckusick exit(2); 682*51667Smckusick } 683*51667Smckusick tgrp->anoncr = anoncr; 684*51667Smckusick tgrp->exflags = exflags; 685*51667Smckusick hpe->h_name = (char *)malloc(sizeof(DEF_NAME)+1); 686*51667Smckusick if (hpe->h_name == NULL) { 687*51667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 688*51667Smckusick exit(2); 689*51667Smckusick } 690*51667Smckusick strcpy(hpe->h_name,DEF_NAME); 691*51667Smckusick hpe->h_addrtype = AF_INET; 692*51667Smckusick hpe->h_length = sizeof (u_long); 693*51667Smckusick hpe->h_addr_list = INADDR_ANY; 694*51667Smckusick tgrp->gr_ptr.gt_hostent = hpe; 695*51667Smckusick tgrp->gr_next = ep->ex_groups; 696*51667Smckusick ep->ex_groups = tgrp; 697*51667Smckusick } 698*51667Smckusick } 699*51667Smckusick grp = ep->ex_groups; 700*51667Smckusick while (grp != NULL) { 701*51667Smckusick exflags = grp->exflags; 702*51667Smckusick anoncr = grp->anoncr; 703*51667Smckusick if (grp->type == MNT_GROUP) { 704*51667Smckusick tgrp = grp->gr_ptr.gt_grpname->gn_glist; 705*51667Smckusick while(tgrp != NULL) { 706*51667Smckusick if (do_mount(ep, tgrp, exflags, &anoncr, 707*51667Smckusick dirplen) == FALSE) 708*51667Smckusick goto nextline; 709*51667Smckusick tgrp = tgrp->gr_next; 710*51667Smckusick } 711*51667Smckusick } else { 712*51667Smckusick if (do_mount(ep, grp, exflags, &anoncr, dirplen) 713*51667Smckusick == FALSE) 714*51667Smckusick goto nextline; 715*51667Smckusick } 716*51667Smckusick grp = grp->gr_next; 717*51667Smckusick } 718*51667Smckusick if (cp) 719*51667Smckusick *cp = savedc; 720*51667Smckusick if (ep->ex_prev == (struct exportlist *)0) { 721*51667Smckusick ep->ex_next = exphead.ex_next; 722*51667Smckusick ep->ex_prev = &exphead; 723*51667Smckusick if (ep->ex_next != NULL) 724*51667Smckusick ep->ex_next->ex_prev = ep; 725*51667Smckusick exphead.ex_next = ep; 726*51667Smckusick } 727*51667Smckusick nextline: 728*51667Smckusick ; 729*51667Smckusick } 730*51667Smckusick fclose(inf); 731*51667Smckusick return; 732*51667Smckusick err: 733*51667Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 734*51667Smckusick exit(2); 735*51667Smckusick } 736*51667Smckusick 737*51667Smckusick do_mount(ep, grp, exflags, anoncrp, dirplen) 738*51667Smckusick struct exportlist *ep; 739*51667Smckusick struct grouplist *grp; 740*51667Smckusick int exflags, dirplen; 741*51667Smckusick struct ucred *anoncrp; 742*51667Smckusick { 743*51667Smckusick int done, found; 744*51667Smckusick register u_long **addrp; 745*51667Smckusick struct sockaddr_in sin; 746*51667Smckusick struct statfs stfsbuf; 747*51667Smckusick struct ufs_args args, targs; 748*51667Smckusick struct al_mnt *al_mp; 749*51667Smckusick char *cp, savedc; 750*51667Smckusick 751*51667Smckusick args.fspec = 0; 752*51667Smckusick args.exflags = exflags; 753*51667Smckusick args.anon = *anoncrp; 754*51667Smckusick sin.sin_family = AF_INET; 755*51667Smckusick sin.sin_port = 0; 756*51667Smckusick sin.sin_len = sizeof(sin); 757*51667Smckusick if (grp->type == MNT_HOST) 758*51667Smckusick addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; 759*51667Smckusick done = FALSE; 760*51667Smckusick while(!done) { 761*51667Smckusick if (grp->type == MNT_HOST) { 762*51667Smckusick if (!strcmp(grp->gr_ptr.gt_hostent->h_name, DEF_NAME)) 763*51667Smckusick sin.sin_addr.s_addr = INADDR_ANY; 764*51667Smckusick else 765*51667Smckusick sin.sin_addr.s_addr = **addrp; 766*51667Smckusick args.saddr = (struct sockaddr *)&sin; 767*51667Smckusick args.slen = sizeof(sin); 768*51667Smckusick #ifdef ISO 769*51667Smckusick } else if (grp->type == MNT_ISO) { 770*51667Smckusick args.saddr = (struct sockaddr *)grp->gr_ptr.gt_isoaddr; 771*51667Smckusick args.slen = sizeof (struct sockaddr_iso); 772*51667Smckusick #endif /* ISO */ 773*51667Smckusick } else { 774*51667Smckusick syslog(LOG_ERR, "Bad grouptype"); 775*51667Smckusick free_exp(ep); 776*51667Smckusick return (FALSE); 777*51667Smckusick } 778*51667Smckusick if (statfs(ep->ex_dirp, &stfsbuf) < 0) { 779*51667Smckusick if (debug) { 780*51667Smckusick fprintf(stderr,"statfs failed.\n"); 781*51667Smckusick } 782*51667Smckusick syslog(LOG_ERR, "Invalid path: %s", ep->ex_dirp); 783*51667Smckusick free_exp(ep); 784*51667Smckusick return(FALSE); 785*51667Smckusick } 786*51667Smckusick found = FALSE; 787*51667Smckusick for (al_mp = al_head; al_mp && !found; al_mp = al_mp->al_next) 788*51667Smckusick if (al_mp->al_mnted.val[0] == stfsbuf.f_fsid.val[0] && 789*51667Smckusick al_mp->al_mnted.val[1] == stfsbuf.f_fsid.val[1]) 790*51667Smckusick found = TRUE; 791*51667Smckusick if (!found) { 792*51667Smckusick /* first time for fs, so must send a MNT_DELEXPORT 793*51667Smckusick * to clear the old export list held in the kernel 794*51667Smckusick * for this fs. 795*51667Smckusick */ 796*51667Smckusick al_mp = (struct al_mnt *)malloc(sizeof (struct al_mnt)); 797*51667Smckusick al_mp->al_mnted = stfsbuf.f_fsid; 798*51667Smckusick al_mp->al_next = al_head; 799*51667Smckusick al_head = al_mp; 800*51667Smckusick targs.fspec = 0; 801*51667Smckusick targs.exflags = MNT_DELEXPORT; 80244015Smckusick cp = (char *)0; 803*51667Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, 804*51667Smckusick stfsbuf.f_flags | MNT_UPDATE, &targs) < 0) { 805*51667Smckusick if (debug) { 806*51667Smckusick fprintf(stderr, 807*51667Smckusick "tried [%s][%d]\n", 808*51667Smckusick ep->ex_dirp,errno); 809*51667Smckusick } 81044015Smckusick if (cp == NULL) 81144015Smckusick cp = ep->ex_dirp + dirplen - 1; 81244015Smckusick else 81344015Smckusick *cp = savedc; 814*51667Smckusick cp--; 81544015Smckusick /* back up over the last component */ 81644015Smckusick while (*cp == '/' && cp > ep->ex_dirp) 81744015Smckusick cp--; 81844015Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 81944015Smckusick cp--; 82044015Smckusick if (cp == ep->ex_dirp) { 821*51667Smckusick if (debug) { 822*51667Smckusick fprintf(stderr,"mnt unsucc\n"); 823*51667Smckusick } 824*51667Smckusick syslog(LOG_ERR, 825*51667Smckusick "Can't export %s", ep->ex_dirp); 82644015Smckusick free_exp(ep); 827*51667Smckusick return(FALSE); 82844015Smckusick } 82944015Smckusick savedc = *cp; 83044015Smckusick *cp = '\0'; 83144015Smckusick } 832*51667Smckusick if (cp != NULL) { 83344015Smckusick *cp = savedc; 834*51667Smckusick } 83538460Smckusick } 836*51667Smckusick cp = (char *)0; 837*51667Smckusick while (mount(MOUNT_UFS, ep->ex_dirp, 838*51667Smckusick stfsbuf.f_flags | MNT_UPDATE, &args) < 0) { 839*51667Smckusick if (errno == EPERM) { 840*51667Smckusick syslog(LOG_ERR, 841*51667Smckusick "Can't change attributes for %s.\n", 842*51667Smckusick ep->ex_dirp); 843*51667Smckusick if (cp != NULL) 844*51667Smckusick *cp = savedc; 845*51667Smckusick break; 846*51667Smckusick } 847*51667Smckusick if (cp == NULL) 848*51667Smckusick cp = ep->ex_dirp + dirplen - 1; 849*51667Smckusick else 850*51667Smckusick *cp = savedc; 851*51667Smckusick cp--; 852*51667Smckusick /* back up over the last component */ 853*51667Smckusick while (*cp == '/' && cp > ep->ex_dirp) 854*51667Smckusick cp--; 855*51667Smckusick while (*(cp - 1) != '/' && cp > ep->ex_dirp) 856*51667Smckusick cp--; 857*51667Smckusick if (cp == ep->ex_dirp) { 858*51667Smckusick if (debug) { 859*51667Smckusick fprintf(stderr,"mnt unsucc\n"); 860*51667Smckusick } 861*51667Smckusick syslog(LOG_ERR, "Can't export %s", ep->ex_dirp); 862*51667Smckusick free_exp(ep); 863*51667Smckusick return(FALSE); 864*51667Smckusick } 865*51667Smckusick savedc = *cp; 866*51667Smckusick *cp = '\0'; 867*51667Smckusick } 868*51667Smckusick if (addrp == NULL) 869*51667Smckusick done = TRUE; 870*51667Smckusick else { 871*51667Smckusick ++addrp; 872*51667Smckusick if (*addrp == NULL) 873*51667Smckusick done = TRUE; 874*51667Smckusick } 875*51667Smckusick if (cp != NULL) 876*51667Smckusick *cp = savedc; 87738460Smckusick } 878*51667Smckusick return(TRUE); 87938460Smckusick } 88038460Smckusick 881*51667Smckusick 88238460Smckusick /* 88338460Smckusick * Parse out the next white space separated field 88438460Smckusick */ 885*51667Smckusick void 88638460Smckusick nextfield(cp, endcp) 88738460Smckusick char **cp; 88838460Smckusick char **endcp; 88938460Smckusick { 89038460Smckusick register char *p; 89138460Smckusick 89238460Smckusick p = *cp; 89338460Smckusick while (*p == ' ' || *p == '\t') 89438460Smckusick p++; 89538460Smckusick if (*p == '\n' || *p == '\0') { 89638460Smckusick *cp = *endcp = p; 89738460Smckusick return; 89838460Smckusick } 89938460Smckusick *cp = p++; 90038460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 90138460Smckusick p++; 90238460Smckusick *endcp = p; 90338460Smckusick } 90439681Smckusick 90539681Smckusick /* 90644015Smckusick * Parse the option string 90739681Smckusick */ 908*51667Smckusick void 909*51667Smckusick do_opt(cpopt, ep, exflagsp, cr) 91044015Smckusick register char *cpopt; 911*51667Smckusick struct exportlist *ep; 912*51667Smckusick int *exflagsp; 913*51667Smckusick struct ucred *cr; 91439681Smckusick { 91544015Smckusick register char *cpoptarg, *cpoptend; 916*51667Smckusick int allflag; 91739681Smckusick 91844015Smckusick while (cpopt && *cpopt) { 91944015Smckusick if (cpoptend = index(cpopt, ',')) 92044015Smckusick *cpoptend++ = '\0'; 92144015Smckusick if (cpoptarg = index(cpopt, '=')) 92244015Smckusick *cpoptarg++ = '\0'; 92344015Smckusick if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 924*51667Smckusick *exflagsp |= MNT_EXRDONLY; 925*51667Smckusick } else if ((!strcmp(cpopt, "root") || !strcmp(cpopt, "r") || 926*51667Smckusick !(allflag = strcmp(cpopt, "allanon"))) && cpoptarg) { 927*51667Smckusick parsecred(cpoptarg, cr); 928*51667Smckusick if (allflag == 0) 929*51667Smckusick *exflagsp |= MNT_EXPORTANON; 930*51667Smckusick } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 931*51667Smckusick *exflagsp |= MNT_EXKERB; 93244015Smckusick } else 933*51667Smckusick syslog(LOG_ERR, "opt %s ignored for %s", cpopt, 93444015Smckusick ep->ex_dirp); 93544015Smckusick cpopt = cpoptend; 93644015Smckusick } 93744015Smckusick } 93844015Smckusick 939*51667Smckusick /* 940*51667Smckusick * Parse a description of a credential. 941*51667Smckusick */ 942*51667Smckusick parsecred(namelist, cr) 943*51667Smckusick char *namelist; 944*51667Smckusick register struct ucred *cr; 945*51667Smckusick { 946*51667Smckusick register char *name; 947*51667Smckusick register int cnt; 948*51667Smckusick char *names; 949*51667Smckusick struct passwd *pw; 950*51667Smckusick struct group *gr; 951*51667Smckusick int ngroups, groups[NGROUPS + 1]; 952*51667Smckusick 953*51667Smckusick /* 954*51667Smckusick * Set up the unpriviledged user. 955*51667Smckusick */ 956*51667Smckusick cr->cr_ref = 1; 957*51667Smckusick cr->cr_uid = -2; 958*51667Smckusick cr->cr_groups[0] = -2; 959*51667Smckusick cr->cr_ngroups = 1; 960*51667Smckusick /* 961*51667Smckusick * Get the user's password table entry. 962*51667Smckusick */ 963*51667Smckusick names = strsep(&namelist, " \t\n"); 964*51667Smckusick name = strsep(&names, ":"); 965*51667Smckusick if (isdigit(*name) || *name == '-') 966*51667Smckusick pw = getpwuid(atoi(name)); 967*51667Smckusick else 968*51667Smckusick pw = getpwnam(name); 969*51667Smckusick /* 970*51667Smckusick * Credentials specified as those of a user. 971*51667Smckusick */ 972*51667Smckusick if (names == NULL) { 973*51667Smckusick if (pw == NULL) { 974*51667Smckusick syslog(LOG_ERR, "Unknown user: %s\n", name); 975*51667Smckusick return; 976*51667Smckusick } 977*51667Smckusick cr->cr_uid = pw->pw_uid; 978*51667Smckusick ngroups = NGROUPS + 1; 979*51667Smckusick if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) 980*51667Smckusick syslog(LOG_ERR, "Too many groups\n"); 981*51667Smckusick /* 982*51667Smckusick * Convert from int's to gid_t's and compress out duplicate 983*51667Smckusick */ 984*51667Smckusick cr->cr_ngroups = ngroups - 1; 985*51667Smckusick cr->cr_groups[0] = groups[0]; 986*51667Smckusick for (cnt = 2; cnt < ngroups; cnt++) 987*51667Smckusick cr->cr_groups[cnt - 1] = groups[cnt]; 988*51667Smckusick return; 989*51667Smckusick } 990*51667Smckusick /* 991*51667Smckusick * Explicit credential specified as a colon separated list: 992*51667Smckusick * uid:gid:gid:... 993*51667Smckusick */ 994*51667Smckusick if (pw != NULL) 995*51667Smckusick cr->cr_uid = pw->pw_uid; 996*51667Smckusick else if (isdigit(*name) || *name == '-') 997*51667Smckusick cr->cr_uid = atoi(name); 998*51667Smckusick else { 999*51667Smckusick syslog(LOG_ERR, "Unknown user: %s\n", name); 1000*51667Smckusick return; 1001*51667Smckusick } 1002*51667Smckusick cr->cr_ngroups = 0; 1003*51667Smckusick while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { 1004*51667Smckusick name = strsep(&names, ":"); 1005*51667Smckusick if (isdigit(*name) || *name == '-') { 1006*51667Smckusick cr->cr_groups[cr->cr_ngroups++] = atoi(name); 1007*51667Smckusick } else { 1008*51667Smckusick if ((gr = getgrnam(name)) == NULL) { 1009*51667Smckusick syslog(LOG_ERR, "Unknown group: %s\n", name); 1010*51667Smckusick continue; 1011*51667Smckusick } 1012*51667Smckusick cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; 1013*51667Smckusick } 1014*51667Smckusick } 1015*51667Smckusick if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) 1016*51667Smckusick syslog(LOG_ERR, "Too many groups\n"); 1017*51667Smckusick } 1018*51667Smckusick 101944015Smckusick #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 102044015Smckusick /* 102144015Smckusick * Routines that maintain the remote mounttab 102244015Smckusick */ 1023*51667Smckusick void 1024*51667Smckusick get_mountlist() 102544015Smckusick { 102644015Smckusick register struct mountlist *mlp, **mlpp; 102744015Smckusick register char *eos, *dirp; 102844015Smckusick int len; 102944015Smckusick char str[STRSIZ]; 103044015Smckusick FILE *mlfile; 103144015Smckusick 103244338Smckusick if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 103344338Smckusick ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 1034*51667Smckusick syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); 103544015Smckusick return; 103644015Smckusick } 103744015Smckusick mlpp = &mlhead; 103844015Smckusick while (fgets(str, STRSIZ, mlfile) != NULL) { 103944015Smckusick if ((dirp = index(str, '\t')) == NULL && 104044015Smckusick (dirp = index(str, ' ')) == NULL) 104144015Smckusick continue; 104244015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 104344015Smckusick len = dirp-str; 104444015Smckusick if (len > RPCMNT_NAMELEN) 104544015Smckusick len = RPCMNT_NAMELEN; 104644015Smckusick bcopy(str, mlp->ml_host, len); 104744015Smckusick mlp->ml_host[len] = '\0'; 104844015Smckusick while (*dirp == '\t' || *dirp == ' ') 104944015Smckusick dirp++; 105044015Smckusick if ((eos = index(dirp, '\t')) == NULL && 105144015Smckusick (eos = index(dirp, ' ')) == NULL && 105244015Smckusick (eos = index(dirp, '\n')) == NULL) 105344015Smckusick len = strlen(dirp); 105444015Smckusick else 105544015Smckusick len = eos-dirp; 105644015Smckusick if (len > RPCMNT_PATHLEN) 105744015Smckusick len = RPCMNT_PATHLEN; 105844015Smckusick bcopy(dirp, mlp->ml_dirp, len); 105944015Smckusick mlp->ml_dirp[len] = '\0'; 106044015Smckusick mlp->ml_next = (struct mountlist *)0; 106144015Smckusick *mlpp = mlp; 106244015Smckusick mlpp = &mlp->ml_next; 106344015Smckusick } 106444015Smckusick fclose(mlfile); 106544015Smckusick } 106644015Smckusick 1067*51667Smckusick void 1068*51667Smckusick del_mlist(hostp, dirp) 106944015Smckusick register char *hostp, *dirp; 107044015Smckusick { 107144015Smckusick register struct mountlist *mlp, **mlpp; 107244015Smckusick FILE *mlfile; 107344015Smckusick int fnd = 0; 107444015Smckusick 107544015Smckusick mlpp = &mlhead; 107644015Smckusick mlp = mlhead; 107744015Smckusick while (mlp) { 107844015Smckusick if (!strcmp(mlp->ml_host, hostp) && 107944015Smckusick (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 108044015Smckusick fnd = 1; 108144015Smckusick *mlpp = mlp->ml_next; 108244015Smckusick free((caddr_t)mlp); 108339681Smckusick } 108444015Smckusick mlpp = &mlp->ml_next; 108544015Smckusick mlp = mlp->ml_next; 108639681Smckusick } 108744015Smckusick if (fnd) { 108844015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 1089*51667Smckusick syslog(LOG_WARNING,"Can't update %s", _PATH_RMOUNTLIST); 109044015Smckusick return; 109144015Smckusick } 109244015Smckusick mlp = mlhead; 109344015Smckusick while (mlp) { 109444015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 109544015Smckusick mlp = mlp->ml_next; 109644015Smckusick } 109744015Smckusick fclose(mlfile); 109844015Smckusick } 109939681Smckusick } 110044015Smckusick 1101*51667Smckusick void 1102*51667Smckusick add_mlist(hostp, dirp) 110344015Smckusick register char *hostp, *dirp; 110444015Smckusick { 110544015Smckusick register struct mountlist *mlp, **mlpp; 110644015Smckusick FILE *mlfile; 110744015Smckusick 110844015Smckusick mlpp = &mlhead; 110944015Smckusick mlp = mlhead; 111044015Smckusick while (mlp) { 111144015Smckusick if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 111244015Smckusick return; 111344015Smckusick mlpp = &mlp->ml_next; 111444015Smckusick mlp = mlp->ml_next; 111544015Smckusick } 111644015Smckusick mlp = (struct mountlist *)malloc(sizeof (*mlp)); 111744015Smckusick strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 111844015Smckusick mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 111944015Smckusick strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 112044015Smckusick mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 112144015Smckusick mlp->ml_next = (struct mountlist *)0; 112244015Smckusick *mlpp = mlp; 112344015Smckusick if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 112444015Smckusick syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 112544015Smckusick return; 112644015Smckusick } 112744015Smckusick fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 112844015Smckusick fclose(mlfile); 112944015Smckusick } 113044015Smckusick 113144015Smckusick /* 113244015Smckusick * This function is called via. SIGTERM when the system is going down. 113344015Smckusick * It sends a broadcast RPCMNT_UMNTALL. 113444015Smckusick */ 113546709Sbostic void 113644015Smckusick send_umntall() 113744015Smckusick { 113844015Smckusick (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 113944015Smckusick xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 1140*51667Smckusick exit(0); 114144015Smckusick } 114244015Smckusick 114344015Smckusick umntall_each(resultsp, raddr) 114444015Smckusick caddr_t resultsp; 114544015Smckusick struct sockaddr_in *raddr; 114644015Smckusick { 114744015Smckusick return (1); 114844015Smckusick } 114944015Smckusick 115044015Smckusick /* 115144015Smckusick * Free up an exports list component 115244015Smckusick */ 1153*51667Smckusick void 115444015Smckusick free_exp(ep) 115544015Smckusick register struct exportlist *ep; 115644015Smckusick { 115744015Smckusick register struct grouplist *grp; 115844015Smckusick struct grouplist *grp2; 115944015Smckusick 116044015Smckusick grp = ep->ex_groups; 116144015Smckusick while (grp != NULL) { 116244015Smckusick grp2 = grp; 116344015Smckusick grp = grp->gr_next; 1164*51667Smckusick free_grp(grp2); 116544015Smckusick } 116644015Smckusick free((caddr_t)ep); 116744015Smckusick } 1168*51667Smckusick 1169*51667Smckusick /* 1170*51667Smckusick * Free up a group list. 1171*51667Smckusick */ 1172*51667Smckusick void 1173*51667Smckusick free_grp(grp) 1174*51667Smckusick register struct grouplist *grp; 1175*51667Smckusick { 1176*51667Smckusick register char **addrp; 1177*51667Smckusick 1178*51667Smckusick if (grp->type == MNT_HOST) { 1179*51667Smckusick addrp = grp->gr_ptr.gt_hostent->h_addr_list; 1180*51667Smckusick while (addrp && *addrp) 1181*51667Smckusick free(*addrp++); 1182*51667Smckusick free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); 1183*51667Smckusick free(grp->gr_ptr.gt_hostent->h_name); 1184*51667Smckusick free((caddr_t)grp->gr_ptr.gt_hostent); 1185*51667Smckusick } 1186*51667Smckusick #ifdef ISO 1187*51667Smckusick else if (grp->type == MNT_ISO) 1188*51667Smckusick free((caddr_t)grp->gr_ptr.gt_isoaddr); 1189*51667Smckusick #endif 1190*51667Smckusick free((caddr_t)grp); 1191*51667Smckusick } 1192*51667Smckusick 1193*51667Smckusick void 1194*51667Smckusick get_group(line, ep) 1195*51667Smckusick char *line; 1196*51667Smckusick struct export_list *ep; 1197*51667Smckusick { 1198*51667Smckusick int done; 1199*51667Smckusick struct grouplist *grp; 1200*51667Smckusick struct groupnames *t_gn; 1201*51667Smckusick char *cp, *endcp, savedc; 1202*51667Smckusick 1203*51667Smckusick cp = line; 1204*51667Smckusick nextfield(&cp, &endcp); 1205*51667Smckusick savedc = *endcp; 1206*51667Smckusick *endcp = NULL; 1207*51667Smckusick if (*(endcp-1) == '=') { 1208*51667Smckusick *(endcp-1) = NULL; 1209*51667Smckusick } 1210*51667Smckusick /* check to see if this group exists already */ 1211*51667Smckusick t_gn = grpnames; 1212*51667Smckusick while(t_gn != NULL) { 1213*51667Smckusick if (strcmp(t_gn->gn_name,cp) == 0) { 1214*51667Smckusick syslog(LOG_ERR,"Group redifined, second ignored."); 1215*51667Smckusick return; 1216*51667Smckusick } 1217*51667Smckusick t_gn = t_gn->gn_next; 1218*51667Smckusick } 1219*51667Smckusick 1220*51667Smckusick /* make a new group list entry */ 1221*51667Smckusick t_gn = (struct groupnames *)malloc(sizeof(struct groupnames)); 1222*51667Smckusick if (t_gn == NULL) { 1223*51667Smckusick syslog(LOG_ERR,"Group: Couldn't Malloc."); 1224*51667Smckusick exit(2); 1225*51667Smckusick } 1226*51667Smckusick strcpy(t_gn->gn_name,cp); 1227*51667Smckusick t_gn->gn_next = grpnames; 1228*51667Smckusick grpnames = t_gn; 1229*51667Smckusick t_gn->gn_glist = NULL; 1230*51667Smckusick *endcp = savedc; 1231*51667Smckusick cp = endcp; 1232*51667Smckusick done = FALSE; 1233*51667Smckusick while(!done) { 1234*51667Smckusick nextfield(&cp, &endcp); 1235*51667Smckusick if (cp == endcp) 1236*51667Smckusick done = TRUE; 1237*51667Smckusick else { 1238*51667Smckusick savedc = *endcp; 1239*51667Smckusick *endcp = NULL; 1240*51667Smckusick if (strcmp(cp, "=")) { 1241*51667Smckusick /* add to group list */ 1242*51667Smckusick get_host(cp, endcp, ep, &grp); 1243*51667Smckusick if (grp != NULL) { 1244*51667Smckusick grp->gr_next = t_gn->gn_glist; 1245*51667Smckusick t_gn->gn_glist = grp; 1246*51667Smckusick } 1247*51667Smckusick } 1248*51667Smckusick *endcp = savedc; 1249*51667Smckusick cp = endcp; 1250*51667Smckusick } 1251*51667Smckusick } 1252*51667Smckusick } 1253*51667Smckusick 1254*51667Smckusick void 1255*51667Smckusick get_host(cp, endcp, ep, gp) 1256*51667Smckusick char *cp, *endcp; 1257*51667Smckusick struct exportlist *ep; 1258*51667Smckusick struct grouplist **gp; 1259*51667Smckusick { 1260*51667Smckusick register struct hostent *hp, *nhp; 1261*51667Smckusick register struct grouplist *grp; 1262*51667Smckusick register char **addrp, **naddrp; 1263*51667Smckusick struct hostent t_host; 1264*51667Smckusick int i; 1265*51667Smckusick u_long saddr; 1266*51667Smckusick char *aptr[2]; 1267*51667Smckusick #ifdef ISO 1268*51667Smckusick struct iso_addr *isop; 1269*51667Smckusick struct sockaddr_iso *isoaddr; 1270*51667Smckusick #endif 1271*51667Smckusick 1272*51667Smckusick if (isdigit(*cp)) { 1273*51667Smckusick saddr = inet_addr(cp); 1274*51667Smckusick if (saddr == -1) { 1275*51667Smckusick syslog(LOG_ERR, 1276*51667Smckusick "Bad Exports File, %s: %s", cp, 1277*51667Smckusick "inet_addr failed, ignored"); 1278*51667Smckusick *gp = NULL; 1279*51667Smckusick return; 1280*51667Smckusick } 1281*51667Smckusick hp = &t_host; 1282*51667Smckusick hp->h_name = cp; 1283*51667Smckusick hp->h_addrtype = AF_INET; 1284*51667Smckusick hp->h_length = sizeof (u_long); 1285*51667Smckusick hp->h_addr_list = aptr; 1286*51667Smckusick aptr[0] = (char *)&saddr; 1287*51667Smckusick aptr[1] = (char *)0; 1288*51667Smckusick #ifdef ISO 1289*51667Smckusick } else if (!strncmp(cp, "iso=", 4)) { 1290*51667Smckusick if ((isop = iso_addr(cp + 4)) == NULL) { 1291*51667Smckusick syslog(LOG_ERR, 1292*51667Smckusick "Bad Exports File, %s: %s", cp, 1293*51667Smckusick "iso_addr failed, ignored"); 1294*51667Smckusick *gp = NULL; 1295*51667Smckusick return; 1296*51667Smckusick } 1297*51667Smckusick isoaddr = (struct sockaddr_iso *) 1298*51667Smckusick malloc(sizeof (struct sockaddr_iso)); 1299*51667Smckusick if (isoaddr == NULL) 1300*51667Smckusick goto err1; 1301*51667Smckusick bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso)); 1302*51667Smckusick bcopy((caddr_t)isop, (caddr_t)isoaddr->siso_addr, 1303*51667Smckusick sizeof (struct iso_addr)); 1304*51667Smckusick isoaddr->siso_len = sizeof (struct sockaddr_iso); 1305*51667Smckusick isoaddr->siso_family = AF_ISO; 1306*51667Smckusick grp = (struct grouplist *) 1307*51667Smckusick malloc(sizeof(struct grouplist)); 1308*51667Smckusick if (grp == NULL) 1309*51667Smckusick goto err1; 1310*51667Smckusick grp->type = MNT_ISO; 1311*51667Smckusick grp->gr_ptr.gt_isoaddr = isoaddr; 1312*51667Smckusick *gp = grp; 1313*51667Smckusick return; 1314*51667Smckusick #endif /* ISO */ 1315*51667Smckusick } else if ((hp = gethostbyname(cp)) == NULL) { 1316*51667Smckusick syslog(LOG_ERR, "Bad Exports File, %s: %s", 1317*51667Smckusick cp, "Gethostbyname failed, ignored"); 1318*51667Smckusick *gp = NULL; 1319*51667Smckusick return; 1320*51667Smckusick } 1321*51667Smckusick grp = (struct grouplist *) 1322*51667Smckusick malloc(sizeof(struct grouplist)); 1323*51667Smckusick if (grp == NULL) 1324*51667Smckusick goto err1; 1325*51667Smckusick grp->type = MNT_HOST; 1326*51667Smckusick nhp = grp->gr_ptr.gt_hostent = (struct hostent *) 1327*51667Smckusick malloc(sizeof(struct hostent)); 1328*51667Smckusick if (nhp == NULL) 1329*51667Smckusick goto err1; 1330*51667Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 1331*51667Smckusick sizeof(struct hostent)); 1332*51667Smckusick i = strlen(hp->h_name)+1; 1333*51667Smckusick nhp->h_name = (char *)malloc(i); 1334*51667Smckusick if (nhp->h_name == NULL) 1335*51667Smckusick goto err1; 1336*51667Smckusick bcopy(hp->h_name, nhp->h_name, i); 1337*51667Smckusick addrp = hp->h_addr_list; 1338*51667Smckusick i = 1; 1339*51667Smckusick while (*addrp++) 1340*51667Smckusick i++; 1341*51667Smckusick naddrp = nhp->h_addr_list = (char **) 1342*51667Smckusick malloc(i*sizeof(char *)); 1343*51667Smckusick if (naddrp == NULL) 1344*51667Smckusick goto err1; 1345*51667Smckusick addrp = hp->h_addr_list; 1346*51667Smckusick while (*addrp) { 1347*51667Smckusick *naddrp = (char *) 1348*51667Smckusick malloc(hp->h_length); 1349*51667Smckusick if (*naddrp == NULL) 1350*51667Smckusick goto err1; 1351*51667Smckusick bcopy(*addrp, *naddrp, 1352*51667Smckusick hp->h_length); 1353*51667Smckusick addrp++; 1354*51667Smckusick naddrp++; 1355*51667Smckusick } 1356*51667Smckusick *naddrp = (char *)0; 1357*51667Smckusick *gp = grp; 1358*51667Smckusick return; 1359*51667Smckusick err1: 1360*51667Smckusick syslog(LOG_ERR, "No more memory: mountd Failed"); 1361*51667Smckusick exit(2); 1362*51667Smckusick } 1363*51667Smckusick 1364*51667Smckusick void 1365*51667Smckusick do_group(cp, endcp, gp) 1366*51667Smckusick char *cp, *endcp; 1367*51667Smckusick struct grouplist **gp; 1368*51667Smckusick { 1369*51667Smckusick int found; 1370*51667Smckusick struct groupnames *t_gn; 1371*51667Smckusick 1372*51667Smckusick t_gn = grpnames; 1373*51667Smckusick found = FALSE; 1374*51667Smckusick while((t_gn != NULL) && !found) { 1375*51667Smckusick if(strcmp(t_gn->gn_name,cp) == 0) { 1376*51667Smckusick found = TRUE; 1377*51667Smckusick *gp = (struct grouplist *) 1378*51667Smckusick malloc(sizeof(struct grouplist)); 1379*51667Smckusick if (*gp == NULL) { 1380*51667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 1381*51667Smckusick exit(2); 1382*51667Smckusick } 1383*51667Smckusick (*gp)->gr_ptr.gt_grpname = (struct groupnames *) 1384*51667Smckusick malloc(sizeof(struct groupnames)); 1385*51667Smckusick if ((*gp)->gr_ptr.gt_grpname == NULL) { 1386*51667Smckusick syslog(LOG_ERR,"No more memory: mountd Failed"); 1387*51667Smckusick exit(2); 1388*51667Smckusick } 1389*51667Smckusick (*gp)->gr_ptr.gt_grpname->gn_glist = t_gn->gn_glist; 1390*51667Smckusick return; 1391*51667Smckusick } 1392*51667Smckusick t_gn = t_gn->gn_next; 1393*51667Smckusick } 1394*51667Smckusick *gp = NULL; 1395*51667Smckusick } 1396*51667Smckusick 1397*51667Smckusick /* 1398*51667Smckusick * char *realpath(const char *path, char resolved_path[MAXPATHLEN]) 1399*51667Smckusick * 1400*51667Smckusick * find the real name of path, by removing all ".", ".." 1401*51667Smckusick * and symlink components. 1402*51667Smckusick * 1403*51667Smckusick * Jan-Simon Pendry, September 1991. 1404*51667Smckusick */ 1405*51667Smckusick char * 1406*51667Smckusick realpath(path, resolved) 1407*51667Smckusick char *path; 1408*51667Smckusick char resolved[MAXPATHLEN]; 1409*51667Smckusick { 1410*51667Smckusick int d = open(".", O_RDONLY); 1411*51667Smckusick int rootd = 0; 1412*51667Smckusick char *p, *q; 1413*51667Smckusick struct stat stb; 1414*51667Smckusick char wbuf[MAXPATHLEN]; 1415*51667Smckusick 1416*51667Smckusick strcpy(resolved, path); 1417*51667Smckusick 1418*51667Smckusick if (d < 0) 1419*51667Smckusick return 0; 1420*51667Smckusick 1421*51667Smckusick loop:; 1422*51667Smckusick q = strrchr(resolved, '/'); 1423*51667Smckusick if (q) { 1424*51667Smckusick p = q + 1; 1425*51667Smckusick if (q == resolved) 1426*51667Smckusick q = "/"; 1427*51667Smckusick else { 1428*51667Smckusick do 1429*51667Smckusick --q; 1430*51667Smckusick while (q > resolved && *q == '/'); 1431*51667Smckusick q[1] = '\0'; 1432*51667Smckusick q = resolved; 1433*51667Smckusick } 1434*51667Smckusick if (chdir(q) < 0) 1435*51667Smckusick goto out; 1436*51667Smckusick } else 1437*51667Smckusick p = resolved; 1438*51667Smckusick 1439*51667Smckusick if (lstat(p, &stb) == 0) { 1440*51667Smckusick if (S_ISLNK(stb.st_mode)) { 1441*51667Smckusick int n = readlink(p, resolved, MAXPATHLEN); 1442*51667Smckusick if (n < 0) 1443*51667Smckusick goto out; 1444*51667Smckusick resolved[n] = '\0'; 1445*51667Smckusick goto loop; 1446*51667Smckusick } 1447*51667Smckusick if (S_ISDIR(stb.st_mode)) { 1448*51667Smckusick if (chdir(p) < 0) 1449*51667Smckusick goto out; 1450*51667Smckusick p = ""; 1451*51667Smckusick } 1452*51667Smckusick } 1453*51667Smckusick 1454*51667Smckusick strcpy(wbuf, p); 1455*51667Smckusick if (getcwd(resolved, MAXPATHLEN) == 0) 1456*51667Smckusick goto out; 1457*51667Smckusick if (resolved[0] == '/' && resolved[1] == '\0') 1458*51667Smckusick rootd = 1; 1459*51667Smckusick 1460*51667Smckusick if (*wbuf) { 1461*51667Smckusick if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { 1462*51667Smckusick errno = ENAMETOOLONG; 1463*51667Smckusick goto out; 1464*51667Smckusick } 1465*51667Smckusick if (rootd == 0) 1466*51667Smckusick strcat(resolved, "/"); 1467*51667Smckusick strcat(resolved, wbuf); 1468*51667Smckusick } 1469*51667Smckusick 1470*51667Smckusick if (fchdir(d) < 0) 1471*51667Smckusick goto out; 1472*51667Smckusick (void) close(d); 1473*51667Smckusick 1474*51667Smckusick return resolved; 1475*51667Smckusick 1476*51667Smckusick out:; 1477*51667Smckusick (void) close(d); 1478*51667Smckusick return 0; 1479*51667Smckusick } 1480