1/* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35#include <stdint.h> 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/kernel.h> 39#include <sys/malloc.h> 40#include <sys/proc.h> 41#include <sys/lock.h> 42#include <sys/vnode.h> 43#include <sys/xattr.h> 44#include <sys/kpi_mbuf.h> 45#include <sys/mount.h> 46 47#include <sys/kauth.h> 48 49#include <sys/smb_apple.h> 50#include <sys/msfscc.h> 51 52#include <netsmb/smb.h> 53#include <netsmb/smb_2.h> 54#include <netsmb/smb_subr.h> 55#include <netsmb/smb_rq.h> 56#include <netsmb/smb_rq_2.h> 57#include <netsmb/smb_conn.h> 58#include <netsmb/smb_conn_2.h> 59 60#include <smbfs/smbfs.h> 61#include <smbfs/smbfs_node.h> 62#include <smbfs/smbfs_subr.h> 63#include <smbfs/smbfs_subr_2.h> 64#include <smbfs/smbfs_lockf.h> 65#include <netsmb/smb_converter.h> 66#include <smbfs/smbfs_security.h> 67#include <smbclient/ntstatus.h> 68#include <libkern/crypto/md5.h> 69 70#define SMBFS_DELETE_PREFIX ".smbdeleteAAA" 71#define MAKE_DELETED_NAME(NAME, SIZE, FID) \ 72(void) snprintf((NAME), SIZE, "%s%llx", SMBFS_DELETE_PREFIX, (FID)) 73 74/* 75 * Lack of inode numbers leads us to the problem of generating them. 76 * Partially this problem can be solved by having a dir/file cache 77 * with inode numbers generated from the incremented by one counter. 78 * However this way will require too much kernel memory, gives all 79 * sorts of locking and consistency problems, not to mention counter overflows. 80 * So, I'm decided to use a hash function to generate pseudo random (and unique) 81 * inode numbers. 82 * 83 * SMB 2/3 - if server supports File IDs, then use inode number from the server 84 * and never call this function. 85 * SMB 1 and SMB 2/3 servers that do not support File IDs still hashes the 86 * name and thus still calls this function. 87 */ 88uint64_t 89smbfs_getino(struct smbnode *dnp, const char *name, size_t nmlen) 90{ 91 uint64_t ino; 92 93 ino = dnp->n_ino + smbfs_hash(NULL, 0, name, nmlen); 94 if (ino <= SMBFS_ROOT_INO) 95 ino += 3; 96 return ino; 97} 98 99/* 100 * The calling routine must hold a reference on the share 101 * 102 * [MS-CIFS] 103 * This command is used to explicitly lock and/or unlock a contiguous range of 104 * bytes in a regular file. More than one non-overlapping byte range MAY be 105 * locked and/or unlocked on an open file. Locks prevent attempts to lock, read, 106 * or write the locked portion of the file by other processes using a separate 107 * file handle (FID). Any process using the same FID specified in the request 108 * that obtained the lock has access to the locked bytes. 109 * 110 * So we handle the pid issue at our level, curently that code is broken and 111 * needs to be fixed. We should fix that as part of <rdar://problem/7946972>. 112 * We need to hold on to the local users pid and not the network user pid in 113 * the byterange locking list. 114 * 115 * Since we always use the fid that open the file to take the lock the network 116 * code should always work, even if we change the network pid. 117 */ 118int 119smb1fs_smb_lock(struct smb_share *share, int op, SMBFID fid, uint32_t pid, 120 off_t start, uint64_t len, uint32_t timo, vfs_context_t context) 121{ 122#pragma unused(pid) 123 struct smb_rq rq, *rqp = &rq; 124 struct mbchain *mbp; 125 u_char ltype = 0; 126 int error; 127 uint16_t smb1_fid = (uint16_t) fid; /* cast to SMB 1 fid */ 128 129 if (op == SMB_LOCK_SHARED) 130 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 131 /* Do they support large offsets */ 132 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_LARGE_FILES) 133 ltype |= SMB_LOCKING_ANDX_LARGE_FILES; 134 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_LOCKING_ANDX, 0, context); 135 if (error) 136 return error; 137 smb_rq_getrequest(rqp, &mbp); 138 smb_rq_wstart(rqp); 139 mb_put_uint8(mbp, 0xff); /* secondary command */ 140 mb_put_uint8(mbp, 0); /* MBZ */ 141 mb_put_uint16le(mbp, 0); 142 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 143 mb_put_uint8(mbp, ltype); /* locktype */ 144 mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 145 mb_put_uint32le(mbp, timo); /* 0 nowait, -1 infinite wait */ 146 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 147 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 148 smb_rq_wend(rqp); 149 smb_rq_bstart(rqp); 150 /* Always keep it in sync with the pid in the smb header */ 151 mb_put_uint16le(mbp, rqp->sr_pidLow); 152 if (ltype & SMB_LOCKING_ANDX_LARGE_FILES) { 153 mb_put_uint16le(mbp, 0); /* pad */ 154 mb_put_uint32le(mbp, (uint32_t)(start >> 32)); /* OffsetHigh */ 155 mb_put_uint32le(mbp, (uint32_t)(start & 0xffffffff)); /* OffsetLow */ 156 mb_put_uint32le(mbp, (uint32_t)(len >> 32)); /* LengthHigh */ 157 mb_put_uint32le(mbp, (uint32_t)(len & 0xffffffff)); /* LengthLow */ 158 } else { 159 mb_put_uint32le(mbp, (uint32_t)(start & 0xffffffff)); 160 mb_put_uint32le(mbp, (uint32_t)(len & 0xffffffff)); 161 } 162 smb_rq_bend(rqp); 163 error = smb_rq_simple(rqp); 164 /* 165 * This may seem strange, but both Windows and Samba do the following: 166 * 167 * Lock a region, try to lock it again you get STATUS_LOCK_NOT_GRANTED, 168 * try to lock it a third time you get STATUS_FILE_LOCK_CONFLICT. Seems 169 * the first lock error is always STATUS_LOCK_NOT_GRANTED and the second 170 * time you get a STATUS_FILE_LOCK_CONFLICT. 171 * 172 * For IO they always return STATUS_FILE_LOCK_CONFLICT, which we convert 173 * to EIO, becasue there are multiple IO routines and only one lock routine. 174 * So we want this to be EACCES in the lock cases. So we need to convert 175 * that error here. 176 * 177 */ 178 if ((error == EIO) && (rqp->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS)) { 179 if (rqp->sr_ntstatus == STATUS_FILE_LOCK_CONFLICT) 180 error = EACCES; 181 } 182 smb_rq_done(rqp); 183 return error; 184} 185 186/* 187 * The calling routine must hold a reference on the share 188 */ 189int 190smb1fs_smb_qpathinfo(struct smb_share *share, 191 struct smbnode *np, 192 struct smbfattr *fap, 193 short infolevel, 194 const char **namep, 195 size_t *nmlenp, 196 vfs_context_t context) 197{ 198 struct smb_t2rq *t2p; 199 int error; 200 struct mbchain *mbp; 201 struct mdchain *mdp; 202 uint64_t llint; 203 uint32_t size, dattr, eaSize; 204 const char *name = (namep ? *namep : NULL); 205 size_t nmlen = (nmlenp ? *nmlenp : 0); 206 char *ntwrkname = NULL; 207 char *filename; 208 uint8_t sep = '\\'; 209 char *snamep = NULL; 210 211 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_PATH_INFORMATION, 1, context, &t2p); 212 if (error) 213 return error; 214 mbp = &t2p->t2_tparam; 215 mb_init(mbp); 216 mb_put_uint16le(mbp, infolevel); 217 mb_put_uint32le(mbp, 0); 218 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 219 if ((np->n_vnode) && vnode_isnamedstream(np->n_vnode)) { 220 DBG_ASSERT((namep == NULL)); 221 222 lck_rw_lock_shared(&np->n_name_rwlock); 223 snamep = smb_strndup(np->n_sname, np->n_snmlen); 224 name = snamep; 225 lck_rw_unlock_shared(&np->n_name_rwlock); 226 227 nmlen = np->n_snmlen; 228 sep = ':'; 229 } 230 error = smbfs_fullpath(mbp, np, name, &nmlen, UTF_SFM_CONVERSIONS, 231 SMB_UNICODE_STRINGS(SSTOVC(share)), sep); 232 233 if (error) { 234 smb_t2_done(t2p); 235 goto done; 236 } 237 t2p->t2_maxpcount = 2; 238 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 239 error = smb_t2_request(t2p); 240 if (error) { 241 smb_t2_done(t2p); 242 goto done; 243 } 244 mdp = &t2p->t2_rdata; 245 /* 246 * At this point md_cur and md_top have the same value. Now all the md_get 247 * routines will will check for null, but just to be safe we check here. 248 */ 249 if (mdp->md_cur == NULL) { 250 SMBWARNING("Parsing error reading the message\n"); 251 smb_t2_done(t2p); 252 error = EBADRPC; 253 goto done; 254 } 255 switch (infolevel) { 256 case SMB_QFILEINFO_ALL_INFO: 257 md_get_uint64le(mdp, &llint); /* creation time */ 258 if (llint) { 259 smb_time_NT2local(llint, &fap->fa_crtime); 260 } 261 md_get_uint64le(mdp, &llint); 262 if (llint) { /* access time */ 263 smb_time_NT2local(llint, &fap->fa_atime); 264 } 265 md_get_uint64le(mdp, &llint); 266 if (llint) { /* write time */ 267 smb_time_NT2local(llint, &fap->fa_mtime); 268 } 269 md_get_uint64le(mdp, &llint); 270 if (llint) { /* change time */ 271 smb_time_NT2local(llint, &fap->fa_chtime); 272 } 273 /* 274 * SNIA CIFS Technical Reference is wrong, this should be 275 * a ULONG 276 */ 277 md_get_uint32le(mdp, &dattr); /* Attributes */ 278 fap->fa_attr = dattr; 279 /* 280 * Because of the Steve/Conrad Symlinks we can never be completely 281 * sure that we have the correct vnode type if its a file. For 282 * directories we always know the correct information. 283 */ 284 if (fap->fa_attr & SMB_EFA_DIRECTORY) { 285 fap->fa_valid_mask |= FA_VTYPE_VALID; 286 } 287 fap->fa_vtype = (fap->fa_attr & SMB_EFA_DIRECTORY) ? VDIR : VREG; 288 289 /* 290 * SNIA CIFS Technical Reference is wrong, this should be 291 * a ULONG PAD 292 */ 293 md_get_uint32le(mdp, NULL); 294 295 md_get_uint64le(mdp, &llint); /* allocation size */ 296 fap->fa_data_alloc = llint; 297 298 md_get_uint64le(mdp, &llint); /* file size */ 299 fap->fa_size = llint; 300 301 md_get_uint32le(mdp, NULL); /* Number of hard links */ 302 md_get_uint8(mdp, NULL); /* Delete Pending */ 303 error = md_get_uint8(mdp, NULL); /* Directory or File */ 304 if (error) 305 goto bad; 306 fap->fa_ino = np->n_ino; 307 /* 308 * At this point the SNIA CIFS Technical Reference is wrong. 309 * It should have the following: 310 * USHORT Unknown; 311 * ULONG EASize; 312 * ULONG PathNameLength; 313 * STRING FullPath; 314 * We need to be carefull just in case someone followed the 315 * Technical Reference. 316 */ 317 md_get_uint16(mdp, NULL); /* Unknown */ 318 /* 319 * Confirmed from MS: 320 * When the attribute has the Reparse Point bit set then the EASize 321 * contains the reparse tag info. This behavior is consistent for 322 * Full, Both, FullId, or BothId query dir calls. It will pack the 323 * reparse tag into the EaSize value if ATTRIBUTE_REPARSE_POINT is set. 324 * I verified with local MS Engineers, and they also checking to make 325 * sure the behavior is covered in MS-FSA. 326 * 327 * EAs and reparse points cannot both be in a file at the same 328 * time. We return different information for each case. 329 * 330 * NOTE: This is not true for this call (SMB_QFILEINFO_ALL_INFO), they 331 * return the reparse bit but the eaSize size is always zero? 332 */ 333 md_get_uint32le(mdp, &eaSize); /* extended attributes size */ 334 335 /* 336 * We don't care about the name, so we can skip getting it. 337 * 338 * NOTE: When accessing the root node the name may not be what you would 339 * expect. Windows will return a back slash if the item being shared is 340 * a drive and in all other cases the name of the directory being shared. 341 * We never ask for the name in the root node case so this should never 342 * be an issue. 343 */ 344 if (namep == NULL) 345 break; /* We are done */ 346 347 error = md_get_uint32le(mdp, &size); /* Path name lengh */ 348 if (error) 349 goto bad; 350 /* 351 * Make sure it is something in reason. Don't allocate it, 352 * if it doesn't make sense. 353 */ 354 if (size <= 0 || size >= t2p->t2_maxdcount) { 355 error = EINVAL; 356 goto bad; 357 } 358 /* 359 * Since the SNIA CIFS Technical Reference is wrong, we would 360 * like to do as much checking as possible. The whole message 361 * should be the file name length + 72 bytes. If we get 362 * something bigger print it out. In the worst case situation 363 * we would end up with a bogus name. We have found that the 364 * Snap servers follows the Technical Reference. So in their 365 * case the file name length is bogus. This is not a problem 366 * because they always return zero in that location. So this 367 * would error out above. NT returns the correct information 368 * but does put 4 bytes of zero padd at the end. So now add 369 * 4 bytes to our check. 370 */ 371 m_fixhdr(mdp->md_top); 372 if (mbuf_pkthdr_len(mdp->md_top) > (size+72+4)) { 373 SMBERROR("SMB_QFILEINFO_ALL_INFO: wrong size %ld\n", 374 mbuf_pkthdr_len((mbuf_t)mdp->md_top)); 375 } 376 377 nmlen = size; 378 379 /* Since this is a full path only check SMB_MAXFNAMELEN length 380 * until we get the component. We just allocate what we need 381 * need here. 382 */ 383 SMB_MALLOC(ntwrkname, char *, nmlen, M_SMBFSDATA, M_WAITOK); 384 if (ntwrkname == NULL) 385 error = ENOMEM; 386 else 387 error = md_get_mem(mdp, (void *)ntwrkname, nmlen, 388 MB_MSYSTEM); /* Full path name */ 389 390 if (error) 391 goto bad; 392 393 /* 394 * Here is the problem. They return the full path when we only 395 * need the last component. So we need to find the last back 396 * slash. So first remove any trailing nulls from the path. 397 * Now start at the end of the path name and work our way back 398 * stopping when we find the first back slash. For UTF-16 make 399 * sure there is a null byte after the back slash. 400 */ 401 if (SMB_UNICODE_STRINGS(SSTOVC(share))) { 402 /* Don't count any trailing nulls in the name. */ 403 if (nmlen > 1 && ntwrkname[nmlen - 1] == 0 && 404 ntwrkname[nmlen - 2] == 0) 405 nmlen -= 2; 406 /* 407 * Now get the file name. We need to start at the end 408 * and work our way backwards. 409 */ 410 if (nmlen > 1) 411 filename = &ntwrkname[nmlen-2]; 412 else filename = ntwrkname; 413 /* Work backwards until we reach the begining */ 414 while (filename > ntwrkname) { 415 if ((*filename == 0x5c) && (*(filename+1) == 0x00)) 416 break; 417 filename -= 2; 418 } 419 /* 420 * Found a back slash move passed it and now we have 421 * the real file name. 422 */ 423 if ((*filename == 0x5c) && (*(filename+1) == 0x00)) 424 filename += 2; 425 } else { 426 /* Don't count any trailing null in the name. */ 427 if (nmlen && ntwrkname[nmlen - 1] == 0) 428 nmlen--; 429 /* 430 * Now get the file name. We need to start at the end 431 * and work our way bacckwards. 432 */ 433 if (nmlen) 434 filename = &ntwrkname[nmlen-1]; 435 else filename = ntwrkname; 436 /* Work backwards until we reach the begining */ 437 while ((filename > ntwrkname) && (*filename != 0x5c)) 438 filename--; 439 /* 440 * Found a back slash move passed it and now we have 441 * the real file name. 442 */ 443 if (*filename == 0x5c) 444 filename++; 445 } 446 /* Reset the name length */ 447 nmlen = &ntwrkname[nmlen] - filename; 448 /* Convert the name to a UTF-8 string */ 449 filename = smbfs_ntwrkname_tolocal((const char *)filename, &nmlen, 450 SMB_UNICODE_STRINGS(SSTOVC(share))); 451 /* Done with the network buffer so free it */ 452 SMB_FREE(ntwrkname, M_SMBFSDATA); 453 /* Now reasign it so we free the correct buffer */ 454 ntwrkname = filename; 455 456 if (ntwrkname == NULL) { 457 error = EINVAL; 458 SMBERROR("smbfs_ntwrkname_tolocal return NULL\n"); 459 goto bad; 460 } 461 if (nmlen > SMB_MAXFNAMELEN) { 462 error = EINVAL; 463 SMBERROR("Filename %s nmlen = %ld\n", ntwrkname, nmlen); 464 goto bad; 465 } 466 *namep = smb_strndup(filename, nmlen); 467 if (nmlenp) /* Return the name length */ 468 *nmlenp = nmlen; 469 if (*namep && nmlenp) /* SMB 1 only. Create the inode number */ 470 fap->fa_ino = smbfs_getino(np, *namep, *nmlenp); 471bad: 472 /* Free the buffer that holds the name from the network */ 473 SMB_FREE(ntwrkname, M_SMBFSDATA); 474 break; 475 case SMB_QFILEINFO_UNIX_INFO2: 476 477 md_get_uint64le(mdp, &llint); /* file size */ 478 fap->fa_size = llint; 479 480 md_get_uint64le(mdp, &llint); /* allocation size */ 481 fap->fa_data_alloc = llint; 482 483 md_get_uint64le(mdp, &llint); /* change time */ 484 if (llint) 485 smb_time_NT2local(llint, &fap->fa_chtime); 486 487 md_get_uint64le(mdp, &llint); /* access time */ 488 if (llint) 489 smb_time_NT2local(llint, &fap->fa_atime); 490 491 md_get_uint64le(mdp, &llint); /* write time */ 492 if (llint) 493 smb_time_NT2local(llint, &fap->fa_mtime); 494 495 md_get_uint64le(mdp, &llint); /* Numeric user id for the owner */ 496 fap->fa_uid = llint; 497 498 md_get_uint64le(mdp, &llint); /* Numeric group id for the owner */ 499 fap->fa_gid = llint; 500 501 md_get_uint32le(mdp, &dattr); /* Enumeration specifying the file type, st_mode */ 502 fap->fa_valid_mask |= FA_VTYPE_VALID; 503 /* Make sure the dos attributes are correct */ 504 if (dattr & EXT_UNIX_DIR) { 505 fap->fa_attr |= SMB_EFA_DIRECTORY; 506 fap->fa_vtype = VDIR; 507 } else if (dattr & EXT_UNIX_SYMLINK) { 508 fap->fa_vtype = VLNK; 509 } else { 510 fap->fa_vtype = VREG; 511 } 512 513 md_get_uint64le(mdp, &llint); /* Major device number if type is device */ 514 md_get_uint64le(mdp, &llint); /* Minor device number if type is device */ 515 md_get_uint64le(mdp, &llint); /* This is a server-assigned unique id */ 516 md_get_uint64le(mdp, &llint); /* Standard UNIX permissions */ 517 fap->fa_permissions = llint; 518 fap->fa_valid_mask |= FA_UNIX_MODES_VALID; 519 md_get_uint64le(mdp, &llint); /* Number of hard link */ 520 fap->fa_nlinks = llint; 521 522 md_get_uint64le(mdp, &llint); /* creation time */ 523 if (llint) 524 smb_time_NT2local(llint, &fap->fa_crtime); 525 526 md_get_uint32le(mdp, &dattr); /* File flags enumeration */ 527 error = md_get_uint32le(mdp, &fap->fa_flags_mask); /* Mask of valid flags */ 528 if (error) 529 break; 530 /* Make sure the dos attributes are correct */ 531 if (fap->fa_flags_mask & EXT_HIDDEN) { 532 if (dattr & EXT_HIDDEN) 533 fap->fa_attr |= SMB_EFA_HIDDEN; 534 else 535 fap->fa_attr &= ~SMB_EFA_HIDDEN; 536 } 537 if (fap->fa_flags_mask & EXT_IMMUTABLE) { 538 if (dattr & EXT_IMMUTABLE) 539 fap->fa_attr |= SMB_EFA_RDONLY; 540 else 541 fap->fa_attr &= ~SMB_EFA_RDONLY; 542 } 543 if (fap->fa_flags_mask & SMB_EFA_ARCHIVE) { 544 if (dattr & EXT_DO_NOT_BACKUP) 545 fap->fa_attr &= ~SMB_EFA_ARCHIVE; 546 else 547 fap->fa_attr |= SMB_EFA_ARCHIVE; 548 } 549 fap->fa_unix = TRUE; 550 if (namep == NULL) { 551 fap->fa_ino = np->n_ino; 552 } 553 else { 554 if ((*namep) && nmlenp) { 555 /* np is actually the parent dnp */ 556 fap->fa_ino = smbfs_getino(np, *namep, *nmlenp); 557 } 558 else { 559 /* Should not ever happen */ 560 SMBERROR("Missing namep or nmlenp, so inode left at 0\n"); 561 } 562 } 563 break; 564 default: 565 SMBERROR("unexpected info level %d\n", infolevel); 566 error = EINVAL; 567 break; 568 } 569 smb_t2_done(t2p); 570 571done: 572 if (snamep) { 573 SMB_FREE(snamep, M_SMBSTR); 574 } 575 576 return error; 577} 578 579int 580smbfs_smb_undollardata(const char *fname, char *name, size_t *nmlen, 581 uint32_t *is_data) 582{ 583 char *cp; 584 size_t len = sizeof(SMB_DATASTREAM) - 1; 585 586 /* 587 * Example stream names 588 * ::$DATA 589 * :AFP_AfpInfo:$DATA 590 * :AFP_Resource:$DATA 591 */ 592 593 *is_data = 0; 594 595 /* Sanity check for a stream name */ 596 if (!name) { 597 goto bad; 598 } 599 600 /* Has to be "::$DATA" at a minimum length */ 601 if (*nmlen < len + 1) { 602 goto bad; 603 } 604 605 /* Has to have a leading colon */ 606 if (*name != ':') { 607 goto bad; 608 } 609 610 /* Point to 2nd colon */ 611 cp = &name[*nmlen - len]; 612 613 /* Has to end with $DATA */ 614 if (bcmp(cp, SMB_DATASTREAM, len)) { 615 goto bad; 616 } 617 618 /* Merely the data fork? */ 619 if (*nmlen == (len + 1)) { 620 /* Skip returning it. */ 621 *is_data = 1; 622 return (0); 623 } 624 625 /* We can not return more than 128 bytes */ 626 if ((*nmlen - len) > (XATTR_MAXNAMELEN + 1)) { 627 goto bad; 628 } 629 630 /* 631 * Un-count a colon and the $DATA, then the 632 * 2nd colon is replaced by a terminating null. 633 */ 634 *nmlen -= len; 635 *cp = '\0'; 636 637 /* Skip protected system attrs */ 638 if ((*nmlen >= 17) && (xattr_protected(name + 1))) { 639 return (0); 640 } 641 642 /* 643 * Return the stream name. Examples: 644 * :AFP_AfpInfo 645 * :AFP_Resource 646 */ 647 return (1); 648 649bad: 650 /* 651 * If the name exist then we malloc it so we can print it 652 * out. So just make sure it exist before printing. 653 */ 654 SMBWARNING("file \"%s\" has bad stream \"%s\"\n", fname, (name) ? name : ""); 655 return (0); 656} 657 658/* 659 * smbfs_smb_markfordelete 660 * 661 * We have an open file that they want to delete. This call will tell the 662 * server to delete the file when the last close happens. Currenly we know that 663 * XP, Windows 2000 and Windows 2003 support this call. SAMBA does support the 664 * call, but currently has a bug that prevents it from working. 665 * 666 * The calling routine must hold a reference on the share 667 * 668 */ 669int 670smb1fs_smb_markfordelete(struct smb_share *share, SMBFID fid, 671 vfs_context_t context) 672{ 673 struct smb_t2rq *t2p; 674 struct mbchain *mbp; 675 int error; 676 uint16_t smb1_fid = (uint16_t) fid; /* cast to SMB 1 fid */ 677 678 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_FILE_INFORMATION, 1, 679 context, &t2p); 680 if (error) { 681 return error; 682 } 683 mbp = &t2p->t2_tparam; 684 mb_init(mbp); 685 /* SMB 1 fid in volatile */ 686 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 687 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 688 mb_put_uint16le(mbp, SMB_SFILEINFO_DISPOSITION_INFORMATION); 689 else 690 mb_put_uint16le(mbp, SMB_SFILEINFO_DISPOSITION_INFO); 691 mb_put_uint16le(mbp, 0); 692 mbp = &t2p->t2_tdata; 693 mb_init(mbp); 694 mb_put_uint8(mbp, 1); 695 t2p->t2_maxpcount = 2; 696 t2p->t2_maxdcount = 0; 697 error = smb_t2_request(t2p); 698 smb_t2_done(t2p); 699 return error; 700} 701 702/* 703 * Create the data required for a faked up symbolic link. This is Conrad and Steve 704 * French method for storing and reading symlinks on Window Servers. 705 */ 706static void * 707smbfs_create_windows_symlink_data(const char *target, size_t targetlen, 708 uint32_t *rtlen) 709{ 710 MD5_CTX md5; 711 uint32_t state[4]; 712 uint32_t datalen, filelen; 713 char *wbuf, *wp; 714 int maxwplen; 715 uint32_t targlen = (uint32_t)targetlen; 716 717 datalen = SMB_SYMHDRLEN + targlen; 718 filelen = SMB_SYMLEN; 719 maxwplen = filelen; 720 721 SMB_MALLOC(wbuf, void *, filelen, M_TEMP, M_WAITOK); 722 723 wp = wbuf; 724 bcopy(smb_symmagic, wp, SMB_SYMMAGICLEN); 725 wp += SMB_SYMMAGICLEN; 726 maxwplen -= SMB_SYMMAGICLEN; 727 (void)snprintf(wp, maxwplen, "%04d\n", targlen); 728 wp += SMB_SYMLENLEN; 729 maxwplen -= SMB_SYMLENLEN; 730 MD5Init(&md5); 731 MD5Update(&md5, (unsigned char *)target, targlen); 732 MD5Final((u_char *)state, &md5); 733 (void)snprintf(wp, maxwplen, "%08x%08x%08x%08x\n", htobel(state[0]), 734 htobel(state[1]), htobel(state[2]), htobel(state[3])); 735 wp += SMB_SYMMD5LEN; 736 bcopy(target, wp, targlen); 737 wp += targlen; 738 if (datalen < filelen) { 739 *wp++ = '\n'; 740 datalen++; 741 if (datalen < filelen) 742 memset((caddr_t)wp, ' ', filelen - datalen); 743 } 744 *rtlen = filelen; 745 return wbuf; 746} 747 748/* 749 * Create a UNIX style symlink using the UNIX extension. This uses the smb trans2 750 * set path info call with a unix link info level. The server will create the symlink 751 * using the path, the data portion of the trans2 message will contain the target. 752 * The target will be a UNIX style target including using forward slashes as the 753 * delemiter. 754 * 755 * The calling routine must hold a reference on the share 756 */ 757static int 758smb_setfile_unix_symlink(struct smb_share *share, struct smbnode *dnp, 759 const char *name, size_t nmlen, char *target, 760 size_t targetlen, vfs_context_t context) 761{ 762 struct smb_t2rq *t2p = NULL; 763 struct mbchain *mbp; 764 int error; 765 char *ntwrkpath = NULL; 766 size_t ntwrkpathlen = targetlen * 2; /* UTF8 to UTF16 can be twice as big */ 767 768 SMB_MALLOC(ntwrkpath, char *, ntwrkpathlen, M_SMBFSDATA, M_WAITOK | M_ZERO); 769 /* smb_convert_path_to_network sets the precomosed flag */ 770 error = smb_convert_path_to_network(target, targetlen, ntwrkpath, 771 &ntwrkpathlen, '/', NO_SFM_CONVERSIONS, 772 SMB_UNICODE_STRINGS(SSTOVC(share))); 773 if (! error) { 774 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_PATH_INFORMATION, 1, 775 context, &t2p); 776 } 777 if (error) { 778 goto done; 779 } 780 mbp = &t2p->t2_tparam; 781 mb_init(mbp); 782 mb_put_uint16le(mbp, SMB_SFILEINFO_UNIX_LINK); 783 mb_put_uint32le(mbp, 0); /* MBZ */ 784 error = smbfs_fullpath(mbp, dnp, name, &nmlen, UTF_SFM_CONVERSIONS, 785 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 786 if (error) { 787 goto done; 788 } 789 mbp = &t2p->t2_tdata; 790 mb_init(mbp); 791 mb_put_mem(mbp, (caddr_t)(ntwrkpath), ntwrkpathlen, MB_MSYSTEM); 792 t2p->t2_maxpcount = 2; 793 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 794 error = smb_t2_request(t2p); 795 796done: 797 SMB_FREE(ntwrkpath, M_SMBFSDATA); 798 if (t2p) { 799 smb_t2_done(t2p); 800 } 801 return error; 802 803} 804 805static int 806smbfs_smb_fsctl(struct smb_share *share, uint32_t fsctl, SMBFID fid, 807 uint32_t datacnt, struct mbchain *mbp, struct mdchain *mdp, 808 Boolean * moreDataRequired, vfs_context_t context) 809{ 810 struct smb_ntrq *ntp = NULL; 811 int error; 812 uint16_t smb1_fid = (uint16_t) fid; /* cast to SMB 1 fid */ 813 814 error = smb_nt_alloc(SSTOCP(share), NT_TRANSACT_IOCTL, context, &ntp); 815 if (error) { 816 goto done; 817 } 818 /* 819 * TotalParameterCount (4 bytes): 820 * ULONG This field MUST be set to 0x0000. 821 * 822 * MaxParameterCount (4 bytes): 823 * ULONG This field MUST be set to 0x0000. 824 * 825 * ParameterCount (4 bytes) : 826 * ULONG This field MUST be set to 0x0000. 827 */ 828 /* 829 * MaxDataCount (4 bytes): 830 * ULONG The max data that can be returned. 831 */ 832 ntp->nt_maxdcount = datacnt; 833 834 /* The NT_TRANSACT_IOCTL setup structure */ 835 mb_init(&ntp->nt_tsetup); 836 837 /* 838 * FunctionCode (4 bytes): 839 * ULONG Windows NT device or file system control code. 840 */ 841 mb_put_uint32le(&ntp->nt_tsetup, fsctl); 842 843 /* FID (2 bytes): 844 * USHORT MUST contain a valid FID obtained from a previously successful 845 * SMB open command. The FID MUST be for either an I/O device or for a 846 * file system control device. The type of FID being supplied is specified 847 * by IsFctl. 848 */ 849 mb_put_uint16le(&ntp->nt_tsetup, smb1_fid); 850 851 /* 852 * IsFctl (1 byte): 853 * BOOLEAN This field is TRUE if the command is a file system control 854 * command and the FID is a file system control device. Otherwise, the 855 * command is a device control command and FID is an I/O device. 856 * 857 * Currently always set to true 858 */ 859 mb_put_uint8(&ntp->nt_tsetup, 1); 860 861 /* 862 * IsFlags (1 byte): 863 * BOOLEAN If bit 0 is set, the command is to be applied to a share root 864 * handle. The share MUST be a Distributed File System (DFS) type. 865 * 866 * Currently always set to false 867 */ 868 mb_put_uint8(&ntp->nt_tsetup, 0); 869 870 /* 871 * NT_Trans_Parameters (variable): (0 bytes): 872 * No NT_Trans parameters are sent in this request. 873 */ 874 /* 875 * NT_Trans_Data (variable): 876 * The raw bytes that are passed to the fsctl or ioctl function as the 877 * input buffer. 878 */ 879 if (mbp) { 880 /* Use the mbchain passed in */ 881 ntp->nt_tdata = *mbp; 882 memset(mbp, 0, sizeof(*mbp)); 883 } 884 885 error = smb_nt_request(ntp); 886 if (error) { 887 /* The data buffer wasn't big enough. Caller will have to retry. */ 888 if (moreDataRequired && (ntp->nt_flags & SMBT2_MOREDATA)) { 889 *moreDataRequired = TRUE; 890 } 891 goto done; 892 } 893 if (ntp->nt_rdata.md_top && mdp) { 894 SMBSYMDEBUG("Repase data size = %d\n", (int)datalen); 895 /* Store the mbuf info into their mdchain */ 896 md_initm(mdp, ntp->nt_rdata.md_top); 897 /* Clear it out so we don't free the mbuf */ 898 memset(&ntp->nt_rdata, 0, sizeof(ntp->nt_rdata)); 899 } 900 901done: 902 if (ntp) { 903 smb_nt_done(ntp); 904 } 905 906 return error; 907 908} 909 910void 911smbfs_update_symlink_cache(struct smbnode *np, char *target, size_t targetlen) 912{ 913 struct timespec ts; 914 if (np->n_symlink_target != NULL) { 915 SMB_FREE(np->n_symlink_target, M_TEMP); 916 } 917 np->n_symlink_target_len = 0; 918 np->n_symlink_target = smb_strndup(target, targetlen); 919 if (np->n_symlink_target) { 920 np->n_symlink_target_len = targetlen; 921 nanouptime(&ts); 922 np->n_symlink_cache_timer = ts.tv_sec; 923 } 924} 925 926/* 927 * Create a symbolic link since the server supports the UNIX extensions. This 928 * allows us to access and share symbolic links with AFP and NFS. 929 * 930 * The calling routine must hold a reference on the share 931 */ 932int 933smbfs_smb_create_unix_symlink(struct smb_share *share, struct smbnode *dnp, 934 const char *in_name, size_t in_nmlen, char *target, 935 size_t targetlen, struct smbfattr *fap, 936 vfs_context_t context) 937{ 938 const char *name = in_name; 939 size_t nmlen = in_nmlen; 940 int error; 941 942 memset(fap, 0, sizeof(*fap)); 943 error = smb_setfile_unix_symlink(share, dnp, name, nmlen, target, 944 targetlen, context); 945 if (error) { 946 goto done; 947 } 948 /* 949 * The smb_setfile_unix_symlink call does not return any meta data 950 * info that includes the inode number of the item. We could just dummy up 951 * these values, but that wouldn't be correct and besides we would 952 * just need invalidate the cache, which would cause a lookup anyways. 953 * 954 * Seems if wide links are turned off Snow Leopard servers will return 955 * access denied on any lookup of the symbolic link. So for now dummy up 956 * the file's attribute if an error is returned on the lookup. If this gets 957 * fixed in the future then we could remove this code, but we need to cleanup 958 * on failure. 959 * 960 * We should cleanup on failure, but we don't do that in any of the 961 * other failure case. See <rdar://problem/8498673> 962 */ 963 error = smbfs_lookup(share, dnp, &name, &nmlen, fap, context); 964 if (error) { 965 struct smbmount *smp = dnp->n_mount; 966 967 fap->fa_attr = SMB_EFA_NORMAL; 968 fap->fa_size = targetlen; 969 fap->fa_data_alloc = roundup(fap->fa_size, smp->sm_statfsbuf.f_bsize); 970 nanotime(&fap->fa_crtime); /* Need current date/time, so use nanotime */ 971 fap->fa_atime = fap->fa_crtime; 972 fap->fa_chtime = fap->fa_crtime; 973 fap->fa_mtime = fap->fa_crtime; 974 fap->fa_ino = smbfs_getino(dnp, in_name, in_nmlen); /* SMB 1 only */ 975 nanouptime(&fap->fa_reqtime); 976 fap->fa_valid_mask |= FA_VTYPE_VALID; 977 fap->fa_vtype = VLNK; 978 fap->fa_nlinks = 1; 979 fap->fa_flags_mask = EXT_REQUIRED_BY_MAC; 980 fap->fa_unix = TRUE; 981 error = 0; 982 } 983done: 984 /* If lookup returned a new name free it we never need that name */ 985 if (name != in_name) { 986 SMB_FREE(name, M_SMBNODENAME); 987 } 988 if (error) { 989 SMBWARNING("Creating symlink for %s failed! error = %d\n", name, error); 990 } 991 return error; 992} 993 994/* 995 * This server doesn't support UNIX or reparse point style symbolic links, so 996 * create a faked up symbolic link, using the Conrad and Steve French method 997 * for storing and reading symlinks on Window Servers. 998 * 999 * NOTE: We should remove creating these in the future, but first we need to see 1000 * if we can get reparse point style symbolic links working. 1001 * 1002 * The calling routine must hold a reference on the share 1003 */ 1004int 1005smbfs_smb_create_windows_symlink(struct smb_share *share, struct smbnode *dnp, 1006 const char *name, size_t nmlen, 1007 char *target, size_t targetlen, 1008 struct smbfattr *fap, vfs_context_t context) 1009{ 1010 uint32_t wlen = 0; 1011 uio_t uio = NULL; 1012 char *wdata = NULL; 1013 int error; 1014 SMBFID fid = 0; 1015 uint64_t create_flags = SMB2_CREATE_DO_CREATE | SMB2_CREATE_GET_MAX_ACCESS; 1016 1017 wdata = smbfs_create_windows_symlink_data(target, targetlen, &wlen); 1018 if (!wdata) { 1019 error = ENOMEM; 1020 goto done; 1021 } 1022 1023 uio = uio_create(1, 0, UIO_SYSSPACE, UIO_WRITE); 1024 if (uio == NULL) { 1025 error = ENOMEM; 1026 goto done; 1027 } 1028 1029 uio_addiov(uio, CAST_USER_ADDR_T(wdata), wlen); 1030 1031 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 1032 /* SMB 2/3 - compound Create/Write/Close */ 1033 error = smb2fs_smb_cmpd_create_write(share, dnp, 1034 name, nmlen, 1035 NULL, 0, 1036 SMB2_FILE_WRITE_DATA, fap, 1037 create_flags, uio, 1038 NULL, 0, 1039 context); 1040 } 1041 else { 1042 /* SMB 1 */ 1043 error = smbfs_smb_create(share, dnp, name, nmlen, SMB2_FILE_WRITE_DATA, 1044 &fid, FILE_CREATE, 0, fap, context); 1045 if (error) { 1046 goto done; 1047 } 1048 1049 error = smb_smb_write(share, fid, uio, 0, context); 1050 1051 (void) smbfs_smb_close(share, fid, context); 1052 } 1053 1054 if (!error) { 1055 /* We just changed the size of the file */ 1056 fap->fa_size = wlen; 1057 } 1058 1059done: 1060 if (uio != NULL) { 1061 uio_free(uio); 1062 } 1063 1064 if (wdata) { 1065 SMB_FREE(wdata, M_TEMP); 1066 } 1067 1068 if (error) { 1069 SMBWARNING("Creating symlink for %s failed! error = %d\n", name, error); 1070 } 1071 1072 return error; 1073} 1074 1075/* 1076 * This server support reparse point style symbolic links, This allows us to 1077 * access and share symbolic links with AFP and NFS. 1078 * 1079 * The calling routine must hold a reference on the share 1080 */ 1081int 1082smb1fs_smb_create_reparse_symlink(struct smb_share *share, struct smbnode *dnp, 1083 const char *name, size_t nmlen, char *target, 1084 size_t targetlen, struct smbfattr *fap, 1085 vfs_context_t context) 1086{ 1087 struct smbmount *smp = dnp->n_mount; 1088 int error; 1089 SMBFID fid = 0; 1090 struct mbchain mbp; 1091 size_t path_len; 1092 char *path; 1093 uint16_t reparseLen; 1094 uint16_t SubstituteNameOffset, SubstituteNameLength; 1095 uint16_t PrintNameOffset, PrintNameLength; 1096 int need_close = 0; 1097 uint32_t rights = SMB2_FILE_WRITE_DATA | SMB2_FILE_WRITE_ATTRIBUTES | SMB2_DELETE; 1098 1099 error = smbfs_smb_ntcreatex(share, dnp, 1100 rights, NTCREATEX_SHARE_ACCESS_ALL, VLNK, 1101 &fid, name, nmlen, 1102 FILE_CREATE, FALSE, fap, 1103 TRUE, NULL, context); 1104 if (error) { 1105 goto done; 1106 } 1107 need_close = 1; 1108 1109 path_len = (targetlen * 2) + 2; /* Start with the max possible size */ 1110 SMB_MALLOC(path, char *, path_len, M_TEMP, M_WAITOK | M_ZERO); 1111 if (path == NULL) { 1112 error = ENOMEM; 1113 goto done; 1114 } 1115 /* Convert it to a network style path */ 1116 error = smb_convert_path_to_network(target, targetlen, path, &path_len, 1117 '\\', SMB_UTF_SFM_CONVERSIONS, 1118 SMB_UNICODE_STRINGS(SSTOVC(share))); 1119 if (error) { 1120 SMB_FREE(path, M_TEMP); 1121 goto done; 1122 } 1123 SubstituteNameLength = path_len; 1124 SubstituteNameOffset = 0; 1125 PrintNameOffset = SubstituteNameLength; 1126 PrintNameLength = SubstituteNameLength; 1127 reparseLen = SubstituteNameLength + PrintNameLength + 12; 1128 mb_init(&mbp); 1129 mb_put_uint32le(&mbp, IO_REPARSE_TAG_SYMLINK); 1130 mb_put_uint16le(&mbp, reparseLen); 1131 mb_put_uint16le(&mbp, 0); /* Reserved */ 1132 mb_put_uint16le(&mbp, SubstituteNameOffset); 1133 mb_put_uint16le(&mbp, SubstituteNameLength); 1134 mb_put_uint16le(&mbp, PrintNameOffset); 1135 mb_put_uint16le(&mbp, PrintNameLength); 1136 /* 1137 * Flags field can be either SYMLINK_FLAG_ABSOLUTE or SYMLINK_FLAG_RELATIVE. 1138 * If the target starts with a slash assume its absolute otherwise it must 1139 * me realative. 1140 */ 1141 if (*target == '/') { 1142 mb_put_uint32le(&mbp, SYMLINK_FLAG_ABSOLUTE); 1143 } else { 1144 mb_put_uint32le(&mbp, SYMLINK_FLAG_RELATIVE); 1145 } 1146 mb_put_mem(&mbp, path, SubstituteNameLength, MB_MSYSTEM); 1147 mb_put_mem(&mbp, path, PrintNameLength, MB_MSYSTEM); 1148 SMB_FREE(path, M_TEMP); 1149 error = smbfs_smb_fsctl(share, FSCTL_SET_REPARSE_POINT, fid, 0, &mbp, 1150 NULL, NULL, context); 1151 mb_done(&mbp); 1152 /* 1153 * Windows systems requires special user access to create a reparse symlinks. 1154 * They default to only allow administrator symlink create access. This can 1155 * be changed on the server, but we are going to run into this issue. So if 1156 * we get an access error on the fsctl then we assume this user doesn't have 1157 * create symlink rights and we need to fallback to the old Conrad/Steve 1158 * symlinks. Since the create work we know the user has access to the file 1159 * system, they just don't have create symlink rights. We never fallback if 1160 * the server is running darwin. 1161 */ 1162 if ((error == EACCES) && !(SSTOVC(share)->vc_flags & SMBV_DARWIN)) { 1163 smp->sm_flags &= ~MNT_SUPPORTS_REPARSE_SYMLINKS; 1164 } 1165 1166 if (error) { 1167 /* Failed to create the symlink, remove the file on close */ 1168 (void)smbfs_smb_markfordelete(share, fid, context); 1169 } else { 1170 /* Reset any other fap information */ 1171 fap->fa_size = targetlen; 1172 /* The FSCTL_SET_REPARSE_POINT succeeded, so mark it as a reparse point */ 1173 fap->fa_attr |= SMB_EFA_REPARSE_POINT; 1174 fap->fa_valid_mask |= FA_REPARSE_TAG_VALID; 1175 fap->fa_reparse_tag = IO_REPARSE_TAG_SYMLINK; 1176 fap->fa_valid_mask |= FA_VTYPE_VALID; 1177 fap->fa_vtype = VLNK; 1178 } 1179 1180done: 1181 if (need_close) { 1182 (void)smbfs_smb_close(share, fid, context); 1183 } 1184 1185 /* 1186 * This user doesn't have access to create a reparse symlink, create the 1187 * old style symlink. 1188 */ 1189 if ((error == EACCES) && !(smp->sm_flags & MNT_SUPPORTS_REPARSE_SYMLINKS)) { 1190 error = smbfs_smb_create_windows_symlink(share, dnp, name, nmlen, target, 1191 targetlen, fap, context); 1192 } 1193 1194 if (error) { 1195 SMBWARNING("Creating symlink for %s failed! error = %d\n", name, error); 1196 } 1197 return error; 1198} 1199 1200/* 1201 * Get the reparse tag and if its a symlink get the target and target size. 1202 * 1203 * The calling routine must hold a reference on the share 1204 * 1205 */ 1206int 1207smbfs_smb_get_reparse_tag(struct smb_share *share, SMBFID fid, 1208 uint32_t *reparseTag, char **outTarget, 1209 size_t *outTargetlen, vfs_context_t context) 1210{ 1211 int error; 1212 Boolean moreDataRequired = FALSE; 1213 uint32_t rdatacnt = SSTOVC(share)->vc_txmax; 1214 struct mdchain mdp; 1215 uint16_t reparseLen = 0; 1216 uint16_t SubstituteNameOffset = 0; 1217 uint16_t SubstituteNameLength = 0; 1218 uint16_t PrintNameOffset = 0; 1219 uint16_t PrintNameLength = 0; 1220 uint32_t Flags = 0; 1221 char *ntwrkname = NULL; 1222 char *target = NULL; 1223 size_t targetlen; 1224 1225 memset(&mdp, 0, sizeof(mdp)); 1226 1227 error = smbfs_smb_fsctl(share, FSCTL_GET_REPARSE_POINT, fid, rdatacnt, NULL, 1228 &mdp, &moreDataRequired, context); 1229 if (!error && !mdp.md_top) { 1230 error = ENOENT; 1231 } 1232 if (error) { 1233 goto done; 1234 } 1235 1236 md_get_uint32le(&mdp, reparseTag); 1237 /* Should have checked to make sure the node reparse tag matches */ 1238 if (*reparseTag != IO_REPARSE_TAG_SYMLINK) { 1239 md_done(&mdp); 1240 goto done; 1241 } 1242 md_get_uint16le(&mdp, &reparseLen); 1243 md_get_uint16le(&mdp, NULL); /* Reserved */ 1244 md_get_uint16le(&mdp, &SubstituteNameOffset); 1245 md_get_uint16le(&mdp, &SubstituteNameLength); 1246 md_get_uint16le(&mdp, &PrintNameOffset); 1247 md_get_uint16le(&mdp, &PrintNameLength); 1248 /* 1249 * Flags field can be either SYMLINK_FLAG_ABSOLUTE or SYMLINK_FLAG_RELATIVE, 1250 * in either case we don't care and just ignore it for now. 1251 */ 1252 md_get_uint32le(&mdp, &Flags); 1253 SMBSYMDEBUG("reparseLen = %d SubstituteNameOffset = %d SubstituteNameLength = %d PrintNameOffset = %d PrintNameLength = %d Flags = %d\n", 1254 reparseLen, 1255 SubstituteNameOffset, SubstituteNameLength, 1256 PrintNameOffset, PrintNameLength, Flags); 1257 /* 1258 * Mount Point Reparse Data Buffer 1259 * A mount point has a substitute name and a print name associated with it. 1260 * The substitute name is a pathname (section 2.1.5) identifying the target 1261 * of the mount point. The print name SHOULD be an informative pathname 1262 * (section 2.1.5), suitable for display to a user, that also identifies the 1263 * target of the mount point. Neither of these pathnames can contain dot 1264 * directory names. 1265 * 1266 * So the above implies that we should always use the substitute name, but 1267 * my guess is they are always the same in symbolic link case. 1268 */ 1269 /* Never allocate more than our transcation size buffer */ 1270 if ((SubstituteNameLength == 0) || (SubstituteNameLength > SSTOVC(share)->vc_txmax)) { 1271 error = ENOMEM; 1272 SMBSYMDEBUG("SubstituteNameLength too large or zero %d \n", SubstituteNameLength); 1273 md_done(&mdp); 1274 goto done; 1275 } 1276 1277 if (SubstituteNameOffset) { 1278 md_get_mem(&mdp, NULL, SubstituteNameOffset, MB_MSYSTEM); 1279 } 1280 1281 SMB_MALLOC(ntwrkname, char *, (size_t)SubstituteNameLength, M_TEMP, M_WAITOK | M_ZERO); 1282 if (ntwrkname == NULL) { 1283 error = ENOMEM; 1284 } else { 1285 error = md_get_mem(&mdp, (void *)ntwrkname, (size_t)SubstituteNameLength, MB_MSYSTEM); 1286 } 1287 md_done(&mdp); 1288 if (error) { 1289 goto done; 1290 } 1291 targetlen = SubstituteNameLength * 9 + 1; 1292 SMB_MALLOC(target, char *, targetlen, M_TEMP, M_WAITOK | M_ZERO); 1293 if (target == NULL) { 1294 error = ENOMEM; 1295 } else { 1296 error = smb_convert_network_to_path(ntwrkname, SubstituteNameLength, target, 1297 &targetlen, '\\', UTF_SFM_CONVERSIONS, 1298 SMB_UNICODE_STRINGS(SSTOVC(share))); 1299 } 1300 if (!error) { 1301 *outTarget = target; 1302 *outTargetlen = targetlen; 1303 target = NULL; 1304 } 1305 1306done: 1307 SMB_FREE(ntwrkname, M_TEMP); 1308 SMB_FREE(target, M_TEMP); 1309 return error; 1310 1311} 1312 1313/* 1314 * The symbolic link is stored in a reparse point, support by some windows servers 1315 * and Darwin servers. 1316 * 1317 * The calling routine must hold a reference on the share 1318 * 1319 */ 1320int 1321smb1fs_smb_reparse_read_symlink(struct smb_share *share, struct smbnode *np, 1322 struct uio *uiop, vfs_context_t context) 1323{ 1324 int error; 1325 uint32_t reparseTag = 0; 1326 SMBFID fid = 0; 1327 char *target = NULL; 1328 size_t targetlen = 0; 1329 int need_close = 0; 1330 1331 error = smbfs_tmpopen(share, np, 1332 SMB2_FILE_READ_DATA | SMB2_FILE_READ_ATTRIBUTES, 1333 &fid, context); 1334 if (error) { 1335 goto done; 1336 } 1337 need_close = 1; 1338 1339 error = smbfs_smb_get_reparse_tag(share, fid, &reparseTag, &target, 1340 &targetlen, context); 1341 if (!error && (reparseTag != IO_REPARSE_TAG_SYMLINK)) { 1342 error = ENOENT; 1343 } else if (!error && (target == NULL)) { 1344 error = EINVAL; 1345 } 1346 if (error) { 1347 goto done; 1348 } 1349 1350 /* smbfs_update_symlink_cache will deal with the null pointer */ 1351 SMBSYMDEBUG_LOCK(np, "%s --> %s\n", np->n_name, target); 1352 1353 smbfs_update_symlink_cache(np, target, targetlen); 1354 error = uiomove(target, (int)targetlen, uiop); 1355 1356done: 1357 SMB_FREE(target, M_TEMP); 1358 1359 if (need_close == 1) { 1360 (void)smbfs_tmpclose(share, np, fid, context); 1361 } 1362 1363 if (error) { 1364 SMBWARNING_LOCK(np, "%s failed %d\n", np->n_name, error); 1365 } 1366 1367 return error; 1368} 1369 1370/* 1371 * Supports reading a faked up symbolic link. This is Conrad and Steve 1372 * French method for storing and reading symlinks on Window Servers. 1373 * 1374 * The calling routine must hold a reference on the share 1375 * 1376 */ 1377int 1378smbfs_smb_windows_read_symlink(struct smb_share *share, struct smbnode *np, 1379 struct uio *uiop, vfs_context_t context) 1380{ 1381 unsigned char *wbuf, *cp; 1382 unsigned len, flen; 1383 uio_t uio; 1384 int error; 1385 SMBFID fid = 0; 1386 char *target = NULL; 1387 1388 flen = SMB_SYMLEN; 1389 SMB_MALLOC(wbuf, void *, flen, M_TEMP, M_WAITOK); 1390 1391 error = smbfs_tmpopen(share, np, SMB2_FILE_READ_DATA, &fid, context); 1392 if (error) 1393 goto out; 1394 1395 uio = uio_create(1, 0, UIO_SYSSPACE, UIO_READ); 1396 uio_addiov(uio, CAST_USER_ADDR_T(wbuf), flen); 1397 error = smb_smb_read(share, fid, uio, context); 1398 uio_free(uio); 1399 1400 (void)smbfs_tmpclose(share, np, fid, context); 1401 if (error) 1402 goto out; 1403 1404 for (len = 0, cp = wbuf + SMB_SYMMAGICLEN; 1405 cp < wbuf + SMB_SYMMAGICLEN + SMB_SYMLENLEN-1; cp++) { 1406 if (*cp < '0' || *cp > '9') { 1407 SMBWARNING("symlink length nonnumeric: %c (0x%x)\n", *cp, *cp); 1408 return (EINVAL); 1409 } 1410 len *= 10; 1411 len += *cp - '0'; 1412 } 1413 if (len != np->n_size) { 1414 SMBWARNING("symlink length payload changed from %u to %u\n", 1415 (unsigned)np->n_size, len); 1416 np->n_size = len; 1417 } 1418 /* %%% is this function valid for SMB 2/3, note the SMBHDRLEN below */ 1419 target = (char *)(wbuf + SMB_SYMHDRLEN); 1420 1421 SMBSYMDEBUG_LOCK(np, "%s --> %s\n", np->n_name, target); 1422 1423 smbfs_update_symlink_cache(np, target, len); 1424 error = uiomove(target, (int)len, uiop); 1425out: 1426 SMB_FREE(wbuf, M_TEMP); 1427 1428 if (error) { 1429 SMBWARNING_LOCK(np, "%s failed %d\n", np->n_name, error); 1430 } 1431 return (error); 1432} 1433 1434/* 1435 * Support for reading a symbolic link that resides on a UNIX server. This allows 1436 * us to access and share symbolic links with AFP and NFS. 1437 * 1438 * The calling routine must hold a reference on the share 1439 * 1440 */ 1441int 1442smbfs_smb_unix_read_symlink(struct smb_share *share, struct smbnode *np, 1443 struct uio *uiop, vfs_context_t context) 1444{ 1445 struct smb_t2rq *t2p; 1446 int error; 1447 struct mbchain *mbp; 1448 struct mdchain *mdp; 1449 char *ntwrkname = NULL; 1450 char *target; 1451 size_t targetlen; 1452 size_t nmlen; 1453 1454 /* %%% To Do - implement for SMB 2/3 */ 1455 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 1456 SMBERROR("smbfs_smb_unix_read_symlink not supported by SMB 2/3\n"); 1457 error = ENOTSUP; 1458 return error; 1459 } 1460 1461 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_PATH_INFORMATION, 1, context, &t2p); 1462 if (error) 1463 return error; 1464 mbp = &t2p->t2_tparam; 1465 mb_init(mbp); 1466 mb_put_uint16le(mbp, SMB_QFILEINFO_UNIX_LINK); 1467 mb_put_uint32le(mbp, 0); 1468 error = smbfs_fullpath(mbp, np, NULL, NULL, UTF_SFM_CONVERSIONS, 1469 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 1470 if (error) 1471 goto out; 1472 t2p->t2_maxpcount = 2; 1473 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 1474 error = smb_t2_request(t2p); 1475 if (error) 1476 goto out; 1477 mdp = &t2p->t2_rdata; 1478 /* 1479 * At this point md_cur and md_top have the same value. Now all the md_get 1480 * routines will will check for null, but just to be safe we check here 1481 */ 1482 if (mdp->md_top == NULL) { 1483 error = EIO; 1484 goto out; 1485 } 1486 /* Get the size of the data that contains the symbolic link */ 1487 m_fixhdr(mdp->md_top); 1488 nmlen = mbuf_pkthdr_len(mdp->md_top); 1489 SMBSYMDEBUG("network len of the symbolic link = %ld\n", nmlen); 1490 SMB_MALLOC(ntwrkname, char *, nmlen, M_TEMP, M_WAITOK); 1491 if (ntwrkname == NULL) { 1492 error = ENOMEM; 1493 } else { 1494 /* Read in the data that contains the symbolic link */ 1495 error = md_get_mem(mdp, (void *)ntwrkname, nmlen, MB_MSYSTEM); 1496 } 1497 if (error) 1498 goto out; 1499#ifdef DEBUG_SYMBOLIC_LINKS 1500 smb_hexdump(__FUNCTION__, "Symlink: ", (u_char *)ntwrkname, nmlen); 1501#endif // DEBUG_SYMBOLIC_LINKS 1502 /* 1503 * The Symbolic link data is a UNIX style symbolic link, except it is in UTF16 1504 * format. The unix slash is the delemter used. The path should end with two 1505 * null bytes as a terminator. The smb_convert_network_to_path does not expect 1506 * nmlen to include those bytes, so we can just back those bytes out. Nothiing 1507 * in the reference states that the null bytes are require, but this would be 1508 * the normal way to handle this type of string in SMB. 1509 */ 1510 nmlen -= 2; 1511 targetlen = nmlen * 9 + 1; 1512 SMB_MALLOC(target, char *, targetlen, M_TEMP, M_WAITOK | M_ZERO); 1513 error = smb_convert_network_to_path(ntwrkname, nmlen, target, 1514 &targetlen, '/', UTF_SFM_CONVERSIONS, 1515 SMB_UNICODE_STRINGS(SSTOVC(share))); 1516 if (!error) { 1517 SMBSYMDEBUG_LOCK(np, "%s --> %s\n", np->n_name, target); 1518 smbfs_update_symlink_cache(np, target, targetlen); 1519 error = uiomove(target, (int)targetlen, uiop); 1520 } 1521 1522 SMB_FREE(target, M_TEMP); 1523 1524out: 1525 SMB_FREE(ntwrkname, M_TEMP); 1526 smb_t2_done(t2p); 1527 if (error) { 1528 SMBWARNING_LOCK(np, "%s failed %d\n", np->n_name, error); 1529 } 1530 return error; 1531} 1532 1533/* 1534 * When calling this routine be very careful when passing the arguments. 1535 * Depending on the arguments different actions will be taken with this routine. 1536 * 1537 * The calling routine must hold a reference on the share 1538 * 1539 */ 1540int 1541smb1fs_smb_qstreaminfo(struct smb_share *share, struct smbnode *np, 1542 const char *namep, size_t name_len, 1543 const char *strmname, 1544 uio_t uio, size_t *sizep, 1545 uint64_t *strmsize, uint64_t *strmsize_alloc, 1546 uint32_t *stream_flagsp, 1547 vfs_context_t context) 1548{ 1549 struct smb_t2rq *t2p; 1550 int error; 1551 struct mbchain *mbp; 1552 struct mdchain *mdp; 1553 uint32_t next, nlen, used; 1554 uint64_t stream_size, stream_alloc_size; 1555 enum stream_types stype = kNoStream; 1556 struct timespec ts; 1557 int foundStream = (strmname) ? FALSE : TRUE; /* Are they looking for a specific stream */ 1558 char *streamName = NULL; /* current file name */ 1559 size_t streamNameLen = 0; /* name len */ 1560 size_t in_name_len = name_len; 1561 const char *fname; 1562 uint32_t is_data_stream = 0; 1563 int n_name_locked = 0; 1564 1565 /* 1566 * Two usage cases: 1567 * 1) Given np and namep == NULL. Query the path of np 1568 * 2) Given np and namep (must be readdirattr). Query PARENT np and 1569 * child namep. In this case, do not update vnode np as that is the parent. 1570 * 1571 * In both cases, Query for a list of streams and if streams are found, 1572 * see if they match stream_namep that was passed in. 1573 */ 1574 1575 if (namep == NULL) { 1576 /* Not readdirattr case */ 1577 if ((np->n_fstatus & kNO_SUBSTREAMS) || 1578 (np->n_dosattr & SMB_EFA_REPARSE_POINT)) { 1579 foundStream = FALSE; 1580 error = ENOATTR; 1581 goto done; 1582 } 1583 } 1584 1585 if (sizep) 1586 *sizep = 0; 1587 1588 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_PATH_INFORMATION, 1, context, &t2p); 1589 if (error) 1590 return (error); 1591 1592 mbp = &t2p->t2_tparam; 1593 mb_init(mbp); 1594 /* 1595 * SAMBA only supports the SMB_QFILEINFO_STREAM_INFORMATION level. Samba declined to 1596 * support the older info level with a comment claiming doing so caused a BSOD. Not sure 1597 * what that is all about. I have never seen that happen, but there is no differences 1598 * between the two levels. So if the server supports the new levels then use it. 1599 */ 1600 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 1601 mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFORMATION); 1602 else 1603 mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO); 1604 mb_put_uint32le(mbp, 0); 1605 1606 error = smbfs_fullpath(mbp, np, namep, &in_name_len, UTF_SFM_CONVERSIONS, 1607 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 1608 if (error) 1609 goto out; 1610 t2p->t2_maxpcount = 2; 1611 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 1612 error = smb_t2_request(t2p); 1613 if (error) 1614 goto out; 1615 1616 /* 1617 * Should never happen since we test for UNICODE CAPS when mounting, but 1618 * just to be safe never let them send us a Query Stream call that doesn't 1619 * have the UNICODE bit set in the flags field. See <rdar://problem/7653132> 1620 */ 1621 if (!SMB_UNICODE_STRINGS(SSTOVC(share))) { 1622 error = ENOTSUP; 1623 goto out; 1624 } 1625 mdp = &t2p->t2_rdata; 1626 /* 1627 * There could be no streams info associated with the item. You will find this with directory 1628 * or items copied from FAT file systems. Nothing to process just get out. 1629 */ 1630 if (mdp->md_cur == NULL) 1631 goto out; 1632 1633 do { 1634 char *ntwrk_name = NULL; 1635 1636 stream_size = 0; 1637 stream_alloc_size = 0; 1638 if ((error = md_get_uint32le(mdp, &next))) 1639 goto out; 1640 used = 4; 1641 if ((error = md_get_uint32le(mdp, &nlen))) /* name length */ 1642 goto out; 1643 used += 4; 1644 /* If this is the resource fork should we save this information */ 1645 if ((error = md_get_uint64le(mdp, &stream_size))) /* stream size */ 1646 goto out; 1647 used += 8; 1648 if ((error = md_get_uint64le(mdp, &stream_alloc_size))) /* alloc size */ 1649 goto out; 1650 used += 8; 1651 /* 1652 * Sanity check to limit DoS or buffer overrun attempts. 1653 * Make sure the length is not bigger than our max buffers size. 1654 */ 1655 if (nlen > SSTOVC(share)->vc_txmax) { 1656 error = EBADRPC; 1657 goto out; 1658 } 1659 SMB_MALLOC(ntwrk_name, char *, nlen, M_SMBFSDATA, M_WAITOK | M_ZERO); 1660 if ((error = md_get_mem(mdp, ntwrk_name, nlen, MB_MSYSTEM))) { 1661 SMB_FREE(ntwrk_name, M_SMBFSDATA); 1662 goto out; 1663 } 1664 used += nlen; 1665 1666 /* 1667 * Ignore any trailing null, not that we expect them 1668 * NOTE: MS-CIFS states that the stream name is alway in UNICODE. We 1669 * only support streams if the server supports UNICODE. 1670 */ 1671 if ((nlen > 1) && !ntwrk_name[nlen - 1] && !ntwrk_name[nlen - 2]) 1672 nlen -= 2; 1673 streamNameLen = nlen; 1674 streamName = smbfs_ntwrkname_tolocal(ntwrk_name, &streamNameLen, 1675 SMB_UNICODE_STRINGS(SSTOVC(share))); 1676 SMB_FREE(ntwrk_name, M_SMBFSDATA); 1677 /* 1678 * We should now have a name in the form : <foo> :$DATA Where <foo> is 1679 * UTF-8 w/o null termination. If it isn't in that form we want to LOG it 1680 * and skip it. Note we want to skip w/o logging the "data fork" entry, 1681 * which is simply ::$DATA Otherwise we want to uiomove out <foo> with a null added. 1682 */ 1683 if (namep == NULL) { 1684 lck_rw_lock_shared(&np->n_name_rwlock); 1685 n_name_locked = 1; 1686 fname = np->n_name; 1687 } 1688 else { 1689 /* readdirattr case - parent np and child namep */ 1690 fname = namep; 1691 } 1692 1693 if (smbfs_smb_undollardata(fname, streamName, &streamNameLen, 1694 &is_data_stream)) { 1695 const char *s; 1696 1697 if (n_name_locked) { 1698 lck_rw_unlock_shared(&np->n_name_rwlock); 1699 n_name_locked = 0; 1700 } 1701 1702 /* the "+ 1" skips over the leading colon */ 1703 s = streamName + 1; 1704 1705 /* Check for special case streams (resource fork and finder info */ 1706 if ((streamNameLen >= sizeof(SFM_RESOURCEFORK_NAME)) && 1707 (!strncasecmp(s, SFM_RESOURCEFORK_NAME, sizeof(SFM_RESOURCEFORK_NAME)))) { 1708 stype |= kResourceFrk; 1709 1710 if (namep == NULL) { 1711 /* We always get the resource fork size and cache it here. */ 1712 lck_mtx_lock(&np->rfrkMetaLock); 1713 np->rfrk_size = stream_size; 1714 np->rfrk_alloc_size = stream_alloc_size; 1715 nanouptime(&ts); 1716 np->rfrk_cache_timer = ts.tv_sec; 1717 lck_mtx_unlock(&np->rfrkMetaLock); 1718 } 1719 1720 /* 1721 * The Resource fork and Finder info names are special and get 1722 * translated between stream names and extended attribute names. 1723 * In this case we need to make sure the correct name gets used. 1724 * So we are looking for a specfic stream use its stream name 1725 * otherwise use its extended attribute name. 1726 */ 1727 if ((uio == NULL) && strmname && (sizep == NULL)) { 1728 s = SFM_RESOURCEFORK_NAME; 1729 streamNameLen = sizeof(SFM_RESOURCEFORK_NAME); 1730 } else { 1731 s = XATTR_RESOURCEFORK_NAME; 1732 streamNameLen = sizeof(XATTR_RESOURCEFORK_NAME); 1733 } 1734 /* 1735 * The uio means we are gettting this from a listxattr call, never 1736 * display zero length resource forks. Resource forks should 1737 * always contain a resource map. Seems CoreService never deleted 1738 * the resource fork, they just set the eof to zero. We need to 1739 * handle these resource forks here. 1740 */ 1741 if (uio && (stream_size == 0)) 1742 goto skipentry; 1743 1744 } else if ((streamNameLen >= sizeof(SFM_FINDERINFO_NAME)) && 1745 (!strncasecmp(s, SFM_FINDERINFO_NAME, sizeof(SFM_FINDERINFO_NAME)))) { 1746 /* 1747 * They have an AFP_Info stream and it has no size must be a Samba 1748 * server. We treat this the same as if the file has no Finder Info 1749 */ 1750 if (stream_size == 0) 1751 goto skipentry; 1752 1753 stype |= kFinderInfo; 1754 /* 1755 * The Resource fork and Finder info names are special and get 1756 * translated between stream names and extended attribute names. 1757 * In this case we need to make sure the correct name gets used. 1758 * So we are looking for a specfic stream use its stream name 1759 * otherwise use its extended attribute name. 1760 */ 1761 if ((uio == NULL) && strmname && (sizep == NULL)) { 1762 s = SFM_FINDERINFO_NAME; 1763 streamNameLen = sizeof(SFM_FINDERINFO_NAME); 1764 } 1765 else { 1766 s = XATTR_FINDERINFO_NAME; 1767 streamNameLen = sizeof(XATTR_FINDERINFO_NAME); 1768 } 1769 } 1770 1771 /* 1772 * Depending on what is passed in we handle the data in two different ways. 1773 * 1. If they have a uio then just put all the stream names into the uio buffer. 1774 * 2. If they pass in a stream name then they just want the size of that stream. 1775 * 1776 * NOTE: If there is nothing in the stream we will not return it in the list. This 1777 * allows us to hide empty streams from copy engines. 1778 * 1779 * We never return SFM_DESKTOP_NAME or SFM_IDINDEX_NAME streams. 1780 */ 1781 if (( (streamNameLen >= sizeof(SFM_DESKTOP_NAME)) && 1782 (!strncasecmp(s, SFM_DESKTOP_NAME, sizeof(SFM_DESKTOP_NAME)))) || 1783 ((streamNameLen >= sizeof(SFM_IDINDEX_NAME)) && 1784 (!strncasecmp(s, SFM_IDINDEX_NAME, sizeof(SFM_IDINDEX_NAME))))) { 1785 /* Is this a SFM Volume */ 1786 if (strmname && (!strncasecmp(SFM_DESKTOP_NAME, strmname, sizeof(SFM_DESKTOP_NAME)))) { 1787 foundStream = TRUE; 1788 } 1789 goto skipentry; 1790 } else if (uio) 1791 uiomove(s, (int)streamNameLen, uio); 1792 else if (!foundStream && strmname && strmsize) { 1793 /* They are looking for a specific stream name and we havn't found it yet. */ 1794 nlen = (uint32_t)strnlen(strmname, share->ss_maxfilenamelen+1); 1795 if ((streamNameLen >= nlen) && (!strncasecmp(s, strmname, nlen))) { 1796 *strmsize = stream_size; 1797 *strmsize_alloc = stream_alloc_size; 1798 foundStream = TRUE; 1799 } 1800 } 1801 /* 1802 * They could just want to know the buffer size they will need when 1803 * requesting a list. This has several problem, but we cannot solve 1804 * them all here. First someone can create a stream/EA between this 1805 * call and the one they make to get the data. Second this will cause 1806 * an extra round of traffic. We could cache all of this, but how 1807 * long would we keep this information around. Could require a large buffer. 1808 */ 1809 if (sizep) 1810 *sizep += streamNameLen; 1811 } 1812 1813 if (n_name_locked) { 1814 lck_rw_unlock_shared(&np->n_name_rwlock); 1815 n_name_locked = 0; 1816 } 1817 1818skipentry: 1819 SMB_FREE(streamName, M_SMBFSDATA); 1820 /* 1821 * Next should be the offset to the next entry. We have already move into 1822 * the buffer used bytes. So now need to move pass any remaining pad bytes. 1823 * So if the value next is larger than the value used, then we need to move 1824 * that many more bytes into the buffer. If that value is larger than 1825 * our buffer get out. 1826 */ 1827 if (next > used) { 1828 next -= used; 1829 if (next > SSTOVC(share)->vc_txmax) { 1830 error = EBADRPC; 1831 goto out; 1832 } 1833 md_get_mem(mdp, NULL, next, MB_MSYSTEM); 1834 } 1835 } while (next && !error); 1836 1837out: 1838 if (streamName != NULL) { 1839 SMB_FREE(streamName, M_SMBFSDATA); 1840 } 1841 smb_t2_done(t2p); 1842 1843done: 1844 /* 1845 * If we searched the entire list and did not find a finder info stream, 1846 * then reset the cache timer. 1847 */ 1848 if ((stype & kFinderInfo) != kFinderInfo) { 1849 /* set stream_flag indicating no Finder Info */ 1850 *stream_flagsp |= SMB_NO_FINDER_INFO; 1851 1852 if (namep == NULL) { 1853 /* Negative cache the Finder Info in the vnode */ 1854 bzero(np->finfo, sizeof(np->finfo)); 1855 nanouptime(&ts); 1856 np->finfo_cache_timer = ts.tv_sec; 1857 } 1858 } 1859 1860 /* 1861 * If we searched the entire list and did not find a resource stream, 1862 * then reset the cache timer. 1863 */ 1864 if ((stype & kResourceFrk) != kResourceFrk) { 1865 /* set stream_flag indicating no Resource Fork */ 1866 *stream_flagsp |= SMB_NO_RESOURCE_FORK; 1867 1868 if (namep == NULL) { 1869 /* Negative cache the resource fork in the vnode */ 1870 lck_mtx_lock(&np->rfrkMetaLock); 1871 1872 nanouptime(&ts); 1873 np->rfrk_size = 0; 1874 np->rfrk_alloc_size = 0; 1875 np->rfrk_cache_timer = ts.tv_sec; 1876 1877 lck_mtx_unlock(&np->rfrkMetaLock); 1878 } 1879 } 1880 1881 if ((foundStream == FALSE) || (error == ENOENT)) /* We did not find the stream we were looking for */ 1882 error = ENOATTR; 1883 return (error); 1884} 1885 1886/* 1887 * The SMB_QFS_POSIX_WHOAMI allows us to find out who the server thinks we are 1888 * and what groups we are in. 1889 * 1890 * The calling routine must hold a reference on the share 1891 * 1892 */ 1893void 1894smbfs_unix_whoami(struct smb_share *share, struct smbmount *smp, vfs_context_t context) 1895{ 1896 struct smb_t2rq *t2p; 1897 struct mbchain *mbp; 1898 struct mdchain *mdp; 1899 int error; 1900 uint32_t ii; 1901 uint32_t reserved; 1902 size_t total_bytes; 1903 uint32_t ntwrk_sids_cnt; 1904 uint32_t ntwrk_sid_size; 1905 1906 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_FS_INFORMATION, 1, context, &t2p); 1907 if (error) 1908 return; 1909 1910 mbp = &t2p->t2_tparam; 1911 mb_init(mbp); 1912 mb_put_uint16le(mbp, SMB_QFS_POSIX_WHOAMI); 1913 t2p->t2_maxpcount = 4; 1914 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 1915 error = smb_t2_request(t2p); 1916 if (error) 1917 goto done; 1918 1919 mdp = &t2p->t2_rdata; 1920 /* 1921 * At this point md_cur and md_top have the same value. Now all the md_get 1922 * routines will will check for null, but just to be safe we check here 1923 */ 1924 if (mdp->md_cur == NULL) { 1925 error = EBADRPC; 1926 goto done; 1927 } 1928 /* Currently only tells us if we logged in as guest, we should already know this by now */ 1929 md_get_uint32le(mdp, NULL); /* Mapping flags, currently only used for guest */ 1930 md_get_uint32le(mdp, NULL); /* Mask of valid mapping flags */ 1931 md_get_uint64le(mdp, &smp->ntwrk_uid); /* Primary user ID */ 1932 md_get_uint64le(mdp, &smp->ntwrk_gid); /* Primary group ID */ 1933 md_get_uint32le(mdp, &smp->ntwrk_cnt_gid); /* number of supplementary GIDs */ 1934 md_get_uint32le(mdp, &ntwrk_sids_cnt); /* number of SIDs */ 1935 md_get_uint32le(mdp, &ntwrk_sid_size); /* size of the list of SIDs */ 1936 error = md_get_uint32le(mdp, &reserved); /* Reserved (should be zero) */ 1937 if (error) 1938 goto done; 1939 SMBWARNING("network uid = %lld network gid = %lld supplementary group cnt = %d SID cnt = %d\n", 1940 smp->ntwrk_uid, smp->ntwrk_gid, smp->ntwrk_cnt_gid, ntwrk_sids_cnt); 1941 /* 1942 * If we can't get the reserved field then the buffer is not big enough. Both the 1943 * group count and sid count must set to zero if no groups or sids are return. 1944 * Added a little safty net here, we do not allow these fields to be negative. 1945 */ 1946 if (error || (reserved != 0) || ((int32_t)smp->ntwrk_cnt_gid < 0) || ((int32_t)ntwrk_sids_cnt < 0)) { 1947 if (! error) 1948 error = EBADRPC; 1949 goto done; 1950 } 1951 1952 /* No group list see if there is a sid list */ 1953 if (smp->ntwrk_cnt_gid == 0) 1954 goto sid_groups; 1955 1956 /* Now check to make sure we don't have an integer overflow */ 1957 total_bytes = smp->ntwrk_cnt_gid * sizeof(uint64_t); 1958 if ((total_bytes / sizeof(uint64_t)) != smp->ntwrk_cnt_gid) { 1959 error = EBADRPC; 1960 goto done; 1961 } 1962 1963 /* Make sure we are not allocating more than we said we could handle */ 1964 if (total_bytes > SSTOVC(share)->vc_txmax) { 1965 error = EBADRPC; 1966 goto done; 1967 } 1968 1969 SMB_MALLOC(smp->ntwrk_gids, uint64_t *, total_bytes, M_TEMP, M_WAITOK); 1970 /* Should never happen, but just to be safe */ 1971 if (smp->ntwrk_gids == NULL) { 1972 error = ENOMEM; 1973 goto done; 1974 } 1975 for (ii = 0; ii < smp->ntwrk_cnt_gid; ii++) { 1976 error = md_get_uint64le(mdp, &smp->ntwrk_gids[ii]); 1977 if (error) 1978 goto done; 1979 SMBDEBUG("smp->ntwrk_gids[%d] = %lld\n", ii, smp->ntwrk_gids[ii]); 1980 } 1981 UNIX_CAPS(share) |= UNIX_QFS_POSIX_WHOAMI_CAP; 1982 /* 1983 * At this point we have everything we really need. So any errors from this 1984 * point on should be ignored. If we error out below we should just pretend 1985 * that we didn't get any network sids. 1986 */ 1987sid_groups: 1988 if (share->ss_attributes & FILE_PERSISTENT_ACLS) { 1989 smb_get_sid_list(share, smp, mdp,ntwrk_sids_cnt, ntwrk_sid_size); 1990 } 1991 1992done: 1993 smb_t2_done(t2p); 1994 if (error == EBADRPC) 1995 SMBERROR("Parsing error reading the message\n"); 1996 1997 if (error && smp->ntwrk_gids) { 1998 SMB_FREE(smp->ntwrk_gids, M_TEMP); 1999 smp->ntwrk_gids = NULL; 2000 smp->ntwrk_cnt_gid = 0; 2001 } 2002} 2003 2004/* 2005 * This is a UNIX server get its UNIX capiblities 2006 * 2007 * The calling routine must hold a reference on the share 2008 * 2009 */ 2010void 2011smbfs_unix_qfsattr(struct smb_share *share, vfs_context_t context) 2012{ 2013 struct smb_t2rq *t2p; 2014 struct mbchain *mbp; 2015 struct mdchain *mdp; 2016 uint16_t majorv; 2017 uint16_t minorv; 2018 uint64_t cap; 2019 int error; 2020 2021 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_FS_INFORMATION, 1, context, &t2p); 2022 if (error) 2023 return; 2024 2025 mbp = &t2p->t2_tparam; 2026 mb_init(mbp); 2027 mb_put_uint16le(mbp, SMB_QFS_UNIX_INFO); 2028 t2p->t2_maxpcount = 4; 2029 t2p->t2_maxdcount = 12; 2030 error = smb_t2_request(t2p); 2031 if (error) 2032 goto done; 2033 2034 mdp = &t2p->t2_rdata; 2035 /* 2036 * At this point md_cur and md_top have the same value. Now all the md_get 2037 * routines will will check for null, but just to be safe we check here 2038 */ 2039 if (mdp->md_cur == NULL) { 2040 SMBWARNING("Parsing error reading the message\n"); 2041 goto done; 2042 } 2043 md_get_uint16le(mdp, &majorv); 2044 md_get_uint16le(mdp, &minorv); 2045 md_get_uint64le(mdp, &cap); 2046 SMBWARNING("version %x.%x cap = %llx\n", majorv, minorv, cap); 2047 UNIX_CAPS(share) = UNIX_QFS_UNIX_INFO_CAP | (cap & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP); 2048 2049 if (UNIX_CAPS(share) & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) { 2050 UNIX_CAPS(share) |= UNIX_QFILEINFO_UNIX_LINK_CAP | UNIX_SFILEINFO_UNIX_LINK_CAP | 2051 UNIX_QFILEINFO_UNIX_INFO2_CAP | UNIX_SFILEINFO_UNIX_INFO2_CAP; 2052 /* 2053 * Seems Leopard Servers don't handle the posix unlink call correctly. 2054 * They support the call and say it work, but they don't really delete 2055 * the item. So until we stop supporting Leopard don't set this unless 2056 * the server doesn't support the BSD flags. Mac servers support the 2057 * BSD flags, but Linux servers don't. So in mount_smbfs we will turn 2058 * this back on if we determine its a linux server. 2059 * NOTE: Snow Leopard seems to work correctly 2060 * 2061 * UNIX_CAPS(share) |= UNIX_SFILEINFO_POSIX_UNLINK_CAP; 2062 */ 2063 } 2064done: 2065 smb_t2_done(t2p); 2066} 2067 2068/* 2069 * Since the first thing we do is set the default values there is no longer 2070 * any reason to return an error for this routine. Some servers may not support 2071 * this call. We should not fail the mount just because they do not support this 2072 * call. 2073 * 2074 * The calling routine must hold a reference on the share 2075 * 2076 */ 2077void 2078smb1fs_qfsattr(struct smb_share *share, vfs_context_t context) 2079{ 2080 struct smb_t2rq *t2p; 2081 struct mbchain *mbp; 2082 struct mdchain *mdp; 2083 uint32_t nlen = 0; 2084 int error; 2085 size_t fs_nmlen; /* The sized malloced for fs_name */ 2086 char *fsname = NULL; 2087 2088 /* Start with the default values */ 2089 share->ss_fstype = SMB_FS_FAT; /* default to FAT File System */ 2090 share->ss_attributes = 0; 2091 share->ss_maxfilenamelen = 255; 2092 2093 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_FS_INFORMATION, 1, context, &t2p); 2094 if (error) { 2095 return; 2096 } 2097 2098 mbp = &t2p->t2_tparam; 2099 mb_init(mbp); 2100 mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO); 2101 t2p->t2_maxpcount = 4; 2102 t2p->t2_maxdcount = 4 * 3 + 512; 2103 error = smb_t2_request(t2p); 2104 if (error) { 2105 goto done; 2106 } 2107 2108 mdp = &t2p->t2_rdata; 2109 /* 2110 * At this point md_cur and md_top have the same value. Now all the md_get 2111 * routines will will check for null, but just to be safe we check here 2112 */ 2113 if (mdp->md_cur == NULL) { 2114 error = EBADRPC; 2115 } 2116 else { 2117 md_get_uint32le(mdp, &share->ss_attributes); 2118 2119 /* 2120 * Make sure Max Name Length is a reasonable value. 2121 * See <rdar://problem/12171424>. 2122 */ 2123 md_get_uint32le(mdp, &share->ss_maxfilenamelen); /* max name length */ 2124 if (share->ss_maxfilenamelen > (SMB_MAXFNAMELEN * 2)) { 2125 SMBERROR("Illegal file name len %u\n", share->ss_maxfilenamelen); 2126 share->ss_maxfilenamelen = 255; 2127 } 2128 2129 error = md_get_uint32le(mdp, &nlen); /* fs name length */ 2130 } 2131 if (error) { 2132 /* This is a very bad server */ 2133 SMBWARNING("Server returned a bad SMB_QFS_ATTRIBUTE_INFO message\n"); 2134 /* Don't believe them when they say they are unix */ 2135 SSTOVC(share)->vc_sopt.sv_caps &= ~SMB_CAP_UNIX; 2136 goto done; 2137 } 2138 if ((nlen > 0) && (nlen < PATH_MAX)) { 2139 char *ntwrkName; 2140 2141 SMB_MALLOC(ntwrkName, char *, nlen, M_SMBFSDATA, M_WAITOK | M_ZERO); 2142 md_get_mem(mdp, ntwrkName, nlen, MB_MSYSTEM); 2143 /* 2144 * Just going from memory, I believe this is really just a 2145 * WCHAR not a STRING value. I know that both Windows 98 2146 * and SNAP return it as WCHAR and neither supports 2147 * UNICODE. So if they do not support UNICODE then lets 2148 * do some test and see if we can get the file system name. 2149 */ 2150 2151 fs_nmlen = nlen; 2152 fsname = smbfs_ntwrkname_tolocal(ntwrkName, &fs_nmlen, 2153 SMB_UNICODE_STRINGS(SSTOVC(share))); 2154 SMB_FREE(ntwrkName, M_SMBFSDATA); 2155 2156 if (fsname == NULL) { 2157 goto done; /* Should never happen, but just to be safe */ 2158 } 2159 2160 fs_nmlen += 1; /* Include the null byte for the compare */ 2161 /* 2162 * Let's start keeping track of the file system type. Most 2163 * things we need to do differently really depend on the 2164 * file system type. As an example we know that FAT file systems 2165 * do not update the modify time on drectories. 2166 */ 2167 if (strncmp(fsname, "FAT", fs_nmlen) == 0) 2168 share->ss_fstype = SMB_FS_FAT; 2169 else if (strncmp(fsname, "FAT12", fs_nmlen) == 0) 2170 share->ss_fstype = SMB_FS_FAT; 2171 else if (strncmp(fsname, "FAT16", fs_nmlen) == 0) 2172 share->ss_fstype = SMB_FS_FAT; 2173 else if (strncmp(fsname, "FAT32", fs_nmlen) == 0) 2174 share->ss_fstype = SMB_FS_FAT; 2175 else if (strncmp(fsname, "CDFS", fs_nmlen) == 0) 2176 share->ss_fstype = SMB_FS_CDFS; 2177 else if (strncmp(fsname, "UDF", fs_nmlen) == 0) 2178 share->ss_fstype = SMB_FS_UDF; 2179 else if (strncmp(fsname, "NTFS", fs_nmlen) == 0) 2180 share->ss_fstype = SMB_FS_NTFS_UNKNOWN; /* Could be lying */ 2181 2182 SMBWARNING("%s/%s type '%s', attr 0x%x, maxfilename %d\n", 2183 SSTOVC(share)->vc_srvname, share->ss_name, fsname, 2184 share->ss_attributes, share->ss_maxfilenamelen); 2185 /* 2186 * NT4 will not return the FILE_NAMED_STREAMS bit in the ss_attributes 2187 * even though they support streams. So if its a NT4 server and a 2188 * NTFS file format then turn on the streams flag. 2189 */ 2190 if ((SSTOVC(share)->vc_flags & SMBV_NT4) && (share->ss_fstype & SMB_FS_NTFS_UNKNOWN)) 2191 share->ss_attributes |= FILE_NAMED_STREAMS; 2192 /* 2193 * The server says they support streams and they say they are NTFS. So mark 2194 * the subtype as NTFS. Remember a lot of non Windows servers pretend 2195 * their NTFS so they can support ACLs, but they aren't really because they have 2196 * no stream support. This allows us to tell the difference. 2197 */ 2198 if ((share->ss_fstype == SMB_FS_NTFS_UNKNOWN) && (share->ss_attributes & FILE_NAMED_STREAMS)) 2199 share->ss_fstype = SMB_FS_NTFS; /* Real NTFS Volume */ 2200 else if ((share->ss_fstype == SMB_FS_NTFS_UNKNOWN) && (UNIX_SERVER(SSTOVC(share)))) 2201 share->ss_fstype = SMB_FS_NTFS_UNIX; /* UNIX system lying about being NTFS */ 2202 /* Some day mark it as being Mac OS X */ 2203 } 2204done: 2205 SMB_FREE(fsname, M_SMBSTR); 2206 smb_t2_done(t2p); 2207} 2208 2209/* 2210 * The calling routine must hold a reference on the share 2211 */ 2212int 2213smb1fs_statfs(struct smb_share *share, struct vfsstatfs *sbp, vfs_context_t context) 2214{ 2215 struct smb_t2rq *t2p; 2216 struct mbchain *mbp; 2217 struct mdchain *mdp; 2218 uint32_t bpu, bsize32; 2219 uint64_t s, t, f; 2220 int error; 2221 size_t xmax; 2222 2223 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_QUERY_FS_INFORMATION, 1, context, &t2p); 2224 if (error) 2225 return error; 2226 mbp = &t2p->t2_tparam; 2227 mb_init(mbp); 2228 2229 /* SMB_QFS_SIZE_INFO info level allows us to return large volume sizes. 2230 * 2231 * Total number of allocated units as a 64 bit value 2232 * Number of free units as a 64 bit value 2233 * Number of sectors in each unit as a 32 bit value 2234 * Number of bytes in each sector as a 32 bit value 2235 */ 2236 mb_put_uint16le(mbp, SMB_QFS_SIZE_INFO); 2237 t2p->t2_maxpcount = 4; 2238 /* The call returns two 64 bit values and two 32 bit value */ 2239 t2p->t2_maxdcount = (8 * 2) + (4 * 2); 2240 2241 error = smb_t2_request(t2p); 2242 if (error) { 2243 smb_t2_done(t2p); 2244 return error; 2245 } 2246 mdp = &t2p->t2_rdata; 2247 /* 2248 * At this point md_cur and md_top have the same value. Now all the md_get 2249 * routines will will check for null, but just to be safe we check here 2250 */ 2251 if (mdp->md_cur == NULL) { 2252 SMBWARNING("Parsing error reading the message\n"); 2253 smb_t2_done(t2p); 2254 return EBADRPC; 2255 } 2256 /* Now retrieve the correct inforamtion. */ 2257 md_get_uint64le(mdp, &t); /* Total number of allocated units */ 2258 md_get_uint64le(mdp, &f); /* Number of free units */ 2259 md_get_uint32le(mdp, &bpu); /* Number of sectors in each unit */ 2260 md_get_uint32le(mdp, &bsize32); /* Number of bytes in a sector */ 2261 s = bsize32; 2262 s *= bpu; 2263 /* 2264 * Don't allow over-large blocksizes as they determine 2265 * Finder List-view size granularities. On the other 2266 * hand, we mustn't let the block count overflow the 2267 * 31 bits available. 2268 */ 2269 while (s > 16 * 1024) { 2270 if (t > LONG_MAX) 2271 break; 2272 s /= 2; 2273 t *= 2; 2274 f *= 2; 2275 } 2276 while (t > LONG_MAX) { 2277 t /= 2; 2278 f /= 2; 2279 s *= 2; 2280 } 2281 sbp->f_bsize = (uint32_t)s; /* fundamental file system block size */ 2282 sbp->f_blocks= t; /* total data blocks in file system */ 2283 sbp->f_bfree = f; /* free blocks in fs */ 2284 sbp->f_bavail= f; /* free blocks avail to non-superuser */ 2285 sbp->f_files = (-1); /* total file nodes in file system */ 2286 sbp->f_ffree = (-1); /* free file nodes in fs */ 2287 smb_t2_done(t2p); 2288 2289 /* Done with the network stuff now get the iosize, this code was moved from smbfs_vfs_getattr to here */ 2290 2291 /* 2292 * Now get the iosize, this code was down in smbfs_vfs_getattr, but now we do it here 2293 * 2294 * The Finder will in general use the f_iosize as its i/o buffer size. We want to give it the 2295 * largest size which is less than the UBC/UPL limit (SMB_IOMAX) but is also a multiple of our 2296 * maximum xfer size in a single smb. If possible we would like for every offset to be on a PAGE_SIZE 2297 * boundary. So the way to force that is make sure the f_iosize always ends up on a PAGE_SIZE boundary. 2298 * Our second goal is to use as many smb xfer as possible, but also have the f_iosize end on a xfer 2299 * boundary. We can do this in all cases, but they smb xfer must be on a 1K boundary. 2300 * 2301 * NOTE: Remember that if the server sets the SMB_CAP_LARGE bit then we have complete control of the 2302 * xmax size. So our goal here is to work with those systems and do the best we can for others. So currently 2303 * we we have two different numbers for SMB_CAP_LARGE servers, 60K for Windows and 126K for the others. Since 2304 * this will affect most systems we are dealing with make sure are numbers always work in those two cases. For 2305 * all other cases just do the best we can do. 2306 * 2307 * NOTE: We always make sure that vc_rxmax and vc_wxmax are on a 1k boundary! 2308 */ 2309 2310 xmax = max(SSTOVC(share)->vc_rxmax, SSTOVC(share)->vc_wxmax); 2311 2312 /* 2313 * Now we want to make sure it will land on both a PAGE_SIZE boundary and a 2314 * smb xfer size boundary. So first mod the xfer size by the page size, then 2315 * subtract that from page size. This will give us the extra amount that 2316 * will be needed to get it on a page boundary. Now divide the page size by 2317 * this amount. This will give us the number of xmax it will take to make 2318 * f_iosize land on a page size and xfer boundary. 2319 */ 2320 xmax = (PAGE_SIZE / (PAGE_SIZE - (xmax % PAGE_SIZE))) * xmax; 2321 if (xmax > SMB_IOMAX) 2322 sbp->f_iosize = SMB_IOMAX; 2323 else 2324 sbp->f_iosize = (SMB_IOMAX/xmax) * xmax; 2325 /* 2326 * Examples: 2327 * Windows (xfer is 60K) - f_iosize 2328 * (4 / (4 - (60 % 4))) * 60 = 60 2329 * (1024 / 60) * 60 = 1020 2330 * (1020 / PAGE_SIZE) = exactly 255 pages 2331 * (1020 / 60) = exactly 17 xfer 2332 * 2333 * Snow (xfer is 126K) - f_iosize 2334 * (4 / (4 - (126 % 4))) * 126 = 252 2335 * (1024 / 252) * 252 = 1008 2336 * (1008 / PAGE_SIZE) = exactly 252 pages 2337 * (1008 / 126) = exactly 8 xfer 2338 * 2339 * Lion (xfer is 128K) - f_iosize 2340 * (4 / (4 - (128 % 4))) * 128 = 128 2341 * (1024 / 128) * 128 = 1024 2342 * (1024 / PAGE_SIZE) = exactly 256 pages 2343 * (1024 / 128) = exactly 8 xfer 2344 */ 2345 2346 return 0; 2347} 2348 2349/* 2350 * The calling routine must hold a reference on the share 2351 */ 2352int 2353smbfs_smb_t2rename(struct smb_share *share, struct smbnode *np, 2354 const char *tname, size_t tnmlen, int overwrite, 2355 SMBFID *infid, vfs_context_t context) 2356{ 2357 struct smb_t2rq *t2p; 2358 struct mbchain *mbp; 2359 int32_t *ucslenp; 2360 size_t outLen = 0; 2361 int error, cerror; 2362 SMBFID fid = 0; 2363 int need_close = 0; 2364 uint16_t smb1_fid = 0; 2365 2366 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 2367 SMBERROR("smbfs_smb_t2rename not supported by SMB 2/3\n"); 2368 error = ENOTSUP; 2369 return error; 2370 } 2371 2372 if (infid) { 2373 fid = *infid; 2374 smb1_fid = (uint16_t) fid; 2375 } 2376 else { 2377 fid = 0; 2378 } 2379 2380 /* 2381 * We will continue to return not supported here. If the calling routine 2382 * needs a different error then it needs to make this check before calling 2383 * this routine. 2384 */ 2385 if (!(VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU)) 2386 return (ENOTSUP); 2387 /* 2388 * Rember that smb_t2_alloc allocates t2p. We need to call 2389 * smb_t2_done to free it. 2390 */ 2391 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_FILE_INFORMATION, 1, context, &t2p); 2392 if (error) 2393 return error; 2394 2395 if (!infid) { 2396 /* 2397 * See if we can open the item with delete access. Requesting 2398 * delete access can mean more then just requesting to delete 2399 * the file. It is used to mark the item for deletion on close 2400 * and for renaming an open file. If I find any other uses for 2401 * it I will add them to this comment. 2402 */ 2403 error = smbfs_tmpopen(share, np, SMB2_DELETE, &fid, context); 2404 if (error) 2405 goto exit; 2406 need_close = 1; 2407 smb1_fid = fid; 2408 } 2409 mbp = &t2p->t2_tparam; 2410 mb_init(mbp); 2411 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 2412 mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION); 2413 mb_put_uint16le(mbp, 0); /* reserved, nowadays */ 2414 mbp = &t2p->t2_tdata; 2415 mb_init(mbp); 2416 mb_put_uint32le(mbp, overwrite); 2417 mb_put_uint32le(mbp, 0); /* Root fid, not used */ 2418 /* Reserve file name location */ 2419 ucslenp = (int32_t *)mb_reserve(mbp, sizeof(int32_t)); 2420 error = smb_put_dmem(mbp, tname, tnmlen, UTF_SFM_CONVERSIONS, 2421 SMB_UNICODE_STRINGS(SSTOVC(share)), &outLen); 2422 if (!error) 2423 error = mb_put_uint16le(mbp, 0); 2424 if (error) 2425 goto exit; 2426 /* Now we can put the file name length into the buffer */ 2427 *ucslenp = htolel((int32_t)outLen); 2428 t2p->t2_maxpcount = 2; 2429 t2p->t2_maxdcount = 0; 2430 error = smb_t2_request(t2p); 2431exit:; 2432 if (need_close == 1) { 2433 cerror = smbfs_tmpclose(share, np, fid, context); 2434 if (cerror) { 2435 SMBWARNING("error %d closing fid %llx\n", cerror, fid); 2436 } 2437 } 2438 smb_t2_done(t2p); 2439 return (error); 2440} 2441 2442/* 2443 * smbfs_delete_openfile 2444 * 2445 * We have an open file that they want to delete. Use the NFS silly rename 2446 * trick, but try to do better than NFS. The picking of the name came from the 2447 * NFS code. So we first open the file for deletion. Now come up with a new 2448 * name and rename the file. Make the file hidden if we can. Now lets mark 2449 * it for deletion and close the file. If the rename fails then the whole call 2450 * should fail. If the mark for deletion call fails just set a flag on the 2451 * vnode and delete it when we close. 2452 * 2453 * The calling routine must hold a reference on the share 2454 * 2455 */ 2456int 2457smbfs_delete_openfile(struct smb_share *share, struct smbnode *dnp, 2458 struct smbnode *np, vfs_context_t context) 2459{ 2460 struct proc *p; 2461 SMBFID fid = 0; 2462 int error, cerror; 2463 char s_name[32]; /* make sure that sillyrename_name will fit */ 2464 size_t s_namlen; 2465 int i, j, k; 2466 int need_close = 0; 2467 int need_hide = 0; 2468 int samba_bug = 0; 2469 struct smbmount *smp = np->n_mount; 2470 uint64_t ino = 0; 2471 uint64_t hashval = 0; 2472 char *new_name = NULL; 2473 char *old_name = NULL; 2474 2475 /* Should never happen, but just to be safe */ 2476 if (context == NULL) { 2477 return ENOTSUP; 2478 } 2479 p = vfs_context_proc(context); 2480 2481 if (!(SSTOVC(share)->vc_flags & SMBV_SMB2)) { 2482 /* 2483 * SMB 1 2484 * 2485 * smbfs_smb_t2rename requires passthru, so just return EBUSY since we 2486 * are attempting to delete an open file. 2487 */ 2488 if (!(VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU)) { 2489 return EBUSY; 2490 } 2491 2492 error = smbfs_tmpopen(share, np, SMB2_DELETE, &fid, context); 2493 if (error) { 2494 return (error); 2495 } 2496 need_close = 1; 2497 2498 /* SMB 2/3 will not hide the file as I deem it unnecessary work */ 2499 need_hide = 1; 2500 } 2501 2502 if (SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) { 2503 /* 2504 * Use the unique File ID to create a unique name 2505 */ 2506 lck_rw_lock_shared(&np->n_name_rwlock); 2507 ino = smb2fs_smb_file_id_get(smp, np->n_ino, np->n_name); 2508 lck_rw_unlock_shared(&np->n_name_rwlock); 2509 2510 /* Just try once to rename in the same dir */ 2511 MAKE_DELETED_NAME((char*) s_name, sizeof(s_name), ino); 2512 s_namlen = strlen((char *) s_name); 2513 2514 error = smbfs_smb_rename(share, np, dnp, s_name, s_namlen, context); 2515 } 2516 else { 2517 /* 2518 * No File IDs, so have to use NFS naming convention to find unique 2519 * name. Get the first silly name 2520 */ 2521 s_namlen = snprintf(s_name, sizeof(s_name), ".smbdeleteAAA%04x4.4", 2522 proc_pid(p)); 2523 if (s_namlen >= sizeof(s_name)) { 2524 error = ENOENT; 2525 goto out; 2526 } 2527 2528 /* Try rename until we get one that isn't there */ 2529 i = j = k = 0; 2530 2531 do { 2532 if ((SSTOVC(share)->vc_flags & SMBV_SMB2) || 2533 (samba_bug == 1)) { 2534 /* SMB 2/3 or dealing with SAMBA buggy server */ 2535 error = smbfs_smb_rename(share, np, dnp, s_name, s_namlen, 2536 context); 2537 } 2538 else { 2539 /* SMB 1 */ 2540 error = smbfs_smb_t2rename(share, np, s_name, s_namlen, 0, &fid, 2541 context); 2542 2543 if (((error == ENOENT) || (error == ENOTSUP)) && 2544 SMBTOV(dnp) && 2545 (samba_bug == 0)) { 2546 /* 2547 * SAMBA Bug: 2548 * 2549 * Some times the SAMBA code gets confused and fails the 2550 * above rename with an ENOENT error. We need to make sure 2551 * this code works with all SAMBA servers, so try again 2552 * with the old rename call. SAMBA allows us to rename an 2553 * open file with this call, but not with delete access. 2554 * So close it, rename it and hide it. Once the SAMBA 2555 * server is in this state, it will always return an error, 2556 * so just use the old rename from now on. 2557 */ 2558 if (need_close == 1) { 2559 (void)smbfs_tmpclose(share, np, fid, context); 2560 need_close = 0; 2561 } 2562 2563 /* loop around and try with old rename */ 2564 samba_bug = 1; 2565 continue; 2566 } 2567 } 2568 2569 if (error && (error != EEXIST)) { 2570 /* 2571 * They returned an error we did not expect. If the silly name 2572 * file exists then we want to keep trying. So do a look up and 2573 * if the file exists, keep trying otherwise just get out since 2574 * there is nothing else for us to do. 2575 */ 2576 if (smbfs_smb_query_info(share, dnp, VREG, 2577 s_name, s_namlen, NULL, context) == 0) { 2578 /* That name exists on server, keep trying for a new name */ 2579 error = EEXIST; 2580 } 2581 else { 2582 break; 2583 } 2584 } 2585 2586 /* 2587 * The file name already exists, try another one. This code was 2588 * taken from NFS. NFS tested by doing a lookup, we use the rename 2589 * call, see above for how we handle strange errors. If the rename 2590 * call fails, keep trying till we run out of names. 2591 */ 2592 if (error) { 2593 if (s_name[10]++ >= 'z') 2594 s_name[10] = 'A'; 2595 if (++i > ('z' - 'A' + 1)) { 2596 i = 0; 2597 if (s_name[11]++ >= 'z') 2598 s_name[11] = 'A'; 2599 if (++j > ('z' - 'A' + 1)) { 2600 j = 0; 2601 if (s_name[12]++ >= 'z') 2602 s_name[12] = 'A'; 2603 if (++k > ('z' - 'A' + 1)) { 2604 error = EINVAL; 2605 } 2606 } 2607 } 2608 } 2609 } while (error == EEXIST); 2610 } 2611 2612 if (error) { 2613 goto out; 2614 } 2615 2616 /* 2617 * At this point, the file has been successfully renamed on the server. 2618 */ 2619 2620 if (need_hide) { 2621 /* ignore any errors return from hiding the item */ 2622 (void)smbfs_set_hidden_bit(share, dnp, VREG, 2623 s_name, s_namlen, 2624 TRUE, context); 2625 } 2626 2627 if ((SSTOVC(share)->vc_flags & SMBV_SMB2) || (samba_bug == 1)) { 2628 /* 2629 * SMB 2/3 will always just wait until last close to do the delete. 2630 * This matches AFP behavior. 2631 * If we hit the SAMBA bug, then the file is closed so cant set the 2632 * Delete on Close because we have no fid. 2633 */ 2634 np->n_flag |= NDELETEONCLOSE; 2635 } 2636 else { 2637 /* SMB 1 - Set file for Delete on Close */ 2638 cerror = smbfs_smb_markfordelete(share, fid, context); 2639 if (cerror) { 2640 /* 2641 * Failed to delete it now, so just wait until last close to do 2642 * the delete. Could be SAMBA misbehaving. 2643 */ 2644 np->n_flag |= NDELETEONCLOSE; 2645 } 2646 } 2647 2648out: 2649 if (need_close == 1) { 2650 cerror = smbfs_tmpclose(share, np, fid, context); 2651 if (cerror) { 2652 SMBWARNING("error %d closing fid %llx\n", cerror, fid); 2653 } 2654 } 2655 2656 if (!error) { 2657 lck_rw_lock_exclusive(&np->n_name_rwlock); 2658 2659 new_name = smb_strndup(s_name, s_namlen); 2660 old_name = np->n_name; 2661 2662 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) || 2663 !(np->n_flag & NDELETEONCLOSE)) { 2664 /* 2665 * If no File IDs OR if we deleted it now, then remove the node 2666 * from hash table 2667 */ 2668 smb_vhashrem(np); 2669 } 2670 2671 /* Now reset the name, so other path lookups can use it. */ 2672 if (new_name) { 2673 np->n_name = new_name; 2674 np->n_nmlen = s_namlen; 2675 2676 /* Mark smb node so Meta data cache never expires */ 2677 np->n_flag |= NMARKEDFORDLETE; 2678 2679 if (!(SSTOVC(share)->vc_misc_flags & SMBV_HAS_FILEIDS) && 2680 !(np->n_flag & NDELETEONCLOSE)) { 2681 /* 2682 * If no File IDs AND the file has not been deleted yet, then 2683 * add it back into hash table. 2684 */ 2685 hashval = smbfs_hash(NULL, 0, np->n_name, np->n_nmlen); 2686 smb_vhashadd(np, hashval); 2687 } 2688 2689 /* Now its safe to free the old name */ 2690 SMB_FREE(old_name, M_SMBNODENAME); 2691 } 2692 2693 lck_rw_unlock_exclusive(&np->n_name_rwlock); 2694 } 2695 else { 2696 /* All errors are mapped to EBUSY */ 2697 error = EBUSY; 2698 } 2699 2700 return(error); 2701} 2702 2703/* 2704 * This routine will send a flush across the wire to the server. This is an expensive 2705 * operation that should only be done when the user request it. 2706 * 2707 * The calling routine must hold a reference on the share 2708 * 2709 */ 2710int 2711smb1fs_smb_flush(struct smb_share *share, SMBFID fid, vfs_context_t context) 2712{ 2713 struct smb_rq rq, *rqp = &rq; 2714 struct mbchain *mbp; 2715 int error; 2716 uint16_t smb1_fid = (uint16_t) fid; 2717 2718 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_FLUSH, 0, context); 2719 if (error) { 2720 goto done; 2721 } 2722 smb_rq_getrequest(rqp, &mbp); 2723 smb_rq_wstart(rqp); 2724 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 2725 smb_rq_wend(rqp); 2726 smb_rq_bstart(rqp); 2727 smb_rq_bend(rqp); 2728 error = smb_rq_simple(rqp); 2729 /* 2730 * Flushed failed on a reconnect. The server will flush the file when it 2731 * closes the file after the connection goes down. Ignore the error in this case. 2732 */ 2733 if ((error == EBADF) && (rqp->sr_flags & SMBR_REXMIT)) 2734 error = 0; 2735 smb_rq_done(rqp); 2736done: 2737 if (error) { 2738 SMBWARNING("smbfs_smb_flush failed error = %d\n", error); 2739 } 2740 return (error); 2741} 2742 2743/* 2744 * This routine will send a seteof across the wire to the server. 2745 * 2746 * The calling routine must hold a reference on the share 2747 * 2748 */ 2749int 2750smb1fs_seteof(struct smb_share *share, SMBFID fid, uint64_t newsize, 2751 vfs_context_t context) 2752{ 2753 struct mbchain *mbp; 2754 int error; 2755 uint16_t smb1_fid = (uint16_t) fid; 2756 struct smb_t2rq *t2p; 2757 2758 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_FILE_INFORMATION, 1, context, &t2p); 2759 if (error) 2760 return error; 2761 mbp = &t2p->t2_tparam; 2762 mb_init(mbp); 2763 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 2764 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 2765 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION); 2766 else 2767 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO); 2768 mb_put_uint16le(mbp, 0); 2769 mbp = &t2p->t2_tdata; 2770 mb_init(mbp); 2771 mb_put_uint64le(mbp, newsize); 2772 t2p->t2_maxpcount = 2; 2773 t2p->t2_maxdcount = 0; 2774 error = smb_t2_request(t2p); 2775 smb_t2_done(t2p); 2776 2777 return error; 2778} 2779 2780 2781/* 2782 * This routine will send an allocation across the wire to the server. 2783 * 2784 * The calling routine must hold a reference on the share 2785 * 2786 */ 2787int 2788smb1fs_set_allocation(struct smb_share *share, SMBFID fid, uint64_t newsize, 2789 vfs_context_t context) 2790{ 2791 struct smb_t2rq *t2p; 2792 struct mbchain *mbp; 2793 int error; 2794 uint16_t smb1_fid = (uint16_t) fid; 2795 2796 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_FILE_INFORMATION, 1, context, &t2p); 2797 if (error) 2798 return error; 2799 mbp = &t2p->t2_tparam; 2800 mb_init(mbp); 2801 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 2802 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 2803 mb_put_uint16le(mbp, SMB_SFILEINFO_ALLOCATION_INFORMATION); 2804 else 2805 mb_put_uint16le(mbp, SMB_SFILEINFO_ALLOCATION_INFO); 2806 mb_put_uint16le(mbp, 0); 2807 mbp = &t2p->t2_tdata; 2808 mb_init(mbp); 2809 mb_put_uint64le(mbp, newsize); 2810 t2p->t2_maxpcount = 2; 2811 t2p->t2_maxdcount = 0; 2812 error = smb_t2_request(t2p); 2813 smb_t2_done(t2p); 2814 return error; 2815} 2816 2817/* 2818 * Set the eof and clear and set the node flags required, 2819 * 2820 * The calling routine must hold a reference on the share 2821 * 2822 */ 2823int 2824smbfs_seteof(struct smb_share *share, struct smbnode *np, SMBFID fid, 2825 uint64_t newsize, vfs_context_t context) 2826{ 2827 int error; 2828 2829 error = smbfs_smb_seteof(share, fid, newsize, context); 2830 if (error && (error != EBADF)) { 2831 /* Not a reconnect error then report it */ 2832 SMBWARNING("smbfs_node_seteof failed error = %d\n", error); 2833 } else if (!error) { 2834 np->n_flag &= ~NNEEDS_EOF_SET; 2835 np->n_flag |= NNEEDS_FLUSH; 2836 } 2837 return error; 2838} 2839 2840/* 2841 * See if we have a pending seteof or need to flush the file. 2842 * 2843 * The calling routine must hold a reference on the share 2844 * 2845 */ 2846int 2847smbfs_smb_fsync(struct smb_share *share, struct smbnode *np, vfs_context_t context) 2848{ 2849 int error; 2850 SMBFID fid = 0; 2851 2852 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_START, np->n_flag, 0, 0, 0, 0); 2853 2854 if ((np->n_flag & (NNEEDS_EOF_SET | NNEEDS_FLUSH)) == 0) { 2855 /* Nothing to do here just return */ 2856 error = 0; 2857 goto done; 2858 } 2859 2860 if ((np->f_refcnt <= 0) || (!SMBTOV(np)) || (!vnode_isreg(SMBTOV(np)))) { 2861 error = 0; /* not a regular open file */ 2862 goto done; 2863 } 2864 2865 /* Before trying the flush see if the file needs to be reopened */ 2866 error = smbfs_smb_reopen_file(share, np, context); 2867 if (error) { 2868 SMBDEBUG_LOCK(np, " %s waiting to be revoked\n", np->n_name); 2869 goto done; 2870 } 2871 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_NONE, 0xabc001, error, 0, 0, 0); 2872 2873 /* See if the file is opened for write access */ 2874 if (FindFileRef(SMBTOV(np), vfs_context_proc(context), kAccessWrite, 2875 kCheckDenyOrLocks, 0, 0, NULL, &fid)) { 2876 fid = np->f_fid; /* Nope use the shared fid */ 2877 if ((fid == 0) || 2878 ((np->f_accessMode & kAccessWrite) != kAccessWrite)) { 2879 error = 0; /* Nothing to do here get out */ 2880 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_NONE, 2881 0xabc002, error, 0, 0, 0); 2882 goto done; 2883 } 2884 } 2885 /* We have a set eof pending do it here and clear the flag */ 2886 if (np->n_flag & NNEEDS_EOF_SET) { 2887 error = smbfs_seteof(share, np, fid, np->n_size, context); 2888 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_NONE, 2889 0xabc003, error, 0, 0, 0); 2890 if (error) { 2891 goto done; 2892 } 2893 } 2894 error = smbfs_smb_flush(share, fid, context); 2895 if (!error) 2896 np->n_flag &= ~NNEEDS_FLUSH; 2897 2898 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_NONE, 0xabc004, error, 0, 0, 0); 2899 2900done: 2901 SMB_LOG_KTRACE(SMB_DBG_SMB_FSYNC | DBG_FUNC_END, error, 0, 0, 0, 0); 2902 return error; 2903} 2904 2905/* 2906 * We should replace it with something more modern. See <rdar://problem/7595213>. 2907 * This routine is only used to test the existence of an item or to get its 2908 * DOS attributes when changing the status of the HIDDEN bit. 2909 * 2910 * The calling routine must hold a reference on the share 2911 * 2912 * Eventually, smb1fs_smb_query_info will just go away and we wont have to worry 2913 * about it using an old call any more. 2914 */ 2915int 2916smb1fs_smb_query_info(struct smb_share *share, struct smbnode *np, 2917 const char *name, size_t len, uint32_t *in_attr, 2918 vfs_context_t context) 2919{ 2920 struct smb_rq rq, *rqp = &rq; 2921 struct mbchain *mbp; 2922 struct mdchain *mdp; 2923 uint8_t wc = 0; 2924 int error; 2925 uint16_t attr; 2926 2927 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_QUERY_INFORMATION, 0, context); 2928 if (error) 2929 return error; 2930 smb_rq_getrequest(rqp, &mbp); 2931 smb_rq_wstart(rqp); 2932 smb_rq_wend(rqp); 2933 smb_rq_bstart(rqp); 2934 mb_put_uint8(mbp, SMB_DT_ASCII); 2935 error = smbfs_fullpath(mbp, np, name, &len, UTF_SFM_CONVERSIONS, 2936 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 2937 if (!error) { 2938 smb_rq_bend(rqp); 2939 error = smb_rq_simple(rqp); 2940 } 2941 if (!error && in_attr) { 2942 smb_rq_getreply(rqp, &mdp); 2943 md_get_uint8(mdp, &wc); 2944 error = md_get_uint16le(mdp, &attr); 2945 *in_attr = attr; 2946 } 2947 smb_rq_done(rqp); 2948 return error; 2949} 2950 2951/* 2952 * Set DOS file attributes, may want to replace with a more modern call 2953 * 2954 * The calling routine must hold a reference on the share 2955 * 2956 */ 2957int 2958smb1fs_smb_setpattr(struct smb_share *share, struct smbnode *np, 2959 const char *name, size_t len, 2960 uint16_t attr, vfs_context_t context) 2961{ 2962 struct smb_rq rq, *rqp = &rq; 2963 struct mbchain *mbp; 2964 uint32_t time; 2965 int error; 2966 2967 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_SET_INFORMATION, 0, context); 2968 if (error) 2969 return error; 2970 smb_rq_getrequest(rqp, &mbp); 2971 smb_rq_wstart(rqp); 2972 mb_put_uint16le(mbp, attr); 2973 time = 0; 2974 mb_put_uint32le(mbp, time); /* mtime */ 2975 mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 2976 smb_rq_wend(rqp); 2977 smb_rq_bstart(rqp); 2978 mb_put_uint8(mbp, SMB_DT_ASCII); 2979 do { 2980 error = smbfs_fullpath(mbp, np, name, &len, UTF_SFM_CONVERSIONS, 2981 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 2982 if (error) 2983 break; 2984 if (SMB_UNICODE_STRINGS(SSTOVC(share))) { 2985 mb_put_padbyte(mbp); 2986 mb_put_uint8(mbp, 0); /* 1st byte of NULL Unicode char */ 2987 } 2988 mb_put_uint8(mbp, 0); 2989 smb_rq_bend(rqp); 2990 error = smb_rq_simple(rqp); 2991 if (error) 2992 break; 2993 } while(0); 2994 smb_rq_done(rqp); 2995 return error; 2996} 2997 2998/* 2999 * The calling routine must hold a reference on the share 3000 */ 3001int 3002smbfs_set_hidden_bit(struct smb_share *share, struct smbnode *dnp, enum vtype vnode_type, 3003 const char *name, size_t len, 3004 Boolean hideit, vfs_context_t context) 3005{ 3006 int error; 3007 uint32_t attr; 3008 3009 /* Look it up and get the dos attributes */ 3010 error = smbfs_smb_query_info(share, dnp, vnode_type, 3011 name, len, 3012 &attr, context); 3013 if (error) { 3014 return error; 3015 } 3016 3017 if (hideit && !(attr & SMB_EFA_HIDDEN)) { 3018 attr |= SMB_EFA_HIDDEN; 3019 } else if (!hideit && (attr & SMB_EFA_HIDDEN)) { 3020 attr &= ~SMB_EFA_HIDDEN; 3021 } else { 3022 return 0; /* Nothing to do here */ 3023 } 3024 3025 return smbfs_smb_setpattr(share, dnp, vnode_type, 3026 name, len, 3027 attr, context); 3028} 3029 3030/* 3031 * The calling routine must hold a reference on the share 3032 */ 3033int 3034smbfs_set_unix_info2(struct smb_share *share, struct smbnode *np, 3035 struct timespec *crtime, struct timespec *mtime, 3036 struct timespec *atime, uint64_t fsize, uint64_t perms, 3037 uint32_t FileFlags, uint32_t FileFlagsMask, vfs_context_t context) 3038{ 3039 struct smb_t2rq *t2p; 3040 struct mbchain *mbp; 3041 uint64_t tm; 3042 uint32_t ftype; 3043 int error; 3044 3045 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_PATH_INFORMATION, 1, context, &t2p); 3046 if (error) 3047 return error; 3048 mbp = &t2p->t2_tparam; 3049 mb_init(mbp); 3050 mb_put_uint16le(mbp, SMB_SFILEINFO_UNIX_INFO2); 3051 mb_put_uint32le(mbp, 0); /* MBZ */ 3052 error = smbfs_fullpath(mbp, np, NULL, NULL, UTF_SFM_CONVERSIONS, 3053 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 3054 if (error) { 3055 smb_t2_done(t2p); 3056 return error; 3057 } 3058 3059 mbp = &t2p->t2_tdata; 3060 mb_init(mbp); 3061 /* File size */ 3062 mb_put_uint64le(mbp, fsize); 3063 /* Number of blocks used on disk */ 3064 tm = SMB_SIZE_NO_CHANGE; 3065 mb_put_uint64le(mbp, tm); 3066 3067 /* Set the change time, not allowed */ 3068 mb_put_uint64le(mbp, 0); 3069 3070 /* set the access time */ 3071 if (atime) 3072 smb_time_local2NT(atime, &tm, FALSE); 3073 else 3074 tm = 0; 3075 mb_put_uint64le(mbp, tm); 3076 3077 /* set the write/modify time */ 3078 if (mtime) 3079 smb_time_local2NT(mtime, &tm, FALSE); 3080 else 3081 tm = 0; 3082 mb_put_uint64le(mbp, tm); 3083 3084 /* Numeric user id for the owner */ 3085 tm = SMB_UID_NO_CHANGE; 3086 mb_put_uint64le(mbp, tm); 3087 /* Numeric group id of owner */ 3088 tm = SMB_GID_NO_CHANGE; 3089 mb_put_uint64le(mbp, tm); 3090 /* Enumeration specifying the file type */ 3091 ftype = SMB_DEFAULT_NO_CHANGE; 3092 mb_put_uint32le(mbp, ftype); 3093 /* Major device number if type is device */ 3094 tm = SMB_DEFAULT_NO_CHANGE; 3095 mb_put_uint64le(mbp, tm); 3096 /* Minor device number if type is device */ 3097 tm = SMB_DEFAULT_NO_CHANGE; 3098 mb_put_uint64le(mbp, tm); 3099 /* This is a server-assigned unique id */ 3100 tm = SMB_DEFAULT_NO_CHANGE; 3101 mb_put_uint64le(mbp, tm); 3102 /* Standard UNIX permissions */ 3103 mb_put_uint64le(mbp, perms); 3104 /* Number of hard link */ 3105 tm = SMB_DEFAULT_NO_CHANGE; 3106 mb_put_uint64le(mbp, tm); 3107 /* set the creation time */ 3108 if (crtime) 3109 smb_time_local2NT(crtime, &tm, FALSE); 3110 else 3111 tm = 0; 3112 mb_put_uint64le(mbp, tm); 3113 /* File flags enumeration */ 3114 mb_put_uint32le(mbp, FileFlags); 3115 /* Mask of valid flags */ 3116 mb_put_uint32le(mbp, FileFlagsMask); 3117 3118 t2p->t2_maxpcount = 24; 3119 t2p->t2_maxdcount = 116; 3120 error = smb_t2_request(t2p); 3121 3122 smb_t2_done(t2p); 3123 return error; 3124 3125} 3126 3127/* 3128 * BASIC_INFO works with Samba, but Win2K servers say it is an invalid information 3129 * level on a SET_PATH_INFO. Note Win2K does support *BASIC_INFO on a SET_FILE_INFO, 3130 * and they support the equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure. 3131 * 3132 * The calling routine must hold a reference on the share 3133 * 3134 */ 3135int 3136smb1fs_smb_setpattrNT(struct smb_share *share, struct smbnode *np, 3137 uint32_t attr, struct timespec *crtime, 3138 struct timespec *mtime, struct timespec *atime, 3139 vfs_context_t context) 3140{ 3141 struct smb_t2rq *t2p; 3142 struct mbchain *mbp; 3143 uint64_t tm; 3144 int error; 3145 3146 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_PATH_INFORMATION, 1, context, &t2p); 3147 if (error) 3148 return error; 3149 mbp = &t2p->t2_tparam; 3150 mb_init(mbp); 3151 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 3152 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION); 3153 else 3154 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO); 3155 mb_put_uint32le(mbp, 0); /* MBZ */ 3156 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 3157 error = smbfs_fullpath(mbp, np, NULL, NULL, UTF_SFM_CONVERSIONS, 3158 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 3159 if (error) { 3160 smb_t2_done(t2p); 3161 return error; 3162 } 3163 3164 mbp = &t2p->t2_tdata; 3165 mb_init(mbp); 3166 3167 /* set the creation time */ 3168 tm = 0; 3169 if (crtime) { 3170 smb_time_local2NT(crtime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3171 } 3172 mb_put_uint64le(mbp, tm); 3173 3174 /* set the access time */ 3175 tm = 0; 3176 if (atime) { 3177 smb_time_local2NT(atime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3178 } 3179 mb_put_uint64le(mbp, tm); 3180 3181 /* set the write/modify time */ 3182 tm = 0; 3183 if (mtime) { 3184 smb_time_local2NT(mtime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3185 } 3186 mb_put_uint64le(mbp, tm); 3187 3188 /* Never let them set the change time */ 3189 tm = 0; 3190 mb_put_uint64le(mbp, tm); 3191 3192 mb_put_uint32le(mbp, attr); /* attr */ 3193 mb_put_uint32le(mbp, 0); /* undocumented padding */ 3194 t2p->t2_maxpcount = 24; 3195 t2p->t2_maxdcount = 56; 3196 error = smb_t2_request(t2p); 3197 3198 smb_t2_done(t2p); 3199 return error; 3200} 3201 3202/* 3203 * Same as above except with a file hanlde. Note once we remove Windows 98 3204 * support we can remove passing the node into this routine. 3205 * 3206 * The calling routine must hold a reference on the share 3207 * 3208 */ 3209int 3210smb1fs_smb_setfattrNT(struct smb_share *share, uint32_t attr, SMBFID fid, 3211 struct timespec *crtime, struct timespec *mtime, 3212 struct timespec *atime, vfs_context_t context) 3213{ 3214 struct smb_t2rq *t2p; 3215 struct mbchain *mbp; 3216 uint64_t tm; 3217 int error; 3218 uint16_t smb1_fid = (uint16_t) fid; 3219 3220 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_FILE_INFORMATION, 1, context, &t2p); 3221 if (error) 3222 return error; 3223 mbp = &t2p->t2_tparam; 3224 mb_init(mbp); 3225 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 3226 if (VC_CAPS(SSTOVC(share)) & SMB_CAP_INFOLEVEL_PASSTHRU) 3227 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION); 3228 else 3229 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO); 3230 mb_put_uint16le(mbp, 0); 3231 mbp = &t2p->t2_tdata; 3232 mb_init(mbp); 3233 3234 /* set the creation time */ 3235 tm = 0; 3236 if (crtime) { 3237 smb_time_local2NT(crtime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3238 } 3239 mb_put_uint64le(mbp, tm); 3240 3241 /* set the access time */ 3242 tm = 0; 3243 if (atime) { 3244 smb_time_local2NT(atime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3245 } 3246 mb_put_uint64le(mbp, tm); 3247 3248 /* set the write/modify time */ 3249 tm = 0; 3250 if (mtime) { 3251 smb_time_local2NT(mtime, &tm, (share->ss_fstype == SMB_FS_FAT)); 3252 } 3253 mb_put_uint64le(mbp, tm); 3254 3255 /* We never allow anyone to set the change time */ 3256 tm = 0; 3257 mb_put_uint64le(mbp, tm); 3258 3259 mb_put_uint32le(mbp, attr); 3260 mb_put_uint32le(mbp, 0); /* padding */ 3261 t2p->t2_maxpcount = 2; 3262 t2p->t2_maxdcount = 0; 3263 error = smb_t2_request(t2p); 3264 smb_t2_done(t2p); 3265 return error; 3266} 3267 3268/* 3269 * Modern create/open of file or directory. 3270 * 3271 * If disp is FILE_OPEN then this is an open attempt, and: 3272 * If xattr then name is the stream to be opened at np, 3273 * Else np should be opened. 3274 * ...we won't touch *fidp, 3275 * Else this is a creation attempt, and: 3276 * If xattr then name is the stream to create at np, 3277 * Else name is the thing to create under directory np. 3278 * ...we will return *fidp, 3279 * 3280 * The calling routine must hold a reference on the share 3281 * 3282 * Either pass in np which is the file/dir to open OR 3283 * pass in dnp and a name 3284 * 3285 */ 3286int 3287smb1fs_smb_ntcreatex(struct smb_share *share, struct smbnode *np, 3288 uint32_t rights, uint32_t shareMode, enum vtype vt, 3289 SMBFID *fidp, const char *name, size_t in_nmlen, 3290 uint32_t disp, int xattr, struct smbfattr *fap, 3291 int do_create, vfs_context_t context) 3292{ 3293 struct smb_rq rq, *rqp = &rq; 3294 int unix_info2 = ((UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP)) ? TRUE : FALSE; 3295 struct mbchain *mbp; 3296 struct mdchain *mdp; 3297 uint8_t wc; 3298 uint32_t lint, createopt, efa; 3299 uint64_t llint; 3300 int error; 3301 uint16_t fid, *namelenp; 3302 size_t nmlen = in_nmlen; /* Don't change the input name length, we need it for making the ino number */ 3303 int need_close = 0; 3304 SMBFID temp_fid = 0; 3305 char *snamep = NULL; 3306 3307 DBG_ASSERT(fap); /* Should never happen */ 3308 bzero(fap, sizeof(*fap)); 3309 nanouptime(&fap->fa_reqtime); 3310 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_NT_CREATE_ANDX, 0, context); 3311 if (error) 3312 return error; 3313 smb_rq_getrequest(rqp, &mbp); 3314 smb_rq_wstart(rqp); 3315 mb_put_uint8(mbp, 0xff); /* secondary command */ 3316 mb_put_uint8(mbp, 0); /* MBZ */ 3317 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 3318 mb_put_uint8(mbp, 0); /* MBZ */ 3319 namelenp = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); 3320 /* 3321 * XP to W2K Server never sets the NTCREATEX_FLAGS_OPEN_DIRECTORY 3322 * for creating nor for opening a directory. Samba ignores the bit. 3323 * 3324 * Request the extended reply to get maximal access 3325 */ 3326 mb_put_uint32le(mbp, NTCREATEX_FLAGS_EXTENDED); /* NTCREATEX_FLAGS_* */ 3327 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ 3328 mb_put_uint32le(mbp, rights); 3329 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 3330 efa = (vt == VDIR) ? SMB_EFA_DIRECTORY : SMB_EFA_NORMAL; 3331 if (disp != FILE_OPEN && !xattr) { 3332 if (efa == SMB_EFA_NORMAL) 3333 efa |= SMB_EFA_ARCHIVE; 3334 if (name && (*name == '.')) 3335 efa |= SMB_EFA_HIDDEN; 3336 } 3337 mb_put_uint32le(mbp, efa); 3338 /* 3339 * To rename an open file we need delete shared access. We currently always 3340 * allow delete access. 3341 */ 3342 mb_put_uint32le(mbp, shareMode); 3343 mb_put_uint32le(mbp, disp); 3344 createopt = 0; 3345 if (disp != FILE_OPEN) { 3346 if (vt == VDIR) 3347 createopt |= NTCREATEX_OPTIONS_DIRECTORY; 3348 /* (other create options currently not useful) */ 3349 } 3350 /* 3351 * The server supports reparse points so open the item with a reparse point 3352 * and bypass normal reparse point processing for the file. 3353 */ 3354 if (share->ss_attributes & FILE_SUPPORTS_REPARSE_POINTS) { 3355 createopt |= NTCREATEX_OPTIONS_OPEN_REPARSE_POINT; 3356 3357 if (np && (np->n_dosattr & SMB_EFA_OFFLINE)) { 3358 /* 3359 * File has been moved to offline storage, do not open with a 3360 * reparse point in this case. See <rdar://problem/10836961>. 3361 */ 3362 createopt &= ~NTCREATEX_OPTIONS_OPEN_REPARSE_POINT; 3363 } 3364 } 3365 3366 mb_put_uint32le(mbp, createopt); 3367 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */ 3368 mb_put_uint8(mbp, 0); /* security flags (?) */ 3369 smb_rq_wend(rqp); 3370 smb_rq_bstart(rqp); 3371 do { 3372 uint16_t resourceType = 0; 3373 uint8_t sep = xattr ? ':' : '\\'; 3374 /* Do they want to open the resource fork? */ 3375 if ((np->n_vnode) && (vnode_isnamedstream(np->n_vnode)) && (!name) && (!xattr)) { 3376 lck_rw_lock_shared(&np->n_name_rwlock); 3377 snamep = smb_strndup(np->n_sname, np->n_snmlen); 3378 name = snamep; 3379 lck_rw_unlock_shared(&np->n_name_rwlock); 3380 3381 nmlen = np->n_snmlen; 3382 sep = ':'; 3383 } 3384 if (name == NULL) 3385 nmlen = 0; 3386 error = smbfs_fullpath(mbp, np, name, &nmlen, UTF_SFM_CONVERSIONS, 3387 SMB_UNICODE_STRINGS(SSTOVC(share)), sep); 3388 if (error) 3389 break; 3390 *namelenp = htoles(nmlen); /* doesn't includes null */ 3391 smb_rq_bend(rqp); 3392 error = smb_rq_simple(rqp); 3393 if (error) 3394 break; 3395 smb_rq_getreply(rqp, &mdp); 3396 /* 3397 * Spec say 26 for word count, but 34 words are defined and observed from 3398 * all servers. 3399 * 3400 * The spec is wrong and word count should always be 34 unless we request 3401 * the extended reply. Now some server will always return 42 even it the 3402 * NTCREATEX_FLAGS_EXTENDED flag is not set. 3403 * 3404 * From the MS-SMB document concern the extend response: 3405 * 3406 * The word count for this response MUST be 0x2A (42). WordCount in this 3407 * case is not used as the count of parameter words but is just a number. 3408 */ 3409 error = md_get_uint8(mdp, &wc); 3410 if (!error) { 3411 md_get_uint8(mdp, NULL); /* secondary cmd */ 3412 md_get_uint8(mdp, NULL); /* mbz */ 3413 md_get_uint16le(mdp, NULL); /* andxoffset */ 3414 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 3415 error = md_get_uint16(mdp, &fid); /* yes, leaving it LE */ 3416 need_close = 1; 3417 } 3418 3419 if (error) { 3420 error = EBADRPC; 3421 break; 3422 } 3423 3424 if ( (wc != NTCREATEX_NORMAL_WDCNT) && (wc != NTCREATEX_EXTENDED_WDCNT) && 3425 (wc != NTCREATEX_BRKEN_SPEC_26_WDCNT) ) { 3426 if (need_close == 1) { 3427 /* not much we can do if the close fails */ 3428 temp_fid = fid; /* cast SMB 1 fid to full smb fid */ 3429 smbfs_smb_close(share, temp_fid, context); 3430 } 3431 3432 error = EBADRPC; 3433 break; 3434 } 3435 3436 md_get_uint32le(mdp, &fap->fa_created_disp); /* create disposition */ 3437 md_get_uint64le(mdp, &llint); /* creation time */ 3438 if (llint) { 3439 smb_time_NT2local(llint, &fap->fa_crtime); 3440 } 3441 md_get_uint64le(mdp, &llint); /* access time */ 3442 if (llint) { 3443 smb_time_NT2local(llint, &fap->fa_atime); 3444 } 3445 md_get_uint64le(mdp, &llint); /* write time */ 3446 if (llint) { 3447 smb_time_NT2local(llint, &fap->fa_mtime); 3448 } 3449 md_get_uint64le(mdp, &llint); /* change time */ 3450 if (llint) { 3451 smb_time_NT2local(llint, &fap->fa_chtime); 3452 } 3453 md_get_uint32le(mdp, &lint); /* attributes */ 3454 fap->fa_attr = lint; 3455 /* 3456 * Because of the Steve/Conrad Symlinks we can never be completely 3457 * sure that we have the correct vnode type if its a file. For 3458 * directories we always know the correct information. 3459 */ 3460 if (fap->fa_attr & SMB_EFA_DIRECTORY) { 3461 fap->fa_valid_mask |= FA_VTYPE_VALID; 3462 } 3463 fap->fa_vtype = (fap->fa_attr & SMB_EFA_DIRECTORY) ? VDIR : VREG; 3464 md_get_uint64le(mdp, &llint); /* allocation size */ 3465 fap->fa_data_alloc = llint; 3466 md_get_uint64le(mdp, &llint); /* EOF */ 3467 fap->fa_size = llint; 3468 md_get_uint16le(mdp, &resourceType); /* Resource Type */ 3469 /* 3470 * Never trust UNIX Servers when it comes to the FileStatus flags, they 3471 * lie and always return a hard coded 7. We make an exception for Darwin 3472 * servers, since they treat this field correctly. 3473 */ 3474 if ((resourceType == kFileTypeDisk) && 3475 ((!UNIX_SERVER(SSTOVC(share))) || (SSTOVC(share)->vc_flags & SMBV_DARWIN))) { 3476 /* 3477 * If device type has NO_SUBSTREAMS then spec says: The file or directory 3478 * has no data streams other than the main data stream. 3479 * 3480 * If NO_EAS, then spec says: The file or directory has no extended 3481 * attributes. 3482 */ 3483 md_get_uint16le(mdp, &fap->fa_fstatus); /* FileStatus Flags */ 3484 fap->fa_valid_mask |= FA_FSTATUS_VALID; /* Mark that this field is valid */ 3485 } else { 3486 md_get_uint16le(mdp, NULL); /* NMPipeStatus */ 3487 } 3488 3489 md_get_uint8(mdp, NULL); /* directory (boolean) */ 3490 /* 3491 * We want maximal access if we are opening up the node, if we have a 3492 * name then ignore. This means we will never update the stream node, 3493 * but currently we always use the main node for checking access. 3494 */ 3495 if (name) 3496 break; 3497 3498 /* Supports the maximal access rights, so lets get them */ 3499 if (wc == NTCREATEX_EXTENDED_WDCNT) { 3500 int maxAccessRightsError; 3501 uint8_t VolumeGID[16]; 3502 uint64_t fileID = 0; 3503 uint32_t guestMaxAccessRights = 0; 3504 3505 md_get_mem(mdp, (caddr_t)VolumeGID, sizeof(VolumeGID), MB_MSYSTEM); 3506 md_get_uint64le(mdp, &fileID); /* File ID */ 3507 /* We only care about maximal access rights currently, so check for any errors */ 3508 maxAccessRightsError = md_get_uint32le(mdp, &np->maxAccessRights); 3509 if (!maxAccessRightsError) 3510 maxAccessRightsError = md_get_uint32le(mdp, &guestMaxAccessRights); 3511 if (maxAccessRightsError) { 3512 np->n_flag |= NO_EXTENDEDOPEN; 3513 SMB_LOG_AUTH_LOCK(np, "Error %d getting extended reply for %s\n", maxAccessRightsError, np->n_name); 3514 } else { 3515 SMB_LOG_AUTH_LOCK(np, "%s fileID = %llx maxAccessRights = 0x%x guestMaxAccessRights = 0x%x\n", 3516 np->n_name, fileID, np->maxAccessRights, guestMaxAccessRights); 3517 np->n_flag &= ~NO_EXTENDEDOPEN; 3518 /* 3519 * We weren't granted delete access, but the parent allows delete child 3520 * so say we have delete access on the item. If no parent then just 3521 * say we have delete access (let the server control it). 3522 */ 3523 3524 lck_rw_lock_shared(&np->n_parent_rwlock); 3525 if (((np->maxAccessRights & SMB2_DELETE) != SMB2_DELETE) && 3526 (!np->n_parent || (np->n_parent->maxAccessRights & SMB2_FILE_DELETE_CHILD))) { 3527 np->maxAccessRights |= SMB2_DELETE; 3528 } 3529 lck_rw_unlock_shared(&np->n_parent_rwlock); 3530 } 3531 } else { 3532 np->n_flag |= NO_EXTENDEDOPEN; 3533 } 3534 /* 3535 * They don't support maximal access rights, so set it to all access rights 3536 * and let the server handle any deny issues. 3537 */ 3538 if (np->n_flag & NO_EXTENDEDOPEN) { 3539 np->maxAccessRights = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 3540 SMBDEBUG_LOCK(np, "Extended reply not supported: %s setting maxAccessRights to 0x%x rights = 0x%x\n", 3541 np->n_name, np->maxAccessRights, rights); 3542 } 3543 np->maxAccessRightChTime = fap->fa_chtime; 3544 } while(0); 3545 smb_rq_done(rqp); 3546 if (error) { 3547 if (snamep) { 3548 SMB_FREE(snamep, M_SMBSTR); 3549 } 3550 3551 return error; 3552 } 3553 3554 if (fidp) { 3555 /* note fid is in native form */ 3556 *fidp = fid; /* save SMB 1 fid */ 3557 } 3558 3559 /* 3560 * If not a directory, check if node needs to be reopened, 3561 * if so, then don't update anything at this point. 3562 * See <rdar://problem/11366143>. 3563 */ 3564 if (vt != VDIR) { 3565 lck_mtx_lock(&np->f_openStateLock); 3566 if (np->f_openState & kInReopen) { 3567 lck_mtx_unlock(&np->f_openStateLock); 3568 goto WeAreDone; 3569 } 3570 lck_mtx_unlock(&np->f_openStateLock); 3571 } 3572 3573 if (xattr) { 3574 /* If an EA or Stream then we are done */ 3575 goto WeAreDone; 3576 } 3577 3578 /* We are creating the item so create the ino number */ 3579 if (do_create == TRUE) { 3580 DBG_ASSERT(name != NULL); /* This is a create so better have a name */ 3581 fap->fa_ino = smbfs_getino(np, name, in_nmlen); /* SMB 1 only */ 3582 goto WeAreDone; 3583 } 3584 3585 /* If this is a SYMLINK, then n_vnode could be set to NULL */ 3586 if (np->n_vnode == NULL) { 3587 goto WeAreDone; 3588 } 3589 /* 3590 * We only get to this point if the n_vnode exist and we are doing a normal 3591 * open. If we are using UNIX extensions then we can't trust some of the 3592 * values returned from this open response. We need to reset some of the 3593 * value back to what we found in in the UNIX Info2 lookup. 3594 */ 3595 if (unix_info2) { 3596 /* Reset it to look like a UNIX Info2 lookup */ 3597 fap->fa_unix = TRUE; 3598 fap->fa_flags_mask = EXT_REQUIRED_BY_MAC; 3599 fap->fa_nlinks = np->n_nlinks; 3600 /* 3601 * Samba servers will return the read only bit when the posix modes 3602 * are set to read only. This is not the same as the immutable bit, 3603 * so don't believe what they say here about the read only bit. Keep 3604 * the value we have store in the node we can update from the unix 3605 * info level.if 3606 */ 3607 fap->fa_attr &= ~SMB_EFA_RDONLY; 3608 fap->fa_attr |= (np->n_dosattr & SMB_EFA_RDONLY); 3609 fap->fa_valid_mask |= FA_VTYPE_VALID; 3610 fap->fa_vtype = vnode_vtype(np->n_vnode); 3611 /* Make sure we have the correct fa_attr setting */ 3612 if (vnode_isdir(np->n_vnode)) 3613 fap->fa_attr |= SMB_EFA_DIRECTORY; 3614 else 3615 fap->fa_attr &= ~SMB_EFA_DIRECTORY; 3616 /* 3617 * Samba will return the modify time for the change time in this 3618 * call. So if we are doing unix extensions never trust the change 3619 * time retrieved from this call. 3620 */ 3621 fap->fa_chtime = np->n_chtime; 3622 } 3623 3624 /* 3625 * We have all the meta data attributes so update the cache. If the 3626 * calling routine is setting an attribute it should not change the 3627 * smb node value until after the open has completed. NOTE: The old 3628 * code would only update the cache if the mtime, attributes and size 3629 * haven't changed. 3630 */ 3631 smbfs_attr_cacheenter(share, np->n_vnode, fap, TRUE, context); 3632 3633WeAreDone: 3634 if (snamep) { 3635 SMB_FREE(snamep, M_SMBSTR); 3636 } 3637 3638 return (0); 3639} 3640 3641/* 3642 * The calling routine must hold a reference on the share 3643 */ 3644int 3645smbfs_tmpopen(struct smb_share *share, struct smbnode *np, uint32_t rights, 3646 SMBFID *fidp, vfs_context_t context) 3647{ 3648 int searchOpenFiles; 3649 int error = 0; 3650 struct smbfattr fattr; 3651 3652 /* If no vnode or the vnode is a directory then don't use already open items */ 3653 if (!np->n_vnode || vnode_isdir(np->n_vnode)) 3654 searchOpenFiles = FALSE; 3655 else { 3656 /* Check to see if the file needs to be reopened */ 3657 error = smbfs_smb_reopen_file(share, np, context); 3658 if (error) { 3659 SMBDEBUG_LOCK(np, " %s waiting to be revoked\n", np->n_name); 3660 return(error); 3661 } 3662 3663 /* 3664 * A normal open can have the following rights 3665 * SMB2_READ_CONTROL - always set 3666 * SMB2_FILE_READ_DATA 3667 * SMB2_FILE_APPEND_DATA 3668 * SMB2_FILE_WRITE_DATA 3669 * 3670 * A normal open will never have the following rights 3671 * SMB2_DELETE 3672 * SMB2_WRITE_DAC 3673 * SMB2_WRITE_OWNER 3674 * SMB2_FILE_WRITE_ATTRIBUTES 3675 * 3676 */ 3677 if (rights & (SMB2_DELETE | SMB2_WRITE_DAC | SMB2_WRITE_OWNER)) 3678 searchOpenFiles = FALSE; 3679 else if (rights & SMB2_FILE_WRITE_ATTRIBUTES) 3680 searchOpenFiles = FALSE; 3681 else 3682 searchOpenFiles = TRUE; 3683 } 3684 3685 /* 3686 * Remember we could have been called before the vnode is create. Conrads 3687 * crazy symlink code. So if we have no vnode then we cannot borrow the 3688 * fid. Only borrow a fid if the requested access modes could have been 3689 * made on an open call. 3690 */ 3691 if (searchOpenFiles && SMBTOV(np)) { 3692 uint16_t accessMode = 0; 3693 3694 if (rights & (SMB2_READ_CONTROL | SMB2_FILE_READ_DATA)) 3695 accessMode |= kAccessRead; 3696 if (rights & (SMB2_FILE_APPEND_DATA | SMB2_FILE_WRITE_DATA)) 3697 accessMode |= kAccessWrite; 3698 /* Must be a Windows 98 system */ 3699 if (rights & SMB2_FILE_WRITE_ATTRIBUTES) 3700 accessMode |= kAccessWrite; 3701 /* First check the non deny mode opens, if we have one up the refcnt */ 3702 if ( (np->f_fid != 0) 3703 && ((accessMode & np->f_accessMode) == accessMode) ) { 3704 np->f_refcnt++; 3705 *fidp = np->f_fid; 3706 return (0); 3707 } 3708 /* Now check the deny mode opens, if we find one up the refcnt */ 3709 if (np->f_refcnt && context && 3710 (FindFileRef(SMBTOV(np), vfs_context_proc(context), accessMode, 3711 kAnyMatch, 0, 0, NULL, fidp) == 0)) { 3712 np->f_refcnt++; 3713 return (0); 3714 } 3715 } 3716 /* 3717 * For temp opens we give unixy semantics of permitting everything not forbidden 3718 * by permissions. Ie denial is up to server with clients/openers needing to use 3719 * advisory locks for further control. 3720 */ 3721 uint32_t shareMode = NTCREATEX_SHARE_ACCESS_ALL; 3722 3723 error = smbfs_smb_ntcreatex(share, np, 3724 rights, shareMode, (np->n_vnode && vnode_isdir(np->n_vnode)) ? VDIR : VREG, 3725 fidp, NULL, 0, 3726 FILE_OPEN, FALSE, &fattr, 3727 FALSE, NULL, context); 3728 if (error) { 3729 SMBWARNING_LOCK(np, "%s failed to open: error = %d\n", np->n_name, error); 3730 } 3731 3732 return (error); 3733} 3734 3735/* 3736 * The calling routine must hold a reference on the share 3737 */ 3738int 3739smbfs_tmpclose(struct smb_share *share, struct smbnode *np, SMBFID fid, 3740 vfs_context_t context) 3741{ 3742 struct fileRefEntry *entry = NULL; 3743 vnode_t vp = SMBTOV(np); 3744 3745 /* 3746 * Remember we could have been called before the vnode is created. Conrads 3747 * crazy symlink code. So if we have no vnode then we did not borrow the 3748 * fid. If we did not borrow the fid then just close the fid and get out. 3749 * 3750 * If no vnode or the vnode is a directory then just close it, we are not 3751 * sharing the open. 3752 */ 3753 if (!vp || vnode_isdir(vp) || 3754 ((fid != np->f_fid) && 3755 (FindFileEntryByFID(vp, fid, &entry)))) { 3756 return(smbfs_smb_close(share, fid, context)); 3757 } 3758 /* 3759 * OK we borrowed the fid do we have the last reference count on it. If 3760 * yes, then we need to close up every thing. smbfs_close can handle this 3761 * for us. 3762 */ 3763 if (np->f_refcnt == 1) { 3764 /* Open Mode does not matter becasue we closing everything */ 3765 return(smbfs_close(share, vp, 0, context)); 3766 } 3767 3768 /* We borrowed the fid decrement the ref count */ 3769 if (np->f_refcnt > 0) { 3770 np->f_refcnt--; 3771 } 3772 3773 return (0); 3774} 3775 3776/* 3777 * This routine chains the open and read into one message. This routine is used only 3778 * for reading data out of a stream. If we decided to use it for something else then 3779 * we will need to make some changes. 3780 * 3781 * The calling routine must hold a reference on the share 3782 * 3783 */ 3784int 3785smb1fs_smb_openread(struct smb_share *share, struct smbnode *np, SMBFID *fid, 3786 uint32_t rights, uio_t uio, size_t *sizep, const char *name, 3787 struct timespec *mtime, vfs_context_t context) 3788{ 3789 struct smb_rq rq, *rqp = &rq; 3790 struct mbchain *mbp; 3791 struct mdchain *mdp; 3792 uint8_t wc, cmd; 3793 int error = 0; 3794 uint16_t *namelenp, *nextWdCntOffset, nextOffset; 3795 uint64_t eof; 3796 uint16_t residhi, residlo, off, doff; 3797 uint32_t resid; 3798 uint32_t len = (uint32_t)uio_resid(uio); 3799 size_t nmlen = strnlen(name, share->ss_maxfilenamelen+1); 3800 uint16_t smb1_fid; 3801 3802 /* 3803 * Make sure the whole response message will fit in our max buffer size. Since 3804 * we use the CreateAndX open call make sure the server supports that call. 3805 * The calling routine must handle this routine returning ENOTSUP. 3806 */ 3807 if ((SSTOVC(share)->vc_txmax - SMB_MAX_CHAIN_READ) < len) 3808 return(ENOTSUP); 3809 3810 /* encode the CreateAndX request */ 3811 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_NT_CREATE_ANDX, 0, context); 3812 if (error) 3813 return error; 3814 smb_rq_getrequest(rqp, &mbp); 3815 smb_rq_wstart(rqp); 3816 mb_put_uint8(mbp, SMB_COM_READ_ANDX); /* next chain command will be a read */ 3817 mb_put_uint8(mbp, 0); /* MBZ */ 3818 /* 3819 * The next command offset is the numbers of bytes from the smb header to 3820 * the location ofthe next commands word count field. Save that location so 3821 * we can fill it in later. 3822 */ 3823 nextWdCntOffset = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); /* offset to next command */ 3824 mb_put_uint8(mbp, 0); /* MBZ */ 3825 /* Save off the name length field so we can fill it in later */ 3826 namelenp = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); 3827 3828 mb_put_uint32le(mbp, 0); /* Oplock? NTCREATEX_FLAGS_REQUEST_OPLOCK */ 3829 mb_put_uint32le(mbp, 0); /* Root fid not used */ 3830 mb_put_uint32le(mbp, rights); 3831 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 3832 mb_put_uint32le(mbp, SMB_EFA_NORMAL); 3833 /* Deny write access if they want write access */ 3834 if (rights & SMB2_FILE_WRITE_DATA) { 3835 mb_put_uint32le(mbp, (NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE)); 3836 mb_put_uint32le(mbp, FILE_OPEN_IF); 3837 } else { 3838 mb_put_uint32le(mbp, NTCREATEX_SHARE_ACCESS_ALL); 3839 mb_put_uint32le(mbp, FILE_OPEN); 3840 } 3841 mb_put_uint32le(mbp, 0); 3842 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); 3843 mb_put_uint8(mbp, 0); /* security flags */ 3844 smb_rq_wend(rqp); 3845 smb_rq_bstart(rqp); 3846 /* Put in the path name here */ 3847 error = smbfs_fullpath(mbp, np, name, &nmlen, UTF_SFM_CONVERSIONS, 3848 SMB_UNICODE_STRINGS(SSTOVC(share)), ':'); 3849 if (error) 3850 goto exit; 3851 3852 *namelenp = htoles(nmlen); /* doesn't include the null bytes */ 3853 smb_rq_bend(rqp); 3854 3855 mb_put_padbyte(mbp); /* make sure the next message is on an even boundry */ 3856 *nextWdCntOffset = htoles(mb_fixhdr(mbp)); 3857 3858 /* now add the read request */ 3859 smb_rq_wstart(rqp); 3860 mb_put_uint8(mbp, 0xff); /* no secondary command */ 3861 mb_put_uint8(mbp, 0); 3862 mb_put_uint16le(mbp, 0); /* offset to secondary, no more chain items */ 3863 mb_put_uint16le(mbp, 0); /* set fid field to zero the server fills this in */ 3864 3865 mb_put_uint32le(mbp, (uint32_t)uio_offset(uio)); /* Lower offset */ 3866 mb_put_uint16le(mbp, (uint16_t)len); /* MaxCount */ 3867 mb_put_uint16le(mbp, (uint16_t)len); /* MinCount (only indicates blocking) */ 3868 mb_put_uint32le(mbp, len >> 16); /* MaxCountHigh */ 3869 mb_put_uint16le(mbp, (uint16_t)len); /* Remaining ("obsolete") */ 3870 mb_put_uint32le(mbp, (uint32_t)(uio_offset(uio) >> 32)); /* high offset */ 3871 3872 smb_rq_wend(rqp); 3873 smb_rq_bstart(rqp); 3874 smb_rq_bend(rqp); 3875 /* Send the message */ 3876 error = smb_rq_simple(rqp); 3877 if (error) 3878 goto exit; 3879 smb_rq_getreply(rqp, &mdp); 3880 3881 /* 3882 * I know there are some servers that return word counts of 42, but I don't 3883 * remember exactly why (Not Windows Systems). Shouldn't matter to us because 3884 * the offset to the read message will eat any extra bytes. 3885 */ 3886 if (md_get_uint8(mdp, &wc) != 0 || (wc != 34 && wc != 42)) { 3887 error = EINVAL; 3888 goto exit; 3889 } 3890 md_get_uint8(mdp, &cmd); /* secondary cmd */ 3891 3892 md_get_uint8(mdp, NULL); /* mbz */ 3893 /* Contains the offset from the start of the message to the read message. */ 3894 md_get_uint16le(mdp, &nextOffset); /* andxoffset */ 3895 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 3896 md_get_uint16(mdp, &smb1_fid); /* Get the fid */ 3897 *fid = smb1_fid; /* save SMB 1 fid */ 3898 md_get_uint32le(mdp, NULL); /* create_action */ 3899 md_get_uint64le(mdp, NULL); /* creation time */ 3900 md_get_uint64le(mdp, NULL); /* access time */ 3901 if (mtime) { 3902 uint64_t llint; 3903 3904 md_get_uint64le(mdp, &llint); /* write time */ 3905 if (llint) 3906 smb_time_NT2local(llint, mtime); 3907 } 3908 else 3909 md_get_uint64le(mdp, NULL); /* write time */ 3910 3911 md_get_uint64le(mdp, NULL); /* change time */ 3912 md_get_uint32le(mdp, NULL); /* attributes */ 3913 md_get_uint64le(mdp, NULL); /* allocation size */ 3914 md_get_uint64le(mdp, &eof); /* EOF */ 3915 if (sizep) 3916 *sizep = (size_t)eof; /* The calling routines can only handle size_t */ 3917 md_get_uint16le(mdp, NULL); /* file type */ 3918 md_get_uint16le(mdp, NULL); /* device state */ 3919 md_get_uint8(mdp, NULL); /* directory (boolean) */ 3920 md_get_uint16(mdp, NULL); /* byte count */ 3921 3922 if (cmd != SMB_COM_READ_ANDX) { 3923 if ((rights & SMB2_FILE_WRITE_DATA) && fid) /* We created the file */ 3924 error = 0; 3925 else 3926 error = ENOENT; 3927 goto exit; 3928 } 3929 3930 off = nextOffset; 3931 /* Is the offset pass the end of our buffer? */ 3932 m_fixhdr(mdp->md_top); 3933 if (nextOffset > mbuf_pkthdr_len(mdp->md_top)) { 3934 error = EINVAL; 3935 goto exit; 3936 } 3937 /* Take off what we have already consumed. */ 3938 nextOffset -= (SMB_HDRLEN + SMB_CREATEXRLEN + SMB_BCOUNT_LEN); 3939 if (nextOffset != 0) /* Anything left dump it */ 3940 md_get_mem(mdp, NULL, nextOffset, MB_MSYSTEM); 3941 3942 /* We are at the read message make sure the word count matches. */ 3943 if (md_get_uint8(mdp, &wc) != 0 || (wc != 12)) { 3944 error = EINVAL; 3945 goto exit; 3946 } 3947 /* Now handle the read response */ 3948 off++; 3949 md_get_uint8(mdp, NULL); 3950 off++; 3951 md_get_uint8(mdp, NULL); 3952 off++; 3953 md_get_uint16le(mdp, NULL); 3954 off += 2; 3955 md_get_uint16le(mdp, NULL); 3956 off += 2; 3957 md_get_uint16le(mdp, NULL); /* data compaction mode */ 3958 off += 2; 3959 md_get_uint16le(mdp, NULL); 3960 off += 2; 3961 md_get_uint16le(mdp, &residlo); 3962 off += 2; 3963 md_get_uint16le(mdp, &doff); /* data offset */ 3964 off += 2; 3965 md_get_uint16le(mdp, &residhi); 3966 off += 2; 3967 resid = (residhi << 16) | residlo; 3968 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 3969 off += 4*2; 3970 md_get_uint16le(mdp, NULL); /* ByteCount */ 3971 off += 2; 3972 if (doff > off) /* pad byte(s)? */ 3973 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 3974 if (resid) 3975 error = md_get_uio(mdp, uio, resid); 3976 3977exit: 3978 smb_rq_done(rqp); 3979 return (error); 3980} 3981 3982int 3983smb1fs_smb_open_maxaccess(struct smb_share *share, struct smbnode *dnp, 3984 const char *namep, size_t name_len, 3985 SMBFID *fidp, uint32_t *max_accessp, 3986 vfs_context_t context) 3987{ 3988#pragma unused(name_len) 3989 struct smb_rq rq, *rqp = &rq; 3990 struct mbchain *mbp; 3991 struct mdchain *mdp; 3992 uint8_t wc; 3993 int error = 0; 3994 uint16_t *namelenp, nextOffset; 3995 size_t nmlen = strnlen(namep, share->ss_maxfilenamelen+1); 3996 uint16_t smb1_fid; 3997 3998 /* Non zero fid means the open worked and a close is needed */ 3999 *fidp = 0; 4000 4001 /* encode the CreateAndX request */ 4002 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_NT_CREATE_ANDX, 0, context); 4003 if (error) { 4004 return error; 4005 } 4006 4007 smb_rq_getrequest(rqp, &mbp); 4008 4009 smb_rq_wstart(rqp); 4010 mb_put_uint8(mbp, 0xff); /* secondary command */ 4011 mb_put_uint8(mbp, 0); /* MBZ */ 4012 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 4013 mb_put_uint8(mbp, 0); /* MBZ */ 4014 /* Save off the name length field so we can fill it in later */ 4015 namelenp = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); 4016 mb_put_uint32le(mbp, NTCREATEX_FLAGS_EXTENDED); /* NTCREATEX_FLAGS_* */ 4017 mb_put_uint32le(mbp, 0); /* Root fid not used */ 4018 mb_put_uint32le(mbp, SMB2_FILE_READ_DATA); 4019 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 4020 mb_put_uint32le(mbp, SMB_EFA_NORMAL); 4021 mb_put_uint32le(mbp, NTCREATEX_SHARE_ACCESS_ALL); 4022 mb_put_uint32le(mbp, FILE_OPEN); 4023 mb_put_uint32le(mbp, 0); 4024 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); 4025 mb_put_uint8(mbp, 0); /* security flags */ 4026 smb_rq_wend(rqp); 4027 4028 smb_rq_bstart(rqp); 4029 /* Put in the path name with stream name here */ 4030 error = smbfs_fullpath_stream(mbp, dnp, 4031 namep, NULL, 4032 &nmlen, 0, UTF_SFM_CONVERSIONS, 4033 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4034 if (error) 4035 goto exit; 4036 4037 *namelenp = htoles(nmlen); /* doesn't include the null bytes */ 4038 smb_rq_bend(rqp); 4039 4040 /* Send the message */ 4041 error = smb_rq_simple(rqp); 4042 if (error) 4043 goto exit; 4044 4045 smb_rq_getreply(rqp, &mdp); 4046 4047 /* 4048 * I know there are some servers that return word counts of 42, but I don't 4049 * remember exactly why (Not Windows Systems). Shouldn't matter to us because 4050 * the offset to the read message will eat any extra bytes. 4051 */ 4052 if (md_get_uint8(mdp, &wc) != 0 || 4053 (wc != NTCREATEX_NORMAL_WDCNT && wc != NTCREATEX_EXTENDED_WDCNT)) { 4054 error = EINVAL; 4055 goto exit; 4056 } 4057 4058 md_get_uint8(mdp, NULL); /* secondary cmd */ 4059 4060 md_get_uint8(mdp, NULL); /* mbz */ 4061 /* Contains the offset from the start of the message to the read message. */ 4062 md_get_uint16le(mdp, &nextOffset); /* andxoffset */ 4063 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 4064 md_get_uint16(mdp, &smb1_fid); /* Get the fid */ 4065 *fidp = smb1_fid; /* save SMB 1 fid */ 4066 md_get_uint32le(mdp, NULL); /* create_action */ 4067 md_get_uint64le(mdp, NULL); /* creation time */ 4068 md_get_uint64le(mdp, NULL); /* access time */ 4069 md_get_uint64le(mdp, NULL); /* write time */ 4070 4071 md_get_uint64le(mdp, NULL); /* change time */ 4072 md_get_uint32le(mdp, NULL); /* attributes */ 4073 md_get_uint64le(mdp, NULL); /* allocation size */ 4074 md_get_uint64le(mdp, NULL); /* EOF */ 4075 md_get_uint16le(mdp, NULL); /* file type */ 4076 md_get_uint16le(mdp, NULL); /* device state */ 4077 md_get_uint8(mdp, NULL); /* directory (boolean) */ 4078 4079 /* Supports the maximal access rights, so lets get them */ 4080 if (wc == NTCREATEX_EXTENDED_WDCNT) { 4081 int maxAccessRightsError; 4082 uint8_t VolumeGID[16]; 4083 uint64_t fileID = 0; 4084 uint32_t guestMaxAccessRights = 0; 4085 uint32_t max_access_rights = 0; 4086 4087 md_get_mem(mdp, (caddr_t)VolumeGID, sizeof(VolumeGID), MB_MSYSTEM); 4088 md_get_uint64le(mdp, &fileID); /* File ID */ 4089 4090 /* 4091 * We only care about maximal access rights currently, 4092 * so check for any errors 4093 */ 4094 maxAccessRightsError = md_get_uint32le(mdp, &max_access_rights); 4095 if (!maxAccessRightsError) { 4096 maxAccessRightsError = md_get_uint32le(mdp, &guestMaxAccessRights); 4097 } 4098 4099 if (maxAccessRightsError) { 4100 *max_accessp = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 4101 } 4102 else { 4103 /* 4104 * We weren't granted delete access, but the parent allows delete child 4105 * so say we have delete access on the item. If no parent then just 4106 * say we have delete access (let the server control it). 4107 */ 4108 if (((max_access_rights & SMB2_DELETE) != SMB2_DELETE) && 4109 (!dnp || (dnp->maxAccessRights & SMB2_FILE_DELETE_CHILD))) { 4110 max_access_rights |= SMB2_DELETE; 4111 } 4112 4113 *max_accessp = max_access_rights; 4114 } 4115 } 4116 else { 4117 /* Must not support max access rights, so grant full access */ 4118 SMBDEBUG("Server does not support max access, returning full access\n"); 4119 *max_accessp = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 4120 } 4121 4122exit: 4123 smb_rq_done(rqp); 4124 return (error); 4125} 4126 4127int 4128smb1fs_smb_open_read(struct smb_share *share, struct smbnode *dnp, 4129 const char *namep, size_t name_len, 4130 const char *strm_namep, size_t strm_name_len, 4131 SMBFID *fidp, uio_t uio, size_t *sizep, 4132 uint32_t *max_accessp, 4133 vfs_context_t context) 4134{ 4135#pragma unused(name_len) 4136#pragma unused(strm_name_len) 4137 struct smb_rq rq, *rqp = &rq; 4138 struct mbchain *mbp; 4139 struct mdchain *mdp; 4140 uint8_t wc, cmd; 4141 int error = 0; 4142 int error2 = 0; 4143 uint16_t *namelenp, *nextWdCntOffset, nextOffset; 4144 uint64_t eof; 4145 uint16_t residhi, residlo, off, doff; 4146 uint32_t resid; 4147 uint32_t len = (uint32_t)uio_resid(uio); 4148 size_t nmlen = strnlen(namep, share->ss_maxfilenamelen+1); 4149 size_t snmlen = strnlen(strm_namep, share->ss_maxfilenamelen+1); 4150 uint16_t smb1_fid; 4151 uint32_t rights = SMB2_FILE_READ_DATA; 4152 4153 /* 4154 * Make sure the whole response message will fit in our max buffer size. Since 4155 * we use the CreateAndX open call make sure the server supports that call. 4156 * The calling routine must handle this routine returning ENOTSUP. 4157 */ 4158 if ((SSTOVC(share)->vc_txmax - SMB_MAX_CHAIN_READ) < len) 4159 return(ENOTSUP); 4160 4161 /* encode the CreateAndX request */ 4162 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_NT_CREATE_ANDX, 0, context); 4163 if (error) 4164 return error; 4165 smb_rq_getrequest(rqp, &mbp); 4166 smb_rq_wstart(rqp); 4167 mb_put_uint8(mbp, SMB_COM_READ_ANDX); /* next chain command will be a read */ 4168 mb_put_uint8(mbp, 0); /* MBZ */ 4169 /* 4170 * The next command offset is the numbers of bytes from the smb header to 4171 * the location ofthe next commands word count field. Save that location so 4172 * we can fill it in later. 4173 */ 4174 nextWdCntOffset = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); /* offset to next command */ 4175 mb_put_uint8(mbp, 0); /* MBZ */ 4176 /* Save off the name length field so we can fill it in later */ 4177 namelenp = (uint16_t *)mb_reserve(mbp, sizeof(uint16_t)); 4178 4179 if (max_accessp) { 4180 /* Ask for max access */ 4181 mb_put_uint32le(mbp, NTCREATEX_FLAGS_EXTENDED); /* NTCREATEX_FLAGS_* */ 4182 } 4183 else { 4184 mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */ 4185 } 4186 4187 mb_put_uint32le(mbp, 0); /* Root fid not used */ 4188 mb_put_uint32le(mbp, rights); 4189 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 4190 mb_put_uint32le(mbp, SMB_EFA_NORMAL); 4191 /* Deny write access if they want write access */ 4192 if (rights & SMB2_FILE_WRITE_DATA) { 4193 mb_put_uint32le(mbp, (NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE)); 4194 mb_put_uint32le(mbp, FILE_OPEN_IF); 4195 } else { 4196 mb_put_uint32le(mbp, NTCREATEX_SHARE_ACCESS_ALL); 4197 mb_put_uint32le(mbp, FILE_OPEN); 4198 } 4199 mb_put_uint32le(mbp, 0); 4200 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); 4201 mb_put_uint8(mbp, 0); /* security flags */ 4202 smb_rq_wend(rqp); 4203 smb_rq_bstart(rqp); 4204 /* Put in the path name with stream name here */ 4205 error = smbfs_fullpath_stream(mbp, dnp, 4206 namep, strm_namep, 4207 &nmlen, snmlen, UTF_SFM_CONVERSIONS, 4208 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4209 if (error) 4210 goto exit; 4211 4212 *namelenp = htoles(nmlen); /* doesn't include the null bytes */ 4213 smb_rq_bend(rqp); 4214 4215 mb_put_padbyte(mbp); /* make sure the next message is on an even boundry */ 4216 *nextWdCntOffset = htoles(mb_fixhdr(mbp)); 4217 4218 /* now add the read request */ 4219 smb_rq_wstart(rqp); 4220 mb_put_uint8(mbp, 0xff); /* no secondary command */ 4221 mb_put_uint8(mbp, 0); 4222 mb_put_uint16le(mbp, 0); /* offset to secondary, no more chain items */ 4223 mb_put_uint16le(mbp, 0); /* set fid field to zero the server fills this in */ 4224 4225 mb_put_uint32le(mbp, (uint32_t)uio_offset(uio)); /* Lower offset */ 4226 mb_put_uint16le(mbp, (uint16_t)len); /* MaxCount */ 4227 mb_put_uint16le(mbp, (uint16_t)len); /* MinCount (only indicates blocking) */ 4228 mb_put_uint32le(mbp, len >> 16); /* MaxCountHigh */ 4229 mb_put_uint16le(mbp, (uint16_t)len); /* Remaining ("obsolete") */ 4230 mb_put_uint32le(mbp, (uint32_t)(uio_offset(uio) >> 32)); /* high offset */ 4231 4232 smb_rq_wend(rqp); 4233 smb_rq_bstart(rqp); 4234 smb_rq_bend(rqp); 4235 /* Send the message */ 4236 error = smb_rq_simple(rqp); 4237 if (error) { 4238 /* 4239 * Dont exit yet, may still be able to parse the Create part out and 4240 * get the fid so we can do a close 4241 */ 4242 } 4243 smb_rq_getreply(rqp, &mdp); 4244 4245 /* 4246 * I know there are some servers that return word counts of 42, but I don't 4247 * remember exactly why (Not Windows Systems). Shouldn't matter to us because 4248 * the offset to the read message will eat any extra bytes. 4249 */ 4250 if (md_get_uint8(mdp, &wc) != 0 || 4251 (wc != NTCREATEX_NORMAL_WDCNT && wc != NTCREATEX_EXTENDED_WDCNT)) { 4252 /* Dont overwrite earlier error */ 4253 if (error == 0) { 4254 error = EINVAL; 4255 } 4256 goto exit; 4257 } 4258 4259 error2 = md_get_uint8(mdp, &cmd); /* AndX Command */ 4260 if (error2) { 4261 /* Dont overwrite earlier error */ 4262 if (error == 0) { 4263 error = error2; 4264 } 4265 goto exit; 4266 } 4267 4268 error2 = md_get_uint8(mdp, NULL); /* AndX Reserved */ 4269 if (error2) { 4270 /* Dont overwrite earlier error */ 4271 if (error == 0) { 4272 error = error2; 4273 } 4274 goto exit; 4275 } 4276 4277 error2 = md_get_uint16le(mdp, &nextOffset); /* AndX Offset */ 4278 if (error2) { 4279 /* Dont overwrite earlier error */ 4280 if (error == 0) { 4281 error = error2; 4282 } 4283 goto exit; 4284 } 4285 4286 error2 = md_get_uint8(mdp, NULL); /* OpLock Level */ 4287 if (error2) { 4288 /* Dont overwrite earlier error */ 4289 if (error == 0) { 4290 error = error2; 4291 } 4292 goto exit; 4293 } 4294 4295 error2 = md_get_uint16(mdp, &smb1_fid); /* FID */ 4296 if (error2) { 4297 /* Dont overwrite earlier error */ 4298 if (error == 0) { 4299 error = error2; 4300 } 4301 goto exit; 4302 } 4303 *fidp = smb1_fid; /* save SMB 1 fid */ 4304 4305 if (error) { 4306 /* Now have FID so can do a close, now we can return with error */ 4307 goto exit; 4308 } 4309 4310 md_get_uint32le(mdp, NULL); /* create_action */ 4311 md_get_uint64le(mdp, NULL); /* creation time */ 4312 md_get_uint64le(mdp, NULL); /* access time */ 4313 md_get_uint64le(mdp, NULL); /* write time */ 4314 4315 md_get_uint64le(mdp, NULL); /* change time */ 4316 md_get_uint32le(mdp, NULL); /* attributes */ 4317 md_get_uint64le(mdp, NULL); /* allocation size */ 4318 md_get_uint64le(mdp, &eof); /* EOF */ 4319 if (sizep) 4320 *sizep = (size_t)eof; /* The calling routines can only handle size_t */ 4321 md_get_uint16le(mdp, NULL); /* file type */ 4322 md_get_uint16le(mdp, NULL); /* device state */ 4323 md_get_uint8(mdp, NULL); /* directory (boolean) */ 4324 4325 /* Supports the maximal access rights, so lets get them */ 4326 if (wc == NTCREATEX_EXTENDED_WDCNT) { 4327 int maxAccessRightsError; 4328 uint8_t VolumeGID[16]; 4329 uint64_t fileID = 0; 4330 uint32_t guestMaxAccessRights = 0; 4331 uint32_t max_access_rights = 0; 4332 4333 md_get_mem(mdp, (caddr_t)VolumeGID, sizeof(VolumeGID), MB_MSYSTEM); 4334 md_get_uint64le(mdp, &fileID); /* File ID */ 4335 4336 /* We only care about maximal access rights currently, so check for any errors */ 4337 maxAccessRightsError = md_get_uint32le(mdp, &max_access_rights); 4338 if (!maxAccessRightsError) { 4339 maxAccessRightsError = md_get_uint32le(mdp, &guestMaxAccessRights); 4340 } 4341 4342 if (maxAccessRightsError) { 4343 if (max_accessp) { 4344 *max_accessp = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 4345 } 4346 } 4347 else { 4348 /* 4349 * We weren't granted delete access, but the parent allows delete child 4350 * so say we have delete access on the item. If no parent then just 4351 * say we have delete access (let the server control it). 4352 */ 4353 if (((max_access_rights & SMB2_DELETE) != SMB2_DELETE) && 4354 (!dnp || (dnp->maxAccessRights & SMB2_FILE_DELETE_CHILD))) { 4355 max_access_rights |= SMB2_DELETE; 4356 } 4357 4358 if (max_accessp) { 4359 *max_accessp = max_access_rights; 4360 } 4361 } 4362 } 4363 else { 4364 /* Must not support max access rights, so grant full access */ 4365 if (max_accessp) { 4366 SMBDEBUG("Server does not support max access, returning full access\n"); 4367 *max_accessp = SA_RIGHT_FILE_ALL_ACCESS | STD_RIGHT_ALL_ACCESS; 4368 } 4369 } 4370 4371 if (cmd != SMB_COM_READ_ANDX) { 4372 if ((rights & SMB2_FILE_WRITE_DATA) && fidp) /* We created the file */ 4373 error = 0; 4374 else 4375 error = ENOENT; 4376 goto exit; 4377 } 4378 4379 off = nextOffset; 4380 /* Is the offset pass the end of our buffer? */ 4381 m_fixhdr(mdp->md_top); 4382 if (nextOffset > mbuf_pkthdr_len(mdp->md_top)) { 4383 error = EINVAL; 4384 goto exit; 4385 } 4386 4387 /* Take off what we have already consumed. */ 4388 if (wc == NTCREATEX_EXTENDED_WDCNT) { 4389 /* Extended Create response */ 4390 nextOffset -= SMB_HDRLEN; 4391 nextOffset -= 69; /* Ext Create Response length */ 4392 nextOffset -= 32; /* Max Access Rights len */ 4393 } 4394 else { 4395 /* Non Extended Create response */ 4396 md_get_uint16(mdp, NULL); /* Byte Count */ 4397 4398 nextOffset -= (SMB_HDRLEN + SMB_CREATEXRLEN + SMB_BCOUNT_LEN); 4399 } 4400 4401 if (nextOffset != 0) { 4402 /* Anything left dump it */ 4403 md_get_mem(mdp, NULL, nextOffset, MB_MSYSTEM); 4404 } 4405 4406 /* We are at the read message make sure the word count matches. */ 4407 if (md_get_uint8(mdp, &wc) != 0 || (wc != 12)) { 4408 error = EINVAL; 4409 goto exit; 4410 } 4411 4412 /* Now handle the read response */ 4413 off++; 4414 md_get_uint8(mdp, NULL); 4415 off++; 4416 md_get_uint8(mdp, NULL); 4417 off++; 4418 md_get_uint16le(mdp, NULL); 4419 off += 2; 4420 md_get_uint16le(mdp, NULL); 4421 off += 2; 4422 md_get_uint16le(mdp, NULL); /* data compaction mode */ 4423 off += 2; 4424 md_get_uint16le(mdp, NULL); 4425 off += 2; 4426 md_get_uint16le(mdp, &residlo); 4427 off += 2; 4428 md_get_uint16le(mdp, &doff); /* data offset */ 4429 off += 2; 4430 md_get_uint16le(mdp, &residhi); 4431 off += 2; 4432 resid = (residhi << 16) | residlo; 4433 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 4434 off += 4*2; 4435 md_get_uint16le(mdp, NULL); /* ByteCount */ 4436 off += 2; 4437 if (doff > off) /* pad byte(s)? */ 4438 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 4439 if (resid) 4440 error = md_get_uio(mdp, uio, resid); 4441 4442exit: 4443 smb_rq_done(rqp); 4444 return (error); 4445} 4446 4447/* 4448 * The calling routine must hold a reference on the share 4449 */ 4450int 4451smbfs_smb_open_file(struct smb_share *share, struct smbnode *np, 4452 uint32_t rights, uint32_t shareMode, SMBFID *fidp, 4453 const char *name, size_t nmlen, int xattr, 4454 struct smbfattr *fap, vfs_context_t context) 4455{ 4456 int error; 4457 int do_create; 4458 uint32_t disp; 4459 4460 /* 4461 * We are opening the resource fork from a normal open, so it should 4462 * always exist. Tell the server to create it if it doesn't exist otherwise 4463 * just open it. We never create it if coming from an xattr call. 4464 */ 4465 if ((np->n_flag & N_ISRSRCFRK) && !xattr) { 4466 disp = FILE_OPEN_IF; 4467 do_create = TRUE; 4468 } else { 4469 disp = FILE_OPEN; 4470 do_create = FALSE; 4471 } 4472 error = smbfs_smb_ntcreatex(share, np, 4473 rights, shareMode, VREG, 4474 fidp, name, nmlen, 4475 disp, xattr, fap, 4476 do_create, NULL, context); 4477 return (error); 4478} 4479 4480/* 4481 * The calling routine must hold a reference on the share 4482 */ 4483int 4484smbfs_smb_open_xattr(struct smb_share *share, struct smbnode *np, uint32_t rights, 4485 uint32_t shareMode, SMBFID *fidp, const char *name, 4486 size_t *sizep, vfs_context_t context) 4487{ 4488 size_t nmlen = strnlen(name, share->ss_maxfilenamelen+1); 4489 int error; 4490 struct smbfattr fattr; 4491 4492 error = smbfs_smb_open_file(share, np, rights, shareMode, fidp, 4493 name, nmlen, TRUE, &fattr, context); 4494 if (!error && sizep) 4495 *sizep = (size_t)fattr.fa_size; 4496 return(error); 4497} 4498 4499/* 4500 * The calling routine must hold a reference on the share 4501 * Attempts to reopen the shared fid only. 4502 */ 4503int 4504smbfs_smb_reopen_file(struct smb_share *share, struct smbnode *np, 4505 vfs_context_t context) 4506{ 4507 int error = 0; 4508 struct timespec n_mtime = np->n_mtime; /* open can change this value save it */ 4509 u_quad_t n_size = np->n_size; /* open can change this value save it */ 4510 struct smbfattr fattr; 4511 4512 /* 4513 * We are in the middle of a reconnect, wait for it to complete 4514 * Although if its the iod_context, allow this reopen to proceed 4515 */ 4516 if (context != SSTOVC(share)->vc_iod->iod_context) { 4517 while (share->ss_flags & SMBS_RECONNECTING) { 4518 SMBDEBUG("SMBS_RECONNECTING Going to sleep! \n"); 4519 msleep(&share->ss_flags, 0, PWAIT, "smbfs_smb_reopen_file", NULL); 4520 } 4521 } 4522 4523 lck_mtx_lock(&np->f_openStateLock); 4524 4525 /* File was already revoked, just return the correct error */ 4526 if (np->f_openState & kNeedRevoke) { 4527 lck_mtx_unlock(&np->f_openStateLock); 4528 return EIO; 4529 } else if (!(np->f_openState & kNeedReopen) && 4530 !(np->f_openState & kInReopen)) { 4531 /* 4532 * Note smb2fs_reconnect() resets kNeedReopen before making this call 4533 * so it can detect if another reconnect happened while trying to reopen 4534 * the file. But this inadvertently prevents the file from being opened, 4535 * since we would simply return here. 4536 * 4537 * Luckily smb2fs_reconnect() sets kInReopen at the same time, 4538 * so now we check both kNeedReopen and kInReopen to decide 4539 * whether to just return here or try to open the file below. 4540 * Fixes <rdar://problem/17510490>. 4541 */ 4542 lck_mtx_unlock(&np->f_openStateLock); 4543 return 0; /* Nothing wrong so just return */ 4544 } 4545 4546 /* 4547 * Clear the kNeedReopen flag, this way we know if a 4548 * reconnect happens during reopen 4549 */ 4550 np->f_openState &= ~kNeedReopen; 4551 np->f_openState |= kInReopen; 4552 lck_mtx_unlock(&np->f_openStateLock); 4553 4554 DBG_ASSERT(np->f_refcnt); /* Better have an open at this point */ 4555 4556 /* 4557 * For SMB 1, if there was anything on f_openDenyList, then the file got 4558 * revoked and thus no need for reopen. 4559 * 4560 * For SMB 2/3, only uses this to reopen shared fid 4561 */ 4562 /* POSIX Open: Reopen with the same modes we had it open with before the reconnect */ 4563 error = smbfs_smb_open_file(share, np, np->f_rights, 4564 NTCREATEX_SHARE_ACCESS_ALL, 4565 &np->f_fid, NULL, 0, FALSE, &fattr, 4566 context); 4567 if (error) { 4568 SMBERROR_LOCK(np, "Reopen %s failed because the open call failed!\n", np->n_name); 4569 } 4570 4571 /* If an error or no lock then we are done, nothing else to do */ 4572 if (error || (np->f_smbflock == NULL)) { 4573 goto exit; 4574 } 4575 4576 if ((!(timespeccmp(&n_mtime, &fattr.fa_mtime, ==))) || 4577 (n_size != fattr.fa_size)) { 4578 if (n_size != np->n_size) { 4579 SMBERROR_LOCK(np, "Reopen %s failed because the size has changed was 0x%lld now 0x%lld!\n", 4580 np->n_name, n_size, fattr.fa_size); 4581 } 4582 else { 4583 SMBERROR_LOCK(np, "Reopen %s failed because the modify time has changed was %lds %ldns now %lds %ldns!\n", 4584 np->n_name, n_mtime.tv_sec, n_mtime.tv_nsec, 4585 fattr.fa_mtime.tv_sec, fattr.fa_mtime.tv_nsec); 4586 } 4587 error = EIO; 4588 } 4589 else { 4590 struct smbfs_flock *flk = np->f_smbflock; 4591 error = smbfs_smb_lock(share, SMB_LOCK_EXCL, np->f_fid, 4592 flk->lck_pid, flk->start, flk->len, 4593 0, context); 4594 if (error) { 4595 SMBERROR_LOCK(np, "Reopen %s failed because we could not reestablish the lock! \n", np->n_name); 4596 } 4597 } 4598 4599 /* Something is different or we failed on the lock request, close it */ 4600 if (error) { 4601 (void)smbfs_smb_close(share, np->f_fid, context); 4602 } 4603 4604exit: 4605 lck_mtx_lock(&np->f_openStateLock); 4606 np->f_openState &= ~kInReopen; 4607 4608 /* Error or we reconnect after the open, not much we can do here */ 4609 if (context && (error || (np->f_openState & kNeedReopen))) { 4610 char errbuf[32]; 4611 int pid = proc_pid(vfs_context_proc(context)); 4612 4613 proc_name(pid, &errbuf[0], 32); 4614 4615 SMBERROR_LOCK(np, "Warning: pid %d(%.*s) reopening of %s failed with error %d\n", 4616 pid, 32, &errbuf[0], np->n_name, error); 4617 4618 np->f_openState |= kNeedRevoke; 4619 error = EIO; 4620 } 4621 lck_mtx_unlock(&np->f_openStateLock); 4622 4623 return(error); 4624} 4625 4626/* 4627 * The calling routine must hold a reference on the share 4628 */ 4629int 4630smb1fs_smb_close(struct smb_share *share, SMBFID fid, vfs_context_t context) 4631{ 4632 struct smb_rq rq, *rqp = &rq; 4633 struct mbchain *mbp; 4634 uint32_t time; 4635 int error; 4636 uint16_t smb1_fid = (uint16_t) fid; 4637 4638 DBG_ASSERT(smb1_fid); 4639 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_CLOSE, 0, context); 4640 if (error) 4641 return error; 4642 smb_rq_getrequest(rqp, &mbp); 4643 smb_rq_wstart(rqp); 4644 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 4645 /* 4646 * Never set the modify time on close. Just a really bad idea! 4647 * 4648 * Leach and SNIA docs say to send zero here. X/Open says 4649 * 0 and -1 both are leaving timestamp up to the server. 4650 * Win9x treats zero as a real time-to-be-set! We send -1, 4651 * same as observed with smbclient. 4652 */ 4653 time = -1; 4654 mb_put_uint32le(mbp, time); 4655 smb_rq_wend(rqp); 4656 smb_rq_bstart(rqp); 4657 smb_rq_bend(rqp); 4658 error = smb_rq_simple(rqp); 4659 smb_rq_done(rqp); 4660 /* 4661 * ENOTCONN isn't interesting - if the connection is closed, 4662 * so are all our FIDs - and ENXIO is also not interesting, 4663 * as it means a forced unmount was done. 4664 * 4665 * EBADF means the fid is no longer good. Reconnect will make this happen. 4666 * Should we check to see if the open was broken on the reconnect or does it 4667 * really matter? 4668 * 4669 * Don't clog up the system log with warnings about those failures 4670 * on closes. 4671 */ 4672 if ((error == ENOTCONN) || (error == ENXIO) || (error == EBADF)) 4673 error = 0; 4674 return error; 4675} 4676 4677/* 4678 * The calling routine must hold a reference on the share 4679 */ 4680int 4681smbfs_smb_create(struct smb_share *share, struct smbnode *dnp, 4682 const char *in_name, size_t in_nmlen, uint32_t rights, 4683 SMBFID *fidp, uint32_t disp, int xattr, struct smbfattr *fap, 4684 vfs_context_t context) 4685{ 4686 const char *name = in_name; 4687 size_t nmlen = in_nmlen; 4688 SMBFID fid = 0; 4689 int error; 4690 uint32_t desired_access = rights; 4691 uint32_t share_access = NTCREATEX_SHARE_ACCESS_ALL; 4692 uint64_t create_flags = SMB2_CREATE_DO_CREATE | SMB2_CREATE_GET_MAX_ACCESS; 4693 uint32_t ntstatus = 0; 4694 char *file_namep = NULL, *stream_namep = NULL; 4695 size_t file_name_len = 0, stream_name_len = 0; 4696 4697 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 4698 /* 4699 * SMB 2/3 - do compound create/close, or create 4700 * If fidp == NULL, then it will do a create/close. 4701 */ 4702 if (!xattr) { 4703 file_namep = (char *) in_name; 4704 file_name_len = in_nmlen; 4705 } 4706 else { 4707 /* name is actually the stream name */ 4708 create_flags |= SMB2_CREATE_IS_NAMED_STREAM; 4709 4710 stream_namep = (char *) in_name; 4711 stream_name_len = in_nmlen; 4712 } 4713 4714 error = smb2fs_smb_cmpd_create(share, dnp, 4715 file_namep, file_name_len, 4716 stream_namep, stream_name_len, 4717 desired_access, VREG, 4718 share_access, disp, 4719 create_flags, &ntstatus, 4720 fidp, fap, 4721 NULL, context); 4722 } 4723 else { 4724 /* SMB 1 */ 4725 error = smbfs_smb_ntcreatex(share, dnp, 4726 desired_access, share_access, VREG, 4727 &fid, name, nmlen, 4728 disp, xattr, fap, 4729 TRUE, NULL, context); 4730 if (fidp) { 4731 /* Caller wants the FID, return it to them */ 4732 *fidp = fid; 4733 } 4734 else { 4735 if (!error) { 4736 /* Caller doesn't want the FID, close it if we have it opened */ 4737 (void)smbfs_smb_close(share, fid, context); 4738 } 4739 } 4740 } 4741 4742 return error; 4743} 4744 4745/* 4746 * This is the only way to remove symlinks with a samba server. 4747 * 4748 * The calling routine must hold a reference on the share 4749 * 4750 */ 4751static int 4752smbfs_posix_unlink(struct smb_share *share, struct smbnode *np, 4753 vfs_context_t context, const char *name, size_t nmlen) 4754{ 4755 struct smb_t2rq *t2p; 4756 struct mbchain *mbp; 4757 int error; 4758 uint32_t isDir = (vnode_isdir(np->n_vnode)) ? 1 : 0; 4759 4760 error = smb_t2_alloc(SSTOCP(share), SMB_TRANS2_SET_PATH_INFORMATION, 1, context, &t2p); 4761 if (error) 4762 return error; 4763 mbp = &t2p->t2_tparam; 4764 mb_init(mbp); 4765 mb_put_uint16le(mbp, SMB_SFILEINFO_POSIX_UNLINK); 4766 mb_put_uint32le(mbp, 0); 4767 error = smbfs_fullpath(mbp, np, name, &nmlen, UTF_SFM_CONVERSIONS, 4768 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4769 if (error) { 4770 smb_t2_done(t2p); 4771 return error; 4772 } 4773 4774 mbp = &t2p->t2_tdata; 4775 mb_init(mbp); 4776 mb_put_uint32le(mbp, isDir); 4777 4778 t2p->t2_maxpcount = 2; 4779 t2p->t2_maxdcount = SSTOVC(share)->vc_txmax; 4780 error = smb_t2_request(t2p); 4781 smb_t2_done(t2p); 4782 return error; 4783} 4784 4785/* 4786 * The calling routine must hold a reference on the share 4787 */ 4788int 4789smb1fs_smb_delete(struct smb_share *share, struct smbnode *np, const char *name, 4790 size_t nmlen, int xattr, vfs_context_t context) 4791{ 4792 struct smb_rq rq, *rqp = &rq; 4793 struct mbchain *mbp; 4794 int error; 4795 4796 /* Not doing extended attribute and they support the posix unlink call */ 4797 if (!xattr && (UNIX_CAPS(share) & UNIX_SFILEINFO_POSIX_UNLINK_CAP)) { 4798 error = smbfs_posix_unlink(share, np, context, name, nmlen); 4799 /* 4800 * If the file doesn't have write posix modes then Samba returns 4801 * STATUS_CANNOT_DELETE, which we convert to EPERM. This seems 4802 * wrong we are expecting posix symantics from the call. So for now 4803 * try to change the mode and attempt the delete again. 4804 */ 4805 if (error == EPERM) { 4806 int chmod_error; 4807 uint64_t vamode = np->n_mode | S_IWUSR; 4808 4809 /* See if we can chmod on the file */ 4810 chmod_error = smbfs_set_unix_info2(share, np, NULL, NULL, NULL, SMB_SIZE_NO_CHANGE, 4811 vamode, SMB_FLAGS_NO_CHANGE, SMB_FLAGS_NO_CHANGE, context); 4812 if (chmod_error == 0) { 4813 error = smbfs_posix_unlink(share, np, context, name, nmlen); 4814 } 4815 } 4816 if (error != ENOTSUP) { 4817 return error; 4818 } else { 4819 /* They don't really support this call, don't call them again */ 4820 UNIX_CAPS(share) &= ~UNIX_SFILEINFO_POSIX_UNLINK_CAP; 4821 } 4822 } 4823 4824 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_DELETE, 0, context); 4825 if (error) 4826 return error; 4827 smb_rq_getrequest(rqp, &mbp); 4828 smb_rq_wstart(rqp); 4829 mb_put_uint16le(mbp, SMB_EFA_SYSTEM | SMB_EFA_HIDDEN); 4830 smb_rq_wend(rqp); 4831 smb_rq_bstart(rqp); 4832 mb_put_uint8(mbp, SMB_DT_ASCII); 4833 error = smbfs_fullpath(mbp, np, name, &nmlen, UTF_SFM_CONVERSIONS, 4834 SMB_UNICODE_STRINGS(SSTOVC(share)), xattr ? ':' : '\\'); 4835 if (!error) { 4836 smb_rq_bend(rqp); 4837 error = smb_rq_simple(rqp); 4838 } 4839 /* 4840 * We could have sent the delete before the connection went down, but we lost the 4841 * response. We resent the delete, but since it already succeeded we got an ENOENT 4842 * error. We are deleting something that does not exist, since it happen during 4843 * a reconnect take a guess that we succeeded. 4844 */ 4845 if ((error == ENOENT) && (rqp->sr_flags & SMBR_REXMIT)) 4846 error = 0; 4847 smb_rq_done(rqp); 4848 return error; 4849} 4850 4851/* 4852 * The calling routine must hold a reference on the share 4853 */ 4854int 4855smb1fs_smb_rename(struct smb_share *share, struct smbnode *src, 4856 struct smbnode *tdnp, const char *tname, size_t tnmlen, 4857 vfs_context_t context) 4858{ 4859 struct smb_rq rq, *rqp = &rq; 4860 struct mbchain *mbp; 4861 int error, retest = 0; 4862 4863 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_RENAME, 0, context); 4864 if (error) 4865 return error; 4866 smb_rq_getrequest(rqp, &mbp); 4867 smb_rq_wstart(rqp); 4868 /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */ 4869 mb_put_uint16le(mbp, (vnode_isdir(SMBTOV(src)) ? SMB_EFA_DIRECTORY : 0) | 4870 SMB_EFA_SYSTEM | SMB_EFA_HIDDEN); 4871 smb_rq_wend(rqp); 4872 smb_rq_bstart(rqp); 4873 mb_put_uint8(mbp, SMB_DT_ASCII); 4874 do { 4875 error = smbfs_fullpath(mbp, src, NULL, NULL, UTF_SFM_CONVERSIONS, 4876 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4877 if (error) 4878 break; 4879 mb_put_uint8(mbp, SMB_DT_ASCII); 4880 error = smbfs_fullpath(mbp, tdnp, tname, &tnmlen, UTF_SFM_CONVERSIONS, 4881 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4882 if (error) 4883 break; 4884 smb_rq_bend(rqp); 4885 error = smb_rq_simple(rqp); 4886 } while(0); 4887 if ((error == ENOENT) && (rqp->sr_flags & SMBR_REXMIT)) 4888 retest = 1; 4889 smb_rq_done(rqp); 4890 /* 4891 * We could have sent the rename before the connection went down, but we lost 4892 * the response. We resent the rename message, but since it already succeeded 4893 * we got an ENOENTerror. So lets test to see if the rename worked or not. 4894 * 4895 * 1. Check to make sure the source doesn't exist. 4896 * 2. Check to make sure the dest does exist. 4897 * 4898 * If either fails then we leave the error alone, we could still be wrong here. 4899 * Someone could have played with the file between the time we lost the 4900 * connection and the time we do our test. Not trying to be prefect here just 4901 * to the best we can. 4902 */ 4903 if (error && retest) { 4904 if ((smbfs_smb_query_info(share, src, VREG, NULL, 0, NULL, context) == ENOENT) && 4905 (smbfs_smb_query_info(share, tdnp, VREG, tname, tnmlen, NULL, context) == 0)) 4906 error = 0; 4907 } 4908 return error; 4909} 4910 4911/* 4912 * The calling routine must hold a reference on the share 4913 */ 4914int 4915smbfs_smb_mkdir(struct smb_share *share, struct smbnode *dnp, const char *name, 4916 size_t len, struct smbfattr *fap, vfs_context_t context) 4917{ 4918 SMBFID fid = 0; 4919 int error = 0; 4920 uint32_t desired_access = SMB2_FILE_READ_DATA; 4921 uint32_t share_access = NTCREATEX_SHARE_ACCESS_ALL; 4922 uint64_t create_flags = SMB2_CREATE_DO_CREATE | SMB2_CREATE_GET_MAX_ACCESS; 4923 uint32_t ntstatus = 0; 4924 4925 /* 4926 * We ask for SMB2_FILE_READ_DATA not because we need it, but 4927 * just to be asking for something. The rights == 0 case could 4928 * easily be broken on some old or unusual servers. 4929 */ 4930 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 4931 /* SMB 2 - do compound create/close */ 4932 error = smb2fs_smb_cmpd_create(share, dnp, 4933 name, len, 4934 NULL, 0, 4935 desired_access, VDIR, 4936 share_access, FILE_CREATE, 4937 create_flags, &ntstatus, 4938 NULL, fap, 4939 NULL, context); 4940 } 4941 else { 4942 /* SMB 1 */ 4943 error = smbfs_smb_ntcreatex(share, dnp, 4944 desired_access, share_access, VDIR, 4945 &fid, name, len, 4946 FILE_CREATE, 0, fap, 4947 TRUE, NULL, context); 4948 if (!error) { 4949 (void)smbfs_smb_close(share, fid, context); 4950 } 4951 } 4952 4953 return error; 4954} 4955 4956/* 4957 * The calling routine must hold a reference on the share 4958 */ 4959int 4960smb1fs_smb_rmdir(struct smb_share *share, struct smbnode *np, vfs_context_t context) 4961{ 4962 struct smb_rq rq, *rqp = &rq; 4963 struct mbchain *mbp; 4964 int error; 4965 4966 error = smb_rq_init(rqp, SSTOCP(share), SMB_COM_DELETE_DIRECTORY, 0, context); 4967 if (error) 4968 return error; 4969 smb_rq_getrequest(rqp, &mbp); 4970 smb_rq_wstart(rqp); 4971 smb_rq_wend(rqp); 4972 smb_rq_bstart(rqp); 4973 mb_put_uint8(mbp, SMB_DT_ASCII); 4974 error = smbfs_fullpath(mbp, np, NULL, NULL, UTF_SFM_CONVERSIONS, 4975 SMB_UNICODE_STRINGS(SSTOVC(share)), '\\'); 4976 if (!error) { 4977 smb_rq_bend(rqp); 4978 error = smb_rq_simple(rqp); 4979 } 4980 /* 4981 * We could have sent the delete before the connection went down, but we lost the 4982 * response. We resent the delete, but since it already succeeded we got an ENOENT 4983 * error. We are deleting something that does not exist, since it happen during 4984 * a reconnect take a guess that we succeeded. 4985 */ 4986 if ((error == ENOENT) && (rqp->sr_flags & SMBR_REXMIT)) 4987 error = 0; 4988 smb_rq_done(rqp); 4989 return error; 4990} 4991 4992/* 4993 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 4994 */ 4995static int 4996smbfs_smb_trans2find2(struct smbfs_fctx *ctx, vfs_context_t context) 4997{ 4998 struct smb_t2rq *t2p; 4999 struct mbchain *mbp; 5000 struct mdchain *mdp; 5001 uint16_t tw, flags; 5002 size_t len; 5003 int error; 5004 5005 if (ctx->f_t2) { 5006 smb_t2_done(ctx->f_t2); 5007 ctx->f_t2 = NULL; 5008 } 5009 ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; 5010 flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS; 5011 if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 5012 flags |= FIND2_CLOSE_AFTER_REQUEST; 5013 ctx->f_flags |= SMBFS_RDD_NOCLOSE; 5014 } 5015 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 5016 error = smb_t2_alloc(SSTOCP(ctx->f_share), SMB_TRANS2_FIND_FIRST2, 1, context, &t2p); 5017 if (error) 5018 return error; 5019 ctx->f_t2 = t2p; 5020 mbp = &t2p->t2_tparam; 5021 mb_init(mbp); 5022 mb_put_uint16le(mbp, ctx->f_attrmask); 5023 mb_put_uint16le(mbp, ctx->f_searchCount); 5024 mb_put_uint16le(mbp, flags); 5025 mb_put_uint16le(mbp, ctx->f_infolevel); 5026 mb_put_uint32le(mbp, 0); 5027 len = ctx->f_lookupNameLen; 5028 error = smbfs_fullpath(mbp, ctx->f_dnp, ctx->f_lookupName, &len, 5029 ctx->f_sfm_conversion, 5030 SMB_UNICODE_STRINGS(SSTOVC(ctx->f_share)), '\\'); 5031 if (error) 5032 return error; 5033 } else { 5034 error = smb_t2_alloc(SSTOCP(ctx->f_share), SMB_TRANS2_FIND_NEXT2, 1, context, &t2p); 5035 if (error) 5036 return error; 5037 ctx->f_t2 = t2p; 5038 mbp = &t2p->t2_tparam; 5039 mb_init(mbp); 5040 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 5041 mb_put_uint16le(mbp, ctx->f_searchCount); 5042 mb_put_uint16le(mbp, ctx->f_infolevel); 5043 /* If they give us a resume key return it */ 5044 mb_put_uint32le(mbp, ctx->f_rkey); 5045 mb_put_uint16le(mbp, flags); 5046 if (ctx->f_rname) { 5047 /* resume file name */ 5048 mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen, MB_MSYSTEM); 5049 } 5050 /* Add trailing null - 1 byte if ASCII, 2 if Unicode */ 5051 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_share))) 5052 mb_put_uint8(mbp, 0); /* 1st byte of NULL Unicode char */ 5053 mb_put_uint8(mbp, 0); 5054 } 5055 t2p->t2_maxpcount = 5 * 2; 5056 t2p->t2_maxdcount = SSTOVC(ctx->f_share)->vc_txmax; 5057 error = smb_t2_request(t2p); 5058 if (error) { 5059 /* 5060 * We told them to close search when end of search is reached. So if we 5061 * get an ENOENT, no reason to send a close. From testing this 5062 * is correct. Not sure about other errors, so for now only do it on 5063 * ENOENT. 5064 */ 5065 if (error == ENOENT) { 5066 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 5067 } 5068 return error; 5069 } 5070 mdp = &t2p->t2_rparam; 5071 /* 5072 * At this point md_cur and md_top have the same value. Now all the md_get 5073 * routines will will check for null, but just to be safe we check here 5074 */ 5075 if (mdp->md_cur == NULL) { 5076 SMBWARNING("Parsing error reading the message\n"); 5077 return EBADRPC; 5078 } 5079 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 5080 if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) 5081 return error; 5082 /* Turn on the SFM Conversion flag. Next call is a FindNext */ 5083 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 5084 ctx->f_sfm_conversion = UTF_SFM_CONVERSIONS; 5085 } 5086 if ((error = md_get_uint16le(mdp, &tw)) != 0) 5087 return error; 5088 ctx->f_ecnt = tw; /* search count - # entries returned */ 5089 if ((error = md_get_uint16le(mdp, &tw)) != 0) 5090 return error; 5091 /* 5092 * tw now is the "end of search" flag. against an XP server tw 5093 * comes back zero when the prior find_next returned exactly 5094 * the number of entries requested. in which case we'd try again 5095 * but the search has in fact been closed so an EBADF results. our 5096 * circumvention is to check here for a zero search count. 5097 */ 5098 if (tw || ctx->f_ecnt == 0) 5099 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 5100 if ((error = md_get_uint16le(mdp, &tw)) != 0) 5101 return error; 5102 if ((error = md_get_uint16le(mdp, &tw)) != 0) 5103 return error; 5104 if (ctx->f_ecnt == 0) 5105 return ENOENT; 5106 ctx->f_rnameofs = tw; 5107 mdp = &t2p->t2_rdata; 5108 if (mdp->md_top == NULL) { 5109 SMBERROR("bug: ecnt = %d, but data is NULL (please report)\n", ctx->f_ecnt); 5110 /* 5111 * Something bad has happened we did not get all the data. We 5112 * need to close the directory listing, otherwise we may cause 5113 * the calling process to hang in an infinite loop. 5114 */ 5115 ctx->f_ecnt = 0; /* Force the directory listing to close. */ 5116 ctx->f_flags |= SMBFS_RDD_EOF; 5117 return ENOENT; 5118 } 5119 /* 5120 * Changed the code to check to see if there is any data on the whole 5121 * mbuf chain, not just the first mbuf. Remember in a mbuf chain there 5122 * can be mbufs with nothing in them. Need to make sure we have data in 5123 * the mbuf chain, if not we received a bad message. 5124 */ 5125 m_fixhdr(mdp->md_top); 5126 if (mbuf_pkthdr_len(mdp->md_top) == 0) { 5127 SMBERROR("bug: ecnt = %d, but m_len = 0 and m_next = %p (please report)\n", 5128 ctx->f_ecnt, mbuf_next(mbp->mb_top)); 5129 /* 5130 * Something bad has happened we did not get all the data. We 5131 * need to close the directory listing, otherwise we may cause 5132 * the calling process to hang in an infinite loop. 5133 */ 5134 ctx->f_ecnt = 0; /* Force the directory listing to close. */ 5135 ctx->f_flags |= SMBFS_RDD_EOF; 5136 return ENOENT; 5137 } 5138 ctx->f_eofs = 0; 5139 return 0; 5140} 5141 5142static int 5143smbfs_ntwrk_findclose(struct smbfs_fctx *ctx, vfs_context_t context) 5144{ 5145 struct smb_rq rq, *rqp = &rq; 5146 struct mbchain *mbp; 5147 int error; 5148 5149 error = smb_rq_init(rqp, SSTOCP(ctx->f_share), SMB_COM_FIND_CLOSE2, 0, context); 5150 if (error) 5151 return error; 5152 smb_rq_getrequest(rqp, &mbp); 5153 smb_rq_wstart(rqp); 5154 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 5155 smb_rq_wend(rqp); 5156 smb_rq_bstart(rqp); 5157 smb_rq_bend(rqp); 5158 error = smb_rq_simple(rqp); 5159 smb_rq_done(rqp); 5160 return error; 5161} 5162 5163int 5164smb1fs_smb_findclose(struct smbfs_fctx *ctx, vfs_context_t context) 5165{ 5166 if (ctx->f_t2) 5167 smb_t2_done(ctx->f_t2); 5168 if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0) 5169 smbfs_ntwrk_findclose(ctx, context); 5170 /* We are done with the share release our reference */ 5171 smb_share_rele(ctx->f_share, context); 5172 5173 if (ctx->f_LocalName) { 5174 SMB_FREE(ctx->f_LocalName, M_SMBFSDATA); 5175 } 5176 5177 if (ctx->f_NetworkNameBuffer) { 5178 SMB_FREE(ctx->f_NetworkNameBuffer, M_SMBFSDATA); 5179 } 5180 5181 if (ctx->f_rname) { 5182 SMB_FREE(ctx->f_rname, M_SMBFSDATA); 5183 } 5184 5185 SMB_FREE(ctx, M_SMBFSDATA); 5186 return 0; 5187} 5188 5189int 5190smb1fs_smb_findnext(struct smbfs_fctx *ctx, vfs_context_t context) 5191{ 5192 struct mdchain *mdp; 5193 struct smb_t2rq *t2p; 5194 uint32_t next, dattr, resumekey = 0; 5195 uint64_t llint; 5196 int error, cnt; 5197 uint32_t fxsz, recsz; 5198 struct timespec ts; 5199 uint32_t eaSize; 5200 5201 if (ctx->f_ecnt == 0) { 5202 if (ctx->f_flags & SMBFS_RDD_EOF) 5203 return ENOENT; 5204 nanouptime(&ts); 5205 error = smbfs_smb_trans2find2(ctx, context); 5206 if (error) 5207 return error; 5208 ctx->f_attr.fa_reqtime = ts; 5209 } 5210 t2p = ctx->f_t2; 5211 mdp = &t2p->t2_rdata; 5212 5213 ctx->f_NetworkNameLen = 0; 5214 5215 /* Set default uid/gid values */ 5216 ctx->f_attr.fa_uid = KAUTH_UID_NONE; 5217 ctx->f_attr.fa_gid = KAUTH_GID_NONE; 5218 5219 switch (ctx->f_infolevel) { 5220 case SMB_FIND_BOTH_DIRECTORY_INFO: 5221 md_get_uint32le(mdp, &next); 5222 md_get_uint32le(mdp, &resumekey); /* file index (resume key) */ 5223 md_get_uint64le(mdp, &llint); /* creation time */ 5224 if (llint) { 5225 smb_time_NT2local(llint, &ctx->f_attr.fa_crtime); 5226 } 5227 md_get_uint64le(mdp, &llint); 5228 if (llint) { 5229 smb_time_NT2local(llint, &ctx->f_attr.fa_atime); 5230 } 5231 md_get_uint64le(mdp, &llint); 5232 if (llint) { 5233 smb_time_NT2local(llint, &ctx->f_attr.fa_mtime); 5234 } 5235 md_get_uint64le(mdp, &llint); 5236 if (llint) { 5237 smb_time_NT2local(llint, &ctx->f_attr.fa_chtime); 5238 } 5239 md_get_uint64le(mdp, &llint); /* data size */ 5240 ctx->f_attr.fa_size = llint; 5241 md_get_uint64le(mdp, &llint); /* data allocation size */ 5242 ctx->f_attr.fa_data_alloc = llint; 5243 /* freebsd bug: fa_attr endian bug */ 5244 md_get_uint32le(mdp, &dattr); /* extended file attributes */ 5245 ctx->f_attr.fa_attr = dattr; 5246 /* 5247 * Because of the Steve/Conrad Symlinks we can never be completely 5248 * sure that we have the correct vnode type if its a file. Since we 5249 * don't support Steve/Conrad Symlinks with Darwin we can always count 5250 * on the vtype being correct. For directories we always know the 5251 * correct information. 5252 */ 5253 if ((SSTOVC(ctx->f_share)->vc_flags & SMBV_DARWIN) || 5254 (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY)) { 5255 ctx->f_attr.fa_valid_mask |= FA_VTYPE_VALID; 5256 } 5257 ctx->f_attr.fa_vtype = (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY) ? VDIR : VREG; 5258 md_get_uint32le(mdp, &ctx->f_NetworkNameLen); 5259 fxsz = 64; /* size of info up to filename */ 5260 /* 5261 * Confirmed from MS: 5262 * When the attribute has the Reparse Point bit set then the EASize 5263 * contains the reparse tag info. This behavior is consistent for 5264 * Full, Both, FullId, or BothId query dir calls. It will pack the 5265 * reparse tag into the EaSize value if ATTRIBUTE_REPARSE_POINT is set. 5266 * I verified with local MS Engineers, and they also checking to make 5267 * sure the behavior is covered in MS-FSA. 5268 * 5269 * EAs and reparse points cannot both be in a file at the same 5270 * time. We return different information for each case. 5271 */ 5272 ctx->f_attr.fa_valid_mask |= FA_REPARSE_TAG_VALID; 5273 md_get_uint32le(mdp, &eaSize); /* extended attributes size */ 5274 if (ctx->f_attr.fa_attr & SMB_EFA_REPARSE_POINT) { 5275 ctx->f_attr.fa_reparse_tag = eaSize; 5276 if (ctx->f_attr.fa_reparse_tag == IO_REPARSE_TAG_SYMLINK) { 5277 ctx->f_attr.fa_valid_mask |= FA_VTYPE_VALID; 5278 ctx->f_attr.fa_vtype = VLNK; 5279 } 5280 } else { 5281 ctx->f_attr.fa_reparse_tag = IO_REPARSE_TAG_RESERVED_ZERO; 5282 } 5283 md_get_uint8(mdp, NULL); /* Skip short name Length */ 5284 md_get_uint8(mdp, NULL); /* Skip reserved byte */ 5285 /* Skip 8.3 short name, defined to be 12 WCHAR or 24 bytes. */ 5286 md_get_mem(mdp, NULL, 24, MB_MSYSTEM); 5287 fxsz += 30; 5288 recsz = next ? next : fxsz + ctx->f_NetworkNameLen; 5289 break; 5290 case SMB_FIND_FILE_UNIX_INFO2: 5291 md_get_uint32le(mdp, &next); 5292 md_get_uint32le(mdp, &resumekey); /* file index (resume key) */ 5293 5294 5295 md_get_uint64le(mdp, &llint); /* file size */ 5296 ctx->f_attr.fa_size = llint; 5297 5298 md_get_uint64le(mdp, &llint); /* allocation size */ 5299 ctx->f_attr.fa_data_alloc = llint; 5300 5301 md_get_uint64le(mdp, &llint); /* change time */ 5302 if (llint) 5303 smb_time_NT2local(llint, &ctx->f_attr.fa_chtime); 5304 5305 md_get_uint64le(mdp, &llint); /* access time */ 5306 if (llint) 5307 smb_time_NT2local(llint, &ctx->f_attr.fa_atime); 5308 5309 md_get_uint64le(mdp, &llint); /* write time */ 5310 if (llint) 5311 smb_time_NT2local(llint, &ctx->f_attr.fa_mtime); 5312 5313 md_get_uint64le(mdp, &llint); /* Numeric user id for the owner */ 5314 ctx->f_attr.fa_uid = llint; 5315 5316 md_get_uint64le(mdp, &llint); /* Numeric group id for the owner */ 5317 ctx->f_attr.fa_gid = llint; 5318 5319 md_get_uint32le(mdp, &dattr); /* Enumeration specifying the file type, st_mode */ 5320 /* Make sure the dos attributes are correct */ 5321 if (dattr & EXT_UNIX_DIR) { 5322 ctx->f_attr.fa_attr |= SMB_EFA_DIRECTORY; 5323 ctx->f_attr.fa_vtype = VDIR; 5324 } else { 5325 ctx->f_attr.fa_attr &= ~SMB_EFA_DIRECTORY; 5326 if (dattr & EXT_UNIX_SYMLINK) 5327 ctx->f_attr.fa_vtype = VLNK; 5328 else /* Do we ever what to handle the others? */ 5329 ctx->f_attr.fa_vtype = VREG; 5330 } 5331 5332 md_get_uint64le(mdp, &llint); /* Major device number if type is device */ 5333 md_get_uint64le(mdp, &llint); /* Minor device number if type is device */ 5334 md_get_uint64le(mdp, &llint); /* This is a server-assigned unique id */ 5335 md_get_uint64le(mdp, &llint); /* Standard UNIX permissions */ 5336 ctx->f_attr.fa_permissions = llint; 5337 ctx->f_attr.fa_valid_mask |= FA_UNIX_MODES_VALID; 5338 md_get_uint64le(mdp, &llint); /* Number of hard link */ 5339 ctx->f_attr.fa_nlinks = llint; 5340 5341 md_get_uint64le(mdp, &llint); /* creation time */ 5342 if (llint) 5343 smb_time_NT2local(llint, &ctx->f_attr.fa_crtime); 5344 5345 md_get_uint32le(mdp, &dattr); /* File flags enumeration */ 5346 md_get_uint32le(mdp, &ctx->f_attr.fa_flags_mask); /* Mask of valid flags */ 5347 if (ctx->f_attr.fa_flags_mask & EXT_HIDDEN) { 5348 if (dattr & EXT_HIDDEN) 5349 ctx->f_attr.fa_attr |= SMB_EFA_HIDDEN; 5350 else 5351 ctx->f_attr.fa_attr &= ~SMB_EFA_HIDDEN; 5352 } 5353 if (ctx->f_attr.fa_flags_mask & EXT_IMMUTABLE) { 5354 if (dattr & EXT_IMMUTABLE) 5355 ctx->f_attr.fa_attr |= SMB_EFA_RDONLY; 5356 else 5357 ctx->f_attr.fa_attr &= ~SMB_EFA_RDONLY; 5358 } 5359 if (ctx->f_attr.fa_flags_mask & EXT_DO_NOT_BACKUP) { 5360 if (dattr & EXT_DO_NOT_BACKUP) 5361 ctx->f_attr.fa_attr &= ~SMB_EFA_ARCHIVE; 5362 else 5363 ctx->f_attr.fa_attr |= SMB_EFA_ARCHIVE; 5364 } 5365 5366 ctx->f_attr.fa_unix = TRUE; 5367 5368 md_get_uint32le(mdp, &ctx->f_NetworkNameLen); 5369 fxsz = 128; /* size ofinfo up to filename */ 5370 recsz = next ? next : fxsz + ctx->f_NetworkNameLen; 5371 break; 5372 default: 5373 SMBERROR("unexpected info level %d\n", ctx->f_infolevel); 5374 return EINVAL; 5375 } 5376 if ((size_t)ctx->f_NetworkNameLen > ctx->f_MaxNetworkNameBufferSize) 5377 ctx->f_NetworkNameLen = (uint32_t)ctx->f_MaxNetworkNameBufferSize; 5378 error = md_get_mem(mdp, ctx->f_NetworkNameBuffer, ctx->f_NetworkNameLen, MB_MSYSTEM); 5379 if (error) 5380 return error; 5381 if (next) { 5382 cnt = next - ctx->f_NetworkNameLen - fxsz; 5383 if (cnt > 0) 5384 md_get_mem(mdp, NULL, cnt, MB_MSYSTEM); 5385 else if (cnt < 0) { 5386 SMBERROR("out of sync\n"); 5387 return EBADRPC; 5388 } 5389 } 5390 /* Don't count any trailing null in the name. */ 5391 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_share))) { 5392 if ((ctx->f_NetworkNameLen > 1) && (ctx->f_NetworkNameBuffer[ctx->f_NetworkNameLen - 1] == 0) && 5393 (ctx->f_NetworkNameBuffer[ctx->f_NetworkNameLen - 2] == 0)) 5394 ctx->f_NetworkNameLen -= 2; 5395 } else { 5396 if (ctx->f_NetworkNameLen && ctx->f_NetworkNameBuffer[ctx->f_NetworkNameLen - 1] == 0) 5397 ctx->f_NetworkNameLen--; 5398 } 5399 if (ctx->f_NetworkNameLen == 0) 5400 return EBADRPC; 5401 5402 /* 5403 * Ref radar 3983209. On a find-next we expect a server will 5404 * 1) if the continue bit is set, use the server's idea of current loc, 5405 * 2) else if the resume key is non-zero, use that location, 5406 * 3) else if the resume name is set, use that location, 5407 * 4) else use the server's idea of current location. 5408 * 5409 * There was some crazy code here to work around a NetApp bug, but it 5410 * was wrong. We always set the resume key flag. If the server returns a 5411 * resume key then we should send it back to them. This would have solve 5412 * the NetApp bug. 5413 */ 5414 ctx->f_rkey = resumekey; 5415 5416 next = ctx->f_eofs + recsz; 5417 if (ctx->f_rnameofs && ((ctx->f_flags & SMBFS_RDD_GOTRNAME) == 0) && 5418 ((ctx->f_rnameofs >= ctx->f_eofs) && (ctx->f_rnameofs < next))) { 5419 /* Server needs a resume filename. */ 5420 if (ctx->f_rnamelen < ctx->f_NetworkNameLen) { 5421 if (ctx->f_rname) { 5422 SMB_FREE(ctx->f_rname, M_SMBFSDATA); 5423 } 5424 SMB_MALLOC(ctx->f_rname, char *, ctx->f_NetworkNameLen, M_SMBFSDATA, M_WAITOK); 5425 } 5426 ctx->f_rnamelen = ctx->f_NetworkNameLen; 5427 bcopy(ctx->f_NetworkNameBuffer, ctx->f_rname, ctx->f_NetworkNameLen); 5428 ctx->f_flags |= SMBFS_RDD_GOTRNAME; 5429 } 5430 ctx->f_eofs = next; 5431 ctx->f_ecnt--; 5432 return 0; 5433} 5434 5435/* 5436 * The calling routine must hold a reference on the share 5437 */ 5438int 5439smbfs_smb_findopen(struct smb_share *share, struct smbnode *dnp, 5440 const char *lookupName, size_t lookupNameLen, 5441 struct smbfs_fctx **ctxpp, int wildCardLookup, 5442 vfs_context_t context) 5443{ 5444 struct smbfs_fctx *ctx; 5445 int error = 0; 5446 5447 SMB_MALLOC(ctx, struct smbfs_fctx *, sizeof(*ctx), M_SMBFSDATA, 5448 M_WAITOK | M_ZERO); 5449 if (ctx == NULL) { 5450 return ENOMEM; 5451 } 5452 5453 /* We need to hold a reference on the share for the life of the directory listing. */ 5454 ctx->f_share = share; 5455 smb_share_ref(ctx->f_share); 5456 ctx->f_dnp = dnp; 5457 ctx->f_flags |= SMBFS_RDD_FINDFIRST; 5458 /* 5459 * If this is a wildcard lookup then make sure we are not setting the 5460 * UTF_SFM_CONVERSIONS flag. We are either doing a lookup by name or we are 5461 * doing a wildcard lookup using the asterisk. When doing a wildcard lookup 5462 * the asterisk is legit, so we don't have to convert it. Now once we send 5463 * the FindFirst we need to turn the UTF_SFM_CONVERSIONS flag back on, this 5464 * is done in smbfs_smb_trans2find2. Also by definition non wildcard lookups 5465 * need to be single lookups, so if we are not doing a wildcard lookup then 5466 * set the SMBFS_RDD_FINDSINGLE flag. 5467 */ 5468 if (!wildCardLookup) { 5469 ctx->f_sfm_conversion = UTF_SFM_CONVERSIONS; 5470 ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 5471 ctx->f_searchCount = 1; 5472 } 5473 5474 if (UNIX_CAPS(share) & UNIX_FIND_FILE_UNIX_INFO2_CAP) { 5475 /* 5476 * Search count is the clients request for the max number of items to 5477 * be return. We could always request some large number, but lets just 5478 * request the max number of entries that will fit in a buffer. 5479 * 5480 * NOTE: We always make sure vc_txmax is 1k or larger. 5481 */ 5482 if (wildCardLookup) { 5483 ctx->f_searchCount = SSTOVC(share)->vc_txmax / SMB_FIND_FILE_UNIX_INFO2_MIN_LEN; 5484 } 5485 ctx->f_infolevel = SMB_FIND_FILE_UNIX_INFO2; 5486 } else { 5487 /* 5488 * Search count is the clients request for the max number of items to 5489 * be return. We could always request some large number, but lets just 5490 * request the max number of entries that will fit in a buffer. 5491 * 5492 * NOTE: We always make sure vc_txmax is 1k or larger. 5493 */ 5494 if (wildCardLookup) { 5495 ctx->f_searchCount = SSTOVC(share)->vc_txmax / SMB_FIND_BOTH_DIRECTORY_INFO_MIN_LEN; 5496 } 5497 5498 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 5499 /* Short Name info may contain special info if its a Mac OS Server */ 5500 ctx->f_infolevel = SMB_FIND_BOTH_DIRECTORY_INFO; 5501 } 5502 else { 5503 ctx->f_infolevel = SMB_FIND_BOTH_DIRECTORY_INFO; 5504 } 5505 } 5506 /* We always default to using the same attribute mask */ 5507 ctx->f_attrmask = SMB_EFA_SYSTEM | SMB_EFA_HIDDEN | SMB_EFA_DIRECTORY; 5508 ctx->f_lookupName = lookupName; 5509 ctx->f_lookupNameLen = lookupNameLen; 5510 /* 5511 * Unicode requires 4 * max file name len, codepage requires 3 * max file 5512 * name, so lets just always use the unicode size. 5513 */ 5514 ctx->f_MaxNetworkNameBufferSize = share->ss_maxfilenamelen * 4; 5515 SMB_MALLOC(ctx->f_NetworkNameBuffer, char *, ctx->f_MaxNetworkNameBufferSize, M_TEMP, M_WAITOK); 5516 if (ctx->f_NetworkNameBuffer == NULL) { 5517 SMBERROR("f_NetworkNameBuffer failed\n"); 5518 error = ENOMEM; 5519 } 5520 5521 if (error) { 5522 smbfs_smb_findclose(ctx, context); 5523 } 5524 else { 5525 *ctxpp = ctx; 5526 } 5527 5528 return error; 5529} 5530 5531int 5532smbfs_findnext(struct smbfs_fctx *ctx, vfs_context_t context) 5533{ 5534 int error; 5535 struct timespec save_reqtime; 5536 5537 for (;;) { 5538 /* save time that enumerate was done at */ 5539 save_reqtime = ctx->f_attr.fa_reqtime; 5540 bzero(&ctx->f_attr, sizeof(ctx->f_attr)); 5541 ctx->f_attr.fa_reqtime = save_reqtime; 5542 5543 error = smbfs_smb_findnext(ctx, context); 5544 if (error == EAGAIN) { 5545 /* 5546 * Try one more time, server may have a tempsmbfs_smb_qpathinfo 5547 * resource issue 5548 */ 5549 /* save time that enumerate was done at */ 5550 save_reqtime = ctx->f_attr.fa_reqtime; 5551 bzero(&ctx->f_attr, sizeof(ctx->f_attr)); 5552 ctx->f_attr.fa_reqtime = save_reqtime; 5553 5554 error = smbfs_smb_findnext(ctx, context); 5555 } 5556 if (error) { 5557 return error; 5558 } 5559 5560 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_share))) { 5561 /* ignore the Unicode '.' and '..' dirs */ 5562 if ((ctx->f_NetworkNameLen == 2 && 5563 letohs(*(uint16_t *)ctx->f_NetworkNameBuffer) == 0x002e) || 5564 (ctx->f_NetworkNameLen == 4 && 5565 letohl(*(uint32_t *)ctx->f_NetworkNameBuffer) == 0x002e002e)) 5566 continue; 5567 } 5568 else { 5569 /* ignore the '.' and '..' dirs */ 5570 if ((ctx->f_NetworkNameLen == 1 && ctx->f_NetworkNameBuffer[0] == '.') || 5571 (ctx->f_NetworkNameLen == 2 && ctx->f_NetworkNameBuffer[0] == '.' && 5572 ctx->f_NetworkNameBuffer[1] == '.')) 5573 continue; 5574 } 5575 break; 5576 } 5577 5578 /* 5579 * Successfully parsed out one entry from the search buffer 5580 * so return that one entry. 5581 */ 5582 if (ctx->f_LocalName) { 5583 SMB_FREE(ctx->f_LocalName, M_TEMP); /* Free any old name we may have */ 5584 } 5585 ctx->f_LocalNameLen = ctx->f_NetworkNameLen; 5586 ctx->f_LocalName = smbfs_ntwrkname_tolocal(ctx->f_NetworkNameBuffer, 5587 &ctx->f_LocalNameLen, 5588 SMB_UNICODE_STRINGS(SSTOVC(ctx->f_share))); 5589 5590 if (!(SSTOVC(ctx->f_share)->vc_misc_flags & SMBV_HAS_FILEIDS)) { 5591 /* Server does not support File IDs */ 5592 ctx->f_attr.fa_ino = smbfs_getino(ctx->f_dnp, 5593 ctx->f_LocalName, 5594 ctx->f_LocalNameLen); 5595 } 5596 5597 return 0; 5598} 5599 5600/* 5601 * The calling routine must hold a reference on the share 5602 */ 5603int 5604smbfs_lookup(struct smb_share *share, struct smbnode *dnp, const char **namep, 5605 size_t *nmlenp, struct smbfattr *fap, vfs_context_t context) 5606{ 5607 struct smbfs_fctx *ctx; 5608 int error = EINVAL; 5609 const char *name = (namep ? *namep : NULL); 5610 size_t nmlen = (nmlenp ? *nmlenp : 0); 5611 struct smbmount *smp; 5612 struct smb_vc *vcp = SSTOVC(share); 5613 enum vtype vnode_type = VREG; 5614 5615 DBG_ASSERT(dnp); 5616 5617 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_START, 0, 0, 0, 0, 0); 5618 5619 /* This should no longer happen, but just in case (should remove someday). */ 5620 if (dnp == NULL) { 5621 SMBERROR("The parent node is NULL, shouldn't happen\n"); 5622 error = EINVAL; 5623 goto done; 5624 } 5625 5626 smp = dnp->n_mount; 5627 if ((dnp->n_ino == smp->sm_root_ino) && (name == NULL)) { 5628 uint64_t DIFF1980TO1601 = 11960035200ULL*10000000ULL; 5629 5630 bzero(fap, sizeof(*fap)); 5631 5632 /* We keep track of the time the lookup call was requested */ 5633 nanouptime(&fap->fa_reqtime); 5634 5635 fap->fa_attr = SMB_EFA_DIRECTORY; 5636 fap->fa_vtype = VDIR; 5637 fap->fa_valid_mask |= FA_VTYPE_VALID; 5638 5639 if (smp->sm_root_ino == 0) { 5640 /* 5641 * Must be at mount time and we dont know what the root File ID is. 5642 * Assume its 2 to start with 5643 */ 5644 smp->sm_root_ino = SMBFS_ROOT_INO; 5645 fap->fa_ino = SMBFS_ROOT_INO; 5646 } 5647 else { 5648 /* Recreating root vnode and we know what its ID was */ 5649 fap->fa_ino = smp->sm_root_ino; 5650 } 5651 5652 /* Its the root,thus its a dir */ 5653 vnode_type = VDIR; 5654 5655 if (!(vcp->vc_misc_flags & SMBV_NO_QUERYINFO)) { 5656 /* Try the normal Query Info */ 5657 if (UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP) { 5658 error = smbfs_smb_qpathinfo(share, dnp, vnode_type, 5659 fap, SMB_QFILEINFO_UNIX_INFO2, 5660 NULL, NULL, 5661 context); 5662 } 5663 else { 5664 error = smbfs_smb_qpathinfo(share, dnp, vnode_type, 5665 fap, SMB_QFILEINFO_ALL_INFO, 5666 NULL, NULL, 5667 context); 5668 } 5669 5670 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5671 0xabc001, error, 0, 0, 0); 5672 5673 if (error) { 5674 /* This server does not support Query Info? */ 5675 SMBERROR("Server failed Query Info %d\n", error); 5676 vcp->vc_misc_flags |= SMBV_NO_QUERYINFO; 5677 } 5678 } 5679 5680 if ((vcp->vc_flags & SMBV_SMB2) && 5681 (vcp->vc_misc_flags & SMBV_NO_QUERYINFO)) { 5682 /* Use Query Dir instead of Query Info, but only if SMB 2/3 */ 5683 error = smb2fs_smb_cmpd_query_dir_one(share, dnp, 5684 NULL, 0, 5685 fap, NULL, NULL, 5686 context); 5687 5688 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5689 0xabc002, error, 0, 0, 0); 5690 } 5691 5692 /* 5693 * NTFS handles dates correctly, but FAT file systems have some 5694 * problems. If an entire FAT drive is shared, then the root of the 5695 * share may have either no dates (ie 0) or bad dates. This seems to 5696 * only happen with the root of the share, so we have to check for bad 5697 * dates and fix them up. Windows XP/2000/2003 will return Jan. 1, 1980 5698 * for the create, modif and access dates. NT4 will return no dates 5699 * at all. 5700 * 5701 * So we follow the Windows 2000 model. If any of the time 5702 * fields are zero we fill them in with Jan 1, 1980. 5703 * 5704 * Note: in setattr, we also do not allow any dates before 1980 for a 5705 * FAT file system. 5706 */ 5707 if (fap->fa_mtime.tv_sec == 0) 5708 smb_time_NT2local(DIFF1980TO1601, &fap->fa_mtime); 5709 if (fap->fa_crtime.tv_sec == 0) 5710 smb_time_NT2local(DIFF1980TO1601, &fap->fa_crtime); 5711 if (fap->fa_atime.tv_sec == 0) 5712 fap->fa_atime = fap->fa_mtime; 5713 if (fap->fa_chtime.tv_sec == 0) 5714 fap->fa_chtime = fap->fa_mtime; 5715 5716 goto done; 5717 } 5718 5719 if (nmlen == 1 && name && name[0] == '.') { 5720 error = smbfs_lookup(share, dnp, NULL, NULL, fap, context); 5721 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5722 0xabc003, error, 0, 0, 0); 5723 goto done; 5724 } else if (nmlen == 2 && name && name[0] == '.' && name[1] == '.') { 5725 /* 5726 * Remember that error is set to EINVAL. This should never happen, but 5727 * just in case make sure we have a parent, if not return EINVAL 5728 */ 5729 lck_rw_lock_shared(&dnp->n_parent_rwlock); 5730 if (dnp->n_parent) { 5731 error = smbfs_lookup(share, dnp->n_parent, NULL, NULL, fap, context); 5732 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5733 0xabc004, error, 0, 0, 0); 5734 } 5735 lck_rw_unlock_shared(&dnp->n_parent_rwlock); 5736 5737 goto done; 5738 } 5739 5740 bzero(fap, sizeof(*fap)); 5741 /* We keep track of the time the lookup call was requested */ 5742 nanouptime(&fap->fa_reqtime); 5743 5744 /* 5745 * So we now default to using FindFirst, because of Dfs. Only FindFirst 5746 * support getting the reparse point tag. If this is a stream node then 5747 * use the query info call to do the lookup. The FindFirst code doesn't 5748 * handle stream nodes yet, may want to change that in the future. 5749 */ 5750 if ((dnp->n_vnode) && vnode_isnamedstream(dnp->n_vnode)) { 5751 goto doQueryInfo; 5752 } 5753 5754 if (vcp->vc_flags & SMBV_SMB2) { 5755 /* SMB 2/3 can do this in in one compound req */ 5756 error = smb2fs_smb_cmpd_query_dir_one(share, dnp, 5757 name, nmlen, 5758 fap, (char **) namep, nmlenp, 5759 context); 5760 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5761 0xabc005, error, 0, 0, 0); 5762 } 5763 else { 5764 Boolean unix_symlink = ((UNIX_CAPS(share) & UNIX_SFILEINFO_UNIX_LINK_CAP)) ? TRUE : FALSE; 5765 Boolean darwin = (SSTOVC(share)->vc_flags & SMBV_DARWIN) ? TRUE : FALSE; 5766 5767 /* 5768 * We need to workaround a Samba Server bug. In some lookup paths, Samba 5769 * will follow the symlink to see if it exists before returning the info 5770 * requested. In the case were the symlink is broken Samba will return 5771 * that the symlink doesn't exist when its what the symlink points to that 5772 * doesn't exist. This can cause symlinks to appear not to exist in some case 5773 * and not others. Samba servers will follow the symlink if we make a 5774 * non wildcard FindFirst/Next call, but they will not follow it if we do a 5775 * Trans2Query. The problem we have here is the Trans2Query call does not 5776 * return the name of the file, which means we could have the wrong case. 5777 * 5778 * If they support unix symlinks and its not darwin then we know its one 5779 * of these Samba servers, this includes Snow Leopard Servers. 5780 * 5781 * So if we already have the vnode then we know its a symlink and have its 5782 * name so just make the Trans2Query call and we are done. 5783 * 5784 * In the case were we don't have the vnode we need to do the FindFirst/Next 5785 * call first, if that call returns ENOENT then we need to retry with a 5786 * Trans2Query call. This can cause a performance issue, but only when 5787 * the item doesn't exist and we should have this in our negative name 5788 * cache after this double lookup. 5789 */ 5790 if (unix_symlink && !darwin && (namep == NULL) && dnp->n_vnode && 5791 (vnode_vtype(dnp->n_vnode) == VLNK)) { 5792 return smbfs_smb_qpathinfo(share, dnp, VREG, 5793 fap, SMB_QFILEINFO_UNIX_INFO2, 5794 namep, nmlenp, 5795 context); 5796 } 5797 5798 /* SMB 1 using old, slower way */ 5799 error = smbfs_smb_findopen(share, dnp, name, nmlen, &ctx, FALSE, context); 5800 if (error) { 5801 /* Can't happen we do wait ok */ 5802 goto done; 5803 } 5804 error = smbfs_findnext(ctx, context); 5805 if (error == 0) { 5806 *fap = ctx->f_attr; 5807 if (name == NULL) { 5808 fap->fa_ino = dnp->n_ino; 5809 } 5810 if (namep) { 5811 *namep = ctx->f_LocalName; 5812 ctx->f_LocalName = NULL; 5813 } 5814 if (nmlenp) { 5815 *nmlenp = ctx->f_LocalNameLen; 5816 } 5817 } 5818 smbfs_smb_findclose(ctx, context); 5819 5820 /* 5821 * We need to workaround a Samba Server bug. See the comment above for 5822 * complete details. 5823 */ 5824 if ((error == ENOENT) && unix_symlink && !darwin && (namep)) { 5825 SMBWARNING("Working around Samba bug doing second lookup\n"); 5826 vnode_type = (ctx->f_attr.fa_attr & SMB_EFA_DIRECTORY) ? VDIR : VREG; 5827 error = smbfs_smb_qpathinfo(share, dnp, vnode_type, 5828 fap, SMB_QFILEINFO_UNIX_INFO2, 5829 namep, nmlenp, 5830 context); 5831 goto done; 5832 } 5833 } 5834 5835 /* 5836 * So if the FindFirst fails with an access error of some kind. If they support 5837 * the UNIX extensions we can try SMB_QFILEINFO_UNIX_INFO2. If they support 5838 * the NT CAPS option we can try SMB_QFILEINFO_ALL_INFO. Both Trans2 Query 5839 * Info levels return the same information as FindFirst and will work 5840 * with Drop boxes. 5841 * 5842 * Setting up a Drop Box for Windows 2000 and 2003 5843 * 5844 * 1. In Windows Explorer, right-click on the folder and choose 5845 * "Properties" 5846 * 2. Switch to the Security tab in the Properties dialog 5847 * 3. Confirm "Allow inheritable permissions from parent to propagate 5848 * to this object" is not checked. 5849 * 4. Confirm that CREATOR OWNER exist and has full access to 5850 * sub-folders and files. 5851 * 5. Select/Add the user, group or everyone who will only have drop box 5852 * permissions. 5853 * 6. Under the "Permissions" section at the bottom of the dialog, click 5854 * "Write" under the "Allow" column. 5855 * 7. Click on the Advanced Tab 5856 * 8. Select the user or group who will only have drop box permissions. 5857 * 9. Click "View/Edit" 5858 * 10. There are several different settings that will work, but here are 5859 * the ones required. 5860 * 5861 * In the Apply onto menu select "This Folder, subfolders and files". 5862 * 5863 * Select the following under the "Allow" column: 5864 * - Traverse Folders / Execute File 5865 * - Create Files / Write Data 5866 * - Create Folders / Append Data 5867 * - Write Attributes 5868 * - Write Extended Attributes 5869 * 5870 * 11. Click OK. 5871 * 12. Click Apply to apply your changes. 5872 * 13. Click OK 5873 * 5874 * Setting up a Drop Box for Windows NT 5875 * 5876 * 1. In Windows Explorer, right-click on the folder and choose 5877 * "Properties" 5878 * 2. Switch to the Security tab in the Properties dialog 5879 * 3. Click on the "Permissions" button. 5880 * 4. Confirm that CREATOR OWNER exist and has full control. 5881 * 5. Select/Add the user, group or everyone who will only have drop box 5882 * permissions. 5883 * 6. Double click on the user, group or everyone who will only have 5884 * drop box permissions. 5885 * 7. Check the Write checkbox. 5886 * 8. Un-check all the other checkboxes. 5887 * 9. Click Apply to apply your changes. 5888 * 10. Click OK 5889 * 5890 * Setting up a Drop Box for SAMBA on a Mac OS X system 5891 * 5892 * 1. Bring up a terminal. 5893 * 2. Create a folder and make the owner the administrator of the 5894 * system. 5895 * 3. Now run the chmod command give everyone write and execute 5896 * privileges. 5897 * e.g. chmod 733 ./DropBox 5898 * 5899 * If they support UNIX_QFILEINFO_UNIX_INFO2_CAP then they must support UNIX_INFO2. 5900 * Hopefully everyone does this correctly. Remember the SMB_QFILEINFO_UNIX_INFO2 call does 5901 * not return the name. So if they are asking for the name then just fail. 5902 * 5903 * NOTE: If we failed because of a low resources (EAGAIN) then try again. 5904 */ 5905 if ((error != EACCES) && (error != EPERM) && (error != EAGAIN)) { 5906 goto done; 5907 } 5908 5909doQueryInfo: 5910 /* 5911 * Either its a named stream vnode, or the Query Dir failed so try 5912 * doing a Query Info instead 5913 */ 5914 5915 /* 5916 * Since we dont know what the item is, try VREG as that is least likely 5917 * to return an error 5918 */ 5919 vnode_type = VREG; 5920 if (UNIX_CAPS(share) & UNIX_QFILEINFO_UNIX_INFO2_CAP) { 5921 if (namep == NULL) { 5922 error = smbfs_smb_qpathinfo(share, dnp, vnode_type, 5923 fap, SMB_QFILEINFO_UNIX_INFO2, 5924 namep, nmlenp, 5925 context); 5926 } else { 5927 /* If they are requesting the name, return error nothing else we can do here. */ 5928 error = EACCES; 5929 } 5930 } 5931 else { 5932 error = smbfs_smb_qpathinfo(share, dnp, vnode_type, 5933 fap, SMB_QFILEINFO_ALL_INFO, 5934 namep, nmlenp, 5935 context); 5936 } 5937 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_NONE, 5938 0xabc006, error, 0, 0, 0); 5939 5940done: 5941 SMB_LOG_KTRACE(SMB_DBG_SMBFS_LOOKUP | DBG_FUNC_END, error, 0, 0, 0, 0); 5942 return error; 5943} 5944 5945/* 5946 * Close the network search, reset the offset count and if there is 5947 * a next entry remove it. 5948 */ 5949void smbfs_closedirlookup(struct smbnode *np, vfs_context_t context) 5950{ 5951 if (np->d_fctx) 5952 smbfs_smb_findclose(np->d_fctx, context); 5953 np->d_fctx = NULL; 5954 np->d_offset = 0; 5955 if (np->d_nextEntry) 5956 SMB_FREE(np->d_nextEntry, M_TEMP); 5957 np->d_nextEntry = NULL; 5958 np->d_nextEntryLen = 0; 5959} 5960 5961/* 5962 * The calling routine must hold a reference on the share 5963 */ 5964static int 5965smbfs_smb_getsec_int(struct smb_share *share, SMBFID fid, uint32_t selector, 5966 struct ntsecdesc **res, uint32_t *reslen, 5967 vfs_context_t context) 5968{ 5969 struct smb_ntrq *ntp; 5970 struct mbchain *mbp; 5971 struct mdchain *mdp; 5972 int error; 5973 size_t len; 5974 uint16_t smb1_fid = (uint16_t) fid; 5975 5976 error = smb_nt_alloc(SSTOCP(share), NT_TRANSACT_QUERY_SECURITY_DESC, context, &ntp); 5977 if (error) 5978 return error; 5979 mbp = &ntp->nt_tparam; 5980 mb_init(mbp); 5981 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 5982 mb_put_uint16le(mbp, 0); /* reserved */ 5983 mb_put_uint32le(mbp, selector); 5984 ntp->nt_maxpcount = 4; 5985 ntp->nt_maxdcount = *reslen; 5986 error = smb_nt_request(ntp); 5987 *res = NULL; 5988 mdp = &ntp->nt_rparam; 5989 if (error) { 5990 /* 5991 * The error is that the buffer wasn't big enough; get 5992 * the required buffer size, so our caller can try again 5993 * with a bigger buffer. 5994 */ 5995 if (ntp->nt_flags & SMBT2_MOREDATA) 5996 md_get_uint32le(mdp, reslen); 5997 goto done; 5998 } else { 5999 md_get_uint32le(mdp, reslen); 6000 } 6001 mdp = &ntp->nt_rdata; 6002 if (mdp->md_top) { 6003 len = m_fixhdr(mdp->md_top); 6004 if (len != (size_t)*reslen) 6005 SMBWARNING("Sent us %ld but said they sent us %d for fid = 0x%x\n", 6006 len, *reslen, letohs(smb1_fid)); 6007 /* 6008 * The following "if (len < *reslen)" handles a Windows bug 6009 * observed when the underlying filesystem is FAT32. In that 6010 * case a 32 byte security descriptor comes back (S-1-1-0, ie 6011 * "Everyone") but the Parameter Block claims 44 is the length 6012 * of the security descriptor. (The Data Block length 6013 * claimed is 32. This server bug was reported against NT 6014 * first and I've personally observed it with W2K. 6015 */ 6016 6017 if (len < (size_t)*reslen) { 6018 /* Believe what we got instead of what they told us */ 6019 *reslen = (uint32_t)len; 6020 } else if (len > (size_t)*reslen) { 6021 len = *reslen; /* ignore any extra data */ 6022 } 6023 /* 6024 * All the calling routines expect to have sizeof(struct ntsecdesc). The 6025 * len is the amount of data we have received and *reslen is what they 6026 * claim they sent. Up above we make sure that *reslen and len are the 6027 * same. So all we need to do here is make sure that len is not less than 6028 * the size of our ntsecdesc structure. 6029 */ 6030 if (len >= sizeof(struct ntsecdesc)) { 6031 SMB_MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK); 6032 md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM); 6033 } else { 6034 SMBERROR("len %ld < ntsecdesc %ld fid 0x%x\n", len, 6035 sizeof(struct ntsecdesc), letohs(smb1_fid)); 6036 error = EBADRPC; 6037 } 6038 } else { 6039 SMBERROR("null md_top? fid 0x%x\n", letohs(smb1_fid)); 6040 error = EBADRPC; 6041 } 6042done: 6043 smb_nt_done(ntp); 6044 return (error); 6045} 6046 6047/* 6048 * The calling routine must hold a reference on the share 6049 */ 6050int 6051smbfs_smb_getsec(struct smb_share *share, struct smbnode *np, 6052 uint32_t desired_access, SMBFID fid, uint32_t selector, 6053 struct ntsecdesc **res, size_t *rt_len, vfs_context_t context) 6054{ 6055 int error; 6056 uint32_t seclen; 6057 6058 seclen = SSTOVC(share)->vc_txmax; 6059 6060 if (SSTOVC(share)->vc_flags & SMBV_SMB2) { 6061 error = smb2fs_smb_security_get(share, np, 6062 desired_access, selector, 6063 res, &seclen, 6064 context); 6065 } 6066 else { 6067 /* 6068 * If the buffer size is to small we could end up making two request. Using 6069 * the max transmit buffer should limit this from happening to often. 6070 */ 6071 error = smbfs_smb_getsec_int(share, fid, selector, res, &seclen, context); 6072 if (error && (seclen > SSTOVC(share)->vc_txmax)) { 6073 error = smbfs_smb_getsec_int(share, fid, selector, res, &seclen, 6074 context); 6075 } 6076 } 6077 6078 /* Return the the size we ended up getting */ 6079 if (error == 0) 6080 *rt_len = seclen; 6081 6082 return (error); 6083} 6084 6085/* 6086 * The calling routine must hold a reference on the share 6087 */ 6088int 6089smb1fs_setsec(struct smb_share *share, SMBFID fid, uint32_t selector, 6090 uint16_t ControlFlags, struct ntsid *owner, struct ntsid *group, 6091 struct ntacl *sacl, struct ntacl *dacl, vfs_context_t context) 6092{ 6093 struct smb_ntrq *ntp; 6094 struct mbchain *mbp; 6095 int error; 6096 uint32_t off; 6097 struct ntsecdesc ntsd; 6098 uint16_t smb1_fid = (uint16_t) fid; 6099 6100 error = smb_nt_alloc(SSTOCP(share), NT_TRANSACT_SET_SECURITY_DESC, 6101 context, &ntp); 6102 if (error) 6103 return error; 6104 mbp = &ntp->nt_tparam; 6105 mb_init(mbp); 6106 mb_put_mem(mbp, (caddr_t)&smb1_fid, sizeof(smb1_fid), MB_MSYSTEM); 6107 mb_put_uint16le(mbp, 0); /* reserved */ 6108 mb_put_uint32le(mbp, selector); 6109 mbp = &ntp->nt_tdata; 6110 mb_init(mbp); 6111 bzero(&ntsd, sizeof ntsd); 6112 ntsd.Revision = 0x01; /* Should we make this a define? */ 6113 /* 6114 * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN) 6115 * We set here only those bits we can be sure must be set. The rest 6116 * are up to the caller. In particular, the caller may intentionally 6117 * set an acl PRESENT bit while giving us a null pointer for the 6118 * acl - that sets a null acl, denying access to everyone. 6119 */ 6120 ControlFlags |= SE_SELF_RELATIVE; 6121 off = (uint32_t)sizeof(ntsd); 6122 if (owner) { 6123 ntsd.OffsetOwner = htolel(off); 6124 off += (uint32_t)sidlen(owner); 6125 } 6126 if (group) { 6127 ntsd.OffsetGroup = htolel(off); 6128 off += (uint32_t)sidlen(group); 6129 } 6130 if (sacl) { 6131 ControlFlags |= SE_SACL_PRESENT | SE_SACL_AUTO_INHERITED | SE_SACL_AUTO_INHERIT_REQ; 6132 ntsd.OffsetSacl = htolel(off); 6133 off += acllen(sacl); 6134 } 6135 if (dacl) { 6136 ControlFlags |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERITED | SE_DACL_AUTO_INHERIT_REQ; 6137 ntsd.OffsetDacl = htolel(off); 6138 } 6139 6140 ntsd.ControlFlags = htoles(ControlFlags); 6141 mb_put_mem(mbp, (caddr_t)&ntsd, sizeof ntsd, MB_MSYSTEM); 6142 if (owner) 6143 mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM); 6144 if (group) 6145 mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM); 6146 if (sacl) 6147 mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM); 6148 if (dacl) 6149 mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM); 6150 ntp->nt_maxpcount = 0; 6151 ntp->nt_maxdcount = 0; 6152 error = smb_nt_request(ntp); 6153 6154 if ((error != 0) && (ntp->nt_status == STATUS_INVALID_SID)) { 6155 /* 6156 * If the server returns STATUS_INVALID_SID, then just pretend that 6157 * we set the security info even though it "failed". 6158 * See <rdar://problem/10852453>. 6159 */ 6160 error = 0; 6161 } 6162 6163 smb_nt_done(ntp); 6164 return (error); 6165} 6166