1/* 2 * Copyright (c) 2006-2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29/* 30 * miscellaneous support functions for NFSv4 31 */ 32#include <sys/param.h> 33#include <sys/proc.h> 34#include <sys/kauth.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/mount_internal.h> 38#include <sys/vnode_internal.h> 39#include <sys/kpi_mbuf.h> 40#include <sys/socket.h> 41#include <sys/stat.h> 42#include <sys/malloc.h> 43#include <sys/syscall.h> 44#include <sys/ubc_internal.h> 45#include <sys/fcntl.h> 46#include <sys/quota.h> 47#include <sys/domain.h> 48#include <libkern/OSAtomic.h> 49#include <kern/thread_call.h> 50 51#include <sys/vm.h> 52#include <sys/vmparam.h> 53 54#include <sys/time.h> 55#include <kern/clock.h> 56 57#include <nfs/rpcv2.h> 58#include <nfs/nfsproto.h> 59#include <nfs/nfs.h> 60#include <nfs/nfsnode.h> 61#include <nfs/xdr_subs.h> 62#include <nfs/nfsm_subs.h> 63#include <nfs/nfs_gss.h> 64#include <nfs/nfsmount.h> 65#include <nfs/nfs_lock.h> 66 67#include <miscfs/specfs/specdev.h> 68 69#include <netinet/in.h> 70#include <net/kpi_interface.h> 71 72/* 73 * NFS_MAX_WHO is the maximum length of a string representation used 74 * in as an ace who, owner, or group. There is no explicit limit in the 75 * protocol, however the kauth routines have a limit of MAPATHLEN for 76 * strings including the trailing null character, so we impose that 77 * limit. This should be changed if kauth routines change. 78 * 79 * We also want some reasonable maximum, as 32 bits worth of string length 80 * is liable to cause problems. At the very least this limit must guarantee 81 * that any express that contains the 32 bit length from off the wire used in 82 * allocations does not overflow. 83 */ 84#define NFS_MAX_WHO MAXPATHLEN 85 86/* 87 * Create the unique client ID to use for this mount. 88 * 89 * Format: unique ID + en0_address + server_address + mntfromname + mntonname 90 * 91 * We could possibly use one client ID for all mounts of the same server; 92 * however, that would complicate some aspects of state management. 93 * 94 * Each mount socket connection sends a SETCLIENTID. If the ID is the same but 95 * the verifier (mounttime) changes, then all previous (mounts') state gets dropped. 96 * 97 * State is typically managed per-mount and in order to keep it that way 98 * each mount needs to use a separate client ID. However, we also need to 99 * make sure that each mount uses the same client ID each time. 100 * 101 * In an attempt to differentiate mounts we include the mntfromname and mntonname 102 * strings to the client ID (as long as they fit). We also make sure that the 103 * value does not conflict with any existing values in use (changing the unique ID). 104 * 105 * Note that info such as the server's address may change over the lifetime of the 106 * mount. But the client ID will not be updated because we don't want it changing 107 * simply because we switched to a different server address. 108 */ 109int 110nfs4_init_clientid(struct nfsmount *nmp) 111{ 112 struct nfs_client_id *ncip, *ncip2; 113 struct sockaddr *saddr; 114 int error, len, len2, cmp; 115 struct vfsstatfs *vsfs; 116 117 static uint8_t en0addr[6]; 118 static uint8_t en0addr_set = 0; 119 120 lck_mtx_lock(nfs_global_mutex); 121 if (!en0addr_set) { 122 ifnet_t interface = NULL; 123 error = ifnet_find_by_name("en0", &interface); 124 if (!error) 125 error = ifnet_lladdr_copy_bytes(interface, en0addr, sizeof(en0addr)); 126 if (error) 127 printf("nfs4_init_clientid: error getting en0 address, %d\n", error); 128 if (!error) 129 en0addr_set = 1; 130 if (interface) 131 ifnet_release(interface); 132 } 133 lck_mtx_unlock(nfs_global_mutex); 134 135 MALLOC(ncip, struct nfs_client_id *, sizeof(struct nfs_client_id), M_TEMP, M_WAITOK); 136 if (!ncip) 137 return (ENOMEM); 138 139 vsfs = vfs_statfs(nmp->nm_mountp); 140 saddr = nmp->nm_saddr; 141 ncip->nci_idlen = sizeof(uint32_t) + sizeof(en0addr) + saddr->sa_len + 142 strlen(vsfs->f_mntfromname) + 1 + strlen(vsfs->f_mntonname) + 1; 143 if (ncip->nci_idlen > NFS4_OPAQUE_LIMIT) 144 ncip->nci_idlen = NFS4_OPAQUE_LIMIT; 145 MALLOC(ncip->nci_id, char *, ncip->nci_idlen, M_TEMP, M_WAITOK); 146 if (!ncip->nci_id) { 147 FREE(ncip, M_TEMP); 148 return (ENOMEM); 149 } 150 151 *(uint32_t*)ncip->nci_id = 0; 152 len = sizeof(uint32_t); 153 len2 = min(sizeof(en0addr), ncip->nci_idlen-len); 154 bcopy(en0addr, &ncip->nci_id[len], len2); 155 len += sizeof(en0addr); 156 len2 = min(saddr->sa_len, ncip->nci_idlen-len); 157 bcopy(saddr, &ncip->nci_id[len], len2); 158 len += len2; 159 if (len < ncip->nci_idlen) { 160 len2 = strlcpy(&ncip->nci_id[len], vsfs->f_mntfromname, ncip->nci_idlen-len); 161 if (len2 < (ncip->nci_idlen - len)) 162 len += len2 + 1; 163 else 164 len = ncip->nci_idlen; 165 } 166 if (len < ncip->nci_idlen) { 167 len2 = strlcpy(&ncip->nci_id[len], vsfs->f_mntonname, ncip->nci_idlen-len); 168 if (len2 < (ncip->nci_idlen - len)) 169 len += len2 + 1; 170 else 171 len = ncip->nci_idlen; 172 } 173 174 /* make sure the ID is unique, and add it to the sorted list */ 175 lck_mtx_lock(nfs_global_mutex); 176 TAILQ_FOREACH(ncip2, &nfsclientids, nci_link) { 177 if (ncip->nci_idlen > ncip2->nci_idlen) 178 continue; 179 if (ncip->nci_idlen < ncip2->nci_idlen) 180 break; 181 cmp = bcmp(ncip->nci_id + sizeof(uint32_t), 182 ncip2->nci_id + sizeof(uint32_t), 183 ncip->nci_idlen - sizeof(uint32_t)); 184 if (cmp > 0) 185 continue; 186 if (cmp < 0) 187 break; 188 if (*(uint32_t*)ncip->nci_id > *(uint32_t*)ncip2->nci_id) 189 continue; 190 if (*(uint32_t*)ncip->nci_id < *(uint32_t*)ncip2->nci_id) 191 break; 192 *(uint32_t*)ncip->nci_id += 1; 193 } 194 if (*(uint32_t*)ncip->nci_id) 195 printf("nfs client ID collision (%d) for %s on %s\n", *(uint32_t*)ncip->nci_id, 196 vsfs->f_mntfromname, vsfs->f_mntonname); 197 if (ncip2) 198 TAILQ_INSERT_BEFORE(ncip2, ncip, nci_link); 199 else 200 TAILQ_INSERT_TAIL(&nfsclientids, ncip, nci_link); 201 nmp->nm_longid = ncip; 202 lck_mtx_unlock(nfs_global_mutex); 203 204 return (0); 205} 206 207/* 208 * NFSv4 SETCLIENTID 209 */ 210int 211nfs4_setclientid(struct nfsmount *nmp) 212{ 213 uint64_t verifier, xid; 214 int error = 0, status, numops; 215 uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; 216 thread_t thd; 217 kauth_cred_t cred; 218 struct nfsm_chain nmreq, nmrep; 219 struct sockaddr_storage ss; 220 void *sinaddr = NULL; 221 char raddr[MAX_IPv6_STR_LEN]; 222 char uaddr[MAX_IPv6_STR_LEN+16]; 223 int ualen = 0; 224 in_port_t port; 225 226 thd = current_thread(); 227 cred = IS_VALID_CRED(nmp->nm_mcred) ? nmp->nm_mcred : vfs_context_ucred(vfs_context_kernel()); 228 kauth_cred_ref(cred); 229 230 nfsm_chain_null(&nmreq); 231 nfsm_chain_null(&nmrep); 232 233 if (!nmp->nm_longid) 234 error = nfs4_init_clientid(nmp); 235 236 // SETCLIENTID 237 numops = 1; 238 nfsm_chain_build_alloc_init(error, &nmreq, 14 * NFSX_UNSIGNED + nmp->nm_longid->nci_idlen); 239 nfsm_chain_add_compound_header(error, &nmreq, "setclid", numops); 240 numops--; 241 nfsm_chain_add_32(error, &nmreq, NFS_OP_SETCLIENTID); 242 /* nfs_client_id4 client; */ 243 nfsm_chain_add_64(error, &nmreq, nmp->nm_mounttime); 244 nfsm_chain_add_32(error, &nmreq, nmp->nm_longid->nci_idlen); 245 nfsm_chain_add_opaque(error, &nmreq, nmp->nm_longid->nci_id, nmp->nm_longid->nci_idlen); 246 nfsmout_if(error); 247 /* cb_client4 callback; */ 248 if (!NMFLAG(nmp, NOCALLBACK) && nmp->nm_cbid && nfs4_cb_port && 249 !sock_getsockname(nmp->nm_nso->nso_so, (struct sockaddr*)&ss, sizeof(ss))) { 250 if (ss.ss_family == AF_INET) { 251 sinaddr = &((struct sockaddr_in*)&ss)->sin_addr; 252 port = nfs4_cb_port; 253 } else if (ss.ss_family == AF_INET6) { 254 sinaddr = &((struct sockaddr_in6*)&ss)->sin6_addr; 255 port = nfs4_cb_port6; 256 } 257 if (sinaddr && port && (inet_ntop(ss.ss_family, sinaddr, raddr, sizeof(raddr)) == raddr)) { 258 /* assemble r_addr = universal address (nmp->nm_nso->nso_so source IP addr + port) */ 259 ualen = snprintf(uaddr, sizeof(uaddr), "%s.%d.%d", raddr, 260 ((port >> 8) & 0xff), 261 (port & 0xff)); 262 /* make sure it fit, give up if it didn't */ 263 if (ualen >= (int)sizeof(uaddr)) 264 ualen = 0; 265 } 266 } 267 if (ualen > 0) { 268 /* add callback info */ 269 nfsm_chain_add_32(error, &nmreq, NFS4_CALLBACK_PROG); /* callback program */ 270 if (ss.ss_family == AF_INET) 271 nfsm_chain_add_string(error, &nmreq, "tcp", 3); /* callback r_netid */ 272 else if (ss.ss_family == AF_INET6) 273 nfsm_chain_add_string(error, &nmreq, "tcp6", 4); /* callback r_netid */ 274 nfsm_chain_add_string(error, &nmreq, uaddr, ualen); /* callback r_addr */ 275 nfsm_chain_add_32(error, &nmreq, nmp->nm_cbid); /* callback_ident */ 276 } else { 277 /* don't provide valid callback info */ 278 nfsm_chain_add_32(error, &nmreq, 0); /* callback program */ 279 nfsm_chain_add_string(error, &nmreq, "", 0); /* callback r_netid */ 280 nfsm_chain_add_string(error, &nmreq, "", 0); /* callback r_addr */ 281 nfsm_chain_add_32(error, &nmreq, 0); /* callback_ident */ 282 } 283 nfsm_chain_build_done(error, &nmreq); 284 nfsm_assert(error, (numops == 0), EPROTO); 285 nfsmout_if(error); 286 error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, thd, cred, NULL, R_SETUP, &nmrep, &xid, &status); 287 nfsm_chain_skip_tag(error, &nmrep); 288 nfsm_chain_get_32(error, &nmrep, numops); 289 if (!error && (numops != 1) && status) 290 error = status; 291 nfsm_chain_op_check(error, &nmrep, NFS_OP_SETCLIENTID); 292 if (error == NFSERR_CLID_INUSE) 293 printf("nfs4_setclientid: client ID in use?\n"); 294 nfsmout_if(error); 295 nfsm_chain_get_64(error, &nmrep, nmp->nm_clientid); 296 nfsm_chain_get_64(error, &nmrep, verifier); 297 nfsm_chain_cleanup(&nmreq); 298 nfsm_chain_cleanup(&nmrep); 299 300 // SETCLIENTID_CONFIRM 301 numops = 1; 302 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED); 303 nfsm_chain_add_compound_header(error, &nmreq, "setclid_conf", numops); 304 numops--; 305 nfsm_chain_add_32(error, &nmreq, NFS_OP_SETCLIENTID_CONFIRM); 306 nfsm_chain_add_64(error, &nmreq, nmp->nm_clientid); 307 nfsm_chain_add_64(error, &nmreq, verifier); 308 nfsm_chain_build_done(error, &nmreq); 309 nfsm_assert(error, (numops == 0), EPROTO); 310 nfsmout_if(error); 311 error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, thd, cred, NULL, R_SETUP, &nmrep, &xid, &status); 312 nfsm_chain_skip_tag(error, &nmrep); 313 nfsm_chain_get_32(error, &nmrep, numops); 314 nfsm_chain_op_check(error, &nmrep, NFS_OP_SETCLIENTID_CONFIRM); 315 if (error) 316 printf("nfs4_setclientid: confirm error %d\n", error); 317 lck_mtx_lock(&nmp->nm_lock); 318 if (!error) 319 nmp->nm_state |= NFSSTA_CLIENTID; 320 lck_mtx_unlock(&nmp->nm_lock); 321 322 nfsmout_if(error || !nmp->nm_dnp); 323 324 /* take the opportunity to refresh fs attributes too */ 325 // PUTFH, GETATTR(FS) 326 numops = 2; 327 nfsm_chain_build_alloc_init(error, &nmreq, 23 * NFSX_UNSIGNED); 328 nfsm_chain_add_compound_header(error, &nmreq, "setclid_attr", numops); 329 numops--; 330 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH); 331 nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, nmp->nm_dnp->n_fhp, nmp->nm_dnp->n_fhsize); 332 numops--; 333 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR); 334 NFS_CLEAR_ATTRIBUTES(bitmap); 335 NFS4_PER_FS_ATTRIBUTES(bitmap); 336 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN); 337 nfsm_chain_build_done(error, &nmreq); 338 nfsm_assert(error, (numops == 0), EPROTO); 339 nfsmout_if(error); 340 error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, thd, cred, NULL, R_SETUP, &nmrep, &xid, &status); 341 nfsm_chain_skip_tag(error, &nmrep); 342 nfsm_chain_get_32(error, &nmrep, numops); 343 lck_mtx_lock(&nmp->nm_lock); 344 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH); 345 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR); 346 if (!error) 347 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, NULL, NULL, NULL, NULL); 348 lck_mtx_unlock(&nmp->nm_lock); 349 if (error) /* ignore any error from the getattr */ 350 error = 0; 351nfsmout: 352 nfsm_chain_cleanup(&nmreq); 353 nfsm_chain_cleanup(&nmrep); 354 kauth_cred_unref(&cred); 355 if (error) 356 printf("nfs4_setclientid failed, %d\n", error); 357 return (error); 358} 359 360/* 361 * renew/check lease state on server 362 */ 363int 364nfs4_renew(struct nfsmount *nmp, int rpcflag) 365{ 366 int error = 0, status, numops; 367 u_int64_t xid; 368 struct nfsm_chain nmreq, nmrep; 369 kauth_cred_t cred; 370 371 cred = IS_VALID_CRED(nmp->nm_mcred) ? nmp->nm_mcred : vfs_context_ucred(vfs_context_kernel()); 372 kauth_cred_ref(cred); 373 374 nfsm_chain_null(&nmreq); 375 nfsm_chain_null(&nmrep); 376 377 // RENEW 378 numops = 1; 379 nfsm_chain_build_alloc_init(error, &nmreq, 8 * NFSX_UNSIGNED); 380 nfsm_chain_add_compound_header(error, &nmreq, "renew", numops); 381 numops--; 382 nfsm_chain_add_32(error, &nmreq, NFS_OP_RENEW); 383 nfsm_chain_add_64(error, &nmreq, nmp->nm_clientid); 384 nfsm_chain_build_done(error, &nmreq); 385 nfsm_assert(error, (numops == 0), EPROTO); 386 nfsmout_if(error); 387 error = nfs_request2(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, 388 current_thread(), cred, NULL, rpcflag, &nmrep, &xid, &status); 389 nfsm_chain_skip_tag(error, &nmrep); 390 nfsm_chain_get_32(error, &nmrep, numops); 391 nfsm_chain_op_check(error, &nmrep, NFS_OP_RENEW); 392nfsmout: 393 nfsm_chain_cleanup(&nmreq); 394 nfsm_chain_cleanup(&nmrep); 395 kauth_cred_unref(&cred); 396 return (error); 397} 398 399 400/* 401 * periodic timer to renew lease state on server 402 */ 403void 404nfs4_renew_timer(void *param0, __unused void *param1) 405{ 406 struct nfsmount *nmp = param0; 407 u_int64_t clientid; 408 int error = 0, interval; 409 410 lck_mtx_lock(&nmp->nm_lock); 411 clientid = nmp->nm_clientid; 412 if ((nmp->nm_state & NFSSTA_RECOVER) || !(nmp->nm_sockflags & NMSOCK_READY)) { 413 lck_mtx_unlock(&nmp->nm_lock); 414 goto out; 415 } 416 lck_mtx_unlock(&nmp->nm_lock); 417 418 error = nfs4_renew(nmp, R_RECOVER); 419out: 420 if (error == ETIMEDOUT) 421 nfs_need_reconnect(nmp); 422 else if (error) 423 printf("nfs4_renew_timer: error %d\n", error); 424 lck_mtx_lock(&nmp->nm_lock); 425 if (error && (error != ETIMEDOUT) && 426 (nmp->nm_clientid == clientid) && !(nmp->nm_state & NFSSTA_RECOVER)) { 427 printf("nfs4_renew_timer: error %d, initiating recovery\n", error); 428 nfs_need_recover(nmp, error); 429 } 430 431 interval = nmp->nm_fsattr.nfsa_lease / (error ? 4 : 2); 432 if ((interval < 1) || (nmp->nm_state & NFSSTA_RECOVER)) 433 interval = 1; 434 lck_mtx_unlock(&nmp->nm_lock); 435 nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000); 436} 437 438/* 439 * get the list of supported security flavors 440 * 441 * How we get them depends on what args we are given: 442 * 443 * FH? Name? Action 444 * ----- ----- ------ 445 * YES YES Use the fh and name provided 446 * YES NO 4.1-only just use the fh provided 447 * NO YES Use the node's (or root) fh and the name provided 448 * NO NO Use the node's parent and the node's name (4.1 will just use node's fh) 449 */ 450int 451nfs4_secinfo_rpc(struct nfsmount *nmp, struct nfsreq_secinfo_args *siap, kauth_cred_t cred, uint32_t *sec, int *seccountp) 452{ 453 int error = 0, status, nfsvers, numops, namelen, fhsize; 454 vnode_t dvp = NULLVP; 455 nfsnode_t np, dnp; 456 u_char *fhp; 457 const char *vname = NULL, *name; 458 uint64_t xid; 459 struct nfsm_chain nmreq, nmrep; 460 461 *seccountp = 0; 462 if (nfs_mount_gone(nmp)) 463 return (ENXIO); 464 nfsvers = nmp->nm_vers; 465 np = siap->rsia_np; 466 467 nfsm_chain_null(&nmreq); 468 nfsm_chain_null(&nmrep); 469 470 fhp = siap->rsia_fh; 471 fhsize = fhp ? siap->rsia_fhsize : 0; 472 name = siap->rsia_name; 473 namelen = name ? siap->rsia_namelen : 0; 474 if (name && !namelen) 475 namelen = strlen(name); 476 if (!fhp && name) { 477 if (!np) /* use PUTROOTFH */ 478 goto gotargs; 479 fhp = np->n_fhp; 480 fhsize = np->n_fhsize; 481 } 482 if (fhp && name) 483 goto gotargs; 484 485 if (!np) 486 return (EIO); 487 nfs_node_lock_force(np); 488 if ((vnode_vtype(NFSTOV(np)) != VDIR) && np->n_sillyrename) { 489 /* 490 * The node's been sillyrenamed, so we need to use 491 * the sillyrename directory/name to do the open. 492 */ 493 struct nfs_sillyrename *nsp = np->n_sillyrename; 494 dnp = nsp->nsr_dnp; 495 dvp = NFSTOV(dnp); 496 if ((error = vnode_get(dvp))) { 497 nfs_node_unlock(np); 498 goto nfsmout; 499 } 500 fhp = dnp->n_fhp; 501 fhsize = dnp->n_fhsize; 502 name = nsp->nsr_name; 503 namelen = nsp->nsr_namlen; 504 } else { 505 /* 506 * [sigh] We can't trust VFS to get the parent right for named 507 * attribute nodes. (It likes to reparent the nodes after we've 508 * created them.) Luckily we can probably get the right parent 509 * from the n_parent we have stashed away. 510 */ 511 if ((np->n_vattr.nva_flags & NFS_FFLAG_IS_ATTR) && 512 (((dvp = np->n_parent)) && (error = vnode_get(dvp)))) 513 dvp = NULL; 514 if (!dvp) 515 dvp = vnode_getparent(NFSTOV(np)); 516 vname = vnode_getname(NFSTOV(np)); 517 if (!dvp || !vname) { 518 if (!error) 519 error = EIO; 520 nfs_node_unlock(np); 521 goto nfsmout; 522 } 523 dnp = VTONFS(dvp); 524 fhp = dnp->n_fhp; 525 fhsize = dnp->n_fhsize; 526 name = vname; 527 namelen = strnlen(vname, MAXPATHLEN); 528 } 529 nfs_node_unlock(np); 530 531gotargs: 532 // PUT(ROOT)FH + SECINFO 533 numops = 2; 534 nfsm_chain_build_alloc_init(error, &nmreq, 535 4 * NFSX_UNSIGNED + NFSX_FH(nfsvers) + nfsm_rndup(namelen)); 536 nfsm_chain_add_compound_header(error, &nmreq, "secinfo", numops); 537 numops--; 538 if (fhp) { 539 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH); 540 nfsm_chain_add_fh(error, &nmreq, nfsvers, fhp, fhsize); 541 } else { 542 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH); 543 } 544 numops--; 545 nfsm_chain_add_32(error, &nmreq, NFS_OP_SECINFO); 546 nfsm_chain_add_name(error, &nmreq, name, namelen, nmp); 547 nfsm_chain_build_done(error, &nmreq); 548 nfsm_assert(error, (numops == 0), EPROTO); 549 nfsmout_if(error); 550 error = nfs_request2(np, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, 551 current_thread(), cred, NULL, 0, &nmrep, &xid, &status); 552 nfsm_chain_skip_tag(error, &nmrep); 553 nfsm_chain_get_32(error, &nmrep, numops); 554 nfsm_chain_op_check(error, &nmrep, fhp ? NFS_OP_PUTFH : NFS_OP_PUTROOTFH); 555 nfsm_chain_op_check(error, &nmrep, NFS_OP_SECINFO); 556 nfsmout_if(error); 557 error = nfsm_chain_get_secinfo(&nmrep, sec, seccountp); 558nfsmout: 559 nfsm_chain_cleanup(&nmreq); 560 nfsm_chain_cleanup(&nmrep); 561 if (vname) 562 vnode_putname(vname); 563 if (dvp != NULLVP) 564 vnode_put(dvp); 565 return (error); 566} 567 568/* 569 * Parse an NFSv4 SECINFO array to an array of pseudo flavors. 570 * (Note: also works for MOUNTv3 security arrays.) 571 */ 572int 573nfsm_chain_get_secinfo(struct nfsm_chain *nmc, uint32_t *sec, int *seccountp) 574{ 575 int error = 0, secmax, seccount, srvcount; 576 uint32_t flavor, val; 577 u_char oid[12]; 578 579 seccount = srvcount = 0; 580 secmax = *seccountp; 581 *seccountp = 0; 582 583 nfsm_chain_get_32(error, nmc, srvcount); 584 while (!error && (srvcount > 0) && (seccount < secmax)) { 585 nfsm_chain_get_32(error, nmc, flavor); 586 nfsmout_if(error); 587 switch (flavor) { 588 case RPCAUTH_NONE: 589 case RPCAUTH_SYS: 590 case RPCAUTH_KRB5: 591 case RPCAUTH_KRB5I: 592 case RPCAUTH_KRB5P: 593 sec[seccount++] = flavor; 594 break; 595 case RPCSEC_GSS: 596 /* we only recognize KRB5, KRB5I, KRB5P */ 597 nfsm_chain_get_32(error, nmc, val); /* OID length */ 598 nfsmout_if(error); 599 if (val != sizeof(krb5_mech)) { 600 nfsm_chain_adv(error, nmc, val); 601 nfsm_chain_adv(error, nmc, 2*NFSX_UNSIGNED); 602 break; 603 } 604 nfsm_chain_get_opaque(error, nmc, val, oid); /* OID bytes */ 605 nfsmout_if(error); 606 if (bcmp(oid, krb5_mech, sizeof(krb5_mech))) { 607 nfsm_chain_adv(error, nmc, 2*NFSX_UNSIGNED); 608 break; 609 } 610 nfsm_chain_get_32(error, nmc, val); /* QOP */ 611 nfsm_chain_get_32(error, nmc, val); /* SERVICE */ 612 nfsmout_if(error); 613 switch (val) { 614 case RPCSEC_GSS_SVC_NONE: 615 sec[seccount++] = RPCAUTH_KRB5; 616 break; 617 case RPCSEC_GSS_SVC_INTEGRITY: 618 sec[seccount++] = RPCAUTH_KRB5I; 619 break; 620 case RPCSEC_GSS_SVC_PRIVACY: 621 sec[seccount++] = RPCAUTH_KRB5P; 622 break; 623 } 624 break; 625 } 626 srvcount--; 627 } 628nfsmout: 629 if (!error) 630 *seccountp = seccount; 631 return (error); 632} 633 634 635/* 636 * Fetch the FS_LOCATIONS attribute for the node found at directory/name. 637 */ 638int 639nfs4_get_fs_locations( 640 struct nfsmount *nmp, 641 nfsnode_t dnp, 642 u_char *fhp, 643 int fhsize, 644 const char *name, 645 vfs_context_t ctx, 646 struct nfs_fs_locations *nfslsp) 647{ 648 int error = 0, numops, status; 649 uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; 650 struct nfsreq rq, *req = &rq; 651 struct nfsreq_secinfo_args si; 652 struct nfsm_chain nmreq, nmrep; 653 uint64_t xid; 654 655 if (!fhp && dnp) { 656 fhp = dnp->n_fhp; 657 fhsize = dnp->n_fhsize; 658 } 659 if (!fhp) 660 return (EINVAL); 661 662 nfsm_chain_null(&nmreq); 663 nfsm_chain_null(&nmrep); 664 665 NFSREQ_SECINFO_SET(&si, NULL, fhp, fhsize, name, 0); 666 numops = 3; 667 nfsm_chain_build_alloc_init(error, &nmreq, 18 * NFSX_UNSIGNED); 668 nfsm_chain_add_compound_header(error, &nmreq, "fs_locations", numops); 669 numops--; 670 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH); 671 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, fhp, fhsize); 672 numops--; 673 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUP); 674 nfsm_chain_add_name(error, &nmreq, name, strlen(name), nmp); 675 numops--; 676 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR); 677 NFS_CLEAR_ATTRIBUTES(bitmap); 678 NFS_BITMAP_SET(bitmap, NFS_FATTR_FS_LOCATIONS); 679 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN); 680 nfsm_chain_build_done(error, &nmreq); 681 nfsm_assert(error, (numops == 0), EPROTO); 682 nfsmout_if(error); 683 error = nfs_request_async(dnp, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, 684 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req); 685 if (!error) 686 error = nfs_request_async_finish(req, &nmrep, &xid, &status); 687 nfsm_chain_skip_tag(error, &nmrep); 688 nfsm_chain_get_32(error, &nmrep, numops); 689 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH); 690 nfsm_chain_op_check(error, &nmrep, NFS_OP_LOOKUP); 691 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR); 692 nfsmout_if(error); 693 error = nfs4_parsefattr(&nmrep, NULL, NULL, NULL, NULL, nfslsp); 694nfsmout: 695 nfsm_chain_cleanup(&nmrep); 696 nfsm_chain_cleanup(&nmreq); 697 return (error); 698} 699 700/* 701 * Referral trigger nodes may not have many attributes provided by the 702 * server, so put some default values in place. 703 */ 704void 705nfs4_default_attrs_for_referral_trigger( 706 nfsnode_t dnp, 707 char *name, 708 int namelen, 709 struct nfs_vattr *nvap, 710 fhandle_t *fhp) 711{ 712 struct timeval now; 713 microtime(&now); 714 int len; 715 716 nvap->nva_flags = NFS_FFLAG_TRIGGER | NFS_FFLAG_TRIGGER_REFERRAL; 717 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_TYPE)) { 718 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_TYPE); 719 nvap->nva_type = VDIR; 720 } 721 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_FSID)) { 722 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_FSID); 723 nvap->nva_fsid.major = 0; 724 nvap->nva_fsid.minor = 0; 725 } 726 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_OWNER) && dnp) { 727 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_OWNER); 728 nvap->nva_uid = dnp->n_vattr.nva_uid; 729 nvap->nva_uuuid = dnp->n_vattr.nva_uuuid; 730 } 731 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_OWNER_GROUP) && dnp) { 732 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_OWNER_GROUP); 733 nvap->nva_gid = dnp->n_vattr.nva_gid; 734 nvap->nva_guuid = dnp->n_vattr.nva_guuid; 735 } 736 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_MODE)) { 737 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_MODE); 738 nvap->nva_mode = 0777; 739 } 740 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_SIZE)) { 741 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_SIZE); 742 nvap->nva_size = 0; 743 } 744 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_SPACE_USED)) { 745 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_SPACE_USED); 746 nvap->nva_bytes = 0; 747 } 748 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_NUMLINKS)) { 749 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_NUMLINKS); 750 nvap->nva_nlink = 2; 751 } 752 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_TIME_ACCESS)) { 753 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_TIME_ACCESS); 754 nvap->nva_timesec[NFSTIME_ACCESS] = now.tv_sec; 755 nvap->nva_timensec[NFSTIME_ACCESS] = now.tv_usec * 1000; 756 } 757 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_TIME_MODIFY)) { 758 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_TIME_MODIFY); 759 nvap->nva_timesec[NFSTIME_MODIFY] = now.tv_sec; 760 nvap->nva_timensec[NFSTIME_MODIFY] = now.tv_usec * 1000; 761 } 762 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_TIME_METADATA)) { 763 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_TIME_METADATA); 764 nvap->nva_timesec[NFSTIME_CHANGE] = now.tv_sec; 765 nvap->nva_timensec[NFSTIME_CHANGE] = now.tv_usec * 1000; 766 } 767 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_FILEID)) { 768 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_FILEID); 769 nvap->nva_fileid = 42; 770 } 771 if (!NFS_BITMAP_ISSET(nvap->nva_bitmap, NFS_FATTR_FILEHANDLE) && dnp && name && fhp) { 772 /* Build a fake filehandle made up of parent node pointer and name */ 773 NFS_BITMAP_SET(nvap->nva_bitmap, NFS_FATTR_FILEHANDLE); 774 bcopy(&dnp, &fhp->fh_data[0], sizeof(dnp)); 775 len = sizeof(fhp->fh_data) - sizeof(dnp); 776 bcopy(name, &fhp->fh_data[0] + sizeof(dnp), MIN(len, namelen)); 777 fhp->fh_len = sizeof(dnp) + namelen; 778 if (fhp->fh_len > (int)sizeof(fhp->fh_data)) 779 fhp->fh_len = sizeof(fhp->fh_data); 780 } 781} 782 783/* 784 * Set NFS bitmap according to what's set in vnode_attr (and supported by the server). 785 */ 786void 787nfs_vattr_set_bitmap(struct nfsmount *nmp, uint32_t *bitmap, struct vnode_attr *vap) 788{ 789 int i; 790 791 NFS_CLEAR_ATTRIBUTES(bitmap); 792 if (VATTR_IS_ACTIVE(vap, va_data_size)) 793 NFS_BITMAP_SET(bitmap, NFS_FATTR_SIZE); 794 if (VATTR_IS_ACTIVE(vap, va_acl) && (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL)) 795 NFS_BITMAP_SET(bitmap, NFS_FATTR_ACL); 796 if (VATTR_IS_ACTIVE(vap, va_flags)) { 797 NFS_BITMAP_SET(bitmap, NFS_FATTR_ARCHIVE); 798 NFS_BITMAP_SET(bitmap, NFS_FATTR_HIDDEN); 799 } 800 // NFS_BITMAP_SET(bitmap, NFS_FATTR_MIMETYPE) 801 if (VATTR_IS_ACTIVE(vap, va_mode) && !NMFLAG(nmp, ACLONLY)) 802 NFS_BITMAP_SET(bitmap, NFS_FATTR_MODE); 803 if (VATTR_IS_ACTIVE(vap, va_uid) || VATTR_IS_ACTIVE(vap, va_uuuid)) 804 NFS_BITMAP_SET(bitmap, NFS_FATTR_OWNER); 805 if (VATTR_IS_ACTIVE(vap, va_gid) || VATTR_IS_ACTIVE(vap, va_guuid)) 806 NFS_BITMAP_SET(bitmap, NFS_FATTR_OWNER_GROUP); 807 // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM) 808 if (vap->va_vaflags & VA_UTIMES_NULL) { 809 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_ACCESS_SET); 810 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_MODIFY_SET); 811 } else { 812 if (VATTR_IS_ACTIVE(vap, va_access_time)) 813 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_ACCESS_SET); 814 if (VATTR_IS_ACTIVE(vap, va_modify_time)) 815 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_MODIFY_SET); 816 } 817 if (VATTR_IS_ACTIVE(vap, va_backup_time)) 818 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_BACKUP); 819 if (VATTR_IS_ACTIVE(vap, va_create_time)) 820 NFS_BITMAP_SET(bitmap, NFS_FATTR_TIME_CREATE); 821 /* and limit to what is supported by server */ 822 for (i=0; i < NFS_ATTR_BITMAP_LEN; i++) 823 bitmap[i] &= nmp->nm_fsattr.nfsa_supp_attr[i]; 824} 825 826/* 827 * Convert between NFSv4 and VFS ACE types 828 */ 829uint32_t 830nfs4_ace_nfstype_to_vfstype(uint32_t nfsacetype, int *errorp) 831{ 832 switch (nfsacetype) { 833 case NFS_ACE_ACCESS_ALLOWED_ACE_TYPE: 834 return KAUTH_ACE_PERMIT; 835 case NFS_ACE_ACCESS_DENIED_ACE_TYPE: 836 return KAUTH_ACE_DENY; 837 case NFS_ACE_SYSTEM_AUDIT_ACE_TYPE: 838 return KAUTH_ACE_AUDIT; 839 case NFS_ACE_SYSTEM_ALARM_ACE_TYPE: 840 return KAUTH_ACE_ALARM; 841 } 842 *errorp = EBADRPC; 843 return 0; 844} 845 846uint32_t 847nfs4_ace_vfstype_to_nfstype(uint32_t vfstype, int *errorp) 848{ 849 switch (vfstype) { 850 case KAUTH_ACE_PERMIT: 851 return NFS_ACE_ACCESS_ALLOWED_ACE_TYPE; 852 case KAUTH_ACE_DENY: 853 return NFS_ACE_ACCESS_DENIED_ACE_TYPE; 854 case KAUTH_ACE_AUDIT: 855 return NFS_ACE_SYSTEM_AUDIT_ACE_TYPE; 856 case KAUTH_ACE_ALARM: 857 return NFS_ACE_SYSTEM_ALARM_ACE_TYPE; 858 } 859 *errorp = EINVAL; 860 return 0; 861} 862 863/* 864 * Convert between NFSv4 and VFS ACE flags 865 */ 866uint32_t 867nfs4_ace_nfsflags_to_vfsflags(uint32_t nfsflags) 868{ 869 uint32_t vfsflags = 0; 870 871 if (nfsflags & NFS_ACE_FILE_INHERIT_ACE) 872 vfsflags |= KAUTH_ACE_FILE_INHERIT; 873 if (nfsflags & NFS_ACE_DIRECTORY_INHERIT_ACE) 874 vfsflags |= KAUTH_ACE_DIRECTORY_INHERIT; 875 if (nfsflags & NFS_ACE_NO_PROPAGATE_INHERIT_ACE) 876 vfsflags |= KAUTH_ACE_LIMIT_INHERIT; 877 if (nfsflags & NFS_ACE_INHERIT_ONLY_ACE) 878 vfsflags |= KAUTH_ACE_ONLY_INHERIT; 879 if (nfsflags & NFS_ACE_SUCCESSFUL_ACCESS_ACE_FLAG) 880 vfsflags |= KAUTH_ACE_SUCCESS; 881 if (nfsflags & NFS_ACE_FAILED_ACCESS_ACE_FLAG) 882 vfsflags |= KAUTH_ACE_FAILURE; 883 if (nfsflags & NFS_ACE_INHERITED_ACE) 884 vfsflags |= KAUTH_ACE_INHERITED; 885 886 return (vfsflags); 887} 888 889uint32_t 890nfs4_ace_vfsflags_to_nfsflags(uint32_t vfsflags) 891{ 892 uint32_t nfsflags = 0; 893 894 if (vfsflags & KAUTH_ACE_FILE_INHERIT) 895 nfsflags |= NFS_ACE_FILE_INHERIT_ACE; 896 if (vfsflags & KAUTH_ACE_DIRECTORY_INHERIT) 897 nfsflags |= NFS_ACE_DIRECTORY_INHERIT_ACE; 898 if (vfsflags & KAUTH_ACE_LIMIT_INHERIT) 899 nfsflags |= NFS_ACE_NO_PROPAGATE_INHERIT_ACE; 900 if (vfsflags & KAUTH_ACE_ONLY_INHERIT) 901 nfsflags |= NFS_ACE_INHERIT_ONLY_ACE; 902 if (vfsflags & KAUTH_ACE_SUCCESS) 903 nfsflags |= NFS_ACE_SUCCESSFUL_ACCESS_ACE_FLAG; 904 if (vfsflags & KAUTH_ACE_FAILURE) 905 nfsflags |= NFS_ACE_FAILED_ACCESS_ACE_FLAG; 906 if (vfsflags & KAUTH_ACE_INHERITED) 907 nfsflags |= NFS_ACE_INHERITED_ACE; 908 909 return (nfsflags); 910} 911 912/* 913 * Convert between NFSv4 ACE access masks and VFS access rights 914 */ 915uint32_t 916nfs4_ace_nfsmask_to_vfsrights(uint32_t nfsmask) 917{ 918 uint32_t vfsrights = 0; 919 920 if (nfsmask & NFS_ACE_READ_DATA) 921 vfsrights |= KAUTH_VNODE_READ_DATA; 922 if (nfsmask & NFS_ACE_LIST_DIRECTORY) 923 vfsrights |= KAUTH_VNODE_LIST_DIRECTORY; 924 if (nfsmask & NFS_ACE_WRITE_DATA) 925 vfsrights |= KAUTH_VNODE_WRITE_DATA; 926 if (nfsmask & NFS_ACE_ADD_FILE) 927 vfsrights |= KAUTH_VNODE_ADD_FILE; 928 if (nfsmask & NFS_ACE_APPEND_DATA) 929 vfsrights |= KAUTH_VNODE_APPEND_DATA; 930 if (nfsmask & NFS_ACE_ADD_SUBDIRECTORY) 931 vfsrights |= KAUTH_VNODE_ADD_SUBDIRECTORY; 932 if (nfsmask & NFS_ACE_READ_NAMED_ATTRS) 933 vfsrights |= KAUTH_VNODE_READ_EXTATTRIBUTES; 934 if (nfsmask & NFS_ACE_WRITE_NAMED_ATTRS) 935 vfsrights |= KAUTH_VNODE_WRITE_EXTATTRIBUTES; 936 if (nfsmask & NFS_ACE_EXECUTE) 937 vfsrights |= KAUTH_VNODE_EXECUTE; 938 if (nfsmask & NFS_ACE_DELETE_CHILD) 939 vfsrights |= KAUTH_VNODE_DELETE_CHILD; 940 if (nfsmask & NFS_ACE_READ_ATTRIBUTES) 941 vfsrights |= KAUTH_VNODE_READ_ATTRIBUTES; 942 if (nfsmask & NFS_ACE_WRITE_ATTRIBUTES) 943 vfsrights |= KAUTH_VNODE_WRITE_ATTRIBUTES; 944 if (nfsmask & NFS_ACE_DELETE) 945 vfsrights |= KAUTH_VNODE_DELETE; 946 if (nfsmask & NFS_ACE_READ_ACL) 947 vfsrights |= KAUTH_VNODE_READ_SECURITY; 948 if (nfsmask & NFS_ACE_WRITE_ACL) 949 vfsrights |= KAUTH_VNODE_WRITE_SECURITY; 950 if (nfsmask & NFS_ACE_WRITE_OWNER) 951 vfsrights |= KAUTH_VNODE_CHANGE_OWNER; 952 if (nfsmask & NFS_ACE_SYNCHRONIZE) 953 vfsrights |= KAUTH_VNODE_SYNCHRONIZE; 954 if ((nfsmask & NFS_ACE_GENERIC_READ) == NFS_ACE_GENERIC_READ) 955 vfsrights |= KAUTH_ACE_GENERIC_READ; 956 if ((nfsmask & NFS_ACE_GENERIC_WRITE) == NFS_ACE_GENERIC_WRITE) 957 vfsrights |= KAUTH_ACE_GENERIC_WRITE; 958 if ((nfsmask & NFS_ACE_GENERIC_EXECUTE) == NFS_ACE_GENERIC_EXECUTE) 959 vfsrights |= KAUTH_ACE_GENERIC_EXECUTE; 960 961 return (vfsrights); 962} 963 964uint32_t 965nfs4_ace_vfsrights_to_nfsmask(uint32_t vfsrights) 966{ 967 uint32_t nfsmask = 0; 968 969 if (vfsrights & KAUTH_VNODE_READ_DATA) 970 nfsmask |= NFS_ACE_READ_DATA; 971 if (vfsrights & KAUTH_VNODE_LIST_DIRECTORY) 972 nfsmask |= NFS_ACE_LIST_DIRECTORY; 973 if (vfsrights & KAUTH_VNODE_WRITE_DATA) 974 nfsmask |= NFS_ACE_WRITE_DATA; 975 if (vfsrights & KAUTH_VNODE_ADD_FILE) 976 nfsmask |= NFS_ACE_ADD_FILE; 977 if (vfsrights & KAUTH_VNODE_APPEND_DATA) 978 nfsmask |= NFS_ACE_APPEND_DATA; 979 if (vfsrights & KAUTH_VNODE_ADD_SUBDIRECTORY) 980 nfsmask |= NFS_ACE_ADD_SUBDIRECTORY; 981 if (vfsrights & KAUTH_VNODE_READ_EXTATTRIBUTES) 982 nfsmask |= NFS_ACE_READ_NAMED_ATTRS; 983 if (vfsrights & KAUTH_VNODE_WRITE_EXTATTRIBUTES) 984 nfsmask |= NFS_ACE_WRITE_NAMED_ATTRS; 985 if (vfsrights & KAUTH_VNODE_EXECUTE) 986 nfsmask |= NFS_ACE_EXECUTE; 987 if (vfsrights & KAUTH_VNODE_DELETE_CHILD) 988 nfsmask |= NFS_ACE_DELETE_CHILD; 989 if (vfsrights & KAUTH_VNODE_READ_ATTRIBUTES) 990 nfsmask |= NFS_ACE_READ_ATTRIBUTES; 991 if (vfsrights & KAUTH_VNODE_WRITE_ATTRIBUTES) 992 nfsmask |= NFS_ACE_WRITE_ATTRIBUTES; 993 if (vfsrights & KAUTH_VNODE_DELETE) 994 nfsmask |= NFS_ACE_DELETE; 995 if (vfsrights & KAUTH_VNODE_READ_SECURITY) 996 nfsmask |= NFS_ACE_READ_ACL; 997 if (vfsrights & KAUTH_VNODE_WRITE_SECURITY) 998 nfsmask |= NFS_ACE_WRITE_ACL; 999 if (vfsrights & KAUTH_VNODE_CHANGE_OWNER) 1000 nfsmask |= NFS_ACE_WRITE_OWNER; 1001 if (vfsrights & KAUTH_VNODE_SYNCHRONIZE) 1002 nfsmask |= NFS_ACE_SYNCHRONIZE; 1003 if (vfsrights & KAUTH_ACE_GENERIC_READ) 1004 nfsmask |= NFS_ACE_GENERIC_READ; 1005 if (vfsrights & KAUTH_ACE_GENERIC_WRITE) 1006 nfsmask |= NFS_ACE_GENERIC_WRITE; 1007 if (vfsrights & KAUTH_ACE_GENERIC_EXECUTE) 1008 nfsmask |= NFS_ACE_GENERIC_EXECUTE; 1009 if (vfsrights & KAUTH_ACE_GENERIC_ALL) 1010 nfsmask |= (KAUTH_ACE_GENERIC_READ|KAUTH_ACE_GENERIC_WRITE|NFS_ACE_GENERIC_EXECUTE); 1011 1012 return (nfsmask); 1013} 1014 1015/* 1016 * Map an NFSv4 ID string to a VFS guid. 1017 * 1018 * Try to use the ID mapping service... but we may fallback to trying to do it ourselves. 1019 */ 1020int 1021nfs4_id2guid(/*const*/ char *id, guid_t *guidp, int isgroup) 1022{ 1023 int error1 = 0, error = 0, compare; 1024 guid_t guid1, guid2, *gp; 1025 ntsid_t sid; 1026 long num, unknown; 1027 const char *p, *at; 1028 1029 *guidp = kauth_null_guid; 1030 compare = ((nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE) && 1031 (nfs_idmap_ctrl & NFS_IDMAP_CTRL_COMPARE_RESULTS)); 1032 unknown = (nfs_idmap_ctrl & NFS_IDMAP_CTRL_UNKNOWN_IS_99) ? 99 : -2; 1033 1034 /* 1035 * First check if it is just a simple numeric ID string or a special "XXX@" name. 1036 * If it's a number, there's no need trying to ask the IDMAP service to map it. 1037 * If it's a special "XXX@" name, we want to make sure to treat it as a group. 1038 */ 1039 num = 1; 1040 at = NULL; 1041 p = id; 1042 while (*p) { 1043 if ((*p < '0') || (*p > '9')) 1044 num = 0; 1045 if (*p == '@') 1046 at = p; 1047 p++; 1048 } 1049 if (at && !at[1] && !isgroup) 1050 isgroup = 1; /* special "XXX@" names should always be treated as groups */ 1051 if (num) { 1052 /* must be numeric ID (or empty) */ 1053 num = *id ? strtol(id, NULL, 10) : unknown; 1054 gp = guidp; 1055 goto gotnumid; 1056 } 1057 1058 if (nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE) { 1059 /* 1060 * Ask the ID mapping service to map the ID string to a GUID. 1061 * 1062 * [sigh] this isn't a "pwnam/grnam" it's an NFS ID string! 1063 */ 1064 gp = compare ? &guid1 : guidp; 1065 if (isgroup) 1066 error = kauth_cred_grnam2guid(id, gp); 1067 else 1068 error = kauth_cred_pwnam2guid(id, gp); 1069 if (error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) 1070 printf("nfs4_id2guid: idmap failed for %s %s error %d\n", id, isgroup ? "G" : " ", error); 1071 if (!error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS)) 1072 printf("nfs4_id2guid: idmap for %s %s got guid " 1073 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x\n", 1074 id, isgroup ? "G" : " ", 1075 gp->g_guid[0], gp->g_guid[1], gp->g_guid[2], gp->g_guid[3], 1076 gp->g_guid[4], gp->g_guid[5], gp->g_guid[6], gp->g_guid[7], 1077 gp->g_guid[8], gp->g_guid[9], gp->g_guid[10], gp->g_guid[11], 1078 gp->g_guid[12], gp->g_guid[13], gp->g_guid[14], gp->g_guid[15]); 1079 error1 = error; 1080 } 1081 if (error || compare || !(nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE)) { 1082 /* 1083 * fallback path... see if we can come up with an answer ourselves. 1084 */ 1085 gp = compare ? &guid2 : guidp; 1086 1087 if (!(nfs_idmap_ctrl & NFS_IDMAP_CTRL_FALLBACK_NO_WELLKNOWN_IDS) && at && !at[1]) { 1088 /* must be a special ACE "who" ID */ 1089 bzero(&sid, sizeof(sid)); 1090 sid.sid_kind = 1; 1091 sid.sid_authcount = 1; 1092 if (!strcmp(id, "OWNER@")) { 1093 // S-1-3-0 1094 sid.sid_authority[5] = 3; 1095 sid.sid_authorities[0] = 0; 1096 } else if (!strcmp(id, "GROUP@")) { 1097 // S-1-3-1 1098 sid.sid_authority[5] = 3; 1099 sid.sid_authorities[0] = 1; 1100 } else if (!strcmp(id, "EVERYONE@")) { 1101 // S-1-1-0 1102 sid.sid_authority[5] = 1; 1103 sid.sid_authorities[0] = 0; 1104 } else if (!strcmp(id, "INTERACTIVE@")) { 1105 // S-1-5-4 1106 sid.sid_authority[5] = 5; 1107 sid.sid_authorities[0] = 4; 1108 } else if (!strcmp(id, "NETWORK@")) { 1109 // S-1-5-2 1110 sid.sid_authority[5] = 5; 1111 sid.sid_authorities[0] = 2; 1112 } else if (!strcmp(id, "DIALUP@")) { 1113 // S-1-5-1 1114 sid.sid_authority[5] = 5; 1115 sid.sid_authorities[0] = 1; 1116 } else if (!strcmp(id, "BATCH@")) { 1117 // S-1-5-3 1118 sid.sid_authority[5] = 5; 1119 sid.sid_authorities[0] = 3; 1120 } else if (!strcmp(id, "ANONYMOUS@")) { 1121 // S-1-5-7 1122 sid.sid_authority[5] = 5; 1123 sid.sid_authorities[0] = 7; 1124 } else if (!strcmp(id, "AUTHENTICATED@")) { 1125 // S-1-5-11 1126 sid.sid_authority[5] = 5; 1127 sid.sid_authorities[0] = 11; 1128 } else if (!strcmp(id, "SERVICE@")) { 1129 // S-1-5-6 1130 sid.sid_authority[5] = 5; 1131 sid.sid_authorities[0] = 6; 1132 } else { 1133 // S-1-0-0 "NOBODY" 1134 sid.sid_authority[5] = 0; 1135 sid.sid_authorities[0] = 0; 1136 } 1137 error = kauth_cred_ntsid2guid(&sid, gp); 1138 } else { 1139 if (!(nfs_idmap_ctrl & NFS_IDMAP_CTRL_FALLBACK_NO_COMMON_IDS) && at) { 1140 /* must be user@domain */ 1141 /* try to identify some well-known IDs */ 1142 if (!strncmp(id, "root@", 5)) 1143 num = 0; 1144 else if (!strncmp(id, "wheel@", 6)) 1145 num = 0; 1146 else if (!strncmp(id, "nobody@", 7)) 1147 num = -2; 1148 else if (!strncmp(id, "nfsnobody@", 10)) 1149 num = -2; 1150 else 1151 num = unknown; 1152 } else if (!(nfs_idmap_ctrl & NFS_IDMAP_CTRL_FALLBACK_NO_COMMON_IDS) && !strcmp(id, "nobody")) { 1153 num = -2; 1154 } else { 1155 num = unknown; 1156 } 1157gotnumid: 1158 if (isgroup) 1159 error = kauth_cred_gid2guid((gid_t)num, gp); 1160 else 1161 error = kauth_cred_uid2guid((uid_t)num, gp); 1162 } 1163 if (error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) 1164 printf("nfs4_id2guid: fallback map failed for %s %s error %d\n", id, isgroup ? "G" : " ", error); 1165 if (!error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS)) 1166 printf("nfs4_id2guid: fallback map for %s %s got guid " 1167 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x\n", 1168 id, isgroup ? "G" : " ", 1169 gp->g_guid[0], gp->g_guid[1], gp->g_guid[2], gp->g_guid[3], 1170 gp->g_guid[4], gp->g_guid[5], gp->g_guid[6], gp->g_guid[7], 1171 gp->g_guid[8], gp->g_guid[9], gp->g_guid[10], gp->g_guid[11], 1172 gp->g_guid[12], gp->g_guid[13], gp->g_guid[14], gp->g_guid[15]); 1173 } 1174 1175 if (compare) { 1176 /* compare the results, log if different */ 1177 if (!error1 && !error) { 1178 if (!kauth_guid_equal(&guid1, &guid2)) 1179 printf("nfs4_id2guid: idmap/fallback results differ for %s %s - " 1180 "idmap %02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x " 1181 "fallback %02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x\n", 1182 id, isgroup ? "G" : " ", 1183 guid1.g_guid[0], guid1.g_guid[1], guid1.g_guid[2], guid1.g_guid[3], 1184 guid1.g_guid[4], guid1.g_guid[5], guid1.g_guid[6], guid1.g_guid[7], 1185 guid1.g_guid[8], guid1.g_guid[9], guid1.g_guid[10], guid1.g_guid[11], 1186 guid1.g_guid[12], guid1.g_guid[13], guid1.g_guid[14], guid1.g_guid[15], 1187 guid2.g_guid[0], guid2.g_guid[1], guid2.g_guid[2], guid2.g_guid[3], 1188 guid2.g_guid[4], guid2.g_guid[5], guid2.g_guid[6], guid2.g_guid[7], 1189 guid2.g_guid[8], guid2.g_guid[9], guid2.g_guid[10], guid2.g_guid[11], 1190 guid2.g_guid[12], guid2.g_guid[13], guid2.g_guid[14], guid2.g_guid[15]); 1191 /* copy idmap result to output guid */ 1192 *guidp = guid1; 1193 } else if (error1 && !error) { 1194 printf("nfs4_id2guid: idmap/fallback results differ for %s %s - " 1195 "idmap error %d " 1196 "fallback %02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x\n", 1197 id, isgroup ? "G" : " ", 1198 error1, 1199 guid2.g_guid[0], guid2.g_guid[1], guid2.g_guid[2], guid2.g_guid[3], 1200 guid2.g_guid[4], guid2.g_guid[5], guid2.g_guid[6], guid2.g_guid[7], 1201 guid2.g_guid[8], guid2.g_guid[9], guid2.g_guid[10], guid2.g_guid[11], 1202 guid2.g_guid[12], guid2.g_guid[13], guid2.g_guid[14], guid2.g_guid[15]); 1203 /* copy fallback result to output guid */ 1204 *guidp = guid2; 1205 } else if (!error1 && error) { 1206 printf("nfs4_id2guid: idmap/fallback results differ for %s %s - " 1207 "idmap %02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x " 1208 "fallback error %d\n", 1209 id, isgroup ? "G" : " ", 1210 guid1.g_guid[0], guid1.g_guid[1], guid1.g_guid[2], guid1.g_guid[3], 1211 guid1.g_guid[4], guid1.g_guid[5], guid1.g_guid[6], guid1.g_guid[7], 1212 guid1.g_guid[8], guid1.g_guid[9], guid1.g_guid[10], guid1.g_guid[11], 1213 guid1.g_guid[12], guid1.g_guid[13], guid1.g_guid[14], guid1.g_guid[15], 1214 error); 1215 /* copy idmap result to output guid */ 1216 *guidp = guid1; 1217 error = 0; 1218 } else { 1219 if (error1 != error) 1220 printf("nfs4_id2guid: idmap/fallback results differ for %s %s - " 1221 "idmap error %d fallback error %d\n", 1222 id, isgroup ? "G" : " ", error1, error); 1223 } 1224 } 1225 1226 return (error); 1227} 1228 1229/* 1230 * Map a VFS guid to an NFSv4 ID string. 1231 * 1232 * Try to use the ID mapping service... but we may fallback to trying to do it ourselves. 1233 */ 1234int 1235nfs4_guid2id(guid_t *guidp, char *id, int *idlen, int isgroup) 1236{ 1237 int error1 = 0, error = 0, compare; 1238 int id1len, id2len, len; 1239 char *id1buf, *id1; 1240 char numbuf[32]; 1241 const char *id2 = NULL; 1242 1243 id1buf = id1 = NULL; 1244 id1len = id2len = 0; 1245 compare = ((nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE) && 1246 (nfs_idmap_ctrl & NFS_IDMAP_CTRL_COMPARE_RESULTS)); 1247 1248 if (nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE) { 1249 /* 1250 * Ask the ID mapping service to map the GUID to an ID string. 1251 * 1252 * [sigh] this isn't a "pwnam" it's an NFS id string! 1253 */ 1254 1255 /* 1256 * Stupid kauth_cred_guid2pwnam() function requires that the buffer 1257 * be at least MAXPATHLEN bytes long even though most if not all ID 1258 * strings will be much much shorter than that. 1259 */ 1260 if (compare || (*idlen < MAXPATHLEN)) { 1261 MALLOC_ZONE(id1buf, char*, MAXPATHLEN, M_NAMEI, M_WAITOK); 1262 if (!id1buf) 1263 return (ENOMEM); 1264 id1 = id1buf; 1265 id1len = MAXPATHLEN; 1266 } else { 1267 id1 = id; 1268 id1len = *idlen; 1269 } 1270 1271 if (isgroup) 1272 error = kauth_cred_guid2grnam(guidp, id1); 1273 else 1274 error = kauth_cred_guid2pwnam(guidp, id1); 1275 if (error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) 1276 printf("nfs4_guid2id: idmap failed for " 1277 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1278 "error %d\n", 1279 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1280 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1281 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1282 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1283 isgroup ? "G" : " ", error); 1284 if (!error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS)) 1285 printf("nfs4_guid2id: idmap for " 1286 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1287 "got ID %s\n", 1288 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1289 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1290 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1291 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1292 isgroup ? "G" : " ", id1); 1293 error1 = error; 1294 if (!error) { 1295 if (compare) { 1296 id1len = strnlen(id1, id1len); 1297 } else if (id1 == id1buf) { 1298 /* copy idmap result to output buffer */ 1299 len = strlcpy(id, id1, *idlen); 1300 if (len >= *idlen) 1301 error = ENOSPC; 1302 else 1303 *idlen = len; 1304 } 1305 } 1306 } 1307 if (error || compare || !(nfs_idmap_ctrl & NFS_IDMAP_CTRL_USE_IDMAP_SERVICE)) { 1308 /* 1309 * fallback path... see if we can come up with an answer ourselves. 1310 */ 1311 ntsid_t sid; 1312 uid_t uid; 1313 1314 if (!(nfs_idmap_ctrl & NFS_IDMAP_CTRL_FALLBACK_NO_WELLKNOWN_IDS)) { 1315 error = kauth_cred_guid2ntsid(guidp, &sid); 1316 if (!error && (sid.sid_kind == 1) && (sid.sid_authcount == 1)) { 1317 /* check if it's one of our well-known ACE WHO names */ 1318 if (sid.sid_authority[5] == 0) { 1319 if (sid.sid_authorities[0] == 0) // S-1-0-0 1320 id2 = "nobody@localdomain"; 1321 } else if (sid.sid_authority[5] == 1) { 1322 if (sid.sid_authorities[0] == 0) // S-1-1-0 1323 id2 = "EVERYONE@"; 1324 } else if (sid.sid_authority[5] == 3) { 1325 if (sid.sid_authorities[0] == 0) // S-1-3-0 1326 id2 = "OWNER@"; 1327 else if (sid.sid_authorities[0] == 1) // S-1-3-1 1328 id2 = "GROUP@"; 1329 } else if (sid.sid_authority[5] == 5) { 1330 if (sid.sid_authorities[0] == ntohl(1)) // S-1-5-1 1331 id2 = "DIALUP@"; 1332 else if (sid.sid_authorities[0] == ntohl(2)) // S-1-5-2 1333 id2 = "NETWORK@"; 1334 else if (sid.sid_authorities[0] == ntohl(3)) // S-1-5-3 1335 id2 = "BATCH@"; 1336 else if (sid.sid_authorities[0] == ntohl(4)) // S-1-5-4 1337 id2 = "INTERACTIVE@"; 1338 else if (sid.sid_authorities[0] == ntohl(6)) // S-1-5-6 1339 id2 = "SERVICE@"; 1340 else if (sid.sid_authorities[0] == ntohl(7)) // S-1-5-7 1341 id2 = "ANONYMOUS@"; 1342 else if (sid.sid_authorities[0] == ntohl(11)) // S-1-5-11 1343 id2 = "AUTHENTICATED@"; 1344 } 1345 } 1346 } 1347 if (!id2) { 1348 /* OK, let's just try mapping it to a UID/GID */ 1349 if (isgroup) 1350 error = kauth_cred_guid2gid(guidp, (gid_t*)&uid); 1351 else 1352 error = kauth_cred_guid2uid(guidp, &uid); 1353 if (!error) { 1354 if (!(nfs_idmap_ctrl & NFS_IDMAP_CTRL_FALLBACK_NO_COMMON_IDS)) { 1355 /* map well known uid's to strings */ 1356 if (uid == 0) 1357 id2 = isgroup ? "wheel@localdomain" : "root@localdomain"; 1358 else if (uid == (uid_t)-2) 1359 id2 = "nobody@localdomain"; 1360 } 1361 if (!id2) { 1362 /* or just use a decimal number string. */ 1363 snprintf(numbuf, sizeof(numbuf), "%d", uid); 1364 id2 = numbuf; 1365 } 1366 } 1367 } 1368 if (error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) 1369 printf("nfs4_guid2id: fallback map failed for " 1370 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1371 "error %d\n", 1372 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1373 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1374 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1375 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1376 isgroup ? "G" : " ", error); 1377 if (!error && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_SUCCESSFUL_MAPPINGS)) 1378 printf("nfs4_guid2id: fallback map for " 1379 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1380 "got ID %s\n", 1381 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1382 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1383 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1384 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1385 isgroup ? "G" : " ", id2); 1386 if (!error && id2) { 1387 if (compare) { 1388 id2len = strnlen(id2, MAXPATHLEN); 1389 } else { 1390 /* copy fallback result to output buffer */ 1391 len = strlcpy(id, id2, *idlen); 1392 if (len >= *idlen) 1393 error = ENOSPC; 1394 else 1395 *idlen = len; 1396 } 1397 } 1398 } 1399 1400 if (compare) { 1401 /* compare the results, log if different */ 1402 if (!error1 && !error) { 1403 if ((id1len != id2len) || strncmp(id1, id2, id1len)) 1404 printf("nfs4_guid2id: idmap/fallback results differ for " 1405 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1406 "idmap %s fallback %s\n", 1407 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1408 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1409 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1410 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1411 isgroup ? "G" : " ", id1, id2); 1412 if (id1 == id1buf) { 1413 /* copy idmap result to output buffer */ 1414 len = strlcpy(id, id1, *idlen); 1415 if (len >= *idlen) 1416 error = ENOSPC; 1417 else 1418 *idlen = len; 1419 } 1420 } else if (error1 && !error) { 1421 printf("nfs4_guid2id: idmap/fallback results differ for " 1422 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1423 "idmap error %d fallback %s\n", 1424 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1425 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1426 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1427 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1428 isgroup ? "G" : " ", error1, id2); 1429 /* copy fallback result to output buffer */ 1430 len = strlcpy(id, id2, *idlen); 1431 if (len >= *idlen) 1432 error = ENOSPC; 1433 else 1434 *idlen = len; 1435 } else if (!error1 && error) { 1436 printf("nfs4_guid2id: idmap/fallback results differ for " 1437 "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x %s " 1438 "idmap %s fallback error %d\n", 1439 guidp->g_guid[0], guidp->g_guid[1], guidp->g_guid[2], guidp->g_guid[3], 1440 guidp->g_guid[4], guidp->g_guid[5], guidp->g_guid[6], guidp->g_guid[7], 1441 guidp->g_guid[8], guidp->g_guid[9], guidp->g_guid[10], guidp->g_guid[11], 1442 guidp->g_guid[12], guidp->g_guid[13], guidp->g_guid[14], guidp->g_guid[15], 1443 isgroup ? "G" : " ", id1, error); 1444 if (id1 == id1buf) { 1445 /* copy idmap result to output buffer */ 1446 len = strlcpy(id, id1, *idlen); 1447 if (len >= *idlen) 1448 error = ENOSPC; 1449 else 1450 *idlen = len; 1451 } 1452 error = 0; 1453 } else { 1454 if (error1 != error) 1455 printf("nfs4_guid2id: idmap/fallback results differ for %s %s - " 1456 "idmap error %d fallback error %d\n", 1457 id, isgroup ? "G" : " ", error1, error); 1458 } 1459 } 1460 if (id1buf) 1461 FREE_ZONE(id1buf, MAXPATHLEN, M_NAMEI); 1462 return (error); 1463} 1464 1465 1466/* 1467 * Set a vnode attr's supported bits according to the given bitmap 1468 */ 1469void 1470nfs_vattr_set_supported(uint32_t *bitmap, struct vnode_attr *vap) 1471{ 1472 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TYPE)) 1473 VATTR_SET_SUPPORTED(vap, va_type); 1474 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE)) 1475 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) 1476 VATTR_SET_SUPPORTED(vap, va_data_size); 1477 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FSID)) 1478 VATTR_SET_SUPPORTED(vap, va_fsid); 1479 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)) 1480 VATTR_SET_SUPPORTED(vap, va_acl); 1481 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) 1482 VATTR_SET_SUPPORTED(vap, va_flags); 1483 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEID)) 1484 VATTR_SET_SUPPORTED(vap, va_fileid); 1485 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) 1486 VATTR_SET_SUPPORTED(vap, va_flags); 1487 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE)) 1488 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) 1489 VATTR_SET_SUPPORTED(vap, va_mode); 1490 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NUMLINKS)) 1491 VATTR_SET_SUPPORTED(vap, va_nlink); 1492 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) { 1493 VATTR_SET_SUPPORTED(vap, va_uid); 1494 VATTR_SET_SUPPORTED(vap, va_uuuid); 1495 } 1496 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) { 1497 VATTR_SET_SUPPORTED(vap, va_gid); 1498 VATTR_SET_SUPPORTED(vap, va_guuid); 1499 } 1500 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RAWDEV)) 1501 VATTR_SET_SUPPORTED(vap, va_rdev); 1502 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_USED)) 1503 VATTR_SET_SUPPORTED(vap, va_total_alloc); 1504 // if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYSTEM)) 1505 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS)) 1506 VATTR_SET_SUPPORTED(vap, va_access_time); 1507 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) 1508 VATTR_SET_SUPPORTED(vap, va_backup_time); 1509 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) 1510 VATTR_SET_SUPPORTED(vap, va_create_time); 1511 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_METADATA)) 1512 VATTR_SET_SUPPORTED(vap, va_change_time); 1513 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY)) 1514 VATTR_SET_SUPPORTED(vap, va_modify_time); 1515} 1516 1517/* 1518 * Parse the attributes that are in the mbuf list and store them in 1519 * the given structures. 1520 */ 1521int 1522nfs4_parsefattr( 1523 struct nfsm_chain *nmc, 1524 struct nfs_fsattr *nfsap, 1525 struct nfs_vattr *nvap, 1526 fhandle_t *fhp, 1527 struct dqblk *dqbp, 1528 struct nfs_fs_locations *nfslsp) 1529{ 1530 int error = 0, error2, rderror = 0, attrbytes; 1531 uint32_t val, val2, val3, i; 1532 uint32_t bitmap[NFS_ATTR_BITMAP_LEN], len; 1533 size_t slen; 1534 char sbuf[64], *s; 1535 struct nfs_fsattr nfsa_dummy; 1536 struct nfs_vattr nva_dummy; 1537 struct dqblk dqb_dummy; 1538 kauth_acl_t acl = NULL; 1539 uint32_t ace_type, ace_flags, ace_mask; 1540 struct nfs_fs_locations nfsls_dummy; 1541 struct sockaddr_storage ss; 1542 1543 /* if not interested in some values... throw 'em into a local dummy variable */ 1544 if (!nfsap) 1545 nfsap = &nfsa_dummy; 1546 if (!nvap) 1547 nvap = &nva_dummy; 1548 if (!dqbp) 1549 dqbp = &dqb_dummy; 1550 if (!nfslsp) 1551 nfslsp = &nfsls_dummy; 1552 bzero(nfslsp, sizeof(*nfslsp)); 1553 1554 attrbytes = val = val2 = val3 = 0; 1555 s = sbuf; 1556 slen = sizeof(sbuf); 1557 NVATTR_INIT(nvap); 1558 1559 len = NFS_ATTR_BITMAP_LEN; 1560 nfsm_chain_get_bitmap(error, nmc, bitmap, len); 1561 /* add bits to object/fs attr bitmaps */ 1562 for (i=0; i < NFS_ATTR_BITMAP_LEN; i++) { 1563 nvap->nva_bitmap[i] |= bitmap[i] & nfs_object_attr_bitmap[i]; 1564 nfsap->nfsa_bitmap[i] |= bitmap[i] & nfs_fs_attr_bitmap[i]; 1565 } 1566 1567 nfsm_chain_get_32(error, nmc, attrbytes); 1568 nfsmout_if(error); 1569 1570 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SUPPORTED_ATTRS)) { 1571 len = NFS_ATTR_BITMAP_LEN; 1572 nfsm_chain_get_bitmap(error, nmc, nfsap->nfsa_supp_attr, len); 1573 attrbytes -= (len + 1) * NFSX_UNSIGNED; 1574 } 1575 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TYPE)) { 1576 nfsm_chain_get_32(error, nmc, val); 1577 nvap->nva_type = nfstov_type(val, NFS_VER4); 1578 if ((val == NFATTRDIR) || (val == NFNAMEDATTR)) 1579 nvap->nva_flags |= NFS_FFLAG_IS_ATTR; 1580 else 1581 nvap->nva_flags &= ~NFS_FFLAG_IS_ATTR; 1582 attrbytes -= NFSX_UNSIGNED; 1583 } 1584 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FH_EXPIRE_TYPE)) { 1585 nfsm_chain_get_32(error, nmc, val); 1586 nfsmout_if(error); 1587 nfsap->nfsa_flags &= ~NFS_FSFLAG_FHTYPE_MASK; 1588 nfsap->nfsa_flags |= val << NFS_FSFLAG_FHTYPE_SHIFT; 1589 if (val & ~0xff) 1590 printf("nfs: warning unknown fh type: 0x%x\n", val); 1591 attrbytes -= NFSX_UNSIGNED; 1592 } 1593 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHANGE)) { 1594 nfsm_chain_get_64(error, nmc, nvap->nva_change); 1595 attrbytes -= 2 * NFSX_UNSIGNED; 1596 } 1597 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) { 1598 nfsm_chain_get_64(error, nmc, nvap->nva_size); 1599 attrbytes -= 2 * NFSX_UNSIGNED; 1600 } 1601 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LINK_SUPPORT)) { 1602 nfsm_chain_get_32(error, nmc, val); 1603 if (val) 1604 nfsap->nfsa_flags |= NFS_FSFLAG_LINK; 1605 else 1606 nfsap->nfsa_flags &= ~NFS_FSFLAG_LINK; 1607 attrbytes -= NFSX_UNSIGNED; 1608 } 1609 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYMLINK_SUPPORT)) { 1610 nfsm_chain_get_32(error, nmc, val); 1611 if (val) 1612 nfsap->nfsa_flags |= NFS_FSFLAG_SYMLINK; 1613 else 1614 nfsap->nfsa_flags &= ~NFS_FSFLAG_SYMLINK; 1615 attrbytes -= NFSX_UNSIGNED; 1616 } 1617 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NAMED_ATTR)) { 1618 nfsm_chain_get_32(error, nmc, val); 1619 if (val) 1620 nvap->nva_flags |= NFS_FFLAG_HAS_NAMED_ATTRS; 1621 else 1622 nvap->nva_flags &= ~NFS_FFLAG_HAS_NAMED_ATTRS; 1623 attrbytes -= NFSX_UNSIGNED; 1624 } 1625 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FSID)) { 1626 nfsm_chain_get_64(error, nmc, nvap->nva_fsid.major); 1627 nfsm_chain_get_64(error, nmc, nvap->nva_fsid.minor); 1628 attrbytes -= 4 * NFSX_UNSIGNED; 1629 } 1630 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_UNIQUE_HANDLES)) { 1631 nfsm_chain_get_32(error, nmc, val); 1632 if (val) 1633 nfsap->nfsa_flags |= NFS_FSFLAG_UNIQUE_FH; 1634 else 1635 nfsap->nfsa_flags &= ~NFS_FSFLAG_UNIQUE_FH; 1636 attrbytes -= NFSX_UNSIGNED; 1637 } 1638 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_LEASE_TIME)) { 1639 nfsm_chain_get_32(error, nmc, nfsap->nfsa_lease); 1640 attrbytes -= NFSX_UNSIGNED; 1641 } 1642 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RDATTR_ERROR)) { 1643 nfsm_chain_get_32(error, nmc, rderror); 1644 attrbytes -= NFSX_UNSIGNED; 1645 if (!rderror) { /* no error */ 1646 NFS_BITMAP_CLR(bitmap, NFS_FATTR_RDATTR_ERROR); 1647 NFS_BITMAP_CLR(nvap->nva_bitmap, NFS_FATTR_RDATTR_ERROR); 1648 } 1649 } 1650 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)) { 1651 error2 = 0; 1652 ace_type = ace_flags = ace_mask = 0; 1653 nfsm_chain_get_32(error, nmc, val); /* ACE count */ 1654 if (!error && (val > KAUTH_ACL_MAX_ENTRIES)) 1655 error = EOVERFLOW; 1656 if (!error && !((acl = kauth_acl_alloc(val)))) 1657 error = ENOMEM; 1658 if (!error && acl) { 1659 acl->acl_entrycount = val; 1660 acl->acl_flags = 0; 1661 } 1662 attrbytes -= NFSX_UNSIGNED; 1663 nfsm_assert(error, (attrbytes >= 0), EBADRPC); 1664 for (i=0; !error && (i < val); i++) { 1665 nfsm_chain_get_32(error, nmc, ace_type); 1666 nfsm_chain_get_32(error, nmc, ace_flags); 1667 nfsm_chain_get_32(error, nmc, ace_mask); 1668 nfsm_chain_get_32(error, nmc, len); 1669 if (!error && len >= NFS_MAX_WHO) 1670 error = EBADRPC; 1671 acl->acl_ace[i].ace_flags = nfs4_ace_nfstype_to_vfstype(ace_type, &error); 1672 acl->acl_ace[i].ace_flags |= nfs4_ace_nfsflags_to_vfsflags(ace_flags); 1673 acl->acl_ace[i].ace_rights = nfs4_ace_nfsmask_to_vfsrights(ace_mask); 1674 if (!error && !error2 && (len >= slen)) { 1675 if (s != sbuf) { 1676 FREE(s, M_TEMP); 1677 s = sbuf; 1678 slen = sizeof(sbuf); 1679 } 1680 /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */ 1681 MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK); 1682 if (s) 1683 slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO; 1684 else 1685 error = ENOMEM; 1686 } 1687 if (error2) 1688 nfsm_chain_adv(error, nmc, nfsm_rndup(len)); 1689 else 1690 nfsm_chain_get_opaque(error, nmc, len, s); 1691 if (!error && !error2) { 1692 s[len] = '\0'; 1693 error2 = nfs4_id2guid(s, &acl->acl_ace[i].ace_applicable, 1694 (ace_flags & NFS_ACE_IDENTIFIER_GROUP)); 1695 if (error2 && (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS)) 1696 printf("nfs4_parsefattr: ACE WHO %s is no one, no guid?, error %d\n", s, error2); 1697 } 1698 attrbytes -= 4*NFSX_UNSIGNED + nfsm_rndup(len); 1699 nfsm_assert(error, (attrbytes >= 0), EBADRPC); 1700 } 1701 nfsmout_if(error); 1702 if ((nvap != &nva_dummy) && !error2) { 1703 nvap->nva_acl = acl; 1704 acl = NULL; 1705 } 1706 } 1707 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACLSUPPORT)) { 1708 /* 1709 * Support ACLs if: the server supports DENY/ALLOC ACEs and 1710 * (just to be safe) FATTR_ACL is in the supported list too. 1711 */ 1712 nfsm_chain_get_32(error, nmc, val); 1713 if ((val & (NFS_ACL_SUPPORT_ALLOW_ACL|NFS_ACL_SUPPORT_DENY_ACL)) && 1714 NFS_BITMAP_ISSET(nfsap->nfsa_supp_attr, NFS_FATTR_ACL)) { 1715 nfsap->nfsa_flags |= NFS_FSFLAG_ACL; 1716 } else { 1717 nfsap->nfsa_flags &= ~NFS_FSFLAG_ACL; 1718 } 1719 attrbytes -= NFSX_UNSIGNED; 1720 } 1721 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) { /* SF_ARCHIVED */ 1722 nfsm_chain_get_32(error, nmc, val); 1723 if (val) 1724 nvap->nva_flags |= NFS_FFLAG_ARCHIVED; 1725 else 1726 nvap->nva_flags &= ~NFS_FFLAG_ARCHIVED; 1727 attrbytes -= NFSX_UNSIGNED; 1728 } 1729 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CANSETTIME)) { 1730 nfsm_chain_get_32(error, nmc, val); 1731 if (val) 1732 nfsap->nfsa_flags |= NFS_FSFLAG_SET_TIME; 1733 else 1734 nfsap->nfsa_flags &= ~NFS_FSFLAG_SET_TIME; 1735 attrbytes -= NFSX_UNSIGNED; 1736 } 1737 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_INSENSITIVE)) { 1738 nfsm_chain_get_32(error, nmc, val); 1739 if (val) 1740 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_INSENSITIVE; 1741 else 1742 nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_INSENSITIVE; 1743 attrbytes -= NFSX_UNSIGNED; 1744 } 1745 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CASE_PRESERVING)) { 1746 nfsm_chain_get_32(error, nmc, val); 1747 if (val) 1748 nfsap->nfsa_flags |= NFS_FSFLAG_CASE_PRESERVING; 1749 else 1750 nfsap->nfsa_flags &= ~NFS_FSFLAG_CASE_PRESERVING; 1751 attrbytes -= NFSX_UNSIGNED; 1752 } 1753 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_CHOWN_RESTRICTED)) { 1754 nfsm_chain_get_32(error, nmc, val); 1755 if (val) 1756 nfsap->nfsa_flags |= NFS_FSFLAG_CHOWN_RESTRICTED; 1757 else 1758 nfsap->nfsa_flags &= ~NFS_FSFLAG_CHOWN_RESTRICTED; 1759 attrbytes -= NFSX_UNSIGNED; 1760 } 1761 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEHANDLE)) { 1762 nfsm_chain_get_32(error, nmc, val); 1763 if (fhp) { 1764 fhp->fh_len = val; 1765 nfsm_chain_get_opaque(error, nmc, nfsm_rndup(val), fhp->fh_data); 1766 } else { 1767 nfsm_chain_adv(error, nmc, nfsm_rndup(val)); 1768 } 1769 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); 1770 } 1771 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILEID)) { 1772 nfsm_chain_get_64(error, nmc, nvap->nva_fileid); 1773 attrbytes -= 2 * NFSX_UNSIGNED; 1774 } 1775 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_AVAIL)) { 1776 nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_avail); 1777 attrbytes -= 2 * NFSX_UNSIGNED; 1778 } 1779 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_FREE)) { 1780 nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_free); 1781 attrbytes -= 2 * NFSX_UNSIGNED; 1782 } 1783 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FILES_TOTAL)) { 1784 nfsm_chain_get_64(error, nmc, nfsap->nfsa_files_total); 1785 attrbytes -= 2 * NFSX_UNSIGNED; 1786 } 1787 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_FS_LOCATIONS)) { 1788 uint32_t loc, serv, comp; 1789 struct nfs_fs_location *fsl; 1790 struct nfs_fs_server *fss; 1791 struct nfs_fs_path *fsp; 1792 1793 /* get root pathname */ 1794 fsp = &nfslsp->nl_root; 1795 nfsm_chain_get_32(error, nmc, fsp->np_compcount); /* component count */ 1796 attrbytes -= NFSX_UNSIGNED; 1797 /* sanity check component count */ 1798 if (!error && (fsp->np_compcount > MAXPATHLEN)) 1799 error = EBADRPC; 1800 nfsmout_if(error); 1801 if (fsp->np_compcount) { 1802 MALLOC(fsp->np_components, char **, fsp->np_compcount * sizeof(char*), M_TEMP, M_WAITOK|M_ZERO); 1803 if (!fsp->np_components) 1804 error = ENOMEM; 1805 } 1806 for (comp = 0; comp < fsp->np_compcount; comp++) { 1807 nfsm_chain_get_32(error, nmc, val); /* component length */ 1808 /* sanity check component length */ 1809 if (!error && (val == 0)) { 1810 /* 1811 * Apparently some people think a path with zero components should 1812 * be encoded with one zero-length component. So, just ignore any 1813 * zero length components. 1814 */ 1815 comp--; 1816 fsp->np_compcount--; 1817 if (fsp->np_compcount == 0) { 1818 FREE(fsp->np_components, M_TEMP); 1819 fsp->np_components = NULL; 1820 } 1821 attrbytes -= NFSX_UNSIGNED; 1822 continue; 1823 } 1824 if (!error && ((val < 1) || (val > MAXPATHLEN))) 1825 error = EBADRPC; 1826 nfsmout_if(error); 1827 MALLOC(fsp->np_components[comp], char *, val+1, M_TEMP, M_WAITOK|M_ZERO); 1828 if (!fsp->np_components[comp]) 1829 error = ENOMEM; 1830 nfsmout_if(error); 1831 nfsm_chain_get_opaque(error, nmc, val, fsp->np_components[comp]); /* component */ 1832 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); 1833 } 1834 nfsm_chain_get_32(error, nmc, nfslsp->nl_numlocs); /* fs location count */ 1835 attrbytes -= NFSX_UNSIGNED; 1836 /* sanity check location count */ 1837 if (!error && (nfslsp->nl_numlocs > 256)) 1838 error = EBADRPC; 1839 nfsmout_if(error); 1840 if (nfslsp->nl_numlocs > 0) { 1841 MALLOC(nfslsp->nl_locations, struct nfs_fs_location **, nfslsp->nl_numlocs * sizeof(struct nfs_fs_location*), M_TEMP, M_WAITOK|M_ZERO); 1842 if (!nfslsp->nl_locations) 1843 error = ENOMEM; 1844 } 1845 nfsmout_if(error); 1846 for (loc = 0; loc < nfslsp->nl_numlocs; loc++) { 1847 nfsmout_if(error); 1848 MALLOC(fsl, struct nfs_fs_location *, sizeof(struct nfs_fs_location), M_TEMP, M_WAITOK|M_ZERO); 1849 if (!fsl) 1850 error = ENOMEM; 1851 nfslsp->nl_locations[loc] = fsl; 1852 nfsm_chain_get_32(error, nmc, fsl->nl_servcount); /* server count */ 1853 attrbytes -= NFSX_UNSIGNED; 1854 /* sanity check server count */ 1855 if (!error && ((fsl->nl_servcount < 1) || (fsl->nl_servcount > 256))) 1856 error = EBADRPC; 1857 nfsmout_if(error); 1858 MALLOC(fsl->nl_servers, struct nfs_fs_server **, fsl->nl_servcount * sizeof(struct nfs_fs_server*), M_TEMP, M_WAITOK|M_ZERO); 1859 if (!fsl->nl_servers) 1860 error = ENOMEM; 1861 for (serv = 0; serv < fsl->nl_servcount; serv++) { 1862 nfsmout_if(error); 1863 MALLOC(fss, struct nfs_fs_server *, sizeof(struct nfs_fs_server), M_TEMP, M_WAITOK|M_ZERO); 1864 if (!fss) 1865 error = ENOMEM; 1866 fsl->nl_servers[serv] = fss; 1867 nfsm_chain_get_32(error, nmc, val); /* server name length */ 1868 /* sanity check server name length */ 1869 if (!error && ((val < 1) || (val > MAXPATHLEN))) 1870 error = EINVAL; 1871 nfsmout_if(error); 1872 MALLOC(fss->ns_name, char *, val+1, M_TEMP, M_WAITOK|M_ZERO); 1873 if (!fss->ns_name) 1874 error = ENOMEM; 1875 nfsm_chain_get_opaque(error, nmc, val, fss->ns_name); /* server name */ 1876 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); 1877 nfsmout_if(error); 1878 /* copy name to address if it converts to a sockaddr */ 1879 if (nfs_uaddr2sockaddr(fss->ns_name, (struct sockaddr*)&ss)) { 1880 fss->ns_addrcount = 1; 1881 MALLOC(fss->ns_addresses, char **, sizeof(char *), M_TEMP, M_WAITOK|M_ZERO); 1882 if (!fss->ns_addresses) 1883 error = ENOMEM; 1884 nfsmout_if(error); 1885 MALLOC(fss->ns_addresses[0], char *, val+1, M_TEMP, M_WAITOK|M_ZERO); 1886 if (!fss->ns_addresses[0]) 1887 error = ENOMEM; 1888 nfsmout_if(error); 1889 strlcpy(fss->ns_addresses[0], fss->ns_name, val+1); 1890 } 1891 } 1892 /* get pathname */ 1893 fsp = &fsl->nl_path; 1894 nfsm_chain_get_32(error, nmc, fsp->np_compcount); /* component count */ 1895 attrbytes -= NFSX_UNSIGNED; 1896 /* sanity check component count */ 1897 if (!error && (fsp->np_compcount > MAXPATHLEN)) 1898 error = EINVAL; 1899 nfsmout_if(error); 1900 if (fsp->np_compcount) { 1901 MALLOC(fsp->np_components, char **, fsp->np_compcount * sizeof(char*), M_TEMP, M_WAITOK|M_ZERO); 1902 if (!fsp->np_components) 1903 error = ENOMEM; 1904 } 1905 for (comp = 0; comp < fsp->np_compcount; comp++) { 1906 nfsm_chain_get_32(error, nmc, val); /* component length */ 1907 /* sanity check component length */ 1908 if (!error && (val == 0)) { 1909 /* 1910 * Apparently some people think a path with zero components should 1911 * be encoded with one zero-length component. So, just ignore any 1912 * zero length components. 1913 */ 1914 comp--; 1915 fsp->np_compcount--; 1916 if (fsp->np_compcount == 0) { 1917 FREE(fsp->np_components, M_TEMP); 1918 fsp->np_components = NULL; 1919 } 1920 attrbytes -= NFSX_UNSIGNED; 1921 continue; 1922 } 1923 if (!error && ((val < 1) || (val > MAXPATHLEN))) 1924 error = EINVAL; 1925 nfsmout_if(error); 1926 MALLOC(fsp->np_components[comp], char *, val+1, M_TEMP, M_WAITOK|M_ZERO); 1927 if (!fsp->np_components[comp]) 1928 error = ENOMEM; 1929 nfsm_chain_get_opaque(error, nmc, val, fsp->np_components[comp]); /* component */ 1930 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); 1931 } 1932 } 1933 nfsm_assert(error, (attrbytes >= 0), EBADRPC); 1934 } 1935 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) { /* UF_HIDDEN */ 1936 nfsm_chain_get_32(error, nmc, val); 1937 if (val) 1938 nvap->nva_flags |= NFS_FFLAG_HIDDEN; 1939 else 1940 nvap->nva_flags &= ~NFS_FFLAG_HIDDEN; 1941 attrbytes -= NFSX_UNSIGNED; 1942 } 1943 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HOMOGENEOUS)) { 1944 /* XXX If NOT homogeneous, we may need to clear flags on the mount */ 1945 nfsm_chain_get_32(error, nmc, val); 1946 if (val) 1947 nfsap->nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS; 1948 else 1949 nfsap->nfsa_flags &= ~NFS_FSFLAG_HOMOGENEOUS; 1950 attrbytes -= NFSX_UNSIGNED; 1951 } 1952 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXFILESIZE)) { 1953 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxfilesize); 1954 attrbytes -= 2 * NFSX_UNSIGNED; 1955 } 1956 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXLINK)) { 1957 nfsm_chain_get_32(error, nmc, nvap->nva_maxlink); 1958 if (!error && (nfsap->nfsa_maxlink > INT32_MAX)) 1959 nfsap->nfsa_maxlink = INT32_MAX; 1960 attrbytes -= NFSX_UNSIGNED; 1961 } 1962 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXNAME)) { 1963 nfsm_chain_get_32(error, nmc, nfsap->nfsa_maxname); 1964 if (!error && (nfsap->nfsa_maxname > INT32_MAX)) 1965 nfsap->nfsa_maxname = INT32_MAX; 1966 attrbytes -= NFSX_UNSIGNED; 1967 } 1968 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXREAD)) { 1969 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxread); 1970 attrbytes -= 2 * NFSX_UNSIGNED; 1971 } 1972 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MAXWRITE)) { 1973 nfsm_chain_get_64(error, nmc, nfsap->nfsa_maxwrite); 1974 attrbytes -= 2 * NFSX_UNSIGNED; 1975 } 1976 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE)) { 1977 nfsm_chain_get_32(error, nmc, val); 1978 nfsm_chain_adv(error, nmc, nfsm_rndup(val)); 1979 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(val); 1980 } 1981 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) { 1982 nfsm_chain_get_32(error, nmc, nvap->nva_mode); 1983 attrbytes -= NFSX_UNSIGNED; 1984 } 1985 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NO_TRUNC)) { 1986 nfsm_chain_get_32(error, nmc, val); 1987 if (val) 1988 nfsap->nfsa_flags |= NFS_FSFLAG_NO_TRUNC; 1989 else 1990 nfsap->nfsa_flags &= ~NFS_FSFLAG_NO_TRUNC; 1991 attrbytes -= NFSX_UNSIGNED; 1992 } 1993 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_NUMLINKS)) { 1994 nfsm_chain_get_32(error, nmc, val); 1995 nvap->nva_nlink = val; 1996 attrbytes -= NFSX_UNSIGNED; 1997 } 1998 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) { 1999 nfsm_chain_get_32(error, nmc, len); 2000 if (!error && len >= NFS_MAX_WHO) 2001 error = EBADRPC; 2002 if (!error && (len >= slen)) { 2003 if (s != sbuf) { 2004 FREE(s, M_TEMP); 2005 s = sbuf; 2006 slen = sizeof(sbuf); 2007 } 2008 /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */ 2009 MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK); 2010 if (s) 2011 slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO; 2012 else 2013 error = ENOMEM; 2014 } 2015 nfsm_chain_get_opaque(error, nmc, len, s); 2016 if (!error) { 2017 s[len] = '\0'; 2018 error = nfs4_id2guid(s, &nvap->nva_uuuid, 0); 2019 if (!error) 2020 error = kauth_cred_guid2uid(&nvap->nva_uuuid, &nvap->nva_uid); 2021 if (error) { 2022 /* unable to get either GUID or UID, set to default */ 2023 nvap->nva_uid = (uid_t)((nfs_idmap_ctrl & NFS_IDMAP_CTRL_UNKNOWN_IS_99) ? 99 : -2); 2024 if (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS) 2025 printf("nfs4_parsefattr: owner %s is no one, no %s?, error %d\n", s, 2026 kauth_guid_equal(&nvap->nva_uuuid, &kauth_null_guid) ? "guid" : "uid", 2027 error); 2028 error = 0; 2029 } 2030 } 2031 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(len); 2032 } 2033 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) { 2034 nfsm_chain_get_32(error, nmc, len); 2035 if (!error && len >= NFS_MAX_WHO) 2036 error = EBADRPC; 2037 if (!error && (len >= slen)) { 2038 if (s != sbuf) { 2039 FREE(s, M_TEMP); 2040 s = sbuf; 2041 slen = sizeof(sbuf); 2042 } 2043 /* Let's add a bit more if we can to the allocation as to try and avoid future allocations */ 2044 MALLOC(s, char*, (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO, M_TEMP, M_WAITOK); 2045 if (s) 2046 slen = (len + 16 < NFS_MAX_WHO) ? len+16 : NFS_MAX_WHO; 2047 else 2048 error = ENOMEM; 2049 } 2050 nfsm_chain_get_opaque(error, nmc, len, s); 2051 if (!error) { 2052 s[len] = '\0'; 2053 error = nfs4_id2guid(s, &nvap->nva_guuid, 1); 2054 if (!error) 2055 error = kauth_cred_guid2gid(&nvap->nva_guuid, &nvap->nva_gid); 2056 if (error) { 2057 /* unable to get either GUID or GID, set to default */ 2058 nvap->nva_gid = (gid_t)((nfs_idmap_ctrl & NFS_IDMAP_CTRL_UNKNOWN_IS_99) ? 99 : -2); 2059 if (nfs_idmap_ctrl & NFS_IDMAP_CTRL_LOG_FAILED_MAPPINGS) 2060 printf("nfs4_parsefattr: group %s is no one, no %s?, error %d\n", s, 2061 kauth_guid_equal(&nvap->nva_guuid, &kauth_null_guid) ? "guid" : "gid", 2062 error); 2063 error = 0; 2064 } 2065 } 2066 attrbytes -= NFSX_UNSIGNED + nfsm_rndup(len); 2067 } 2068 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_AVAIL_HARD)) { 2069 nfsm_chain_get_64(error, nmc, dqbp->dqb_bhardlimit); 2070 attrbytes -= 2 * NFSX_UNSIGNED; 2071 } 2072 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_AVAIL_SOFT)) { 2073 nfsm_chain_get_64(error, nmc, dqbp->dqb_bsoftlimit); 2074 attrbytes -= 2 * NFSX_UNSIGNED; 2075 } 2076 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_QUOTA_USED)) { 2077 nfsm_chain_get_64(error, nmc, dqbp->dqb_curbytes); 2078 attrbytes -= 2 * NFSX_UNSIGNED; 2079 } 2080 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_RAWDEV)) { 2081 nfsm_chain_get_32(error, nmc, nvap->nva_rawdev.specdata1); 2082 nfsm_chain_get_32(error, nmc, nvap->nva_rawdev.specdata2); 2083 attrbytes -= 2 * NFSX_UNSIGNED; 2084 } 2085 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_AVAIL)) { 2086 nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_avail); 2087 attrbytes -= 2 * NFSX_UNSIGNED; 2088 } 2089 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_FREE)) { 2090 nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_free); 2091 attrbytes -= 2 * NFSX_UNSIGNED; 2092 } 2093 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_TOTAL)) { 2094 nfsm_chain_get_64(error, nmc, nfsap->nfsa_space_total); 2095 attrbytes -= 2 * NFSX_UNSIGNED; 2096 } 2097 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SPACE_USED)) { 2098 nfsm_chain_get_64(error, nmc, nvap->nva_bytes); 2099 attrbytes -= 2 * NFSX_UNSIGNED; 2100 } 2101 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SYSTEM)) { 2102 /* we'd support this if we had a flag to map it to... */ 2103 nfsm_chain_adv(error, nmc, NFSX_UNSIGNED); 2104 attrbytes -= NFSX_UNSIGNED; 2105 } 2106 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS)) { 2107 nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_ACCESS]); 2108 nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_ACCESS]); 2109 attrbytes -= 3 * NFSX_UNSIGNED; 2110 } 2111 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS_SET)) { 2112 nfsm_chain_adv(error, nmc, 4*NFSX_UNSIGNED); /* just skip it */ 2113 attrbytes -= 4 * NFSX_UNSIGNED; 2114 } 2115 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) { 2116 nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_BACKUP]); 2117 nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_BACKUP]); 2118 attrbytes -= 3 * NFSX_UNSIGNED; 2119 } 2120 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) { 2121 nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_CREATE]); 2122 nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_CREATE]); 2123 attrbytes -= 3 * NFSX_UNSIGNED; 2124 } 2125 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_DELTA)) { /* skip for now */ 2126 nfsm_chain_adv(error, nmc, 3*NFSX_UNSIGNED); 2127 attrbytes -= 3 * NFSX_UNSIGNED; 2128 } 2129 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_METADATA)) { 2130 nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_CHANGE]); 2131 nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_CHANGE]); 2132 attrbytes -= 3 * NFSX_UNSIGNED; 2133 } 2134 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY)) { 2135 nfsm_chain_get_64(error, nmc, nvap->nva_timesec[NFSTIME_MODIFY]); 2136 nfsm_chain_get_32(error, nmc, nvap->nva_timensec[NFSTIME_MODIFY]); 2137 attrbytes -= 3 * NFSX_UNSIGNED; 2138 } 2139 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY_SET)) { 2140 nfsm_chain_adv(error, nmc, 4*NFSX_UNSIGNED); /* just skip it */ 2141 attrbytes -= 4 * NFSX_UNSIGNED; 2142 } 2143 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MOUNTED_ON_FILEID)) { 2144#if CONFIG_TRIGGERS 2145 /* we prefer the mounted on file ID, so just replace the fileid */ 2146 nfsm_chain_get_64(error, nmc, nvap->nva_fileid); 2147#else 2148 nfsm_chain_adv(error, nmc, 2*NFSX_UNSIGNED); 2149#endif 2150 attrbytes -= 2 * NFSX_UNSIGNED; 2151 } 2152 /* advance over any leftover attrbytes */ 2153 nfsm_assert(error, (attrbytes >= 0), EBADRPC); 2154 nfsm_chain_adv(error, nmc, nfsm_rndup(attrbytes)); 2155nfsmout: 2156 if (error) 2157 nfs_fs_locations_cleanup(nfslsp); 2158 if (!error && rderror) 2159 error = rderror; 2160 /* free up temporary resources */ 2161 if (s && (s != sbuf)) 2162 FREE(s, M_TEMP); 2163 if (acl) 2164 kauth_acl_free(acl); 2165 if (error && nvap->nva_acl) { 2166 kauth_acl_free(nvap->nva_acl); 2167 nvap->nva_acl = NULL; 2168 } 2169 return (error); 2170} 2171 2172/* 2173 * Add an NFSv4 "sattr" structure to an mbuf chain 2174 */ 2175int 2176nfsm_chain_add_fattr4_f(struct nfsm_chain *nmc, struct vnode_attr *vap, struct nfsmount *nmp) 2177{ 2178 int error = 0, attrbytes, slen, len, i, isgroup; 2179 uint32_t *pattrbytes, val, acecount;; 2180 uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; 2181 char sbuf[64], *s; 2182 kauth_acl_t acl; 2183 gid_t gid; 2184 2185 s = sbuf; 2186 slen = sizeof(sbuf); 2187 2188 /* First calculate the bitmap... */ 2189 nfs_vattr_set_bitmap(nmp, bitmap, vap); 2190 2191 /* 2192 * Now pack it all together: 2193 * BITMAP, #BYTES, ATTRS 2194 * Keep a pointer to the length so we can set it later. 2195 */ 2196 nfsm_chain_add_bitmap(error, nmc, bitmap, NFS_ATTR_BITMAP_LEN); 2197 attrbytes = 0; 2198 nfsm_chain_add_32(error, nmc, attrbytes); 2199 pattrbytes = (uint32_t*)(nmc->nmc_ptr - NFSX_UNSIGNED); 2200 2201 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_SIZE)) { 2202 nfsm_chain_add_64(error, nmc, vap->va_data_size); 2203 attrbytes += 2*NFSX_UNSIGNED; 2204 } 2205 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ACL)) { 2206 acl = vap->va_acl; 2207 if (!acl || (acl->acl_entrycount == KAUTH_FILESEC_NOACL)) 2208 acecount = 0; 2209 else 2210 acecount = acl->acl_entrycount; 2211 nfsm_chain_add_32(error, nmc, acecount); 2212 attrbytes += NFSX_UNSIGNED; 2213 for (i=0; !error && (i < (int)acecount); i++) { 2214 val = (acl->acl_ace[i].ace_flags & KAUTH_ACE_KINDMASK); 2215 val = nfs4_ace_vfstype_to_nfstype(val, &error); 2216 nfsm_chain_add_32(error, nmc, val); 2217 val = nfs4_ace_vfsflags_to_nfsflags(acl->acl_ace[i].ace_flags); 2218 nfsm_chain_add_32(error, nmc, val); 2219 val = nfs4_ace_vfsrights_to_nfsmask(acl->acl_ace[i].ace_rights); 2220 nfsm_chain_add_32(error, nmc, val); 2221 len = slen; 2222 isgroup = (kauth_cred_guid2gid(&acl->acl_ace[i].ace_applicable, &gid) == 0); 2223 error = nfs4_guid2id(&acl->acl_ace[i].ace_applicable, s, &len, isgroup); 2224 if (error == ENOSPC) { 2225 if (s != sbuf) { 2226 FREE(s, M_TEMP); 2227 s = sbuf; 2228 } 2229 len += 8; 2230 MALLOC(s, char*, len, M_TEMP, M_WAITOK); 2231 if (s) { 2232 slen = len; 2233 error = nfs4_guid2id(&acl->acl_ace[i].ace_applicable, s, &len, isgroup); 2234 } else { 2235 error = ENOMEM; 2236 } 2237 } 2238 nfsm_chain_add_name(error, nmc, s, len, nmp); 2239 attrbytes += 4*NFSX_UNSIGNED + nfsm_rndup(len); 2240 } 2241 } 2242 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_ARCHIVE)) { 2243 nfsm_chain_add_32(error, nmc, (vap->va_flags & SF_ARCHIVED) ? 1 : 0); 2244 attrbytes += NFSX_UNSIGNED; 2245 } 2246 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_HIDDEN)) { 2247 nfsm_chain_add_32(error, nmc, (vap->va_flags & UF_HIDDEN) ? 1 : 0); 2248 attrbytes += NFSX_UNSIGNED; 2249 } 2250 // NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MIMETYPE) 2251 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_MODE)) { 2252 nfsm_chain_add_32(error, nmc, vap->va_mode); 2253 attrbytes += NFSX_UNSIGNED; 2254 } 2255 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER)) { 2256 nfsmout_if(error); 2257 /* if we have va_uuuid use it, otherwise use uid */ 2258 if (!VATTR_IS_ACTIVE(vap, va_uuuid)) { 2259 error = kauth_cred_uid2guid(vap->va_uid, &vap->va_uuuid); 2260 nfsmout_if(error); 2261 } 2262 len = slen; 2263 error = nfs4_guid2id(&vap->va_uuuid, s, &len, 0); 2264 if (error == ENOSPC) { 2265 if (s != sbuf) { 2266 FREE(s, M_TEMP); 2267 s = sbuf; 2268 } 2269 len += 8; 2270 MALLOC(s, char*, len, M_TEMP, M_WAITOK); 2271 if (s) { 2272 slen = len; 2273 error = nfs4_guid2id(&vap->va_uuuid, s, &len, 0); 2274 } else { 2275 error = ENOMEM; 2276 } 2277 } 2278 nfsm_chain_add_name(error, nmc, s, len, nmp); 2279 attrbytes += NFSX_UNSIGNED + nfsm_rndup(len); 2280 } 2281 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_OWNER_GROUP)) { 2282 nfsmout_if(error); 2283 /* if we have va_guuid use it, otherwise use gid */ 2284 if (!VATTR_IS_ACTIVE(vap, va_guuid)) { 2285 error = kauth_cred_gid2guid(vap->va_gid, &vap->va_guuid); 2286 nfsmout_if(error); 2287 } 2288 len = slen; 2289 error = nfs4_guid2id(&vap->va_guuid, s, &len, 1); 2290 if (error == ENOSPC) { 2291 if (s != sbuf) { 2292 FREE(s, M_TEMP); 2293 s = sbuf; 2294 } 2295 len += 8; 2296 MALLOC(s, char*, len, M_TEMP, M_WAITOK); 2297 if (s) { 2298 slen = len; 2299 error = nfs4_guid2id(&vap->va_guuid, s, &len, 1); 2300 } else { 2301 error = ENOMEM; 2302 } 2303 } 2304 nfsm_chain_add_name(error, nmc, s, len, nmp); 2305 attrbytes += NFSX_UNSIGNED + nfsm_rndup(len); 2306 } 2307 // NFS_BITMAP_SET(bitmap, NFS_FATTR_SYSTEM) 2308 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_ACCESS_SET)) { 2309 if (vap->va_vaflags & VA_UTIMES_NULL) { 2310 nfsm_chain_add_32(error, nmc, NFS4_TIME_SET_TO_SERVER); 2311 attrbytes += NFSX_UNSIGNED; 2312 } else { 2313 nfsm_chain_add_32(error, nmc, NFS4_TIME_SET_TO_CLIENT); 2314 nfsm_chain_add_64(error, nmc, vap->va_access_time.tv_sec); 2315 nfsm_chain_add_32(error, nmc, vap->va_access_time.tv_nsec); 2316 attrbytes += 4*NFSX_UNSIGNED; 2317 } 2318 } 2319 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_BACKUP)) { 2320 nfsm_chain_add_64(error, nmc, vap->va_backup_time.tv_sec); 2321 nfsm_chain_add_32(error, nmc, vap->va_backup_time.tv_nsec); 2322 attrbytes += 3*NFSX_UNSIGNED; 2323 } 2324 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_CREATE)) { 2325 nfsm_chain_add_64(error, nmc, vap->va_create_time.tv_sec); 2326 nfsm_chain_add_32(error, nmc, vap->va_create_time.tv_nsec); 2327 attrbytes += 3*NFSX_UNSIGNED; 2328 } 2329 if (NFS_BITMAP_ISSET(bitmap, NFS_FATTR_TIME_MODIFY_SET)) { 2330 if (vap->va_vaflags & VA_UTIMES_NULL) { 2331 nfsm_chain_add_32(error, nmc, NFS4_TIME_SET_TO_SERVER); 2332 attrbytes += NFSX_UNSIGNED; 2333 } else { 2334 nfsm_chain_add_32(error, nmc, NFS4_TIME_SET_TO_CLIENT); 2335 nfsm_chain_add_64(error, nmc, vap->va_modify_time.tv_sec); 2336 nfsm_chain_add_32(error, nmc, vap->va_modify_time.tv_nsec); 2337 attrbytes += 4*NFSX_UNSIGNED; 2338 } 2339 } 2340 nfsmout_if(error); 2341 /* Now, set the attribute data length */ 2342 *pattrbytes = txdr_unsigned(attrbytes); 2343nfsmout: 2344 if (s && (s != sbuf)) 2345 FREE(s, M_TEMP); 2346 return (error); 2347} 2348 2349/* 2350 * Got the given error and need to start recovery (if not already started). 2351 * Note: nmp must be locked! 2352 */ 2353void 2354nfs_need_recover(struct nfsmount *nmp, int error) 2355{ 2356 int wake = !(nmp->nm_state & NFSSTA_RECOVER); 2357 2358 nmp->nm_state |= NFSSTA_RECOVER; 2359 if ((error == NFSERR_ADMIN_REVOKED) || 2360 (error == NFSERR_EXPIRED) || 2361 (error == NFSERR_STALE_CLIENTID)) 2362 nmp->nm_state |= NFSSTA_RECOVER_EXPIRED; 2363 if (wake) 2364 nfs_mount_sock_thread_wake(nmp); 2365} 2366 2367/* 2368 * After recovery due to state expiry, check each node and 2369 * drop any lingering delegation we thought we had. 2370 * 2371 * If a node has an open that is not lost and is not marked 2372 * for reopen, then we hold onto any delegation because it is 2373 * likely newly-granted. 2374 */ 2375static void 2376nfs4_expired_check_delegation(nfsnode_t np, vfs_context_t ctx) 2377{ 2378 struct nfsmount *nmp = NFSTONMP(np); 2379 struct nfs_open_file *nofp; 2380 int drop = 1; 2381 2382 if ((np->n_flag & NREVOKE) || !(np->n_openflags & N_DELEG_MASK)) 2383 return; 2384 2385 lck_mtx_lock(&np->n_openlock); 2386 2387 TAILQ_FOREACH(nofp, &np->n_opens, nof_link) { 2388 if (!nofp->nof_opencnt) 2389 continue; 2390 if (nofp->nof_flags & NFS_OPEN_FILE_LOST) 2391 continue; 2392 if (nofp->nof_flags & NFS_OPEN_FILE_REOPEN) 2393 continue; 2394 /* we have an open that is not lost and not marked for reopen */ 2395 // XXX print out what's keeping this node from dropping the delegation. 2396 NP(nofp->nof_np, "nfs4_expired_check_delegation: !drop: opencnt %d flags 0x%x access %d %d mmap %d %d", 2397 nofp->nof_opencnt, nofp->nof_flags, 2398 nofp->nof_access, nofp->nof_deny, 2399 nofp->nof_mmap_access, nofp->nof_mmap_deny); 2400 drop = 0; 2401 break; 2402 } 2403 2404 if (drop) { 2405 /* need to drop a delegation */ 2406 if (np->n_dreturn.tqe_next != NFSNOLIST) { 2407 /* remove this node from the delegation return list */ 2408 lck_mtx_lock(&nmp->nm_lock); 2409 if (np->n_dreturn.tqe_next != NFSNOLIST) { 2410 TAILQ_REMOVE(&nmp->nm_dreturnq, np, n_dreturn); 2411 np->n_dreturn.tqe_next = NFSNOLIST; 2412 } 2413 lck_mtx_unlock(&nmp->nm_lock); 2414 } 2415 if (np->n_openflags & N_DELEG_MASK) { 2416 np->n_openflags &= ~N_DELEG_MASK; 2417 lck_mtx_lock(&nmp->nm_lock); 2418 if (np->n_dlink.tqe_next != NFSNOLIST) { 2419 TAILQ_REMOVE(&nmp->nm_delegations, np, n_dlink); 2420 np->n_dlink.tqe_next = NFSNOLIST; 2421 } 2422 lck_mtx_unlock(&nmp->nm_lock); 2423 nfs4_delegreturn_rpc(nmp, np->n_fhp, np->n_fhsize, &np->n_dstateid, 2424 0, vfs_context_thread(ctx), vfs_context_ucred(ctx)); 2425 } 2426 } 2427 2428 lck_mtx_unlock(&np->n_openlock); 2429} 2430 2431/* 2432 * Recover state for an NFS mount. 2433 * 2434 * Iterates over all open files, reclaiming opens and lock state. 2435 */ 2436void 2437nfs_recover(struct nfsmount *nmp) 2438{ 2439 struct timespec ts = { 1, 0 }; 2440 int error, lost, reopen; 2441 struct nfs_open_owner *noop; 2442 struct nfs_open_file *nofp; 2443 struct nfs_file_lock *nflp, *nextnflp; 2444 struct nfs_lock_owner *nlop; 2445 thread_t thd = current_thread(); 2446 nfsnode_t np, nextnp; 2447 struct timeval now; 2448 2449restart: 2450 error = 0; 2451 lck_mtx_lock(&nmp->nm_lock); 2452 /* 2453 * First, wait for the state inuse count to go to zero so 2454 * we know there are no state operations in progress. 2455 */ 2456 do { 2457 if ((error = nfs_sigintr(nmp, NULL, NULL, 1))) 2458 break; 2459 if (!(nmp->nm_sockflags & NMSOCK_READY)) 2460 error = EPIPE; 2461 if (nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)) 2462 error = ENXIO; 2463 if (nmp->nm_sockflags & NMSOCK_UNMOUNT) 2464 error = ENXIO; 2465 if (error) 2466 break; 2467 if (nmp->nm_stateinuse) 2468 msleep(&nmp->nm_stateinuse, &nmp->nm_lock, (PZERO-1), "nfsrecoverstartwait", &ts); 2469 } while (nmp->nm_stateinuse); 2470 if (error) { 2471 if (error == EPIPE) 2472 printf("nfs recovery reconnecting for %s, 0x%x\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid); 2473 else 2474 printf("nfs recovery aborted for %s, 0x%x\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid); 2475 lck_mtx_unlock(&nmp->nm_lock); 2476 return; 2477 } 2478 2479 microuptime(&now); 2480 if (now.tv_sec == nmp->nm_recover_start) { 2481 printf("nfs recovery throttled for %s, 0x%x\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid); 2482 lck_mtx_unlock(&nmp->nm_lock); 2483 tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz); 2484 goto restart; 2485 } 2486 nmp->nm_recover_start = now.tv_sec; 2487 if (++nmp->nm_stategenid == 0) 2488 ++nmp->nm_stategenid; 2489 printf("nfs recovery started for %s, 0x%x\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid); 2490 lck_mtx_unlock(&nmp->nm_lock); 2491 2492 /* for each open owner... */ 2493 TAILQ_FOREACH(noop, &nmp->nm_open_owners, noo_link) { 2494 /* for each of its opens... */ 2495 TAILQ_FOREACH(nofp, &noop->noo_opens, nof_oolink) { 2496 if (!nofp->nof_access || (nofp->nof_flags & NFS_OPEN_FILE_LOST) || (nofp->nof_np->n_flag & NREVOKE)) 2497 continue; 2498 lost = reopen = 0; 2499 /* for NFSv2/v3, just skip straight to lock reclaim */ 2500 if (nmp->nm_vers < NFS_VER4) 2501 goto reclaim_locks; 2502 if (nofp->nof_rw_drw) 2503 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_BOTH, NFS_OPEN_SHARE_DENY_BOTH); 2504 if (!error && nofp->nof_w_drw) 2505 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_WRITE, NFS_OPEN_SHARE_DENY_BOTH); 2506 if (!error && nofp->nof_r_drw) 2507 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_READ, NFS_OPEN_SHARE_DENY_BOTH); 2508 if (!error && nofp->nof_rw_dw) 2509 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_BOTH, NFS_OPEN_SHARE_DENY_WRITE); 2510 if (!error && nofp->nof_w_dw) 2511 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_WRITE, NFS_OPEN_SHARE_DENY_WRITE); 2512 if (!error && nofp->nof_r_dw) 2513 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_READ, NFS_OPEN_SHARE_DENY_WRITE); 2514 /* 2515 * deny-none opens with no locks can just be reopened (later) if reclaim fails. 2516 */ 2517 if (!error && nofp->nof_rw) { 2518 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_BOTH, NFS_OPEN_SHARE_DENY_NONE); 2519 if ((error == NFSERR_ADMIN_REVOKED) || (error == NFSERR_EXPIRED) || (error == NFSERR_NO_GRACE)) { 2520 reopen = error; 2521 error = 0; 2522 } 2523 } 2524 if (!error && !reopen && nofp->nof_w) { 2525 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_WRITE, NFS_OPEN_SHARE_DENY_NONE); 2526 if ((error == NFSERR_ADMIN_REVOKED) || (error == NFSERR_EXPIRED) || (error == NFSERR_NO_GRACE)) { 2527 reopen = error; 2528 error = 0; 2529 } 2530 } 2531 if (!error && !reopen && nofp->nof_r) { 2532 error = nfs4_open_reclaim_rpc(nofp, NFS_OPEN_SHARE_ACCESS_READ, NFS_OPEN_SHARE_DENY_NONE); 2533 if ((error == NFSERR_ADMIN_REVOKED) || (error == NFSERR_EXPIRED) || (error == NFSERR_NO_GRACE)) { 2534 reopen = error; 2535 error = 0; 2536 } 2537 } 2538 2539 /* 2540 * If we hold delegated state but we don't have any non-delegated opens, 2541 * then we should attempt to claim that state now (but don't return the 2542 * delegation unless asked to). 2543 */ 2544 if ((nofp->nof_d_rw_drw || nofp->nof_d_w_drw || nofp->nof_d_r_drw || 2545 nofp->nof_d_rw_dw || nofp->nof_d_w_dw || nofp->nof_d_r_dw || 2546 nofp->nof_d_rw || nofp->nof_d_w || nofp->nof_d_r) && 2547 (!nofp->nof_rw_drw && !nofp->nof_w_drw && !nofp->nof_r_drw && 2548 !nofp->nof_rw_dw && !nofp->nof_w_dw && !nofp->nof_r_dw && 2549 !nofp->nof_rw && !nofp->nof_w && !nofp->nof_r)) { 2550 if (!error && !nfs_open_state_set_busy(nofp->nof_np, NULL)) { 2551 error = nfs4_claim_delegated_state_for_node(nofp->nof_np, R_RECOVER); 2552 if (!error && (nofp->nof_flags & NFS_OPEN_FILE_REOPEN)) 2553 reopen = EAGAIN; 2554 nfs_open_state_clear_busy(nofp->nof_np); 2555 /* if claim didn't go well, we may need to return delegation now */ 2556 if (nofp->nof_np->n_openflags & N_DELEG_RETURN) { 2557 nfs4_delegation_return(nofp->nof_np, R_RECOVER, thd, noop->noo_cred); 2558 if (!(nmp->nm_sockflags & NMSOCK_READY)) 2559 error = ETIMEDOUT; /* looks like we need a reconnect */ 2560 } 2561 } 2562 } 2563 2564 /* 2565 * Handle any issue claiming open state. 2566 * Potential reopens need to first confirm that there are no locks. 2567 */ 2568 if (error || reopen) { 2569 /* restart recovery? */ 2570 if ((error == ETIMEDOUT) || nfs_mount_state_error_should_restart(error)) { 2571 if (error == ETIMEDOUT) 2572 nfs_need_reconnect(nmp); 2573 tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz); 2574 printf("nfs recovery restarting for %s, 0x%x, error %d\n", 2575 vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error); 2576 goto restart; 2577 } 2578 if (reopen && (nfs_check_for_locks(noop, nofp) == 0)) { 2579 /* just reopen the file on next access */ 2580 NP(nofp->nof_np, "nfs_recover: %d, need reopen for %d %p 0x%x", reopen, 2581 kauth_cred_getuid(noop->noo_cred), nofp->nof_np, nofp->nof_np->n_flag); 2582 lck_mtx_lock(&nofp->nof_lock); 2583 nofp->nof_flags |= NFS_OPEN_FILE_REOPEN; 2584 lck_mtx_unlock(&nofp->nof_lock); 2585 } else { 2586 /* open file state lost */ 2587 if (reopen) 2588 NP(nofp->nof_np, "nfs_recover: %d, can't reopen because of locks %d %p", reopen, 2589 kauth_cred_getuid(noop->noo_cred), nofp->nof_np); 2590 lost = 1; 2591 error = 0; 2592 reopen = 0; 2593 } 2594 } else { 2595 /* no error, so make sure the reopen flag isn't set */ 2596 lck_mtx_lock(&nofp->nof_lock); 2597 nofp->nof_flags &= ~NFS_OPEN_FILE_REOPEN; 2598 lck_mtx_unlock(&nofp->nof_lock); 2599 } 2600 2601 /* 2602 * Scan this node's lock owner list for entries with this open owner, 2603 * then walk the lock owner's held lock list recovering each lock. 2604 */ 2605reclaim_locks: 2606 TAILQ_FOREACH(nlop, &nofp->nof_np->n_lock_owners, nlo_link) { 2607 if (lost || reopen) 2608 break; 2609 if (nlop->nlo_open_owner != noop) 2610 continue; 2611 TAILQ_FOREACH_SAFE(nflp, &nlop->nlo_locks, nfl_lolink, nextnflp) { 2612 /* skip dead & blocked lock requests (shouldn't be any in the held lock list) */ 2613 if (nflp->nfl_flags & (NFS_FILE_LOCK_DEAD|NFS_FILE_LOCK_BLOCKED)) 2614 continue; 2615 /* skip delegated locks */ 2616 if (nflp->nfl_flags & NFS_FILE_LOCK_DELEGATED) 2617 continue; 2618 error = nmp->nm_funcs->nf_setlock_rpc(nofp->nof_np, nofp, nflp, 1, R_RECOVER, thd, noop->noo_cred); 2619 if (error) 2620 NP(nofp->nof_np, "nfs: lock reclaim (0x%llx, 0x%llx) %s %d", 2621 nflp->nfl_start, nflp->nfl_end, 2622 error ? "failed" : "succeeded", error); 2623 if (!error) 2624 continue; 2625 /* restart recovery? */ 2626 if ((error == ETIMEDOUT) || nfs_mount_state_error_should_restart(error)) { 2627 if (error == ETIMEDOUT) 2628 nfs_need_reconnect(nmp); 2629 tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz); 2630 printf("nfs recovery restarting for %s, 0x%x, error %d\n", 2631 vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error); 2632 goto restart; 2633 } 2634 /* lock state lost - attempt to close file */ 2635 lost = 1; 2636 error = 0; 2637 break; 2638 } 2639 } 2640 2641 /* 2642 * If we've determined that we need to reopen the file then we probably 2643 * didn't receive any delegation we think we hold. We should attempt to 2644 * return that delegation (and claim any delegated state). 2645 * 2646 * If we hold a delegation that is marked for return, then we should 2647 * return it now. 2648 */ 2649 if ((nofp->nof_np->n_openflags & N_DELEG_RETURN) || 2650 (reopen && (nofp->nof_np->n_openflags & N_DELEG_MASK))) { 2651 nfs4_delegation_return(nofp->nof_np, R_RECOVER, thd, noop->noo_cred); 2652 if (!(nmp->nm_sockflags & NMSOCK_READY)) { 2653 /* looks like we need a reconnect */ 2654 tsleep(nfs_recover, (PZERO-1), "nfsrecoverrestart", hz); 2655 printf("nfs recovery restarting for %s, 0x%x, error %d\n", 2656 vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error); 2657 goto restart; 2658 } 2659 } 2660 2661 if (lost) { 2662 /* revoke open file state */ 2663 NP(nofp->nof_np, "nfs_recover: state lost for %d %p 0x%x", 2664 kauth_cred_getuid(noop->noo_cred), nofp->nof_np, nofp->nof_np->n_flag); 2665 nfs_revoke_open_state_for_node(nofp->nof_np); 2666 } 2667 } 2668 } 2669 2670 if (!error) { 2671 /* If state expired, make sure we're not holding onto any stale delegations */ 2672 lck_mtx_lock(&nmp->nm_lock); 2673 if ((nmp->nm_vers >= NFS_VER4) && (nmp->nm_state & NFSSTA_RECOVER_EXPIRED)) { 2674recheckdeleg: 2675 TAILQ_FOREACH_SAFE(np, &nmp->nm_delegations, n_dlink, nextnp) { 2676 lck_mtx_unlock(&nmp->nm_lock); 2677 nfs4_expired_check_delegation(np, vfs_context_kernel()); 2678 lck_mtx_lock(&nmp->nm_lock); 2679 if (nextnp == NFSNOLIST) 2680 goto recheckdeleg; 2681 } 2682 } 2683 nmp->nm_state &= ~(NFSSTA_RECOVER|NFSSTA_RECOVER_EXPIRED); 2684 wakeup(&nmp->nm_state); 2685 printf("nfs recovery completed for %s, 0x%x\n", 2686 vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid); 2687 lck_mtx_unlock(&nmp->nm_lock); 2688 } else { 2689 printf("nfs recovery failed for %s, 0x%x, error %d\n", 2690 vfs_statfs(nmp->nm_mountp)->f_mntfromname, nmp->nm_stategenid, error); 2691 } 2692} 2693