1 /* $NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $ */
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
38 * Copyright 2000 Wasabi Systems, Inc.
39 * All rights reserved.
41 * Written by Frank van der Linden for Wasabi Systems, Inc.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed for the NetBSD Project by
54 * Wasabi Systems, Inc.
55 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
56 * or promote products derived from this software without specific prior
59 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
61 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
62 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
63 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69 * POSSIBILITY OF SUCH DAMAGE.
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $");
75 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/kernel.h>
80 #include <sys/mount.h>
81 #include <sys/vnode.h>
82 #include <sys/namei.h>
84 #include <sys/socket.h>
86 #include <sys/filedesc.h>
88 #include <sys/dirent.h>
90 #include <sys/kauth.h>
91 #include <sys/atomic.h>
93 #include <uvm/uvm_extern.h>
95 #include <nfs/rpcv2.h>
96 #include <nfs/nfsproto.h>
97 #include <nfs/nfsnode.h>
99 #include <nfs/xdr_subs.h>
100 #include <nfs/nfsm_subs.h>
101 #include <nfs/nfsmount.h>
102 #include <nfs/nfsrtt.h>
103 #include <nfs/nfs_var.h>
105 #include <miscfs/specfs/specdev.h>
107 #include <netinet/in.h>
110 * Set up nameidata for a lookup() call and do it.
112 * If pubflag is set, this call is done for a lookup operation on the
113 * public filehandle. In that case we allow crossing mountpoints and
114 * absolute pathnames. However, the caller is expected to check that
115 * the lookup result is within the public fs, and deny access if
119 nfs_namei(struct nameidata
*ndp
, nfsrvfh_t
*nsfh
, uint32_t len
, struct nfssvc_sock
*slp
, struct mbuf
*nam
, struct mbuf
**mdp
, char **dposp
, struct vnode
**retdirp
, struct lwp
*l
, int kerbflag
, int pubflag
)
123 char *fromcp
, *tocp
, *cp
;
127 struct componentname
*cnp
= &ndp
->ni_cnd
;
131 if ((len
+ 1) > MAXPATHLEN
)
132 return (ENAMETOOLONG
);
135 cnp
->cn_pnbuf
= PNBUF_GET();
138 * Copy the name from the mbuf list to ndp->ni_pnbuf
139 * and set the various ndp fields appropriately.
142 tocp
= cnp
->cn_pnbuf
;
144 rem
= mtod(md
, char *) + md
->m_len
- fromcp
;
145 for (i
= 0; i
< len
; i
++) {
152 fromcp
= mtod(md
, void *);
155 if (*fromcp
== '\0' || (!pubflag
&& *fromcp
== '/')) {
165 len
= nfsm_rndup(len
)-len
;
169 else if ((error
= nfs_adv(mdp
, dposp
, len
, rem
)) != 0)
174 * Extract and set starting directory.
176 error
= nfsrv_fhtovp(nsfh
, false, &dp
, ndp
->ni_cnd
.cn_cred
, slp
,
177 nam
, &rdonly
, kerbflag
, pubflag
);
180 if (dp
->v_type
!= VDIR
) {
187 cnp
->cn_flags
|= RDONLY
;
193 * Oh joy. For WebNFS, handle those pesky '%' escapes,
194 * and the 'native path' indicator.
197 fromcp
= cnp
->cn_pnbuf
;
199 if ((unsigned char)*fromcp
>= WEBNFS_SPECCHAR_START
) {
200 switch ((unsigned char)*fromcp
) {
201 case WEBNFS_NATIVE_CHAR
:
203 * 'Native' path for us is the same
204 * as a path according to the NFS spec,
205 * just skip the escape char.
210 * More may be added in the future, range 0x80-0xff
220 * Translate the '%' escapes, URL-style.
222 while (*fromcp
!= '\0') {
223 if (*fromcp
== WEBNFS_ESC_CHAR
) {
224 if (fromcp
[1] != '\0' && fromcp
[2] != '\0') {
226 *tocp
++ = HEXSTRTOI(fromcp
);
239 PNBUF_PUT(cnp
->cn_pnbuf
);
243 ndp
->ni_pathlen
= (tocp
- cnp
->cn_pnbuf
) + 1;
244 ndp
->ni_segflg
= UIO_SYSSPACE
;
245 ndp
->ni_rootdir
= rootvnode
;
246 ndp
->ni_erootdir
= NULL
;
250 if (cnp
->cn_pnbuf
[0] == '/')
253 cnp
->cn_flags
|= NOCROSSMOUNT
;
256 neverfollow
= !pubflag
;
259 * And call lookup() to do the real work
261 error
= lookup_for_nfsd(ndp
, dp
, neverfollow
);
268 PNBUF_PUT(cnp
->cn_pnbuf
);
273 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
274 * - look up fsid in mount list (if not found ret error)
275 * - get vp and export rights by calling VFS_FHTOVP()
276 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
277 * - if not lockflag unlock it with VOP_UNLOCK()
280 nfsrv_fhtovp(nfsrvfh_t
*nsfh
, int lockflag
, struct vnode
**vpp
,
281 kauth_cred_t cred
, struct nfssvc_sock
*slp
, struct mbuf
*nam
, int *rdonlyp
,
282 int kerbflag
, int pubflag
)
285 kauth_cred_t credanon
;
287 struct sockaddr_in
*saddr
;
290 fhp
= NFSRVFH_FHANDLE(nsfh
);
291 *vpp
= (struct vnode
*)0;
293 if (nfs_ispublicfh(nsfh
)) {
294 if (!pubflag
|| !nfs_pub
.np_valid
)
296 fhp
= nfs_pub
.np_handle
;
299 error
= netexport_check(&fhp
->fh_fsid
, nam
, &mp
, &exflags
, &credanon
);
304 error
= VFS_FHTOVP(mp
, &fhp
->fh_fid
, vpp
);
308 if (!(exflags
& (MNT_EXNORESPORT
|MNT_EXPUBLIC
))) {
309 saddr
= mtod(nam
, struct sockaddr_in
*);
310 if ((saddr
->sin_family
== AF_INET
) &&
311 ntohs(saddr
->sin_port
) >= IPPORT_RESERVED
) {
313 return (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
315 if ((saddr
->sin_family
== AF_INET6
) &&
316 ntohs(saddr
->sin_port
) >= IPV6PORT_RESERVED
) {
318 return (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
322 * Check/setup credentials.
324 if (exflags
& MNT_EXKERB
) {
327 return (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
329 } else if (kerbflag
) {
331 return (NFSERR_AUTHERR
| AUTH_TOOWEAK
);
332 } else if (kauth_cred_geteuid(cred
) == 0 || /* NFS maproot, see below */
333 (exflags
& MNT_EXPORTANON
)) {
335 * This is used by the NFS maproot option. While we can change
336 * the secmodel on our own host, we can't change it on the
337 * clients. As means of least surprise, we're doing the
338 * traditional thing here.
339 * Should look into adding a "mapprivileged" or similar where
340 * the users can be explicitly specified...
341 * [elad, yamt 2008-03-05]
343 kauth_cred_clone(credanon
, cred
);
345 if (exflags
& MNT_EXRDONLY
)
355 * WebNFS: check if a filehandle is a public filehandle. For v3, this
356 * means a length of 0, for v2 it means all zeroes.
359 nfs_ispublicfh(const nfsrvfh_t
*nsfh
)
361 const char *cp
= (const void *)(NFSRVFH_DATA(nsfh
));
364 if (NFSRVFH_SIZE(nsfh
) == 0) {
367 if (NFSRVFH_SIZE(nsfh
) != NFSX_V2FH
) {
370 for (i
= 0; i
< NFSX_V2FH
; i
++)
377 nfsrv_composefh(struct vnode
*vp
, nfsrvfh_t
*nsfh
, bool v3
)
382 fhsize
= NFSD_MAXFHSIZE
;
383 error
= vfs_composefh(vp
, (void *)NFSRVFH_DATA(nsfh
), &fhsize
);
384 if (NFSX_FHTOOBIG_P(fhsize
, v3
)) {
390 if (!v3
&& fhsize
< NFSX_V2FH
) {
391 memset((char *)NFSRVFH_DATA(nsfh
) + fhsize
, 0,
395 if ((fhsize
% NFSX_UNSIGNED
) != 0) {
398 nsfh
->nsfh_size
= fhsize
;
403 nfsrv_comparefh(const nfsrvfh_t
*fh1
, const nfsrvfh_t
*fh2
)
406 if (NFSRVFH_SIZE(fh1
) != NFSRVFH_SIZE(fh2
)) {
407 return NFSRVFH_SIZE(fh2
) - NFSRVFH_SIZE(fh1
);
409 return memcmp(NFSRVFH_DATA(fh1
), NFSRVFH_DATA(fh2
), NFSRVFH_SIZE(fh1
));
413 nfsrv_copyfh(nfsrvfh_t
*fh1
, const nfsrvfh_t
*fh2
)
417 fh1
->nsfh_size
= size
= NFSRVFH_SIZE(fh2
);
418 memcpy(NFSRVFH_DATA(fh1
), NFSRVFH_DATA(fh2
), size
);