diff options
author | 2007-05-27 21:14:41 +0000 | |
---|---|---|
committer | 2007-05-27 21:14:41 +0000 | |
commit | 09b20ce0965b0c782137f33fbf9911b7e02b571e (patch) | |
tree | 40afbe8fb239ef43b753f8ab3a249235d81245ab | |
parent | Add bounds check for cvs command arguments. Initial diff by Tobias (diff) | |
download | wireguard-openbsd-09b20ce0965b0c782137f33fbf9911b7e02b571e.tar.xz wireguard-openbsd-09b20ce0965b0c782137f33fbf9911b7e02b571e.zip |
cleanup the nfssvc() system call.
* Remove alot of dead kerberos code like
the options for NFSSVC_AUTHIN and NFSSVC_AUTHFAIL wich where
originally to get the kerberos auth info into the kernel.
(that hasnt worked for long, if ever.)
Also remove some helper functions and associated goo, however
theres still alot of it left.
* Remove NFSSVC_BIOD, biod's where replaced with kernel threads
a long time ago.
* NFSSVC_MNTD wich was is NQNFS leftover.
Update the man page and nfsd(8).
nfssvc(2) besides being special has only one user in the tree
nfsd(8), therefore no library bumps are needed.
(discussed with deraadt@).
ok beck@, "go a head" deraadt@
Tested by ckuethe@
-rw-r--r-- | lib/libc/sys/nfssvc.2 | 152 | ||||
-rw-r--r-- | sbin/nfsd/nfsd.c | 21 | ||||
-rw-r--r-- | sys/nfs/nfs_syscalls.c | 275 |
3 files changed, 56 insertions, 392 deletions
diff --git a/lib/libc/sys/nfssvc.2 b/lib/libc/sys/nfssvc.2 index 1dcb3473696..acd7e80a506 100644 --- a/lib/libc/sys/nfssvc.2 +++ b/lib/libc/sys/nfssvc.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nfssvc.2,v 1.17 2003/10/22 04:45:54 jmc Exp $ +.\" $OpenBSD: nfssvc.2,v 1.18 2007/05/27 21:14:41 thib Exp $ .\" $NetBSD: nfssvc.2,v 1.6 1995/02/27 12:35:08 cgd Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 @@ -44,94 +44,19 @@ .Sh DESCRIPTION The .Fn nfssvc -function is used by the NFS daemons to pass information into and out -of the kernel and also to enter the kernel as a server daemon. +function is used by the NFS daemons to pass information into the kernel +and also to enter the kernel as a server daemon. The .Fa flags argument consists of several bits that show what action is to be taken once in the kernel and the .Fa argstructp -points to one of three structures depending on which bits are set in +points to one of two structures depending on which bits are set in flags. .Pp -On the client side, there is no longer a need to call -.Fn nfssvc -with the -.Fa flags -argument set to -.Dv NFSSVC_BIOD -since this functionality has been replaced by a -.Nm nfsiod -implementation using kernel threads. -See +To enter an .Xr nfsd 8 -and -.Xr sysctl 8 -for further discussion. -For -.Nm NQNFS , -.Xr mount_nfs 8 -calls -.Fn nfssvc -with the -.Dv NFSSVC_MNTD -flag, optionally or'd with the flags -.Dv NFSSVC_GOTAUTH -and -.Dv NFSSVC_AUTHINFAIL -along with a pointer to a -.Bd -literal -struct nfsd_cargs { - char *ncd_dirp; /* Mount dir path */ - uid_t ncd_authuid; /* Effective uid */ - int ncd_authtype; /* Type of authenticator */ - u_int ncd_authlen; /* Length of authenticator string */ - u_char *ncd_authstr; /* Authenticator string */ - u_int ncd_verflen; /* and the verifier */ - u_char *ncd_verfstr; - NFSKERBKEY_T ncd_key; /* Session key */ -}; -.Ed -.Pp -structure. -The initial call has only the -.Dv NFSSVC_MNTD -flag set to specify service for the mount point. -If the mount point is using Kerberos, then the -.Xr mount_nfs 8 -daemon will return from -.Fn nfssvc -with -.Va errno -set to -.Er ENEEDAUTH -whenever the client side requires an -.Dq rcmd -authentication ticket for the user. -.Xr mount_nfs 8 -will attempt to get the Kerberos ticket, and if successful will call -.Fn nfssvc -with the flags -.Dv NFSSVC_MNTD -and -.Dv NFSSVC_GOTAUTH -after filling the ticket into the -ncd_authstr field -and -setting the ncd_authlen and ncd_authtype -fields of the nfsd_cargs structure. -If -.Xr mount_nfs 8 -failed to get the ticket, -.Fn nfssvc -will be called with the flags -.Dv NFSSVC_MNTD , -.Dv NFSSVC_GOTAUTH -and -.Dv NFSSVC_AUTHINFAIL -to denote a failed authentication attempt. -.Pp -On the server side, +daemon into the kernel .Fn nfssvc is called with the flag .Dv NFSSVC_NFSD @@ -151,51 +76,13 @@ struct nfsd_srvargs { NFSKERBKEY_T nsd_key; /* Session key */ }; .Ed +structure. .Pp -to enter the kernel as an -.Xr nfsd 8 -daemon. -Whenever an +To add further sockets for processing by the .Xr nfsd 8 -daemon receives a Kerberos authentication ticket, it will return from -.Fn nfssvc -with -.Va errno -set to -.Er ENEEDAUTH . -The -.Xr nfsd 8 -will attempt to authenticate the ticket and generate a set of credentials -on the server for the user ID specified in the field nsd_uid. -This is done by first authenticating the Kerberos ticket and then mapping -the Kerberos principal to a local name and getting a set of credentials for -that user via -.Xr getpwnam 3 -and -.Xr getgrouplist 3 . -If successful, the -.Xr nfsd 8 -will call -.Fn nfssvc -with the -.Dv NFSSVC_NFSD -and -.Dv NFSSVC_AUTHIN -flags set to pass the credential mapping in nsd_cr into the -kernel to be cached on the server socket for that client. -If the authentication failed, -.Xr nfsd 8 -calls -.Fn nfssvc -with the flags -.Dv NFSSVC_NFSD -and -.Dv NFSSVC_AUTHINFAIL -to denote an authentication failure. -.Pp -The master +server daemons the master .Xr nfsd 8 -server daemon calls +daemon calls .Fn nfssvc with the flag .Dv NFSSVC_ADDSOCK @@ -207,12 +94,8 @@ struct nfsd_args { int namelen; /* Length of name */ }; .Ed +structure. .Pp -to pass a server side -.Tn NFS -socket into the kernel for servicing by the -.Xr nfsd 8 -daemons. .Sh RETURN VALUES Normally .Nm nfssvc @@ -223,12 +106,11 @@ Otherwise, \-1 is returned and the global variable is set to specify the error. .Sh ERRORS .Bl -tag -width Er -.It Bq Er ENEEDAUTH -This special error value -is really used for authentication support, particularly Kerberos, -as explained above. .It Bq Er EPERM The caller is not the superuser. +.It Bq Er EINVAL +The flag argument consisted of incompatible or otherwise +unsupported bits. .El .Sh SEE ALSO .Xr mount_nfs 8 , @@ -245,11 +127,7 @@ The system call is designed specifically for the .Tn NFS support daemons and as such is specific to their requirements. -It should really return values to indicate the need for authentication -support, since -.Er ENEEDAUTH -is not really an error. Several fields of the argument structures are assumed to be valid and sometimes to be unchanged from a previous call, such that -.Nm nfssvc +.Fn nfssvc must be used with extreme care. diff --git a/sbin/nfsd/nfsd.c b/sbin/nfsd/nfsd.c index b963f55dbbb..14286e1159b 100644 --- a/sbin/nfsd/nfsd.c +++ b/sbin/nfsd/nfsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfsd.c,v 1.26 2005/12/02 01:08:01 deraadt Exp $ */ +/* $OpenBSD: nfsd.c,v 1.27 2007/05/27 21:14:41 thib Exp $ */ /* $NetBSD: nfsd.c,v 1.19 1996/02/18 23:18:56 mycroft Exp $ */ /* @@ -43,7 +43,7 @@ static const char copyright[] = #if 0 static const char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; #else -static const char rcsid[] = "$OpenBSD: nfsd.c,v 1.26 2005/12/02 01:08:01 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: nfsd.c,v 1.27 2007/05/27 21:14:41 thib Exp $"; #endif #endif /* not lint */ @@ -120,7 +120,7 @@ main(int argc, char *argv[]) fd_set *ready, *sockbits; size_t fd_size; int ch, connect_type_cnt, i, maxsock = 0, msgsock; - int nfsdcnt = DEFNFSDCNT, nfssvc_flag, on, reregister = 0, sock; + int nfsdcnt = DEFNFSDCNT, on, reregister = 0, sock; int udpflag = 0, tcpflag = 0, tcpsock; const char *errstr = NULL; socklen_t len; @@ -199,14 +199,10 @@ main(int argc, char *argv[]) } setproctitle("server"); - nfssvc_flag = NFSSVC_NFSD; nsd.nsd_nfsd = NULL; - while (nfssvc(nfssvc_flag, &nsd) < 0) { - if (errno != ENEEDAUTH) { - syslog(LOG_ERR, "nfssvc: %m"); - return (1); - } - nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; + if (nfssvc(NFSSVC_NFSD, &nsd) < 0) { + syslog(LOG_ERR, "nfssvc: %m"); + return (1); } return (0); } @@ -323,7 +319,10 @@ main(int argc, char *argv[]) nfsdargs.sock = msgsock; nfsdargs.name = (caddr_t)&inetpeer; nfsdargs.namelen = sizeof(inetpeer); - nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { + syslog(LOG_ERR, "can't Add TCP socket"); + return (1); + } (void)close(msgsock); } } diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c index 25e956d0f8c..a6da0887e1e 100644 --- a/sys/nfs/nfs_syscalls.c +++ b/sys/nfs/nfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_syscalls.c,v 1.50 2006/11/29 12:24:18 miod Exp $ */ +/* $OpenBSD: nfs_syscalls.c,v 1.51 2007/05/27 21:14:41 thib Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* @@ -109,187 +109,57 @@ int nfs_niothreads = -1; static void nfsd_rt(int, struct nfsrv_descript *, int); #endif -int nfs_clientd(struct nfsmount *nmp, struct ucred *cred, - struct nfsd_cargs *ncd, int flag, caddr_t argp, struct proc *p); - /* - * Nfs client helper daemon. - * It also get authorization strings for "kerb" mounts. - * It must start at the beginning of the list again after any potential - * "sleep" since nfs_reclaim() called from vclean() can pull a node off - * the list asynchronously. - */ -int -nfs_clientd(struct nfsmount *nmp, struct ucred *cred, struct nfsd_cargs *ncd, - int flag, caddr_t argp, struct proc *p) -{ - struct nfsuid *nuidp, *nnuidp; - int error = 0; - - /* - * First initialize some variables - */ - - /* - * If an authorization string is being passed in, get it. - */ - if ((flag & NFSSVC_GOTAUTH) && - (nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) { - if (nmp->nm_flag & NFSMNT_HASAUTH) - panic("cld kerb"); - if ((flag & NFSSVC_AUTHINFAIL) == 0) { - if (ncd->ncd_authlen <= nmp->nm_authlen && - ncd->ncd_verflen <= nmp->nm_verflen && - !copyin(ncd->ncd_authstr,nmp->nm_authstr,ncd->ncd_authlen)&& - !copyin(ncd->ncd_verfstr,nmp->nm_verfstr,ncd->ncd_verflen)){ - nmp->nm_authtype = ncd->ncd_authtype; - nmp->nm_authlen = ncd->ncd_authlen; - nmp->nm_verflen = ncd->ncd_verflen; - } else - nmp->nm_flag |= NFSMNT_AUTHERR; - } else - nmp->nm_flag |= NFSMNT_AUTHERR; - nmp->nm_flag |= NFSMNT_HASAUTH; - wakeup((caddr_t)&nmp->nm_authlen); - } else - nmp->nm_flag |= NFSMNT_WAITAUTH; - - /* - * Loop every second updating queue until there is a termination sig. - */ - while ((nmp->nm_flag & NFSMNT_DISMNT) == 0) { - /* - * Get an authorization string, if required. - */ - if ((nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT | NFSMNT_HASAUTH)) == 0) { - ncd->ncd_authuid = nmp->nm_authuid; - if (copyout((caddr_t)ncd, argp, sizeof (struct nfsd_cargs))) - nmp->nm_flag |= NFSMNT_WAITAUTH; - else - return (ENEEDAUTH); - } - - /* - * Wait a bit (no pun) and do it again. - */ - if ((nmp->nm_flag & NFSMNT_DISMNT) == 0 && - (nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_HASAUTH))) { - error = tsleep((caddr_t)&nmp->nm_authstr, PSOCK | PCATCH, - "nqnfstimr", hz / 3); - if (error == EINTR || error == ERESTART) { - if (vfs_busy(nmp->nm_mountp, VB_WRITE|VB_WAIT) == 0) - dounmount(nmp->nm_mountp, MNT_FORCE, p, NULL); - } - } - } - - /* - * Finally, we can free up the mount structure. - */ - for (nuidp = TAILQ_FIRST(&nmp->nm_uidlruhead); nuidp != NULL; - nuidp = nnuidp) { - nnuidp = TAILQ_NEXT(nuidp, nu_lru); - LIST_REMOVE(nuidp, nu_hash); - TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru); - free((caddr_t)nuidp, M_NFSUID); - } - free((caddr_t)nmp, M_NFSMNT); - if (error == EWOULDBLOCK) - error = 0; - return (error); -} - - -/* - * NFS server system calls - */ - -/* - * Nfs server pseudo system call for the nfsd's + * NFS server pseudo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd - * - remains in the kernel as an nfsiod */ int -sys_nfssvc(p, v, retval) - struct proc *p; - void *v; - register_t *retval; +sys_nfssvc(struct proc *p, void *v, register_t *retval) { struct sys_nfssvc_args /* { syscallarg(int) flag; syscallarg(caddr_t) argp; } */ *uap = v; -#ifdef NFSCLIENT - struct nameidata nd; - struct nfsmount *nmp; - struct nfsd_cargs ncd; -#endif - int error; + int flags = SCARG(uap, flag); + int error = 0; #ifdef NFSSERVER struct file *fp; struct mbuf *nam; struct nfsd_args nfsdarg; struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; - struct nfsd *nfsd; - struct nfssvc_sock *slp; - struct nfsuid *nuidp; #endif - /* - * Must be super user - */ + /* Must be super user */ error = suser(p, 0); - if(error) + if (error) return (error); - while (nfssvc_sockhead_flag & SLP_INIT) { - nfssvc_sockhead_flag |= SLP_WANTINIT; - (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); - } - if (SCARG(uap, flag) & NFSSVC_BIOD) { - error = ENOSYS; - } else if (SCARG(uap, flag) & NFSSVC_MNTD) { -#ifndef NFSCLIENT - error = ENOSYS; -#else - error = copyin(SCARG(uap, argp), (caddr_t)&ncd, sizeof (ncd)); - if (error) - return (error); - NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, - ncd.ncd_dirp, p); - error = namei(&nd); - if (error) - return (error); - if ((nd.ni_vp->v_flag & VROOT) == 0) - error = EINVAL; - nmp = VFSTONFS(nd.ni_vp->v_mount); - vput(nd.ni_vp); - if (error) - return (error); - if ((nmp->nm_flag & NFSMNT_MNTD) && - (SCARG(uap, flag) & NFSSVC_GOTAUTH) == 0) - return (0); - nmp->nm_flag |= NFSMNT_MNTD; - error = nfs_clientd(nmp, p->p_ucred, &ncd, SCARG(uap, flag), - SCARG(uap, argp), p); -#endif /* NFSCLIENT */ - } else if (SCARG(uap, flag) & NFSSVC_ADDSOCK) { + #ifndef NFSSERVER - error = ENOSYS; + error = ENOSYS; #else - error = copyin(SCARG(uap, argp), (caddr_t)&nfsdarg, - sizeof(nfsdarg)); + + while (nfssvc_sockhead_flag & SLP_INIT) { + nfssvc_sockhead_flag |= SLP_WANTINIT; + tsleep(&nfssvc_sockhead, PSOCK, "nfsd init", 0); + } + + switch (flags) { + case NFSSVC_ADDSOCK: + error = copyin(SCARG(uap, argp), &nfsdarg, sizeof(nfsdarg)); if (error) return (error); + error = getsock(p->p_fd, nfsdarg.sock, &fp); if (error) return (error); + /* * Get the client address for connected sockets. */ if (nfsdarg.name == NULL || nfsdarg.namelen == 0) - nam = (struct mbuf *)0; + nam = NULL; else { error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, MT_SONAME); @@ -300,106 +170,23 @@ sys_nfssvc(p, v, retval) } error = nfssvc_addsock(fp, nam); FRELE(fp); -#endif /* !NFSSERVER */ - } else { -#ifndef NFSSERVER - error = ENOSYS; -#else - error = copyin(SCARG(uap, argp), (caddr_t)nsd, sizeof (*nsd)); + break; + case NFSSVC_NFSD: + error = copyin(SCARG(uap, argp), nsd, sizeof(*nsd)); if (error) return (error); - if ((SCARG(uap, flag) & NFSSVC_AUTHIN) && - ((nfsd = nsd->nsd_nfsd)) != NULL && - (nfsd->nfsd_slp->ns_flag & SLP_VALID)) { - slp = nfsd->nfsd_slp; - - /* - * First check to see if another nfsd has already - * added this credential. - */ - LIST_FOREACH(nuidp, NUIDHASH(slp,nsd->nsd_cr.cr_uid), - nu_hash) { - if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid && - (!nfsd->nfsd_nd->nd_nam2 || - netaddr_match(NU_NETFAM(nuidp), - &nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2))) - break; - } - if (nuidp) { - nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr); - nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; - } else { - /* - * Nope, so we will. - */ - if (slp->ns_numuids < nuidhash_max) { - slp->ns_numuids++; - nuidp = (struct nfsuid *) - malloc(sizeof (struct nfsuid), M_NFSUID, - M_WAITOK); - } else - nuidp = (struct nfsuid *)0; - if ((slp->ns_flag & SLP_VALID) == 0) { - if (nuidp) - free((caddr_t)nuidp, M_NFSUID); - } else { - if (nuidp == (struct nfsuid *)0) { - nuidp = TAILQ_FIRST(&slp->ns_uidlruhead); - LIST_REMOVE(nuidp, nu_hash); - TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, - nu_lru); - if (nuidp->nu_flag & NU_NAM) - m_freem(nuidp->nu_nam); - } - nuidp->nu_flag = 0; - nuidp->nu_cr = nsd->nsd_cr; - if (nuidp->nu_cr.cr_ngroups > NGROUPS) - nuidp->nu_cr.cr_ngroups = NGROUPS; - nuidp->nu_cr.cr_ref = 1; - nuidp->nu_timestamp = nsd->nsd_timestamp; - nuidp->nu_expire = time_second + nsd->nsd_ttl; - /* - * and save the session key in nu_key. - */ - bcopy(nsd->nsd_key, nuidp->nu_key, - sizeof (nsd->nsd_key)); - if (nfsd->nfsd_nd->nd_nam2) { - struct sockaddr_in *saddr; - saddr = mtod(nfsd->nfsd_nd->nd_nam2, - struct sockaddr_in *); - switch (saddr->sin_family) { - case AF_INET: - nuidp->nu_flag |= NU_INETADDR; - nuidp->nu_inetaddr = - saddr->sin_addr.s_addr; - break; - default: - nuidp->nu_flag |= NU_NAM; - nuidp->nu_nam = m_copym( - nfsd->nfsd_nd->nd_nam2, 0, - M_COPYALL, M_WAIT); - break; - }; - } - TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp, - nu_lru); - LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid), - nuidp, nu_hash); - nfsrv_setcred(&nuidp->nu_cr, - &nfsd->nfsd_nd->nd_cr); - nfsd->nfsd_nd->nd_flag |= ND_KERBFULL; - } - } - } - if ((SCARG(uap, flag) & NFSSVC_AUTHINFAIL) && - (nfsd = nsd->nsd_nfsd)) - nfsd->nfsd_flag |= NFSD_AUTHFAIL; error = nfssvc_nfsd(nsd, SCARG(uap, argp), p); -#endif /* !NFSSERVER */ + break; + default: + error = EINVAL; + break; } + if (error == EINTR || error == ERESTART) error = 0; +#endif /* !NFSSERVER */ + return (error); } |