diff options
author | dfr <dfr@FreeBSD.org> | 2008-11-03 10:38:00 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2008-11-03 10:38:00 +0000 |
commit | 2fb03513fc4b5d35a398f1ceb4b439fe4bb5fb74 (patch) | |
tree | c59f88924c0b3ead68523ce14806894836f8d9a7 /sys/nfsserver/nfs.h | |
parent | 8b86595849b35ac7c26977f1b8206c1678c9b5bb (diff) | |
download | FreeBSD-src-2fb03513fc4b5d35a398f1ceb4b439fe4bb5fb74.zip FreeBSD-src-2fb03513fc4b5d35a398f1ceb4b439fe4bb5fb74.tar.gz |
Implement support for RPCSEC_GSS authentication to both the NFS client
and server. This replaces the RPC implementation of the NFS client and
server with the newer RPC implementation originally developed
(actually ported from the userland sunrpc code) to support the NFS
Lock Manager. I have tested this code extensively and I believe it is
stable and that performance is at least equal to the legacy RPC
implementation.
The NFS code currently contains support for both the new RPC
implementation and the older legacy implementation inherited from the
original NFS codebase. The default is to use the new implementation -
add the NFS_LEGACYRPC option to fall back to the old code. When I
merge this support back to RELENG_7, I will probably change this so
that users have to 'opt in' to get the new code.
To use RPCSEC_GSS on either client or server, you must build a kernel
which includes the KGSSAPI option and the crypto device. On the
userland side, you must build at least a new libc, mountd, mount_nfs
and gssd. You must install new versions of /etc/rc.d/gssd and
/etc/rc.d/nfsd and add 'gssd_enable=YES' to /etc/rc.conf.
As long as gssd is running, you should be able to mount an NFS
filesystem from a server that requires RPCSEC_GSS authentication. The
mount itself can happen without any kerberos credentials but all
access to the filesystem will be denied unless the accessing user has
a valid ticket file in the standard place (/tmp/krb5cc_<uid>). There
is currently no support for situations where the ticket file is in a
different place, such as when the user logged in via SSH and has
delegated credentials from that login. This restriction is also
present in Solaris and Linux. In theory, we could improve this in
future, possibly using Brooks Davis' implementation of variant
symlinks.
Supporting RPCSEC_GSS on a server is nearly as simple. You must create
service creds for the server in the form 'nfs/<fqdn>@<REALM>' and
install them in /etc/krb5.keytab. The standard heimdal utility ktutil
makes this fairly easy. After the service creds have been created, you
can add a '-sec=krb5' option to /etc/exports and restart both mountd
and nfsd.
The only other difference an administrator should notice is that nfsd
doesn't fork to create service threads any more. In normal operation,
there will be two nfsd processes, one in userland waiting for TCP
connections and one in the kernel handling requests. The latter
process will create as many kthreads as required - these should be
visible via 'top -H'. The code has some support for varying the number
of service threads according to load but initially at least, nfsd uses
a fixed number of threads according to the value supplied to its '-n'
option.
Sponsored by: Isilon Systems
MFC after: 1 month
Diffstat (limited to 'sys/nfsserver/nfs.h')
-rw-r--r-- | sys/nfsserver/nfs.h | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h index beb9359..2709377 100644 --- a/sys/nfsserver/nfs.h +++ b/sys/nfsserver/nfs.h @@ -89,13 +89,26 @@ * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs * should ever try and use it. */ -struct nfsd_args { + +/* + * Add a socket to monitor for NFS requests. + */ +struct nfsd_addsock_args { int sock; /* Socket to serve */ caddr_t name; /* Client addr for connection based sockets */ int namelen; /* Length of name */ }; /* + * Start processing requests. + */ +struct nfsd_nfsd_args { + const char *principal; /* GSS-API service principal name */ + int minthreads; /* minimum service thread count */ + int maxthreads; /* maximum service thread count */ +}; + +/* * XXX to allow amd to include nfs.h without nfsproto.h */ #ifdef NFS_NPROCS @@ -105,8 +118,9 @@ struct nfsd_args { /* * Flags for nfssvc() system call. */ -#define NFSSVC_NFSD 0x004 +#define NFSSVC_OLDNFSD 0x004 #define NFSSVC_ADDSOCK 0x008 +#define NFSSVC_NFSD 0x010 /* * vfs.nfsrv sysctl(3) identifiers @@ -167,6 +181,7 @@ extern int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd, #define NWDELAYHASH(sock, f) \ (&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ]) +#ifdef NFS_LEGACYRPC /* * Network address hash list element */ @@ -257,11 +272,37 @@ struct nfsrv_descript { struct timeval nd_starttime; /* Time RPC initiated */ fhandle_t nd_fh; /* File handle */ struct ucred *nd_cr; /* Credentials */ + int nd_credflavor; /* Security flavor */ }; +#else + +/* + * This structure is used by the server for describing each request. + */ +struct nfsrv_descript { + struct mbuf *nd_mrep; /* Request mbuf list */ + struct mbuf *nd_md; /* Current dissect mbuf */ + struct mbuf *nd_mreq; /* Reply mbuf list */ + struct sockaddr *nd_nam; /* and socket addr */ + struct sockaddr *nd_nam2; /* return socket addr */ + caddr_t nd_dpos; /* Current dissect pos */ + u_int32_t nd_procnum; /* RPC # */ + int nd_stable; /* storage type */ + int nd_flag; /* nd_flag */ + int nd_repstat; /* Reply status */ + fhandle_t nd_fh; /* File handle */ + struct ucred *nd_cr; /* Credentials */ + int nd_credflavor; /* Security flavor */ +}; + +#endif + /* Bits for "nd_flag" */ #define ND_NFSV3 0x08 +#ifdef NFS_LEGACYRPC + extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head; extern int nfsd_head_flag; #define NFSD_CHECKSLP 0x01 @@ -273,6 +314,8 @@ extern int nfsd_head_flag; ((o)->nd_eoff >= (n)->nd_off && \ !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH)) +#endif + /* * Defines for WebNFS */ @@ -315,38 +358,42 @@ extern int nfs_debug; #endif +#ifdef NFS_LEGACYRPC +int netaddr_match(int, union nethostaddr *, struct sockaddr *); int nfs_getreq(struct nfsrv_descript *, struct nfsd *, int); int nfsrv_send(struct socket *, struct sockaddr *, struct mbuf *); -struct mbuf *nfs_rephead(int, struct nfsrv_descript *, int, struct mbuf **, - caddr_t *); +int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *, + struct nfsrv_descript **); int nfs_slplock(struct nfssvc_sock *, int); void nfs_slpunlock(struct nfssvc_sock *); +void nfsrv_initcache(void); +void nfsrv_destroycache(void); +void nfsrv_timer(void *); +int nfsrv_getcache(struct nfsrv_descript *, struct mbuf **); +void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *); +void nfsrv_cleancache(void); +void nfsrv_rcv(struct socket *so, void *arg, int waitflag); +void nfsrv_slpderef(struct nfssvc_sock *slp); +void nfsrv_wakenfsd(struct nfssvc_sock *slp); +int nfsrv_writegather(struct nfsrv_descript **, struct nfssvc_sock *, + struct mbuf **); +#endif +struct mbuf *nfs_rephead(int, struct nfsrv_descript *, int, struct mbuf **, + caddr_t *); void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *, struct nfs_fattr *); void nfsm_srvwcc(struct nfsrv_descript *, int, struct vattr *, int, struct vattr *, struct mbuf **, char **); void nfsm_srvpostopattr(struct nfsrv_descript *, int, struct vattr *, struct mbuf **, char **); -int netaddr_match(int, union nethostaddr *, struct sockaddr *); -int nfs_namei(struct nameidata *, fhandle_t *, int, - struct nfssvc_sock *, struct sockaddr *, struct mbuf **, +int nfs_namei(struct nameidata *, struct nfsrv_descript *, fhandle_t *, + int, struct nfssvc_sock *, struct sockaddr *, struct mbuf **, caddr_t *, struct vnode **, int, struct vattr *, int *, int); void nfsm_adj(struct mbuf *, int, int); int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *); -void nfsrv_initcache(void); -void nfsrv_destroycache(void); -void nfsrv_timer(void *); -int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *, - struct nfsrv_descript **); -int nfsrv_getcache(struct nfsrv_descript *, struct mbuf **); -void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *); -void nfsrv_cleancache(void); void nfsrv_init(int); int nfsrv_errmap(struct nfsrv_descript *, int); void nfsrvw_sort(gid_t *, int); -void nfsrv_wakenfsd(struct nfssvc_sock *slp); -int nfsrv_writegather(struct nfsrv_descript **, struct nfssvc_sock *, - struct mbuf **); int nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf **mrq); @@ -354,8 +401,9 @@ int nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf **mrq); int nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf **mrq); -int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, int *, struct ucred *, - struct nfssvc_sock *, struct sockaddr *, int *, int); +int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, int *, + struct nfsrv_descript *, struct nfssvc_sock *, struct sockaddr *, + int *, int); int nfsrv_setpublicfs(struct mount *, struct netexport *, struct export_args *); int nfs_ispublicfh(fhandle_t *); @@ -399,8 +447,6 @@ int nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf **mrq); int nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, struct mbuf **mrq); -void nfsrv_rcv(struct socket *so, void *arg, int waitflag); -void nfsrv_slpderef(struct nfssvc_sock *slp); #endif /* _KERNEL */ #endif |