18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 388fae3551SRodney W. Grimes static char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 418fae3551SRodney W. Grimes #endif not lint 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 448fae3551SRodney W. Grimes static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94"; 458fae3551SRodney W. Grimes #endif not lint 468fae3551SRodney W. Grimes 478fae3551SRodney W. Grimes #include <sys/param.h> 488fae3551SRodney W. Grimes #include <sys/syslog.h> 498fae3551SRodney W. Grimes #include <sys/ioctl.h> 508fae3551SRodney W. Grimes #include <sys/stat.h> 518fae3551SRodney W. Grimes #include <sys/wait.h> 528fae3551SRodney W. Grimes #include <sys/uio.h> 538fae3551SRodney W. Grimes #include <sys/ucred.h> 548fae3551SRodney W. Grimes #include <sys/mount.h> 558fae3551SRodney W. Grimes #include <sys/socket.h> 568fae3551SRodney W. Grimes #include <sys/socketvar.h> 578fae3551SRodney W. Grimes 588fae3551SRodney W. Grimes #include <rpc/rpc.h> 598fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 608fae3551SRodney W. Grimes #include <rpc/pmap_prot.h> 618fae3551SRodney W. Grimes 628fae3551SRodney W. Grimes #ifdef ISO 638fae3551SRodney W. Grimes #include <netiso/iso.h> 648fae3551SRodney W. Grimes #endif 658fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 66a62dc406SDoug Rabson #include <nfs/nfsproto.h> 678fae3551SRodney W. Grimes #include <nfs/nfs.h> 688fae3551SRodney W. Grimes 69a62dc406SDoug Rabson #ifdef NFSKERB 708fae3551SRodney W. Grimes #include <kerberosIV/des.h> 718fae3551SRodney W. Grimes #include <kerberosIV/krb.h> 728fae3551SRodney W. Grimes #endif 738fae3551SRodney W. Grimes 748fae3551SRodney W. Grimes #include <err.h> 758fae3551SRodney W. Grimes #include <errno.h> 768fae3551SRodney W. Grimes #include <fcntl.h> 778fae3551SRodney W. Grimes #include <grp.h> 788fae3551SRodney W. Grimes #include <pwd.h> 798fae3551SRodney W. Grimes #include <signal.h> 808fae3551SRodney W. Grimes #include <stdio.h> 818fae3551SRodney W. Grimes #include <stdlib.h> 828fae3551SRodney W. Grimes #include <strings.h> 838fae3551SRodney W. Grimes #include <unistd.h> 848fae3551SRodney W. Grimes 858fae3551SRodney W. Grimes /* Global defs */ 868fae3551SRodney W. Grimes #ifdef DEBUG 878fae3551SRodney W. Grimes #define syslog(e, s) fprintf(stderr,(s)) 888fae3551SRodney W. Grimes int debug = 1; 898fae3551SRodney W. Grimes #else 908fae3551SRodney W. Grimes int debug = 0; 918fae3551SRodney W. Grimes #endif 928fae3551SRodney W. Grimes 938fae3551SRodney W. Grimes struct nfsd_srvargs nsd; 948fae3551SRodney W. Grimes char **Argv = NULL; /* pointer to argument vector */ 958fae3551SRodney W. Grimes char *LastArg = NULL; /* end of argv */ 968fae3551SRodney W. Grimes 97a62dc406SDoug Rabson #ifdef NFSKERB 988fae3551SRodney W. Grimes char lnam[ANAME_SZ]; 998fae3551SRodney W. Grimes KTEXT_ST kt; 100a62dc406SDoug Rabson AUTH_DAT kauth; 1018fae3551SRodney W. Grimes char inst[INST_SZ]; 102a62dc406SDoug Rabson struct nfsrpc_fullblock kin, kout; 103a62dc406SDoug Rabson struct nfsrpc_fullverf kverf; 104a62dc406SDoug Rabson NFSKERBKEY_T kivec; 105a62dc406SDoug Rabson struct timeval ktv; 106a62dc406SDoug Rabson NFSKERBKEYSCHED_T kerb_keysched; 1078fae3551SRodney W. Grimes #endif 1088fae3551SRodney W. Grimes 1098fae3551SRodney W. Grimes void nonfs __P((int)); 1108fae3551SRodney W. Grimes void reapchild __P((int)); 111a62dc406SDoug Rabson #ifdef __FreeBSD__ 1128fae3551SRodney W. Grimes void setproctitle __P((char *)); 113a62dc406SDoug Rabson #endif 1148fae3551SRodney W. Grimes void usage __P((void)); 1158fae3551SRodney W. Grimes 1168fae3551SRodney W. Grimes /* 1178fae3551SRodney W. Grimes * Nfs server daemon mostly just a user context for nfssvc() 1188fae3551SRodney W. Grimes * 1198fae3551SRodney W. Grimes * 1 - do file descriptor and signal cleanup 1208fae3551SRodney W. Grimes * 2 - fork the nfsd(s) 1218fae3551SRodney W. Grimes * 3 - create server socket(s) 1228fae3551SRodney W. Grimes * 4 - register socket with portmap 1238fae3551SRodney W. Grimes * 1248fae3551SRodney W. Grimes * For connectionless protocols, just pass the socket into the kernel via. 1258fae3551SRodney W. Grimes * nfssvc(). 1268fae3551SRodney W. Grimes * For connection based sockets, loop doing accepts. When you get a new 1278fae3551SRodney W. Grimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1288fae3551SRodney W. Grimes * The arguments are: 1298fae3551SRodney W. Grimes * -c - support iso cltp clients 1308fae3551SRodney W. Grimes * -r - reregister with portmapper 1318fae3551SRodney W. Grimes * -t - support tcp nfs clients 1328fae3551SRodney W. Grimes * -u - support udp nfs clients 1338fae3551SRodney W. Grimes * followed by "n" which is the number of nfsds' to fork off 1348fae3551SRodney W. Grimes */ 1358fae3551SRodney W. Grimes int 1368fae3551SRodney W. Grimes main(argc, argv, envp) 1378fae3551SRodney W. Grimes int argc; 1388fae3551SRodney W. Grimes char *argv[], *envp[]; 1398fae3551SRodney W. Grimes { 1408fae3551SRodney W. Grimes extern int optind; 1418fae3551SRodney W. Grimes struct group *grp; 1428fae3551SRodney W. Grimes struct nfsd_args nfsdargs; 1438fae3551SRodney W. Grimes struct passwd *pwd; 1448fae3551SRodney W. Grimes struct ucred *cr; 1458fae3551SRodney W. Grimes struct sockaddr_in inetaddr, inetpeer; 1468fae3551SRodney W. Grimes #ifdef ISO 1478fae3551SRodney W. Grimes struct sockaddr_iso isoaddr, isopeer; 1488fae3551SRodney W. Grimes #endif 149a62dc406SDoug Rabson struct timeval ktv; 1508fae3551SRodney W. Grimes fd_set ready, sockbits; 1518fae3551SRodney W. Grimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 1528fae3551SRodney W. Grimes int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 1538fae3551SRodney W. Grimes int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; 1548fae3551SRodney W. Grimes char *cp, **cpp; 155a62dc406SDoug Rabson #ifdef __FreeBSD__ 156d599144dSGarrett Wollman struct vfsconf *vfc; 157d599144dSGarrett Wollman 158d599144dSGarrett Wollman vfc = getvfsbyname("nfs"); 159d599144dSGarrett Wollman if(!vfc && vfsisloadable("nfs")) { 160d599144dSGarrett Wollman if(vfsload("nfs")) 161d599144dSGarrett Wollman err(1, "vfsload(nfs)"); 162d599144dSGarrett Wollman endvfsent(); /* flush cache */ 163d599144dSGarrett Wollman vfc = getvfsbyname("nfs"); /* probably unnecessary */ 164d599144dSGarrett Wollman } 165d599144dSGarrett Wollman if(!vfc) { 166d599144dSGarrett Wollman errx(1, "NFS is not available in the running kernel"); 167d599144dSGarrett Wollman } 168a62dc406SDoug Rabson #endif 1698fae3551SRodney W. Grimes 1708fae3551SRodney W. Grimes /* Save start and extent of argv for setproctitle. */ 1718fae3551SRodney W. Grimes Argv = argv; 1728fae3551SRodney W. Grimes if (envp == 0 || *envp == 0) 1738fae3551SRodney W. Grimes envp = argv; 1748fae3551SRodney W. Grimes while (*envp) 1758fae3551SRodney W. Grimes envp++; 1768fae3551SRodney W. Grimes LastArg = envp[-1] + strlen(envp[-1]); 1778fae3551SRodney W. Grimes 1788fae3551SRodney W. Grimes #define MAXNFSDCNT 20 1798fae3551SRodney W. Grimes #define DEFNFSDCNT 4 1808fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 1818fae3551SRodney W. Grimes cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 1828fae3551SRodney W. Grimes tpipflag = udpflag = 0; 1838fae3551SRodney W. Grimes #ifdef ISO 1848fae3551SRodney W. Grimes #define GETOPT "cn:rtu" 1858fae3551SRodney W. Grimes #define USAGE "[-crtu] [-n num_servers]" 1868fae3551SRodney W. Grimes #else 1878fae3551SRodney W. Grimes #define GETOPT "n:rtu" 1888fae3551SRodney W. Grimes #define USAGE "[-rtu] [-n num_servers]" 1898fae3551SRodney W. Grimes #endif 1908fae3551SRodney W. Grimes while ((ch = getopt(argc, argv, GETOPT)) != EOF) 1918fae3551SRodney W. Grimes switch (ch) { 1928fae3551SRodney W. Grimes case 'n': 1938fae3551SRodney W. Grimes nfsdcnt = atoi(optarg); 1948fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 1958fae3551SRodney W. Grimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 1968fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 1978fae3551SRodney W. Grimes } 1988fae3551SRodney W. Grimes break; 1998fae3551SRodney W. Grimes case 'r': 2008fae3551SRodney W. Grimes reregister = 1; 2018fae3551SRodney W. Grimes break; 2028fae3551SRodney W. Grimes case 't': 2038fae3551SRodney W. Grimes tcpflag = 1; 2048fae3551SRodney W. Grimes break; 2058fae3551SRodney W. Grimes case 'u': 2068fae3551SRodney W. Grimes udpflag = 1; 2078fae3551SRodney W. Grimes break; 2088fae3551SRodney W. Grimes #ifdef ISO 2098fae3551SRodney W. Grimes case 'c': 2108fae3551SRodney W. Grimes cltpflag = 1; 2118fae3551SRodney W. Grimes break; 2128fae3551SRodney W. Grimes #ifdef notyet 2138fae3551SRodney W. Grimes case 'i': 2148fae3551SRodney W. Grimes tp4cnt = 1; 2158fae3551SRodney W. Grimes break; 2168fae3551SRodney W. Grimes case 'p': 2178fae3551SRodney W. Grimes tpipcnt = 1; 2188fae3551SRodney W. Grimes break; 2198fae3551SRodney W. Grimes #endif /* notyet */ 2208fae3551SRodney W. Grimes #endif /* ISO */ 2218fae3551SRodney W. Grimes default: 2228fae3551SRodney W. Grimes case '?': 2238fae3551SRodney W. Grimes usage(); 2248fae3551SRodney W. Grimes }; 2258fae3551SRodney W. Grimes argv += optind; 2268fae3551SRodney W. Grimes argc -= optind; 2278fae3551SRodney W. Grimes 2288fae3551SRodney W. Grimes /* 2298fae3551SRodney W. Grimes * XXX 2308fae3551SRodney W. Grimes * Backward compatibility, trailing number is the count of daemons. 2318fae3551SRodney W. Grimes */ 2328fae3551SRodney W. Grimes if (argc > 1) 2338fae3551SRodney W. Grimes usage(); 2348fae3551SRodney W. Grimes if (argc == 1) { 2358fae3551SRodney W. Grimes nfsdcnt = atoi(argv[0]); 2368fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2378fae3551SRodney W. Grimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 2388fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 2398fae3551SRodney W. Grimes } 2408fae3551SRodney W. Grimes } 2418fae3551SRodney W. Grimes 2428fae3551SRodney W. Grimes if (debug == 0) { 2438fae3551SRodney W. Grimes daemon(0, 0); 2448fae3551SRodney W. Grimes (void)signal(SIGHUP, SIG_IGN); 2458fae3551SRodney W. Grimes (void)signal(SIGINT, SIG_IGN); 2468fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_IGN); 2478fae3551SRodney W. Grimes (void)signal(SIGSYS, nonfs); 2488fae3551SRodney W. Grimes (void)signal(SIGTERM, SIG_IGN); 2498fae3551SRodney W. Grimes } 2508fae3551SRodney W. Grimes (void)signal(SIGCHLD, reapchild); 2518fae3551SRodney W. Grimes 2528fae3551SRodney W. Grimes if (reregister) { 2538fae3551SRodney W. Grimes if (udpflag && 254a62dc406SDoug Rabson (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 255a62dc406SDoug Rabson !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) 2568fae3551SRodney W. Grimes err(1, "can't register with portmap for UDP."); 2578fae3551SRodney W. Grimes if (tcpflag && 258a62dc406SDoug Rabson (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 259a62dc406SDoug Rabson !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) 2608fae3551SRodney W. Grimes err(1, "can't register with portmap for TCP."); 2618fae3551SRodney W. Grimes exit(0); 2628fae3551SRodney W. Grimes } 2638fae3551SRodney W. Grimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 2648fae3551SRodney W. Grimes 2658fae3551SRodney W. Grimes for (i = 0; i < nfsdcnt; i++) { 2668fae3551SRodney W. Grimes switch (fork()) { 2678fae3551SRodney W. Grimes case -1: 2688fae3551SRodney W. Grimes syslog(LOG_ERR, "fork: %m"); 2698fae3551SRodney W. Grimes exit (1); 2708fae3551SRodney W. Grimes case 0: 2718fae3551SRodney W. Grimes break; 2728fae3551SRodney W. Grimes default: 2738fae3551SRodney W. Grimes continue; 2748fae3551SRodney W. Grimes } 2758fae3551SRodney W. Grimes 276a62dc406SDoug Rabson setproctitle("server"); 2778fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD; 2788fae3551SRodney W. Grimes nsd.nsd_nfsd = NULL; 279a62dc406SDoug Rabson #ifdef NFSKERB 280a62dc406SDoug Rabson if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 281a62dc406SDoug Rabson sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 282a62dc406SDoug Rabson syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 283a62dc406SDoug Rabson nsd.nsd_authstr = (u_char *)&kt; 284a62dc406SDoug Rabson nsd.nsd_authlen = sizeof (kt); 285a62dc406SDoug Rabson nsd.nsd_verfstr = (u_char *)&kverf; 286a62dc406SDoug Rabson nsd.nsd_verflen = sizeof (kverf); 2878fae3551SRodney W. Grimes #endif 2888fae3551SRodney W. Grimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 2898fae3551SRodney W. Grimes if (errno != ENEEDAUTH) { 2908fae3551SRodney W. Grimes syslog(LOG_ERR, "nfssvc: %m"); 2918fae3551SRodney W. Grimes exit(1); 2928fae3551SRodney W. Grimes } 2938fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 294a62dc406SDoug Rabson #ifdef NFSKERB 295a62dc406SDoug Rabson /* 296a62dc406SDoug Rabson * Get the Kerberos ticket out of the authenticator 297a62dc406SDoug Rabson * verify it and convert the principal name to a user 298a62dc406SDoug Rabson * name. The user name is then converted to a set of 299a62dc406SDoug Rabson * user credentials via the password and group file. 300a62dc406SDoug Rabson * Finally, decrypt the timestamp and validate it. 301a62dc406SDoug Rabson * For more info see the IETF Draft "Authentication 302a62dc406SDoug Rabson * in ONC RPC". 303a62dc406SDoug Rabson */ 304a62dc406SDoug Rabson kt.length = ntohl(kt.length); 305a62dc406SDoug Rabson if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 306a62dc406SDoug Rabson kt.length > 0 && kt.length <= 307a62dc406SDoug Rabson (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 308a62dc406SDoug Rabson kin.w1 = NFS_KERBW1(kt); 3098fae3551SRodney W. Grimes kt.mbz = 0; 3108fae3551SRodney W. Grimes (void)strcpy(inst, "*"); 311a62dc406SDoug Rabson if (krb_rd_req(&kt, NFS_KERBSRV, 312a62dc406SDoug Rabson inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 313a62dc406SDoug Rabson krb_kntoln(&kauth, lnam) == KSUCCESS && 3148fae3551SRodney W. Grimes (pwd = getpwnam(lnam)) != NULL) { 3158fae3551SRodney W. Grimes cr = &nsd.nsd_cr; 3168fae3551SRodney W. Grimes cr->cr_uid = pwd->pw_uid; 3178fae3551SRodney W. Grimes cr->cr_groups[0] = pwd->pw_gid; 3188fae3551SRodney W. Grimes cr->cr_ngroups = 1; 3198fae3551SRodney W. Grimes setgrent(); 3208fae3551SRodney W. Grimes while ((grp = getgrent()) != NULL) { 3218fae3551SRodney W. Grimes if (grp->gr_gid == cr->cr_groups[0]) 3228fae3551SRodney W. Grimes continue; 3238fae3551SRodney W. Grimes for (cpp = grp->gr_mem; 3248fae3551SRodney W. Grimes *cpp != NULL; ++cpp) 3258fae3551SRodney W. Grimes if (!strcmp(*cpp, lnam)) 3268fae3551SRodney W. Grimes break; 3278fae3551SRodney W. Grimes if (*cpp == NULL) 3288fae3551SRodney W. Grimes continue; 3298fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] 3308fae3551SRodney W. Grimes = grp->gr_gid; 3318fae3551SRodney W. Grimes if (cr->cr_ngroups == NGROUPS) 3328fae3551SRodney W. Grimes break; 3338fae3551SRodney W. Grimes } 3348fae3551SRodney W. Grimes endgrent(); 335a62dc406SDoug Rabson 336a62dc406SDoug Rabson /* 337a62dc406SDoug Rabson * Get the timestamp verifier out of the 338a62dc406SDoug Rabson * authenticator and verifier strings. 339a62dc406SDoug Rabson */ 340a62dc406SDoug Rabson kin.t1 = kverf.t1; 341a62dc406SDoug Rabson kin.t2 = kverf.t2; 342a62dc406SDoug Rabson kin.w2 = kverf.w2; 343a62dc406SDoug Rabson bzero((caddr_t)kivec, sizeof (kivec)); 344a62dc406SDoug Rabson bcopy((caddr_t)kauth.session, 345a62dc406SDoug Rabson (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 346a62dc406SDoug Rabson 347a62dc406SDoug Rabson /* 348a62dc406SDoug Rabson * Decrypt the timestamp verifier in CBC mode. 349a62dc406SDoug Rabson */ 350a62dc406SDoug Rabson XXX 351a62dc406SDoug Rabson 352a62dc406SDoug Rabson /* 353a62dc406SDoug Rabson * Validate the timestamp verifier, to 354a62dc406SDoug Rabson * check that the session key is ok. 355a62dc406SDoug Rabson */ 356a62dc406SDoug Rabson nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 357a62dc406SDoug Rabson nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 358a62dc406SDoug Rabson nsd.nsd_ttl = ntohl(kout.w1); 359a62dc406SDoug Rabson if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 3608fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 3618fae3551SRodney W. Grimes } 362a62dc406SDoug Rabson #endif /* NFSKERB */ 3638fae3551SRodney W. Grimes } 3648fae3551SRodney W. Grimes exit(0); 3658fae3551SRodney W. Grimes } 3668fae3551SRodney W. Grimes 3678fae3551SRodney W. Grimes /* If we are serving udp, set up the socket. */ 3688fae3551SRodney W. Grimes if (udpflag) { 3698fae3551SRodney W. Grimes if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 3708fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create udp socket"); 3718fae3551SRodney W. Grimes exit(1); 3728fae3551SRodney W. Grimes } 3738fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 3748fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3758fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 3768fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 3778fae3551SRodney W. Grimes if (bind(sock, 3788fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 3798fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind udp addr"); 3808fae3551SRodney W. Grimes exit(1); 3818fae3551SRodney W. Grimes } 382a62dc406SDoug Rabson if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 383a62dc406SDoug Rabson !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { 3848fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register with udp portmap"); 3858fae3551SRodney W. Grimes exit(1); 3868fae3551SRodney W. Grimes } 3878fae3551SRodney W. Grimes nfsdargs.sock = sock; 3888fae3551SRodney W. Grimes nfsdargs.name = NULL; 3898fae3551SRodney W. Grimes nfsdargs.namelen = 0; 3908fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 3918fae3551SRodney W. Grimes syslog(LOG_ERR, "can't Add UDP socket"); 3928fae3551SRodney W. Grimes exit(1); 3938fae3551SRodney W. Grimes } 3948fae3551SRodney W. Grimes (void)close(sock); 3958fae3551SRodney W. Grimes } 3968fae3551SRodney W. Grimes 3978fae3551SRodney W. Grimes #ifdef ISO 3988fae3551SRodney W. Grimes /* If we are serving cltp, set up the socket. */ 3998fae3551SRodney W. Grimes if (cltpflag) { 4008fae3551SRodney W. Grimes if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 4018fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create cltp socket"); 4028fae3551SRodney W. Grimes exit(1); 4038fae3551SRodney W. Grimes } 4048fae3551SRodney W. Grimes memset(&isoaddr, 0, sizeof(isoaddr)); 4058fae3551SRodney W. Grimes isoaddr.siso_family = AF_ISO; 4068fae3551SRodney W. Grimes isoaddr.siso_tlen = 2; 4078fae3551SRodney W. Grimes cp = TSEL(&isoaddr); 4088fae3551SRodney W. Grimes *cp++ = (NFS_PORT >> 8); 4098fae3551SRodney W. Grimes *cp = (NFS_PORT & 0xff); 4108fae3551SRodney W. Grimes isoaddr.siso_len = sizeof(isoaddr); 4118fae3551SRodney W. Grimes if (bind(sock, 4128fae3551SRodney W. Grimes (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 4138fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind cltp addr"); 4148fae3551SRodney W. Grimes exit(1); 4158fae3551SRodney W. Grimes } 4168fae3551SRodney W. Grimes #ifdef notyet 4178fae3551SRodney W. Grimes /* 4188fae3551SRodney W. Grimes * XXX 4198fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 4208fae3551SRodney W. Grimes * portmap. 4218fae3551SRodney W. Grimes */ 4228fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 4238fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register with udp portmap"); 4248fae3551SRodney W. Grimes exit(1); 4258fae3551SRodney W. Grimes } 4268fae3551SRodney W. Grimes #endif /* notyet */ 4278fae3551SRodney W. Grimes nfsdargs.sock = sock; 4288fae3551SRodney W. Grimes nfsdargs.name = NULL; 4298fae3551SRodney W. Grimes nfsdargs.namelen = 0; 4308fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 4318fae3551SRodney W. Grimes syslog(LOG_ERR, "can't add UDP socket"); 4328fae3551SRodney W. Grimes exit(1); 4338fae3551SRodney W. Grimes } 4348fae3551SRodney W. Grimes close(sock); 4358fae3551SRodney W. Grimes } 4368fae3551SRodney W. Grimes #endif /* ISO */ 4378fae3551SRodney W. Grimes 4388fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tcp connections. */ 4398fae3551SRodney W. Grimes on = 1; 4408fae3551SRodney W. Grimes FD_ZERO(&sockbits); 4418fae3551SRodney W. Grimes connect_type_cnt = 0; 4428fae3551SRodney W. Grimes if (tcpflag) { 4438fae3551SRodney W. Grimes if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 4448fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tcp socket"); 4458fae3551SRodney W. Grimes exit(1); 4468fae3551SRodney W. Grimes } 4478fae3551SRodney W. Grimes if (setsockopt(tcpsock, 4488fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4498fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4508fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 4518fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 4528fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 4538fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 4548fae3551SRodney W. Grimes if (bind(tcpsock, 4558fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 4568fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tcp addr"); 4578fae3551SRodney W. Grimes exit(1); 4588fae3551SRodney W. Grimes } 4598fae3551SRodney W. Grimes if (listen(tcpsock, 5) < 0) { 4608fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 4618fae3551SRodney W. Grimes exit(1); 4628fae3551SRodney W. Grimes } 463a62dc406SDoug Rabson if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 464a62dc406SDoug Rabson !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { 4658fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 4668fae3551SRodney W. Grimes exit(1); 4678fae3551SRodney W. Grimes } 4688fae3551SRodney W. Grimes FD_SET(tcpsock, &sockbits); 4698fae3551SRodney W. Grimes maxsock = tcpsock; 4708fae3551SRodney W. Grimes connect_type_cnt++; 4718fae3551SRodney W. Grimes } 4728fae3551SRodney W. Grimes 4738fae3551SRodney W. Grimes #ifdef notyet 4748fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tp4 connections. */ 4758fae3551SRodney W. Grimes if (tp4flag) { 4768fae3551SRodney W. Grimes if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 4778fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tp4 socket"); 4788fae3551SRodney W. Grimes exit(1); 4798fae3551SRodney W. Grimes } 4808fae3551SRodney W. Grimes if (setsockopt(tp4sock, 4818fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4828fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4838fae3551SRodney W. Grimes memset(&isoaddr, 0, sizeof(isoaddr)); 4848fae3551SRodney W. Grimes isoaddr.siso_family = AF_ISO; 4858fae3551SRodney W. Grimes isoaddr.siso_tlen = 2; 4868fae3551SRodney W. Grimes cp = TSEL(&isoaddr); 4878fae3551SRodney W. Grimes *cp++ = (NFS_PORT >> 8); 4888fae3551SRodney W. Grimes *cp = (NFS_PORT & 0xff); 4898fae3551SRodney W. Grimes isoaddr.siso_len = sizeof(isoaddr); 4908fae3551SRodney W. Grimes if (bind(tp4sock, 4918fae3551SRodney W. Grimes (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 4928fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tp4 addr"); 4938fae3551SRodney W. Grimes exit(1); 4948fae3551SRodney W. Grimes } 4958fae3551SRodney W. Grimes if (listen(tp4sock, 5) < 0) { 4968fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 4978fae3551SRodney W. Grimes exit(1); 4988fae3551SRodney W. Grimes } 4998fae3551SRodney W. Grimes /* 5008fae3551SRodney W. Grimes * XXX 5018fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 5028fae3551SRodney W. Grimes * portmap. 5038fae3551SRodney W. Grimes */ 5048fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5058fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 5068fae3551SRodney W. Grimes exit(1); 5078fae3551SRodney W. Grimes } 5088fae3551SRodney W. Grimes FD_SET(tp4sock, &sockbits); 5098fae3551SRodney W. Grimes maxsock = tp4sock; 5108fae3551SRodney W. Grimes connect_type_cnt++; 5118fae3551SRodney W. Grimes } 5128fae3551SRodney W. Grimes 5138fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tpip connections. */ 5148fae3551SRodney W. Grimes if (tpipflag) { 5158fae3551SRodney W. Grimes if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 5168fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tpip socket"); 5178fae3551SRodney W. Grimes exit(1); 5188fae3551SRodney W. Grimes } 5198fae3551SRodney W. Grimes if (setsockopt(tpipsock, 5208fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 5218fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 5228fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 5238fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 5248fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 5258fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 5268fae3551SRodney W. Grimes if (bind(tpipsock, 5278fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 5288fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tcp addr"); 5298fae3551SRodney W. Grimes exit(1); 5308fae3551SRodney W. Grimes } 5318fae3551SRodney W. Grimes if (listen(tpipsock, 5) < 0) { 5328fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 5338fae3551SRodney W. Grimes exit(1); 5348fae3551SRodney W. Grimes } 5358fae3551SRodney W. Grimes /* 5368fae3551SRodney W. Grimes * XXX 5378fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 5388fae3551SRodney W. Grimes * portmap. 5398fae3551SRodney W. Grimes */ 5408fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5418fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 5428fae3551SRodney W. Grimes exit(1); 5438fae3551SRodney W. Grimes } 5448fae3551SRodney W. Grimes FD_SET(tpipsock, &sockbits); 5458fae3551SRodney W. Grimes maxsock = tpipsock; 5468fae3551SRodney W. Grimes connect_type_cnt++; 5478fae3551SRodney W. Grimes } 5488fae3551SRodney W. Grimes #endif /* notyet */ 5498fae3551SRodney W. Grimes 5508fae3551SRodney W. Grimes if (connect_type_cnt == 0) 5518fae3551SRodney W. Grimes exit(0); 5528fae3551SRodney W. Grimes 553a62dc406SDoug Rabson setproctitle("master"); 5548fae3551SRodney W. Grimes 5558fae3551SRodney W. Grimes /* 5568fae3551SRodney W. Grimes * Loop forever accepting connections and passing the sockets 5578fae3551SRodney W. Grimes * into the kernel for the mounts. 5588fae3551SRodney W. Grimes */ 5598fae3551SRodney W. Grimes for (;;) { 5608fae3551SRodney W. Grimes ready = sockbits; 5618fae3551SRodney W. Grimes if (connect_type_cnt > 1) { 5628fae3551SRodney W. Grimes if (select(maxsock + 1, 5638fae3551SRodney W. Grimes &ready, NULL, NULL, NULL) < 1) { 5648fae3551SRodney W. Grimes syslog(LOG_ERR, "select failed: %m"); 5658fae3551SRodney W. Grimes exit(1); 5668fae3551SRodney W. Grimes } 5678fae3551SRodney W. Grimes } 5688fae3551SRodney W. Grimes if (tcpflag && FD_ISSET(tcpsock, &ready)) { 5698fae3551SRodney W. Grimes len = sizeof(inetpeer); 5708fae3551SRodney W. Grimes if ((msgsock = accept(tcpsock, 5718fae3551SRodney W. Grimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5728fae3551SRodney W. Grimes syslog(LOG_ERR, "accept failed: %m"); 5738fae3551SRodney W. Grimes exit(1); 5748fae3551SRodney W. Grimes } 5758fae3551SRodney W. Grimes memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 5768fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 5778fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5788fae3551SRodney W. Grimes syslog(LOG_ERR, 5798fae3551SRodney W. Grimes "setsockopt SO_KEEPALIVE: %m"); 5808fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 5818fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&inetpeer; 5828fae3551SRodney W. Grimes nfsdargs.namelen = sizeof(inetpeer); 5838fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5848fae3551SRodney W. Grimes (void)close(msgsock); 5858fae3551SRodney W. Grimes } 5868fae3551SRodney W. Grimes #ifdef notyet 5878fae3551SRodney W. Grimes if (tp4flag && FD_ISSET(tp4sock, &ready)) { 5888fae3551SRodney W. Grimes len = sizeof(isopeer); 5898fae3551SRodney W. Grimes if ((msgsock = accept(tp4sock, 5908fae3551SRodney W. Grimes (struct sockaddr *)&isopeer, &len)) < 0) { 5918fae3551SRodney W. Grimes syslog(LOG_ERR, "accept failed: %m"); 5928fae3551SRodney W. Grimes exit(1); 5938fae3551SRodney W. Grimes } 5948fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 5958fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5968fae3551SRodney W. Grimes syslog(LOG_ERR, 5978fae3551SRodney W. Grimes "setsockopt SO_KEEPALIVE: %m"); 5988fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 5998fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&isopeer; 6008fae3551SRodney W. Grimes nfsdargs.namelen = len; 6018fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6028fae3551SRodney W. Grimes (void)close(msgsock); 6038fae3551SRodney W. Grimes } 6048fae3551SRodney W. Grimes if (tpipflag && FD_ISSET(tpipsock, &ready)) { 6058fae3551SRodney W. Grimes len = sizeof(inetpeer); 6068fae3551SRodney W. Grimes if ((msgsock = accept(tpipsock, 6078fae3551SRodney W. Grimes (struct sockaddr *)&inetpeer, &len)) < 0) { 6088fae3551SRodney W. Grimes syslog(LOG_ERR, "Accept failed: %m"); 6098fae3551SRodney W. Grimes exit(1); 6108fae3551SRodney W. Grimes } 6118fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 6128fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6138fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 6148fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 6158fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&inetpeer; 6168fae3551SRodney W. Grimes nfsdargs.namelen = len; 6178fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6188fae3551SRodney W. Grimes (void)close(msgsock); 6198fae3551SRodney W. Grimes } 6208fae3551SRodney W. Grimes #endif /* notyet */ 6218fae3551SRodney W. Grimes } 6228fae3551SRodney W. Grimes } 6238fae3551SRodney W. Grimes 6248fae3551SRodney W. Grimes void 6258fae3551SRodney W. Grimes usage() 6268fae3551SRodney W. Grimes { 627a62dc406SDoug Rabson (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 6288fae3551SRodney W. Grimes exit(1); 6298fae3551SRodney W. Grimes } 6308fae3551SRodney W. Grimes 6318fae3551SRodney W. Grimes void 6328fae3551SRodney W. Grimes nonfs(signo) 6338fae3551SRodney W. Grimes int signo; 6348fae3551SRodney W. Grimes { 6358fae3551SRodney W. Grimes syslog(LOG_ERR, "missing system call: NFS not available."); 6368fae3551SRodney W. Grimes } 6378fae3551SRodney W. Grimes 6388fae3551SRodney W. Grimes void 6398fae3551SRodney W. Grimes reapchild(signo) 6408fae3551SRodney W. Grimes int signo; 6418fae3551SRodney W. Grimes { 6428fae3551SRodney W. Grimes 643a62dc406SDoug Rabson while (wait3(NULL, WNOHANG, NULL) > 0); 6448fae3551SRodney W. Grimes } 6458fae3551SRodney W. Grimes 646a62dc406SDoug Rabson #ifdef __FreeBSD__ 6478fae3551SRodney W. Grimes void 6488fae3551SRodney W. Grimes setproctitle(a) 6498fae3551SRodney W. Grimes char *a; 6508fae3551SRodney W. Grimes { 6518fae3551SRodney W. Grimes register char *cp; 6528fae3551SRodney W. Grimes char buf[80]; 6538fae3551SRodney W. Grimes 6548fae3551SRodney W. Grimes cp = Argv[0]; 655a62dc406SDoug Rabson (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 6568fae3551SRodney W. Grimes (void)strncpy(cp, buf, LastArg - cp); 6578fae3551SRodney W. Grimes cp += strlen(cp); 6588fae3551SRodney W. Grimes while (cp < LastArg) 6596aab3b5aSDavid Greenman *cp++ = '\0'; 6608fae3551SRodney W. Grimes } 661a62dc406SDoug Rabson #endif /* __FreeBSD__ */ 662