1 /* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smbfs_smb.c,v 1.73.38.1 2005/05/27 02:35:28 lindak Exp $ 33 */ 34 35 /* 36 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/time.h> 45 #include <sys/vnode.h> 46 #include <sys/cmn_err.h> 47 48 #ifdef APPLE 49 #include <sys/smb_apple.h> 50 #include <sys/utfconv.h> 51 #else 52 #include <netsmb/smb_osdep.h> 53 #endif 54 55 #include <netsmb/smb.h> 56 #include <netsmb/smb_conn.h> 57 #include <netsmb/smb_subr.h> 58 #include <netsmb/smb_rq.h> 59 60 #include <smbfs/smbfs.h> 61 #include <smbfs/smbfs_node.h> 62 #include <smbfs/smbfs_subr.h> 63 64 /* 65 * Local functions. 66 * Not static, to aid debugging. 67 */ 68 69 int smbfs_smb_qfileinfo(struct smbnode *np, struct smbfattr *fap, 70 struct smb_cred *scrp, short infolevel); 71 int smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap, 72 struct smb_cred *scrp, short infolevel); 73 int smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen, 74 struct smbfattr *fap, struct smb_cred *scrp); 75 76 int smbfs_smb_statfsLM1(struct smb_share *ssp, 77 statvfs64_t *sbp, struct smb_cred *scrp); 78 int smbfs_smb_statfsLM2(struct smb_share *ssp, 79 statvfs64_t *sbp, struct smb_cred *scrp); 80 81 int smbfs_smb_setftime1(struct smbnode *np, uint16_t fid, 82 struct timespec *mtime, struct timespec *atime, 83 struct smb_cred *scrp); 84 int smbfs_smb_setfattrNT(struct smbnode *np, uint16_t fid, 85 uint32_t attr, struct timespec *mtime, struct timespec *atime, 86 struct smb_cred *scrp); 87 88 int smbfs_smb_setpattr1(struct smbnode *np, 89 const char *name, int len, uint32_t attr, 90 struct timespec *mtime, struct smb_cred *scrp); 91 int smbfs_smb_setpattr2(struct smbnode *np, uint32_t attr, 92 struct timespec *mtime, struct timespec *atime, 93 struct smb_cred *scrp); 94 int smbfs_smb_setpattrNT(struct smbnode *np, uint32_t attr, 95 struct timespec *mtime, struct timespec *atime, 96 struct smb_cred *scrp); 97 98 99 /* 100 * Todo: locking over-the-wire 101 */ 102 #ifdef APPLE 103 104 static int 105 smbfs_smb_lockandx(struct smbnode *np, int op, uint32_t pid, 106 offset_t start, uint64_t len, int largelock, 107 struct smb_cred *scrp, uint32_t timeout) 108 { 109 struct smb_share *ssp = np->n_mount->smi_share; 110 struct smb_rq rq, *rqp = &rq; 111 struct mbchain *mbp; 112 uint8_t ltype = 0; 113 int error; 114 115 /* Shared lock for n_fid use below. */ 116 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 117 118 if (op == SMB_LOCK_SHARED) 119 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK; 120 if (largelock) 121 ltype |= SMB_LOCKING_ANDX_LARGE_FILES; 122 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp); 123 if (error) 124 return (error); 125 smb_rq_getrequest(rqp, &mbp); 126 smb_rq_wstart(rqp); 127 mb_put_uint8(mbp, 0xff); /* secondary command */ 128 mb_put_uint8(mbp, 0); /* MBZ */ 129 mb_put_uint16le(mbp, 0); 130 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 131 mb_put_uint8(mbp, ltype); /* locktype */ 132 mb_put_uint8(mbp, 0); /* oplocklevel - 0 seems is NO_OPLOCK */ 133 mb_put_uint32le(mbp, timeout); /* 0 nowait, -1 infinite wait */ 134 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0); 135 mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1); 136 smb_rq_wend(rqp); 137 smb_rq_bstart(rqp); 138 mb_put_uint16le(mbp, pid); 139 if (!largelock) { 140 mb_put_uint32le(mbp, start); 141 mb_put_uint32le(mbp, len); 142 } else { 143 mb_put_uint16le(mbp, 0); /* pad */ 144 mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */ 145 mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */ 146 mb_put_uint32le(mbp, len >> 32); /* LengthHigh */ 147 mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */ 148 } 149 smb_rq_bend(rqp); 150 /* 151 * Don't want to risk missing a successful 152 * unlock send or lock response, or we could 153 * lose track of an outstanding lock. 154 */ 155 if (op == SMB_LOCK_RELEASE) 156 rqp->sr_flags |= SMBR_NOINTR_SEND; 157 else 158 rqp->sr_flags |= SMBR_NOINTR_RECV; 159 160 error = smb_rq_simple(rqp); 161 smb_rq_done(rqp); 162 return (error); 163 } 164 165 int 166 smbfs_smb_lock(struct smbnode *np, int op, caddr_t id, 167 offset_t start, uint64_t len, int largelock, 168 struct smb_cred *scrp, uint32_t timeout) 169 { 170 struct smb_share *ssp = np->n_mount->smi_share; 171 172 if (SMB_DIALECT(SSTOVC(ssp)) < SMB_DIALECT_LANMAN1_0) 173 /* 174 * TODO: use LOCK_BYTE_RANGE here. 175 */ 176 return (EINVAL); 177 else 178 return (smbfs_smb_lockandx(np, op, (uint32_t)id, start, len, 179 largelock, scrp, timeout)); 180 } 181 182 #endif /* APPLE */ 183 184 /* 185 * Helper for smbfs_getattr 186 * Something like nfs_getattr_otw 187 */ 188 int 189 smbfs_smb_getfattr( 190 struct smbnode *np, 191 struct smbfattr *fap, 192 struct smb_cred *scrp) 193 { 194 int error; 195 196 /* 197 * This lock is really only necessary for qfileinfo, 198 * but hopefully we use that most of the time. 199 * Lock may be writer (via open) or reader. 200 */ 201 ASSERT(np->r_lkserlock.count != 0); 202 203 if (np->n_fidrefs) 204 error = smbfs_smb_qfileinfo(np, fap, scrp, 0); 205 else 206 error = smbfs_smb_qpathinfo(np, fap, scrp, 0); 207 208 if (error == EINVAL) { 209 /* fallback */ 210 error = smbfs_smb_query_info(np, NULL, 0, fap, scrp); 211 } 212 213 #if 0 /* Moved this part to caller. */ 214 if (!error && fap->fa_mtime.tv_sec == 0) 215 smbfs_attr_touchdir(dnp); 216 #endif 217 218 return (error); 219 } 220 221 222 /* 223 * Nearly identical to smbfs_smb_qfileinfo (below). 224 * Please keep them in sync. 225 */ 226 int 227 smbfs_smb_qpathinfo(struct smbnode *np, struct smbfattr *fap, 228 struct smb_cred *scrp, short infolevel) 229 { 230 struct smb_share *ssp = np->n_mount->smi_share; 231 struct smb_vc *vcp = SSTOVC(ssp); 232 struct smb_t2rq *t2p; 233 int error, svtz, timesok = 1; 234 struct mbchain *mbp; 235 struct mdchain *mdp; 236 uint16_t date, time, wattr; 237 uint64_t llongint, lsize; 238 uint32_t size, dattr; 239 240 top: 241 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION, 242 scrp, &t2p); 243 if (error) 244 return (error); 245 mbp = &t2p->t2_tparam; 246 mb_init(mbp); 247 if (!infolevel) { 248 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) 249 infolevel = SMB_QFILEINFO_STANDARD; 250 else 251 infolevel = SMB_QFILEINFO_ALL_INFO; 252 } 253 mb_put_uint16le(mbp, infolevel); 254 mb_put_uint32le(mbp, 0); 255 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 256 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 257 if (error) { 258 smb_t2_done(t2p); 259 return (error); 260 } 261 t2p->t2_maxpcount = 2; 262 t2p->t2_maxdcount = vcp->vc_txmax; 263 error = smb_t2_request(t2p); 264 if (error) { 265 smb_t2_done(t2p); 266 /* Invalid info level? Try fallback. */ 267 if (error == EINVAL && 268 infolevel == SMB_QFILEINFO_ALL_INFO) { 269 infolevel = SMB_QFILEINFO_STANDARD; 270 goto top; 271 } 272 return (error); 273 } 274 mdp = &t2p->t2_rdata; 275 svtz = vcp->vc_sopt.sv_tz; 276 switch (infolevel) { 277 case SMB_QFILEINFO_STANDARD: 278 timesok = 0; 279 md_get_uint16le(mdp, NULL); 280 md_get_uint16le(mdp, NULL); /* creation time */ 281 md_get_uint16le(mdp, &date); 282 md_get_uint16le(mdp, &time); /* access time */ 283 if (date || time) { 284 timesok++; 285 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); 286 } 287 md_get_uint16le(mdp, &date); 288 md_get_uint16le(mdp, &time); /* modify time */ 289 if (date || time) { 290 timesok++; 291 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); 292 } 293 md_get_uint32le(mdp, &size); 294 fap->fa_size = size; 295 md_get_uint32(mdp, NULL); /* allocation size */ 296 md_get_uint16le(mdp, &wattr); 297 fap->fa_attr = wattr; 298 break; 299 case SMB_QFILEINFO_ALL_INFO: 300 timesok = 0; 301 /* creation time (discard) */ 302 md_get_uint64(mdp, NULL); 303 /* last access time */ 304 md_get_uint64le(mdp, &llongint); 305 if (llongint) { 306 timesok++; 307 smb_time_NT2local(llongint, svtz, &fap->fa_atime); 308 } 309 /* last write time */ 310 md_get_uint64le(mdp, &llongint); 311 if (llongint) { 312 timesok++; 313 smb_time_NT2local(llongint, svtz, &fap->fa_mtime); 314 } 315 /* last change time */ 316 md_get_uint64le(mdp, &llongint); 317 if (llongint) { 318 timesok++; 319 smb_time_NT2local(llongint, svtz, &fap->fa_ctime); 320 } 321 /* attributes */ 322 md_get_uint32le(mdp, &dattr); 323 fap->fa_attr = dattr; 324 /* 325 * 4-Byte alignment - discard 326 * Specs doesn't talk about this. 327 */ 328 md_get_uint32le(mdp, NULL); 329 /* allocation size (discard) */ 330 md_get_uint64le(mdp, NULL); 331 /* File size */ 332 md_get_uint64le(mdp, &lsize); 333 fap->fa_size = lsize; 334 break; 335 default: 336 SMBVDEBUG("unexpected info level %d\n", infolevel); 337 error = EINVAL; 338 } 339 smb_t2_done(t2p); 340 /* 341 * if all times are zero (observed with FAT on NT4SP6) 342 * then fall back to older info level 343 */ 344 if (!timesok) { 345 if (infolevel == SMB_QFILEINFO_ALL_INFO) { 346 infolevel = SMB_QFILEINFO_STANDARD; 347 goto top; 348 } 349 error = EINVAL; 350 } 351 return (error); 352 } 353 354 /* 355 * Nearly identical to smbfs_smb_qpathinfo (above). 356 * Please keep them in sync. 357 */ 358 int 359 smbfs_smb_qfileinfo(struct smbnode *np, struct smbfattr *fap, 360 struct smb_cred *scrp, short infolevel) 361 { 362 struct smb_share *ssp = np->n_mount->smi_share; 363 struct smb_vc *vcp = SSTOVC(ssp); 364 struct smb_t2rq *t2p; 365 int error, svtz, timesok = 1; 366 struct mbchain *mbp; 367 struct mdchain *mdp; 368 uint16_t date, time, wattr; 369 uint64_t llongint, lsize; 370 uint32_t size, dattr; 371 372 /* 373 * Shared lock for n_fid use below. 374 * See smbfs_smb_getfattr() 375 */ 376 ASSERT(np->r_lkserlock.count != 0); 377 378 if (np->n_fid == SMB_FID_UNUSED) 379 return (EBADF); 380 381 top: 382 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FILE_INFORMATION, 383 scrp, &t2p); 384 if (error) 385 return (error); 386 mbp = &t2p->t2_tparam; 387 mb_init(mbp); 388 if (!infolevel) { 389 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) 390 infolevel = SMB_QFILEINFO_STANDARD; 391 else 392 infolevel = SMB_QFILEINFO_ALL_INFO; 393 } 394 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 395 mb_put_uint16le(mbp, infolevel); 396 t2p->t2_maxpcount = 2; 397 t2p->t2_maxdcount = vcp->vc_txmax; 398 error = smb_t2_request(t2p); 399 if (error) { 400 smb_t2_done(t2p); 401 /* Invalid info level? Try fallback. */ 402 if (error == EINVAL && 403 infolevel == SMB_QFILEINFO_ALL_INFO) { 404 infolevel = SMB_QFILEINFO_STANDARD; 405 goto top; 406 } 407 return (error); 408 } 409 mdp = &t2p->t2_rdata; 410 svtz = vcp->vc_sopt.sv_tz; 411 switch (infolevel) { 412 case SMB_QFILEINFO_STANDARD: 413 timesok = 0; 414 md_get_uint16le(mdp, NULL); 415 md_get_uint16le(mdp, NULL); /* creation time */ 416 md_get_uint16le(mdp, &date); 417 md_get_uint16le(mdp, &time); /* access time */ 418 if (date || time) { 419 timesok++; 420 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_atime); 421 } 422 md_get_uint16le(mdp, &date); 423 md_get_uint16le(mdp, &time); /* modify time */ 424 if (date || time) { 425 timesok++; 426 smb_dos2unixtime(date, time, 0, svtz, &fap->fa_mtime); 427 } 428 md_get_uint32le(mdp, &size); 429 fap->fa_size = size; 430 md_get_uint32(mdp, NULL); /* allocation size */ 431 md_get_uint16le(mdp, &wattr); 432 fap->fa_attr = wattr; 433 break; 434 case SMB_QFILEINFO_ALL_INFO: 435 timesok = 0; 436 /* creation time (discard) */ 437 md_get_uint64(mdp, NULL); 438 /* last access time */ 439 md_get_uint64le(mdp, &llongint); 440 if (llongint) { 441 timesok++; 442 smb_time_NT2local(llongint, svtz, &fap->fa_atime); 443 } 444 /* last write time */ 445 md_get_uint64le(mdp, &llongint); 446 if (llongint) { 447 timesok++; 448 smb_time_NT2local(llongint, svtz, &fap->fa_mtime); 449 } 450 /* last change time */ 451 md_get_uint64le(mdp, &llongint); 452 if (llongint) { 453 timesok++; 454 smb_time_NT2local(llongint, svtz, &fap->fa_ctime); 455 } 456 /* attributes */ 457 md_get_uint32le(mdp, &dattr); 458 fap->fa_attr = dattr; 459 /* 460 * 4-Byte alignment - discard 461 * Specs doesn't talk about this. 462 */ 463 md_get_uint32le(mdp, NULL); 464 /* allocation size (discard) */ 465 md_get_uint64le(mdp, NULL); 466 /* File size */ 467 md_get_uint64le(mdp, &lsize); 468 fap->fa_size = lsize; 469 break; 470 default: 471 SMBVDEBUG("unexpected info level %d\n", infolevel); 472 error = EINVAL; 473 } 474 smb_t2_done(t2p); 475 /* 476 * if all times are zero (observed with FAT on NT4SP6) 477 * then fall back to older info level 478 */ 479 if (!timesok) { 480 if (infolevel == SMB_QFILEINFO_ALL_INFO) { 481 infolevel = SMB_QFILEINFO_STANDARD; 482 goto top; 483 } 484 error = EINVAL; 485 } 486 return (error); 487 } 488 489 /* 490 * Support functions for _qstreaminfo 491 * Todo: show NT file streams as 492 * Solaris named attributes. 493 */ 494 #ifdef APPLE 495 496 static char * 497 sfm2xattr(char *sfm) 498 { 499 if (!strncasecmp(sfm, SFM_RESOURCEFORK_NAME, 500 sizeof (SFM_RESOURCEFORK_NAME))) 501 return (XATTR_RESOURCEFORK_NAME); 502 if (!strncasecmp(sfm, SFM_FINDERINFO_NAME, 503 sizeof (SFM_FINDERINFO_NAME))) 504 return (XATTR_FINDERINFO_NAME); 505 return (NULL); 506 } 507 508 static int 509 smbfs_smb_undollardata(struct smbnode *np, struct smbfs_fctx *ctx) 510 { 511 char *cp; 512 int len = strlen(SMB_DATASTREAM); 513 514 if (!ctx->f_name) /* sanity check */ 515 goto bad; 516 if (ctx->f_nmlen < len + 1) /* "::$DATA" at a minimum */ 517 goto bad; 518 if (*ctx->f_name != ':') /* leading colon - "always" */ 519 goto bad; 520 cp = &ctx->f_name[ctx->f_nmlen - len]; /* point to 2nd colon */ 521 if (bcmp(cp, SMB_DATASTREAM, len)) 522 goto bad; 523 if (ctx->f_nmlen == len + 1) /* merely the data fork? */ 524 return (0); /* skip it */ 525 /* 526 * XXX here we should be calling KPI to validate the stream name 527 */ 528 if (ctx->f_nmlen >= 18 && 529 !(bcmp(ctx->f_name, ":com.apple.system.", 18) == 0)) 530 return (0); /* skip protected system attrs */ 531 if (ctx->f_nmlen - len > XATTR_MAXNAMELEN + 1) 532 goto bad; /* mustnt return more than 128 bytes */ 533 /* 534 * Un-count a colon and the $DATA, then the 535 * 2nd colon is replaced by a terminating null. 536 */ 537 ctx->f_nmlen -= len; 538 *cp = '\0'; 539 return (1); 540 bad: 541 SMBSDEBUG("file \"%.*s\" has bad stream \"%.*s\"\n", 542 np->n_nmlen, np->n_name, ctx->f_nmlen, ctx->f_name); 543 return (0); /* skip it */ 544 } 545 546 PRIVSYM int 547 smbfs_smb_qstreaminfo(struct smbnode *np, struct smb_cred *scrp, 548 uio_t uio, size_t *sizep) 549 { 550 struct smb_share *ssp = np->n_mount->smi_share; 551 struct smb_vc *vcp = SSTOVC(ssp); 552 struct smb_t2rq *t2p; 553 int error; 554 struct mbchain *mbp; 555 struct mdchain *mdp; 556 uint32_t next, nlen, used; 557 struct smbfs_fctx ctx; 558 559 *sizep = 0; 560 ctx.f_ssp = ssp; 561 ctx.f_name = NULL; 562 563 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_PATH_INFORMATION, 564 scrp, &t2p); 565 if (error) 566 return (error); 567 mbp = &t2p->t2_tparam; 568 mb_init(mbp); 569 /* 570 * SMB_QFILEINFO_STREAM_INFORMATION is an option to consider 571 * here. Samba declined to support the older info level with 572 * a comment claiming doing so caused a BSOD. 573 */ 574 mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO); 575 mb_put_uint32le(mbp, 0); 576 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ 577 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 578 if (error) 579 goto out; 580 t2p->t2_maxpcount = 2; 581 t2p->t2_maxdcount = vcp->vc_txmax; 582 error = smb_t2_request(t2p); 583 if (error) { 584 if (smb_t2_err(t2p) == NT_STATUS_INVALID_PARAMETER) 585 error = ENOTSUP; 586 goto out; 587 } 588 mdp = &t2p->t2_rdata; 589 /* 590 * On a directory Windows is likely to return a zero data count. 591 * Check for that now to avoid EBADRPC from md_get_uint32le 592 */ 593 if (mdp->md_cur == NULL) 594 goto out; 595 do { 596 if ((error = md_get_uint32le(mdp, &next))) 597 goto out; 598 if ((error = md_get_uint32le(mdp, &nlen))) /* name length */ 599 goto out; 600 if ((error = md_get_uint64le(mdp, NULL))) /* stream size */ 601 goto out; 602 if ((error = md_get_uint64le(mdp, NULL))) /* allocated size */ 603 goto out; 604 /* 605 * Sanity check to limit DoS or buffer overrun attempts. 606 * The arbitrary 16384 is sufficient for all legit packets. 607 */ 608 if (nlen > 16384) { 609 SMBVDEBUG("huge name length in packet!\n"); 610 error = EBADRPC; 611 goto out; 612 } 613 ctx.f_name = kmem_zalloc(nlen, KM_SLEEP); 614 ctx.f_namesz = nlen; 615 if ((error = md_get_mem(mdp, ctx.f_name, nlen, MB_MSYSTEM))) 616 goto out; 617 /* 618 * skip pad bytes and/or tail of overlong name 619 */ 620 used = 4 + 4 + 8 + 8 + nlen; 621 if (next && next > used) { 622 if (next - used > 16384) { 623 SMBVDEBUG("huge offset in packet!\n"); 624 error = EBADRPC; 625 goto out; 626 } 627 md_get_mem(mdp, NULL, next - used, MB_MSYSTEM); 628 } 629 /* ignore a trailing null, not that we expect them */ 630 if (SMB_UNICODE_STRINGS(vcp)) { 631 if (nlen > 1 && !ctx.f_name[nlen - 1] && 632 !ctx.f_name[nlen - 2]) 633 nlen -= 2; 634 } else { 635 if (nlen && !ctx.f_name[nlen - 1]) 636 nlen -= 1; 637 } 638 ctx.f_nmlen = nlen; 639 smbfs_fname_tolocal(&ctx); /* converts from UCS2LE */ 640 /* 641 * We should now have a name in the form 642 * : <foo> :$DATA 643 * Where <foo> is UTF-8 w/o null termination 644 * If it isn't in that form we want to LOG it and skip it. 645 * Note we want to skip w/o logging the "data fork" entry, 646 * which is simply ::$DATA 647 * Otherwise we want to uiomove out <foo> with a null added. 648 */ 649 if (smbfs_smb_undollardata(np, &ctx)) { 650 char *s; 651 652 /* the "+ 1" skips over the leading colon */ 653 s = sfm2xattr(ctx.f_name + 1); 654 #ifndef DUAL_EAS /* XXX */ 655 /* 656 * In Tiger Carbon still accesses dot-underscore files directly, so... 657 * For Tiger we preserve the SFM/Thursby AFP_* stream names rather 658 * than mapping them to com.apple.*. This means our copy engines 659 * will preserve SFM/Thursby resource-fork and finder-info. 660 */ 661 s = NULL; 662 #endif 663 if (s) 664 ctx.f_nmlen = strlen(s) + 1; 665 else 666 s = ctx.f_name + 1; 667 if (uio) 668 uiomove(s, ctx.f_nmlen, uio); 669 else 670 *sizep += ctx.f_nmlen; 671 } 672 kmem_free(ctx.f_name, ctx.f_namesz); 673 ctx.f_name = NULL; 674 } while (next && !error); 675 out: 676 if (ctx.f_name) 677 kmem_free(ctx.f_name, ctx.f_namesz); 678 smb_t2_done(t2p); 679 return (error); 680 } 681 682 #endif /* APPLE */ 683 684 int 685 smbfs_smb_qfsattr(struct smb_share *ssp, uint32_t *attrp, 686 struct smb_cred *scrp) 687 { 688 struct smb_t2rq *t2p; 689 struct mbchain *mbp; 690 struct mdchain *mdp; 691 uint32_t nlen; 692 int error; 693 char *fs_name; /* will malloc whatever the size is */ 694 struct smbfs_fctx ctx; 695 696 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 697 scrp, &t2p); 698 if (error) 699 return (error); 700 mbp = &t2p->t2_tparam; 701 mb_init(mbp); 702 mb_put_uint16le(mbp, SMB_QFS_ATTRIBUTE_INFO); 703 t2p->t2_maxpcount = 4; 704 t2p->t2_maxdcount = 4 * 3 + 512; 705 error = smb_t2_request(t2p); 706 if (error) { 707 smb_t2_done(t2p); 708 return (error); 709 } 710 mdp = &t2p->t2_rdata; 711 md_get_uint32le(mdp, attrp); 712 md_get_uint32le(mdp, &ssp->ss_maxfilenamelen); 713 md_get_uint32le(mdp, &nlen); /* fs name length */ 714 if (ssp->ss_fsname == NULL && nlen) { 715 ctx.f_ssp = ssp; 716 ctx.f_name = kmem_alloc(nlen, KM_SLEEP); 717 ctx.f_namesz = nlen; 718 md_get_mem(mdp, ctx.f_name, nlen, MB_MSYSTEM); 719 ctx.f_nmlen = nlen; 720 smbfs_fname_tolocal(&ctx); 721 fs_name = kmem_alloc(ctx.f_nmlen+1, KM_SLEEP); 722 bcopy(ctx.f_name, fs_name, ctx.f_nmlen); 723 fs_name[ctx.f_nmlen] = '\0'; 724 ssp->ss_fsname = fs_name; 725 kmem_free(ctx.f_name, ctx.f_namesz); 726 /* 727 * If fs_name isn't NTFS they probably require resume keys. 728 * This is another example of the client trying to fix a server 729 * bug. This code uses the logic created by PR-3983209. See 730 * long block comment in smbfs_smb_findnextLM2. 731 */ 732 if (strcmp(fs_name, "NTFS")) { 733 SMB_SS_LOCK(ssp); 734 ssp->ss_flags |= SMBS_RESUMEKEYS; 735 SMB_SS_UNLOCK(ssp); 736 } 737 SMBVDEBUG("(fyi) share '%s', attr 0x%x, maxfilename %d\n", 738 ssp->ss_fsname, *attrp, ssp->ss_maxfilenamelen); 739 } 740 smb_t2_done(t2p); 741 return (0); 742 } 743 744 int 745 smbfs_smb_statfs(struct smb_share *ssp, statvfs64_t *sbp, 746 struct smb_cred *scp) 747 { 748 int error; 749 750 if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) 751 error = smbfs_smb_statfsLM2(ssp, sbp, scp); 752 else 753 error = smbfs_smb_statfsLM1(ssp, sbp, scp); 754 755 return (error); 756 } 757 758 int 759 smbfs_smb_statfsLM2(struct smb_share *ssp, statvfs64_t *sbp, 760 struct smb_cred *scrp) 761 { 762 struct smb_t2rq *t2p; 763 struct mbchain *mbp; 764 struct mdchain *mdp; 765 uint16_t bsize; 766 uint32_t units, bpu, funits; 767 uint64_t s, t, f; 768 int error; 769 770 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION, 771 scrp, &t2p); 772 if (error) 773 return (error); 774 mbp = &t2p->t2_tparam; 775 mb_init(mbp); 776 mb_put_uint16le(mbp, SMB_QFS_ALLOCATION); 777 t2p->t2_maxpcount = 4; 778 t2p->t2_maxdcount = 4 * 4 + 2; 779 error = smb_t2_request(t2p); 780 if (error) { 781 smb_t2_done(t2p); 782 return (error); 783 } 784 mdp = &t2p->t2_rdata; 785 md_get_uint32(mdp, NULL); /* fs id */ 786 md_get_uint32le(mdp, &bpu); 787 md_get_uint32le(mdp, &units); 788 md_get_uint32le(mdp, &funits); 789 md_get_uint16le(mdp, &bsize); 790 s = bsize; 791 s *= bpu; 792 t = units; 793 f = funits; 794 /* 795 * Don't allow over-large blocksizes as they determine 796 * Finder List-view size granularities. On the other 797 * hand, we mustn't let the block count overflow the 798 * 31 bits available. 799 */ 800 while (s > 16 * 1024) { 801 if (t > LONG_MAX) 802 break; 803 s /= 2; 804 t *= 2; 805 f *= 2; 806 } 807 while (t > LONG_MAX) { 808 t /= 2; 809 f /= 2; 810 s *= 2; 811 } 812 sbp->f_bsize = (ulong_t)s; /* file system block size */ 813 sbp->f_blocks = t; /* total data blocks in file system */ 814 sbp->f_bfree = f; /* free blocks in fs */ 815 sbp->f_bavail = f; /* free blocks avail to non-superuser */ 816 sbp->f_files = (-1); /* total file nodes in file system */ 817 sbp->f_ffree = (-1); /* free file nodes in fs */ 818 smb_t2_done(t2p); 819 return (0); 820 } 821 822 int 823 smbfs_smb_statfsLM1(struct smb_share *ssp, statvfs64_t *sbp, 824 struct smb_cred *scrp) 825 { 826 struct smb_rq rq, *rqp = &rq; 827 struct mdchain *mdp; 828 uint16_t units, bpu, bsize, funits; 829 uint64_t s, t, f; 830 int error; 831 832 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, 833 scrp); 834 if (error) 835 return (error); 836 smb_rq_wstart(rqp); 837 smb_rq_wend(rqp); 838 smb_rq_bstart(rqp); 839 smb_rq_bend(rqp); 840 error = smb_rq_simple(rqp); 841 if (error) { 842 smb_rq_done(rqp); 843 return (error); 844 } 845 smb_rq_getreply(rqp, &mdp); 846 md_get_uint16le(mdp, &units); 847 md_get_uint16le(mdp, &bpu); 848 md_get_uint16le(mdp, &bsize); 849 md_get_uint16le(mdp, &funits); 850 s = bsize; 851 s *= bpu; 852 t = units; 853 f = funits; 854 /* 855 * Don't allow over-large blocksizes as they determine 856 * Finder List-view size granularities. On the other 857 * hand, we mustn't let the block count overflow the 858 * 31 bits available. 859 */ 860 while (s > 16 * 1024) { 861 if (t > LONG_MAX) 862 break; 863 s /= 2; 864 t *= 2; 865 f *= 2; 866 } 867 while (t > LONG_MAX) { 868 t /= 2; 869 f /= 2; 870 s *= 2; 871 } 872 sbp->f_bsize = (ulong_t)s; /* file system block size */ 873 sbp->f_blocks = t; /* total data blocks in file system */ 874 sbp->f_bfree = f; /* free blocks in fs */ 875 sbp->f_bavail = f; /* free blocks avail to non-superuser */ 876 sbp->f_files = (-1); /* total file nodes in file system */ 877 sbp->f_ffree = (-1); /* free file nodes in fs */ 878 smb_rq_done(rqp); 879 return (0); 880 } 881 882 int 883 smbfs_smb_seteof(struct smb_share *ssp, uint16_t fid, uint64_t newsize, 884 struct smb_cred *scrp) 885 { 886 struct smb_t2rq *t2p; 887 struct smb_vc *vcp = SSTOVC(ssp); 888 struct mbchain *mbp; 889 int error; 890 891 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 892 scrp, &t2p); 893 if (error) 894 return (error); 895 mbp = &t2p->t2_tparam; 896 mb_init(mbp); 897 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 898 if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) 899 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFORMATION); 900 else 901 mb_put_uint16le(mbp, SMB_SFILEINFO_END_OF_FILE_INFO); 902 mb_put_uint32le(mbp, 0); /* XXX should be 16 not 32(?) */ 903 mbp = &t2p->t2_tdata; 904 mb_init(mbp); 905 mb_put_uint64le(mbp, newsize); 906 mb_put_uint32le(mbp, 0); /* padding */ 907 mb_put_uint16le(mbp, 0); 908 t2p->t2_maxpcount = 2; 909 t2p->t2_maxdcount = 0; 910 error = smb_t2_request(t2p); 911 smb_t2_done(t2p); 912 return (error); 913 } 914 915 /*ARGSUSED*/ 916 int 917 smbfs_smb_t2rename(struct smbnode *np, struct smbnode *tdnp, 918 const char *tname, int tnmlen, struct smb_cred *scrp, int overwrite) 919 { 920 struct smb_t2rq *t2p; 921 struct smb_share *ssp = np->n_mount->smi_share; 922 struct smb_vc *vcp = SSTOVC(ssp); 923 struct mbchain *mbp; 924 int32_t *ucslenp; 925 int error, cerror; 926 uint16_t fid = 0; 927 928 /* Shared lock for n_fid use below. */ 929 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 930 931 if (!(vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)) 932 return (ENOTSUP); 933 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 934 scrp, &t2p); 935 if (error) 936 return (error); 937 if (tdnp) { 938 error = smbfs_smb_tmpopen(tdnp, SA_RIGHT_FILE_READ_DATA, scrp, 939 &fid); 940 if (error) 941 goto exit; 942 } 943 mbp = &t2p->t2_tparam; 944 mb_init(mbp); 945 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 946 mb_put_uint16le(mbp, SMB_SFILEINFO_RENAME_INFORMATION); 947 mb_put_uint16le(mbp, 0); /* reserved, nowadays */ 948 mbp = &t2p->t2_tdata; 949 mb_init(mbp); 950 mb_put_uint32le(mbp, overwrite); 951 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); /* base for tname */ 952 mb_put_uint16le(mbp, 0); /* part of a 32bit fid? */ 953 ucslenp = (int32_t *)mb_reserve(mbp, sizeof (int32_t)); 954 mbp->mb_count = 0; 955 error = smb_put_dstring(mbp, vcp, tname, SMB_CS_NONE); 956 if (error) 957 goto exit; 958 mbp->mb_count--; /* don't count the null */ 959 *ucslenp = htolel(mbp->mb_count); 960 t2p->t2_maxpcount = 2; 961 t2p->t2_maxdcount = 0; 962 error = smb_t2_request(t2p); 963 exit: 964 if (fid) { 965 cerror = smbfs_smb_tmpclose(tdnp, fid, scrp); 966 if (cerror) 967 SMBERROR("error %d closing fid %d\n", cerror, fid); 968 } 969 smb_t2_done(t2p); 970 return (error); 971 } 972 973 int 974 smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp) 975 { 976 struct smb_share *ssp = np->n_mount->smi_share; 977 struct smb_rq rq, *rqp = &rq; 978 struct mbchain *mbp; 979 int error; 980 981 /* Shared lock for n_fid use below. */ 982 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 983 984 if (!(np->n_flag & NFLUSHWIRE)) 985 return (0); 986 if (np->r_count == 0) 987 return (0); /* not open */ 988 if (np->r_vnode->v_type != VREG) 989 return (0); /* not a file */ 990 991 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp); 992 if (error) 993 return (error); 994 smb_rq_getrequest(rqp, &mbp); 995 smb_rq_wstart(rqp); 996 mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); 997 smb_rq_wend(rqp); 998 smb_rq_bstart(rqp); 999 smb_rq_bend(rqp); 1000 error = smb_rq_simple(rqp); 1001 smb_rq_done(rqp); 1002 if (!error) { 1003 mutex_enter(&np->r_statelock); 1004 np->n_flag &= ~NFLUSHWIRE; 1005 mutex_exit(&np->r_statelock); 1006 } 1007 return (error); 1008 } 1009 1010 int 1011 smbfs_smb_setfsize(struct smbnode *np, uint16_t fid, uint64_t newsize, 1012 struct smb_cred *scrp) 1013 { 1014 struct smb_share *ssp = np->n_mount->smi_share; 1015 struct smb_rq rq, *rqp = &rq; 1016 struct mbchain *mbp; 1017 int error; 1018 1019 /* 1020 * This call knows about 64-bit offsets. 1021 */ 1022 error = smbfs_smb_seteof(ssp, fid, newsize, scrp); 1023 if (!error) { 1024 mutex_enter(&np->r_statelock); 1025 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 1026 mutex_exit(&np->r_statelock); 1027 return (0); 1028 } 1029 1030 /* 1031 * If we have SMB_CAP_LARGE_FILES, the above 1032 * should have worked. XXX: Don't fallback? 1033 * XXX: Or fallback on specific errors? 1034 */ 1035 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) { 1036 SMBVDEBUG("Have CAP_LARGE but _seteof error=%d\n", error); 1037 } 1038 1039 /* 1040 * OK, so fallback to SMB_COM_WRITE, but note: 1041 * it only supports 32-bit file offsets. 1042 */ 1043 if (newsize > UINT32_MAX) 1044 return (EFBIG); 1045 1046 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scrp); 1047 if (error) 1048 return (error); 1049 smb_rq_getrequest(rqp, &mbp); 1050 smb_rq_wstart(rqp); 1051 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 1052 mb_put_uint16le(mbp, 0); 1053 mb_put_uint32le(mbp, newsize); 1054 mb_put_uint16le(mbp, 0); 1055 smb_rq_wend(rqp); 1056 smb_rq_bstart(rqp); 1057 mb_put_uint8(mbp, SMB_DT_DATA); 1058 mb_put_uint16le(mbp, 0); 1059 smb_rq_bend(rqp); 1060 error = smb_rq_simple(rqp); 1061 smb_rq_done(rqp); 1062 mutex_enter(&np->r_statelock); 1063 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 1064 mutex_exit(&np->r_statelock); 1065 return (error); 1066 } 1067 1068 int 1069 smbfs_smb_query_info(struct smbnode *np, const char *name, int nmlen, 1070 struct smbfattr *fap, struct smb_cred *scrp) 1071 { 1072 struct smb_rq rq, *rqp = &rq; 1073 struct smb_share *ssp = np->n_mount->smi_share; 1074 struct mbchain *mbp; 1075 struct mdchain *mdp; 1076 uint8_t wc; 1077 int error; 1078 uint16_t wattr; 1079 uint32_t longint; 1080 1081 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scrp); 1082 if (error) 1083 return (error); 1084 smb_rq_getrequest(rqp, &mbp); 1085 smb_rq_wstart(rqp); 1086 smb_rq_wend(rqp); 1087 smb_rq_bstart(rqp); 1088 mb_put_uint8(mbp, SMB_DT_ASCII); 1089 do { 1090 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, 1091 name, &nmlen, '\\'); 1092 if (error) 1093 break; 1094 smb_rq_bend(rqp); 1095 error = smb_rq_simple(rqp); 1096 if (error) 1097 break; 1098 smb_rq_getreply(rqp, &mdp); 1099 if (md_get_uint8(mdp, &wc) != 0 || wc != 10) { 1100 error = EBADRPC; 1101 break; 1102 } 1103 md_get_uint16le(mdp, &wattr); 1104 fap->fa_attr = wattr; 1105 /* 1106 * Be careful using the time returned here, as 1107 * with FAT on NT4SP6, at least, the time returned is low 1108 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 1109 * over about every seven minutes! 1110 */ 1111 md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */ 1112 if (longint) /* avoid bogus zero returns */ 1113 smb_time_server2local(longint, 1114 SSTOVC(ssp)->vc_sopt.sv_tz, &fap->fa_mtime); 1115 md_get_uint32le(mdp, &longint); 1116 fap->fa_size = longint; 1117 /*LINTED*/ 1118 } while (0); 1119 smb_rq_done(rqp); 1120 return (error); 1121 } 1122 1123 int 1124 smbfs_smb_setpattr(struct smbnode *np, uint32_t attr, 1125 struct timespec *mtime, struct timespec *atime, 1126 struct smb_cred *scrp) 1127 { 1128 struct smb_share *ssp = np->n_mount->smi_share; 1129 struct smb_vc *vcp = SSTOVC(ssp); 1130 int error; 1131 1132 /* 1133 * This is the logic that was in smbfs_vnops.c 1134 */ 1135 if ((vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) && 1136 (vcp->vc_flags & SMBV_NT4) == 0) { 1137 /* 1138 * NT4 doesn't understand "NT" style SMBs; 1139 * for NT4 we use the old SET_PATH_INFO 1140 * XXX Actually, I think the issue is that 1141 * NT requires an open handle for this. 1142 */ 1143 error = smbfs_smb_setpattrNT(np, 1144 attr, mtime, atime, scrp); 1145 if (error != EBADRPC) 1146 return (error); 1147 1148 /* NT4 response, remember */ 1149 SMB_VC_LOCK(vcp); 1150 vcp->vc_flags |= SMBV_NT4; 1151 SMB_VC_UNLOCK(vcp); 1152 } 1153 1154 if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) { 1155 error = smbfs_smb_setpattr2(np, 1156 attr, mtime, atime, scrp); 1157 } else { 1158 error = smbfs_smb_setpattr1(np, NULL, 0, 1159 attr, mtime, scrp); 1160 } 1161 1162 return (error); 1163 } 1164 1165 /* 1166 * Set DOS file attributes. mtime should be NULL for dialects above lm10 1167 */ 1168 int 1169 smbfs_smb_setpattr1(struct smbnode *np, const char *name, int len, 1170 uint32_t attr, struct timespec *mtime, 1171 struct smb_cred *scrp) 1172 { 1173 struct smb_rq rq, *rqp = &rq; 1174 struct smb_share *ssp = np->n_mount->smi_share; 1175 struct mbchain *mbp; 1176 long time; 1177 int error, svtz; 1178 1179 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scrp); 1180 if (error) 1181 return (error); 1182 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 1183 smb_rq_getrequest(rqp, &mbp); 1184 smb_rq_wstart(rqp); 1185 mb_put_uint16le(mbp, (uint16_t)attr); 1186 if (mtime) { 1187 smb_time_local2server(mtime, svtz, &time); 1188 } else 1189 time = 0; 1190 mb_put_uint32le(mbp, time); /* mtime */ 1191 mb_put_mem(mbp, NULL, 5 * 2, MB_MZERO); 1192 smb_rq_wend(rqp); 1193 smb_rq_bstart(rqp); 1194 mb_put_uint8(mbp, SMB_DT_ASCII); 1195 do { 1196 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\'); 1197 if (error) 1198 break; 1199 mb_put_uint8(mbp, SMB_DT_ASCII); 1200 if (SMB_UNICODE_STRINGS(SSTOVC(ssp))) { 1201 mb_put_padbyte(mbp); 1202 mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */ 1203 } 1204 mb_put_uint8(mbp, 0); 1205 smb_rq_bend(rqp); 1206 error = smb_rq_simple(rqp); 1207 if (error) 1208 break; 1209 /*LINTED*/ 1210 } while (0); 1211 smb_rq_done(rqp); 1212 return (error); 1213 } 1214 1215 int 1216 smbfs_smb_hideit(struct smbnode *np, const char *name, int len, 1217 struct smb_cred *scrp) 1218 { 1219 struct smbfattr fa; 1220 int error; 1221 uint32_t attr; 1222 1223 error = smbfs_smb_query_info(np, name, len, &fa, scrp); 1224 attr = fa.fa_attr; 1225 if (!error && !(attr & SMB_FA_HIDDEN)) { 1226 attr |= SMB_FA_HIDDEN; 1227 error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp); 1228 } 1229 return (error); 1230 } 1231 1232 1233 int 1234 smbfs_smb_unhideit(struct smbnode *np, const char *name, int len, 1235 struct smb_cred *scrp) 1236 { 1237 struct smbfattr fa; 1238 uint32_t attr; 1239 int error; 1240 1241 error = smbfs_smb_query_info(np, name, len, &fa, scrp); 1242 attr = fa.fa_attr; 1243 if (!error && (attr & SMB_FA_HIDDEN)) { 1244 attr &= ~SMB_FA_HIDDEN; 1245 error = smbfs_smb_setpattr1(np, name, len, attr, NULL, scrp); 1246 } 1247 return (error); 1248 } 1249 1250 /* 1251 * Note, win95 doesn't support this call. 1252 */ 1253 int 1254 smbfs_smb_setpattr2(struct smbnode *np, uint32_t attr, 1255 struct timespec *mtime, struct timespec *atime, 1256 struct smb_cred *scrp) 1257 { 1258 struct smb_t2rq *t2p; 1259 struct smb_share *ssp = np->n_mount->smi_share; 1260 struct smb_vc *vcp = SSTOVC(ssp); 1261 struct mbchain *mbp; 1262 uint16_t date, time; 1263 int error, tzoff; 1264 1265 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 1266 scrp, &t2p); 1267 if (error) 1268 return (error); 1269 mbp = &t2p->t2_tparam; 1270 mb_init(mbp); 1271 mb_put_uint16le(mbp, SMB_SFILEINFO_STANDARD); 1272 mb_put_uint32le(mbp, 0); /* MBZ */ 1273 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 1274 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 1275 if (error) { 1276 smb_t2_done(t2p); 1277 return (error); 1278 } 1279 tzoff = vcp->vc_sopt.sv_tz; 1280 mbp = &t2p->t2_tdata; 1281 mb_init(mbp); 1282 mb_put_uint32le(mbp, 0); /* creation time */ 1283 if (atime) 1284 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 1285 else 1286 time = date = 0; 1287 mb_put_uint16le(mbp, date); 1288 mb_put_uint16le(mbp, time); 1289 if (mtime) 1290 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 1291 else 1292 time = date = 0; 1293 mb_put_uint16le(mbp, date); 1294 mb_put_uint16le(mbp, time); 1295 mb_put_uint32le(mbp, 0); /* file size */ 1296 mb_put_uint32le(mbp, 0); /* allocation unit size */ 1297 mb_put_uint16le(mbp, attr); /* DOS attr */ 1298 mb_put_uint32le(mbp, 0); /* EA size */ 1299 t2p->t2_maxpcount = 5 * 2; 1300 t2p->t2_maxdcount = vcp->vc_txmax; 1301 error = smb_t2_request(t2p); 1302 smb_t2_done(t2p); 1303 return (error); 1304 } 1305 1306 /* 1307 * *BASIC_INFO works with Samba, but Win2K servers say it is an 1308 * invalid information level on a SET_PATH_INFO. Note Win2K does 1309 * support *BASIC_INFO on a SET_FILE_INFO, and they support the 1310 * equivalent *BASIC_INFORMATION on SET_PATH_INFO. Go figure. 1311 */ 1312 int 1313 smbfs_smb_setpattrNT(struct smbnode *np, uint32_t attr, 1314 struct timespec *mtime, struct timespec *atime, 1315 struct smb_cred *scrp) 1316 { 1317 struct smb_t2rq *t2p; 1318 struct smb_share *ssp = np->n_mount->smi_share; 1319 struct smb_vc *vcp = SSTOVC(ssp); 1320 struct mbchain *mbp; 1321 uint64_t tm; 1322 int error, tzoff; 1323 /* 64 bit value for Jan 1 1980 */ 1324 PRIVSYM uint64_t DIFF1980TO1601 = 11960035200ULL*10000000ULL; 1325 1326 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, 1327 scrp, &t2p); 1328 if (error) 1329 return (error); 1330 mbp = &t2p->t2_tparam; 1331 mb_init(mbp); 1332 if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) 1333 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION); 1334 else 1335 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO); 1336 mb_put_uint32le(mbp, 0); /* MBZ */ 1337 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs incorrect */ 1338 error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); 1339 if (error) { 1340 smb_t2_done(t2p); 1341 return (error); 1342 } 1343 tzoff = vcp->vc_sopt.sv_tz; 1344 1345 /* do we know it won't support dates < 1980? */ 1346 if (!(ssp->ss_flags & SMBS_1980)) { 1347 mbp = &t2p->t2_tdata; 1348 mb_init(mbp); 1349 mb_put_uint64le(mbp, 0); /* creation time */ 1350 if (atime) { 1351 smb_time_local2NT(atime, tzoff, &tm); 1352 } else 1353 tm = 0; 1354 mb_put_uint64le(mbp, tm); /* access time */ 1355 if (mtime) { 1356 smb_time_local2NT(mtime, tzoff, &tm); 1357 } else 1358 tm = 0; 1359 mb_put_uint64le(mbp, tm); /* last write time */ 1360 mb_put_uint64le(mbp, tm); /* change time */ 1361 mb_put_uint32le(mbp, attr); /* attr */ 1362 mb_put_uint32le(mbp, 0); /* undocumented padding */ 1363 t2p->t2_maxpcount = 24; 1364 t2p->t2_maxdcount = 56; 1365 error = smb_t2_request(t2p); 1366 } 1367 /* 1368 * "invalid argument" error probably means it's a 1369 * FAT drive that doesn't accept dates earlier 1370 * than 1980, so adjust dates and retry. If the 1371 * 1980 flag is on we fell thru the if {} above 1372 */ 1373 if ((ssp->ss_flags & SMBS_1980) || (error == EINVAL)) { 1374 mbp = &t2p->t2_tdata; 1375 mb_init(mbp); 1376 mb_put_uint64le(mbp, 0); /* creation time */ 1377 if (atime) { 1378 smb_time_local2NT(atime, tzoff, &tm); 1379 if (tm < DIFF1980TO1601) 1380 tm = DIFF1980TO1601; 1381 } else 1382 tm = 0; 1383 mb_put_uint64le(mbp, tm); /* access time */ 1384 if (mtime) { 1385 smb_time_local2NT(mtime, tzoff, &tm); 1386 if (tm < DIFF1980TO1601) 1387 tm = DIFF1980TO1601; 1388 } else 1389 tm = 0; 1390 mb_put_uint64le(mbp, tm); /* last write time */ 1391 mb_put_uint64le(mbp, tm); /* change time */ 1392 mb_put_uint32le(mbp, attr); /* attr */ 1393 mb_put_uint32le(mbp, 0); /* undocumented padding */ 1394 t2p->t2_maxpcount = 24; 1395 t2p->t2_maxdcount = 56; 1396 error = smb_t2_request(t2p); 1397 1398 /* if this worked set flag to do the right thing next time */ 1399 if (!(error)) { 1400 SMB_SS_LOCK(ssp); 1401 ssp->ss_flags |= SMBS_1980; 1402 SMB_SS_UNLOCK(ssp); 1403 } 1404 } 1405 smb_t2_done(t2p); 1406 return (error); 1407 } 1408 1409 int 1410 smbfs_smb_setfattr(struct smbnode *np, uint16_t fid, 1411 uint32_t attr, struct timespec *mtime, 1412 struct timespec *atime, struct smb_cred *scrp) 1413 { 1414 struct smb_share *ssp = np->n_mount->smi_share; 1415 struct smb_vc *vcp = SSTOVC(ssp); 1416 int error; 1417 1418 /* 1419 * This is the logic that was in smbfs_vnops.c 1420 * Might not be quite right for older dialects. 1421 * (XXX: What about the DOS attributes?) 1422 */ 1423 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) 1424 error = smbfs_smb_setfattrNT(np, fid, 1425 np->n_dosattr, mtime, atime, scrp); 1426 else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) 1427 error = smbfs_smb_setftime1(np, fid, 1428 mtime, atime, scrp); 1429 else 1430 error = smbfs_smb_setpattr1(np, NULL, 0, 1431 attr, mtime, scrp); 1432 1433 return (error); 1434 } 1435 1436 /* 1437 * Set file atime and mtime. Isn't supported by core dialect. 1438 */ 1439 int 1440 smbfs_smb_setftime1( 1441 struct smbnode *np, 1442 uint16_t fid, 1443 struct timespec *mtime, 1444 struct timespec *atime, 1445 struct smb_cred *scrp) 1446 { 1447 struct smb_rq rq, *rqp = &rq; 1448 struct smb_share *ssp = np->n_mount->smi_share; 1449 struct mbchain *mbp; 1450 uint16_t date, time; 1451 int error, tzoff; 1452 1453 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scrp); 1454 if (error) 1455 return (error); 1456 tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; 1457 smb_rq_getrequest(rqp, &mbp); 1458 smb_rq_wstart(rqp); 1459 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 1460 mb_put_uint32le(mbp, 0); /* creation time */ 1461 1462 if (atime) 1463 smb_time_unix2dos(atime, tzoff, &date, &time, NULL); 1464 else 1465 time = date = 0; 1466 mb_put_uint16le(mbp, date); 1467 mb_put_uint16le(mbp, time); 1468 if (mtime) 1469 smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); 1470 else 1471 time = date = 0; 1472 mb_put_uint16le(mbp, date); 1473 mb_put_uint16le(mbp, time); 1474 smb_rq_wend(rqp); 1475 smb_rq_bstart(rqp); 1476 smb_rq_bend(rqp); 1477 error = smb_rq_simple(rqp); 1478 SMBVDEBUG("%d\n", error); 1479 smb_rq_done(rqp); 1480 return (error); 1481 } 1482 1483 /* 1484 * Set DOS file attributes. 1485 * Looks like this call can be used only if CAP_NT_SMBS bit is on. 1486 */ 1487 int 1488 smbfs_smb_setfattrNT(struct smbnode *np, uint16_t fid, 1489 uint32_t attr, struct timespec *mtime, 1490 struct timespec *atime, struct smb_cred *scrp) 1491 { 1492 struct smb_t2rq *t2p; 1493 struct smb_share *ssp = np->n_mount->smi_share; 1494 struct smb_vc *vcp = SSTOVC(ssp); 1495 struct mbchain *mbp; 1496 uint64_t tm; 1497 int error, svtz; 1498 1499 error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, 1500 scrp, &t2p); 1501 if (error) 1502 return (error); 1503 svtz = SSTOVC(ssp)->vc_sopt.sv_tz; 1504 mbp = &t2p->t2_tparam; 1505 mb_init(mbp); 1506 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 1507 if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU) 1508 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFORMATION); 1509 else 1510 mb_put_uint16le(mbp, SMB_SFILEINFO_BASIC_INFO); 1511 mb_put_uint32le(mbp, 0); /* XXX should be 16 not 32(?) */ 1512 mbp = &t2p->t2_tdata; 1513 mb_init(mbp); 1514 mb_put_uint64le(mbp, 0); /* creation time */ 1515 if (atime) { 1516 smb_time_local2NT(atime, svtz, &tm); 1517 } else 1518 tm = 0; 1519 mb_put_uint64le(mbp, tm); /* access time */ 1520 if (mtime) { 1521 smb_time_local2NT(mtime, svtz, &tm); 1522 } else 1523 tm = 0; 1524 mb_put_uint64le(mbp, tm); /* last write time */ 1525 mb_put_uint64le(mbp, tm); /* change time */ 1526 mb_put_uint32le(mbp, attr); 1527 mb_put_uint32le(mbp, 0); /* padding */ 1528 t2p->t2_maxpcount = 2; 1529 t2p->t2_maxdcount = 0; 1530 error = smb_t2_request(t2p); 1531 smb_t2_done(t2p); 1532 return (error); 1533 } 1534 1535 /* 1536 * Modern create/open of file or directory. 1537 * 1538 * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or... 1539 * then this is an open attempt, and: 1540 * If xattr then name is the stream to be opened at np, 1541 * Else np should be opened. 1542 * ...we won't touch *fidp, 1543 * ...we will set or clear *attrcacheupdated. 1544 * Else this is a creation attempt, and: 1545 * If xattr then name is the stream to create at np, 1546 * Else name is the thing to create under directory np. 1547 * ...we will return *fidp, 1548 * ...we won't touch *attrcacheupdated. 1549 * 1550 * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc. 1551 * now too, which may or may not create a new object. 1552 */ 1553 int 1554 smbfs_smb_ntcreatex(struct smbnode *np, uint32_t rights, 1555 struct smb_cred *scrp, enum vtype vt, 1556 int *attrcacheupdated, uint16_t *fidp, 1557 const char *name, int nmlen, uint32_t disp, int xattr, 1558 len_t *sizep, uint32_t *rightsp) 1559 { 1560 struct smb_rq rq, *rqp = &rq; 1561 struct smb_share *ssp = np->n_mount->smi_share; 1562 struct smb_vc *vcp = SSTOVC(ssp); 1563 struct mbchain *mbp; 1564 struct mdchain *mdp; 1565 struct smbfattr fap; 1566 uint8_t wc; 1567 uint32_t longint, createact, createopt, efa; 1568 uint64_t llongint; 1569 int error; 1570 uint16_t fid, *namelenp; 1571 1572 /* 1573 * Set the File attributes and Create options. 1574 * WinXP uses EFA_NORMAL in all of these cases. 1575 */ 1576 createopt = (vt == VDIR) ? 1577 NTCREATEX_OPTIONS_DIRECTORY : 1578 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE; 1579 efa = SMB_EFA_NORMAL; 1580 if (disp != NTCREATEX_DISP_OPEN && !xattr) { 1581 if (name && *name == '.') 1582 efa = SMB_EFA_HIDDEN; 1583 } 1584 1585 gethrestime(&fap.fa_reqtime); 1586 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); 1587 if (error) 1588 return (error); 1589 smb_rq_getrequest(rqp, &mbp); 1590 smb_rq_wstart(rqp); 1591 mb_put_uint8(mbp, 0xff); /* secondary command */ 1592 mb_put_uint8(mbp, 0); /* MBZ */ 1593 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 1594 mb_put_uint8(mbp, 0); /* MBZ */ 1595 namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t)); 1596 /* 1597 * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY 1598 * for creating nor for opening a directory. Samba ignores the bit. 1599 */ 1600 #if 0 /* causes sharing violation when making dir on W2K! */ 1601 mb_put_uint32le(mbp, vt == VDIR ? NTCREATEX_FLAGS_OPEN_DIRECTORY : 0); 1602 #else 1603 mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */ 1604 #endif 1605 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ 1606 mb_put_uint32le(mbp, rights); 1607 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 1608 mb_put_uint32le(mbp, efa); 1609 mb_put_uint32le(mbp, NTCREATEX_SHARE_ACCESS_ALL); 1610 mb_put_uint32le(mbp, disp); 1611 mb_put_uint32le(mbp, createopt); 1612 mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */ 1613 mb_put_uint8(mbp, 0); /* security flags (?) */ 1614 smb_rq_wend(rqp); 1615 smb_rq_bstart(rqp); 1616 do { 1617 if (name == NULL) 1618 nmlen = 0; 1619 error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, 1620 xattr ? ':' : '\\'); 1621 if (error) 1622 break; 1623 *namelenp = htoles(nmlen); /* includes null */ 1624 smb_rq_bend(rqp); 1625 /* 1626 * Don't want to risk missing a successful 1627 * open response, or we could "leak" FIDs. 1628 */ 1629 rqp->sr_flags |= SMBR_NOINTR_RECV; 1630 error = smb_rq_simple_timed(rqp, smb_timo_open); 1631 if (error) 1632 break; 1633 smb_rq_getreply(rqp, &mdp); 1634 /* 1635 * spec says 26 for word count, but 34 words are defined 1636 * and observed from win2000 1637 */ 1638 if (md_get_uint8(mdp, &wc) != 0 || 1639 (wc != 26 && wc != 34 && wc != 42)) { 1640 error = EBADRPC; 1641 break; 1642 } 1643 md_get_uint8(mdp, NULL); /* secondary cmd */ 1644 md_get_uint8(mdp, NULL); /* mbz */ 1645 md_get_uint16le(mdp, NULL); /* andxoffset */ 1646 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 1647 md_get_uint16(mdp, &fid); /* yes, leaving it LE */ 1648 md_get_uint32le(mdp, &createact); /* create_action */ 1649 md_get_uint64le(mdp, &llongint); /* creation time */ 1650 md_get_uint64le(mdp, &llongint); /* access time */ 1651 if (llongint) /* avoid bogus 0 time (on FAT roots) */ 1652 smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz, 1653 &fap.fa_atime); 1654 md_get_uint64le(mdp, &llongint); /* write time */ 1655 if (llongint) /* avoid bogus 0 time (on FAT roots) */ 1656 smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz, 1657 &fap.fa_mtime); 1658 md_get_uint64le(mdp, &llongint); /* change time */ 1659 if (llongint) /* avoid bogus 0 time (on FAT roots) */ 1660 smb_time_NT2local(llongint, vcp->vc_sopt.sv_tz, 1661 &fap.fa_ctime); 1662 md_get_uint32le(mdp, &longint); /* attributes */ 1663 fap.fa_attr = longint; 1664 md_get_uint64le(mdp, NULL); /* allocation size */ 1665 md_get_uint64le(mdp, &llongint); /* EOF */ 1666 fap.fa_size = llongint; 1667 if (sizep) 1668 *sizep = fap.fa_size; 1669 md_get_uint16le(mdp, NULL); /* file type */ 1670 md_get_uint16le(mdp, NULL); /* device state */ 1671 md_get_uint8(mdp, NULL); /* directory (boolean) */ 1672 /*LINTED*/ 1673 } while (0); 1674 smb_rq_done(rqp); 1675 if (error) 1676 return (error); 1677 if (fidp) 1678 *fidp = fid; 1679 if (rightsp) 1680 *rightsp = rights; 1681 /* 1682 * Is it possible that we have cached attributes? 1683 * Assume "not cached" if we created the object. 1684 */ 1685 if (createact == NTCREATEX_ACTION_CREATED || xattr) 1686 goto uncached; 1687 if (attrcacheupdated) 1688 *attrcacheupdated = 0; 1689 /* 1690 * Update the cached attributes if they are still valid 1691 * in the cache and if nothing has changed. 1692 */ 1693 if (np->r_vnode == NULL) 1694 goto uncached; 1695 if (smbfs_attr_cachelookup(np->r_vnode, NULL) != 0) 1696 goto uncached; /* the cached attributes are not valid */ 1697 if (fap.fa_size != np->n_size) 1698 goto uncached; /* the size is different */ 1699 if (fap.fa_attr != np->n_dosattr) 1700 goto uncached; /* the attrs are different */ 1701 /* 1702 * fap.fa_mtime is in two second increments while np->n_mtime 1703 * may be in one second increments, so comparing the times is 1704 * somewhat sloppy. 1705 * 1706 * XXX: true fap.fa_mtime resolution must depend upon server's 1707 * local filesystem and is thus indeterminate... XXX ...TBD how that 1708 * affects this code... note wire resolution here is 100ns versus 1709 * 1sec down in smbfs_smb_oldopen(SMB_COM_OPEN) 1710 */ 1711 if (fap.fa_mtime.tv_sec != np->n_mtime.tv_sec && 1712 fap.fa_mtime.tv_sec != np->n_mtime.tv_sec - 1 && 1713 fap.fa_mtime.tv_sec != np->n_mtime.tv_sec + 1) 1714 goto uncached; /* the mod time is different */ 1715 1716 fap.fa_mtime.tv_sec = np->n_mtime.tv_sec; /* keep higher res time */ 1717 smbfs_attr_cacheenter(np->r_vnode, &fap); 1718 if (attrcacheupdated) 1719 *attrcacheupdated = 1; 1720 uncached: 1721 return (0); 1722 } 1723 1724 static uint32_t 1725 smb_mode2rights(int mode) 1726 { 1727 mode = mode & SMB_AM_OPENMODE; 1728 1729 switch (mode) { 1730 case SMB_AM_OPENREAD: 1731 return (GENERIC_RIGHT_READ_ACCESS); 1732 case SMB_AM_OPENWRITE: 1733 return (GENERIC_RIGHT_WRITE_ACCESS); 1734 case SMB_AM_OPENRW: 1735 return (GENERIC_RIGHT_ALL_ACCESS); 1736 case SMB_AM_OPENEXEC: 1737 return (GENERIC_RIGHT_EXECUTE_ACCESS); 1738 } 1739 return (0); 1740 } 1741 1742 static int 1743 smb_rights2mode(uint32_t rights) 1744 { 1745 int accmode = SMB_AM_OPENEXEC; /* our fallback */ 1746 1747 if (rights & (SA_RIGHT_FILE_APPEND_DATA | SA_RIGHT_FILE_DELETE_CHILD | 1748 SA_RIGHT_FILE_WRITE_EA | SA_RIGHT_FILE_WRITE_ATTRIBUTES | 1749 SA_RIGHT_FILE_WRITE_DATA | STD_RIGHT_WRITE_OWNER_ACCESS | 1750 STD_RIGHT_DELETE_ACCESS | STD_RIGHT_WRITE_DAC_ACCESS | 1751 GENERIC_RIGHT_ALL_ACCESS | GENERIC_RIGHT_WRITE_ACCESS)) 1752 accmode = SMB_AM_OPENWRITE; 1753 if (rights & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_READ_ATTRIBUTES | 1754 SA_RIGHT_FILE_READ_EA | STD_RIGHT_READ_CONTROL_ACCESS | 1755 GENERIC_RIGHT_ALL_ACCESS | GENERIC_RIGHT_READ_ACCESS)) 1756 accmode = (accmode == SMB_AM_OPENEXEC) ? SMB_AM_OPENREAD 1757 : SMB_AM_OPENRW; 1758 return (accmode); 1759 } 1760 1761 static int 1762 smbfs_smb_oldopen(struct smbnode *np, int accmode, struct smb_cred *scrp, 1763 int *attrcacheupdated, uint16_t *fidp, const char *name, 1764 int nmlen, int xattr, len_t *sizep, uint32_t *rightsp) 1765 { 1766 struct smb_rq rq, *rqp = &rq; 1767 struct smb_share *ssp = np->n_mount->smi_share; 1768 struct smb_vc *vcp = SSTOVC(ssp); 1769 struct mbchain *mbp; 1770 struct mdchain *mdp; 1771 struct smbfattr fap; 1772 uint8_t wc; 1773 uint16_t fid, wattr, grantedmode; 1774 uint32_t longint; 1775 int error; 1776 1777 /* 1778 * Use DENYNONE to give unixy semantics of permitting 1779 * everything not forbidden by permissions. Ie denial 1780 * is up to server with clients/openers needing to use 1781 * advisory locks for further control. 1782 */ 1783 accmode |= SMB_SM_DENYNONE; 1784 1785 gethrestime(&fap.fa_reqtime); 1786 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scrp); 1787 if (error) 1788 return (error); 1789 smb_rq_getrequest(rqp, &mbp); 1790 smb_rq_wstart(rqp); 1791 mb_put_uint16le(mbp, accmode); 1792 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_RDONLY | 1793 SMB_FA_DIR); 1794 smb_rq_wend(rqp); 1795 smb_rq_bstart(rqp); 1796 mb_put_uint8(mbp, SMB_DT_ASCII); 1797 do { 1798 error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, 1799 xattr ? ':' : '\\'); 1800 if (error) 1801 break; 1802 smb_rq_bend(rqp); 1803 /* 1804 * Don't want to risk missing a successful 1805 * open response, or we could "leak" FIDs. 1806 */ 1807 rqp->sr_flags |= SMBR_NOINTR_RECV; 1808 error = smb_rq_simple_timed(rqp, smb_timo_open); 1809 if (error) 1810 break; 1811 smb_rq_getreply(rqp, &mdp); 1812 /* 1813 * 8/2002 a DAVE server returned wc of 15 so we ignore that. 1814 * (the actual packet length and data was correct) 1815 */ 1816 if (md_get_uint8(mdp, &wc) != 0 || (wc != 7 && wc != 15)) { 1817 error = EBADRPC; 1818 break; 1819 } 1820 md_get_uint16(mdp, &fid); /* yes, we leave it LE */ 1821 md_get_uint16le(mdp, &wattr); 1822 fap.fa_attr = wattr; 1823 /* 1824 * Be careful using the time returned here, as 1825 * with FAT on NT4SP6, at least, the time returned is low 1826 * 32 bits of 100s of nanoseconds (since 1601) so it rolls 1827 * over about every seven minutes! 1828 */ 1829 md_get_uint32le(mdp, &longint); /* specs: secs since 1970 */ 1830 if (longint) /* avoid bogus zero returns */ 1831 smb_time_server2local(longint, vcp->vc_sopt.sv_tz, 1832 &fap.fa_mtime); 1833 md_get_uint32le(mdp, &longint); 1834 fap.fa_size = longint; 1835 if (sizep) 1836 *sizep = fap.fa_size; 1837 md_get_uint16le(mdp, &grantedmode); 1838 /*LINTED*/ 1839 } while (0); 1840 smb_rq_done(rqp); 1841 if (error) 1842 return (error); 1843 if (fidp) 1844 *fidp = fid; 1845 if (xattr) 1846 goto uncached; 1847 if (rightsp) 1848 *rightsp = smb_mode2rights(grantedmode); 1849 if (attrcacheupdated) 1850 *attrcacheupdated = 0; 1851 /* 1852 * Update the cached attributes if they are still valid 1853 * in the cache and if nothing has changed. 1854 * Note that this won't ever update if the file size is 1855 * greater than the 32-bits returned by SMB_COM_OPEN. 1856 * For 64-bit file sizes, SMB_COM_NT_CREATE_ANDX must 1857 * be used instead of SMB_COM_OPEN. 1858 */ 1859 if (np->r_vnode == NULL) 1860 goto uncached; 1861 if (smbfs_attr_cachelookup(np->r_vnode, NULL) != 0) 1862 goto uncached; /* the cached attributes are not valid */ 1863 if (fap.fa_size != np->n_size) 1864 goto uncached; /* the size is different */ 1865 if (fap.fa_attr != np->n_dosattr) 1866 goto uncached; /* the attrs are different */ 1867 /* 1868 * fap.fa_mtime is in two second increments while np->n_mtime 1869 * may be in one second increments, so comparing the times is 1870 * somewhat sloppy. 1871 */ 1872 if (fap.fa_mtime.tv_sec != np->n_mtime.tv_sec && 1873 fap.fa_mtime.tv_sec != np->n_mtime.tv_sec - 1 && 1874 fap.fa_mtime.tv_sec != np->n_mtime.tv_sec + 1) 1875 goto uncached; /* the mod time is different */ 1876 1877 fap.fa_mtime.tv_sec = np->n_mtime.tv_sec; /* keep higher res time */ 1878 smbfs_attr_cacheenter(np->r_vnode, &fap); 1879 if (attrcacheupdated) 1880 *attrcacheupdated = 1; 1881 uncached: 1882 return (0); 1883 } 1884 1885 int 1886 smbfs_smb_tmpopen(struct smbnode *np, uint32_t rights, struct smb_cred *scrp, 1887 uint16_t *fidp) 1888 { 1889 struct smb_vc *vcp = SSTOVC(np->n_mount->smi_share); 1890 enum vtype vt = VREG; 1891 int error; 1892 1893 /* Shared lock for n_fid use below. */ 1894 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 1895 1896 mutex_enter(&np->r_statelock); 1897 if (np->n_fidrefs && (rights & np->n_rights) == rights) { 1898 np->n_fidrefs++; 1899 *fidp = np->n_fid; 1900 mutex_exit(&np->r_statelock); 1901 return (0); 1902 } 1903 mutex_exit(&np->r_statelock); 1904 1905 if (!(vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)) { 1906 int mode = smb_rights2mode(rights); 1907 error = smbfs_smb_oldopen(np, mode, scrp, 1908 NULL, fidp, NULL, 0, 0, NULL, NULL); 1909 } else { 1910 if (SMBTOV(np)) 1911 vt = SMBTOV(np)->v_type; 1912 error = smbfs_smb_ntcreatex(np, rights, scrp, vt, 1913 NULL, fidp, NULL, 0, NTCREATEX_DISP_OPEN, 0, 1914 NULL, NULL); 1915 } 1916 1917 if (*fidp == np->n_fid) { 1918 /* 1919 * Oh no, the server gave us the same FID again? 1920 * This will cause us to close np->n_fid early! 1921 */ 1922 SMBVDEBUG("duplicate fid: 0x%x\n", *fidp); 1923 } 1924 1925 return (error); 1926 } 1927 1928 int 1929 smbfs_smb_tmpclose(struct smbnode *np, uint16_t fid, struct smb_cred *scrp) 1930 { 1931 struct smb_share *ssp = np->n_mount->smi_share; 1932 int error = 0; 1933 uint16_t oldfid = SMB_FID_UNUSED; 1934 1935 /* Shared lock for n_fid use below. */ 1936 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER)); 1937 1938 mutex_enter(&np->r_statelock); 1939 if (fid == np->n_fid) { 1940 ASSERT(np->n_fidrefs > 0); 1941 if (--np->n_fidrefs == 0) { 1942 /* 1943 * Don't expect to find the last reference 1944 * here in tmpclose. Hard to deal with as 1945 * we don't have r_lkserlock exclusive. 1946 * Will close oldfid below. 1947 */ 1948 oldfid = np->n_fid; 1949 np->n_fid = SMB_FID_UNUSED; 1950 } 1951 } else { 1952 /* Will close the passed fid. */ 1953 oldfid = fid; 1954 } 1955 mutex_exit(&np->r_statelock); 1956 1957 if (oldfid != SMB_FID_UNUSED) 1958 error = smbfs_smb_close(ssp, oldfid, NULL, scrp); 1959 1960 return (error); 1961 } 1962 1963 int 1964 smbfs_smb_open(struct smbnode *np, uint32_t rights, struct smb_cred *scrp, 1965 int *attrcacheupdated, uint16_t *fidp, const char *name, 1966 int nmlen, int xattr, len_t *sizep, uint32_t *rightsp) 1967 { 1968 int error; 1969 struct smb_share *ssp = np->n_mount->smi_share; 1970 struct smb_vc *vcp = SSTOVC(ssp); 1971 enum vtype vt = VREG; 1972 1973 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 1974 if (SMBTOV(np)) 1975 vt = SMBTOV(np)->v_type; 1976 error = smbfs_smb_ntcreatex(np, rights, scrp, vt, 1977 attrcacheupdated, fidp, name, nmlen, 1978 NTCREATEX_DISP_OPEN, xattr, sizep, rightsp); 1979 } else { 1980 error = smbfs_smb_oldopen(np, smb_rights2mode(rights), scrp, 1981 attrcacheupdated, fidp, name, nmlen, xattr, sizep, rightsp); 1982 } 1983 #if 0 /* let caller do this */ 1984 if (!error && !name) 1985 np->n_fidrefs++; 1986 #endif 1987 return (error); 1988 } 1989 1990 int 1991 smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, 1992 struct smb_cred *scrp) 1993 { 1994 struct smb_rq rq, *rqp = &rq; 1995 struct mbchain *mbp; 1996 long time; 1997 int error; 1998 1999 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); 2000 if (error) 2001 return (error); 2002 smb_rq_getrequest(rqp, &mbp); 2003 smb_rq_wstart(rqp); 2004 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 2005 if (mtime) { 2006 smb_time_local2server(mtime, SSTOVC(ssp)->vc_sopt.sv_tz, &time); 2007 } else 2008 time = 0; 2009 mb_put_uint32le(mbp, time); 2010 smb_rq_wend(rqp); 2011 smb_rq_bstart(rqp); 2012 smb_rq_bend(rqp); 2013 2014 /* 2015 * We don't really care about the result here, but we 2016 * do need to make sure we send this out, or we could 2017 * "leak" open file handles on interrupt or timeout. 2018 * The NOINTR_SEND flag makes this request immune to 2019 * interrupt or timeout until the send is done. 2020 */ 2021 rqp->sr_flags |= SMBR_NOINTR_SEND; 2022 error = smb_rq_simple(rqp); 2023 smb_rq_done(rqp); 2024 /* 2025 * ENOTCONN isn't interesting - if the connection is closed, 2026 * so are all our FIDs - and EIO is also not interesting, 2027 * as it means a forced unmount was done. (was ENXIO) 2028 * Also ETIME, which means we sent the request but gave up 2029 * waiting before the response came back. 2030 * 2031 * Don't clog up the system log with warnings about these 2032 * uninteresting failures on closes. 2033 */ 2034 switch (error) { 2035 case ENOTCONN: 2036 case ENXIO: 2037 case EIO: 2038 case ETIME: 2039 error = 0; 2040 } 2041 return (error); 2042 } 2043 2044 static int 2045 smbfs_smb_oldcreate(struct smbnode *dnp, const char *name, int nmlen, 2046 struct smb_cred *scrp, uint16_t *fidp, int xattr) 2047 { 2048 struct smb_rq rq, *rqp = &rq; 2049 struct smb_share *ssp = dnp->n_mount->smi_share; 2050 struct mbchain *mbp; 2051 struct mdchain *mdp; 2052 struct timespec ctime; 2053 uint8_t wc; 2054 long tm; 2055 int error; 2056 uint16_t attr = SMB_FA_ARCHIVE; 2057 2058 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scrp); 2059 if (error) 2060 return (error); 2061 smb_rq_getrequest(rqp, &mbp); 2062 smb_rq_wstart(rqp); 2063 if (name && *name == '.') 2064 attr |= SMB_FA_HIDDEN; 2065 mb_put_uint16le(mbp, attr); /* attributes */ 2066 gethrestime(&ctime); 2067 smb_time_local2server(&ctime, SSTOVC(ssp)->vc_sopt.sv_tz, &tm); 2068 mb_put_uint32le(mbp, tm); 2069 smb_rq_wend(rqp); 2070 smb_rq_bstart(rqp); 2071 mb_put_uint8(mbp, SMB_DT_ASCII); 2072 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen, 2073 xattr ? ':' : '\\'); 2074 if (!error) { 2075 smb_rq_bend(rqp); 2076 /* 2077 * Don't want to risk missing a successful 2078 * open response, or we could "leak" FIDs. 2079 */ 2080 rqp->sr_flags |= SMBR_NOINTR_RECV; 2081 error = smb_rq_simple_timed(rqp, smb_timo_open); 2082 if (!error) { 2083 smb_rq_getreply(rqp, &mdp); 2084 md_get_uint8(mdp, &wc); 2085 if (wc == 1) 2086 md_get_uint16(mdp, fidp); 2087 else 2088 error = EBADRPC; 2089 } 2090 } 2091 smb_rq_done(rqp); 2092 return (error); 2093 } 2094 2095 int 2096 smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen, 2097 struct smb_cred *scrp, uint16_t *fidp, uint32_t disp, int xattr) 2098 { 2099 struct smb_vc *vcp = SSTOVC(dnp->n_mount->smi_share); 2100 2101 /* 2102 * At present the only access we might need is to WRITE data, 2103 * and that only if we are creating a "symlink". When/if the 2104 * access needed gets more complex it should made a parameter 2105 * and be set upstream. 2106 */ 2107 if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 2108 return (smbfs_smb_ntcreatex(dnp, SA_RIGHT_FILE_WRITE_DATA, 2109 scrp, VREG, NULL, fidp, name, nmlen, disp, xattr, 2110 NULL, NULL)); 2111 } else 2112 return (smbfs_smb_oldcreate(dnp, name, nmlen, scrp, fidp, 2113 xattr)); 2114 } 2115 2116 int 2117 smbfs_smb_delete(struct smbnode *np, struct smb_cred *scrp, const char *name, 2118 int nmlen, int xattr) 2119 { 2120 struct smb_rq rq, *rqp = &rq; 2121 struct smb_share *ssp = np->n_mount->smi_share; 2122 struct mbchain *mbp; 2123 int error; 2124 2125 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scrp); 2126 if (error) 2127 return (error); 2128 smb_rq_getrequest(rqp, &mbp); 2129 smb_rq_wstart(rqp); 2130 mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); 2131 smb_rq_wend(rqp); 2132 smb_rq_bstart(rqp); 2133 mb_put_uint8(mbp, SMB_DT_ASCII); 2134 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen, 2135 xattr ? ':' : '\\'); 2136 if (!error) { 2137 smb_rq_bend(rqp); 2138 error = smb_rq_simple(rqp); 2139 } 2140 smb_rq_done(rqp); 2141 return (error); 2142 } 2143 2144 int 2145 smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, 2146 const char *tname, int tnmlen, struct smb_cred *scrp) 2147 { 2148 struct smb_rq rq, *rqp = &rq; 2149 struct smb_share *ssp = src->n_mount->smi_share; 2150 struct mbchain *mbp; 2151 int error; 2152 uint16_t fa; 2153 2154 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp); 2155 if (error) 2156 return (error); 2157 smb_rq_getrequest(rqp, &mbp); 2158 smb_rq_wstart(rqp); 2159 /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */ 2160 fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0; 2161 fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN; 2162 mb_put_uint16le(mbp, fa); 2163 smb_rq_wend(rqp); 2164 smb_rq_bstart(rqp); 2165 mb_put_uint8(mbp, SMB_DT_ASCII); 2166 do { 2167 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\'); 2168 if (error) 2169 break; 2170 mb_put_uint8(mbp, SMB_DT_ASCII); 2171 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, 2172 '\\'); 2173 if (error) 2174 break; 2175 smb_rq_bend(rqp); 2176 error = smb_rq_simple(rqp); 2177 /*LINTED*/ 2178 } while (0); 2179 smb_rq_done(rqp); 2180 return (error); 2181 } 2182 2183 int 2184 smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, 2185 const char *tname, int tnmlen, uint16_t flags, struct smb_cred *scrp) 2186 { 2187 struct smb_rq rq, *rqp = &rq; 2188 struct smb_share *ssp = src->n_mount->smi_share; 2189 struct mbchain *mbp; 2190 int error; 2191 2192 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scrp); 2193 if (error) 2194 return (error); 2195 smb_rq_getrequest(rqp, &mbp); 2196 smb_rq_wstart(rqp); 2197 mb_put_uint16le(mbp, SMB_TID_UNKNOWN); 2198 mb_put_uint16le(mbp, 0x20); /* delete target file */ 2199 mb_put_uint16le(mbp, flags); 2200 smb_rq_wend(rqp); 2201 smb_rq_bstart(rqp); 2202 mb_put_uint8(mbp, SMB_DT_ASCII); 2203 do { 2204 error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\'); 2205 if (error) 2206 break; 2207 mb_put_uint8(mbp, SMB_DT_ASCII); 2208 error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, 2209 '\\'); 2210 if (error) 2211 break; 2212 smb_rq_bend(rqp); 2213 error = smb_rq_simple(rqp); 2214 /*LINTED*/ 2215 } while (0); 2216 smb_rq_done(rqp); 2217 return (error); 2218 } 2219 2220 static int 2221 smbfs_smb_oldmkdir(struct smbnode *dnp, const char *name, int len, 2222 struct smb_cred *scrp) 2223 { 2224 struct smb_rq rq, *rqp = &rq; 2225 struct smb_share *ssp = dnp->n_mount->smi_share; 2226 struct mbchain *mbp; 2227 int error; 2228 2229 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scrp); 2230 if (error) 2231 return (error); 2232 smb_rq_getrequest(rqp, &mbp); 2233 smb_rq_wstart(rqp); 2234 smb_rq_wend(rqp); 2235 smb_rq_bstart(rqp); 2236 mb_put_uint8(mbp, SMB_DT_ASCII); 2237 error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\'); 2238 if (!error) { 2239 smb_rq_bend(rqp); 2240 error = smb_rq_simple(rqp); 2241 } 2242 smb_rq_done(rqp); 2243 return (error); 2244 } 2245 2246 int 2247 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len, 2248 struct smb_cred *scrp) 2249 { 2250 struct smb_share *ssp = dnp->n_mount->smi_share; 2251 uint16_t fid; 2252 int error; 2253 2254 /* 2255 * We ask for SA_RIGHT_FILE_READ_DATA not because we need it, but 2256 * just to be asking for something. The rights==0 case could 2257 * easily be broken on some old or unusual servers. 2258 */ 2259 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) { 2260 error = smbfs_smb_ntcreatex(dnp, SA_RIGHT_FILE_READ_DATA, 2261 scrp, VDIR, NULL, &fid, name, len, 2262 NTCREATEX_DISP_CREATE, 0, NULL, NULL); 2263 if (error) 2264 return (error); 2265 error = smbfs_smb_close(ssp, fid, NULL, scrp); 2266 if (error) 2267 SMBERROR("error %d closing fid %d\n", error, fid); 2268 return (0); 2269 } else 2270 return (smbfs_smb_oldmkdir(dnp, name, len, scrp)); 2271 } 2272 2273 int 2274 smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scrp) 2275 { 2276 struct smb_rq rq, *rqp = &rq; 2277 struct smb_share *ssp = np->n_mount->smi_share; 2278 struct mbchain *mbp; 2279 int error; 2280 2281 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scrp); 2282 if (error) 2283 return (error); 2284 smb_rq_getrequest(rqp, &mbp); 2285 smb_rq_wstart(rqp); 2286 smb_rq_wend(rqp); 2287 smb_rq_bstart(rqp); 2288 mb_put_uint8(mbp, SMB_DT_ASCII); 2289 error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\'); 2290 if (!error) { 2291 smb_rq_bend(rqp); 2292 error = smb_rq_simple(rqp); 2293 } 2294 smb_rq_done(rqp); 2295 return (error); 2296 } 2297 2298 static int 2299 smbfs_smb_search(struct smbfs_fctx *ctx) 2300 { 2301 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 2302 struct smb_rq *rqp; 2303 struct mbchain *mbp; 2304 struct mdchain *mdp; 2305 uint8_t wc, bt; 2306 uint16_t ec, dlen, bc; 2307 int len, maxent, error, iseof = 0; 2308 2309 maxent = min(ctx->f_left, 2310 (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN); 2311 if (ctx->f_rq) { 2312 smb_rq_done(ctx->f_rq); 2313 ctx->f_rq = NULL; 2314 } 2315 error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, 2316 ctx->f_scred, &rqp); 2317 if (error) 2318 return (error); 2319 ctx->f_rq = rqp; 2320 smb_rq_getrequest(rqp, &mbp); 2321 smb_rq_wstart(rqp); 2322 mb_put_uint16le(mbp, maxent); /* max entries to return */ 2323 mb_put_uint16le(mbp, ctx->f_attrmask); 2324 smb_rq_wend(rqp); 2325 smb_rq_bstart(rqp); 2326 mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ 2327 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 2328 len = ctx->f_wclen; 2329 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, 2330 &len, '\\'); 2331 if (error) 2332 return (error); 2333 mb_put_uint8(mbp, SMB_DT_VARIABLE); 2334 mb_put_uint16le(mbp, 0); /* context length */ 2335 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 2336 } else { 2337 if (SMB_UNICODE_STRINGS(vcp)) { 2338 mb_put_padbyte(mbp); 2339 mb_put_uint8(mbp, 0); 2340 } 2341 mb_put_uint8(mbp, 0); 2342 mb_put_uint8(mbp, SMB_DT_VARIABLE); 2343 mb_put_uint16le(mbp, SMB_SKEYLEN); 2344 mb_put_mem(mbp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 2345 } 2346 smb_rq_bend(rqp); 2347 error = smb_rq_simple(rqp); 2348 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnofiles) { 2349 error = 0; 2350 iseof = 1; 2351 ctx->f_flags |= SMBFS_RDD_EOF; 2352 } else if (error) 2353 return (error); 2354 smb_rq_getreply(rqp, &mdp); 2355 md_get_uint8(mdp, &wc); 2356 if (wc != 1) 2357 return (iseof ? ENOENT : EBADRPC); 2358 md_get_uint16le(mdp, &ec); 2359 if (ec == 0) 2360 return (ENOENT); 2361 ctx->f_ecnt = ec; 2362 md_get_uint16le(mdp, &bc); 2363 if (bc < 3) 2364 return (EBADRPC); 2365 bc -= 3; 2366 md_get_uint8(mdp, &bt); 2367 if (bt != SMB_DT_VARIABLE) 2368 return (EBADRPC); 2369 md_get_uint16le(mdp, &dlen); 2370 if (dlen != bc || dlen % SMB_DENTRYLEN != 0) 2371 return (EBADRPC); 2372 return (0); 2373 } 2374 2375 2376 /*ARGSUSED*/ 2377 static int 2378 smbfs_smb_findopenLM1(struct smbfs_fctx *ctx, struct smbnode *dnp, 2379 const char *wildcard, int wclen, uint16_t attr, struct smb_cred *scrp) 2380 { 2381 /* #pragma unused(dnp, scrp) */ 2382 ctx->f_attrmask = attr; 2383 if (wildcard) { 2384 if (wclen == 1 && wildcard[0] == '*') { 2385 ctx->f_wildcard = "*.*"; 2386 ctx->f_wclen = 3; 2387 } else { 2388 ctx->f_wildcard = wildcard; 2389 ctx->f_wclen = wclen; 2390 } 2391 } else { 2392 ctx->f_wildcard = NULL; 2393 ctx->f_wclen = 0; 2394 } 2395 ctx->f_name = (char *)ctx->f_fname; 2396 ctx->f_namesz = 0; 2397 return (0); 2398 } 2399 2400 static int 2401 smbfs_smb_findnextLM1(struct smbfs_fctx *ctx, uint16_t limit) 2402 { 2403 struct mdchain *mdp; 2404 struct smb_rq *rqp; 2405 char *cp; 2406 uint8_t battr; 2407 uint16_t date, time; 2408 uint32_t size; 2409 int error; 2410 struct timespec ts; 2411 2412 if (ctx->f_ecnt == 0) { 2413 if (ctx->f_flags & SMBFS_RDD_EOF) 2414 return (ENOENT); 2415 ctx->f_left = ctx->f_limit = limit; 2416 gethrestime(&ts); 2417 error = smbfs_smb_search(ctx); 2418 if (error) 2419 return (error); 2420 ctx->f_attr.fa_reqtime = ts; 2421 } 2422 rqp = ctx->f_rq; 2423 smb_rq_getreply(rqp, &mdp); 2424 md_get_mem(mdp, (char *)ctx->f_skey, SMB_SKEYLEN, MB_MSYSTEM); 2425 md_get_uint8(mdp, &battr); 2426 md_get_uint16le(mdp, &time); 2427 md_get_uint16le(mdp, &date); 2428 md_get_uint32le(mdp, &size); 2429 cp = ctx->f_name; 2430 md_get_mem(mdp, cp, sizeof (ctx->f_fname), MB_MSYSTEM); 2431 cp[sizeof (ctx->f_fname) - 1] = 0; 2432 cp += strlen(cp) - 1; 2433 while (*cp == ' ' && cp >= ctx->f_name) 2434 *cp-- = 0; 2435 ctx->f_attr.fa_attr = battr; 2436 smb_dos2unixtime(date, time, 0, rqp->sr_vc->vc_sopt.sv_tz, 2437 &ctx->f_attr.fa_mtime); 2438 ctx->f_attr.fa_size = size; 2439 ctx->f_nmlen = strlen(ctx->f_name); 2440 ctx->f_ecnt--; 2441 ctx->f_left--; 2442 return (0); 2443 } 2444 2445 static int 2446 smbfs_smb_findcloseLM1(struct smbfs_fctx *ctx) 2447 { 2448 if (ctx->f_rq) 2449 smb_rq_done(ctx->f_rq); 2450 return (0); 2451 } 2452 2453 /* 2454 * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect 2455 */ 2456 static int 2457 smbfs_smb_trans2find2(struct smbfs_fctx *ctx) 2458 { 2459 struct smb_t2rq *t2p; 2460 struct smb_vc *vcp = SSTOVC(ctx->f_ssp); 2461 struct mbchain *mbp; 2462 struct mdchain *mdp; 2463 uint16_t tw, flags; 2464 int len, error; 2465 2466 if (ctx->f_t2) { 2467 smb_t2_done(ctx->f_t2); 2468 ctx->f_t2 = NULL; 2469 } 2470 ctx->f_flags &= ~SMBFS_RDD_GOTRNAME; 2471 flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS; 2472 if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) { 2473 flags |= FIND2_CLOSE_AFTER_REQUEST; 2474 ctx->f_flags |= SMBFS_RDD_NOCLOSE; 2475 } 2476 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 2477 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2, 2478 ctx->f_scred, &t2p); 2479 if (error) 2480 return (error); 2481 ctx->f_t2 = t2p; 2482 mbp = &t2p->t2_tparam; 2483 mb_init(mbp); 2484 mb_put_uint16le(mbp, ctx->f_attrmask); 2485 mb_put_uint16le(mbp, ctx->f_limit); 2486 mb_put_uint16le(mbp, flags); 2487 mb_put_uint16le(mbp, ctx->f_infolevel); 2488 mb_put_uint32le(mbp, 0); 2489 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs? hah! */ 2490 len = ctx->f_wclen; 2491 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, 2492 &len, '\\'); 2493 if (error) 2494 return (error); 2495 } else { 2496 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2, 2497 ctx->f_scred, &t2p); 2498 if (error) 2499 return (error); 2500 ctx->f_t2 = t2p; 2501 mbp = &t2p->t2_tparam; 2502 mb_init(mbp); 2503 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 2504 mb_put_uint16le(mbp, ctx->f_limit); 2505 mb_put_uint16le(mbp, ctx->f_infolevel); 2506 if (ctx->f_ssp->ss_flags & SMBS_RESUMEKEYS) { 2507 mb_put_uint32le(mbp, ctx->f_rkey); 2508 } else 2509 mb_put_uint32le(mbp, 0); 2510 mb_put_uint16le(mbp, flags); 2511 if (ctx->f_rname) { 2512 /* resume file name */ 2513 mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen, 2514 MB_MSYSTEM); 2515 } 2516 /* Add trailing null - 1 byte if ASCII, 2 if Unicode */ 2517 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2518 mb_put_uint8(mbp, 0); /* 1st byte NULL Unicode char */ 2519 mb_put_uint8(mbp, 0); 2520 #if 0 2521 struct timespec ts; 2522 ts.tv_sec = 0; 2523 ts.tv_nsec = 200 * 1000 * 1000; /* 200ms */ 2524 if (vcp->vc_flags & SMBC_WIN95) { 2525 /* 2526 * some implementations suggests to sleep here 2527 * for 200ms, due to the bug in the Win95. 2528 * I've didn't notice any problem, but put code 2529 * for it. 2530 */ 2531 msleep(&flags, 0, PVFS, "fix95", &ts); 2532 } 2533 #endif 2534 } 2535 t2p->t2_maxpcount = 5 * 2; 2536 t2p->t2_maxdcount = vcp->vc_txmax; 2537 error = smb_t2_request(t2p); 2538 if (error) 2539 return (error); 2540 mdp = &t2p->t2_rparam; 2541 if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { 2542 if ((error = md_get_uint16(mdp, &ctx->f_Sid)) != 0) 2543 return (error); 2544 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST; 2545 } 2546 if ((error = md_get_uint16le(mdp, &tw)) != 0) 2547 return (error); 2548 ctx->f_ecnt = tw; /* search count - # entries returned */ 2549 if ((error = md_get_uint16le(mdp, &tw)) != 0) 2550 return (error); 2551 /* 2552 * tw now is the "end of search" flag. against an XP server tw 2553 * comes back zero when the prior find_next returned exactly 2554 * the number of entries requested. in which case we'd try again 2555 * but the search has in fact been closed so an EBADF results. our 2556 * circumvention is to check here for a zero search count. 2557 */ 2558 if (tw || ctx->f_ecnt == 0) 2559 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE; 2560 if ((error = md_get_uint16le(mdp, &tw)) != 0) 2561 return (error); 2562 if ((error = md_get_uint16le(mdp, &tw)) != 0) 2563 return (error); 2564 if (ctx->f_ecnt == 0) 2565 return (ENOENT); 2566 ctx->f_rnameofs = tw; 2567 mdp = &t2p->t2_rdata; 2568 if (mdp->md_top == NULL) { 2569 SMBVDEBUG("ecnt = %d, but data is NULL\n", ctx->f_ecnt); 2570 return (ENOENT); 2571 } 2572 #ifdef APPLE 2573 if (mdp->md_top->m_len == 0) { 2574 printf("bug: ecnt = %d, but m_len = 0 and m_next = %p " 2575 "(please report)\n", ctx->f_ecnt, mbp->mb_top->m_next); 2576 return (ENOENT); 2577 } 2578 #endif 2579 ctx->f_eofs = 0; 2580 return (0); 2581 } 2582 2583 static int 2584 smbfs_smb_findclose2(struct smbfs_fctx *ctx) 2585 { 2586 struct smb_rq rq, *rqp = &rq; 2587 struct mbchain *mbp; 2588 int error; 2589 2590 error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, 2591 ctx->f_scred); 2592 if (error) 2593 return (error); 2594 smb_rq_getrequest(rqp, &mbp); 2595 smb_rq_wstart(rqp); 2596 mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM); 2597 smb_rq_wend(rqp); 2598 smb_rq_bstart(rqp); 2599 smb_rq_bend(rqp); 2600 /* Ditto comments at _smb_close */ 2601 rqp->sr_flags |= SMBR_NOINTR_SEND; 2602 error = smb_rq_simple(rqp); 2603 smb_rq_done(rqp); 2604 return (error); 2605 } 2606 2607 /*ARGSUSED*/ 2608 static int 2609 smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp, 2610 const char *wildcard, int wclen, uint16_t attr, struct smb_cred *scrp) 2611 { 2612 ctx->f_namesz = SMB_MAXFNAMELEN; 2613 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2614 ctx->f_namesz *= 2; 2615 ctx->f_name = kmem_zalloc(ctx->f_namesz, KM_SLEEP); 2616 ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) 2617 < SMB_DIALECT_NTLM0_12 ? SMB_FIND_STANDARD : 2618 SMB_FIND_BOTH_DIRECTORY_INFO; 2619 ctx->f_attrmask = attr; 2620 ctx->f_wildcard = wildcard; 2621 ctx->f_wclen = wclen; 2622 return (0); 2623 } 2624 2625 static int 2626 smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit) 2627 { 2628 struct mdchain *mdp; 2629 struct smb_t2rq *t2p; 2630 char *cp; 2631 uint8_t tb; 2632 uint16_t date, time, wattr; 2633 uint32_t size, next, dattr, resumekey = 0; 2634 uint64_t llongint; 2635 int error, svtz, cnt, fxsz, nmlen, recsz, otw; 2636 struct timespec ts; 2637 2638 again: 2639 otw = 0; /* nothing sent Over The Wire (yet) */ 2640 if (ctx->f_ecnt == 0) { 2641 if (ctx->f_flags & SMBFS_RDD_EOF) 2642 return (ENOENT); 2643 ctx->f_left = ctx->f_limit = limit; 2644 gethrestime(&ts); 2645 error = smbfs_smb_trans2find2(ctx); 2646 if (error) 2647 return (error); 2648 ctx->f_attr.fa_reqtime = ts; 2649 ctx->f_otws++; 2650 otw = 1; 2651 } 2652 t2p = ctx->f_t2; 2653 mdp = &t2p->t2_rdata; 2654 svtz = SSTOVC(ctx->f_ssp)->vc_sopt.sv_tz; 2655 switch (ctx->f_infolevel) { 2656 case SMB_FIND_STANDARD: 2657 next = 0; 2658 fxsz = 0; 2659 md_get_uint16le(mdp, &date); 2660 md_get_uint16le(mdp, &time); /* creation time */ 2661 md_get_uint16le(mdp, &date); 2662 md_get_uint16le(mdp, &time); /* access time */ 2663 smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_atime); 2664 md_get_uint16le(mdp, &date); 2665 md_get_uint16le(mdp, &time); /* modify time */ 2666 smb_dos2unixtime(date, time, 0, svtz, &ctx->f_attr.fa_mtime); 2667 md_get_uint32le(mdp, &size); 2668 ctx->f_attr.fa_size = size; 2669 md_get_uint32(mdp, NULL); /* allocation size */ 2670 md_get_uint16le(mdp, &wattr); 2671 ctx->f_attr.fa_attr = wattr; 2672 md_get_uint8(mdp, &tb); 2673 size = nmlen = tb; 2674 fxsz = 23; 2675 recsz = next = 24 + nmlen; /* docs misses zero byte @end */ 2676 break; 2677 case SMB_FIND_DIRECTORY_INFO: 2678 case SMB_FIND_BOTH_DIRECTORY_INFO: 2679 md_get_uint32le(mdp, &next); 2680 md_get_uint32le(mdp, &resumekey); /* file index (resume key) */ 2681 md_get_uint64(mdp, NULL); /* creation time */ 2682 md_get_uint64le(mdp, &llongint); 2683 smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_atime); 2684 md_get_uint64le(mdp, &llongint); 2685 smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_mtime); 2686 md_get_uint64le(mdp, &llongint); 2687 smb_time_NT2local(llongint, svtz, &ctx->f_attr.fa_ctime); 2688 md_get_uint64le(mdp, &llongint); /* file size */ 2689 ctx->f_attr.fa_size = llongint; 2690 md_get_uint64(mdp, NULL); /* real size (should use) */ 2691 /* freebsd bug: fa_attr endian bug */ 2692 md_get_uint32le(mdp, &dattr); /* extended file attributes */ 2693 ctx->f_attr.fa_attr = dattr; 2694 md_get_uint32le(mdp, &size); /* name len */ 2695 fxsz = 64; /* size ofinfo up to filename */ 2696 if (ctx->f_infolevel == SMB_FIND_BOTH_DIRECTORY_INFO) { 2697 /* 2698 * Skip EaSize(4 bytes), a byte of ShortNameLength, 2699 * a reserved byte, and ShortName(8.3 means 24 bytes, 2700 * as Leach defined it to always be Unicode) 2701 */ 2702 md_get_mem(mdp, NULL, 30, MB_MSYSTEM); 2703 fxsz += 30; 2704 } 2705 recsz = next ? next : fxsz + size; 2706 break; 2707 default: 2708 SMBVDEBUG("unexpected info level %d\n", ctx->f_infolevel); 2709 return (EINVAL); 2710 } 2711 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) 2712 nmlen = min(size, SMB_MAXFNAMELEN * 2); 2713 else 2714 nmlen = min(size, SMB_MAXFNAMELEN); 2715 if (ctx->f_name) 2716 kmem_free(ctx->f_name, ctx->f_namesz); 2717 cp = ctx->f_name = kmem_alloc(nmlen, KM_SLEEP); 2718 ctx->f_namesz = nmlen; 2719 error = md_get_mem(mdp, cp, nmlen, MB_MSYSTEM); 2720 if (error) 2721 return (error); 2722 if (next) { 2723 cnt = next - nmlen - fxsz; 2724 if (cnt > 0) 2725 md_get_mem(mdp, NULL, cnt, MB_MSYSTEM); 2726 else if (cnt < 0) { 2727 SMBVDEBUG("out of sync\n"); 2728 return (EBADRPC); 2729 } 2730 } 2731 /* Don't count any trailing null in the name. */ 2732 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 2733 if (nmlen > 1 && cp[nmlen - 1] == 0 && cp[nmlen - 2] == 0) 2734 nmlen -= 2; 2735 } else { 2736 if (nmlen && cp[nmlen - 1] == 0) 2737 nmlen--; 2738 } 2739 if (nmlen == 0) 2740 return (EBADRPC); 2741 2742 /* 2743 * Ref radar 3983209. On a find-next we expect a server will 2744 * 1) if the continue bit is set, use the server's idea of current loc, 2745 * 2) else if the resume key is non-zero, use that location, 2746 * 3) else if the resume name is set, use that location, 2747 * 4) else use the server's idea of current location. 2748 * 2749 * Current NetApps don't do that. If we send no continue bit, a zero 2750 * resume key, and a resume name, the NetApp ignores the resume name 2751 * and acts on the (zero) resume key, sending back the start of the 2752 * directory again. Panther doesn't expose the netapp bug; Panther used 2753 * the continue bit, but that was changed for 2866172. Win2000 as a 2754 * client also relies upon the resume name, but they request a very 2755 * large number of files, so the bug would be seen only with very 2756 * large directories. 2757 * 2758 * Our fix is to notice if the second OTW op (the first find-next) 2759 * returns, in the first filename, the same filename we got back 2760 * at the start of the first OTW (the find-first). In that case 2761 * we've detected the server bug and set SMBS_RESUMEKEYS, causing us 2762 * to send non-zero resume keys henceforth. 2763 * 2764 * Caveat: if there's a netapp so old it doesn't negotiate NTLM 0.12 2765 * then we get no resume keys so f_rkey stays zero and this "fix" 2766 * changes nothing. 2767 * 2768 * Note due to a similar problem (4051871) we also set SMBS_RESUMEKEYS 2769 * for FAT volumes, at mount time. 2770 */ 2771 if (otw && !(ctx->f_ssp->ss_flags & SMBS_RESUMEKEYS)) { 2772 if (ctx->f_otws == 1) { 2773 ctx->f_firstnmlen = nmlen; 2774 ctx->f_firstnm = kmem_alloc(nmlen, KM_SLEEP); 2775 bcopy(ctx->f_name, ctx->f_firstnm, nmlen); 2776 } else if (ctx->f_otws == 2 && nmlen == ctx->f_firstnmlen && 2777 !(bcmp(ctx->f_name, ctx->f_firstnm, nmlen) == 0)) { 2778 struct smb_share *ssp = ctx->f_ssp; 2779 SMBERROR( 2780 "server resume_name bug seen; using resume keys\n"); 2781 SMB_SS_LOCK(ssp); 2782 ssp->ss_flags |= SMBS_RESUMEKEYS; 2783 SMB_SS_UNLOCK(ssp); 2784 ctx->f_ecnt = 0; 2785 goto again; /* must redo last otw op! */ 2786 } 2787 } 2788 ctx->f_rkey = resumekey; 2789 2790 next = ctx->f_eofs + recsz; 2791 if (ctx->f_rnameofs && 2792 (ctx->f_flags & SMBFS_RDD_GOTRNAME) == 0 && 2793 (ctx->f_rnameofs >= ctx->f_eofs && 2794 ctx->f_rnameofs < (int)next)) { 2795 /* 2796 * Server needs a resume filename. 2797 */ 2798 if (ctx->f_rnamelen != nmlen) { 2799 if (ctx->f_rname) 2800 kmem_free(ctx->f_rname, ctx->f_rnamelen); 2801 ctx->f_rname = kmem_alloc(nmlen, KM_SLEEP); 2802 ctx->f_rnamelen = nmlen; 2803 } 2804 bcopy(ctx->f_name, ctx->f_rname, nmlen); 2805 ctx->f_flags |= SMBFS_RDD_GOTRNAME; 2806 } 2807 ctx->f_nmlen = nmlen; 2808 ctx->f_eofs = next; 2809 ctx->f_ecnt--; 2810 ctx->f_left--; 2811 return (0); 2812 } 2813 2814 static int 2815 smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx) 2816 { 2817 int error = 0; 2818 if (ctx->f_name) 2819 kmem_free(ctx->f_name, ctx->f_namesz); 2820 if (ctx->f_t2) 2821 smb_t2_done(ctx->f_t2); 2822 if ((ctx->f_flags & SMBFS_RDD_NOCLOSE) == 0) 2823 error = smbfs_smb_findclose2(ctx); 2824 return (error); 2825 } 2826 2827 int 2828 smbfs_smb_findopen(struct smbnode *dnp, const char *wildcard, int wclen, 2829 int attr, struct smb_cred *scrp, 2830 struct smbfs_fctx **ctxpp) 2831 { 2832 struct smbfs_fctx *ctx; 2833 int error; 2834 2835 ctx = kmem_alloc(sizeof (*ctx), KM_SLEEP); 2836 if (ctx == NULL) 2837 return (ENOMEM); 2838 bzero(ctx, sizeof (*ctx)); 2839 if (dnp->n_mount->smi_share) { 2840 ctx->f_ssp = dnp->n_mount->smi_share; 2841 } 2842 ctx->f_dnp = dnp; 2843 ctx->f_flags = SMBFS_RDD_FINDFIRST; 2844 ctx->f_scred = scrp; 2845 if (SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_LANMAN2_0 || 2846 (dnp->n_mount->smi_args.flags & SMBFS_MOUNT_NO_LONG)) { 2847 ctx->f_flags |= SMBFS_RDD_USESEARCH; 2848 error = smbfs_smb_findopenLM1(ctx, dnp, wildcard, wclen, 2849 attr, scrp); 2850 } else 2851 error = smbfs_smb_findopenLM2(ctx, dnp, wildcard, wclen, 2852 attr, scrp); 2853 if (error) 2854 (void) smbfs_smb_findclose(ctx, scrp); 2855 else 2856 *ctxpp = ctx; 2857 return (error); 2858 } 2859 2860 int 2861 smbfs_smb_findnext(struct smbfs_fctx *ctx, int limit, struct smb_cred *scrp) 2862 { 2863 int error; 2864 2865 /* 2866 * Note: "limit" (maxcount) needs to fit in a short! 2867 * 2868 * smb_lookup always uses 1, which is OK (no wildcards). 2869 * Otherwise, this is smbfs_readdir, and we want to force 2870 * limit to be in the range 3 to 1000. The low limit (3) 2871 * is so we can always give the caller one "real" entry 2872 * (something other than "." or "..") The high limit is 2873 * just tuning. WinNT used 512, Win2k 1366. We use 1000. 2874 * 2875 * XXX: Move the [skip . ..] gunk to our caller (readdir). 2876 */ 2877 if ((ctx->f_flags & SMBFS_RDD_FINDSINGLE) == 0) { 2878 if (limit < 3) 2879 limit = 3; 2880 if (limit > 1000) 2881 limit = 1000; 2882 } 2883 2884 ctx->f_scred = scrp; 2885 for (;;) { 2886 if (ctx->f_flags & SMBFS_RDD_USESEARCH) { 2887 error = smbfs_smb_findnextLM1(ctx, (uint16_t)limit); 2888 } else 2889 error = smbfs_smb_findnextLM2(ctx, (uint16_t)limit); 2890 if (error) 2891 return (error); 2892 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) { 2893 /*LINTED*/ 2894 uint16_t *up = (uint16_t *)ctx->f_name; 2895 2896 /* Do comparisons on UCS-2LE characters */ 2897 if ((ctx->f_nmlen == 2 && up[0] == htoles('.')) || 2898 (ctx->f_nmlen == 4 && up[0] == htoles('.') && 2899 up[1] == htoles('.'))) 2900 continue; 2901 } else { 2902 if ((ctx->f_nmlen == 1 && ctx->f_name[0] == '.') || 2903 (ctx->f_nmlen == 2 && ctx->f_name[0] == '.' && 2904 ctx->f_name[1] == '.')) 2905 continue; 2906 } 2907 break; 2908 } 2909 smbfs_fname_tolocal(ctx); 2910 ctx->f_attr.fa_ino = smbfs_getino(ctx->f_dnp, ctx->f_name, 2911 ctx->f_nmlen); 2912 return (0); 2913 } 2914 2915 2916 int 2917 smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp) 2918 { 2919 int error; 2920 ctx->f_scred = scrp; 2921 if (ctx->f_flags & SMBFS_RDD_USESEARCH) { 2922 error = smbfs_smb_findcloseLM1(ctx); 2923 } else 2924 error = smbfs_smb_findcloseLM2(ctx); 2925 if (ctx->f_rname) 2926 kmem_free(ctx->f_rname, ctx->f_rnamelen); 2927 if (ctx->f_firstnm) 2928 kmem_free(ctx->f_firstnm, ctx->f_firstnmlen); 2929 kmem_free(ctx, sizeof (*ctx)); 2930 return (error); 2931 } 2932 2933 2934 int 2935 smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, 2936 struct smbfattr *fap, struct smb_cred *scrp) 2937 { 2938 struct smbfs_fctx *ctx; 2939 int error, intr; 2940 const char *name = (namep ? *namep : NULL); 2941 int nmlen = (nmlenp ? *nmlenp : 0); 2942 2943 /* This is no longer called with a null dnp */ 2944 ASSERT(dnp); 2945 2946 /* 2947 * Should not get here with "" anymore. 2948 */ 2949 if (!name || !nmlen) { 2950 DEBUG_ENTER("smbfs_smb_lookup: name is NULL"); 2951 return (EINVAL); 2952 } 2953 2954 /* 2955 * Should not get here with "." or ".." anymore. 2956 */ 2957 if ((nmlen == 1 && name[0] == '.') || 2958 (nmlen == 2 && name[0] == '.' && name[1] == '.')) { 2959 DEBUG_ENTER("smbfs_smb_lookup: name is '.' or '..'"); 2960 return (EINVAL); 2961 } 2962 2963 /* 2964 * Shared lock for n_fid use (smb_flush). 2965 */ 2966 intr = dnp->n_mount->smi_flags & SMI_INT; 2967 if (smbfs_rw_enter_sig(&dnp->r_lkserlock, RW_READER, intr)) 2968 return (EINTR); 2969 2970 bzero(fap, sizeof (*fap)); 2971 2972 /* 2973 * This hides a server bug observable in Win98: 2974 * size changes may not show until a CLOSE or a FLUSH op 2975 * XXX: Make this conditional on !NTSMBs 2976 */ 2977 error = smbfs_smb_flush(dnp, scrp); 2978 if (error) 2979 goto out; 2980 error = smbfs_smb_findopen(dnp, name, nmlen, 2981 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scrp, &ctx); 2982 if (error) 2983 goto out; 2984 ctx->f_flags |= SMBFS_RDD_FINDSINGLE; 2985 error = smbfs_smb_findnext(ctx, 1, scrp); 2986 if (error == 0) { 2987 *fap = ctx->f_attr; 2988 if (name == NULL) 2989 fap->fa_ino = dnp->n_ino; 2990 if (namep) 2991 *namep = (const char *)smbfs_name_alloc( 2992 ctx->f_name, ctx->f_nmlen); 2993 if (nmlenp) 2994 *nmlenp = ctx->f_nmlen; 2995 } 2996 (void) smbfs_smb_findclose(ctx, scrp); 2997 2998 out: 2999 smbfs_rw_exit(&dnp->r_lkserlock); 3000 return (error); 3001 } 3002 3003 /* 3004 * OTW function to Get a security descriptor (SD). 3005 * 3006 * Note: On success, this fills in mdp->md_top, 3007 * which the caller should free. 3008 */ 3009 int 3010 smbfs_smb_getsec_m(struct smb_share *ssp, uint16_t fid, 3011 struct smb_cred *scrp, uint32_t selector, 3012 mblk_t **res, uint32_t *reslen) 3013 { 3014 struct smb_ntrq *ntp; 3015 struct mbchain *mbp; 3016 struct mdchain *mdp; 3017 int error, len; 3018 3019 error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC, 3020 scrp, &ntp); 3021 if (error) 3022 return (error); 3023 3024 /* Parameters part */ 3025 mbp = &ntp->nt_tparam; 3026 mb_init(mbp); 3027 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 3028 mb_put_uint16le(mbp, 0); /* reserved */ 3029 mb_put_uint32le(mbp, selector); 3030 /* Data part (none) */ 3031 3032 /* Max. returned parameters and data. */ 3033 ntp->nt_maxpcount = 4; 3034 ntp->nt_maxdcount = *reslen; 3035 3036 error = smb_nt_request(ntp); 3037 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) 3038 goto done; 3039 *res = NULL; 3040 3041 /* 3042 * if there's more data than we said we could receive, here 3043 * is where we pick up the length of it 3044 */ 3045 mdp = &ntp->nt_rparam; 3046 md_get_uint32le(mdp, reslen); 3047 if (error) 3048 goto done; 3049 3050 /* 3051 * get the data part. 3052 */ 3053 mdp = &ntp->nt_rdata; 3054 if (mdp->md_top == NULL) { 3055 SMBVDEBUG("null md_top? fid 0x%x\n", letohs(fid)); 3056 error = EBADRPC; 3057 goto done; 3058 } 3059 3060 /* 3061 * The returned parameter SD_length should match 3062 * the length of the returned data. Unfortunately, 3063 * we have to work around server bugs here. 3064 */ 3065 len = m_fixhdr(mdp->md_top); 3066 if (len != *reslen) { 3067 SMBVDEBUG("len %d *reslen %d fid 0x%x\n", 3068 len, *reslen, letohs(fid)); 3069 } 3070 3071 /* 3072 * Actual data provided is < returned SD_length. 3073 * 3074 * The following "if (len < *reslen)" handles a Windows bug 3075 * observed when the underlying filesystem is FAT32. In that 3076 * case a 32 byte security descriptor comes back (S-1-1-0, ie 3077 * "Everyone") but the Parameter Block claims 44 is the length 3078 * of the security descriptor. (The Data Block length 3079 * claimed is 32. This server bug was reported against NT 3080 * first and I've personally observed it with W2K. 3081 */ 3082 if (len < *reslen) 3083 *reslen = len; 3084 3085 /* 3086 * Actual data provided is > returned SD_length. 3087 * (Seen on StorageTek NAS 5320, s/w ver. 4.21 M0) 3088 * Narrow work-around for returned SD_length==0. 3089 */ 3090 if (len > *reslen) { 3091 /* 3092 * Increase *reslen, but carefully. 3093 */ 3094 if (*reslen == 0 && len <= ntp->nt_maxdcount) 3095 *reslen = len; 3096 } 3097 error = md_get_mbuf(mdp, len, res); 3098 3099 done: 3100 if (error == 0 && *res == NULL) { 3101 ASSERT(*res); 3102 error = EBADRPC; 3103 } 3104 3105 smb_nt_done(ntp); 3106 return (error); 3107 } 3108 3109 #ifdef APPLE 3110 /* 3111 * Wrapper for _getsd() compatible with darwin code. 3112 */ 3113 int 3114 smbfs_smb_getsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, 3115 uint32_t selector, struct ntsecdesc **res) 3116 { 3117 int error; 3118 uint32_t len, olen; 3119 struct mdchain *mdp, md_store; 3120 struct mbuf *m; 3121 3122 bzero(mdp, sizeof (*mdp)); 3123 len = 500; /* "overlarge" values => server errors */ 3124 again: 3125 olen = len; 3126 error = smbfs_smb_getsec_m(ssp, fid, scrp, selector, &m, &len); 3127 /* 3128 * Server may give us an error indicating that we 3129 * need a larger data buffer to receive the SD, 3130 * and the size we'll need. Use the given size, 3131 * but only after a sanity check. 3132 * 3133 * XXX: Check for specific error values here? 3134 * XXX: also ... && len <= MAX_RAW_SD_SIZE 3135 */ 3136 if (error && len > olen) 3137 goto again; 3138 3139 if (error) 3140 return (error); 3141 3142 mdp = &md_store; 3143 md_initm(mdp, m); 3144 MALLOC(*res, struct ntsecdesc *, len, M_TEMP, M_WAITOK); 3145 error = md_get_mem(mdp, (caddr_t)*res, len, MB_MSYSTEM); 3146 md_done(mdp); 3147 3148 return (error); 3149 } 3150 #endif /* APPLE */ 3151 3152 /* 3153 * OTW function to Set a security descriptor (SD). 3154 * Caller data are carried in an mbchain_t. 3155 * 3156 * Note: This normally consumes mbp->mb_top, and clears 3157 * that pointer when it does. 3158 */ 3159 int smbfs_smb_setsec_m(struct smb_share *ssp, uint16_t fid, 3160 struct smb_cred *scrp, uint32_t selector, mblk_t **mp) 3161 { 3162 struct smb_ntrq *ntp; 3163 struct mbchain *mbp; 3164 int error; 3165 3166 error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC, 3167 scrp, &ntp); 3168 if (error) 3169 return (error); 3170 3171 /* Parameters part */ 3172 mbp = &ntp->nt_tparam; 3173 mb_init(mbp); 3174 mb_put_mem(mbp, (caddr_t)&fid, 2, MB_MSYSTEM); 3175 mb_put_uint16le(mbp, 0); /* reserved */ 3176 mb_put_uint32le(mbp, selector); 3177 3178 /* Data part */ 3179 mbp = &ntp->nt_tdata; 3180 mb_initm(mbp, *mp); 3181 *mp = NULL; /* consumed */ 3182 3183 /* No returned parameters or data. */ 3184 ntp->nt_maxpcount = 0; 3185 ntp->nt_maxdcount = 0; 3186 3187 error = smb_nt_request(ntp); 3188 smb_nt_done(ntp); 3189 3190 return (error); 3191 } 3192 3193 #ifdef APPLE 3194 /* 3195 * This function builds the SD given the various parts. 3196 */ 3197 int 3198 smbfs_smb_setsec(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp, 3199 uint32_t selector, uint16_t flags, struct ntsid *owner, 3200 struct ntsid *group, struct ntacl *sacl, struct ntacl *dacl) 3201 { 3202 struct mbchain *mbp, mb_store; 3203 struct ntsecdesc ntsd; 3204 int error, off; 3205 3206 /* 3207 * Build the SD as its own mbuf chain and pass it to 3208 * smbfs_smb_setsec_m() 3209 */ 3210 mbp = &mb_store; 3211 mb_init(mbp); 3212 bzero(&ntsd, sizeof (ntsd)); 3213 wset_sdrevision(&ntsd); 3214 /* 3215 * A note about flags ("SECURITY_DESCRIPTOR_CONTROL" in MSDN) 3216 * We set here only those bits we can be sure must be set. The rest 3217 * are up to the caller. In particular, the caller may intentionally 3218 * set an acl PRESENT bit while giving us a null pointer for the 3219 * acl - that sets a null acl, giving access to everyone. Note also 3220 * that the AUTO_INHERITED bits should probably always be set unless 3221 * the server is NT. 3222 */ 3223 flags |= SD_SELF_RELATIVE; 3224 off = sizeof (ntsd); 3225 if (owner) { 3226 wset_sdowneroff(&ntsd, off); 3227 off += sidlen(owner); 3228 } 3229 if (group) { 3230 wset_sdgroupoff(&ntsd, off); 3231 off += sidlen(group); 3232 } 3233 if (sacl) { 3234 flags |= SD_SACL_PRESENT; 3235 wset_sdsacloff(&ntsd, off); 3236 off += acllen(sacl); 3237 } 3238 if (dacl) { 3239 flags |= SD_DACL_PRESENT; 3240 wset_sddacloff(&ntsd, off); 3241 } 3242 wset_sdflags(&ntsd, flags); 3243 mb_put_mem(mbp, (caddr_t)&ntsd, sizeof (ntsd), MB_MSYSTEM); 3244 if (owner) 3245 mb_put_mem(mbp, (caddr_t)owner, sidlen(owner), MB_MSYSTEM); 3246 if (group) 3247 mb_put_mem(mbp, (caddr_t)group, sidlen(group), MB_MSYSTEM); 3248 if (sacl) 3249 mb_put_mem(mbp, (caddr_t)sacl, acllen(sacl), MB_MSYSTEM); 3250 if (dacl) 3251 mb_put_mem(mbp, (caddr_t)dacl, acllen(dacl), MB_MSYSTEM); 3252 3253 /* 3254 * Just pass the mbuf to _setsec_m 3255 * It will clear mb_top if consumed. 3256 */ 3257 error = smbfs_smb_setsec_m(ssp, fid, scrp, selector, &mbp->mb_top); 3258 mb_done(mbp); 3259 3260 return (error); 3261 } 3262 3263 #endif /* APPLE */ 3264