diff options
-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); } |